1/*
2 * Copyright (C) 2010 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.services.telephony.sip;
18
19import com.android.internal.os.AtomicFile;
20
21import android.content.Context;
22import android.net.sip.SipProfile;
23import android.util.Log;
24
25import java.io.File;
26import java.io.FileInputStream;
27import java.io.FileOutputStream;
28import java.io.IOException;
29import java.io.ObjectInputStream;
30import java.io.ObjectOutputStream;
31import java.util.ArrayList;
32import java.util.Collections;
33import java.util.List;
34
35/**
36 * Utility class that helps perform operations on the SipProfile database.
37 */
38class SipProfileDb {
39    private static final String PREFIX = "[SipProfileDb] ";
40    private static final boolean VERBOSE = false; /* STOP SHIP if true */
41
42    private static final String PROFILES_DIR = "/profiles/";
43    private static final String PROFILE_OBJ_FILE = ".pobj";
44
45    private String mProfilesDirectory;
46    private SipSharedPreferences mSipSharedPreferences;
47    private int mProfilesCount = -1;
48
49    public SipProfileDb(Context context) {
50        mProfilesDirectory = context.getFilesDir().getAbsolutePath() + PROFILES_DIR;
51        mSipSharedPreferences = new SipSharedPreferences(context);
52    }
53
54    public void deleteProfile(SipProfile p) {
55        synchronized(SipProfileDb.class) {
56            deleteProfile(new File(mProfilesDirectory + p.getProfileName()));
57            if (mProfilesCount < 0) retrieveSipProfileListInternal();
58            mSipSharedPreferences.setProfilesCount(--mProfilesCount);
59        }
60    }
61
62    private void deleteProfile(File file) {
63        if (file.isDirectory()) {
64            for (File child : file.listFiles()) deleteProfile(child);
65        }
66        file.delete();
67    }
68
69    public void saveProfile(SipProfile p) throws IOException {
70        synchronized(SipProfileDb.class) {
71            if (mProfilesCount < 0) retrieveSipProfileListInternal();
72            File f = new File(mProfilesDirectory + p.getProfileName());
73            if (!f.exists()) f.mkdirs();
74            AtomicFile atomicFile = new AtomicFile(new File(f, PROFILE_OBJ_FILE));
75            FileOutputStream fos = null;
76            ObjectOutputStream oos = null;
77            try {
78                fos = atomicFile.startWrite();
79                oos = new ObjectOutputStream(fos);
80                oos.writeObject(p);
81                oos.flush();
82                mSipSharedPreferences.setProfilesCount(++mProfilesCount);
83                atomicFile.finishWrite(fos);
84            } catch (IOException e) {
85                atomicFile.failWrite(fos);
86                throw e;
87            } finally {
88                if (oos != null) oos.close();
89            }
90        }
91    }
92
93    public int getProfilesCount() {
94        return (mProfilesCount < 0) ?  mSipSharedPreferences.getProfilesCount() : mProfilesCount;
95    }
96
97    public List<SipProfile> retrieveSipProfileList() {
98        synchronized(SipProfileDb.class) {
99            return retrieveSipProfileListInternal();
100        }
101    }
102
103    private List<SipProfile> retrieveSipProfileListInternal() {
104        List<SipProfile> sipProfileList = Collections.synchronizedList(
105                new ArrayList<SipProfile>());
106
107        File root = new File(mProfilesDirectory);
108        String[] dirs = root.list();
109        if (dirs == null) return sipProfileList;
110        for (String dir : dirs) {
111            File f = new File(new File(root, dir), PROFILE_OBJ_FILE);
112            if (!f.exists()) continue;
113            try {
114                SipProfile p = deserialize(f);
115                if (p == null) continue;
116                if (!dir.equals(p.getProfileName())) continue;
117
118                sipProfileList.add(p);
119            } catch (IOException e) {
120                log("retrieveSipProfileListInternal, exception: " + e);
121            }
122        }
123        mProfilesCount = sipProfileList.size();
124        mSipSharedPreferences.setProfilesCount(mProfilesCount);
125        return sipProfileList;
126    }
127
128    private SipProfile deserialize(File profileObjectFile) throws IOException {
129        AtomicFile atomicFile = new AtomicFile(profileObjectFile);
130        ObjectInputStream ois = null;
131        try {
132            ois = new ObjectInputStream(atomicFile.openRead());
133            SipProfile p = (SipProfile) ois.readObject();
134            return p;
135        } catch (ClassNotFoundException e) {
136            log("deserialize, exception: " + e);
137        } finally {
138            if (ois!= null) ois.close();
139        }
140        return null;
141    }
142
143    private static void log(String msg) {
144        Log.d(SipUtil.LOG_TAG, PREFIX + msg);
145    }
146}
147