View Javadoc
1   package com.atlassian.plugin.parsers;
2   
3   import com.atlassian.annotations.nonnull.ReturnValuesAreNonnullByDefault;
4   import io.atlassian.util.concurrent.LazyReference;
5   
6   import javax.annotation.ParametersAreNonnullByDefault;
7   import java.util.ArrayList;
8   import java.util.Collections;
9   import java.util.List;
10  import java.util.Optional;
11  import java.util.regex.Matcher;
12  import java.util.regex.Pattern;
13  
14  import static java.util.Arrays.asList;
15  
16  
17  /**
18   * This is used by the application this library is bundled with, it shouldn't be changed without also changing all the products it is bundled with.
19   */
20  @ParametersAreNonnullByDefault
21  @ReturnValuesAreNonnullByDefault
22  public class SafeModeCommandLineArguments {
23      public static final String PLUGIN_LIST_SEPARATOR = ":";
24      private static final String DISABLE_NON_SYSTEM_LINUX = "--disable-all-addons";
25      private static final String DISABLE_NON_SYSTEM_WINDOWS = "/disablealladdons";
26      private static final String DISABLE_LAST_ENABLED_LINUX = "--disable-last-enabled";
27      private static final String DISABLE_LAST_ENABLED_WINDOWS = "/disablelastenabled";
28  
29      //needs to handle case when people put it in quotes
30      //matches --disable-addons="my.cool.plugin"
31      private static final Pattern DISABLE_ADDONS_ARGUMENT_PATTERN = Pattern.compile(".*disable-?addons=([^\\s]+).*");
32  
33      //matches --disable-addons="my cool plugin"
34      private static final Pattern QUOTED_DISABLE_ADDONS_ARGUMENT_PATTERN = Pattern.compile(".*disable-?addons=\"([^\"].+)\".*$");
35  
36      //matches --disable-addons (exists for analytics)
37      private static final Pattern DISABLE_ADDONS_PRESENT_PATTERN = Pattern.compile(".*disable-?addons.*");
38  
39      private final String commandLineArguments;
40      private final LazyReference<Boolean> safeMode = new LazyReference<Boolean>() {
41          @Override
42          protected Boolean create() {
43              return commandLineArguments.contains(getDisableNonSystemWindows()) ||
44                      commandLineArguments.contains(getDisableNonSystemLinux());
45          }
46      };
47  
48      private final LazyReference<Boolean> lastEnabledDisabled = new LazyReference<Boolean>() {
49          @Override
50          protected Boolean create() {
51              return commandLineArguments.contains(getDisableLastEnabledLinux()) ||
52                      commandLineArguments.contains(getDisableLastEnabledWindows());
53          }
54      };
55  
56      /**
57       * The reason we're returning an optional of a list, instead of returning an empty list, is that we want to
58       * distinguish the case where the user supplied no addons to the disable-addons parameter from the case where
59       * they didn't supply the parameter at all
60       *
61       */
62      private final LazyReference<Optional<List<String>>> disabledPlugins = new LazyReference<Optional<List<String>>>() {
63          @Override
64          protected Optional<List<String>> create() {
65  
66              Matcher disableAddonsArgumentMatcher = DISABLE_ADDONS_ARGUMENT_PATTERN.matcher(commandLineArguments);
67              Matcher quotedDisableAddonsArgumentMatcher = QUOTED_DISABLE_ADDONS_ARGUMENT_PATTERN.matcher(commandLineArguments);
68              Matcher disableAddonsPresentMatcher = DISABLE_ADDONS_PRESENT_PATTERN.matcher(commandLineArguments);
69  
70              if (quotedDisableAddonsArgumentMatcher.matches()) {
71                  return Optional.of(Collections.unmodifiableList(asList(quotedDisableAddonsArgumentMatcher.group(1)
72                          .split(getPluginListSeparator()))));
73              } else if (disableAddonsArgumentMatcher.matches()) {
74                  return Optional.of(Collections.unmodifiableList(asList(disableAddonsArgumentMatcher.group(1).split(getPluginListSeparator()))));
75              } else if (disableAddonsPresentMatcher.matches()){
76                 return Optional.of(Collections.emptyList());
77              } else {
78                  return Optional.empty();
79              }
80          }
81      };
82  
83      public SafeModeCommandLineArguments(final String commandLineArguments) {
84          this.commandLineArguments = commandLineArguments;
85      }
86  
87      public static String getDisableLastEnabledLinux() {
88          return DISABLE_LAST_ENABLED_LINUX;
89      }
90  
91      public static String getDisableLastEnabledWindows() {
92          return DISABLE_LAST_ENABLED_WINDOWS;
93      }
94  
95      static String getPluginListSeparator() {
96          return PLUGIN_LIST_SEPARATOR;
97      }
98  
99      static String getDisableNonSystemLinux() {
100         return DISABLE_NON_SYSTEM_LINUX;
101     }
102 
103     static String getDisableNonSystemWindows() {
104         return DISABLE_NON_SYSTEM_WINDOWS;
105     }
106 
107     public String getSafeModeArguments() {
108         return commandLineArguments;
109     }
110 
111     /**
112      * Used for analytics
113      *
114      * @return all plugins that have been specified using the parameter --disable-addons
115      */
116     public Optional<List<String>> getDisabledPlugins() {
117         return disabledPlugins.get();
118     }
119 
120     @SuppressWarnings("ConstantConditions")
121     public boolean isSafeMode() {
122         return safeMode.get();
123     }
124 
125     @SuppressWarnings("ConstantConditions")
126     public boolean shouldLastEnabledBeDisabled() {
127         return lastEnabledDisabled.get();
128     }
129 
130     @SuppressWarnings("ConstantConditions")
131     public boolean isDisabledByParam(String pluginKey) {
132         return getDisabledPlugins().map(plugins -> plugins.contains(pluginKey)).orElse(false);
133     }
134 }