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 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 */ 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 */ 70 public boolean getAskBeforeAdbRestart() { 71 String value = mProperties.getProperty(ISettingsPage.KEY_ASK_ADB_RESTART); 72 if (value == null) { 73 return true; 74 } 75 return Boolean.parseBoolean(value); 76 } 77 78 /** 79 * Returns the value of the {@link ISettingsPage#KEY_SHOW_UPDATE_ONLY} setting. 80 * 81 * @see ISettingsPage#KEY_SHOW_UPDATE_ONLY 82 */ 83 public boolean getShowUpdateOnly() { 84 String value = mProperties.getProperty(ISettingsPage.KEY_SHOW_UPDATE_ONLY); 85 if (value == null) { 86 return true; 87 } 88 return Boolean.parseBoolean(value); 89 } 90 91 /** 92 * Sets the value of the {@link ISettingsPage#KEY_SHOW_UPDATE_ONLY} setting. 93 * 94 * @param enabled True if only compatible non-obsolete update items should be shown. 95 * @see ISettingsPage#KEY_SHOW_UPDATE_ONLY 96 */ 97 public void setShowUpdateOnly(boolean enabled) { 98 setSetting(ISettingsPage.KEY_SHOW_UPDATE_ONLY, enabled); 99 } 100 101 /** 102 * Returns the value of the {@link ISettingsPage#KEY_MONITOR_DENSITY} setting 103 * @see ISettingsPage#KEY_MONITOR_DENSITY 104 */ 105 public int getMonitorDensity() { 106 String value = mProperties.getProperty(ISettingsPage.KEY_MONITOR_DENSITY, null); 107 if (value == null) { 108 return -1; 109 } 110 111 try { 112 return Integer.parseInt(value); 113 } catch (NumberFormatException e) { 114 return -1; 115 } 116 } 117 118 /** 119 * Sets the value of the {@link ISettingsPage#KEY_MONITOR_DENSITY} setting. 120 * 121 * @param density the density of the monitor 122 * @see ISettingsPage#KEY_MONITOR_DENSITY 123 */ 124 public void setMonitorDensity(int density) { 125 mProperties.setProperty(ISettingsPage.KEY_MONITOR_DENSITY, Integer.toString(density)); 126 } 127 128 /** 129 * Internal helper to set a boolean setting. 130 */ 131 void setSetting(String key, boolean value) { 132 mProperties.setProperty(key, Boolean.toString(value)); 133 } 134 135 //--- Controller methods ------------- 136 137 /** 138 * Associate the given {@link ISettingsPage} with this {@link SettingsController}. 139 * <p/> 140 * This loads the current properties into the setting page UI. 141 * It then associates the SettingsChanged callback with this controller. 142 * <p/> 143 * If the setting page given is null, it will be unlinked from controller. 144 * 145 * @param settingsPage An {@link ISettingsPage} to associate with the controller. 146 */ 147 public void setSettingsPage(ISettingsPage settingsPage) { 148 mSettingsPage = settingsPage; 149 150 if (settingsPage != null) { 151 settingsPage.loadSettings(mProperties); 152 153 settingsPage.setOnSettingsChanged(new ISettingsPage.SettingsChangedCallback() { 154 public void onSettingsChanged(ISettingsPage page) { 155 SettingsController.this.onSettingsChanged(); 156 } 157 }); 158 } 159 } 160 161 /** 162 * Load settings from the settings file. 163 */ 164 public void loadSettings() { 165 FileInputStream fis = null; 166 String path = null; 167 try { 168 String folder = AndroidLocation.getFolder(); 169 File f = new File(folder, SETTINGS_FILENAME); 170 path = f.getPath(); 171 if (f.exists()) { 172 fis = new FileInputStream(f); 173 174 mProperties.load(fis); 175 176 // Properly reformat some settings to enforce their default value when missing. 177 setShowUpdateOnly(getShowUpdateOnly()); 178 setSetting(ISettingsPage.KEY_ASK_ADB_RESTART, getAskBeforeAdbRestart()); 179 } 180 181 } catch (Exception e) { 182 ISdkLog log = mUpdaterData.getSdkLog(); 183 if (log != null) { 184 log.error(e, "Failed to load settings from .android folder. Path is '%1$s'.", path); 185 } 186 } finally { 187 if (fis != null) { 188 try { 189 fis.close(); 190 } catch (IOException e) { 191 } 192 } 193 } 194 } 195 196 /** 197 * Saves settings to the settings file. 198 */ 199 public void saveSettings() { 200 201 FileOutputStream fos = null; 202 String path = null; 203 try { 204 String folder = AndroidLocation.getFolder(); 205 File f = new File(folder, SETTINGS_FILENAME); 206 path = f.getPath(); 207 208 fos = new FileOutputStream(f); 209 210 mProperties.store( fos, "## Settings for Android Tool"); //$NON-NLS-1$ 211 212 } catch (Exception e) { 213 ISdkLog log = mUpdaterData.getSdkLog(); 214 215 if (log != null) { 216 log.error(e, "Failed to save settings at '%1$s'", path); 217 } 218 219 // This is important enough that we want to really nag the user about it 220 String reason = null; 221 222 if (e instanceof FileNotFoundException) { 223 reason = "File not found"; 224 } else if (e instanceof AndroidLocationException) { 225 reason = ".android folder not found, please define ANDROID_SDK_HOME"; 226 } else if (e.getMessage() != null) { 227 reason = String.format("%1$s: %2$s", e.getClass().getSimpleName(), e.getMessage()); 228 } else { 229 reason = e.getClass().getName(); 230 } 231 232 MessageDialog.openInformation(mUpdaterData.getWindowShell(), 233 "SDK Manager Settings", 234 String.format( 235 "The Android SDK and AVD Manager failed to save its settings (%1$s) at %2$s", 236 reason, path)); 237 238 } finally { 239 if (fos != null) { 240 try { 241 fos.close(); 242 } catch (IOException e) { 243 } 244 } 245 } 246 } 247 248 /** 249 * When settings have changed: retrieve the new settings, apply them and save them. 250 * 251 * This updates Java system properties for the HTTP proxy. 252 */ 253 private void onSettingsChanged() { 254 if (mSettingsPage == null) { 255 return; 256 } 257 258 String oldHttpsSetting = mProperties.getProperty(ISettingsPage.KEY_FORCE_HTTP, 259 Boolean.FALSE.toString()); 260 261 mSettingsPage.retrieveSettings(mProperties); 262 applySettings(); 263 saveSettings(); 264 265 String newHttpsSetting = mProperties.getProperty(ISettingsPage.KEY_FORCE_HTTP, 266 Boolean.FALSE.toString()); 267 if (!newHttpsSetting.equals(oldHttpsSetting)) { 268 // In case the HTTP/HTTPS setting changes, force sources to be reloaded 269 // (this only refreshes sources that the user has already tried to open.) 270 mUpdaterData.refreshSources(false /*forceFetching*/); 271 } 272 } 273 274 /** 275 * Applies the current settings. 276 */ 277 public void applySettings() { 278 Properties props = System.getProperties(); 279 280 // Get the configured HTTP proxy settings 281 String proxyHost = mProperties.getProperty(ISettingsPage.KEY_HTTP_PROXY_HOST, 282 ""); //$NON-NLS-1$ 283 String proxyPort = mProperties.getProperty(ISettingsPage.KEY_HTTP_PROXY_PORT, 284 ""); //$NON-NLS-1$ 285 286 // Set both the HTTP and HTTPS proxy system properties. 287 // The system property constants can be found in the Java SE documentation at 288 // http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html 289 final String JAVA_PROP_HTTP_PROXY_HOST = "http.proxyHost"; //$NON-NLS-1$ 290 final String JAVA_PROP_HTTP_PROXY_PORT = "http.proxyPort"; //$NON-NLS-1$ 291 final String JAVA_PROP_HTTPS_PROXY_HOST = "https.proxyHost"; //$NON-NLS-1$ 292 final String JAVA_PROP_HTTPS_PROXY_PORT = "https.proxyPort"; //$NON-NLS-1$ 293 294 props.setProperty(JAVA_PROP_HTTP_PROXY_HOST, proxyHost); 295 props.setProperty(JAVA_PROP_HTTP_PROXY_PORT, proxyPort); 296 props.setProperty(JAVA_PROP_HTTPS_PROXY_HOST, proxyHost); 297 props.setProperty(JAVA_PROP_HTTPS_PROXY_PORT, proxyPort); 298 } 299 300 } 301