* do not save default resource permissions in a db migration but in a server-side extension
* new component to save settings from server-side components. It will have to be used by ruby app later.
import org.sonar.core.persistence.MyBatis;
import java.util.List;
+import java.util.Map;
public class PropertiesDao implements BatchComponent, ServerComponent {
MyBatis.closeQuietly(session);
}
}
+
+ public void deleteGlobalProperties() {
+ SqlSession session = mybatis.openSession();
+ PropertiesMapper mapper = session.getMapper(PropertiesMapper.class);
+ try {
+ mapper.deleteGlobalProperties();
+ session.commit();
+
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void deleteGlobalProperty(String key) {
+ SqlSession session = mybatis.openSession();
+ PropertiesMapper mapper = session.getMapper(PropertiesMapper.class);
+ try {
+ mapper.deleteGlobalProperty(key);
+ session.commit();
+
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void saveGlobalProperties(Map<String, String> properties) {
+ SqlSession session = mybatis.openBatchSession();
+ PropertiesMapper mapper = session.getMapper(PropertiesMapper.class);
+ try {
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ mapper.deleteGlobalProperty(entry.getKey());
+ }
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ mapper.insert(new PropertyDto().setKey(entry.getKey()).setValue(entry.getValue()));
+ }
+ session.commit();
+
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
}
PropertyDto selectByKey(PropertyDto key);
void update(PropertyDto property);
void insert(PropertyDto property);
-
+ void deleteGlobalProperty(String key);
+ void deleteGlobalProperties();
}
INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 1);
INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 2);
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (1, 'sonar.role.admin.TRK.defaultGroups', 'sonar-administrators');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (2, 'sonar.role.admin.TRK.defaultUsers', '');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (3, 'sonar.role.user.TRK.defaultGroups', 'Anyone,sonar-users');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (4, 'sonar.role.user.TRK.defaultUsers', '');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (5, 'sonar.role.codeviewer.TRK.defaultGroups', 'Anyone,sonar-users');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (6, 'sonar.role.codeviewer.TRK.defaultUsers', '');
-
--- COMPATIBILITY WITH OLD VERSIONS OF VIEWS PLUGIN -> see migration 320
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (7, 'sonar.role.admin.VW.defaultGroups', 'sonar-administrators');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (8, 'sonar.role.admin.VW.defaultUsers', '');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (9, 'sonar.role.user.VW.defaultGroups', 'Anyone,sonar-users');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (10, 'sonar.role.user.VW.defaultUsers', '');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (11, 'sonar.role.codeviewer.VW.defaultGroups', 'Anyone,sonar-users');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (12, 'sonar.role.codeviewer.VW.defaultUsers', '');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (13, 'sonar.role.admin.SVW.defaultGroups', 'sonar-administrators');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (14, 'sonar.role.admin.SVW.defaultUsers', '');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (15, 'sonar.role.user.SVW.defaultGroups', 'Anyone,sonar-users');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (16, 'sonar.role.user.SVW.defaultUsers', '');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (17, 'sonar.role.codeviewer.SVW.defaultGroups', 'Anyone,sonar-users');
-INSERT INTO PROPERTIES(ID, PROP_KEY, TEXT_VALUE) VALUES (18, 'sonar.role.codeviewer.SVW.defaultUsers', '');
-ALTER TABLE PROPERTIES ALTER COLUMN ID RESTART WITH 19;
-
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('2');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('10');
update properties set text_value = #{value} where id = #{id}
</update>
- <insert id="insert" parameterType="Property" useGeneratedKeys="true" keyProperty="id">
+ <insert id="insert" parameterType="Property" useGeneratedKeys="false">
INSERT INTO properties (prop_key, resource_id, user_id, text_value)
VALUES (#{key}, #{resourceId}, #{userId}, #{value})
</insert>
<!-- Oracle -->
- <insert id="insert" databaseId="oracle" parameterType="Property" useGeneratedKeys="true" keyProperty="id">
+ <insert id="insert" databaseId="oracle" parameterType="Property" useGeneratedKeys="false">
<selectKey order="BEFORE" resultType="Long" keyProperty="id">
select properties_seq.NEXTVAL from DUAL
</selectKey>
VALUES (#{id}, #{key}, #{resourceId}, #{userId}, #{value})
</insert>
+ <delete id="deleteGlobalProperty" parameterType="string">
+ delete from properties where prop_key=#{id} and resource_id is null and user_id is null
+ </delete>
+
+ <delete id="deleteGlobalProperties">
+ delete from properties where resource_id is null and user_id is null
+ </delete>
+
</mapper>
*/
package org.sonar.core.properties;
+import com.google.common.collect.Maps;
import org.junit.Before;
import org.junit.Test;
import org.sonar.core.persistence.AbstractDaoTestCase;
import java.util.List;
+import java.util.TreeMap;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;
private PropertiesDao dao;
@Before
- public void createDao() throws Exception {
+ public void createDao() {
dao = new PropertiesDao(getMyBatis());
}
@Test
- public void shouldFindUserIdsForFavouriteResource() throws Exception {
+ public void shouldFindUserIdsForFavouriteResource() {
setupData("shouldFindUserIdsForFavouriteResource");
List<String> userIds = dao.findUserIdsForFavouriteResource(2L);
assertThat(userIds.size(), is(2));
}
@Test
- public void selectGlobalProperties() throws Exception {
+ public void selectGlobalProperties() {
setupData("selectGlobalProperties");
List<PropertyDto> properties = dao.selectGlobalProperties();
assertThat(properties.size(), is(2));
}
@Test
- public void selectProjectProperties() throws Exception {
+ public void selectProjectProperties() {
setupData("selectProjectProperties");
List<PropertyDto> properties = dao.selectProjectProperties("org.struts:struts");
assertThat(properties.size(), is(1));
}
@Test
- public void setProperty_update() throws Exception {
+ public void setProperty_update() {
setupData("update");
dao.setProperty(new PropertyDto().setKey("global.key").setValue("new_global"));
}
@Test
- public void setProperty_insert() throws Exception {
+ public void setProperty_insert() {
setupData("insert");
dao.setProperty(new PropertyDto().setKey("global.key").setValue("new_global"));
checkTables("insert", "properties");
}
+ @Test
+ public void deleteGlobalProperties() {
+ setupData("deleteGlobalProperties");
+
+ dao.deleteGlobalProperties();
+
+ checkTables("deleteGlobalProperties", "properties");
+ }
+
+ @Test
+ public void deleteGlobalProperty() {
+ setupData("deleteGlobalProperty");
+
+ dao.deleteGlobalProperty("to_be_deleted");
+
+ checkTables("deleteGlobalProperty", "properties");
+ }
+
+ @Test
+ public void saveGlobalProperties() {
+ setupData("saveGlobalProperties");
+
+ TreeMap<String, String> props = Maps.newTreeMap();
+ props.put("to_be_inserted", "inserted");
+ props.put("to_be_updated", "updated");
+ dao.saveGlobalProperties(props);
+
+ checkTable("saveGlobalProperties", "properties", "prop_key", "text_value", "resource_id", "user_id");
+ }
+
private PropertyDto findById(List<PropertyDto> properties, int id) {
for (PropertyDto property : properties) {
if (property.getId() == id) {
--- /dev/null
+<dataset>
+
+ <!-- global -->
+ <!--<properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/>-->
+
+ <!-- project -->
+ <properties id="2" prop_key="project.key" text_value="new_project" resource_id="10" user_id="[null]"/>
+
+ <!-- user -->
+ <properties id="3" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <!-- global -->
+ <properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/>
+
+ <!-- project -->
+ <properties id="2" prop_key="project.key" text_value="new_project" resource_id="10" user_id="[null]"/>
+
+ <!-- user -->
+ <properties id="3" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <!-- global -->
+ <properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/>
+ <!--<properties id="2" prop_key="to_be_deleted" text_value="xxx" resource_id="[null]" user_id="[null]"/>-->
+
+ <!-- project -->
+ <properties id="3" prop_key="to_be_deleted" text_value="new_project" resource_id="10" user_id="[null]"/>
+
+ <!-- user -->
+ <properties id="4" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <!-- global -->
+ <properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/>
+ <properties id="2" prop_key="to_be_deleted" text_value="xxx" resource_id="[null]" user_id="[null]"/>
+
+ <!-- project - do not delete this project property that has the same key -->
+ <properties id="3" prop_key="to_be_deleted" text_value="new_project" resource_id="10" user_id="[null]"/>
+
+ <!-- user -->
+ <properties id="4" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <!-- global -->
+ <!--<properties id="1" prop_key="to_be_updated" text_value="old value" resource_id="[null]" user_id="[null]"/>-->
+ <properties id="2" prop_key="to_not_change" text_value="xxx" resource_id="[null]" user_id="[null]"/>
+
+ <!-- project - do not update this project property that has the same key -->
+ <properties id="3" prop_key="to_be_updated" text_value="new_project" resource_id="10" user_id="[null]"/>
+
+ <!-- user -->
+ <properties id="4" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/>
+
+
+ <properties id="5" prop_key="to_be_inserted" text_value="inserted" resource_id="[null]" user_id="[null]"/>
+ <properties id="6" prop_key="to_be_updated" text_value="updated" resource_id="[null]" user_id="[null]"/>
+
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <!-- global -->
+ <properties id="1" prop_key="to_be_updated" text_value="old value" resource_id="[null]" user_id="[null]"/>
+ <properties id="2" prop_key="to_not_change" text_value="xxx" resource_id="[null]" user_id="[null]"/>
+
+ <!-- project - do not update this project property that has the same key -->
+ <properties id="3" prop_key="to_be_updated" text_value="new_project" resource_id="10" user_id="[null]"/>
+
+ <!-- user -->
+ <properties id="4" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/>
+
+</dataset>
} else {
newValue += "," + StringUtils.trim(value);
}
- properties.put(key, newValue);
- return this;
+ return setProperty(key, newValue);
}
public final Settings setProperty(String key, @Nullable String value) {
- if (!clearIfNullValue(key, value)) {
+ if (value == null) {
+ properties.remove(key);
+ doOnRemoveProperty(key);
+ } else {
properties.put(key, StringUtils.trim(value));
+ doOnSetProperty(key, value);
}
return this;
}
public final Settings setProperty(String key, @Nullable Boolean value) {
- if (!clearIfNullValue(key, value)) {
- properties.put(key, String.valueOf(value));
- }
- return this;
+ return setProperty(key, String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Integer value) {
- if (!clearIfNullValue(key, value)) {
- properties.put(key, String.valueOf(value));
- }
- return this;
+ return setProperty(key, String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Long value) {
- if (!clearIfNullValue(key, value)) {
- properties.put(key, String.valueOf(value));
- }
- return this;
+ return setProperty(key, String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Double value) {
- if (!clearIfNullValue(key, value)) {
- properties.put(key, String.valueOf(value));
- }
- return this;
+ return setProperty(key, String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Date date) {
}
public final Settings setProperties(Map<String, String> props) {
- properties.clear();
+ clear();
return addProperties(props);
}
public final Settings setProperty(String key, @Nullable Date date, boolean includeTime) {
- if (!clearIfNullValue(key, date)) {
- properties.put(key, includeTime ? DateUtils.formatDateTime(date) : DateUtils.formatDate(date));
- }
- return this;
+ return setProperty(key, includeTime ? DateUtils.formatDateTime(date) : DateUtils.formatDate(date));
}
public final Settings removeProperty(String key) {
- properties.remove(key);
- return this;
+ return setProperty(key, (String) null);
}
public final Settings clear() {
properties.clear();
+ doOnClearProperties();
return this;
}
return definitions;
}
- private boolean clearIfNullValue(String key, @Nullable Object value) {
- if (value == null) {
- properties.remove(key);
- return true;
- }
- return false;
- }
-
/**
* Create empty settings. Definition of available properties is loaded from the given annotated class.
* This method is usually used by unit tests.
public static Settings createForComponent(Object component) {
return new Settings(new PropertyDefinitions(component));
}
+
+ protected void doOnSetProperty(String key, @Nullable String value) {
+ }
+
+ protected void doOnRemoveProperty(String key) {
+ }
+
+ protected void doOnClearProperties() {
+ }
}
import org.slf4j.LoggerFactory;
import org.sonar.api.database.DatabaseSession;
import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.server.platform.PersistentSettings;
import javax.annotation.Nullable;
import java.io.IOException;
backupables = new ArrayList<Backupable>();
}
- public Backup(DatabaseSession session) {
+ public Backup(DatabaseSession session, PersistentSettings persistentSettings) {
this();
this.session = session;
backupables.add(new MetricsBackup(session));
- backupables.add(new PropertiesBackup(session));
+ backupables.add(new PropertiesBackup(persistentSettings));
// Note that order is important, because profile can have reference to rule
backupables.add(new RulesBackup(session));
backupables.add(new ProfilesBackup(session));
private XStream getConfiguredXstream() {
XStream xStream = new XStream(
- new XppDriver() {
- @Override
- public HierarchicalStreamWriter createWriter(Writer out) {
- return new PrettyPrintWriter(out) {
- @Override
- protected void writeText(QuickWriter writer, @Nullable String text) {
- if (text != null) {
- writer.write("<![CDATA[");
- /*
- * See http://jira.codehaus.org/browse/SONAR-1605 According to XML specification (
- * http://www.w3.org/TR/REC-xml/#sec-cdata-sect ) CData section may contain everything except of sequence ']]>' so we will
- * split all occurrences of this sequence into two CDATA first one would contain ']]' and second '>'
- */
- text = StringUtils.replace(text, "]]>", "]]]]><![CDATA[>");
- writer.write(text);
- writer.write("]]>");
- }
+ new XppDriver() {
+ @Override
+ public HierarchicalStreamWriter createWriter(Writer out) {
+ return new PrettyPrintWriter(out) {
+ @Override
+ protected void writeText(QuickWriter writer, @Nullable String text) {
+ if (text != null) {
+ writer.write("<![CDATA[");
+ /*
+ * See http://jira.codehaus.org/browse/SONAR-1605 According to XML specification (
+ * http://www.w3.org/TR/REC-xml/#sec-cdata-sect ) CData section may contain everything except of sequence ']]>' so we will
+ * split all occurrences of this sequence into two CDATA first one would contain ']]' and second '>'
+ */
+ text = StringUtils.replace(text, "]]>", "]]]]><![CDATA[>");
+ writer.write(text);
+ writer.write("]]>");
}
- };
- }
- });
+ }
+ };
+ }
+ });
xStream.processAnnotations(SonarConfig.class);
xStream.addDefaultImplementation(ArrayList.class, Collection.class);
*/
package org.sonar.server.configuration;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.thoughtworks.xstream.XStream;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
-import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.configuration.Property;
+import org.sonar.server.platform.PersistentSettings;
-import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
public class PropertiesBackup implements Backupable {
- private DatabaseSession databaseSession;
- private static final String FROM_GLOBAL_PROPERTIES = "from " + Property.class.getSimpleName() + " p WHERE p.resourceId IS NULL and user_id is null";
+ private final PersistentSettings persistentSettings;
- public PropertiesBackup(DatabaseSession databaseSession) {
- this.databaseSession = databaseSession;
+ public PropertiesBackup(PersistentSettings persistentSettings) {
+ this.persistentSettings = persistentSettings;
}
public void exportXml(SonarConfig sonarConfig) {
- List<Property> xmlProperties = new ArrayList<Property>();
+ List<Property> xmlProperties = Lists.newArrayList();
- List<Property> dbProperties = databaseSession.createQuery(FROM_GLOBAL_PROPERTIES).getResultList();
- if (dbProperties != null) {
- for (Property dbProperty : dbProperties) {
- String propKey = dbProperty.getKey();
- if (!CoreProperties.SERVER_ID.equals(propKey)) {
- // "sonar.core.id" must never be restored, it is unique for a server and it created once at the 1rst server startup
- xmlProperties.add(new Property(dbProperty.getKey(), dbProperty.getValue()));
- }
+ for (Map.Entry<String, String> entry : persistentSettings.getProperties().entrySet()) {
+ // "sonar.core.id" must never be restored, it is unique for a server and it created once at the 1rst server startup
+ if (!CoreProperties.SERVER_ID.equals(entry.getKey())) {
+ xmlProperties.add(new Property(entry.getKey(), entry.getValue()));
}
- sonarConfig.setProperties(xmlProperties);
}
+ sonarConfig.setProperties(xmlProperties);
}
public void importXml(SonarConfig sonarConfig) {
LoggerFactory.getLogger(getClass()).info("Restore properties");
- clearProperties();
+ // "sonar.core.id" property should not be cleared, because it is the unique key used to identify the server
+ // and it is used by the batch to verify that it connects to the same DB as the remote server (see SONAR-3126).
+ String serverId = persistentSettings.getString(CoreProperties.SERVER_ID);
+ String serverStartTime = persistentSettings.getString(CoreProperties.SERVER_STARTTIME);
+
+ Map<String, String> properties = Maps.newHashMap();
if (CollectionUtils.isNotEmpty(sonarConfig.getProperties())) {
for (Property xmlProperty : sonarConfig.getProperties()) {
- String propKey = xmlProperty.getKey();
- if (!CoreProperties.SERVER_ID.equals(propKey)) {
- // "sonar.core.id" must never be restored, it is unique for a server and it created once at the 1rst server startup
- databaseSession.save(new Property(propKey, xmlProperty.getValue()));
- }
+ properties.put(xmlProperty.getKey(), xmlProperty.getValue());
}
}
- databaseSession.commit();
- }
-
- private void clearProperties() {
- // "sonar.core.id" property should not be cleared, because it is the unique key used to identify the server
- // and it is used by the batch to verify that it connects to the same DB as the remote server (see SONAR-3126).
- databaseSession.createQuery("delete " + FROM_GLOBAL_PROPERTIES + " and prop_key != '" + CoreProperties.SERVER_ID + "'").executeUpdate();
+ properties.put(CoreProperties.SERVER_ID, serverId);
+ properties.put(CoreProperties.SERVER_STARTTIME, serverStartTime);
+ persistentSettings.deleteProperties();
+ persistentSettings.saveProperties(properties);
}
public void configure(XStream xStream) {
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 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.server.platform;
-
-import org.apache.commons.configuration.Configuration;
-import org.sonar.api.config.GlobalPropertyChangeHandler;
-
-import javax.annotation.Nullable;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Update cache of global settings (see org.sonar.api.config.Settings) and notify org.sonar.api.config.GlobalPropertyChangeHandler extensions
- *
- * @since 3.0
- */
-public class GlobalSettingsUpdater {
- private ServerSettings settings;
- private Configuration deprecatedConf;
- private List<GlobalPropertyChangeHandler> changeHandlers;
-
- public GlobalSettingsUpdater(ServerSettings settings, Configuration config, List<GlobalPropertyChangeHandler> changeHandlers) {
- this.settings = settings;
- this.deprecatedConf = config;
- this.changeHandlers = changeHandlers;
- }
-
- public GlobalSettingsUpdater(ServerSettings settings, Configuration config) {
- this(settings, config, Collections.<GlobalPropertyChangeHandler>emptyList());
- }
-
- public void setProperty(String key, @Nullable String value) {
- settings.setProperty(key, value);
- deprecatedConf.setProperty(key, value);
-
- GlobalPropertyChangeHandler.PropertyChange change = GlobalPropertyChangeHandler.PropertyChange.create(key, value);
- for (GlobalPropertyChangeHandler changeHandler : changeHandlers) {
- changeHandler.onChange(change);
- }
- }
-}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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.server.platform;
+
+import com.google.common.collect.Maps;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.config.Settings;
+import org.sonar.core.properties.PropertiesDao;
+import org.sonar.core.properties.PropertyDto;
+
+import javax.annotation.Nullable;
+import java.util.Map;
+
+/**
+ * @since 3.2
+ */
+public class PersistentSettings implements ServerComponent {
+ private final PropertiesDao propertiesDao;
+ private final ServerSettings settings;
+
+ public PersistentSettings(PropertiesDao propertiesDao, ServerSettings settings) {
+ this.propertiesDao = propertiesDao;
+ this.settings = settings;
+ }
+
+ public void start() {
+ Map<String, String> databaseProperties = Maps.newHashMap();
+ for (PropertyDto property : propertiesDao.selectGlobalProperties()) {
+ databaseProperties.put(property.getKey(), property.getValue());
+ }
+ settings.activateDatabaseSettings(SonarHome.getHome(), databaseProperties);
+ }
+
+ public PersistentSettings saveProperty(String key, @Nullable String value) {
+ settings.setProperty(key, value);
+ propertiesDao.setProperty(new PropertyDto().setKey(key).setValue(value));
+ return this;
+ }
+
+ public PersistentSettings removeProperty(String key) {
+ settings.removeProperty(key);
+ propertiesDao.deleteGlobalProperty(key);
+ return this;
+ }
+
+ public PersistentSettings deleteProperties() {
+ settings.clear();
+ propertiesDao.deleteGlobalProperties();
+ return this;
+ }
+
+ public PersistentSettings saveProperties(Map<String, String> properties) {
+ settings.addProperties(properties);
+ propertiesDao.saveGlobalProperties(properties);
+ return this;
+ }
+
+ public String getString(String key) {
+ return settings.getString(key);
+ }
+
+ public Map<String, String> getProperties() {
+ return settings.getProperties();
+ }
+
+ public Settings getSettings() {
+ return settings;
+ }
+}
import org.sonar.server.qualitymodel.DefaultModelManager;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
-import org.sonar.server.startup.ActivateDefaultProfiles;
-import org.sonar.server.startup.DeleteDeprecatedMeasures;
-import org.sonar.server.startup.EnableProfiles;
-import org.sonar.server.startup.GeneratePluginIndex;
-import org.sonar.server.startup.GwtPublisher;
-import org.sonar.server.startup.JdbcDriverDeployer;
-import org.sonar.server.startup.RegisterMetrics;
-import org.sonar.server.startup.RegisterNewDashboards;
-import org.sonar.server.startup.RegisterNewFilters;
-import org.sonar.server.startup.RegisterProvidedProfiles;
-import org.sonar.server.startup.RegisterQualityModels;
-import org.sonar.server.startup.RegisterRules;
-import org.sonar.server.startup.ServerMetadataPersister;
+import org.sonar.server.startup.*;
import org.sonar.server.ui.CodeColorizers;
import org.sonar.server.ui.JRubyI18n;
import org.sonar.server.ui.SecurityRealmFactory;
private void startCoreComponents() {
coreContainer = rootContainer.createChild();
- coreContainer.addSingleton(ServerDatabaseSettingsLoader.class);
+ coreContainer.addSingleton(PersistentSettings.class);
coreContainer.addSingleton(DefaultDatabaseConnector.class);
coreContainer.addSingleton(ServerExtensionInstaller.class);
coreContainer.addSingleton(ThreadLocalDatabaseSessionFactory.class);
servicesContainer.addSingleton(ReviewDatabaseStore.class);
servicesContainer.addSingleton(WorkflowEngine.class);
- servicesContainer.addSingleton(GlobalSettingsUpdater.class);
servicesContainer.addSingleton(HttpDownloader.class);
servicesContainer.addSingleton(UpdateCenterClient.class);
servicesContainer.addSingleton(UpdateCenterMatrixFactory.class);
startupContainer.addSingleton(GeneratePluginIndex.class);
startupContainer.addSingleton(RegisterNewFilters.class);
startupContainer.addSingleton(RegisterNewDashboards.class);
+ startupContainer.addSingleton(SetDefaultProjectPermissions.class);
startupContainer.startComponents();
startupContainer.getComponentByType(ServerLifecycleNotifier.class).notifyStart();
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 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.server.platform;
-
-import org.sonar.core.properties.PropertiesDao;
-
-/**
- * @since 3.0
- */
-public final class ServerDatabaseSettingsLoader {
-
- private PropertiesDao propertiesDao;
- private ServerSettings settings;
-
- public ServerDatabaseSettingsLoader(PropertiesDao propertiesDao, ServerSettings settings) {
- this.propertiesDao = propertiesDao;
- this.settings = settings;
- }
-
- public void start() {
- settings.activateDatabaseSettings(propertiesDao);
- }
-}
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.configuration.Configuration;
import org.sonar.api.CoreProperties;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.config.GlobalPropertyChangeHandler;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.Settings;
import org.sonar.core.config.ConfigurationUtils;
-import org.sonar.core.properties.PropertiesDao;
-import org.sonar.core.properties.PropertyDto;
+import javax.annotation.Nullable;
import javax.servlet.ServletContext;
import java.io.File;
-import java.util.List;
+import java.util.Collections;
+import java.util.Map;
import java.util.Properties;
/**
*
* @since 2.12
*/
-public class ServerSettings extends Settings {
+public class ServerSettings extends Settings implements ServerComponent {
public static final String DEPLOY_DIR = "sonar.web.deployDir";
- private PropertiesDao propertiesDao;
private Configuration deprecatedConfiguration;
private File deployDir;
+ private GlobalPropertyChangeHandler[] changeHandlers;
+
+ public ServerSettings(PropertyDefinitions definitions, Configuration deprecatedConfiguration, ServletContext servletContext, GlobalPropertyChangeHandler[] changeHandlers) {
+ this(definitions, deprecatedConfiguration, getDeployDir(servletContext), SonarHome.getHome(), changeHandlers);
+ }
public ServerSettings(PropertyDefinitions definitions, Configuration deprecatedConfiguration, ServletContext servletContext) {
- super(definitions);
- this.deprecatedConfiguration = deprecatedConfiguration;
- this.deployDir = getDeployDir(servletContext);
- load();
+ this(definitions, deprecatedConfiguration, servletContext, new GlobalPropertyChangeHandler[0]);
}
- ServerSettings(PropertyDefinitions definitions, Configuration deprecatedConfiguration, File deployDir, File sonarHome) {
+ @VisibleForTesting
+ ServerSettings(PropertyDefinitions definitions, Configuration deprecatedConfiguration, File deployDir, File sonarHome, GlobalPropertyChangeHandler[] changeHandlers) {
super(definitions);
this.deprecatedConfiguration = deprecatedConfiguration;
this.deployDir = deployDir;
- load(sonarHome);
- }
-
- public ServerSettings activateDatabaseSettings(PropertiesDao dao) {
- return activateDatabaseSettings(dao, SonarHome.getHome());
- }
-
- @VisibleForTesting
- ServerSettings activateDatabaseSettings(PropertiesDao dao, File sonarHome) {
- this.propertiesDao = dao;
- load(sonarHome);
- return this;
+ this.changeHandlers = changeHandlers;
+ load(sonarHome, Collections.<String, String>emptyMap());
}
- private ServerSettings load() {
- return load(SonarHome.getHome());
+ public ServerSettings activateDatabaseSettings(File sonarHome, Map<String, String> databaseProperties) {
+ return load(sonarHome, databaseProperties);
}
- private ServerSettings load(File sonarHome) {
- clear();
- setProperty(CoreProperties.SONAR_HOME, sonarHome.getAbsolutePath());
- setProperty(DEPLOY_DIR, deployDir.getAbsolutePath());
+ private ServerSettings load(File sonarHome, Map<String, String> databaseSettings) {
+ properties.clear();
+ properties.put(CoreProperties.SONAR_HOME, sonarHome.getAbsolutePath());
+ properties.put(DEPLOY_DIR, deployDir.getAbsolutePath());
// order is important : the last override the first
- loadDatabaseSettings();
+ properties.putAll(databaseSettings);
loadPropertiesFile(sonarHome);
addEnvironmentVariables();
addSystemProperties();
return this;
}
- private void loadDatabaseSettings() {
- if (propertiesDao != null) {
- List<PropertyDto> dpProps = propertiesDao.selectGlobalProperties();
- for (PropertyDto dbProp : dpProps) {
- setProperty(dbProp.getKey(), dbProp.getValue());
- }
- }
- }
-
private void loadPropertiesFile(File sonarHome) {
File propertiesFile = new File(sonarHome, "conf/sonar.properties");
if (!propertiesFile.isFile() || !propertiesFile.exists()) {
try {
Properties p = ConfigurationUtils.openProperties(propertiesFile);
p = ConfigurationUtils.interpolateEnvVariables(p);
- addProperties(p);
+ for (Map.Entry<Object, Object> entry : p.entrySet()) {
+ properties.put(entry.getKey().toString(), entry.getValue().toString());
+ }
} catch (Exception e) {
throw new IllegalStateException("Fail to load configuration file: " + propertiesFile, e);
}
}
return dir;
}
+
+ @Override
+ protected void doOnSetProperty(String key, @Nullable String value) {
+ deprecatedConfiguration.setProperty(key, value);
+
+ GlobalPropertyChangeHandler.PropertyChange change = GlobalPropertyChangeHandler.PropertyChange.create(key, value);
+ for (GlobalPropertyChangeHandler changeHandler : changeHandlers) {
+ changeHandler.onChange(change);
+ }
+ }
+
+ @Override
+ protected void doOnRemoveProperty(String key) {
+ deprecatedConfiguration.clearProperty(key);
+ }
+
+ @Override
+ protected void doOnClearProperties() {
+ deprecatedConfiguration.clear();
+ }
}
.setOrderIndex(index);
activeDashboardDao.insert(activeDashboardDto);
- LOG.info("New dashboard '" + dashboardDto.getName() + "' registered");
+ LoggerFactory.getLogger(getClass()).info("New dashboard '" + dashboardDto.getName() + "' registered");
}
protected DashboardDto register(String name, Dashboard dashboard) {
}
public void start() {
- TimeProfiler profiler = new TimeProfiler().start("Register filters");
+ TimeProfiler profiler = new TimeProfiler(LoggerFactory.getLogger(getClass())).start("Register filters");
for (FilterTemplate template : filterTemplates) {
if (shouldRegister(template.getName())) {
*/
package org.sonar.server.startup;
+import com.google.common.collect.ImmutableMap;
+import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.configuration.Property;
import org.sonar.api.platform.Server;
+import org.sonar.server.platform.PersistentSettings;
import java.text.SimpleDateFormat;
-public class ServerMetadataPersister {
+public final class ServerMetadataPersister {
private final Server server;
- private final DatabaseSession session;
+ private final PersistentSettings persistentSettings;
- public ServerMetadataPersister(Server server, DatabaseSession session) {
+ public ServerMetadataPersister(Server server, PersistentSettings persistentSettings) {
this.server = server;
- this.session = session;
+ this.persistentSettings = persistentSettings;
}
public void start() {
- setProperty(CoreProperties.SERVER_ID, server.getId());
- setProperty(CoreProperties.SERVER_VERSION, server.getVersion());
- setProperty(CoreProperties.SERVER_STARTTIME, new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(server.getStartedAt()));
- session.commit();
- }
-
- private void setProperty(String key, String value) {
- Property prop = session.getSingleResult(Property.class, "key", key);
-
- if (value == null && prop != null) {
- session.removeWithoutFlush(prop);
-
- } else if (value != null) {
- if (prop == null) {
- prop = new Property(key, value);
- } else {
- prop.setValue(value);
- }
- session.saveWithoutFlush(prop);
- }
+ LoggerFactory.getLogger(getClass()).debug("Persisting server metadata");
+ persistentSettings.saveProperties(ImmutableMap.of(
+ CoreProperties.SERVER_ID, server.getId(),
+ CoreProperties.SERVER_VERSION, server.getVersion(),
+ CoreProperties.SERVER_STARTTIME, new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(server.getStartedAt())));
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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.server.startup;
+
+import com.google.common.collect.Maps;
+import org.slf4j.LoggerFactory;
+import org.sonar.server.platform.PersistentSettings;
+
+import java.util.Map;
+
+/**
+ * @since 3.2
+ */
+public class SetDefaultProjectPermissions {
+ private final PersistentSettings persistentSettings;
+
+ public SetDefaultProjectPermissions(PersistentSettings persistentSettings) {
+ this.persistentSettings = persistentSettings;
+ }
+
+ public void start() {
+ if (persistentSettings.getSettings().getKeysStartingWith("sonar.role.").isEmpty()) {
+ LoggerFactory.getLogger(SetDefaultProjectPermissions.class).info("Setting default project permissions");
+ Map<String, String> props = Maps.newHashMap();
+ props.put("sonar.role.admin.TRK.defaultGroups", "sonar-administrators");
+ props.put("sonar.role.user.TRK.defaultGroups", "Anyone,sonar-users");
+ props.put("sonar.role.codeviewer.TRK.defaultGroups", "Anyone,sonar-users");
+
+ // Support old versions of Views plugin
+ props.put("sonar.role.admin.VW.defaultGroups", "sonar-administrators");
+ props.put("sonar.role.user.VW.defaultGroups", "Anyone,sonar-users");
+ props.put("sonar.role.codeviewer.VW.defaultGroups", "Anyone,sonar-users");
+ props.put("sonar.role.admin.SVW.defaultGroups", "sonar-administrators");
+ props.put("sonar.role.user.SVW.defaultGroups", "Anyone,sonar-users");
+ props.put("sonar.role.codeviewer.SVW.defaultGroups", "Anyone,sonar-users");
+
+ persistentSettings.saveProperties(props);
+ }
+ }
+}
import org.sonar.server.filters.FilterExecutor;
import org.sonar.server.filters.FilterResult;
import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
-import org.sonar.server.platform.GlobalSettingsUpdater;
-import org.sonar.server.platform.NewUserNotifier;
-import org.sonar.server.platform.Platform;
-import org.sonar.server.platform.ServerIdGenerator;
+import org.sonar.server.platform.*;
import org.sonar.server.plugins.*;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
}
public void setGlobalProperty(String key, @Nullable String value) {
- get(GlobalSettingsUpdater.class).setProperty(key, value);
+ get(ServerSettings.class).setProperty(key, value);
}
public Settings getSettings() {
class User < ActiveRecord::Base
end
+
class UserRole < ActiveRecord::Base
end
# upgrade from version < 3.2.
move_groups
move_users
- else
- create_default_groups('admin', 'TRK', 'sonar-administrators')
- create_default_groups('user', 'TRK', 'Anyone,sonar-users')
- create_default_groups('codeviewer', 'TRK', 'Anyone,sonar-users')
-
- # Support old versions of Views plugin
- create_default_groups('admin', 'VW', 'sonar-administrators')
- create_default_groups('user', 'VW', 'Anyone,sonar-users')
- create_default_groups('codeviewer', 'VW', 'Anyone,sonar-users')
- create_default_groups('admin', 'SVW', 'sonar-administrators')
- create_default_groups('user', 'SVW', 'Anyone,sonar-users')
- create_default_groups('codeviewer', 'SVW', 'Anyone,sonar-users')
end
end
private
- def self.create_default_groups(role, qualifier, groups)
- Property.create(:prop_key => "sonar.role.#{role}.#{qualifier}.defaultGroups", :text_value => groups)
- Property.create(:prop_key => "sonar.role.#{role}.#{qualifier}.defaultUsers", :text_value => '')
- end
-
def self.move_groups
groups_per_role={}
group_roles = GroupRole.find(:all, :conditions => ['resource_id is null and role like ?', 'default-%'])
import org.sonar.api.rules.RuleParam;
import org.sonar.api.rules.RulePriority;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
+import org.sonar.server.platform.PersistentSettings;
import org.sonar.test.TestUtils;
import java.io.IOException;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
public class ProfilesBackupTest extends AbstractDbUnitTestCase {
*/
@Test
public void shouldSupportMissingEnabledField() throws IOException {
- Backup backup = new Backup(getSession());
+ Backup backup = new Backup(getSession(), mock(PersistentSettings.class));
backup.doImportXml(FileUtils.readFileToString(TestUtils.getResource(getClass(), "shouldSupportMissingEnabledField.xml")));
RulesProfile profile = getSession().getSingleResult(RulesProfile.class, "name", "Missing enabled field");
@Test
public void shouldSupportEnabledField() throws IOException {
- Backup backup = new Backup(getSession());
+ Backup backup = new Backup(getSession(), mock(PersistentSettings.class));
backup.doImportXml(FileUtils.readFileToString(TestUtils.getResource(getClass(), "shouldSupportEnabledField.xml")));
RulesProfile enabledProfile = getSession().getSingleResult(RulesProfile.class, "name", "Enabled");
*/
package org.sonar.server.configuration;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.CharEncoding;
+import com.google.common.collect.ImmutableMap;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.CoreProperties;
import org.sonar.api.database.configuration.Property;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
-import org.sonar.test.TestUtils;
+import org.sonar.server.platform.PersistentSettings;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Map;
-import static org.hamcrest.Matchers.endsWith;
-import static org.hamcrest.Matchers.startsWith;
-import static org.hamcrest.collection.IsCollectionContaining.hasItem;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
public class PropertiesBackupTest extends AbstractDbUnitTestCase {
- private SonarConfig sonarConfig;
+ private PersistentSettings persistentSettings;
+ private PropertiesBackup backup;
@Before
public void setup() {
- sonarConfig = new SonarConfig();
+ persistentSettings = mock(PersistentSettings.class);
+ backup = new PropertiesBackup(persistentSettings);
}
@Test
- public void shouldExportProperties() {
- setupData("shouldExportProperties");
+ public void export_properties() {
+ when(persistentSettings.getProperties()).thenReturn(ImmutableMap.of("key1", "value1", "key2", "value2"));
- new PropertiesBackup(getSession()).exportXml(sonarConfig);
+ SonarConfig config = new SonarConfig();
+ backup.exportXml(config);
- Property prop1 = new Property("key1", "value1");
- Property prop2 = new Property("key2", "value2");
- Property prop3 = new Property("sonar.core.version", "3.1");
-
- assertTrue(CollectionUtils.isEqualCollection(sonarConfig.getProperties(), Arrays.asList(prop1, prop2, prop3)));
+ assertThat(config.getProperties()).containsOnly(new Property("key1", "value1"), new Property("key2", "value2"));
}
@Test
- public void shouldNotExportPropertiesLinkedToResources() {
- setupData("shouldNotExportPropertiesLinkedToResources");
-
- new PropertiesBackup(getSession()).exportXml(sonarConfig);
+ public void do_not_export_server_id() {
+ when(persistentSettings.getProperties()).thenReturn(ImmutableMap.of(CoreProperties.SERVER_ID, "111"));
- Property prop1 = new Property("key1", "value1");
- Property prop2 = new Property("key2", "value2");
+ SonarConfig config = new SonarConfig();
+ backup.exportXml(config);
- assertTrue(CollectionUtils.isEqualCollection(sonarConfig.getProperties(), Arrays.asList(prop1, prop2)));
+ assertThat(config.getProperties()).isEmpty();
}
- @Test
- public void shouldExportAnArrayProperty() {
- setupData("shouldExportAnArrayProperty");
-
- new PropertiesBackup(getSession()).exportXml(sonarConfig);
-
- assertThat(sonarConfig.getProperties(), hasItem(new Property("key1", "value1,value2,value3")));
- }
-
- @Test
- public void shouldImportProperties() {
- setupData("shouldImportProperties");
-
- Collection<Property> newProperties = Arrays.asList(new Property("key1", "value1"), new Property("key2", "value2"), new Property("key3", "value3"));
- sonarConfig.setProperties(newProperties);
-
- new PropertiesBackup(getSession()).importXml(sonarConfig);
-
- checkTables("shouldImportProperties", "properties");
- }
@Test
- public void shouldNotImportSonarCoreIdProperty() {
- setupData("shouldNotImportSonarCoreIdProperty");
-
- Collection<Property> newProperties = Arrays.asList(new Property("sonar.core.id", "11111111"));
- sonarConfig.setProperties(newProperties);
-
- new PropertiesBackup(getSession()).importXml(sonarConfig);
-
- checkTables("shouldNotImportSonarCoreIdProperty", "properties");
+ public void import_backup_of_properties() {
+ Collection<Property> newProperties = Arrays.asList(new Property("key1", "value1"), new Property("key2", "value2"));
+ SonarConfig config = new SonarConfig();
+ config.setProperties(newProperties);
+
+ backup.importXml(config);
+
+ verify(persistentSettings).saveProperties(argThat(new BaseMatcher<Map<String, String>>() {
+ public boolean matches(Object o) {
+ Map<String, String> map = (Map<String, String>) o;
+ return map.get("key1").equals("value1") && map.get("key2").equals("value2");
+ }
+
+ public void describeTo(Description description) {
+ }
+ }));
}
@Test
- public void shouldImportMultilineProperties() throws Exception {
- setupData("shouldImportMultilineProperties");
-
- new Backup(getSession()).doImportXml(
- FileUtils.readFileToString(
- TestUtils.getResource(getClass(), "backup-with-multiline-property.xml"), CharEncoding.UTF_8));
-
- Property property = getSession().getSingleResult(Property.class, "key", "sonar.multiline.secured");
- assertThat(property.getValue(), startsWith("ONQwdcwcwwdadalkdmaiQGMqMVnhtAbhxwjjoVkHbWgx"));
- assertThat(property.getValue(), endsWith("mmmm"));
-
+ public void do_not_import_server_id() {
+ // initial server id
+ when(persistentSettings.getString(CoreProperties.SERVER_ID)).thenReturn("111");
+
+ Collection<Property> newProperties = Arrays.asList(new Property(CoreProperties.SERVER_ID, "999"));
+ SonarConfig config = new SonarConfig();
+ config.setProperties(newProperties);
+ backup.importXml(config);
+
+ verify(persistentSettings).saveProperties(argThat(new BaseMatcher<Map<String, String>>() {
+ public boolean matches(Object o) {
+ Map<String, String> map = (Map<String, String>) o;
+ return map.get(CoreProperties.SERVER_ID).equals("111");
+ }
+
+ public void describeTo(Description description) {
+ }
+ }));
}
}
*/
package org.sonar.server.platform;
+import com.google.common.collect.ImmutableMap;
import org.apache.commons.configuration.BaseConfiguration;
import org.junit.Test;
+import org.sonar.api.config.GlobalPropertyChangeHandler;
import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.core.persistence.AbstractDaoTestCase;
-import org.sonar.core.properties.PropertiesDao;
import java.io.File;
import java.net.URISyntaxException;
+import java.util.Map;
-import static org.hamcrest.Matchers.nullValue;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
+import static org.fest.assertions.Assertions.assertThat;
-public class ServerSettingsTest extends AbstractDaoTestCase {
+public class ServerSettingsTest {
private static File home = getHome();
@Test
public void shouldLoadPropertiesFile() {
- ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home);
+ ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home, new GlobalPropertyChangeHandler[0]);
- assertThat(settings.getString("hello"), is("world"));
+ assertThat(settings.getString("hello")).isEqualTo("world");
}
@Test
public void systemPropertiesShouldOverridePropertiesFile() {
System.setProperty("ServerSettingsTestEnv", "in_env");
- ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home);
+ ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home, new GlobalPropertyChangeHandler[0]);
- assertThat(settings.getString("ServerSettingsTestEnv"), is("in_env"));
+ assertThat(settings.getString("ServerSettingsTestEnv")).isEqualTo("in_env");
}
@Test(expected = IllegalStateException.class)
public void shouldFailIfPropertiesFileNotFound() {
File sonarHome = new File("unknown/path");
- new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), sonarHome);
+ new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), sonarHome, new GlobalPropertyChangeHandler[0]);
}
@Test
- public void shouldActivateDatabaseSettings() {
- setupData("db/shared");
+ public void activateDatabaseSettings() {
+ ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home, new GlobalPropertyChangeHandler[0]);
- ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home);
- settings.activateDatabaseSettings(new PropertiesDao(getMyBatis()), home);
+ Map<String, String> databaseProperties = ImmutableMap.of("in_db", "true");
+ settings.activateDatabaseSettings(home, databaseProperties);
- assertThat(settings.getString("global_only"), is("is_global"));
- assertThat(settings.getString("global_and_project"), is("is_global"));
- assertThat(settings.getString("project_only"), nullValue());
+ assertThat(settings.getString("in_db")).isEqualTo("true");
+ }
+
+ @Test
+ public void file_settings_override_db_settings() {
+ ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home, new GlobalPropertyChangeHandler[0]);
+ assertThat(settings.getString("in_file")).isEqualTo("true");
+
+ Map<String, String> databaseProperties = ImmutableMap.of("in_file", "false");
+ settings.activateDatabaseSettings(home, databaseProperties);
+
+ assertThat(settings.getString("in_file")).isEqualTo("true");
}
private static File getHome() {
*/
package org.sonar.server.startup;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.CoreProperties;
import org.sonar.api.platform.Server;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
+import org.sonar.server.platform.PersistentSettings;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Map;
import java.util.TimeZone;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
-public class ServerMetadataPersisterTest extends AbstractDbUnitTestCase {
+public class ServerMetadataPersisterTest {
private TimeZone initialTimeZone;
+ private PersistentSettings persistentSettings;
@Before
public void fixTimeZone() {
initialTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ persistentSettings = mock(PersistentSettings.class);
}
@After
@Test
public void testSaveProperties() throws ParseException {
- setupData("testSaveProperties");
- persist(newServer());
- checkTables("testSaveProperties", "properties");
- }
-
- @Test
- public void testUpdateExistingProperties() throws ParseException {
- setupData("testUpdateExistingProperties");
- persist(newServer());
- checkTables("testUpdateExistingProperties", "properties");
- }
-
- @Test
- public void testDeleteProperties() throws ParseException {
- setupData("testDeleteProperties");
- Server server = mock(Server.class);
- when(server.getStartedAt()).thenReturn(new SimpleDateFormat("yyyy-MM-dd HH:mm").parse("2010-05-18 17:59"));//this is a mandatory not-null property
- persist(server);
- checkTables("testDeleteProperties", "properties");
- }
-
- private void persist(Server server) {
- ServerMetadataPersister persister = new ServerMetadataPersister(server, getSession());
- persister.start();
- }
-
- private Server newServer() throws ParseException {
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse("2010-05-18 17:59");
Server server = mock(Server.class);
when(server.getPermanentServerId()).thenReturn("1abcdef");
when(server.getId()).thenReturn("123");
- when(server.getVersion()).thenReturn("2.2");
+ when(server.getVersion()).thenReturn("3.2");
when(server.getStartedAt()).thenReturn(date);
+ ServerMetadataPersister persister = new ServerMetadataPersister(server, persistentSettings);
+ persister.start();
- return server;
+ verify(persistentSettings).saveProperties(argThat(new BaseMatcher<Map<String, String>>() {
+ public boolean matches(Object o) {
+ Map<String, String> map = (Map<String, String>) o;
+ return map.get(CoreProperties.SERVER_ID).equals("123")
+ && map.get(CoreProperties.SERVER_VERSION).equals("3.2")
+ && map.get(CoreProperties.SERVER_STARTTIME).equals("2010-05-18T17:59:00+0000")
+ && map.size() == 3;
+ }
+ public void describeTo(Description description) {
+ }
+ }));
}
+
+
}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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.server.startup;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.server.platform.PersistentSettings;
+
+import java.util.Map;
+
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
+
+public class SetDefaultProjectPermissionsTest {
+ @Test
+ public void set_default_permissions_if_none() {
+ PersistentSettings persistentSettings = mock(PersistentSettings.class);
+ Settings settings = new Settings();
+ when(persistentSettings.getSettings()).thenReturn(settings);
+
+ new SetDefaultProjectPermissions(persistentSettings).start();
+
+ verify(persistentSettings).saveProperties(argThat(new BaseMatcher<Map<String, String>>() {
+ public boolean matches(Object o) {
+ Map<String, String> map = (Map<String, String>) o;
+ return map.size() == 9 && map.get("sonar.role.admin.TRK.defaultGroups").equals("sonar-administrators");
+ }
+
+ public void describeTo(Description description) {
+ }
+ }));
+ }
+
+ @Test
+ public void do_not_set_default_permissions_if_exist() {
+ PersistentSettings persistentSettings = mock(PersistentSettings.class);
+ Settings settings = new Settings().setProperty("sonar.role.admin.TRK.defaultGroups", "custom-group");
+ when(persistentSettings.getSettings()).thenReturn(settings);
+
+ new SetDefaultProjectPermissions(persistentSettings).start();
+
+ verify(persistentSettings, never()).saveProperties(any(Map.class));
+ }
+}
hello: world
+in_file: true
ServerSettingsTestEnv: in_file
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <!-- project -->
- <projects long_name="[null]" id="3333" scope="PRJ" qualifier="TRK" kee="mygroup:anotherproject" name="[null]"
- root_id="[null]"
- description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" person_id="[null]"/>
-
- <!-- global properties -->
- <properties prop_key="global_only" resource_id="[null]" user_id="[null]" text_value="is_global"/>
- <properties prop_key="global_and_project" resource_id="[null]" user_id="[null]" text_value="is_global"/>
-
- <!-- project properties: do not load -->
- <properties prop_key="global_and_project" resource_id="3333" user_id="[null]" text_value="is_project"/>
- <properties prop_key="project_only" resource_id="3333" user_id="[null]" text_value="is_project"/>
-
- <!-- user properties : do not load -->
- <properties prop_key="user" resource_id="[null]" user_id="110" text_value="is_user"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <properties id="1" prop_key="other" resource_id="[null]" text_value="some text" user_id="[null]"/>
-
- <!-- not null property -->
- <properties id="4" prop_key="sonar.core.startTime" resource_id="[null]" text_value="2010-05-18T17:59:00+0000" user_id="[null]"/>
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <properties id="1" prop_key="other" resource_id="[null]" text_value="some text" user_id="[null]" />
-
- <properties id="2" prop_key="sonar.core.id" resource_id="[null]" text_value="123" user_id="[null]"/>
- <properties id="3" prop_key="sonar.core.version" resource_id="[null]" text_value="2.2" user_id="[null]"/>
- <properties id="4" prop_key="sonar.core.startTime" resource_id="[null]" text_value="2010-05-18T17:59:00+0000" user_id="[null]"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <properties id="1" prop_key="other" resource_id="[null]" text_value="some text" user_id="[null]" />
-
- <properties id="2" prop_key="sonar.core.id" resource_id="[null]" text_value="123" user_id="[null]"/>
- <properties id="3" prop_key="sonar.core.version" resource_id="[null]" text_value="2.2" user_id="[null]"/>
- <properties id="4" prop_key="sonar.core.startTime" resource_id="[null]" text_value="2010-05-18T17:59:00+0000" user_id="[null]"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <properties id="1" prop_key="other" resource_id="[null]" text_value="some text" user_id="[null]"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <properties id="1" prop_key="other" resource_id="[null]" text_value="some text" user_id="[null]"/>
-
- <properties id="2" prop_key="sonar.core.id" resource_id="[null]" text_value="123" user_id="[null]"/>
- <properties id="3" prop_key="sonar.core.version" resource_id="[null]" text_value="2.2" user_id="[null]"/>
- <properties id="4" prop_key="sonar.core.startTime" resource_id="[null]" text_value="2010-05-18T17:59:00+0000" user_id="[null]"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <properties id="1" prop_key="other" resource_id="[null]" text_value="some text" user_id="[null]"/>
-
- <properties id="2" prop_key="sonar.core.id" resource_id="[null]" text_value="65" user_id="[null]"/>
- <properties id="3" prop_key="sonar.core.version" resource_id="[null]" text_value="1.9" user_id="[null]"/>
- <properties id="4" prop_key="sonar.core.startTime" resource_id="[null]" text_value="2008-04-18T17:59:00+0000" user_id="[null]"/>
-
-</dataset>
\ No newline at end of file