Home | History | Annotate | Download | only in repository
      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