Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / ListAccountsActivity.java @ f3633a16

History | View | Annotate | Download (15.6 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.CloudServersException;
19
import com.rackspace.cloud.servers.api.client.Flavor;
20
import com.rackspace.cloud.servers.api.client.FlavorManager;
21
import com.rackspace.cloud.servers.api.client.Image;
22
import com.rackspace.cloud.servers.api.client.ImageManager;
23
import com.rackspace.cloud.servers.api.client.http.Authentication;
24

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

    
56
//
57
public class ListAccountsActivity extends CloudListActivity{
58

    
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
        //used to track the current asynctask
68
        @SuppressWarnings("rawtypes")
69
        private AsyncTask task;
70

    
71
        public void onCreate(Bundle savedInstanceState) {
72
                super.onCreate(savedInstanceState);
73
                trackPageView(PAGE_ROOT);
74
                onRestoreInstanceState(savedInstanceState);
75
                registerForContextMenu(getListView());
76
                context = getApplicationContext();
77
                tabViewIntent = new Intent(this, TabViewActivity.class);
78
        }
79

    
80
        @Override
81
        protected void onSaveInstanceState(Bundle outState) {
82
                super.onSaveInstanceState(outState);
83
                outState.putBoolean("authenticating", authenticating);
84
                outState.putSerializable("accounts", accounts);
85

    
86
                //need to set authenticating back to true because it is set to false
87
                //in hideAccountDialog()
88
                if(authenticating){
89
                        hideAccountDialog();
90
                        authenticating = true;
91
                }
92
                writeAccounts();
93
        }
94

    
95
        @SuppressWarnings("unchecked")
96
        @Override
97
        protected void onRestoreInstanceState(Bundle state) {
98

    
99
                /*
100
                 * need reference to the app so you can access
101
                 * isLoggingIn
102
                 */
103

    
104

    
105
                if (state != null && state.containsKey("authenticating") && state.getBoolean("authenticating")) {
106
                        showAccountDialog();
107
                } else {
108
                        hideAccountDialog();
109
                }
110
                if (state != null && state.containsKey("accounts")) {
111
                        accounts = (ArrayList<Account>)state.getSerializable("accounts");
112
                        if (accounts.size() == 0) {
113
                                displayNoAccountsCell();
114
                        } else {
115
                                getListView().setDividerHeight(1); // restore divider lines 
116
                                setListAdapter(new AccountAdapter());
117
                        }
118
                } else {
119
                        loadAccounts();        
120
                }         
121
        }
122

    
123
        @Override
124
        protected void onStart(){
125
                super.onStart();
126
                if(authenticating){
127
                        showAccountDialog();
128
                }
129
        }
130

    
131
        @Override
132
        protected void onStop(){
133
                super.onStop();
134
                if(authenticating){
135
                        hideAccountDialog();
136
                        authenticating = true;
137
                }
138
        }
139

    
140
        private void loadAccounts() {
141
                //check and see if there are any in memory
142
                if(accounts == null){
143
                        accounts = readAccounts();
144
                }
145
                //if nothing was written before accounts will still be null
146
                if(accounts == null){
147
                        accounts = new ArrayList<Account>();
148
                }
149

    
150
                setAccountList();
151
        }
152

    
153
        private void setAccountList() {
154
                if (accounts.size() == 0) {
155
                        displayNoAccountsCell();
156
                } else {
157
                        getListView().setDividerHeight(1); // restore divider lines 
158
                        this.setListAdapter(new AccountAdapter());
159
                }
160
        }
161

    
162
        private void writeAccounts(){
163
                FileOutputStream fos;
164
                ObjectOutputStream out = null;
165
                try{
166
                        fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
167
                        out = new ObjectOutputStream(fos);
168
                        out.writeObject(accounts);
169
                        out.flush();
170
                        out.close();
171
                } catch (FileNotFoundException e) {
172
                        showAlert("Error", "Could not save accounts.");
173
                        e.printStackTrace();
174
                } catch (IOException e) {
175
                        showAlert("Error", "Could not save accounts.");
176
                        e.printStackTrace();
177
                }
178
        }
179

    
180
        private ArrayList<Account> readAccounts(){
181
                FileInputStream fis;
182
                ObjectInputStream in;
183
                try {
184
                        fis = openFileInput(FILENAME);
185
                        in = new ObjectInputStream(fis);
186
                        @SuppressWarnings("unchecked")
187
                        ArrayList<Account> file = (ArrayList<Account>)in.readObject();
188
                        in.close();
189
                        return file; 
190
                } catch (FileNotFoundException e) {
191
                        //showAlert("Error", "Could not load accounts.");
192
                        e.printStackTrace();
193
                        return null;
194
                } catch (StreamCorruptedException e) {
195
                        showAlert("Error", "Could not load accounts.");
196
                        e.printStackTrace();
197
                } catch (IOException e) {
198
                        showAlert("Error", "Could not load accounts.");
199
                        e.printStackTrace();
200
                } catch (ClassNotFoundException e) {
201
                        showAlert("Error", "Could not load accounts.");
202
                        e.printStackTrace();
203
                }
204
                return null;
205

    
206
        }
207

    
208
        private void displayNoAccountsCell() {
209
                String a[] = new String[1];
210
                a[0] = "No Accounts";
211
                setListAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.noaccountscell, R.id.no_accounts_label, a));
212
                getListView().setTextFilterEnabled(true);
213
                getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
214
                getListView().setItemsCanFocus(false);
215
        }
216

    
217
        protected void onListItemClick(ListView l, View v, int position, long id) {
218
                if (accounts != null && accounts.size() > 0) {
219
                        //setActivityIndicatorsVisibility(View.VISIBLE, v);
220
                        Account.setAccount(accounts.get(position));
221
                        Log.d("info", "the server is " + Account.getAccount().getAuthServerV2());
222
                        login();
223
                }                
224
        }
225

    
226
        public void login() {
227
                //showActivityIndicators();
228
                //setLoginPreferences();
229
                new AuthenticateTask().execute((Void[]) null);
230
        }
231

    
232
        //setup menu for when menu button is pressed
233
        public boolean onCreateOptionsMenu(Menu menu) {
234
                super.onCreateOptionsMenu(menu);
235
                MenuInflater inflater = getMenuInflater();
236
                inflater.inflate(R.menu.accounts_list_menu, menu);
237
                return true;
238
        } 
239

    
240
        @Override 
241
        //in options menu, when add account is selected go to add account activity
242
        public boolean onOptionsItemSelected(MenuItem item) {
243
                switch (item.getItemId()) {
244
                case R.id.add_account:
245
                        startActivityForResult(new Intent(this, AddAccountActivity.class), 78); // arbitrary number; never used again
246
                        return true;
247

    
248
                case R.id.contact_rackspace:
249
                        startActivity(new Intent(this, ContactActivity.class));
250
                        return true;
251

    
252
                case R.id.add_password:
253
                        startActivity(new Intent(this, CreatePasswordActivity.class));
254
                        return true;
255
                }        
256
                return false;
257
        } 
258

    
259
        //the context menu for a long press on an account
260
        public void onCreateContextMenu(ContextMenu menu, View v,
261
                        ContextMenuInfo menuInfo) {
262
                super.onCreateContextMenu(menu, v, menuInfo);
263
                MenuInflater inflater = getMenuInflater();
264
                inflater.inflate(R.menu.account_context_menu, menu);
265
        }
266

    
267
        //removes the selected account from account list if remove is clicked
268
        public boolean onContextItemSelected(MenuItem item) {
269
                AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
270
                accounts.remove(info.position);
271
                writeAccounts();
272
                loadAccounts();
273
                return true;
274
        }
275

    
276
        class AccountAdapter extends ArrayAdapter<Account> {
277

    
278
                AccountAdapter() {
279
                        super(ListAccountsActivity.this, R.layout.listaccountcell, accounts);
280
                }
281

    
282
                public View getView(int position, View convertView, ViewGroup parent) {
283

    
284
                        LayoutInflater inflater = getLayoutInflater();
285
                        View row = inflater.inflate(R.layout.listaccountcell, parent, false);
286

    
287
                        TextView label = (TextView) row.findViewById(R.id.label);
288
                        label.setText(accounts.get(position).getUsername());
289

    
290
                        TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
291
                        sublabel.setText(getAccountServer(accounts.get(position)));
292

    
293
                        ImageView icon = (ImageView) row.findViewById(R.id.account_type_icon);
294
                        icon.setImageResource(setAccountIcon(accounts.get(position)));
295

    
296
                        return row;
297
                }
298
        }
299

    
300
        public String getAccountServer(Account account){
301
                String authServer = account.getAuthServer();
302
                if(authServer == null){
303
                        authServer = account.getAuthServerV2();
304
                }
305
                String result;
306
                                
307
                if(authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER) || authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER_V2)){
308
                        result = "Rackspace Cloud (UK)";
309
                }
310
                else if(authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER) || authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER_V2)){
311
                        result = "Rackspace Cloud (US)";
312
                }
313
                else{
314
                        result = "Custom";
315
                        //setCustomIcon();
316
                }
317
                return result;
318
        }
319

    
320
        //display rackspace logo for cloud accounts and openstack logo for others
321
        private int setAccountIcon(Account account){
322
                String authServer = account.getAuthServer();
323
                if(authServer == null){
324
                        authServer = account.getAuthServerV2();
325
                }
326
                if(authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER) 
327
                                || authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER)
328
                                || authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER_V2)
329
                                                || authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER_V2)){
330
                        return R.drawable.rackspacecloud_icon;
331
                }
332
                else{
333
                        return R.drawable.openstack_icon;
334
                }
335
        }
336

    
337
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
338
                super.onActivityResult(requestCode, resultCode, data);
339

    
340
                if(requestCode == 187){
341
                        hideAccountDialog(); 
342
                }
343

    
344
                if (resultCode == RESULT_OK && requestCode == 78) {          
345
                        Account acc = new Account();
346
                        Bundle b = data.getBundleExtra("accountInfo");
347
                        acc.setPassword(b.getString("apiKey"));
348
                        acc.setUsername(b.getString("username"));
349
                        acc.setAuthServerV2(b.getString("server"));
350
                        Log.d("info", "the set server was " + b.getString("server"));
351
                        Log.d("info", "the server is " + acc.getAuthServerV2());
352
                        accounts.add(acc);
353
                        writeAccounts();
354
                        loadAccounts();
355
                }
356
        }        
357

    
358
        private void showAccountDialog() {
359
                app.setIsLoggingIn(true);
360
                authenticating = true;
361
                if(dialog == null || !dialog.isShowing()){
362
                        dialog = new ProgressDialog(this);
363
                        dialog.setProgressStyle(R.style.NewDialog);
364
                        dialog.setOnCancelListener(new OnCancelListener() {
365

    
366
                                @Override
367
                                public void onCancel(DialogInterface dialog) {
368
                                        app.setIsLoggingIn(false);
369
                                        //need to cancel the old task or we may get a double login
370
                                        task.cancel(true);
371
                                        hideAccountDialog();
372
                                }
373
                        });
374
                        dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
375
                        dialog.show();
376
                        dialog.setContentView(new ProgressBar(this), new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
377
                }
378

    
379
                
380
        }
381

    
382
        private void hideAccountDialog() {
383
                if(dialog != null){
384
                        dialog.dismiss();
385
                }
386
                authenticating = false;
387
        }
388

    
389
        private class AuthenticateTask extends AsyncTask<Void, Void, Boolean> {
390

    
391
                @Override
392
                protected void onPreExecute(){
393
                        Log.d("info", "Starting authenticate");
394
                        task = this;
395
                        showAccountDialog();
396
                }
397

    
398
                @Override
399
                protected Boolean doInBackground(Void... arg0) {
400
                        try {
401
                                return new Boolean(Authentication.authenticate(context));
402
                        } catch (CloudServersException e) {
403
                                e.printStackTrace();
404
                                return false;
405
                        }
406
                }
407

    
408
                @Override
409
                protected void onPostExecute(Boolean result) {
410
                        if (result.booleanValue()) {
411
                                //startActivity(tabViewIntent);
412
                                if(app.isLoggingIn()){
413
                                        new LoadImagesTask().execute((Void[]) null);
414
                                } else {
415
                                        hideAccountDialog();
416
                                }
417
                        } else {
418
                                hideAccountDialog();
419
                                if(app.isLoggingIn()){
420
                                        showAlert("Login Failure", "Authentication failed.  Please check your User Name and API Key.");
421
                                }
422
                        }
423
                }
424
        }
425

    
426
        private class LoadImagesTask extends AsyncTask<Void, Void, ArrayList<Image>> {
427
 
428
                @Override
429
                protected void onPreExecute(){
430
                        Log.d("info", "Starting Images");
431
                        task = this;
432
                }
433
                
434
                @Override
435
                protected ArrayList<Image> doInBackground(Void... arg0) {
436
                        return (new ImageManager()).createList(true, context);
437
                }
438

    
439
                @Override
440
                protected void onPostExecute(ArrayList<Image> result) {
441
                        if (result != null && result.size() > 0) {
442
                                TreeMap<String, Image> imageMap = new TreeMap<String, Image>();
443
                                for (int i = 0; i < result.size(); i++) {
444
                                        Image image = result.get(i);
445
                                        imageMap.put(image.getId(), image);
446
                                }
447
                                Image.setImages(imageMap);
448
                                if(app.isLoggingIn()){
449
                                        new LoadProtocolsTask().execute((Void[]) null); 
450
                                } else {
451
                                        hideAccountDialog();
452
                                }
453
                        } else {
454
                                hideAccountDialog();
455
                                if(app.isLoggingIn()){
456
                                        showAlert("Login Failure", "There was a problem loading server images.  Please try again.");
457
                                }
458
                        }
459
                }
460
        }
461

    
462
        private class LoadProtocolsTask extends AsyncTask<Void, Void, ArrayList<Protocol>> {
463

    
464
                @Override
465
                protected void onPreExecute(){
466
                        Log.d("info", "Starting protcols");
467
                        task = this;
468
                }
469
                
470
                @Override
471
                protected ArrayList<Protocol> doInBackground(Void... arg0) {
472
                        return (new ProtocolManager()).createList(context);
473
                }
474

    
475
                @Override
476
                protected void onPostExecute(ArrayList<Protocol> result) {
477
                        if (result != null && result.size() > 0) {
478
                                Protocol.setProtocols(result);
479
                                if(app.isLoggingIn()){
480
                                        new LoadAlgorithmsTask().execute((Void[]) null);
481
                                } else {
482
                                        hideAccountDialog();
483
                                }
484
                        } else {
485
                                hideAccountDialog();
486
                                if(app.isLoggingIn()){
487
                                        showAlert("Login Failure", "There was a problem loading load balancer protocols.  Please try again.");
488
                                }
489
                        }
490
                }
491
        }
492

    
493
        private class LoadAlgorithmsTask extends AsyncTask<Void, Void, ArrayList<Algorithm>> {
494

    
495
                protected void onPreExecute(){
496
                        Log.d("info", "Starting algorithms");
497
                        task = this;
498
                }
499
                
500
                @Override
501
                protected ArrayList<Algorithm> doInBackground(Void... arg0) {
502
                        return (new AlgorithmManager()).createList(context);
503
                }
504

    
505
                @Override
506
                protected void onPostExecute(ArrayList<Algorithm> result) {
507
                        if (result != null && result.size() > 0) {
508
                                Algorithm.setAlgorithms(result);
509
                                if(app.isLoggingIn()){
510
                                        new LoadFlavorsTask().execute((Void[]) null);
511
                                } else {
512
                                        hideAccountDialog();
513
                                }
514
                        } else {
515
                                hideAccountDialog();
516
                                if(app.isLoggingIn()){
517
                                        showAlert("Login Failure", "There was a problem loading load balancer algorithms.  Please try again.");
518
                                }
519
                        }
520
                }
521
        }
522

    
523
        private class LoadFlavorsTask extends AsyncTask<Void, Void, ArrayList<Flavor>> {
524

    
525
                protected void onPreExecute(){
526
                        Log.d("info", "Starting flavors");
527
                        task = this;
528
                }
529
                
530
                @Override
531
                protected ArrayList<Flavor> doInBackground(Void... arg0) {
532
                        return (new FlavorManager()).createList(true, context);
533
                }
534

    
535
                @Override
536
                protected void onPostExecute(ArrayList<Flavor> result) {
537
                        if (result != null && result.size() > 0) {
538
                                TreeMap<String, Flavor> flavorMap = new TreeMap<String, Flavor>();
539
                                for (int i = 0; i < result.size(); i++) {
540
                                        Flavor flavor = result.get(i);
541
                                        flavorMap.put(flavor.getId(), flavor);
542
                                }
543
                                Flavor.setFlavors(flavorMap);
544
                                hideAccountDialog();
545
                                if(app.isLoggingIn()){
546
                                        startActivityForResult(tabViewIntent, 187);
547
                                }
548
                        } else {
549
                                hideAccountDialog();
550
                                if(app.isLoggingIn()){
551
                                        showAlert("Login Failure", "There was a problem loading server flavors.  Please try again.");
552
                                }
553
                        }
554
                }
555
        }
556

    
557

    
558

    
559

    
560

    
561
}