import java.util.TreeSet;
public class DryRunDatabaseFactory implements ServerComponent {
- private static final String SONAR_DRY_RUN_CACHE_LAST_UPDATE = "sonar.dryRun.cache.lastUpdate";
+ public static final String SONAR_DRY_RUN_CACHE_KEY_PREFIX = "sonar.dryRun.cache.";
+ public static final String SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY = SONAR_DRY_RUN_CACHE_KEY_PREFIX + "lastUpdate";
private static final Logger LOG = LoggerFactory.getLogger(DryRunDatabaseFactory.class);
private static final String DIALECT = "h2";
private static final String DRIVER = "org.h2.Driver";
private final Settings settings;
private final ResourceDao resourceDao;
+ public static String getCacheLastUpdateKey(Long rootProjectId) {
+ return SONAR_DRY_RUN_CACHE_KEY_PREFIX + rootProjectId + ".lastUpdate";
+ }
+
public DryRunDatabaseFactory(Database database, ServerFileSystem serverFileSystem, Settings settings, ResourceDao resourceDao) {
this.database = database;
this.serverFileSystem = serverFileSystem;
}
private boolean isValid(@Nullable Long projectId, long lastTimestampInCache) {
- long globalTimestamp = settings.getLong(SONAR_DRY_RUN_CACHE_LAST_UPDATE);
+ long globalTimestamp = settings.getLong(SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY);
if (globalTimestamp > lastTimestampInCache) {
return false;
}
if (projectId != null) {
// For modules look for root project last modification timestamp
Long rootId = resourceDao.getRootProjectByComponentId(projectId).getId();
- long projectTimestamp = settings.getLong("sonar.dryRun.cache." + rootId + ".lastUpdate");
+ long projectTimestamp = settings.getLong(getCacheLastUpdateKey(rootId));
if (projectTimestamp > lastTimestampInCache) {
return false;
}
this.mybatis = mybatis;
}
+ public UserDto getUser(long userId) {
+ SqlSession session = mybatis.openSession();
+ try {
+ return getUser(userId, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public UserDto getUser(long userId, SqlSession session) {
+ return session.getMapper(UserMapper.class).selectUser(userId);
+ }
+
/**
* Search for user by login. Disabled users are ignored.
*
import org.sonar.api.user.UserQuery;
import javax.annotation.CheckForNull;
+
import java.util.List;
public interface UserMapper {
+ @CheckForNull
+ UserDto selectUser(long userId);
+
/**
* Select user by login. Note that disabled users are ignored.
*/
GroupDto selectGroupByName(String name);
void removeUserFromGroups(long userId);
+
void deleteUserActiveDashboards(long userId);
+
void deleteUserDashboards(long userId);
+
void deleteUserIssueFilters(String login);
+
void deleteUserIssueFilterFavourites(String login);
+
void deleteUserMeasureFilters(long userId);
+
void deleteUserMeasureFilterFavourites(long userId);
+
void deleteUserProperties(long userId);
+
void deleteUserRoles(long userId);
+
void deactivateUser(long userId);
}
u.active as "active"
</sql>
+ <select id="selectUser" parameterType="long" resultType="User">
+ SELECT
+ <include refid="userColumns"/>
+ FROM users u WHERE u.id=#{id}
+ </select>
+
<select id="selectUserByLogin" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
import static org.fest.assertions.Assertions.assertThat;
-
public class UserDaoTest extends AbstractDaoTestCase {
private UserDao dao;
public void selectUserByLogin_ignore_inactive() {
setupData("selectActiveUserByLogin");
- UserDto user = dao.selectActiveUserByLogin("inactive_user");
+ UserDto user = dao.getUser(50);
+ assertThat(user.getLogin()).isEqualTo("inactive_user");
+
+ user = dao.selectActiveUserByLogin("inactive_user");
assertThat(user).isNull();
}
@Test
public void selectUsersByLogins_empty_logins() throws Exception {
// no need to access db
- Collection<UserDto> users = dao.selectUsersByLogins(Collections.<String>emptyList());
+ Collection<UserDto> users = dao.selectUsersByLogins(Collections.<String> emptyList());
assertThat(users).isEmpty();
}
*/
package org.sonar.api.config;
-import org.sonar.api.ServerExtension;
-
import javax.annotation.Nullable;
/**
*
* @since 3.0
*/
-public abstract class GlobalPropertyChangeHandler implements ServerExtension {
+public abstract class GlobalPropertyChangeHandler implements SettingsChangeHandler {
public static final class PropertyChange {
private String key;
* This method gets called when a property is changed.
*/
public abstract void onChange(PropertyChange change);
+
+ @Override
+ public void onChange(SettingsChange change) {
+ if (change.isGlobal()) {
+ onChange(PropertyChange.create(change.key(), change.newValue()));
+ }
+ }
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.config;
+
+import org.sonar.api.ServerExtension;
+
+import javax.annotation.Nullable;
+
+/**
+ * Observe changes of properties done from web application. It does not support :
+ * <ul>
+ * <li>changes done programmatically on the component org.sonar.api.config.Settings</li>
+ * </ul>
+ *
+ * @since 4.0
+ */
+public interface SettingsChangeHandler extends ServerExtension {
+
+ public static final class SettingsChange {
+ private String key;
+ private String newValue;
+ private String componentKey;
+ private String userLogin;
+
+ private SettingsChange(String key, @Nullable String newValue, @Nullable String componentKey, @Nullable String userLogin) {
+ this.key = key;
+ this.newValue = newValue;
+ this.componentKey = componentKey;
+ this.userLogin = userLogin;
+ }
+
+ public static SettingsChange create(String key, @Nullable String newValue, @Nullable String componentKey, @Nullable String userLogin) {
+ return new SettingsChange(key, newValue, componentKey, userLogin);
+ }
+
+ public String key() {
+ return key;
+ }
+
+ public String newValue() {
+ return newValue;
+ }
+
+ public String componentKey() {
+ return componentKey;
+ }
+
+ public String userLogin() {
+ return userLogin;
+ }
+
+ public boolean isGlobal() {
+ return componentKey == null && userLogin == null;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("[key=%s, newValue=%s, componentKey=%s]", key, newValue, componentKey);
+ }
+ }
+
+ /**
+ * This method gets called when a property is changed.
+ */
+ public void onChange(SettingsChange change);
+
+}
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.database.configuration.Property;
+import org.sonar.core.persistence.DryRunDatabaseFactory;
import org.sonar.core.properties.PropertyDto;
import org.sonar.server.platform.PersistentSettings;
private boolean shouldBeExported(String propertyKey) {
// "sonar.core.id" must never be restored, it is unique for a server and it created once at the 1rst server startup
// default permissions properties should not be exported as they reference permission_templates entries in the DB
- return !CoreProperties.SERVER_ID.equals(propertyKey) && !propertyKey.startsWith(PERMISSION_PROPERTIES_PREFIX);
+ return !CoreProperties.SERVER_ID.equals(propertyKey)
+ && !propertyKey.startsWith(PERMISSION_PROPERTIES_PREFIX)
+ && !propertyKey.startsWith(DryRunDatabaseFactory.SONAR_DRY_RUN_CACHE_KEY_PREFIX);
}
private boolean shouldNotBeErased(String propertyKey) {
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.platform;
+
+import org.sonar.api.config.SettingsChangeHandler;
+import org.sonar.core.persistence.DryRunDatabaseFactory;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
+
+public class DryRunCacheListener implements SettingsChangeHandler {
+
+ private final PersistentSettings settings;
+ private final ResourceDao resourceDao;
+
+ public DryRunCacheListener(PersistentSettings settings, ResourceDao resourceDao) {
+ this.settings = settings;
+ this.resourceDao = resourceDao;
+ }
+
+ @Override
+ public void onChange(SettingsChange change) {
+ if (change.isGlobal()) {
+ settings.saveProperty(DryRunDatabaseFactory.SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY, String.valueOf(System.nanoTime()));
+ } else if (change.componentKey() != null) {
+ ResourceDto rootProject = resourceDao.getRootProjectByComponentKey(change.componentKey());
+ settings.saveProperty(DryRunDatabaseFactory.getCacheLastUpdateKey(rootProject.getId()), String.valueOf(System.nanoTime()));
+ }
+ }
+}
import org.sonar.core.metric.DefaultMetricFinder;
import org.sonar.core.notification.DefaultNotificationManager;
import org.sonar.core.permission.ComponentPermissionFacade;
-import org.sonar.core.persistence.*;
+import org.sonar.core.persistence.DaoUtils;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.DefaultDatabase;
+import org.sonar.core.persistence.DryRunDatabaseFactory;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.persistence.SemaphoreUpdater;
+import org.sonar.core.persistence.SemaphoresImpl;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.core.qualitymodel.DefaultModelFinder;
import org.sonar.core.resource.DefaultResourcePermissions;
import org.sonar.server.configuration.ProfilesManager;
import org.sonar.server.db.DatabaseMigrator;
import org.sonar.server.db.EmbeddedDatabaseFactory;
-import org.sonar.server.issue.*;
+import org.sonar.server.issue.ActionPlanService;
+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.IssueChangelogService;
+import org.sonar.server.issue.IssueCommentService;
+import org.sonar.server.issue.IssueFilterService;
+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.notifications.NotificationCenter;
import org.sonar.server.notifications.NotificationService;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.InternalPermissionTemplateService;
-import org.sonar.server.plugins.*;
+import org.sonar.server.plugins.ApplicationDeployer;
+import org.sonar.server.plugins.DefaultServerPluginRepository;
+import org.sonar.server.plugins.InstalledPluginReferentialFactory;
+import org.sonar.server.plugins.PluginDeployer;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerExtensionInstaller;
+import org.sonar.server.plugins.UpdateCenterClient;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.server.qualitymodel.DefaultModelManager;
import org.sonar.server.rule.RubyRuleService;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
-import org.sonar.server.startup.*;
+import org.sonar.server.startup.CleanDryRunCache;
+import org.sonar.server.startup.DeleteDeprecatedMeasures;
+import org.sonar.server.startup.GenerateBootstrapIndex;
+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.RegisterMetrics;
+import org.sonar.server.startup.RegisterNewDashboards;
+import org.sonar.server.startup.RegisterNewMeasureFilters;
+import org.sonar.server.startup.RegisterNewProfiles;
+import org.sonar.server.startup.RegisterPermissionTemplates;
+import org.sonar.server.startup.RegisterQualityModels;
+import org.sonar.server.startup.RegisterRules;
+import org.sonar.server.startup.RegisterServletFilters;
+import org.sonar.server.startup.RenameDeprecatedPropertyKeys;
+import org.sonar.server.startup.ServerMetadataPersister;
import org.sonar.server.text.MacroInterpreter;
import org.sonar.server.text.RubyTextService;
-import org.sonar.server.ui.*;
+import org.sonar.server.ui.CodeColorizers;
+import org.sonar.server.ui.JRubyI18n;
+import org.sonar.server.ui.PageDecorations;
+import org.sonar.server.ui.SecurityRealmFactory;
+import org.sonar.server.ui.Views;
import org.sonar.server.user.DefaultUserService;
import org.sonar.server.user.NewUserNotifier;
coreContainer.addSingleton(ThreadLocalDatabaseSessionFactory.class);
coreContainer.addPicoAdapter(new DatabaseSessionProvider());
coreContainer.addSingleton(ServerMetadataPersister.class);
+ coreContainer.addSingleton(DryRunCacheListener.class);
coreContainer.startComponents();
}
startupContainer.addSingleton(RenameDeprecatedPropertyKeys.class);
startupContainer.addSingleton(LogServerId.class);
startupContainer.addSingleton(RegisterServletFilters.class);
+ startupContainer.addSingleton(CleanDryRunCache.class);
startupContainer.startComponents();
startupContainer.getComponentByType(ServerLifecycleNotifier.class).notifyStart();
import com.google.common.annotations.VisibleForTesting;
import org.sonar.api.ServerComponent;
-import org.sonar.api.config.GlobalPropertyChangeHandler;
+import org.sonar.api.config.SettingsChangeHandler;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
+import org.sonar.core.user.UserDao;
+import org.sonar.core.user.UserDto;
import javax.annotation.Nullable;
public class SettingsChangeNotifier implements ServerComponent {
@VisibleForTesting
- GlobalPropertyChangeHandler[] changeHandlers;
+ SettingsChangeHandler[] changeHandlers;
+ private final ResourceDao resourceDao;
+ private final UserDao userDao;
- public SettingsChangeNotifier(GlobalPropertyChangeHandler[] changeHandlers) {
+ public SettingsChangeNotifier(ResourceDao resourceDao, UserDao userDao, SettingsChangeHandler[] changeHandlers) {
+ this.resourceDao = resourceDao;
+ this.userDao = userDao;
this.changeHandlers = changeHandlers;
}
- public SettingsChangeNotifier() {
- this(new GlobalPropertyChangeHandler[0]);
+ public SettingsChangeNotifier(ResourceDao resourceDao, UserDao userDao) {
+ this(resourceDao, userDao, new SettingsChangeHandler[0]);
}
- public void onGlobalPropertyChange(String key, @Nullable String value) {
- GlobalPropertyChangeHandler.PropertyChange change = GlobalPropertyChangeHandler.PropertyChange.create(key, value);
- for (GlobalPropertyChangeHandler changeHandler : changeHandlers) {
+ public void onPropertyChange(String key, @Nullable String value, @Nullable Long componentId, @Nullable Long userId) {
+ String resourceKey = null;
+ if (componentId != null) {
+ ResourceDto resource = resourceDao.getResource(componentId);
+ resourceKey = resource != null ? resource.getKey() : null;
+ }
+ String userLogin = null;
+ if (userId != null) {
+ UserDto user = userDao.getUser(userId);
+ userLogin = user != null ? user.getLogin() : null;
+ }
+ SettingsChangeHandler.SettingsChange change = SettingsChangeHandler.SettingsChange.create(key, value, resourceKey, userLogin);
+ for (SettingsChangeHandler changeHandler : changeHandlers) {
changeHandler.onChange(change);
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.startup;
+
+import org.apache.commons.io.FileUtils;
+import org.sonar.core.persistence.DryRunDatabaseFactory;
+import org.sonar.server.platform.DefaultServerFileSystem;
+import org.sonar.server.platform.PersistentSettings;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @since 4.0
+ */
+public final class CleanDryRunCache {
+
+ private DefaultServerFileSystem serverFileSystem;
+ private PersistentSettings settings;
+
+ public CleanDryRunCache(DefaultServerFileSystem serverFileSystem, PersistentSettings settings) {
+ this.serverFileSystem = serverFileSystem;
+ this.settings = settings;
+ }
+
+ private File getRootCacheLocation() {
+ return new File(serverFileSystem.getTempDir(), "dryRun");
+ }
+
+ public void start() throws IOException {
+ // Delete folder where dryRun DB are stored
+ FileUtils.deleteQuietly(getRootCacheLocation());
+ // Delete all lastUpdate properties to force generation of new DB
+ Map<String, String> properties = settings.getProperties();
+ for (String propKey : properties.keySet()) {
+ if (propKey.startsWith(DryRunDatabaseFactory.SONAR_DRY_RUN_CACHE_KEY_PREFIX)) {
+ settings.deleteProperty(propKey);
+ }
+ }
+ }
+}
import org.sonar.api.test.TestPlan;
import org.sonar.api.test.Testable;
import org.sonar.api.utils.ValidationMessages;
-import org.sonar.api.web.*;
+import org.sonar.api.web.Footer;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.api.web.RubyRailsWebservice;
+import org.sonar.api.web.Widget;
import org.sonar.core.component.SnapshotPerspectives;
import org.sonar.core.i18n.RuleI18nManager;
import org.sonar.core.measure.MeasureFilterEngine;
import org.sonar.core.measure.MeasureFilterResult;
import org.sonar.core.persistence.Database;
-import org.sonar.server.db.DatabaseMigrator;
import org.sonar.core.persistence.DryRunDatabaseFactory;
import org.sonar.core.purge.PurgeDao;
import org.sonar.core.resource.ResourceIndexerDao;
import org.sonar.core.timemachine.Periods;
import org.sonar.server.configuration.Backup;
import org.sonar.server.configuration.ProfilesManager;
-import org.sonar.server.platform.*;
-import org.sonar.server.plugins.*;
+import org.sonar.server.db.DatabaseMigrator;
+import org.sonar.server.platform.Platform;
+import org.sonar.server.platform.ServerIdGenerator;
+import org.sonar.server.platform.ServerSettings;
+import org.sonar.server.platform.SettingsChangeNotifier;
+import org.sonar.server.plugins.DefaultServerPluginRepository;
+import org.sonar.server.plugins.InstalledPluginReferentialFactory;
+import org.sonar.server.plugins.PluginDeployer;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
import org.sonar.server.user.NewUserNotifier;
import org.sonar.updatecenter.common.Version;
import javax.annotation.Nullable;
+
import java.net.InetAddress;
import java.sql.Connection;
-import java.util.*;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import static com.google.common.collect.Lists.newArrayList;
return get(ProfilesManager.class);
}
- public void setGlobalProperty(String key, @Nullable String value) {
- get(ServerSettings.class).setProperty(key, value);
- get(SettingsChangeNotifier.class).onGlobalPropertyChange(key, value);
+ public void updateProperty(String key, @Nullable String value, @Nullable Long componentId, @Nullable Long userId) {
+ if (componentId == null && userId == null) {
+ get(ServerSettings.class).setProperty(key, value);
+ }
+ get(SettingsChangeNotifier.class).onPropertyChange(key, value, componentId, userId);
}
public Settings getSettings() {
private
def self.setGlobalProperty(key, value, resource_id, user_id)
- Api::Utils.java_facade.setGlobalProperty(key, value) unless (resource_id || user_id)
+ Api::Utils.java_facade.updateProperty(key, value, resource_id, user_id)
end
def self.all(key, resource_id=nil, user_id=nil)
import org.junit.Test;
import org.mockito.ArgumentMatcher;
-import org.sonar.api.config.GlobalPropertyChangeHandler;
+import org.sonar.api.config.SettingsChangeHandler;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.user.UserDao;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.argThat;
public class SettingsChangeNotifierTest {
@Test
public void onGlobalPropertyChange() {
- GlobalPropertyChangeHandler handler = mock(GlobalPropertyChangeHandler.class);
- SettingsChangeNotifier notifier = new SettingsChangeNotifier(new GlobalPropertyChangeHandler[]{handler});
+ SettingsChangeHandler handler = mock(SettingsChangeHandler.class);
+ SettingsChangeNotifier notifier = new SettingsChangeNotifier(mock(ResourceDao.class), mock(UserDao.class), new SettingsChangeHandler[] {handler});
- notifier.onGlobalPropertyChange("foo", "bar");
+ notifier.onPropertyChange("foo", "bar", null, null);
- verify(handler).onChange(argThat(new ArgumentMatcher<GlobalPropertyChangeHandler.PropertyChange>() {
+ verify(handler).onChange(argThat(new ArgumentMatcher<SettingsChangeHandler.SettingsChange>() {
@Override
public boolean matches(Object o) {
- GlobalPropertyChangeHandler.PropertyChange change = (GlobalPropertyChangeHandler.PropertyChange) o;
- return change.getKey().equals("foo") && change.getNewValue().equals("bar");
+ SettingsChangeHandler.SettingsChange change = (SettingsChangeHandler.SettingsChange) o;
+ return change.key().equals("foo") && change.newValue().equals("bar") && change.componentKey() == null && change.userLogin() == null;
}
}));
}
@Test
public void no_handlers() {
- SettingsChangeNotifier notifier = new SettingsChangeNotifier();
+ SettingsChangeNotifier notifier = new SettingsChangeNotifier(mock(ResourceDao.class), mock(UserDao.class));
assertThat(notifier.changeHandlers).isEmpty();
// does not fail
- notifier.onGlobalPropertyChange("foo", "bar");
+ notifier.onPropertyChange("foo", "bar", null, null);
}
}