Statistics
| Branch: | Revision:

root / src / com / rackspace / cloud / android / ContainerObjectDetails.java @ d79ae700

History | View | Annotate | Download (36.1 kB)

1
package com.rackspace.cloud.android;
2

    
3
import java.io.BufferedOutputStream;
4
import java.io.File;
5
import java.io.FileOutputStream;
6
import java.io.IOException;
7
import java.io.InputStream;
8
import java.io.OutputStream;
9
import java.util.ArrayList;
10
import java.util.HashMap;
11
import java.util.Iterator;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.Map.Entry;
15
import java.util.StringTokenizer;
16

    
17
import org.apache.http.HttpEntity;
18
import org.apache.http.HttpResponse;
19

    
20
import android.app.Activity;
21
import android.app.AlertDialog;
22
import android.app.Dialog;
23
import android.content.DialogInterface;
24
import android.content.Intent;
25
import android.graphics.Color;
26
import android.net.Uri;
27
import android.os.AsyncTask;
28
import android.os.Bundle;
29
import android.os.Environment;
30
import android.util.Log;
31
import android.view.LayoutInflater;
32
import android.view.Menu;
33
import android.view.MenuInflater;
34
import android.view.MenuItem;
35
import android.view.View;
36
import android.view.View.OnClickListener;
37
import android.widget.Button;
38
import android.widget.CheckBox;
39
import android.widget.CompoundButton;
40
import android.widget.CompoundButton.OnCheckedChangeListener;
41
import android.widget.EditText;
42
import android.widget.ImageButton;
43
import android.widget.LinearLayout;
44
import android.widget.TabHost;
45
import android.widget.TextView;
46
import android.widget.Toast;
47

    
48
import com.rackspace.cloud.files.api.client.Container;
49
import com.rackspace.cloud.files.api.client.ContainerObjectManager;
50
import com.rackspace.cloud.files.api.client.ContainerObjects;
51
import com.rackspace.cloud.files.api.client.GroupResource;
52
import com.rackspace.cloud.files.api.client.ObjectVersion;
53
import com.rackspace.cloud.files.api.client.Permission;
54
import com.rackspace.cloud.servers.api.client.CloudServersException;
55
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
56

    
57
/**
58
 * 
59
 * @author Phillip Toohill
60
 * 
61
 */
62

    
63
public class ContainerObjectDetails extends CloudActivity {
64
        private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
65
        private static final int deleteObject = 0;
66
        private static final int restoreVersion = 1;
67
        private final String DOWNLOAD_DIRECTORY = "PithosPlus";
68

    
69
        private ContainerObjects objects;
70
        private String containerNames;
71
        private String otherUser;
72
        private String cdnURL;
73
        private String cdnEnabled;
74
        public String LOG = "ViewObject";
75
        private int bConver = 1048576;
76
        private int kbConver = 1024;
77
        private double megaBytes;
78
        private double kiloBytes;
79
        public Button previewButton;
80
        public Button downloadButton;
81
        private Boolean isDownloaded;
82
        private AndroidCloudApplication app;
83
        private DeleteObjectListenerTask deleteObjTask;
84
        private DownloadObjectListenerTask downloadObjTask;
85
        private List<ObjectVersion> versions = new ArrayList<ObjectVersion>();
86
        private boolean isReadOnly = false;
87
        private final List<String> metadataRemoved = new ArrayList<String>();
88
        private final Map<String,String> metadataAdded = new HashMap<String, String>();
89
        
90
        /** Called when the activity is first created. */
91
        @Override
92
        public void onCreate(Bundle savedInstanceState) {
93
                super.onCreate(savedInstanceState);
94
                trackPageView(GoogleAnalytics.PAGE_STORAGE_OBJECT);
95

    
96
                objects = (ContainerObjects) this.getIntent().getExtras()
97
                                .get("container");
98
                otherUser = (String) this.getIntent().getExtras()
99
                                .get("otherUser");
100
                Log.i(LOG,"OTHERUSER:"+otherUser);
101
                containerNames = (String) this.getIntent().getExtras()
102
                                .get("containerNames");
103
                cdnURL = (String) this.getIntent().getExtras().get("cdnUrl");
104
                cdnEnabled = (String) this.getIntent().getExtras().get("isCdnEnabled");
105
                
106
                setContentView(R.layout.viewobject);
107
                TabHost tabs = (TabHost) findViewById(R.id.tabhost2);
108

    
109
                tabs.setup();
110

    
111
                TabHost.TabSpec spec = tabs.newTabSpec("tag1");
112

    
113
                spec.setContent(R.id.details);
114
                spec.setIndicator("Details");
115
                tabs.addTab(spec);
116

    
117
                spec = tabs.newTabSpec("tag2");
118
                spec.setContent(R.id.metadata);
119
                spec.setIndicator("Metadata");
120
                tabs.addTab(spec);
121

    
122
                spec = tabs.newTabSpec("tag3");
123
                spec.setContent(R.id.sharing);
124
                spec.setIndicator("Sharing");
125
                tabs.addTab(spec);
126

    
127
                spec = tabs.newTabSpec("tag4");
128
                spec.setContent(R.id.versions);
129
                spec.setIndicator("Versions");
130
                tabs.addTab(spec);
131

    
132
                restoreState(savedInstanceState);
133
        }
134

    
135
        public boolean isFolder(){
136
                return objects.getContentType().startsWith("application/folder")||objects.getContentType().startsWith("application/directory");
137
        }
138
        @Override
139
        protected void onSaveInstanceState(Bundle outState) {
140
                super.onSaveInstanceState(outState);
141
                outState.putSerializable("container", objects);
142
                outState.putBoolean("isDownloaded", isDownloaded);
143
        }
144

    
145
        protected void restoreState(Bundle state) {
146
                super.restoreState(state);
147
                /*
148
                 * need reference to the app so you can access curDirFiles as well as
149
                 * processing status
150
                 */
151
                app = (AndroidCloudApplication) this.getApplication();
152

    
153
                if (state != null && state.containsKey("container")) {
154
                        objects = (ContainerObjects) state.getSerializable("container");
155
                }
156
                if(containerNames.equals(Container.MYSHARED)||containerNames.equals(Container.OTHERS))
157
                        loadObjectData();
158
                else
159
                        new ContainerObjectRefreshTask().execute();
160

    
161
                if (cdnEnabled.equals("true")) {
162
                        this.previewButton = (Button) findViewById(R.id.preview_button);
163
                        previewButton.setOnClickListener(new MyOnClickListener());
164
                } else {
165
                        this.previewButton = (Button) findViewById(R.id.preview_button);
166
                        previewButton.setVisibility(View.GONE);
167
                }
168

    
169
                if (state != null && state.containsKey("isDownloaded")) {
170
                        isDownloaded = state.getBoolean("isDownloaded");
171
                } else {
172
                        isDownloaded = fileIsDownloaded();
173
                }
174
                this.downloadButton = (Button) findViewById(R.id.download_button);
175
                if (isDownloaded) {
176
                        downloadButton.setText("Open File");
177
                } else {
178
                        downloadButton.setText("Download File");
179
                }
180
                downloadButton.setOnClickListener(new MyOnClickListener());
181

    
182
                if (app.isDeletingObject()) {
183
                        deleteObjTask = new DeleteObjectListenerTask();
184
                        deleteObjTask.execute();
185
                }
186

    
187
                if (app.isDownloadingObject()) {
188
                        downloadObjTask = new DownloadObjectListenerTask();
189
                        downloadObjTask.execute();
190
                }
191

    
192
        }
193

    
194
        @Override
195
        protected void onStop() {
196
                super.onStop();
197

    
198
                /*
199
                 * Need to stop running listener task if we exit
200
                 */
201
                if (deleteObjTask != null) {
202
                        deleteObjTask.cancel(true);
203
                }
204

    
205
                if (downloadObjTask != null) {
206
                        downloadObjTask.cancel(true);
207
                }
208
        }
209

    
210
        private void loadObjectData() {
211
                setTitle("Details: " +objects.getCName());
212
                metadataRemoved.clear();
213
                metadataAdded.clear();
214
                if(Container.MYSHARED.equals(objects.getContainerName())||Container.MYSHARED.equals(containerNames)){
215
                        isReadOnly = true;
216
                        
217
                }
218
                // Object Name
219
                TextView name = (TextView) findViewById(R.id.view_container_name);
220
                name.setText(objects.getCName().toString());
221

    
222
                // File size
223
                if (objects.getBytes() >= bConver) {
224
                        megaBytes = Math.abs(objects.getBytes() / bConver + 0.2);
225
                        TextView sublabel = (TextView) findViewById(R.id.view_file_bytes);
226
                        sublabel.setText(megaBytes + " MB");
227
                } else if (objects.getBytes() >= kbConver) {
228
                        kiloBytes = Math.abs(objects.getBytes() / kbConver + 0.2);
229
                        TextView sublabel = (TextView) findViewById(R.id.view_file_bytes);
230
                        sublabel.setText(kiloBytes + " KB");
231
                } else {
232
                        TextView sublabel = (TextView) findViewById(R.id.view_file_bytes);
233
                        sublabel.setText(objects.getBytes() + " B");
234
                }
235

    
236
                // Content Type
237
                TextView cType = (TextView) findViewById(R.id.view_content_type);
238
                if(objects.getContentType()!=null)
239
                        cType.setText(objects.getContentType().toString());
240
                else
241
                        cType.setText("");
242

    
243
                // Last Modification date
244
                String strDate = objects.getLastMod();
245
                strDate = strDate.substring(0, strDate.indexOf('T'));
246

    
247
                TextView lastmod = (TextView) findViewById(R.id.view_file_modification);
248
                lastmod.setText(strDate);
249
                rebuildMetadataList();
250
                if(isFolder()){
251
                        findViewById(R.id.download_text).setVisibility(View.GONE);
252
                        findViewById(R.id.linearLayout1).setVisibility(View.GONE);
253
                        findViewById(R.id.layoutPublic).setVisibility(View.GONE);
254
                }
255
                rebuildPermissionList();
256
                try {
257
                        versions = new ContainerObjectManager(getApplicationContext())
258
                                        .getObjectVersions(objects.getContainerName(),
259
                                                        objects.getCName(), otherUser);
260
                        rebuildVersionList();
261
                } catch (CloudServersException e) {
262
                        // TODO Auto-generated catch block
263
                        e.printStackTrace();
264
                }
265
                
266
        }
267
        
268
        private void rebuildMetadataList() {
269
                Button newmetadata = (Button)findViewById(R.id.newMetadata);
270
                if(isReadOnly)
271
                        newmetadata.setVisibility(View.GONE);
272
                newmetadata.setOnClickListener(new OnClickListener() {
273
                        
274
                        @Override
275
                        public void onClick(View arg0) {
276
                                final AlertDialog.Builder alert = new AlertDialog.Builder(ContainerObjectDetails.this);
277
                                alert.setTitle("Add Metadata");
278
                                LinearLayout ll = new LinearLayout(ContainerObjectDetails.this);
279
                                ll.setOrientation(LinearLayout.VERTICAL);
280

    
281
                                final EditText input = new EditText(ContainerObjectDetails.this);
282
                                final EditText input2 = new EditText(ContainerObjectDetails.this);
283
                                ll.addView(input);
284
                                ll.addView(input2);
285
                                alert.setView(ll);
286
                                alert.setPositiveButton("Create", new DialogInterface.OnClickListener() {
287
                                        public void onClick(DialogInterface dialog, int whichButton) {
288
                                                String key = input.getText().toString().trim();
289
                                                String value = input2.getText().toString().trim();
290
                                                addMetatadata(key, value);
291
                                        }
292
                                });
293
                                
294
                                alert.setNegativeButton("Cancel",
295
                                                new DialogInterface.OnClickListener() {
296
                                        public void onClick(DialogInterface dialog, int whichButton) {
297
                                                dialog.cancel();
298
                                        }
299
                                });
300
                                alert.show();
301
                        }
302
                });
303
                LayoutInflater layoutInflater = LayoutInflater
304
                                .from(ContainerObjectDetails.this);
305
                final LinearLayout metadata = (LinearLayout) findViewById(R.id.metadataList);
306
                if (metadata.getChildCount() > 0)
307
                        metadata.removeViews(0, metadata.getChildCount());
308
                metadata.removeAllViews();
309

    
310
                if (objects.getMetadata() != null) {
311
                        int i = 0;
312
                        Iterator<Entry<String, String>> it = objects.getMetadata()
313
                                        .entrySet().iterator();
314
                        while (it.hasNext()) {
315
                                final Entry<String, String> perm = it.next();
316
                                final View v = layoutInflater.inflate(R.layout.metadatarow,
317
                                                null);
318
                                populateMetadataList(perm, v, metadata, i);
319
                                i++;
320
                        }
321
                }
322
        }
323
        
324
        private void addMetatadata(String key, String value){
325
                if(objects.getMetadata()==null)
326
                        objects.setMetadata(new HashMap<String, String>());
327
                metadataAdded.put(key,value);
328
                objects.getMetadata().put(key, value);
329
                rebuildMetadataList();
330
        }
331

    
332
        private void populateMetadataList(final Entry<String, String> metadata,
333
                        final View v, final LinearLayout properties, int i) {
334
                properties.addView(v, i);
335
                Log.d(LOG, i + " " + metadata.getKey() + " " + metadata.getValue());
336
                ((TextView) v.findViewById(R.id.mkey)).setText(metadata.getKey());
337
                ((TextView) v.findViewById(R.id.mvalue)).setText(metadata.getValue());
338
                if(isReadOnly)
339
                        v.findViewById(R.id.remove).setVisibility(View.GONE);
340
                ((ImageButton) v.findViewById(R.id.remove))
341
                .setOnClickListener(new OnClickListener() {
342

    
343
                        @Override
344
                        public void onClick(View v1) {
345
                                properties.removeView(v);
346
                                metadataRemoved.add(metadata.getKey());
347
                                objects.getMetadata().remove(metadata.getKey());
348
                                
349

    
350
                        }
351
                });
352
        }
353

    
354
        private void rebuildPermissionList() {
355
                Button newmetadata = (Button)findViewById(R.id.newPermission);
356
                CheckBox readForAll = (CheckBox)findViewById(R.id.folderPublic);
357
                if(isReadOnly){
358
                        newmetadata.setVisibility(View.GONE);
359
                        readForAll.setEnabled(false);
360
                }
361
                objects.setPublicf(objects.getIsPublic()!=null);
362
                readForAll.setChecked(objects.isPublicf());
363

    
364
                readForAll.setOnCheckedChangeListener(new OnCheckedChangeListener() {
365

    
366
                                        @Override
367
                                        public void onCheckedChanged(CompoundButton buttonView,
368
                                                        boolean isChecked) {
369
                                                objects.setPublicf(isChecked);
370

    
371
                                        }
372
                                });
373
                newmetadata.setOnClickListener(new OnClickListener() {
374

    
375
                        @Override
376
                        public void onClick(View v) {
377
                                showAddDialog();                                
378
                        }
379
                        
380
                });
381
                LayoutInflater layoutInflater = LayoutInflater
382
                                .from(ContainerObjectDetails.this);
383
                final LinearLayout properties = (LinearLayout) findViewById(R.id.permissionsList);
384
                if (properties.getChildCount() > 0)
385
                        properties.removeViews(0, properties.getChildCount());
386
                properties.removeAllViews();
387
                Iterator<Permission> it = null;
388
                if (objects.getPermissions() != null) {
389
                        it = objects.getPermissions().iterator();
390
                        int i = 0;
391
                        while (it.hasNext()) {
392
                                final Permission perm = it.next();
393
                                final View v = layoutInflater.inflate(R.layout.propertiesrow,
394
                                                null);
395
                                populatePermissionList(perm, v, properties, i);
396
                                i++;
397
                        }
398
                }
399
        }
400

    
401
        private void populatePermissionList(final Permission perm, final View v,
402
                        final LinearLayout properties, int i) {
403

    
404
                properties.addView(v, i);
405
                if(isReadOnly){
406
                        v.findViewById(R.id.remove).setVisibility(View.GONE);
407
                        ((CheckBox) v.findViewById(R.id.read)).setEnabled(false);
408
                        ((CheckBox) v.findViewById(R.id.write)).setEnabled(false);
409
                }
410
                
411
                ((TextView) v.findViewById(R.id.ownerName)).setText(perm.getUser()==null?perm.getGroup()+":":perm.getUser());
412
                ((CheckBox) v.findViewById(R.id.read)).setChecked(perm.isRead());
413
                ((CheckBox) v.findViewById(R.id.write)).setChecked(perm.isWrite());
414

    
415
                ((CheckBox) v.findViewById(R.id.read))
416
                                .setOnCheckedChangeListener(new OnCheckedChangeListener() {
417

    
418
                                        @Override
419
                                        public void onCheckedChanged(CompoundButton buttonView,
420
                                                        boolean isChecked) {
421
                                                perm.setRead(isChecked);
422

    
423
                                        }
424
                                });
425
                ((CheckBox) v.findViewById(R.id.write))
426
                                .setOnCheckedChangeListener(new OnCheckedChangeListener() {
427

    
428
                                        @Override
429
                                        public void onCheckedChanged(CompoundButton buttonView,
430
                                                        boolean isChecked) {
431
                                                perm.setWrite(isChecked);
432

    
433
                                        }
434
                                });
435
                ((Button) v.findViewById(R.id.remove))
436
                                .setOnClickListener(new OnClickListener() {
437

    
438
                                        @Override
439
                                        public void onClick(View v1) {
440
                                                properties.removeView(v);
441
                                                objects.getPermissions().remove(perm);
442

    
443
                                        }
444
                                });
445
        }
446
        
447
        private void addPermission(boolean group, String userOrGroup){
448
                if(objects.getPermissions()==null)
449
                        objects.setPermissions(new ArrayList<Permission>());
450
                Permission np = new Permission();
451
                if(group)
452
                        np.setGroup(userOrGroup);
453
                else
454
                        np.setUser(userOrGroup);
455
                objects.getPermissions().add(np);
456
                rebuildPermissionList();
457
        }
458
        private void showAddDialog(){
459
                final CharSequence[] items = {"Add User", "Add Group"};
460

    
461
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
462
                builder.setTitle("User Or Group");
463
                builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
464
                    public void onClick(DialogInterface dialog, int item) {
465
                            boolean user;
466
                       if(item ==0){
467
                               user=true;
468
                       }
469
                       else
470
                               user=false;
471
                       populateAddDialog(user);
472
                       dialog.dismiss();
473
                       
474
                    }
475
                });
476
                AlertDialog alert2 = builder.create();
477
                alert2.show();
478
                
479
        }
480
        
481
        private void populateAddDialog(final boolean user){
482
                final AlertDialog.Builder alert = new AlertDialog.Builder(ContainerObjectDetails.this);
483
               if(user){
484
                       alert.setTitle("Add User");
485
                       final EditText input = new EditText(ContainerObjectDetails.this);
486
                input.setTextColor(Color.BLACK);
487
                    
488
                    alert.setView(input);
489
                    
490
                    alert.setPositiveButton("Add", new DialogInterface.OnClickListener() {
491
                            public void onClick(DialogInterface dialog, int whichButton) {
492
                                    String value = input.getText().toString().trim();
493
                                    addPermission(false, value);
494
                                    
495
                            }
496
                    });
497

    
498
                    alert.setNegativeButton("Cancel",
499
                                    new DialogInterface.OnClickListener() {
500
                                            public void onClick(DialogInterface dialog, int whichButton) {
501
                                                    dialog.cancel();
502
                                            
503
                                            }
504
                                    });
505
                    alert.show();
506
               }
507
               else{
508
                       AlertDialog.Builder builder = new AlertDialog.Builder(this);
509
                    builder.setTitle("Add Group");
510
                    builder.setSingleChoiceItems(getGroupNames().toArray(new String[0]), -1, new DialogInterface.OnClickListener() {
511
                        public void onClick(DialogInterface dialog, int item) {
512
                                addPermission(true, getGroupNames().get(item));
513
                           dialog.dismiss();
514
                           
515
                        }
516
                    });
517
                    AlertDialog alert2 = builder.create();
518
                    alert2.show();
519
               }
520
            
521
        }
522
        
523
        public List<String> getGroupNames(){
524
                List<String> result = new ArrayList<String>();
525
                List<GroupResource> groups = ((AndroidCloudApplication)getApplication()).getGroups();
526
                for(GroupResource g : groups){
527
                        result.add(g.getName());
528
                }
529
                return result;
530
        }
531
        
532
        private void rebuildVersionList() {
533
                LayoutInflater layoutInflater = LayoutInflater
534
                                .from(ContainerObjectDetails.this);
535
                final LinearLayout properties = (LinearLayout) findViewById(R.id.versionsList);
536
                if (properties.getChildCount() > 0)
537
                        properties.removeViews(0, properties.getChildCount());
538
                properties.removeAllViews();
539
                Iterator<ObjectVersion> it;
540
                // Collections.reverse(versions);
541
                it = versions.iterator();
542
                int i = 0;
543
                while (it.hasNext()) {
544
                        final ObjectVersion perm = it.next();
545
                        final View v = layoutInflater.inflate(R.layout.versionsrow, null);
546
                        populateVersionList(perm, v, properties, i);
547
                        i++;
548
                }
549
        }
550
        String selectedVersion=null;
551
        private void populateVersionList(final ObjectVersion perm, final View v,
552
                        final LinearLayout properties, int i) {
553

    
554
                properties.addView(v, i);
555

    
556
                ((TextView) v.findViewById(R.id.versionName)).setText("Version: "
557
                                + perm.getVersion());
558
                
559
                ((TextView) v.findViewById(R.id.versionModified)).setText("Modified: "
560
                                + perm.getDateString());
561
                if (versions.size() == 1 || isReadOnly) {
562
                        // ((Button)
563
                        // v.findViewById(R.id.vremove)).setVisibility(View.INVISIBLE);
564
                        ((Button) v.findViewById(R.id.vrestore))
565
                                        .setVisibility(View.INVISIBLE);
566
                }
567
                /*
568
                 * ((Button) v.findViewById(R.id.vremove)) .setOnClickListener(new
569
                 * OnClickListener() {
570
                 * 
571
                 * @Override public void onClick(View v1) { Log.d("PERMS",
572
                 * perm.getUri()); try { new GssHttpCommands(getDroidApplication()
573
                 * .getUserDetails
574
                 * ()).deleteFolder(perm.getUri()+"?version="+perm.getVersion()); }
575
                 * catch (SystemErrorException e) { // TODO Auto-generated catch block
576
                 * e.printStackTrace(); } catch (GssHttpException e) { // TODO
577
                 * Auto-generated catch block e.printStackTrace(); }
578
                 * getFileTask().execute(res.getUri()); //properties.removeView(v);
579
                 * 
580
                 * } });
581
                 */
582
                ((Button) v.findViewById(R.id.vrestore))
583
                                .setOnClickListener(new OnClickListener() {
584

    
585
                                        @Override
586
                                        public void onClick(View v1) {
587
                                                selectedVersion = String.valueOf(perm.getVersion());
588
                                                showDialog(restoreVersion);
589

    
590
                                        }
591
                                });
592
                ((Button) v.findViewById(R.id.vdownload))
593
                                .setOnClickListener(new OnClickListener() {
594

    
595
                                        @Override
596
                                        public void onClick(View v1) {
597
                                                if (storageIsReady()) {
598
                                                        new ContainerObjectDownloadTask().execute(String.valueOf(perm.getVersion()));
599
                                                } else {
600
                                                        showAlert("Error", "Storage not found.");
601
                                                }
602
                                                // getDownloadTask().execute(perm.getUri()+"?version="+perm.getVersion());
603
                                                // properties.removeView(v);
604

    
605
                                        }
606
                                });
607
        }
608

    
609
        private class MyOnClickListener implements View.OnClickListener {
610
                @Override
611
                public void onClick(View v) {
612
                        if (v.equals(findViewById(R.id.preview_button))) {
613
                                Intent viewIntent = new Intent("android.intent.action.VIEW",
614
                                                Uri.parse(cdnURL + "/" + objects.getCName()));
615
                                startActivity(viewIntent);
616
                        }
617
                        /*
618
                         * need to perform different functions based on if the file is in
619
                         * the devices filesystem
620
                         */
621
                        if (v.equals(findViewById(R.id.download_button))) {
622
                                if (!isDownloaded) {
623
                                        if (storageIsReady()) {
624
                                                new ContainerObjectDownloadTask().execute();
625
                                        } else {
626
                                                showAlert("Error", "Storage not found.");
627
                                        }
628
                                } else {
629
                                        openFile();
630
                                }
631
                        }
632
                }
633
        }
634

    
635
        // Create the Menu options
636
        @Override
637
        public boolean onCreateOptionsMenu(Menu menu) {
638
                super.onCreateOptionsMenu(menu);
639
                MenuInflater inflater = getMenuInflater();
640
                inflater.inflate(R.menu.container_object_list_menu, menu);
641
                menu.findItem(R.id.delete_object).setVisible(!isReadOnly);
642
                menu.findItem(R.id.save).setVisible(!isReadOnly);
643
                return true;
644
        }
645

    
646
        @Override
647
        public boolean onOptionsItemSelected(MenuItem item) {
648
                switch (item.getItemId()) {
649
                case R.id.delete_object:
650
                        showDialog(deleteObject);
651
                        return true;
652
                case R.id.refresh:
653
                        if(containerNames.equals(Container.MYSHARED)||containerNames.equals(Container.OTHERS))
654
                                loadObjectData();
655
                        else
656
                                new ContainerObjectRefreshTask().execute();
657

    
658
                        return true;
659
                case R.id.save:
660
                        new ContainerObjectUpdateTask().execute();
661
                        return true;
662
                }
663
                return false;
664
        }
665

    
666
        @Override
667
        protected Dialog onCreateDialog(int id) {
668
                switch (id) {
669
                case deleteObject:
670
                        return new AlertDialog.Builder(ContainerObjectDetails.this)
671
                                        .setIcon(R.drawable.alert_dialog_icon)
672
                                        .setTitle("Delete File")
673
                                        .setMessage("Are you sure you want to delete this file?")
674
                                        .setPositiveButton("Delete File",
675
                                                        new DialogInterface.OnClickListener() {
676
                                                                public void onClick(DialogInterface dialog,
677
                                                                                int whichButton) {
678
                                                                        // User clicked OK so do some stuff
679
                                                                        trackEvent(GoogleAnalytics.CATEGORY_FILE,
680
                                                                                        GoogleAnalytics.EVENT_DELETE, "",
681
                                                                                        -1);
682
                                                                        new ContainerObjectDeleteTask()
683
                                                                                        .execute((Void[]) null);
684
                                                                }
685
                                                        })
686
                                        .setNegativeButton("Cancel",
687
                                                        new DialogInterface.OnClickListener() {
688
                                                                public void onClick(DialogInterface dialog,
689
                                                                                int whichButton) {
690
                                                                        // User clicked Cancel so do some stuff
691
                                                                }
692
                                                        }).create();
693
                case restoreVersion:
694
                        return new AlertDialog.Builder(ContainerObjectDetails.this)
695
                                        .setIcon(R.drawable.alert_dialog_icon)
696
                                        .setTitle("Restore Version")
697
                                        .setMessage("Are you sure you want to restore this version?")
698
                                        .setPositiveButton("Restore Version",
699
                                                        new DialogInterface.OnClickListener() {
700
                                                                public void onClick(DialogInterface dialog,
701
                                                                                int whichButton) {
702
                                                                        // User clicked OK so do some stuff
703
                                                                        /*trackEvent(GoogleAnalytics.CATEGORY_FILE,
704
                                                                                        GoogleAnalytics.EVENT_DELETE, "",
705
                                                                                        -1);*/
706
                                                                        new VersionRestoreTask()
707
                                                                                        .execute(selectedVersion);
708
                                                                }
709
                                                        })
710
                                        .setNegativeButton("Cancel",
711
                                                        new DialogInterface.OnClickListener() {
712
                                                                public void onClick(DialogInterface dialog,
713
                                                                                int whichButton) {
714
                                                                        // User clicked Cancel so do some stuff
715
                                                                }
716
                                                        }).create();
717
                
718
                }
719
                
720
                return null;
721
        }
722

    
723
        /**
724
         * @return the file
725
         */
726
        public ContainerObjects getViewFile() {
727
                return objects;
728
        }
729

    
730
        /**
731
         * @param File
732
         *            the file to set
733
         */
734
        public void setViewFile(ContainerObjects object) {
735
                this.objects = object;
736
        }
737

    
738
        /*
739
         * returns false if external storage is not avaliable (if its mounted,
740
         * missing, read-only, etc) from:
741
         * http://developer.android.com/guide/topics/data
742
         * /data-storage.html#filesExternal
743
         */
744
        private boolean storageIsReady() {
745
                boolean mExternalStorageAvailable = false;
746
                boolean mExternalStorageWriteable = false;
747
                String state = Environment.getExternalStorageState();
748

    
749
                if (Environment.MEDIA_MOUNTED.equals(state)) {
750
                        // We can read and write the media
751
                        mExternalStorageAvailable = mExternalStorageWriteable = true;
752
                } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
753
                        // We can only read the media
754
                        mExternalStorageAvailable = true;
755
                        mExternalStorageWriteable = false;
756
                } else {
757
                        // Something else is wrong. It may be one of many other states, but
758
                        // all we need
759
                        // to know is we can neither read nor write
760
                        mExternalStorageAvailable = mExternalStorageWriteable = false;
761
                }
762
                return mExternalStorageAvailable && mExternalStorageWriteable;
763
        }
764

    
765
        private boolean fileIsDownloaded() {
766
                if (storageIsReady()) {
767
                        String fileName = Environment.getExternalStorageDirectory()
768
                                        .getPath() + "/PithosPlus/" + objects.getCName();
769
                        File f = new File(fileName);
770
                        return f.isFile();
771
                }
772
                return false;
773
        }
774

    
775
        private void openFile() {
776
                File object = new File(Environment.getExternalStorageDirectory()
777
                                .getPath() + "/PithosPlus/" + objects.getCName());
778
                Intent myIntent = new Intent(android.content.Intent.ACTION_VIEW);
779
                File file = new File(object.getAbsolutePath());
780
                String extension = android.webkit.MimeTypeMap
781
                                .getFileExtensionFromUrl(Uri.fromFile(file).toString());
782
                String mimetype = android.webkit.MimeTypeMap.getSingleton()
783
                                .getMimeTypeFromExtension(extension);
784
                myIntent.setDataAndType(Uri.fromFile(file), mimetype);
785
                // myIntent.setData(Uri.fromFile(file));
786
                try {
787
                        startActivity(myIntent);
788
                } catch (Exception e) {
789
                        Toast.makeText(this, "Could not open file.", Toast.LENGTH_SHORT)
790
                                        .show();
791
                }
792
        }
793

    
794
        // Task's
795
        
796
        private class ContainerObjectRefreshTask extends
797
                                AsyncTask<Void, Void, ContainerObjects> {
798
                        
799
                        private CloudServersException exception;
800
                        
801
                        protected void onPreExecute() {
802
                                showDialog();
803
                                app.setDeleteingObject(true);
804
                                deleteObjTask = new DeleteObjectListenerTask();
805
                                deleteObjTask.execute();
806
                        }
807
                        
808
                        @Override
809
                        protected ContainerObjects doInBackground(Void... arg0) {
810
                                ContainerObjects bundle = null;
811
                                try {
812
                                        if(otherUser==null)
813
                                                bundle = (new ContainerObjectManager(getContext()))
814
                                                        .executeHead(containerNames, objects.getCName());
815
                                        else
816
                                                bundle = (new ContainerObjectManager(getContext()))
817
                                                .executeHead(containerNames, objects.getCName(), otherUser);
818
                                } catch (CloudServersException e) {
819
                                        exception = e;
820
                                }
821
                        
822
                                return bundle;
823
                        }
824
                        
825
                        @Override
826
                        protected void onPostExecute(ContainerObjects bundle) {
827
                                hideDialog();
828
                                if (bundle != null) {
829
                                        objects=bundle;
830
                                        loadObjectData();
831
                                } else if (exception != null) {
832
                                        showToast("There was a problem refreshing your file: "
833
                                                        + exception.getMessage());
834
                                }
835
                        }
836
        }
837

    
838
        private class ContainerObjectDeleteTask extends
839
                        AsyncTask<Void, Void, HttpBundle> {
840

    
841
                private CloudServersException exception;
842

    
843
                protected void onPreExecute() {
844
                        showDialog();
845
                        app.setDeleteingObject(true);
846
                        deleteObjTask = new DeleteObjectListenerTask();
847
                        deleteObjTask.execute();
848
                }
849

    
850
                @Override
851
                protected HttpBundle doInBackground(Void... arg0) {
852
                        HttpBundle bundle = null;
853
                        try {
854
                                bundle = (new ContainerObjectManager(getContext()))
855
                                                .deleteObject(containerNames, objects.getCName(),otherUser);
856
                        } catch (CloudServersException e) {
857
                                exception = e;
858
                        }
859

    
860
                        return bundle;
861
                }
862

    
863
                @Override
864
                protected void onPostExecute(HttpBundle bundle) {
865
                        app.setDeleteingObject(false);
866
                        hideDialog();
867
                        HttpResponse response = bundle.getResponse();
868
                        if (response != null) {
869
                                int statusCode = response.getStatusLine().getStatusCode();
870
                                if (statusCode == 204) {
871
                                        // handled by listener
872
                                } else {
873
                                        CloudServersException cse = parseCloudServersException(response);
874
                                        if ("".equals(cse.getMessage())) {
875
                                                showError("There was a problem deleting your File.",
876
                                                                bundle);
877
                                        } else {
878
                                                showError("There was a problem deleting your file: "
879
                                                                + cse.getMessage(), bundle);
880
                                        }
881
                                }
882
                        } else if (exception != null) {
883
                                showError("There was a problem deleting your file: "
884
                                                + exception.getMessage(), bundle);
885
                        }
886
                }
887
        }
888

    
889
        private class ContainerObjectDownloadTask extends
890
                        AsyncTask<String, Void, HttpBundle> {
891

    
892
                private CloudServersException exception;
893

    
894
                @Override
895
                protected void onPreExecute() {
896
                        showDialog();
897
                        app.setDownloadingObject(true);
898
                        downloadObjTask = new DownloadObjectListenerTask();
899
                        downloadObjTask.execute();
900
                }
901

    
902
                @Override
903
                protected HttpBundle doInBackground(String... arg0) {
904
                        HttpBundle bundle = null;
905
                        try {
906
                                if(arg0.length==1 && arg0[0]!=null)
907
                                        bundle = (new ContainerObjectManager(getContext())).getObject(
908
                                                        containerNames, objects.getCName(),arg0[0], otherUser);
909
                                else
910
                                        bundle = (new ContainerObjectManager(getContext())).getObject(
911
                                                containerNames, objects.getCName(),otherUser);
912
                        } catch (CloudServersException e) {
913
                                exception = e;
914
                        }
915
                        return bundle;
916
                }
917

    
918
                @Override
919
                protected void onPostExecute(HttpBundle bundle) {
920
                        
921
                        
922
                        HttpResponse response = bundle.getResponse();
923
                        if (response != null) {
924
                                int statusCode = response.getStatusLine().getStatusCode();
925
                                if (statusCode == 200) {
926
                                        setResult(Activity.RESULT_OK);
927
                                        HttpEntity entity = response.getEntity();
928
                                        app.setDownloadedEntity(entity);
929
                                } else {
930
                                        CloudServersException cse = parseCloudServersException(response);
931
                                        if ("".equals(cse.getMessage())) {
932
                                                showError("There was a problem downloading your File.",
933
                                                                bundle);
934
                                        } else {
935
                                                showError("There was a problem downloading your file: "
936
                                                                + cse.getMessage(), bundle);
937
                                        }
938
                                }
939
                        } else if (exception != null) {
940
                                showError("There was a problem downloading your file: "
941
                                                + exception.getMessage(), bundle);
942
                        }
943
                        app.setDownloadingObject(false);
944
                }
945
        }
946

    
947
        private class DeleteObjectListenerTask extends AsyncTask<Void, Void, Void> {
948

    
949
                @Override
950
                protected Void doInBackground(Void... arg1) {
951

    
952
                        while (app.isDeletingObject()) {
953
                                // wait for process to finish
954
                                // or have it be canceled
955
                                if (deleteObjTask.isCancelled()) {
956
                                        return null;
957
                                }
958
                        }
959
                        return null;
960
                }
961

    
962
                /*
963
                 * when no longer processing, time to load the new files
964
                 */
965
                @Override
966
                protected void onPostExecute(Void arg1) {
967
                        hideDialog();
968
                        setResult(99);
969
                        finish();
970
                }
971
        }
972

    
973
        private class DownloadObjectListenerTask extends
974
                        AsyncTask<Void, Void, Void> {
975

    
976
                @Override
977
                protected Void doInBackground(Void... arg1) {
978

    
979
                        while (app.isDownloadingObject()) {
980
                                // wait for process to finish
981
                                // or have it be canceled
982
                                if (downloadObjTask.isCancelled()) {
983
                                        return null;
984
                                }
985
                        }
986
                        return null;
987
                }
988

    
989
                /*
990
                 * when no longer processing, time to load the new files
991
                 */
992
                @Override
993
                protected void onPostExecute(Void arg1) {
994
                        
995
                        try {
996
                                //TODO: run in background
997
                                if (writeFile(app.getDownloadedEntity().getContent())) {
998
                                        downloadButton.setText("Open File");
999
                                        isDownloaded = true;
1000
                                } else {
1001
                                        showAlert("Error",
1002
                                                        "There was a problem downloading your file.");
1003
                                }
1004

    
1005
                        } catch (IOException e) {
1006
                                showAlert("Error", "There was a problem downloading your file.");
1007
                                e.printStackTrace();
1008
                        } catch (Exception e) {
1009
                                showAlert("Error", "There was a problem downloading your file.");
1010
                                e.printStackTrace();
1011
                        }
1012
                        hideDialog();
1013
                }
1014
        }
1015

    
1016
        private boolean writeFile(InputStream in) {
1017
                String directoryName = Environment.getExternalStorageDirectory()
1018
                                .getPath();
1019
                File f = new File(directoryName, DOWNLOAD_DIRECTORY);
1020
                Log.i(LOG,directoryName);
1021
                if (!f.isDirectory()) {
1022
                        if (!f.mkdir()) {
1023
                                return false;
1024
                        }
1025
                }
1026
                Log.i(LOG,objects.toString());
1027
                //String filename = directoryName + "/" + objects.getName();
1028
                StringTokenizer str = new StringTokenizer(objects.getCName(),"/");
1029
                String path="";
1030
                String fname="";
1031
                int count = str.countTokens();
1032
                Log.i(LOG,"object is: "+objects.getCName()+" "+count);
1033
                for(int i=0;i<count;i++){
1034
                        if(i<(count-1)){
1035
                                path = path+str.nextToken()+"/";
1036
                        }
1037
                        else
1038
                                fname=str.nextToken();
1039
                }
1040
                Log.i(LOG,"Path is:"+path);
1041
                Log.i(LOG,"Fname is:"+fname);
1042
                File object;
1043
                if("".equals(path)){
1044
                        object = new File(f,fname);
1045
                }
1046
                else{
1047
                        File t = new File(f,path);
1048
                        t.mkdirs();
1049
                        object = new File(t,fname);
1050
                }
1051
                
1052
                
1053
                BufferedOutputStream bos = null;
1054

    
1055
                try {
1056
                        FileOutputStream fos = new FileOutputStream(object);
1057
                        copy(in, fos);
1058
                } catch (IOException e) {
1059
                        e.printStackTrace();
1060
                } finally {
1061
                        if (bos != null) {
1062
                                try {
1063
                                        bos.flush();
1064
                                        bos.close();
1065
                                } catch (IOException e) {
1066
                                        // TODO Auto-generated catch block
1067
                                        e.printStackTrace();
1068
                                }
1069
                        }
1070
                }
1071
                return true;
1072
        }
1073

    
1074
        public static long copy(InputStream input, OutputStream output) throws IOException {
1075
                
1076
                byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
1077
                long count = 0;
1078
                int n = 0;
1079
                try{
1080
                        while (-1 != (n = input.read(buffer))) {
1081
                                output.write(buffer, 0, n);
1082
                                count += n;
1083
                                //monitor.setCurrent(count);
1084
                        }
1085
                }
1086
                finally{
1087
                        input.close();
1088
                        output.close();
1089
                }
1090
                return count;
1091
        }
1092
        
1093
        @Override
1094
        public void onBackPressed() {
1095
                
1096
                //TODO: perform update
1097
                super.onBackPressed();
1098
        }
1099
        
1100
        
1101
        
1102
        
1103
        private class ContainerObjectUpdateTask extends
1104
                        AsyncTask<Void, Void, HttpBundle> {
1105
                
1106
                private CloudServersException exception;
1107
                
1108
                protected void onPreExecute() {
1109
                        showDialog();
1110
                }
1111
                
1112
                @Override
1113
                protected HttpBundle doInBackground(Void... arg0) {
1114
                        HttpBundle bundle = null;
1115
                        try {
1116
                                bundle = saveObject();
1117
                        } catch (CloudServersException e) {
1118
                                exception = e;
1119
                        }
1120
                
1121
                        return bundle;
1122
                }
1123
                
1124
                @Override
1125
                protected void onPostExecute(HttpBundle bundle) {
1126
                        hideDialog();
1127
                        HttpResponse response = bundle.getResponse();
1128
                        if (response != null) {
1129
                                int statusCode = response.getStatusLine().getStatusCode();
1130
                                if (statusCode == 202) {
1131
                                        hideDialog();
1132
                                        setResult(99);
1133
                                        finish();
1134
                                } else {
1135
                                        CloudServersException cse = parseCloudServersException(response);
1136
                                        if ("".equals(cse.getMessage())) {
1137
                                                showError("There was a problem deleting your File.",
1138
                                                                bundle);
1139
                                        } else {
1140
                                                showError("There was a problem deleting your file: "
1141
                                                                + cse.getMessage(), bundle);
1142
                                        }
1143
                                }
1144
                        } else if (exception != null) {
1145
                                showError("There was a problem deleting your file: "
1146
                                                + exception.getMessage(), bundle);
1147
                        }
1148
                }
1149
        }
1150
        
1151
        private class VersionRestoreTask extends
1152
                                AsyncTask<String, Void, HttpBundle> {
1153
                        
1154
                        private CloudServersException exception;
1155
                        
1156
                        protected void onPreExecute() {
1157
                                showDialog();
1158
                        }
1159
                        
1160
                        @Override
1161
                        protected HttpBundle doInBackground(String... arg0) {
1162
                                HttpBundle bundle = null;
1163
                                try {
1164
                                        bundle = restoreVersion(arg0[0]);
1165
                                } catch (CloudServersException e) {
1166
                                        e.printStackTrace();
1167
                                        exception = e;
1168
                                }
1169
                        
1170
                                return bundle;
1171
                        }
1172
                        
1173
                        @Override
1174
                        protected void onPostExecute(HttpBundle bundle) {
1175
                                hideDialog();
1176
                                HttpResponse response = null;
1177
                                if(bundle!=null)
1178
                                        response= bundle.getResponse();
1179
                                if (response != null) {
1180
                                        int statusCode = response.getStatusLine().getStatusCode();
1181
                                        if (statusCode == 204||statusCode==202) {
1182
                                                hideDialog();
1183
                                                setResult(99);
1184
                                                finish();
1185
                                        } else {
1186
                                                CloudServersException cse = parseCloudServersException(response);
1187
                                                if ("".equals(cse.getMessage())) {
1188
                                                        showError("There was a problem deleting your File.",
1189
                                                                        bundle);
1190
                                                } else {
1191
                                                        showError("There was a problem deleting your file: "
1192
                                                                        + cse.getMessage(), bundle);
1193
                                                }
1194
                                        }
1195
                                } else if (exception != null) {
1196
                                        showError("There was a problem deleting your file: "
1197
                                                        + exception.getMessage(), bundle);
1198
                                }
1199
                        }
1200
                }
1201
        
1202
        public HttpBundle saveObject() throws CloudServersException{
1203
                Map<String,String> headers = new HashMap<String,String>();
1204
                if(objects.getMetadata()!=null)
1205
                        for(Entry<String,String> entry : objects.getMetadata().entrySet()){
1206
                                headers.put("X-Object-Meta-"+entry.getKey(), entry.getValue());
1207
                        }
1208
                for(String s : metadataRemoved){
1209
                        headers.put("X-Object-Meta-"+s, "~");
1210
                }
1211
                if(!isFolder())
1212
                        headers.put("X-Object-Public", String.valueOf(objects.isPublicf()));
1213
                String read ="";
1214
                String write="";
1215
                for(Permission p : objects.getPermissions()){
1216
                        if(p.isWrite()){
1217
                                if(!write.equals("")){
1218
                                        write = write+",";
1219
                                }
1220
                                write = write + (p.getGroup()==null?p.getUser():p.getGroup());
1221
                        }
1222
                        else if(p.isRead()){
1223
                                if(!read.equals("")){
1224
                                        read = read+",";
1225
                                }
1226
                                read = read + (p.getGroup()==null?p.getUser():p.getGroup());
1227
                        }
1228
                        
1229
                        
1230
                }
1231
                Log.d(LOG,"read:"+read);
1232
                Log.d(LOG,"write:"+write);
1233
                String permString = "";
1234
                if(!"".equals(read)){
1235
                        permString = "read="+read;
1236
                }
1237
                if(!"".equals(write)){
1238
                        if(!"".equals(permString))
1239
                                permString = permString+";write="+write;
1240
                        else
1241
                                permString = "write="+write;
1242
                }
1243
                Log.d(LOG,permString);
1244
                if(!"".equals(permString)){
1245
                        headers.put("X-Object-Sharing", permString);
1246
                }
1247
                HttpBundle b = new ContainerObjectManager(getApplicationContext()).updateObject(objects.getContainerName(), objects.getCName(), "", null, headers,otherUser);
1248
                Log.i(LOG,"response:"+b.getResponse().getStatusLine().getStatusCode());
1249
                return b;
1250
        }
1251
        
1252
        public HttpBundle restoreVersion(String version) throws CloudServersException{
1253
                Log.i(LOG,"Update version:"+version);
1254
                Map<String,String> headers=new HashMap<String, String>();
1255
                
1256
                headers.put("X-Source-Object","/"+objects.getContainerName()+"/"+objects.getCName());
1257
                headers.put("X-Source-Version",version);
1258
                headers.put("Content-Range","bytes 0-/*");
1259
                HttpBundle b = new ContainerObjectManager(getApplicationContext()).updateObject(objects.getContainerName(), objects.getCName(), "", "text/plain; charset=UTF-8", headers,otherUser);
1260
                Log.i(LOG,"response:"+b.getResponse().getStatusLine().getStatusCode());
1261
                return b;
1262
        }
1263
        
1264

    
1265
}