1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.sdkuilib.internal.repository; 18 19 import com.android.prefs.AndroidLocation; 20 import com.android.prefs.AndroidLocation.AndroidLocationException; 21 import com.android.sdklib.ISdkLog; 22 23 import org.eclipse.jface.dialogs.MessageDialog; 24 25 import java.io.File; 26 import java.io.FileInputStream; 27 import java.io.FileNotFoundException; 28 import java.io.FileOutputStream; 29 import java.io.IOException; 30 import java.util.Properties; 31 32 /** 33 * Controller class to get settings values. Settings are kept in-memory. 34 * Users of this class must first load the settings before changing them and save 35 * them when modified. 36 * <p/> 37 * Settings are enumerated by constants in {@link ISettingsPage}. 38 */ 39 public class SettingsController { 40 41 private static final String SETTINGS_FILENAME = "androidtool.cfg"; //$NON-NLS-1$ 42 43 private final Properties mProperties = new Properties(); 44 45 /** The currently associated {@link ISettingsPage}. Can be null. */ 46 private ISettingsPage mSettingsPage; 47 48 private final UpdaterData mUpdaterData; 49 SettingsController(UpdaterData updaterData)50 public SettingsController(UpdaterData updaterData) { 51 mUpdaterData = updaterData; 52 } 53 54 //--- Access to settings ------------ 55 56 /** 57 * Returns the value of the {@link ISettingsPage#KEY_FORCE_HTTP} setting. 58 * 59 * @see ISettingsPage#KEY_FORCE_HTTP 60 */ getForceHttp()61 public boolean getForceHttp() { 62 return Boolean.parseBoolean(mProperties.getProperty(ISettingsPage.KEY_FORCE_HTTP)); 63 } 64 65 /** 66 * Returns the value of the {@link ISettingsPage#KEY_ASK_ADB_RESTART} setting. 67 * 68 * @see ISettingsPage#KEY_ASK_ADB_RESTART 69 */ getAskBeforeAdbRestart()70 public boolean getAskBeforeAdbRestart() { 71 return Boolean.parseBoolean(mProperties.getProperty(ISettingsPage.KEY_ASK_ADB_RESTART)); 72 } 73 74 /** 75 * Returns the value of the {@link ISettingsPage#KEY_SHOW_UPDATE_ONLY} setting. 76 * 77 * @see ISettingsPage#KEY_SHOW_UPDATE_ONLY 78 */ getShowUpdateOnly()79 public boolean getShowUpdateOnly() { 80 String value = mProperties.getProperty(ISettingsPage.KEY_SHOW_UPDATE_ONLY); 81 if (value == null) { 82 return true; 83 } 84 return Boolean.parseBoolean(value); 85 } 86 87 /** 88 * Sets the value of the {@link ISettingsPage#KEY_SHOW_UPDATE_ONLY} setting. 89 * 90 * @param enabled True if only compatible non-obsolete update items should be shown. 91 * @see ISettingsPage#KEY_SHOW_UPDATE_ONLY 92 */ setShowUpdateOnly(boolean enabled)93 public void setShowUpdateOnly(boolean enabled) { 94 setSetting(ISettingsPage.KEY_SHOW_UPDATE_ONLY, enabled); 95 } 96 97 /** 98 * Returns the value of the {@link ISettingsPage#KEY_MONITOR_DENSITY} setting 99 * @see ISettingsPage#KEY_MONITOR_DENSITY 100 */ getMonitorDensity()101 public int getMonitorDensity() { 102 String value = mProperties.getProperty(ISettingsPage.KEY_MONITOR_DENSITY, null); 103 if (value == null) { 104 return -1; 105 } 106 107 try { 108 return Integer.parseInt(value); 109 } catch (NumberFormatException e) { 110 return -1; 111 } 112 } 113 114 /** 115 * Sets the value of the {@link ISettingsPage#KEY_MONITOR_DENSITY} setting. 116 * 117 * @param density the density of the monitor 118 * @see ISettingsPage#KEY_MONITOR_DENSITY 119 */ setMonitorDensity(int density)120 public void setMonitorDensity(int density) { 121 mProperties.setProperty(ISettingsPage.KEY_MONITOR_DENSITY, Integer.toString(density)); 122 } 123 124 /** 125 * Internal helper to set a boolean setting. 126 */ setSetting(String key, boolean value)127 void setSetting(String key, boolean value) { 128 mProperties.setProperty(key, Boolean.toString(value)); 129 } 130 131 //--- Controller methods ------------- 132 133 /** 134 * Associate the given {@link ISettingsPage} with this {@link SettingsController}. 135 * <p/> 136 * This loads the current properties into the setting page UI. 137 * It then associates the SettingsChanged callback with this controller. 138 * <p/> 139 * If the setting page given is null, it will be unlinked from controller. 140 * 141 * @param settingsPage An {@link ISettingsPage} to associate with the controller. 142 */ setSettingsPage(ISettingsPage settingsPage)143 public void setSettingsPage(ISettingsPage settingsPage) { 144 mSettingsPage = settingsPage; 145 146 if (settingsPage != null) { 147 settingsPage.loadSettings(mProperties); 148 149 settingsPage.setOnSettingsChanged(new ISettingsPage.SettingsChangedCallback() { 150 @Override 151 public void onSettingsChanged(ISettingsPage page) { 152 SettingsController.this.onSettingsChanged(); 153 } 154 }); 155 } 156 } 157 158 /** 159 * Load settings from the settings file. 160 */ loadSettings()161 public void loadSettings() { 162 FileInputStream fis = null; 163 String path = null; 164 try { 165 String folder = AndroidLocation.getFolder(); 166 File f = new File(folder, SETTINGS_FILENAME); 167 path = f.getPath(); 168 if (f.exists()) { 169 fis = new FileInputStream(f); 170 171 mProperties.load(fis); 172 173 // Properly reformat some settings to enforce their default value when missing. 174 setShowUpdateOnly(getShowUpdateOnly()); 175 setSetting(ISettingsPage.KEY_ASK_ADB_RESTART, getAskBeforeAdbRestart()); 176 } 177 178 } catch (Exception e) { 179 ISdkLog log = mUpdaterData.getSdkLog(); 180 if (log != null) { 181 log.error(e, "Failed to load settings from .android folder. Path is '%1$s'.", path); 182 } 183 } finally { 184 if (fis != null) { 185 try { 186 fis.close(); 187 } catch (IOException e) { 188 } 189 } 190 } 191 } 192 193 /** 194 * Saves settings to the settings file. 195 */ saveSettings()196 public void saveSettings() { 197 198 FileOutputStream fos = null; 199 String path = null; 200 try { 201 String folder = AndroidLocation.getFolder(); 202 File f = new File(folder, SETTINGS_FILENAME); 203 path = f.getPath(); 204 205 fos = new FileOutputStream(f); 206 207 mProperties.store( fos, "## Settings for Android Tool"); //$NON-NLS-1$ 208 209 } catch (Exception e) { 210 ISdkLog log = mUpdaterData.getSdkLog(); 211 212 if (log != null) { 213 log.error(e, "Failed to save settings at '%1$s'", path); 214 } 215 216 // This is important enough that we want to really nag the user about it 217 String reason = null; 218 219 if (e instanceof FileNotFoundException) { 220 reason = "File not found"; 221 } else if (e instanceof AndroidLocationException) { 222 reason = ".android folder not found, please define ANDROID_SDK_HOME"; 223 } else if (e.getMessage() != null) { 224 reason = String.format("%1$s: %2$s", e.getClass().getSimpleName(), e.getMessage()); 225 } else { 226 reason = e.getClass().getName(); 227 } 228 229 MessageDialog.openInformation(mUpdaterData.getWindowShell(), 230 "SDK Manager Settings", 231 String.format( 232 "The Android SDK and AVD Manager failed to save its settings (%1$s) at %2$s", 233 reason, path)); 234 235 } finally { 236 if (fos != null) { 237 try { 238 fos.close(); 239 } catch (IOException e) { 240 } 241 } 242 } 243 } 244 245 /** 246 * When settings have changed: retrieve the new settings, apply them and save them. 247 * 248 * This updates Java system properties for the HTTP proxy. 249 */ onSettingsChanged()250 private void onSettingsChanged() { 251 if (mSettingsPage == null) { 252 return; 253 } 254 255 String oldHttpsSetting = mProperties.getProperty(ISettingsPage.KEY_FORCE_HTTP, 256 Boolean.FALSE.toString()); 257 258 mSettingsPage.retrieveSettings(mProperties); 259 applySettings(); 260 saveSettings(); 261 262 String newHttpsSetting = mProperties.getProperty(ISettingsPage.KEY_FORCE_HTTP, 263 Boolean.FALSE.toString()); 264 if (!newHttpsSetting.equals(oldHttpsSetting)) { 265 // In case the HTTP/HTTPS setting changes, force sources to be reloaded 266 // (this only refreshes sources that the user has already tried to open.) 267 mUpdaterData.refreshSources(false /*forceFetching*/); 268 } 269 } 270 271 /** 272 * Applies the current settings. 273 */ applySettings()274 public void applySettings() { 275 Properties props = System.getProperties(); 276 277 // Get the configured HTTP proxy settings 278 String proxyHost = mProperties.getProperty(ISettingsPage.KEY_HTTP_PROXY_HOST, 279 ""); //$NON-NLS-1$ 280 String proxyPort = mProperties.getProperty(ISettingsPage.KEY_HTTP_PROXY_PORT, 281 ""); //$NON-NLS-1$ 282 283 // Set both the HTTP and HTTPS proxy system properties. 284 // The system property constants can be found in the Java SE documentation at 285 // http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html 286 final String JAVA_PROP_HTTP_PROXY_HOST = "http.proxyHost"; //$NON-NLS-1$ 287 final String JAVA_PROP_HTTP_PROXY_PORT = "http.proxyPort"; //$NON-NLS-1$ 288 final String JAVA_PROP_HTTPS_PROXY_HOST = "https.proxyHost"; //$NON-NLS-1$ 289 final String JAVA_PROP_HTTPS_PROXY_PORT = "https.proxyPort"; //$NON-NLS-1$ 290 291 props.setProperty(JAVA_PROP_HTTP_PROXY_HOST, proxyHost); 292 props.setProperty(JAVA_PROP_HTTP_PROXY_PORT, proxyPort); 293 props.setProperty(JAVA_PROP_HTTPS_PROXY_HOST, proxyHost); 294 props.setProperty(JAVA_PROP_HTTPS_PROXY_PORT, proxyPort); 295 } 296 297 } 298