1 package com.atlassian.plugin.manager;
2
3 import com.atlassian.annotations.nonnull.ReturnValuesAreNonnullByDefault;
4 import com.atlassian.plugin.ModuleDescriptor;
5 import com.atlassian.plugin.Plugin;
6 import com.atlassian.plugin.metadata.PluginMetadataManager;
7 import com.atlassian.plugin.parsers.SafeModeCommandLineArguments;
8 import com.atlassian.plugin.parsers.SafeModeCommandLineArgumentsFactory;
9 import com.google.common.base.Supplier;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 import javax.annotation.ParametersAreNonnullByDefault;
14 import java.util.Comparator;
15 import java.util.Map;
16 import java.util.Optional;
17
18 import static com.atlassian.plugin.manager.ApplicationDefinedPluginsProvider.NO_APPLICATION_PLUGINS;
19 import static com.atlassian.plugin.manager.PluginEnabledState.UNKNOWN_ENABLED_TIME;
20 import static com.google.common.base.Suppliers.memoize;
21 import static java.util.Collections.emptyList;
22
23
24
25
26
27
28 @ParametersAreNonnullByDefault
29 @ReturnValuesAreNonnullByDefault
30 public class DefaultSafeModeManager implements SafeModeManager {
31 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSafeModeManager.class);
32 private final SafeModeCommandLineArguments commandLineArguments;
33 private final PluginMetadataManager pluginMetadataManager;
34 private final ApplicationDefinedPluginsProvider appRelatedPluginsProvider;
35 private final ClusterEnvironmentProvider clusterEnvironmentProvider;
36 private final Supplier<Optional<String>> lastEnabledPluginKey = memoize(new Supplier<Optional<String>>() {
37 @Override
38 public Optional<String> get() {
39 PluginPersistentState state = pluginPersistentStateStore.load();
40 if(state.getStatesMap().isEmpty()){
41 return Optional.empty();
42 }
43 Optional<Map.Entry<String, PluginEnabledState>> mostRecentlyEnabled =
44 state
45 .getStatesMap()
46 .entrySet()
47 .stream()
48 .max(Comparator.comparingLong(entry -> entry.getValue().getTimestamp()));
49 if(mostRecentlyEnabled.isPresent() &&
50 mostRecentlyEnabled.get().getValue().getTimestamp() == UNKNOWN_ENABLED_TIME){
51 return Optional.empty();
52 }
53 return(mostRecentlyEnabled.map(Map.Entry::getKey));
54 }
55
56 });
57
58 private final boolean isInSafeMode;
59
60 private final PluginPersistentStateStore pluginPersistentStateStore;
61
62 public DefaultSafeModeManager(PluginMetadataManager pluginMetadataManager,
63 ClusterEnvironmentProvider clusterEnvironmentProvider,
64 SafeModeCommandLineArgumentsFactory safeModeCommandLineArgumentsFactory,
65 PluginPersistentStateStore pluginPersistentStateStore) {
66 this(pluginMetadataManager,
67 NO_APPLICATION_PLUGINS, clusterEnvironmentProvider, safeModeCommandLineArgumentsFactory, pluginPersistentStateStore);
68 }
69
70 DefaultSafeModeManager(final PluginMetadataManager pluginMetadataManager,
71 final ApplicationDefinedPluginsProvider appRelatedPluginsProvider,
72 final ClusterEnvironmentProvider clusterEnvironmentProvider,
73 final SafeModeCommandLineArgumentsFactory safeModeCommandLineArgumentsFactory,
74 final PluginPersistentStateStore pluginPersistentStateStore) {
75 this.pluginMetadataManager = pluginMetadataManager;
76 this.commandLineArguments = safeModeCommandLineArgumentsFactory.get();
77 this.appRelatedPluginsProvider = appRelatedPluginsProvider;
78 this.clusterEnvironmentProvider = clusterEnvironmentProvider;
79 this.pluginPersistentStateStore = pluginPersistentStateStore;
80 this.isInSafeMode = !clusterEnvironmentProvider.isInCluster() && (commandLineArguments.isSafeMode());
81 if (clusterEnvironmentProvider.isInCluster() && (commandLineArguments.isSafeMode() ||
82 !commandLineArguments.getDisabledPlugins().orElse(emptyList()).isEmpty())) {
83 LOGGER.warn("Add-ons disable options from '{}' are being ignored due to start up in clustered mode!",
84 commandLineArguments.getSafeModeArguments());
85 }
86 }
87
88 @Override
89 public boolean pluginShouldBeStarted(final Plugin plugin, final Iterable<ModuleDescriptor> descriptors) {
90 return clusterEnvironmentProvider.isInCluster() ||
91 (!isPluginDisabledByDisableLastEnabled(plugin)
92 && !isPluginDisabledBySafeMode(plugin, descriptors)
93 && !commandLineArguments.isDisabledByParam(plugin.getKey()));
94 }
95
96 @Override
97 public boolean isInSafeMode() {
98 return isInSafeMode;
99 }
100
101 private boolean isPluginDisabledByDisableLastEnabled(Plugin plugin){
102 return (commandLineArguments.shouldLastEnabledBeDisabled()
103 && plugin.getKey().equals(lastEnabledPluginKey.get().orElse(null)));
104
105 }
106
107 private boolean isPluginDisabledBySafeMode(Plugin plugin, Iterable<ModuleDescriptor> descriptors){
108 return (commandLineArguments.isSafeMode() && !isSystemPlugin(plugin, descriptors));
109 }
110
111
112
113
114
115
116
117
118 @SuppressWarnings("unchecked")
119 private boolean isSystemPlugin(final Plugin plugin, Iterable<ModuleDescriptor> descriptors) {
120 return pluginMetadataManager.isSystemProvided(plugin) ||
121 !pluginMetadataManager.isOptional(plugin) ||
122 appRelatedPluginsProvider.getPluginKeys(descriptors).contains(plugin.getKey());
123 }
124 }