1/*
2 * Copyright (C) 2008 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
17package com.android.prefs;
18
19import com.android.annotations.NonNull;
20
21import java.io.File;
22
23/**
24 * Manages the location of the android files (including emulator files, ddms config, debug keystore)
25 */
26public final class AndroidLocation {
27    /**
28     * Virtual Device folder inside the path returned by {@link #getFolder()}
29     */
30    public static final String FOLDER_AVD = "avd";
31
32    /**
33     * Throw when the location of the android folder couldn't be found.
34     */
35    public static final class AndroidLocationException extends Exception {
36        private static final long serialVersionUID = 1L;
37
38        public AndroidLocationException(String string) {
39            super(string);
40        }
41    }
42
43    private static String sPrefsLocation = null;
44
45    /**
46     * Returns the folder used to store android related files.
47     * @return an OS specific path, terminated by a separator.
48     * @throws AndroidLocationException
49     */
50    @NonNull public final static String getFolder() throws AndroidLocationException {
51        if (sPrefsLocation == null) {
52            String home = findValidPath("ANDROID_SDK_HOME", "user.home", "HOME");
53
54            // if the above failed, we throw an exception.
55            if (home == null) {
56                throw new AndroidLocationException(
57                        "Unable to get the Android SDK home directory.\n" +
58                        "Make sure the environment variable ANDROID_SDK_HOME is set up.");
59            } else {
60                sPrefsLocation = home + File.separator + ".android" + File.separator;
61            }
62        }
63
64        // make sure the folder exists!
65        File f = new File(sPrefsLocation);
66        if (f.exists() == false) {
67            try {
68                f.mkdir();
69            } catch (SecurityException e) {
70                AndroidLocationException e2 = new AndroidLocationException(String.format(
71                        "Unable to create folder '%1$s'. " +
72                        "This is the path of preference folder expected by the Android tools.",
73                        sPrefsLocation));
74                e2.initCause(e);
75                throw e2;
76            }
77        } else if (f.isFile()) {
78            throw new AndroidLocationException(sPrefsLocation +
79                    " is not a directory! " +
80                    "This is the path of preference folder expected by the Android tools.");
81        }
82
83        return sPrefsLocation;
84    }
85
86    /**
87     * Resets the folder used to store android related files. For testing.
88     */
89    public final static void resetFolder() {
90        sPrefsLocation = null;
91    }
92
93    /**
94     * Checks a list of system properties and/or system environment variables for validity, and
95     * existing director, and returns the first one.
96     * @param names
97     * @return the content of the first property/variable.
98     */
99    private static String findValidPath(String... names) {
100        for (String name : names) {
101            String path;
102            if (name.indexOf('.') != -1) {
103                path = System.getProperty(name);
104            } else {
105                path = System.getenv(name);
106            }
107
108            if (path != null) {
109                File f = new File(path);
110                if (f.isDirectory()) {
111                    return path;
112                }
113            }
114        }
115
116        return null;
117    }
118}
119