Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / ListAccountsActivity.java @ 96a8e632

History | View | Annotate | Download (16.3 kB)

1
package com.rackspacecloud.android;
2

    
3
import java.io.FileInputStream;
4
import java.io.FileNotFoundException;
5
import java.io.FileOutputStream;
6
import java.io.IOException;
7
import java.io.ObjectInputStream;
8
import java.io.ObjectOutputStream;
9
import java.io.StreamCorruptedException;
10
import java.util.ArrayList;
11
import java.util.TreeMap;
12

    
13
import com.rackspace.cloud.loadbalancer.api.client.Algorithm;
14
import com.rackspace.cloud.loadbalancer.api.client.AlgorithmManager;
15
import com.rackspace.cloud.loadbalancer.api.client.Protocol;
16
import com.rackspace.cloud.loadbalancer.api.client.ProtocolManager;
17
import com.rackspace.cloud.servers.api.client.Account;
18
import com.rackspace.cloud.servers.api.client.Flavor;
19
import com.rackspace.cloud.servers.api.client.FlavorManager;
20
import com.rackspace.cloud.servers.api.client.Image;
21
import com.rackspace.cloud.servers.api.client.ImageManager;
22
import com.rackspace.cloud.servers.api.client.http.Authentication;
23

    
24
import android.app.AlertDialog;
25
import android.app.Dialog;
26
import android.app.ListActivity;
27
import android.app.ProgressDialog;
28
import android.content.Context;
29
import android.content.DialogInterface;
30
import android.content.Intent;
31
import android.os.AsyncTask;
32
import android.os.Bundle;
33
import android.util.Log;
34
import android.view.ContextMenu;
35
import android.view.ContextMenu.ContextMenuInfo;
36
import android.view.LayoutInflater;
37
import android.view.Menu;
38
import android.view.MenuInflater;
39
import android.view.MenuItem;
40
import android.view.View;
41
import android.view.View.OnClickListener;
42
import android.view.ViewGroup;
43
import android.widget.AdapterView.AdapterContextMenuInfo;
44
import android.widget.ArrayAdapter;
45
import android.widget.Button;
46
import android.widget.EditText;
47
import android.widget.ImageView;
48
import android.widget.ListView;
49
import android.widget.TextView;
50
import android.widget.Toast;
51

    
52
public class ListAccountsActivity extends ListActivity{
53

    
54
        private final int PASSWORD_PROMPT = 123;
55
        private final String FILENAME = "accounts.data";
56
        
57
        private boolean authenticating;
58
        private ArrayList<Account> accounts;
59
        private Intent tabViewIntent;
60
        private ProgressDialog dialog;
61
        private Context context;
62
        
63
        //need to store if the user has successfully logged in
64
        private boolean loggedIn;
65

    
66

    
67
        public void onCreate(Bundle savedInstanceState) {
68
        super.onCreate(savedInstanceState);
69
        onRestoreInstanceState(savedInstanceState);
70
        registerForContextMenu(getListView());
71
        context = getApplicationContext();
72
        tabViewIntent = new Intent(this, ActivityChooser.class);
73
        verifyPassword();
74
    }
75

    
76
        @Override
77
        protected void onSaveInstanceState(Bundle outState) {
78
                super.onSaveInstanceState(outState);
79
                outState.putBoolean("authenticating", authenticating);
80
                outState.putBoolean("loggedIn", loggedIn);
81
                
82
                //need to set authenticating back to true because it is set to false
83
                //in hideDialog()
84
                if(authenticating){
85
                        hideDialog();
86
                        authenticating = true;
87
                }
88
                writeAccounts();
89
        }
90
        
91
        @Override
92
        protected void onRestoreInstanceState(Bundle state) {
93
                if (state != null && state.containsKey("loggedIn")){
94
                        loggedIn = state.getBoolean("loggedIn");
95
                }
96
                else{
97
                        loggedIn = false;
98
                }
99
                if (state != null && state.containsKey("authenticating") && state.getBoolean("authenticating")) {
100
                    showDialog();
101
            } else {
102
                    hideDialog();
103
            }
104
                if (state != null && state.containsKey("accounts")) {
105
                    accounts = readAccounts();
106
                    if (accounts.size() == 0) {
107
                            displayNoAccountsCell();
108
                    } else {
109
                            getListView().setDividerHeight(1); // restore divider lines 
110
                            setListAdapter(new AccountAdapter());
111
                    }
112
            } else {
113
            loadAccounts();        
114
            }         
115
    }
116

    
117
        @Override
118
        protected void onStart(){
119
                super.onStart();
120
                if(authenticating){
121
                        showDialog();
122
                }
123
        }
124
        
125
        @Override
126
        protected void onStop(){
127
                super.onStop();
128
                if(authenticating){
129
                        hideDialog();
130
                        authenticating = true;
131
                }
132
        }
133
        
134

    
135
        /*
136
         * if the application is password protected,
137
         * the user must provide the password before
138
         * gaining access
139
         */
140
        private void verifyPassword(){
141
                PasswordManager pwManager = new PasswordManager(getSharedPreferences(
142
                                Preferences.SHARED_PREFERENCES_NAME, MODE_PRIVATE));
143
                if(pwManager.hasPassword() && !loggedIn){
144
                        createCustomDialog(PASSWORD_PROMPT);
145
                }
146
        }
147
        
148
        private boolean rightPassword(String password){
149
                PasswordManager pwManager = new PasswordManager(getSharedPreferences(
150
                                Preferences.SHARED_PREFERENCES_NAME, MODE_PRIVATE));
151
                return pwManager.verifyEnteredPassword(password);
152
        }
153
        
154
        
155
        /*
156
         * forces the user to enter a correct password
157
         * before they gain access to application data
158
         */
159
        private void createCustomDialog(int id) {
160
                final Dialog dialog = new Dialog(ListAccountsActivity.this);
161
                switch (id) {
162
                case PASSWORD_PROMPT:
163
                        dialog.setContentView(R.layout.passworddialog);
164
                        dialog.setTitle("Enter your password:");
165
                        dialog.setCancelable(false);
166
                        Button button = (Button) dialog.findViewById(R.id.submit_password);
167
                        button.setOnClickListener(new OnClickListener() {
168
                                public void onClick(View v){
169
                                        EditText passwordText = ((EditText)dialog.findViewById(R.id.submit_password_text));
170
                                        if(!rightPassword(passwordText.getText().toString())){
171
                                                passwordText.setText("");
172
                                                showToast("Password was incorrect.");
173
                                                loggedIn = false;
174
                                        }
175
                                        else{
176
                                                dialog.dismiss();
177
                                                loggedIn = true;
178
                                        }
179
                                }
180
                                
181
                        });
182
                        dialog.show();
183
                }
184
        }
185
        
186
        private void loadAccounts() {
187
                //check and see if there are any in memory
188
                if(accounts == null){
189
                        accounts = readAccounts();
190
                }
191
                //if nothing was written before accounts will still be null
192
                if(accounts == null){
193
                        accounts = new ArrayList<Account>();
194
                }
195

    
196
                setAccountList();
197
        }
198

    
199
        private void setAccountList() {
200
        
201
                if (accounts.size() == 0) {
202
                        displayNoAccountsCell();
203
                } else {
204
                        getListView().setDividerHeight(1); // restore divider lines 
205
                        this.setListAdapter(new AccountAdapter());
206
                }
207
        }
208

    
209
        private void writeAccounts(){
210
                FileOutputStream fos;
211
                ObjectOutputStream out = null;
212
                try{
213
                        fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
214
                        out = new ObjectOutputStream(fos);
215
                        out.writeObject(accounts);
216
                        out.flush();
217
                        out.close();
218
                } catch (FileNotFoundException e) {
219
                        showAlert("Error", "Could not save accounts.");
220
                        e.printStackTrace();
221
                } catch (IOException e) {
222
                        showAlert("Error", "Could not save accounts.");
223
                        e.printStackTrace();
224
                }
225
        }
226

    
227
        private ArrayList<Account> readAccounts(){
228
                FileInputStream fis;
229
                ObjectInputStream in;
230
                try {
231
                        fis = openFileInput(FILENAME);
232
                        in = new ObjectInputStream(fis);
233
                        @SuppressWarnings("unchecked")
234
                        ArrayList<Account> file = (ArrayList<Account>)in.readObject();
235
                        in.close();
236
                        return file;
237
                } catch (FileNotFoundException e) {
238
                        //showAlert("Error", "Could not load accounts.");
239
                        e.printStackTrace();
240
                        return null;
241
                } catch (StreamCorruptedException e) {
242
                        showAlert("Error", "Could not load accounts.");
243
                        e.printStackTrace();
244
                } catch (IOException e) {
245
                        showAlert("Error", "Could not load accounts.");
246
                        e.printStackTrace();
247
                } catch (ClassNotFoundException e) {
248
                        showAlert("Error", "Could not load accounts.");
249
                        e.printStackTrace();
250
                }
251
                return null;
252
                
253
        }
254

    
255
        private void displayNoAccountsCell() {
256
            String a[] = new String[1];
257
            a[0] = "No Accounts";
258
        setListAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.noaccountscell, R.id.no_accounts_label, a));
259
        getListView().setTextFilterEnabled(true);
260
        getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
261
        getListView().setItemsCanFocus(false);
262
    }
263
        
264
        protected void onListItemClick(ListView l, View v, int position, long id) {
265
                if (accounts != null && accounts.size() > 0) {
266
                        //setActivityIndicatorsVisibility(View.VISIBLE, v);
267
                        Account.setAccount(accounts.get(position));
268
                        login();
269
                }                
270
    }
271
        
272
        public void login() {
273
        //showActivityIndicators();
274
        //setLoginPreferences();
275
        new AuthenticateTask().execute((Void[]) null);
276
    }
277
        
278
        //setup menu for when menu button is pressed
279
        public boolean onCreateOptionsMenu(Menu menu) {
280
                super.onCreateOptionsMenu(menu);
281
                MenuInflater inflater = getMenuInflater();
282
                inflater.inflate(R.menu.accounts_list_menu, menu);
283
                return true;
284
        } 
285
    
286
    @Override 
287
    //in options menu, when add account is selected go to add account activity
288
    public boolean onOptionsItemSelected(MenuItem item) {
289
            switch (item.getItemId()) {
290
            case R.id.add_account:
291
                    startActivityForResult(new Intent(this, AddAccountActivity.class), 78); // arbitrary number; never used again
292
                    return true;
293

    
294
            case R.id.contact_rackspace:
295
                    startActivity(new Intent(this, ContactActivity.class));
296
                    return true;
297
                    
298
            case R.id.add_password:
299
                    startActivity(new Intent(this, CreatePasswordActivity.class));
300
                    return true;
301
            }        
302
            return false;
303
    } 
304

    
305
    //the context menu for a long press on an account
306
        public void onCreateContextMenu(ContextMenu menu, View v,
307
                        ContextMenuInfo menuInfo) {
308
                super.onCreateContextMenu(menu, v, menuInfo);
309
                MenuInflater inflater = getMenuInflater();
310
                inflater.inflate(R.menu.account_context_menu, menu);
311
        }
312

    
313
        //removes the selected account from account list if remove is clicked
314
        public boolean onContextItemSelected(MenuItem item) {
315
                AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
316
                accounts.remove(info.position);
317
                writeAccounts();
318
                loadAccounts();
319
                return true;
320
        }
321

    
322
        class AccountAdapter extends ArrayAdapter<Account> {
323

    
324
                AccountAdapter() {
325
                        super(ListAccountsActivity.this, R.layout.listaccountcell, accounts);
326
                }
327
                
328
                public View getView(int position, View convertView, ViewGroup parent) {
329
                        
330
                        LayoutInflater inflater = getLayoutInflater();
331
                        View row = inflater.inflate(R.layout.listaccountcell, parent, false);
332

    
333
                        TextView label = (TextView) row.findViewById(R.id.label);
334
                        label.setText(accounts.get(position).getUsername());
335
                        
336
                        TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
337
                        sublabel.setText(getAccountServer(accounts.get(position)));
338
                        
339
                        ImageView icon = (ImageView) row.findViewById(R.id.account_type_icon);
340
                        icon.setImageResource(setAccountIcon(accounts.get(position)));
341
                        
342
                        return row;
343
                }
344
        }
345
        
346
        public String getAccountServer(Account account){
347
                String authServer = account.getAuthServer();
348
                String result;
349
                if(authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER)){
350
                        result = "Rackspace Cloud (UK)";
351
                }
352
                else if(authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER)){
353
                        result = "Rackspace Cloud (US)";
354
                }
355
                else{
356
                        result = "Custom";
357
                        //setCustomIcon();
358
                }
359
                return result;
360
        }
361
        
362
        //display rackspace logo for cloud accounts and openstack logo for others
363
        private int setAccountIcon(Account account){
364
                if(account.getAuthServer().equals(Preferences.COUNTRY_UK_AUTH_SERVER) 
365
                                || account.getAuthServer().equals(Preferences.COUNTRY_US_AUTH_SERVER)){
366
                        return R.drawable.rackspacecloud_icon;
367
                }
368
                else{
369
                        return R.drawable.openstack_icon;
370
                }
371
        }
372

    
373
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
374
                super.onActivityResult(requestCode, resultCode, data);
375
                
376
                if(requestCode == 187){
377
                        hideDialog(); 
378
                }
379
                
380
                if (resultCode == RESULT_OK && requestCode == 78) {          
381
                        Account acc = new Account();
382
                        Bundle b = data.getBundleExtra("accountInfo");
383
                        acc.setApiKey(b.getString("apiKey"));
384
                        acc.setUsername(b.getString("username"));
385
                        acc.setAuthServer(b.getString("server"));
386
                        accounts.add(acc);
387
                        writeAccounts();
388
                        loadAccounts();
389
                }
390
        }        
391
/*
392
        private void setActivityIndicatorsVisibility(int visibility) {
393
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
394
                
395
        //ProgressBar pb = new ProgressBar();
396
            //TextView tv = (TextView) findViewById(R.id.login_authenticating_label);
397
        //pb.setVisibility(visibility);
398
        //tv.setVisibility(visibility);
399
    }
400
        
401
        private void setActivityIndicatorsVisibility(int visibility, View v) {
402
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
403
                
404
        //ProgressBar pb = new ProgressBar();
405
            //TextView tv = (TextView) findViewById(R.id.login_authenticating_label);
406
        //pb.setVisibility(visibility);
407
        //tv.setVisibility(visibility);
408
    }
409
*/
410
        
411
        private void showDialog() {
412
                authenticating = true;
413
                if(dialog == null || !dialog.isShowing()){
414
                        dialog = ProgressDialog.show(ListAccountsActivity.this, "", "Authenticating...", true);
415
                }
416
    }
417
    
418
    private void hideDialog() {
419
            if(dialog != null){
420
                    dialog.dismiss();
421
            }
422
            authenticating = false;
423
    }
424

    
425
        private class AuthenticateTask extends AsyncTask<Void, Void, Boolean> {
426
            
427
                @Override
428
                protected void onPreExecute(){
429
                        showDialog();
430
                }
431
                
432
                @Override
433
                protected Boolean doInBackground(Void... arg0) {
434
                        long startTime = System.currentTimeMillis();
435
                        boolean b =  new Boolean(Authentication.authenticate(context));
436
                        long endTime = System.currentTimeMillis();
437
                        Log.d("info", "it took " + (endTime - startTime) + " millis");
438
                        return b;
439
                        //return true;
440
                }
441
            
442
                @Override
443
                protected void onPostExecute(Boolean result) {
444
                        if (result.booleanValue()) {
445
                                //startActivity(tabViewIntent);
446
                        new LoadImagesTask().execute((Void[]) null);
447
                        } else {
448
                                hideDialog();
449
                                showAlert("Login Failure", "Authentication failed.  Please check your User Name and API Key.");
450
                        }
451
                }
452
    }
453

    
454
    private class LoadImagesTask extends AsyncTask<Void, Void, ArrayList<Image>> {
455
            
456
                @Override
457
                protected ArrayList<Image> doInBackground(Void... arg0) {
458
                        return (new ImageManager()).createList(true, context);
459
                }
460
            
461
                @Override
462
                protected void onPostExecute(ArrayList<Image> result) {
463
                        if (result != null && result.size() > 0) {
464
                                TreeMap<String, Image> imageMap = new TreeMap<String, Image>();
465
                                for (int i = 0; i < result.size(); i++) {
466
                                        Image image = result.get(i);
467
                                        imageMap.put(image.getId(), image);
468
                                }
469
                                Image.setImages(imageMap);
470
                                new LoadProtocolsTask().execute((Void[]) null);
471
                        } else {
472
                                hideDialog();
473
                                showAlert("Login Failure", "There was a problem loading server images.  Please try again.");
474
                        }
475
                }
476
    }
477
    
478
    private class LoadProtocolsTask extends AsyncTask<Void, Void, ArrayList<Protocol>> {
479

    
480
                @Override
481
                protected ArrayList<Protocol> doInBackground(Void... arg0) {
482
                        return (new ProtocolManager()).createList(context);
483
                }
484

    
485
                @Override
486
                protected void onPostExecute(ArrayList<Protocol> result) {
487
                        if (result != null && result.size() > 0) {
488
                                Protocol.setProtocols(result);
489
                                new LoadAlgorithmsTask().execute((Void[]) null);
490
                        } else {
491
                                showAlert("Login Failure", "There was a problem loading load balancer protocols.  Please try again.");
492
                        }
493
                }
494
        }
495
    
496
    private class LoadAlgorithmsTask extends AsyncTask<Void, Void, ArrayList<Algorithm>> {
497

    
498
                @Override
499
                protected ArrayList<Algorithm> doInBackground(Void... arg0) {
500
                        return (new AlgorithmManager()).createList(context);
501
                }
502

    
503
                @Override
504
                protected void onPostExecute(ArrayList<Algorithm> result) {
505
                        if (result != null && result.size() > 0) {
506
                                Algorithm.setAlgorithms(result);
507
                                new LoadFlavorsTask().execute((Void[]) null);
508
                        } else {
509
                                showAlert("Login Failure", "There was a problem loading load balancer algorithms.  Please try again.");
510
                        }
511
                }
512
        }
513
    
514
    private class LoadFlavorsTask extends AsyncTask<Void, Void, ArrayList<Flavor>> {
515
            
516
                @Override
517
                protected ArrayList<Flavor> doInBackground(Void... arg0) {
518
                        return (new FlavorManager()).createList(true, context);
519
                }
520
            
521
                @Override
522
                protected void onPostExecute(ArrayList<Flavor> result) {
523
                        if (result != null && result.size() > 0) {
524
                                TreeMap<String, Flavor> flavorMap = new TreeMap<String, Flavor>();
525
                                for (int i = 0; i < result.size(); i++) {
526
                                        Flavor flavor = result.get(i);
527
                                        flavorMap.put(flavor.getId(), flavor);
528
                                }
529
                                Flavor.setFlavors(flavorMap);
530
                                hideDialog();
531
                                startActivityForResult(tabViewIntent, 187);
532
                        } else {
533
                                hideDialog();
534
                                showAlert("Login Failure", "There was a problem loading server flavors.  Please try again.");
535
                        }
536
                }
537
    }
538
    
539
    private void showAlert(String title, String message) {
540
                AlertDialog alert = new AlertDialog.Builder(this).create();
541
                alert.setTitle(title);
542
                alert.setMessage(message);
543
                alert.setButton("OK", new DialogInterface.OnClickListener() {
544
              public void onClick(DialogInterface dialog, int which) {
545
                return;
546
            } }); 
547
                alert.show();
548
    }
549
    
550
    private void showToast(String message) {
551
                Context context = getApplicationContext();
552
                int duration = Toast.LENGTH_SHORT;
553
                Toast toast = Toast.makeText(context, message, duration);
554
                toast.show();
555
    }
556
    
557
    
558
        
559
                
560
}