Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / ListAccountsActivity.java @ 16615abd

History | View | Annotate | Download (17.1 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.ProgressDialog;
27
import android.content.Context;
28
import android.content.DialogInterface;
29
import android.content.DialogInterface.OnCancelListener;
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.WindowManager;
42
import android.view.View.OnClickListener;
43
import android.view.ViewGroup.LayoutParams;
44
import android.view.ViewGroup;
45
import android.widget.AdapterView.AdapterContextMenuInfo;
46
import android.widget.ArrayAdapter;
47
import android.widget.Button;
48
import android.widget.EditText;
49
import android.widget.ImageView;
50
import android.widget.ListView;
51
import android.widget.ProgressBar;
52
import android.widget.TextView;
53
import android.widget.Toast;
54

    
55
//
56
public class ListAccountsActivity extends GaListActivity{
57

    
58
        private final int PASSWORD_PROMPT = 123;
59
        private final String FILENAME = "accounts.data";
60
        private static final String PAGE_ROOT = "/Root";
61
        
62
        private boolean authenticating;
63
        private ArrayList<Account> accounts;
64
        private Intent tabViewIntent;
65
        private ProgressDialog dialog;
66
        private Context context;
67
        private AndroidCloudApplication app;
68
        //used to track the current asynctask
69
        @SuppressWarnings("rawtypes")
70
        private AsyncTask task;
71

    
72
        //need to store if the user has successfully logged in
73
        private boolean loggedIn;
74

    
75
        public void onCreate(Bundle savedInstanceState) {
76
                super.onCreate(savedInstanceState);
77
                trackPageView(PAGE_ROOT);
78
                onRestoreInstanceState(savedInstanceState);
79
                registerForContextMenu(getListView());
80
                context = getApplicationContext();
81
                tabViewIntent = new Intent(this, TabViewActivity.class);
82
                verifyPassword();
83
        }
84

    
85
        @Override
86
        protected void onSaveInstanceState(Bundle outState) {
87
                super.onSaveInstanceState(outState);
88
                outState.putBoolean("authenticating", authenticating);
89
                outState.putBoolean("loggedIn", loggedIn);
90
                outState.putSerializable("accounts", accounts);
91

    
92
                //need to set authenticating back to true because it is set to false
93
                //in hideDialog()
94
                if(authenticating){
95
                        hideDialog();
96
                        authenticating = true;
97
                }
98
                writeAccounts();
99
        }
100

    
101
        @SuppressWarnings("unchecked")
102
        @Override
103
        protected void onRestoreInstanceState(Bundle state) {
104

    
105
                /*
106
                 * need reference to the app so you can access
107
                 * isLoggingIn
108
                 */
109
                app = (AndroidCloudApplication)this.getApplication();
110
                
111
                if (state != null && state.containsKey("loggedIn")){
112
                        loggedIn = state.getBoolean("loggedIn");
113
                }
114
                else{
115
                        loggedIn = false;
116
                }
117

    
118
                if (state != null && state.containsKey("authenticating") && state.getBoolean("authenticating")) {
119
                        showDialog();
120
                } else {
121
                        hideDialog();
122
                }
123
                if (state != null && state.containsKey("accounts")) {
124
                        accounts = (ArrayList<Account>)state.getSerializable("accounts");
125
                        if (accounts.size() == 0) {
126
                                displayNoAccountsCell();
127
                        } else {
128
                                getListView().setDividerHeight(1); // restore divider lines 
129
                                setListAdapter(new AccountAdapter());
130
                        }
131
                } else {
132
                        loadAccounts();        
133
                }         
134
        }
135

    
136
        @Override
137
        protected void onStart(){
138
                super.onStart();
139
                if(authenticating){
140
                        showDialog();
141
                }
142
        }
143

    
144
        @Override
145
        protected void onStop(){
146
                super.onStop();
147
                if(authenticating){
148
                        hideDialog();
149
                        authenticating = true;
150
                }
151
        }
152

    
153
        /*
154
         * if the application is password protected,
155
         * the user must provide the password before
156
         * gaining access
157
         */
158
        private void verifyPassword(){
159
                PasswordManager pwManager = new PasswordManager(getSharedPreferences(
160
                                Preferences.SHARED_PREFERENCES_NAME, MODE_PRIVATE));
161
                if(pwManager.hasPassword() && !loggedIn){
162
                        createCustomDialog(PASSWORD_PROMPT);
163
                }
164
        }
165

    
166
        private boolean rightPassword(String password){
167
                PasswordManager pwManager = new PasswordManager(getSharedPreferences(
168
                                Preferences.SHARED_PREFERENCES_NAME, MODE_PRIVATE));
169
                return pwManager.verifyEnteredPassword(password);
170
        }
171

    
172

    
173
        /*
174
         * forces the user to enter a correct password
175
         * before they gain access to application data
176
         */
177
        private void createCustomDialog(int id) {
178
                final Dialog dialog = new Dialog(ListAccountsActivity.this);
179
                switch (id) {
180
                case PASSWORD_PROMPT:
181
                        dialog.setContentView(R.layout.passworddialog);
182
                        dialog.setTitle("Enter your password:");
183
                        dialog.setCancelable(false);
184
                        Button button = (Button) dialog.findViewById(R.id.submit_password);
185
                        button.setOnClickListener(new OnClickListener() {
186
                                public void onClick(View v){
187
                                        EditText passwordText = ((EditText)dialog.findViewById(R.id.submit_password_text));
188
                                        if(!rightPassword(passwordText.getText().toString())){
189
                                                passwordText.setText("");
190
                                                showToast("Password was incorrect.");
191
                                                loggedIn = false;
192
                                        }
193
                                        else{
194
                                                dialog.dismiss();
195
                                                loggedIn = true;
196
                                        }
197
                                }
198

    
199
                        });
200
                        dialog.show();
201
                }
202
        }
203

    
204
        private void loadAccounts() {
205
                //check and see if there are any in memory
206
                if(accounts == null){
207
                        accounts = readAccounts();
208
                }
209
                //if nothing was written before accounts will still be null
210
                if(accounts == null){
211
                        accounts = new ArrayList<Account>();
212
                }
213

    
214
                setAccountList();
215
        }
216

    
217
        private void setAccountList() {
218

    
219
                if (accounts.size() == 0) {
220
                        displayNoAccountsCell();
221
                } else {
222
                        getListView().setDividerHeight(1); // restore divider lines 
223
                        this.setListAdapter(new AccountAdapter());
224
                }
225
        }
226

    
227
        private void writeAccounts(){
228
                FileOutputStream fos;
229
                ObjectOutputStream out = null;
230
                try{
231
                        fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
232
                        out = new ObjectOutputStream(fos);
233
                        out.writeObject(accounts);
234
                        out.flush();
235
                        out.close();
236
                } catch (FileNotFoundException e) {
237
                        showAlert("Error", "Could not save accounts.");
238
                        e.printStackTrace();
239
                } catch (IOException e) {
240
                        showAlert("Error", "Could not save accounts.");
241
                        e.printStackTrace();
242
                }
243
        }
244

    
245
        private ArrayList<Account> readAccounts(){
246
                FileInputStream fis;
247
                ObjectInputStream in;
248
                try {
249
                        fis = openFileInput(FILENAME);
250
                        in = new ObjectInputStream(fis);
251
                        @SuppressWarnings("unchecked")
252
                        ArrayList<Account> file = (ArrayList<Account>)in.readObject();
253
                        in.close();
254
                        return file; 
255
                } catch (FileNotFoundException e) {
256
                        //showAlert("Error", "Could not load accounts.");
257
                        e.printStackTrace();
258
                        return null;
259
                } catch (StreamCorruptedException e) {
260
                        showAlert("Error", "Could not load accounts.");
261
                        e.printStackTrace();
262
                } catch (IOException e) {
263
                        showAlert("Error", "Could not load accounts.");
264
                        e.printStackTrace();
265
                } catch (ClassNotFoundException e) {
266
                        showAlert("Error", "Could not load accounts.");
267
                        e.printStackTrace();
268
                }
269
                return null;
270

    
271
        }
272

    
273
        private void displayNoAccountsCell() {
274
                String a[] = new String[1];
275
                a[0] = "No Accounts";
276
                setListAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.noaccountscell, R.id.no_accounts_label, a));
277
                getListView().setTextFilterEnabled(true);
278
                getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
279
                getListView().setItemsCanFocus(false);
280
        }
281

    
282
        protected void onListItemClick(ListView l, View v, int position, long id) {
283
                if (accounts != null && accounts.size() > 0) {
284
                        //setActivityIndicatorsVisibility(View.VISIBLE, v);
285
                        Account.setAccount(accounts.get(position));
286
                        login();
287
                }                
288
        }
289

    
290
        public void login() {
291
                //showActivityIndicators();
292
                //setLoginPreferences();
293
                new AuthenticateTask().execute((Void[]) null);
294
        }
295

    
296
        //setup menu for when menu button is pressed
297
        public boolean onCreateOptionsMenu(Menu menu) {
298
                super.onCreateOptionsMenu(menu);
299
                MenuInflater inflater = getMenuInflater();
300
                inflater.inflate(R.menu.accounts_list_menu, menu);
301
                return true;
302
        } 
303

    
304
        @Override 
305
        //in options menu, when add account is selected go to add account activity
306
        public boolean onOptionsItemSelected(MenuItem item) {
307
                switch (item.getItemId()) {
308
                case R.id.add_account:
309
                        startActivityForResult(new Intent(this, AddAccountActivity.class), 78); // arbitrary number; never used again
310
                        return true;
311

    
312
                case R.id.contact_rackspace:
313
                        startActivity(new Intent(this, ContactActivity.class));
314
                        return true;
315

    
316
                case R.id.add_password:
317
                        startActivity(new Intent(this, CreatePasswordActivity.class));
318
                        return true;
319
                }        
320
                return false;
321
        } 
322

    
323
        //the context menu for a long press on an account
324
        public void onCreateContextMenu(ContextMenu menu, View v,
325
                        ContextMenuInfo menuInfo) {
326
                super.onCreateContextMenu(menu, v, menuInfo);
327
                MenuInflater inflater = getMenuInflater();
328
                inflater.inflate(R.menu.account_context_menu, menu);
329
        }
330

    
331
        //removes the selected account from account list if remove is clicked
332
        public boolean onContextItemSelected(MenuItem item) {
333
                AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
334
                accounts.remove(info.position);
335
                writeAccounts();
336
                loadAccounts();
337
                return true;
338
        }
339

    
340
        class AccountAdapter extends ArrayAdapter<Account> {
341

    
342
                AccountAdapter() {
343
                        super(ListAccountsActivity.this, R.layout.listaccountcell, accounts);
344
                }
345

    
346
                public View getView(int position, View convertView, ViewGroup parent) {
347

    
348
                        LayoutInflater inflater = getLayoutInflater();
349
                        View row = inflater.inflate(R.layout.listaccountcell, parent, false);
350

    
351
                        TextView label = (TextView) row.findViewById(R.id.label);
352
                        label.setText(accounts.get(position).getUsername());
353

    
354
                        TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
355
                        sublabel.setText(getAccountServer(accounts.get(position)));
356

    
357
                        ImageView icon = (ImageView) row.findViewById(R.id.account_type_icon);
358
                        icon.setImageResource(setAccountIcon(accounts.get(position)));
359

    
360
                        return row;
361
                }
362
        }
363

    
364
        public String getAccountServer(Account account){
365
                String authServer = account.getAuthServer();
366
                String result;
367
                if(authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER)){
368
                        result = "Rackspace Cloud (UK)";
369
                }
370
                else if(authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER)){
371
                        result = "Rackspace Cloud (US)";
372
                }
373
                else{
374
                        result = "Custom";
375
                        //setCustomIcon();
376
                }
377
                return result;
378
        }
379

    
380
        //display rackspace logo for cloud accounts and openstack logo for others
381
        private int setAccountIcon(Account account){
382
                if(account.getAuthServer().equals(Preferences.COUNTRY_UK_AUTH_SERVER) 
383
                                || account.getAuthServer().equals(Preferences.COUNTRY_US_AUTH_SERVER)){
384
                        return R.drawable.rackspacecloud_icon;
385
                }
386
                else{
387
                        return R.drawable.openstack_icon;
388
                }
389
        }
390

    
391
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
392
                super.onActivityResult(requestCode, resultCode, data);
393

    
394
                if(requestCode == 187){
395
                        hideDialog(); 
396
                }
397

    
398
                if (resultCode == RESULT_OK && requestCode == 78) {          
399
                        Account acc = new Account();
400
                        Bundle b = data.getBundleExtra("accountInfo");
401
                        acc.setApiKey(b.getString("apiKey"));
402
                        acc.setUsername(b.getString("username"));
403
                        acc.setAuthServer(b.getString("server"));
404
                        accounts.add(acc);
405
                        writeAccounts();
406
                        loadAccounts();
407
                }
408
        }        
409

    
410
        private void showDialog() {
411
                app.setIsLoggingIn(true);
412
                authenticating = true;
413
                if(dialog == null || !dialog.isShowing()){
414
                        dialog = new ProgressDialog(this);
415
                        dialog.setProgressStyle(R.style.NewDialog);
416
                        dialog.setOnCancelListener(new OnCancelListener() {
417

    
418
                                @Override
419
                                public void onCancel(DialogInterface dialog) {
420
                                        app.setIsLoggingIn(false);
421
                                        //need to cancel the old task or we may get a double login
422
                                        task.cancel(true);
423
                                        hideDialog();
424
                                }
425
                        });
426
                        dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
427
                        dialog.show();
428
                        dialog.setContentView(new ProgressBar(this), new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
429
                }
430

    
431
                
432
        }
433

    
434
        private void hideDialog() {
435
                if(dialog != null){
436
                        dialog.dismiss();
437
                }
438
                authenticating = false;
439
        }
440

    
441
        private class AuthenticateTask extends AsyncTask<Void, Void, Boolean> {
442

    
443
                @Override
444
                protected void onPreExecute(){
445
                        Log.d("info", "Starting authenticate");
446
                        task = this;
447
                        showDialog();
448
                }
449

    
450
                @Override
451
                protected Boolean doInBackground(Void... arg0) {
452
                        return new Boolean(Authentication.authenticate(context));
453
                }
454

    
455
                @Override
456
                protected void onPostExecute(Boolean result) {
457
                        if (result.booleanValue()) {
458
                                //startActivity(tabViewIntent);
459
                                if(app.isLoggingIn()){
460
                                        new LoadImagesTask().execute((Void[]) null);
461
                                } else {
462
                                        hideDialog();
463
                                }
464
                        } else {
465
                                hideDialog();
466
                                if(app.isLoggingIn()){
467
                                        showAlert("Login Failure", "Authentication failed.  Please check your User Name and API Key.");
468
                                }
469
                        }
470
                }
471
        }
472

    
473
        private class LoadImagesTask extends AsyncTask<Void, Void, ArrayList<Image>> {
474
 
475
                @Override
476
                protected void onPreExecute(){
477
                        Log.d("info", "Starting Images");
478
                        task = this;
479
                }
480
                
481
                @Override
482
                protected ArrayList<Image> doInBackground(Void... arg0) {
483
                        return (new ImageManager()).createList(true, context);
484
                }
485

    
486
                @Override
487
                protected void onPostExecute(ArrayList<Image> result) {
488
                        if (result != null && result.size() > 0) {
489
                                TreeMap<String, Image> imageMap = new TreeMap<String, Image>();
490
                                for (int i = 0; i < result.size(); i++) {
491
                                        Image image = result.get(i);
492
                                        imageMap.put(image.getId(), image);
493
                                }
494
                                Image.setImages(imageMap);
495
                                if(app.isLoggingIn()){
496
                                        new LoadProtocolsTask().execute((Void[]) null); 
497
                                } else {
498
                                        hideDialog();
499
                                }
500
                        } else {
501
                                hideDialog();
502
                                if(app.isLoggingIn()){
503
                                        showAlert("Login Failure", "There was a problem loading server images.  Please try again.");
504
                                }
505
                        }
506
                }
507
        }
508

    
509
        private class LoadProtocolsTask extends AsyncTask<Void, Void, ArrayList<Protocol>> {
510

    
511
                @Override
512
                protected void onPreExecute(){
513
                        Log.d("info", "Starting protcols");
514
                        task = this;
515
                }
516
                
517
                @Override
518
                protected ArrayList<Protocol> doInBackground(Void... arg0) {
519
                        return (new ProtocolManager()).createList(context);
520
                }
521

    
522
                @Override
523
                protected void onPostExecute(ArrayList<Protocol> result) {
524
                        if (result != null && result.size() > 0) {
525
                                Protocol.setProtocols(result);
526
                                if(app.isLoggingIn()){
527
                                        new LoadAlgorithmsTask().execute((Void[]) null);
528
                                } else {
529
                                        hideDialog();
530
                                }
531
                        } else {
532
                                hideDialog();
533
                                if(app.isLoggingIn()){
534
                                        showAlert("Login Failure", "There was a problem loading load balancer protocols.  Please try again.");
535
                                }
536
                        }
537
                }
538
        }
539

    
540
        private class LoadAlgorithmsTask extends AsyncTask<Void, Void, ArrayList<Algorithm>> {
541

    
542
                protected void onPreExecute(){
543
                        Log.d("info", "Starting algorithms");
544
                        task = this;
545
                }
546
                
547
                @Override
548
                protected ArrayList<Algorithm> doInBackground(Void... arg0) {
549
                        return (new AlgorithmManager()).createList(context);
550
                }
551

    
552
                @Override
553
                protected void onPostExecute(ArrayList<Algorithm> result) {
554
                        if (result != null && result.size() > 0) {
555
                                Algorithm.setAlgorithms(result);
556
                                if(app.isLoggingIn()){
557
                                        new LoadFlavorsTask().execute((Void[]) null);
558
                                } else {
559
                                        hideDialog();
560
                                }
561
                        } else {
562
                                hideDialog();
563
                                if(app.isLoggingIn()){
564
                                        showAlert("Login Failure", "There was a problem loading load balancer algorithms.  Please try again.");
565
                                }
566
                        }
567
                }
568
        }
569

    
570
        private class LoadFlavorsTask extends AsyncTask<Void, Void, ArrayList<Flavor>> {
571

    
572
                protected void onPreExecute(){
573
                        Log.d("info", "Starting flavors");
574
                        task = this;
575
                }
576
                
577
                @Override
578
                protected ArrayList<Flavor> doInBackground(Void... arg0) {
579
                        return (new FlavorManager()).createList(true, context);
580
                }
581

    
582
                @Override
583
                protected void onPostExecute(ArrayList<Flavor> result) {
584
                        if (result != null && result.size() > 0) {
585
                                TreeMap<String, Flavor> flavorMap = new TreeMap<String, Flavor>();
586
                                for (int i = 0; i < result.size(); i++) {
587
                                        Flavor flavor = result.get(i);
588
                                        flavorMap.put(flavor.getId(), flavor);
589
                                }
590
                                Flavor.setFlavors(flavorMap);
591
                                hideDialog();
592
                                if(app.isLoggingIn()){
593
                                        startActivityForResult(tabViewIntent, 187);
594
                                }
595
                        } else {
596
                                hideDialog();
597
                                if(app.isLoggingIn()){
598
                                        showAlert("Login Failure", "There was a problem loading server flavors.  Please try again.");
599
                                }
600
                        }
601
                }
602
        }
603

    
604

    
605
        private void showAlert(String title, String message) {
606
                AlertDialog alert = new AlertDialog.Builder(this).create();
607
                alert.setTitle(title);
608
                alert.setMessage(message);
609
                alert.setButton("OK", new DialogInterface.OnClickListener() {
610
                        public void onClick(DialogInterface dialog, int which) {
611
                                return;
612
                        } }); 
613
                alert.show();
614
        }
615

    
616
        private void showToast(String message) {
617
                Context context = getApplicationContext();
618
                int duration = Toast.LENGTH_SHORT;
619
                Toast toast = Toast.makeText(context, message, duration);
620
                toast.show();
621
        }
622

    
623

    
624

    
625

    
626
}