Merge branch 'master' into debian
authorKostas Papadimitriou <kpap@grnet.gr>
Fri, 8 Feb 2013 12:21:57 +0000 (14:21 +0200)
committerKostas Papadimitriou <kpap@grnet.gr>
Fri, 8 Feb 2013 12:21:57 +0000 (14:21 +0200)
69 files changed:
.gitignore
devflow.conf [new file with mode: 0644]
snf-pithos-webclient/setup.py
src/gr/grnet/pithos/web/client/AbstractPropertiesDialog.java
src/gr/grnet/pithos/web/client/AddUserDialog.java
src/gr/grnet/pithos/web/client/ConfirmationDialog.java
src/gr/grnet/pithos/web/client/Const.java [new file with mode: 0644]
src/gr/grnet/pithos/web/client/CredentialsDialog.java
src/gr/grnet/pithos/web/client/DeleteFileDialog.java
src/gr/grnet/pithos/web/client/DeleteFolderDialog.java
src/gr/grnet/pithos/web/client/FeedbackDialog.java
src/gr/grnet/pithos/web/client/FileContextMenu.java
src/gr/grnet/pithos/web/client/FileList.java
src/gr/grnet/pithos/web/client/FilePermissionsDialog.java
src/gr/grnet/pithos/web/client/FilePropertiesDialog.java
src/gr/grnet/pithos/web/client/FilePublishDialog.java
src/gr/grnet/pithos/web/client/FileUploadDialog.java
src/gr/grnet/pithos/web/client/FileVersionsDialog.java
src/gr/grnet/pithos/web/client/FolderContextMenu.java
src/gr/grnet/pithos/web/client/FolderPermissionsDialog.java
src/gr/grnet/pithos/web/client/FolderPropertiesDialog.java
src/gr/grnet/pithos/web/client/GroupCreateDialog.java
src/gr/grnet/pithos/web/client/Helpers.java [new file with mode: 0644]
src/gr/grnet/pithos/web/client/Invitations.java
src/gr/grnet/pithos/web/client/MessagePanel.java
src/gr/grnet/pithos/web/client/PermissionsAddDialog.java
src/gr/grnet/pithos/web/client/PermissionsList.java
src/gr/grnet/pithos/web/client/Pithos.java
src/gr/grnet/pithos/web/client/PleaseWaitPopup.java
src/gr/grnet/pithos/web/client/Resource.java [moved from src/gr/grnet/pithos/web/client/foldertree/Resource.java with 52% similarity]
src/gr/grnet/pithos/web/client/SessionExpiredDialog.java
src/gr/grnet/pithos/web/client/SharingUsers.java
src/gr/grnet/pithos/web/client/Toolbar.java
src/gr/grnet/pithos/web/client/ToolsMenu.java
src/gr/grnet/pithos/web/client/UploadAlert.java
src/gr/grnet/pithos/web/client/VersionsList.java
src/gr/grnet/pithos/web/client/animation/FadeIn.java [deleted file]
src/gr/grnet/pithos/web/client/animation/FadeOut.java [deleted file]
src/gr/grnet/pithos/web/client/catalog/GetUserCatalogs.java [new file with mode: 0644]
src/gr/grnet/pithos/web/client/catalog/UpdateUserCatalogs.java [new file with mode: 0644]
src/gr/grnet/pithos/web/client/catalog/UserCatalogs.java [new file with mode: 0644]
src/gr/grnet/pithos/web/client/commands/AddUserCommand.java
src/gr/grnet/pithos/web/client/commands/DeleteGroupCommand.java
src/gr/grnet/pithos/web/client/commands/EmptyContainerCommand.java
src/gr/grnet/pithos/web/client/commands/PasteCommand.java
src/gr/grnet/pithos/web/client/commands/RemoveUserCommand.java
src/gr/grnet/pithos/web/client/commands/RestoreTrashCommand.java
src/gr/grnet/pithos/web/client/commands/ToTrashCommand.java
src/gr/grnet/pithos/web/client/foldertree/AccountResource.java
src/gr/grnet/pithos/web/client/foldertree/File.java
src/gr/grnet/pithos/web/client/foldertree/FileVersions.java
src/gr/grnet/pithos/web/client/foldertree/Folder.java
src/gr/grnet/pithos/web/client/foldertree/FolderTreeViewModel.java
src/gr/grnet/pithos/web/client/grouptree/Group.java
src/gr/grnet/pithos/web/client/grouptree/GroupContextMenu.java
src/gr/grnet/pithos/web/client/grouptree/GroupTreeViewModel.java
src/gr/grnet/pithos/web/client/grouptree/User.java
src/gr/grnet/pithos/web/client/grouptree/UserContextMenu.java
src/gr/grnet/pithos/web/client/mysharedtree/MysharedTreeViewModel.java
src/gr/grnet/pithos/web/client/othersharedtree/OtherSharedTreeViewModel.java
src/gr/grnet/pithos/web/client/rest/DeleteRequest.java
src/gr/grnet/pithos/web/client/rest/GetRequest.java
src/gr/grnet/pithos/web/client/rest/HeadRequest.java
src/gr/grnet/pithos/web/client/rest/PostRequest.java
src/gr/grnet/pithos/web/client/rest/PutRequest.java
src/gr/grnet/pithos/web/client/rest/RestRequestCallback.java
src/gr/grnet/pithos/web/client/tagtree/Tag.java
src/gr/grnet/pithos/web/client/tagtree/TagTreeViewModel.java
version [new file with mode: 0644]

index f1bc3ca..0a2da7a 100644 (file)
@@ -24,3 +24,7 @@ distribute*.egg
 docs/build
 pithos-web-client.sublime-project
 pithos-web-client.sublime-workspace
+.ant_targets
+.DS_Store
+out
+__gitstats
diff --git a/devflow.conf b/devflow.conf
new file mode 100644 (file)
index 0000000..911ff20
--- /dev/null
@@ -0,0 +1,3 @@
+[ packages ]
+  [[ snf-pithos-webclient ]]
+    version_file = "snf-pithos-webclient/pithos_webclient/version.py"
index f08248d..c1b622a 100644 (file)
@@ -45,12 +45,6 @@ from setuptools import setup, find_packages
 
 
 HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
-try:
-    # try to update the version file
-    from synnefo.util import version
-    version.update_version('pithos_webclient', 'version', HERE)
-except ImportError:
-    pass
 
 from pithos_webclient.version import __version__
 
index 0c53546..9bc9475 100644 (file)
@@ -60,9 +60,6 @@ public abstract class AbstractPropertiesDialog extends DialogBox {
         app = _app;\r
                // Enable IE selection for the dialog (must disable it upon closing it)\r
                Pithos.enableIESelection();\r
-\r
-               setAnimationEnabled(true);\r
-\r
        }\r
 \r
        /**\r
index 6d29afc..9dcffd1 100644 (file)
  */\r
 package gr.grnet.pithos.web.client;\r
 \r
-import gr.grnet.pithos.web.client.foldertree.Resource;\r
-import gr.grnet.pithos.web.client.grouptree.Group;\r
-import gr.grnet.pithos.web.client.rest.PostRequest;\r
-import gr.grnet.pithos.web.client.rest.RestException;\r
-\r
 import com.google.gwt.core.client.GWT;\r
 import com.google.gwt.core.client.Scheduler;\r
 import com.google.gwt.dom.client.NativeEvent;\r
@@ -48,15 +43,14 @@ import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.dom.client.KeyDownEvent;\r
 import com.google.gwt.http.client.Response;\r
 import com.google.gwt.http.client.URL;\r
-import com.google.gwt.regexp.shared.RegExp;\r
 import com.google.gwt.user.client.Event.NativePreviewEvent;\r
-import com.google.gwt.user.client.ui.Anchor;\r
-import com.google.gwt.user.client.ui.Button;\r
-import com.google.gwt.user.client.ui.DialogBox;\r
-import com.google.gwt.user.client.ui.FlexTable;\r
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
-import com.google.gwt.user.client.ui.TextBox;\r
-import com.google.gwt.user.client.ui.VerticalPanel;\r
+import com.google.gwt.user.client.ui.*;\r
+import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;\r
+import gr.grnet.pithos.web.client.catalog.UserCatalogs;\r
+import gr.grnet.pithos.web.client.grouptree.Group;\r
+import gr.grnet.pithos.web.client.grouptree.User;\r
+import gr.grnet.pithos.web.client.rest.PostRequest;\r
+import gr.grnet.pithos.web.client.rest.RestException;\r
 \r
 /**\r
  * The 'Folder properties' dialog box implementation.\r
@@ -66,52 +60,51 @@ public class AddUserDialog extends DialogBox {
     protected Pithos app;\r
 \r
     Group group;\r
-       /**\r
-        * The widget that holds the folderName of the folder.\r
-        */\r
-       TextBox userName = new TextBox();\r
+    /**\r
+     * The widget that holds the folderName of the folder.\r
+     */\r
+    TextBox userDisplayNameTextBox = new TextBox();\r
 \r
-       final VerticalPanel inner;\r
+    final VerticalPanel inner;\r
 \r
-       /**\r
-        * The widget's constructor.\r
-        */\r
-       public AddUserDialog(final Pithos app, Group _group) {\r
+    /**\r
+     * The widget's constructor.\r
+     */\r
+    public AddUserDialog(final Pithos app, Group _group) {\r
         this.app = app;\r
         this.group = _group;\r
-        \r
-               Anchor close = new Anchor("close");\r
-               close.addStyleName("close");\r
-               close.addClickHandler(new ClickHandler() {\r
-                       \r
-                       @Override\r
-                       public void onClick(ClickEvent event) {\r
-                               hide();\r
-                       }\r
-               });\r
-\r
-               setAnimationEnabled(true);\r
-               setGlassEnabled(true);\r
-               setStyleName("pithos-DialogBox");\r
-\r
-               // Enable IE selection for the dialog (must disable it upon closing it)\r
-               Pithos.enableIESelection();\r
-\r
-               // Use this opportunity to set the dialog's caption.\r
-               setText("Add user");\r
-\r
-               // Outer contains inner and buttons\r
-               VerticalPanel outer = new VerticalPanel();\r
-               outer.add(close);\r
-               // Inner contains generalPanel and permPanel\r
-               inner = new VerticalPanel();\r
-               inner.addStyleName("inner");\r
-\r
-               VerticalPanel generalPanel = new VerticalPanel();\r
+\r
+        Anchor close = new Anchor("close");\r
+        close.addStyleName("close");\r
+        close.addClickHandler(new ClickHandler() {\r
+\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                hide();\r
+            }\r
+        });\r
+\r
+        setGlassEnabled(true);\r
+        setStyleName("pithos-DialogBox");\r
+\r
+        // Enable IE selection for the dialog (must disable it upon closing it)\r
+        Pithos.enableIESelection();\r
+\r
+        // Use this opportunity to set the dialog's caption.\r
+        setText("Add user");\r
+\r
+        // Outer contains inner and buttons\r
+        VerticalPanel outer = new VerticalPanel();\r
+        outer.add(close);\r
+        // Inner contains generalPanel and permPanel\r
+        inner = new VerticalPanel();\r
+        inner.addStyleName("inner");\r
+\r
+        VerticalPanel generalPanel = new VerticalPanel();\r
         FlexTable generalTable = new FlexTable();\r
         generalTable.setText(0, 0, "Username");\r
 \r
-        generalTable.setWidget(0, 1, userName);\r
+        generalTable.setWidget(0, 1, userDisplayNameTextBox);\r
 \r
         generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");\r
         generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");\r
@@ -121,101 +114,126 @@ public class AddUserDialog extends DialogBox {
 \r
         outer.add(inner);\r
 \r
-               // Create the 'Create/Update' button, along with a listener that hides the dialog\r
-               // when the button is clicked and quits the application.\r
-               String okLabel = "Create";\r
-               final Button ok = new Button(okLabel, new ClickHandler() {\r
-                       @Override\r
-                       public void onClick(ClickEvent event) {\r
-                               addUser();\r
-                               closeDialog();\r
-                       }\r
-               });\r
-               ok.addStyleName("button");\r
-               outer.add(ok);\r
+        // Create the 'Create/Update' button, along with a listener that hides the dialog\r
+        // when the button is clicked and quits the application.\r
+        String okLabel = "Create";\r
+        final Button ok = new Button(okLabel, new ClickHandler() {\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                addUser();\r
+                closeDialog();\r
+            }\r
+        });\r
+        ok.addStyleName("button");\r
+        outer.add(ok);\r
         outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
 \r
         setWidget(outer);\r
-       }\r
-\r
-       @Override\r
-       public void center() {\r
-               super.center();\r
-               userName.setFocus(true);\r
-       }\r
-\r
-       @Override\r
-       protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
-               super.onPreviewNativeEvent(preview);\r
-\r
-               NativeEvent evt = preview.getNativeEvent();\r
-               if (evt.getType().equals(KeyDownEvent.getType().getName()))\r
-                       // Use the popup's key preview hooks to close the dialog when either\r
-                       // enter or escape is pressed.\r
-                       switch (evt.getKeyCode()) {\r
-                               case KeyCodes.KEY_ENTER:\r
-                                       addUser();\r
+    }\r
+\r
+    @Override\r
+    public void center() {\r
+        super.center();\r
+        userDisplayNameTextBox.setFocus(true);\r
+    }\r
+\r
+    @Override\r
+    protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
+        super.onPreviewNativeEvent(preview);\r
+\r
+        NativeEvent evt = preview.getNativeEvent();\r
+        if(evt.getType().equals(KeyDownEvent.getType().getName()))\r
+        // Use the popup's key preview hooks to close the dialog when either\r
+        // enter or escape is pressed.\r
+        {\r
+            switch(evt.getKeyCode()) {\r
+                case KeyCodes.KEY_ENTER:\r
+                    addUser();\r
+                    closeDialog();\r
+                    break;\r
+                case KeyCodes.KEY_ESCAPE:\r
                     closeDialog();\r
-                                       break;\r
-                               case KeyCodes.KEY_ESCAPE:\r
-                                       closeDialog();\r
-                                       break;\r
-                       }\r
-       }\r
-\r
-\r
-       /**\r
-        * Enables IE selection prevention and hides the dialog\r
-        * (we disable the prevention on creation of the dialog)\r
-        */\r
-       public void closeDialog() {\r
-               Pithos.preventIESelection();\r
-               hide();\r
-       }\r
-\r
-       /**\r
-        * Generate an RPC request to create a new folder.\r
-        */\r
-       void addUser() {\r
-               String name = userName.getText().trim();\r
-               if (name.length() == 0)\r
-                       return;\r
-               RegExp emailValidator = RegExp.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+[.][A-Z]{2,4}$", "i");\r
-               if (!emailValidator.test(name)) {\r
-                       app.displayWarning("Username must be a valid email address");\r
-                       return;\r
-               }\r
-                       \r
-       group.addMember(name);\r
-       String path = "?update=";\r
-       PostRequest updateGroup = new PostRequest(app.getApiPath(), app.getUsername(), path) {\r
-                       \r
-                       @Override\r
-                       public void onSuccess(Resource result) {\r
-                               app.updateGroupNode(group);\r
-                       }\r
-                       \r
-                       @Override\r
-                       public void onError(Throwable t) {\r
-                               GWT.log("", t);\r
-                               app.setError(t);\r
-                               if (t instanceof RestException) {\r
-                                       app.displayError("Unable to update group:" + ((RestException) t).getHttpStatusText());\r
-                               }\r
-                               else \r
-                                       app.displayError("System error updating group:" + t.getMessage());\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onUnauthorized(Response response) {\r
-                               app.sessionExpired();\r
-                       }\r
-               };\r
-               updateGroup.setHeader("X-Auth-Token", app.getToken());\r
-               String groupMembers = "";\r
-               for (String u : group.getMembers())\r
-                       groupMembers += (URL.encodePathSegment(u) + ",");\r
-               updateGroup.setHeader("X-Account-Group-" + URL.encodePathSegment(group.getName()), groupMembers);\r
-               Scheduler.get().scheduleDeferred(updateGroup);\r
-       }\r
+                    break;\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+    /**\r
+     * Enables IE selection prevention and hides the dialog\r
+     * (we disable the prevention on creation of the dialog)\r
+     */\r
+    public void closeDialog() {\r
+        Pithos.preventIESelection();\r
+        hide();\r
+    }\r
+\r
+    /**\r
+     * Generate an RPC request to create a new folder.\r
+     */\r
+    void addUser() {\r
+        final String userDisplayName = userDisplayNameTextBox.getText().trim();\r
+        if(userDisplayName.length() == 0) {\r
+            return;\r
+        }\r
+        if(!Const.EMAIL_REGEX.test(userDisplayName)) {\r
+            app.displayWarning("Username must be a valid email address");\r
+            return;\r
+        }\r
+\r
+        // Now get the userID\r
+        final String userID = app.getUserIDForDisplayName(userDisplayName);\r
+        if(userID != null) {\r
+            doAddUser(userID, userDisplayName);\r
+        }\r
+        else {\r
+            // Must call server to obtain userID\r
+            new UpdateUserCatalogs(app, null, Helpers.toList(userDisplayName)) {\r
+                @Override\r
+                public void onSuccess(UserCatalogs requestedUserCatalogs, UserCatalogs updatedUserCatalogs) {\r
+                    final String userID = updatedUserCatalogs.getUserID(userDisplayName);\r
+                    if(userID != null) {\r
+                        doAddUser(userID, userDisplayName);\r
+                    }\r
+                    else {\r
+                        app.displayError("Unknown user " + userDisplayName);\r
+                    }\r
+                }\r
+            }.scheduleDeferred();\r
+        }\r
+    }\r
+\r
+    private void doAddUser(String userID, String userDisplayName) {\r
+        final User newUser = new User(userID, userDisplayName, group.getName());\r
+        app.LOG("doAddUser() ", newUser);\r
+        group.addUser(newUser);\r
+        final String path = "?update=";\r
+        PostRequest updateGroup = new PostRequest(app, app.getApiPath(), app.getUserID(), path) {\r
+            @Override\r
+            public void onSuccess(Resource result) {\r
+                app.updateGroupNode(group);\r
+            }\r
+\r
+            @Override\r
+            public void onError(Throwable t) {\r
+                GWT.log("", t);\r
+                app.setError(t);\r
+                if(t instanceof RestException) {\r
+                    app.displayError("Unable to update group:" + ((RestException) t).getHttpStatusText());\r
+                }\r
+                else {\r
+                    app.displayError("System error updating group:" + t.getMessage());\r
+                }\r
+            }\r
+\r
+            @Override\r
+            protected void onUnauthorized(Response response) {\r
+                app.sessionExpired();\r
+            }\r
+        };\r
+        updateGroup.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());\r
+        final String groupMembers = group.encodeUserIDsForXAccountGroup();\r
+        updateGroup.setHeader(Const.X_ACCOUNT_GROUP_ + URL.encodePathSegment(group.getName()), groupMembers);\r
+        Scheduler.get().scheduleDeferred(updateGroup);\r
+    }\r
 }\r
index 27fb9bb..25ef864 100644 (file)
@@ -71,7 +71,6 @@ public abstract class ConfirmationDialog extends DialogBox {
                });
                // Set the dialog's caption.
                setText("Confirmation");
-               setAnimationEnabled(true);
                setGlassEnabled(true);
                setStyleName("pithos-DialogBox");
                // Create a VerticalPanel to contain the label and the buttons.
diff --git a/src/gr/grnet/pithos/web/client/Const.java b/src/gr/grnet/pithos/web/client/Const.java
new file mode 100644 (file)
index 0000000..11589cc
--- /dev/null
@@ -0,0 +1,37 @@
+package gr.grnet.pithos.web.client;
+
+import com.google.gwt.regexp.shared.RegExp;
+
+/**
+ * Gathers application-wide constants, like <code>X-Auth-Token</code>
+ */
+public class Const {
+    public static final String X_AUTH_TOKEN = "X-Auth-Token";
+    public static final String OTHER_PROPERTIES = "otherProperties";
+    public static final String LOGIN_URL = "loginUrl";
+    public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
+    public static final String PERCENT_100 = "100%";
+    public static final String DATE_FORMAT_1 = "EEE, dd MMM yyyy HH:mm:ss";
+    public static final String AUTH_COOKIE = "authCookie";
+    public static final String X_COPY_FROM = "X-Copy-From";
+    public static final String X_SOURCE_ACCOUNT = "X-Source-Account";
+    public static final String CONTENT_TYPE = "Content-Type";
+    public static final String ACCEPT = "Accept";
+    public static final String CONTENT_LENGTH = "Content-Length";
+    public static final String X_MOVE_FROM = "X-Move-From";
+    public static final String HOME_CONTAINER = "pithos";
+    public static final String TRASH_CONTAINER = "trash";
+    public static final RegExp EMAIL_REGEX = RegExp.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+[.][A-Z]{2,4}$", "i");
+    public static final String X_ACCOUNT_GROUP_ = "X-Account-Group-";
+    public static final String X_ACCOUNT_CONTAINER_COUNT = "X-Account-Container-Count";
+    public static final String X_ACCOUNT_OBJECT_COUNT = "X-Account-Object-Count";
+    public static final String X_ACCOUNT_BYTES_USED = "X-Account-Bytes-Used";
+    public static final String X_ACCOUNT_POLICY_QUOTA = "X-Account-Policy-Quota";
+    public static final String X_ACCOUNT_LAST_LOGIN = "X-Account-Last-Login";
+    public static final String LAST_MODIFIED = "Last-Modified";
+    public static final String NUMBER_FORMAT_1 = "######.#";
+
+    private Const() {}
+
+
+}
index eebedf1..fd56799 100644 (file)
@@ -73,7 +73,6 @@ public class CredentialsDialog extends DialogBox {
                });
                // Set the dialog's caption.
                setText("User Credentials");
-               setAnimationEnabled(true);
                setGlassEnabled(true);
                setStyleName("pithos-DialogBox");
                // A VerticalPanel that contains the 'about' label and the 'OK' button.
@@ -93,7 +92,7 @@ public class CredentialsDialog extends DialogBox {
                table.setText(0, 0, "Username");
                table.setText(1, 0, "Token");
                TextBox username = new TextBox();
-               username.setText(app.getUsername());
+               username.setText(app.getUserID());
                username.setReadOnly(true);
                username.setWidth(WIDTH_FIELD);
                username.addClickHandler(new ClickHandler() {
@@ -108,7 +107,7 @@ public class CredentialsDialog extends DialogBox {
                table.setWidget(0, 1, username);
 
                TextBox tokenBox = new TextBox();
-               tokenBox.setText(app.getToken());
+               tokenBox.setText(app.getUserToken());
                tokenBox.setReadOnly(true);
                tokenBox.setWidth(WIDTH_FIELD);
                tokenBox.addClickHandler(new ClickHandler() {
index 7834fa2..dfecfab 100644 (file)
@@ -37,7 +37,6 @@ package gr.grnet.pithos.web.client;
 import gr.grnet.pithos.web.client.MessagePanel.Images;\r
 import gr.grnet.pithos.web.client.foldertree.File;\r
 import gr.grnet.pithos.web.client.foldertree.Folder;\r
-import gr.grnet.pithos.web.client.foldertree.Resource;\r
 import gr.grnet.pithos.web.client.rest.DeleteRequest;\r
 import gr.grnet.pithos.web.client.rest.RestException;\r
 \r
@@ -90,7 +89,6 @@ public class DeleteFileDialog extends DialogBox {
                });\r
                // Set the dialog's caption.\r
                setText("Confirmation");\r
-               setAnimationEnabled(true);\r
                setGlassEnabled(true);\r
                setStyleName("pithos-DialogBox");\r
                // Create a VerticalPanel to contain the label and the buttons.\r
@@ -137,7 +135,7 @@ public class DeleteFileDialog extends DialogBox {
         if (iter.hasNext()) {\r
             File f = iter.next();\r
             String path = f.getUri();\r
-            DeleteRequest deleteFile = new DeleteRequest(app.getApiPath(), f.getOwner(), URL.encode(path)) {\r
+            DeleteRequest deleteFile = new DeleteRequest(app, app.getApiPath(), f.getOwnerID(), URL.encode(path)) {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
                     deleteFile(iter);\r
@@ -160,7 +158,7 @@ public class DeleteFileDialog extends DialogBox {
                                        app.sessionExpired();\r
                                }\r
             };\r
-            deleteFile.setHeader("X-Auth-Token", app.getToken());\r
+            deleteFile.setHeader("X-Auth-Token", app.getUserToken());\r
             Scheduler.get().scheduleDeferred(deleteFile);\r
         }\r
         else {\r
index fc69ff1..7355697 100644 (file)
@@ -79,7 +79,6 @@ public class DeleteFolderDialog extends DialogBox {
 \r
                // Set the dialog's caption.\r
                setText("Confirmation");\r
-               setAnimationEnabled(true);\r
                setGlassEnabled(true);\r
                setStyleName("pithos-DialogBox");\r
                // Create a VerticalPanel to contain the HTML label and the buttons.\r
index b8710f9..5c85235 100644 (file)
  */
 package gr.grnet.pithos.web.client;
 
-import gr.grnet.pithos.web.client.foldertree.Resource;
-import gr.grnet.pithos.web.client.rest.PostRequest;
-
-import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.EventTarget;
 import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.TextAreaElement;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.http.client.Response;
 import com.google.gwt.i18n.client.Dictionary;
 import com.google.gwt.user.client.Event.NativePreviewEvent;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.DialogBox;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.TextArea;
-import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.*;
+import gr.grnet.pithos.web.client.rest.PostRequest;
 
 
 /**
@@ -64,112 +51,113 @@ import com.google.gwt.user.client.ui.VerticalPanel;
  */
 public class FeedbackDialog extends DialogBox {
 
-       Dictionary otherProperties = Dictionary.getDictionary("otherProperties");
-       
-       Pithos app;
-       
-       String appData;
-       
-       TextArea msg;
-       
-       /**
-        * The widget constructor.
-        */
-       public FeedbackDialog(final Pithos _app, final String _appData) {
-               app = _app;
-               appData = _appData;
-               
-               // Set the dialog's caption.
-               Anchor close = new Anchor("close");
-               close.addStyleName("close");
-               close.addClickHandler(new ClickHandler() {
-                       
-                       @Override
-                       public void onClick(ClickEvent event) {
-                               hide();
-                       }
-               });
-               setText("Send feedback");
-               setAnimationEnabled(true);
-               setGlassEnabled(true);
-               
-               setStyleName("pithos-DialogBox");
-
-               VerticalPanel outer = new VerticalPanel();
-               outer.add(close);
-               
-               VerticalPanel inner = new VerticalPanel();
-               inner.addStyleName("inner");
-               // Create the text and set a style name so we can style it with CSS.
-               HTML text = new HTML("Pithos+ is currently in alpha test and we would appreciate any<br>" + "kind of feedback. We welcome any suggestions, questions and<br>" + " bug reports you may have.");
-               text.setStyleName("pithos-credentialsText");
-               inner.add(text);
-               FlexTable table = new FlexTable();
-               table.setText(0, 0, "Please describe your problem here, provide as many details as possible");
-               msg = new TextArea();
-               msg.setWidth("100%");
-               msg.setHeight("100px");
-               table.setWidget(1, 0, msg);
-
-               table.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
-               table.getFlexCellFormatter().setStyleName(0, 1, "props-values");
-               inner.add(table);
-
-               // Create the 'OK' button, along with a listener that hides the dialog
-               // when the button is clicked.
-               Button confirm = new Button("Submit feedback", new ClickHandler() {
-                       @Override
-                       public void onClick(ClickEvent event) {
-                               sendFeedback();
-                               hide();
-                       }
-               });
-               confirm.addStyleName("button");
-               inner.add(confirm);
-               outer.add(inner);
-               outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
-               setWidget(outer);
-       }
-
-       @Override
-       protected void onPreviewNativeEvent(NativePreviewEvent preview) {
-               super.onPreviewNativeEvent(preview);
-               NativeEvent evt = preview.getNativeEvent();
-               if (evt.getType().equals("keydown")) {
-                       // Use the popup's key preview hooks to close the dialog when
-                       // either enter or escape is pressed.
-                       switch (evt.getKeyCode()) {
-                               case KeyCodes.KEY_ENTER:
-                                       sendFeedback();
-                                       hide();
-                                       break;
-                               case KeyCodes.KEY_ESCAPE:
-                                       hide();
-                                       break;
-                       }
-               }
-       }
-
-       /**
-        */
-       void sendFeedback() {
-               PostRequest sendFeedback = new PostRequest("", "", otherProperties.get("feedbackUrl"), "feedback_msg=" + msg.getText() + "&feedback_data=" + appData + "&auth=" + app.getToken()) {
-                       
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               app.sessionExpired();
-                       }
-                       
-                       @Override
-                       public void onSuccess(Resource result) {
-                               app.displayInformation("Feedback sent");
-                       }
-                       
-                       @Override
-                       public void onError(Throwable t) {
-                               GWT.log("", t);
-                       }
-               };
-               Scheduler.get().scheduleDeferred(sendFeedback);
-       }
+    Dictionary otherProperties = Dictionary.getDictionary("otherProperties");
+
+    Pithos app;
+
+    String appData;
+
+    TextArea msg;
+
+    /**
+     * The widget constructor.
+     */
+    public FeedbackDialog(final Pithos _app, final String _appData) {
+        app = _app;
+        appData = _appData;
+
+        // Set the dialog's caption.
+        Anchor close = new Anchor("close");
+        close.addStyleName("close");
+        close.addClickHandler(new ClickHandler() {
+
+            @Override
+            public void onClick(ClickEvent event) {
+                hide();
+            }
+        });
+        setText("Send feedback");
+        setGlassEnabled(true);
+
+        setStyleName("pithos-DialogBox");
+
+        VerticalPanel outer = new VerticalPanel();
+        outer.add(close);
+
+        VerticalPanel inner = new VerticalPanel();
+        inner.addStyleName("inner");
+        // Create the text and set a style name so we can style it with CSS.
+        HTML text = new HTML("Pithos+ is currently in alpha test and we would appreciate any<br>" + "kind of feedback. We welcome any suggestions, questions and<br>" + " bug reports you may have.");
+        text.setStyleName("pithos-credentialsText");
+        inner.add(text);
+        FlexTable table = new FlexTable();
+        table.setText(0, 0, "Please describe your problem here, provide as many details as possible");
+        msg = new TextArea();
+        msg.setWidth("100%");
+        msg.setHeight("100px");
+        table.setWidget(1, 0, msg);
+
+        table.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
+        table.getFlexCellFormatter().setStyleName(0, 1, "props-values");
+        inner.add(table);
+
+        // Create the 'OK' button, along with a listener that hides the dialog
+        // when the button is clicked.
+        Button confirm = new Button("Submit feedback", new ClickHandler() {
+            @Override
+            public void onClick(ClickEvent event) {
+                sendFeedback();
+                hide();
+            }
+        });
+        confirm.addStyleName("button");
+        inner.add(confirm);
+        outer.add(inner);
+        outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
+        setWidget(outer);
+    }
+
+    @Override
+    protected void onPreviewNativeEvent(NativePreviewEvent preview) {
+        super.onPreviewNativeEvent(preview);
+        NativeEvent evt = preview.getNativeEvent();
+        if(evt.getType().equals("keydown")) {
+            // Use the popup's key preview hooks to close the dialog when
+            // either enter or escape is pressed.
+            switch(evt.getKeyCode()) {
+                case KeyCodes.KEY_ENTER:
+                    sendFeedback();
+                    hide();
+                    break;
+                case KeyCodes.KEY_ESCAPE:
+                    hide();
+                    break;
+            }
+        }
+    }
+
+    /**
+     */
+    void sendFeedback() {
+        final String feedbackURL = otherProperties.get("feedbackUrl");
+        PostRequest sendFeedback = new PostRequest(app, "", "", feedbackURL, "feedback_msg=" + msg.getText() + "&feedback_data=" + appData + "&auth=" + app.getUserToken()) {
+
+            @Override
+            protected void onUnauthorized(Response response) {
+                app.sessionExpired();
+            }
+
+            @Override
+            public void onSuccess(Resource result) {
+                app.displayInformation("Feedback sent");
+            }
+
+            @Override
+            public void onError(Throwable t) {
+                app.displayError("Could not send feedback");
+            }
+        };
+        sendFeedback.setHeader("X-Auth-Token", app.getUserToken());
+        Scheduler.get().scheduleDeferred(sendFeedback);
+    }
 }
index d06f79f..1459f6f 100644 (file)
@@ -47,7 +47,6 @@ import gr.grnet.pithos.web.client.foldertree.Folder;
 
 import java.util.List;
 
-import com.google.gwt.http.client.URL;
 import com.google.gwt.resources.client.ClientBundle;
 import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.user.client.Command;
@@ -188,19 +187,18 @@ public class FileContextMenu extends PopupPanel {
                // The popup's constructor's argument is a boolean specifying that it
                // auto-close itself when the user clicks outside of it.
                super(true);
-               setAnimationEnabled(true);
                images = newImages;
         MenuBar contextMenu = new MenuBar(true);
         Boolean[] permissions = null;
         boolean canWrite = true;
         if (selectedFolder != null) {
-               permissions = selectedFolder.getPermissions().get(app.getUsername());
-               canWrite = selectedFolder.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
+               permissions = selectedFolder.getPermissions().get(app.getUserID());
+               canWrite = selectedFolder.getOwnerID().equals(app.getUserID()) || (permissions!= null && permissions[1] != null && permissions[1]);
                }
         else {
                for (File f : selectedFiles) {
-                       permissions = f.getPermissions().get(app.getUsername());
-                       canWrite &= (f.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]));
+                       permissions = f.getPermissions().get(app.getUserID());
+                       canWrite &= (f.getOwnerID().equals(app.getUserID()) || (permissions!= null && permissions[1] != null && permissions[1]));
                }
         }
         boolean isFolderTreeSelected = selectedTree.equals(app.getFolderTreeView());
@@ -254,7 +252,7 @@ public class FileContextMenu extends PopupPanel {
                        @Override
                        public void execute() {
                                for (File f : selectedFiles)
-                                       Window.open(app.getApiPath() + f.getOwner() + f.getUri(), "_blank", "");
+                                       Window.open(app.getApiPath() + f.getOwnerID() + f.getUri(), "_blank", "");
                        }
                }));
 
index 556e5a1..5384d11 100644 (file)
@@ -54,10 +54,8 @@ import com.google.gwt.cell.client.ValueUpdater;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ContextMenuEvent;
 import com.google.gwt.event.dom.client.ContextMenuHandler;
-import com.google.gwt.http.client.URL;
 import com.google.gwt.i18n.client.DateTimeFormat;
 import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.resources.client.ClientBundle.Source;
 import com.google.gwt.resources.client.ImageResource.ImageOptions;
 import com.google.gwt.resources.client.ImageResource.RepeatStyle;
 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
@@ -290,7 +288,7 @@ public class FileList extends Composite {
                                sb.append(Templates.INSTANCE.filenameSpan(object.getName()));
                                if (object.getContentType() != null && (object.getContentType().endsWith("png") || object.getContentType().endsWith("gif") || object.getContentType().endsWith("jpeg"))) {
                                sb.appendHtmlConstant("&nbsp;")
-                      .append(Templates.INSTANCE.viewLink(app.getApiPath() + object.getOwner() + object.getUri(), object.getName()));
+                      .append(Templates.INSTANCE.viewLink(app.getApiPath() + object.getOwnerID() + object.getUri(), object.getName()));
                                }
                                
                                return sb.toSafeHtml();
@@ -417,7 +415,7 @@ public class FileList extends Composite {
                if (DOM.eventGetType(event) == Event.ONDBLCLICK)
                        if (getSelectedFiles().size() == 1) {
                                File file = getSelectedFiles().get(0);
-                               Window.open(app.getApiPath() + file.getOwner() + file.getUri(), "_blank", "");
+                               Window.open(app.getApiPath() + file.getOwnerID() + file.getUri(), "_blank", "");
                                event.preventDefault();
                                return;
                        }
@@ -547,7 +545,7 @@ public class FileList extends Composite {
                             if (sortingProperty.equals("version")) {
                                     return arg0.getVersion() - arg1.getVersion();
                             } else if (sortingProperty.equals("owner")) {
-                                    return arg0.getOwner().compareTo(arg1.getOwner());
+                                    return arg0.getOwnerID().compareTo(arg1.getOwnerID());
                             } else if (sortingProperty.equals("date")) {
                                        if (arg0.getLastModified() != null && arg1.getLastModified() != null)
                                                return arg0.getLastModified().compareTo(arg1.getLastModified());
@@ -567,7 +565,7 @@ public class FileList extends Composite {
                             return arg1.getVersion() - arg0.getVersion();
                     } else if (sortingProperty.equals("owner")) {
                             
-                            return arg1.getOwner().compareTo(arg0.getOwner());
+                            return arg1.getOwnerID().compareTo(arg0.getOwnerID());
                     } else if (sortingProperty.equals("date")) {
                             
                             return arg1.getLastModified().compareTo(arg0.getLastModified());
@@ -649,7 +647,7 @@ public class FileList extends Composite {
                int i = 0;
                boolean scrolled = false;
                for (File f : files) {
-                       if (selectedUrls.contains(app.getApiPath() + f.getOwner() + f.getUri())) {
+                       if (selectedUrls.contains(app.getApiPath() + f.getOwnerID() + f.getUri())) {
                                selectionModel.setSelected(f, true);
                                if (!scrolled) {
                                        celltable.getRowElement(i).getCells().getItem(0).scrollIntoView();
index cf25fc5..dac21b9 100644 (file)
@@ -35,7 +35,6 @@
 package gr.grnet.pithos.web.client;\r
 \r
 import gr.grnet.pithos.web.client.foldertree.File;\r
-import gr.grnet.pithos.web.client.foldertree.Resource;\r
 import gr.grnet.pithos.web.client.rest.HeadRequest;\r
 import gr.grnet.pithos.web.client.rest.PostRequest;\r
 \r
@@ -50,14 +49,12 @@ import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.http.client.Response;\r
 import com.google.gwt.http.client.URL;\r
 import com.google.gwt.http.client.UrlBuilder;\r
-import com.google.gwt.i18n.client.Dictionary;\r
 import com.google.gwt.resources.client.ImageResource;\r
 import com.google.gwt.user.client.Command;\r
 import com.google.gwt.user.client.Window;\r
 import com.google.gwt.user.client.Event.NativePreviewEvent;\r
 import com.google.gwt.user.client.ui.Anchor;\r
 import com.google.gwt.user.client.ui.Button;\r
-import com.google.gwt.user.client.ui.CheckBox;\r
 import com.google.gwt.user.client.ui.FocusPanel;\r
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
 import com.google.gwt.user.client.ui.HorizontalPanel;\r
@@ -114,7 +111,6 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                });\r
                // Set the dialog's caption.\r
                setText("File permissions");\r
-               setAnimationEnabled(true);\r
                setGlassEnabled(true);\r
                setStyleName("pithos-DialogBox");\r
 \r
@@ -148,7 +144,7 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
     private VerticalPanel createSharingPanel() {\r
         VerticalPanel permPanel = new VerticalPanel();\r
 \r
-        permList = new PermissionsList(images, file.getPermissions(), file.getOwner(), false, new Command() {\r
+        permList = new PermissionsList(app, images, file.getPermissions(), file.getOwnerID(), false, new Command() {\r
                        \r
                        @Override\r
                        public void execute() {\r
@@ -244,7 +240,7 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
     void showLinkIfShared() {\r
                if (file.isShared()) {\r
                        UrlBuilder b = Window.Location.createUrlBuilder();\r
-                       b.setPath(app.getApiPath() + file.getOwner() + file.getUri());\r
+                       b.setPath(app.getApiPath() + file.getOwnerID() + file.getUri());\r
                        String href = Window.Location.getHref();\r
                        boolean hasParameters = href.contains("?");\r
                        path.setText(href + (hasParameters ? "&" : "?") + "goto=" + b.buildString());\r
@@ -260,16 +256,16 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
         */\r
        @Override\r
        protected boolean accept() {\r
-        updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", permList.getPermissions());\r
+        updateMetaData(app.getApiPath(), app.getUserID(), file.getUri() + "?update=", permList.getPermissions());\r
         return true;\r
        }\r
 \r
        protected void updateMetaData(String api, String owner, final String path, final Map<String, Boolean[]> newPermissions) {\r
         if (newPermissions != null) {\r
-            PostRequest updateFile = new PostRequest(api, owner, path) {\r
+            PostRequest updateFile = new PostRequest(app, api, owner, path) {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
-                       HeadRequest<File> headFile = new HeadRequest<File>(File.class, app.getApiPath(), file.getOwner(), path, file) {\r
+                       HeadRequest<File> headFile = new HeadRequest<File>(app, File.class, app.getApiPath(), file.getOwnerID(), path, file) {\r
 \r
                                                @Override\r
                                                public void onSuccess(File _result) {\r
@@ -298,7 +294,7 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                                                        app.sessionExpired();\r
                                                }\r
                                        };\r
-                                       headFile.setHeader("X-Auth-Token", app.getToken());\r
+                                       headFile.setHeader("X-Auth-Token", app.getUserToken());\r
                                        Scheduler.get().scheduleDeferred(headFile);\r
                 }\r
 \r
@@ -314,7 +310,7 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                                        app.sessionExpired();\r
                                }\r
             };\r
-            updateFile.setHeader("X-Auth-Token", app.getToken());\r
+            updateFile.setHeader("X-Auth-Token", app.getUserToken());\r
             \r
             String readPermHeader = "read=";\r
             String writePermHeader = "write=";\r
index 31257fc..6bb542f 100644 (file)
@@ -35,7 +35,6 @@
 package gr.grnet.pithos.web.client;\r
 \r
 import gr.grnet.pithos.web.client.foldertree.File;\r
-import gr.grnet.pithos.web.client.foldertree.Resource;\r
 import gr.grnet.pithos.web.client.rest.PostRequest;\r
 import gr.grnet.pithos.web.client.rest.PutRequest;\r
 \r
@@ -56,7 +55,6 @@ import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.FlexTable;\r
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
 import com.google.gwt.user.client.ui.HorizontalPanel;\r
-import com.google.gwt.user.client.ui.Image;\r
 import com.google.gwt.user.client.ui.Label;\r
 import com.google.gwt.user.client.ui.TextBox;\r
 import com.google.gwt.user.client.ui.VerticalPanel;\r
@@ -93,7 +91,6 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
                });\r
                // Set the dialog's caption.\r
                setText("File properties");\r
-               setAnimationEnabled(true);\r
                setGlassEnabled(true);\r
                setStyleName("pithos-DialogBox");\r
 \r
@@ -136,11 +133,24 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
         name.setWidth("100%");\r
         name.setText(file.getName());\r
         generalTable.setWidget(0, 1, name);\r
-        if(file.getParent() != null)\r
+        if(file.getParent() != null) {\r
             generalTable.setText(1, 1, file.getParent().getName());\r
-        else\r
+        }\r
+        else {\r
             generalTable.setText(1, 1, "-");\r
-        generalTable.setText(2, 1, file.getOwner());\r
+        }\r
+\r
+        final String ownerID = file.getOwnerID();\r
+        final String displayName = app.getUserDisplayNameForID(ownerID);\r
+        final String ownerDisplayName;\r
+        if(displayName == null) {\r
+            // FIXME: Get the actual display name and do not use the id\r
+            ownerDisplayName = ownerID;\r
+        }\r
+        else {\r
+            ownerDisplayName = displayName;\r
+        }\r
+        generalTable.setText(2, 1, ownerDisplayName);\r
 \r
         final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");\r
         generalTable.setText(3, 1, file.getLastModified() != null ? formatter.format(file.getLastModified()) : "");\r
@@ -251,10 +261,10 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
 \r
         if (newFilename != null) {\r
             final String path = file.getParent().getUri() + "/" + newFilename;\r
-            PutRequest updateFile = new PutRequest(app.getApiPath(), app.getUsername(), path) {\r
+            PutRequest updateFile = new PutRequest(app, app.getApiPath(), app.getUserID(), path) {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
-                    updateMetaData(app.getApiPath(), file.getOwner(), path, newMeta);\r
+                    updateMetaData(app.getApiPath(), file.getOwnerID(), path, newMeta);\r
                 }\r
 \r
                 @Override\r
@@ -269,7 +279,7 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
                                        app.sessionExpired();\r
                                }\r
             };\r
-            updateFile.setHeader("X-Auth-Token", app.getToken());\r
+            updateFile.setHeader("X-Auth-Token", app.getUserToken());\r
             updateFile.setHeader("X-Move-From", URL.encodePathSegment(file.getUri()));\r
             updateFile.setHeader("Content-Type", file.getContentType());\r
             for (String key : file.getMeta().keySet())\r
@@ -303,13 +313,13 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
             Scheduler.get().scheduleDeferred(updateFile);\r
         }\r
         else\r
-            updateMetaData(app.getApiPath(), app.getUsername(), file.getUri(), newMeta);\r
+            updateMetaData(app.getApiPath(), app.getUserID(), file.getUri(), newMeta);\r
         return true;\r
        }\r
 \r
        protected void updateMetaData(final String api, final String owner, final String path, Map<String, String> newMeta) {\r
         if (newMeta != null) {\r
-            PostRequest updateFile = new PostRequest(api, owner, path + "?update=") {\r
+            PostRequest updateFile = new PostRequest(app, api, owner, path + "?update=") {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
                        if (!app.isMySharedSelected())\r
@@ -344,7 +354,7 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
                                        app.sessionExpired();\r
                                }\r
             };\r
-            updateFile.setHeader("X-Auth-Token", app.getToken());\r
+            updateFile.setHeader("X-Auth-Token", app.getUserToken());\r
             \r
             for (String t : file.getMeta().keySet()) {\r
                        updateFile.setHeader("X-Object-Meta-" + URL.encodePathSegment(t.trim()), "~");\r
index 3ea371f..eca3581 100644 (file)
 package gr.grnet.pithos.web.client;\r
 \r
 import gr.grnet.pithos.web.client.foldertree.File;\r
-import gr.grnet.pithos.web.client.foldertree.Resource;\r
 import gr.grnet.pithos.web.client.rest.HeadRequest;\r
 import gr.grnet.pithos.web.client.rest.PostRequest;\r
 \r
-import java.util.Map;\r
-\r
 import com.google.gwt.core.client.GWT;\r
 import com.google.gwt.core.client.Scheduler;\r
 import com.google.gwt.dom.client.NativeEvent;\r
@@ -48,9 +45,7 @@ import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;\r
 import com.google.gwt.event.dom.client.KeyCodes;\r
 import com.google.gwt.http.client.Response;\r
-import com.google.gwt.http.client.URL;\r
 import com.google.gwt.http.client.UrlBuilder;\r
-import com.google.gwt.i18n.client.Dictionary;\r
 import com.google.gwt.resources.client.ImageResource;\r
 import com.google.gwt.user.client.Command;\r
 import com.google.gwt.user.client.Window;\r
@@ -114,7 +109,6 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
                });\r
                // Set the dialog's caption.\r
                setText("Publish/Un-publish");\r
-               setAnimationEnabled(true);\r
                setGlassEnabled(true);\r
                setStyleName("pithos-DialogBox");\r
 \r
@@ -163,7 +157,7 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
         });\r
 \r
         // Only show the read for all permission if the user is the owner.\r
-        if (file.getOwner().equals(app.getUsername())) {\r
+        if (file.getOwnerID().equals(app.getUserID())) {\r
             final HorizontalPanel permForAll = new HorizontalPanel();\r
             permForAll.add(new Label("Public"));\r
             permForAll.add(readForAll);\r
@@ -228,18 +222,18 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
        protected boolean accept() {\r
         Boolean published = null;\r
                if (readForAll.getValue() != file.isPublished())\r
-                       if (file.getOwner().equals(app.getUsername()))\r
+                       if (file.getOwnerID().equals(app.getUserID()))\r
                 published = readForAll.getValue();\r
-        updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", published);\r
+        updateMetaData(app.getApiPath(), app.getUserID(), file.getUri() + "?update=", published);\r
         return true;\r
        }\r
 \r
        protected void updateMetaData(String api, String owner, final String path, final Boolean published) {\r
         if (published != null) {\r
-            PostRequest updateFile = new PostRequest(api, owner, path) {\r
+            PostRequest updateFile = new PostRequest(app, api, owner, path) {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
-                       HeadRequest<File> headFile = new HeadRequest<File>(File.class, app.getApiPath(), file.getOwner(), path, file) {\r
+                       HeadRequest<File> headFile = new HeadRequest<File>(app, File.class, app.getApiPath(), file.getOwnerID(), path, file) {\r
 \r
                                                @Override\r
                                                public void onSuccess(File _result) {\r
@@ -268,7 +262,7 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
                                                        app.sessionExpired();\r
                                                }\r
                                        };\r
-                                       headFile.setHeader("X-Auth-Token", app.getToken());\r
+                                       headFile.setHeader("X-Auth-Token", app.getUserToken());\r
                                        Scheduler.get().scheduleDeferred(headFile);\r
                 }\r
 \r
@@ -284,7 +278,7 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
                                        app.sessionExpired();\r
                                }\r
             };\r
-            updateFile.setHeader("X-Auth-Token", app.getToken());\r
+            updateFile.setHeader("X-Auth-Token", app.getUserToken());\r
             updateFile.setHeader("X-Object-Public", published.toString());\r
             Scheduler.get().scheduleDeferred(updateFile);\r
         }\r
index 141d4ba..32be778 100644 (file)
@@ -100,8 +100,6 @@ public class FileUploadDialog extends DialogBox {
                });
                // Set the dialog's caption.
                setText("File upload");
-               setAnimationEnabled(true);
-//             setGlassEnabled(true);
                setStyleName("pithos-DialogBox");
                setVisible(false);
                
@@ -202,7 +200,7 @@ public class FileUploadDialog extends DialogBox {
                                        FilesAdded: function(up, files) {
                                                var api = app.@gr.grnet.pithos.web.client.Pithos::getApiPath()();
                                                var folder = app.@gr.grnet.pithos.web.client.Pithos::getUploadFolder()();
-                                               var owner = folder.@gr.grnet.pithos.web.client.foldertree.Folder::getOwner()();
+                                               var owner = folder.@gr.grnet.pithos.web.client.foldertree.Folder::getOwnerID()();
                                                var uri = folder.@gr.grnet.pithos.web.client.foldertree.Folder::getUri()();
                                                var path = api + owner + uri;
                                                for (var j=0; j<files.length; j++)
@@ -343,7 +341,7 @@ public class FileUploadDialog extends DialogBox {
                setVisible(true);
                setModal(true);
                super.center();
-               setupUpload(this, app, app.getToken());
+               setupUpload(this, app, app.getUserToken());
                super.center();
        }
        
index 87d4398..ea5569f 100644 (file)
@@ -51,7 +51,6 @@ import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.user.client.Command;\r
 import com.google.gwt.user.client.ui.Anchor;\r
 import com.google.gwt.user.client.ui.Button;\r
-import com.google.gwt.user.client.ui.CheckBox;\r
 import com.google.gwt.user.client.ui.FocusPanel;\r
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
 import com.google.gwt.user.client.ui.VerticalPanel;\r
@@ -105,7 +104,6 @@ public class FileVersionsDialog extends AbstractPropertiesDialog {
                });\r
                // Set the dialog's caption.\r
                setText("File versions");\r
-               setAnimationEnabled(true);\r
                setGlassEnabled(true);\r
                setStyleName("pithos-DialogBox");\r
 \r
@@ -148,7 +146,7 @@ public class FileVersionsDialog extends AbstractPropertiesDialog {
 \r
     protected void fetchVersions() {\r
        String path = file.getUri() + "?format=json&version=list";\r
-       GetRequest<FileVersions> getVersions = new GetRequest<FileVersions>(FileVersions.class, app.getApiPath(), file.getOwner(), path) {\r
+       GetRequest<FileVersions> getVersions = new GetRequest<FileVersions>(app, FileVersions.class, app.getApiPath(), file.getOwnerID(), path) {\r
 \r
                        @Override\r
                        public void onSuccess(FileVersions _result) {\r
@@ -172,7 +170,7 @@ public class FileVersionsDialog extends AbstractPropertiesDialog {
                                app.sessionExpired();\r
                        }\r
                };\r
-               getVersions.setHeader("X-Auth-Token", app.getToken());\r
+               getVersions.setHeader("X-Auth-Token", app.getUserToken());\r
                Scheduler.get().scheduleDeferred(getVersions);\r
        }\r
 \r
index a25ae9f..464a43a 100644 (file)
@@ -79,12 +79,11 @@ public class FolderContextMenu extends PopupPanel {
                // The popup's constructor's argument is a boolean specifying that it
                // auto-close itself when the user clicks outside of it.
                super(true);
-               setAnimationEnabled(true);
                images = newImages;
         MenuBar contextMenu = new MenuBar(true);
 
-        Boolean[] permissions = folder.getPermissions().get(app.getUsername());
-       boolean canWrite = folder.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
+        Boolean[] permissions = folder.getPermissions().get(app.getUserID());
+       boolean canWrite = folder.getOwnerID().equals(app.getUserID()) || (permissions!= null && permissions[1] != null && permissions[1]);
        boolean isFolderTreeSelected = selectedTree.equals(app.getFolderTreeView());
        boolean otherSharedTreeSelected = selectedTree.equals(app.getOtherSharedTreeView());
        boolean mysharedTreeSelected = selectedTree.equals(app.getMySharedTreeView());
index 720b02e..18dfb24 100644 (file)
  */\r
 package gr.grnet.pithos.web.client;\r
 \r
-import gr.grnet.pithos.web.client.commands.CreateGroupCommand;\r
-import gr.grnet.pithos.web.client.foldertree.File;\r
 import gr.grnet.pithos.web.client.foldertree.Folder;\r
-import gr.grnet.pithos.web.client.foldertree.Resource;\r
 import gr.grnet.pithos.web.client.rest.PostRequest;\r
 import gr.grnet.pithos.web.client.rest.PutRequest;\r
 import gr.grnet.pithos.web.client.rest.RestException;\r
 \r
-import java.util.Iterator;\r
 import java.util.Map;\r
 \r
 import com.google.gwt.core.client.GWT;\r
@@ -97,7 +93,6 @@ public class FolderPermissionsDialog extends DialogBox {
                        }\r
                });\r
 \r
-               setAnimationEnabled(true);\r
                setGlassEnabled(true);\r
                setStyleName("pithos-DialogBox");\r
 \r
@@ -120,7 +115,7 @@ public class FolderPermissionsDialog extends DialogBox {
 \r
         VerticalPanel permPanel = new VerticalPanel();\r
         FilePermissionsDialog.Images images = GWT.create(FilePermissionsDialog.Images.class);\r
-        permList = new PermissionsList(images, folder.getPermissions(), folder.getOwner(), false, null);\r
+        permList = new PermissionsList(app, images, folder.getPermissions(), folder.getOwnerID(), false, null);\r
         permPanel.add(permList);\r
 \r
         HorizontalPanel permButtons = new HorizontalPanel();\r
@@ -220,7 +215,7 @@ public class FolderPermissionsDialog extends DialogBox {
 \r
        protected void updateMetadata(final String path, final Map<String, Boolean[]> newPermissions) {\r
         if (newPermissions != null) {\r
-            PostRequest updateFolder = new PostRequest(app.getApiPath(), folder.getOwner(), path) {\r
+            PostRequest updateFolder = new PostRequest(app, app.getApiPath(), folder.getOwnerID(), path) {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
                     app.updateFolder(folder.getParent(), false, new Command() {\r
@@ -239,7 +234,7 @@ public class FolderPermissionsDialog extends DialogBox {
                     if (t instanceof RestException) {\r
                        if (((RestException) t).getHttpStatusCode() == Response.SC_NOT_FOUND) { //Probably a virtual folder\r
                             final String path1 = folder.getUri();\r
-                            PutRequest newFolder = new PutRequest(app.getApiPath(), folder.getOwner(), path1) {\r
+                            PutRequest newFolder = new PutRequest(app, app.getApiPath(), folder.getOwnerID(), path1) {\r
                                 @Override\r
                                 public void onSuccess(Resource result) {\r
                                        updateMetadata(path, newPermissions);\r
@@ -261,7 +256,7 @@ public class FolderPermissionsDialog extends DialogBox {
                                                        app.sessionExpired();\r
                                                }\r
                             };\r
-                            newFolder.setHeader("X-Auth-Token", app.getToken());\r
+                            newFolder.setHeader("X-Auth-Token", app.getUserToken());\r
                             newFolder.setHeader("Content-Type", "application/folder");\r
                             newFolder.setHeader("Accept", "*/*");\r
                             newFolder.setHeader("Content-Length", "0");\r
@@ -282,7 +277,7 @@ public class FolderPermissionsDialog extends DialogBox {
                                        app.sessionExpired();\r
                                }\r
             };\r
-            updateFolder.setHeader("X-Auth-Token", app.getToken());\r
+            updateFolder.setHeader("X-Auth-Token", app.getUserToken());\r
             String readPermHeader = "read=";\r
             String writePermHeader = "write=";\r
             for (String u : newPermissions.keySet()) {\r
index 245b059..9847b46 100644 (file)
  */\r
 package gr.grnet.pithos.web.client;\r
 \r
-import gr.grnet.pithos.web.client.foldertree.File;\r
-import gr.grnet.pithos.web.client.foldertree.Folder;\r
-import gr.grnet.pithos.web.client.foldertree.Resource;\r
-import gr.grnet.pithos.web.client.rest.PutRequest;\r
-import gr.grnet.pithos.web.client.rest.RestException;\r
-\r
-import java.util.Iterator;\r
-\r
 import com.google.gwt.core.client.GWT;\r
 import com.google.gwt.core.client.Scheduler;\r
 import com.google.gwt.dom.client.NativeEvent;\r
-import com.google.gwt.event.dom.client.ChangeEvent;\r
-import com.google.gwt.event.dom.client.ChangeHandler;\r
-import com.google.gwt.event.dom.client.ClickEvent;\r
-import com.google.gwt.event.dom.client.ClickHandler;\r
-import com.google.gwt.event.dom.client.KeyCodes;\r
-import com.google.gwt.event.dom.client.KeyDownEvent;\r
+import com.google.gwt.event.dom.client.*;\r
 import com.google.gwt.http.client.Response;\r
 import com.google.gwt.i18n.client.DateTimeFormat;\r
 import com.google.gwt.user.client.Command;\r
 import com.google.gwt.user.client.Event.NativePreviewEvent;\r
-import com.google.gwt.user.client.ui.Anchor;\r
-import com.google.gwt.user.client.ui.Button;\r
-import com.google.gwt.user.client.ui.DialogBox;\r
-import com.google.gwt.user.client.ui.FlexTable;\r
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
-import com.google.gwt.user.client.ui.Label;\r
-import com.google.gwt.user.client.ui.TextBox;\r
-import com.google.gwt.user.client.ui.VerticalPanel;\r
+import com.google.gwt.user.client.ui.*;\r
+import gr.grnet.pithos.web.client.foldertree.Folder;\r
+import gr.grnet.pithos.web.client.rest.PutRequest;\r
+import gr.grnet.pithos.web.client.rest.RestException;\r
 \r
 /**\r
  * The 'Folder properties' dialog box implementation.\r
@@ -71,87 +54,103 @@ public class FolderPropertiesDialog extends DialogBox {
 \r
     protected Pithos app;\r
 \r
-       /**\r
-        * The widget that holds the folderName of the folder.\r
-        */\r
-       TextBox folderName = new TextBox();\r
+    /**\r
+     * The widget that holds the folderName of the folder.\r
+     */\r
+    TextBox folderName = new TextBox();\r
 \r
-       /**\r
-        * A flag that denotes whether the dialog will be used to create or modify a\r
-        * folder.\r
-        */\r
-       private final boolean create;\r
+    /**\r
+     * A flag that denotes whether the dialog will be used to create or modify a\r
+     * folder.\r
+     */\r
+    private final boolean create;\r
 \r
-       final Folder folder;\r
+    final Folder folder;\r
 \r
-       final VerticalPanel inner;\r
+    final VerticalPanel inner;\r
 \r
-       /**\r
-        * The widget's constructor.\r
-        */\r
-       public FolderPropertiesDialog(final Pithos app, boolean _create,  Folder selected) {\r
+    /**\r
+     * The widget's constructor.\r
+     */\r
+    public FolderPropertiesDialog(final Pithos app, boolean _create, Folder selected) {\r
         this.app = app;\r
-               Anchor close = new Anchor("close");\r
-               close.addStyleName("close");\r
-               close.addClickHandler(new ClickHandler() {\r
-                       \r
-                       @Override\r
-                       public void onClick(ClickEvent event) {\r
-                               hide();\r
-                       }\r
-               });\r
-\r
-               setAnimationEnabled(true);\r
-               setGlassEnabled(true);\r
-               setStyleName("pithos-DialogBox");\r
-\r
-               // Enable IE selection for the dialog (must disable it upon closing it)\r
-               Pithos.enableIESelection();\r
-\r
-               create = _create;\r
-               \r
-               folder = selected;\r
-\r
-               // Use this opportunity to set the dialog's caption.\r
-               if (create)\r
-                       setText("Create folder");\r
-               else\r
-                       setText("Folder properties");\r
-\r
-               // Outer contains inner and buttons\r
-               VerticalPanel outer = new VerticalPanel();\r
-               outer.add(close);\r
-               // Inner contains generalPanel and permPanel\r
-               inner = new VerticalPanel();\r
-               inner.addStyleName("inner");\r
-\r
-               VerticalPanel generalPanel = new VerticalPanel();\r
+        Anchor close = new Anchor("close");\r
+        close.addStyleName("close");\r
+        close.addClickHandler(new ClickHandler() {\r
+\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                hide();\r
+            }\r
+        });\r
+\r
+        setGlassEnabled(true);\r
+        setStyleName("pithos-DialogBox");\r
+\r
+        // Enable IE selection for the dialog (must disable it upon closing it)\r
+        Pithos.enableIESelection();\r
+\r
+        create = _create;\r
+\r
+        folder = selected;\r
+\r
+        // Use this opportunity to set the dialog's caption.\r
+        if(create) {\r
+            setText("Create folder");\r
+        }\r
+        else {\r
+            setText("Folder properties");\r
+        }\r
+\r
+        // Outer contains inner and buttons\r
+        VerticalPanel outer = new VerticalPanel();\r
+        outer.add(close);\r
+        // Inner contains generalPanel and permPanel\r
+        inner = new VerticalPanel();\r
+        inner.addStyleName("inner");\r
+\r
+        VerticalPanel generalPanel = new VerticalPanel();\r
         FlexTable generalTable = new FlexTable();\r
         generalTable.setText(0, 0, "Name");\r
         generalTable.setText(1, 0, "Parent");\r
         generalTable.setText(2, 0, "Creator");\r
         generalTable.setText(3, 0, "Last modified");\r
 \r
-               folderName.setText(create ? "" : folder.getName());\r
+        folderName.setText(create ? "" : folder.getName());\r
         folderName.setReadOnly(folder.isContainer() && !create);\r
         generalTable.setWidget(0, 1, folderName);\r
 \r
         final Label folderNameNote = new Label("Please note that slashes ('/') are not allowed in folder names.", true);\r
-               folderNameNote.setVisible(false);\r
-               folderNameNote.setStylePrimaryName("gss-readForAllNote");\r
-               generalTable.setWidget(0, 2, folderNameNote);\r
-               \r
-        if (create)\r
+        folderNameNote.setVisible(false);\r
+        folderNameNote.setStylePrimaryName("gss-readForAllNote");\r
+        generalTable.setWidget(0, 2, folderNameNote);\r
+\r
+        if(create) {\r
             generalTable.setText(1, 1, folder.getName());\r
-        else\r
+        }\r
+        else {\r
             generalTable.setText(1, 1, folder.getParent().getName());\r
-        if (create)\r
-               generalTable.setText(2, 1, app.getUsername());\r
-        else\r
-               generalTable.setText(2, 1, folder.getOwner());\r
+        }\r
+        if(create) {\r
+            generalTable.setText(2, 1, app.getCurrentUserDisplayNameOrID());\r
+        }\r
+        else {\r
+            final String ownerID = folder.getOwnerID();\r
+            final String displayName = app.getUserDisplayNameForID(ownerID);\r
+            final String ownerDisplayName;\r
+            if(displayName == null) {\r
+                // FIXME: Get the actual display name and do not use the id\r
+                ownerDisplayName = ownerID;\r
+            }\r
+            else {\r
+                ownerDisplayName = displayName;\r
+            }\r
+            generalTable.setText(2, 1, ownerDisplayName);\r
+        }\r
         DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");\r
-        if(folder.getLastModified() != null)\r
+        if(folder.getLastModified() != null) {\r
             generalTable.setText(3, 1, formatter.format(folder.getLastModified()));\r
+        }\r
         generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");\r
         generalTable.getFlexCellFormatter().setStyleName(1, 0, "props-labels");\r
         generalTable.getFlexCellFormatter().setStyleName(2, 0, "props-labels");\r
@@ -166,160 +165,170 @@ public class FolderPropertiesDialog extends DialogBox {
 \r
         outer.add(inner);\r
 \r
-               // Create the 'Create/Update' button, along with a listener that hides the dialog\r
-               // when the button is clicked and quits the application.\r
-               String okLabel;\r
-               if (create)\r
-                       okLabel = "Create";\r
-               else\r
-                       okLabel = "Update";\r
-               final Button ok = new Button(okLabel, new ClickHandler() {\r
-                       @Override\r
-                       public void onClick(ClickEvent event) {\r
-                               createOrUpdateFolder();\r
-                               closeDialog();\r
-                       }\r
-               });\r
-               ok.addStyleName("button");\r
-               outer.add(ok);\r
+        // Create the 'Create/Update' button, along with a listener that hides the dialog\r
+        // when the button is clicked and quits the application.\r
+        String okLabel;\r
+        if(create) {\r
+            okLabel = "Create";\r
+        }\r
+        else {\r
+            okLabel = "Update";\r
+        }\r
+        final Button ok = new Button(okLabel, new ClickHandler() {\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                createOrUpdateFolder();\r
+                closeDialog();\r
+            }\r
+        });\r
+        ok.addStyleName("button");\r
+        outer.add(ok);\r
         outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
 \r
         folderName.addChangeHandler(new ChangeHandler() {\r
-                       \r
-                       @Override\r
-                       public void onChange(ChangeEvent event) {\r
-                               if(folderName.getText().contains("/")) {\r
-                                       folderNameNote.setVisible(true);\r
-                                       ok.setEnabled(false);\r
-                               }\r
-                               else {\r
-                                       folderNameNote.setVisible(false);\r
-                                       ok.setEnabled(true);\r
-                               }\r
-                       }\r
-               });\r
+\r
+            @Override\r
+            public void onChange(ChangeEvent event) {\r
+                if(folderName.getText().contains("/")) {\r
+                    folderNameNote.setVisible(true);\r
+                    ok.setEnabled(false);\r
+                }\r
+                else {\r
+                    folderNameNote.setVisible(false);\r
+                    ok.setEnabled(true);\r
+                }\r
+            }\r
+        });\r
 \r
         setWidget(outer);\r
-       }\r
-\r
-       @Override\r
-       public void center() {\r
-               super.center();\r
-               folderName.setFocus(true);\r
-       }\r
-\r
-       @Override\r
-       protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
-               super.onPreviewNativeEvent(preview);\r
-\r
-               NativeEvent evt = preview.getNativeEvent();\r
-               if (evt.getType().equals(KeyDownEvent.getType().getName()))\r
-                       // Use the popup's key preview hooks to close the dialog when either\r
-                       // enter or escape is pressed.\r
-                       switch (evt.getKeyCode()) {\r
-                               case KeyCodes.KEY_ENTER:\r
-                                       createOrUpdateFolder();\r
+    }\r
+\r
+    @Override\r
+    public void center() {\r
+        super.center();\r
+        folderName.setFocus(true);\r
+    }\r
+\r
+    @Override\r
+    protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
+        super.onPreviewNativeEvent(preview);\r
+\r
+        NativeEvent evt = preview.getNativeEvent();\r
+        if(evt.getType().equals(KeyDownEvent.getType().getName()))\r
+        // Use the popup's key preview hooks to close the dialog when either\r
+        // enter or escape is pressed.\r
+        {\r
+            switch(evt.getKeyCode()) {\r
+                case KeyCodes.KEY_ENTER:\r
+                    createOrUpdateFolder();\r
+                    closeDialog();\r
+                    break;\r
+                case KeyCodes.KEY_ESCAPE:\r
                     closeDialog();\r
-                                       break;\r
-                               case KeyCodes.KEY_ESCAPE:\r
-                                       closeDialog();\r
-                                       break;\r
-                       }\r
-       }\r
-\r
-\r
-       /**\r
-        * Enables IE selection prevention and hides the dialog\r
-        * (we disable the prevention on creation of the dialog)\r
-        */\r
-       public void closeDialog() {\r
-               Pithos.preventIESelection();\r
-               hide();\r
-       }\r
-\r
-       /**\r
-        * Generate an RPC request to create a new folder.\r
-        */\r
-       private void createFolder() {\r
-               String name = folderName.getText().trim();\r
-               if (name.length() == 0)\r
-                       return;\r
+                    break;\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+    /**\r
+     * Enables IE selection prevention and hides the dialog\r
+     * (we disable the prevention on creation of the dialog)\r
+     */\r
+    public void closeDialog() {\r
+        Pithos.preventIESelection();\r
+        hide();\r
+    }\r
+\r
+    /**\r
+     * Generate an RPC request to create a new folder.\r
+     */\r
+    private void createFolder() {\r
+        String name = folderName.getText().trim();\r
+        if(name.length() == 0) {\r
+            return;\r
+        }\r
         String path = folder.getUri() + "/" + name;\r
-        PutRequest createFolder = new PutRequest(app.getApiPath(), folder.getOwner(), path) {\r
+        PutRequest createFolder = new PutRequest(app, app.getApiPath(), folder.getOwnerID(), path) {\r
             @Override\r
             public void onSuccess(Resource result) {\r
                 app.updateFolder(folder, true, new Command() {\r
-                                       \r
-                                       @Override\r
-                                       public void execute() {\r
-                                               app.updateStatistics();\r
-                                       }\r
-                               }, true);\r
+\r
+                    @Override\r
+                    public void execute() {\r
+                        app.updateStatistics();\r
+                    }\r
+                }, true);\r
             }\r
 \r
             @Override\r
             public void onError(Throwable t) {\r
-                               GWT.log("", t);\r
-                               app.setError(t);\r
-                               if (t instanceof RestException) {\r
-                                       app.displayError("Unable to create folder:" + ((RestException) t).getHttpStatusText());\r
-                               }\r
-                               else\r
-                                       app.displayError("System error creating folder:" + t.getMessage());\r
+                GWT.log("", t);\r
+                app.setError(t);\r
+                if(t instanceof RestException) {\r
+                    app.displayError("Unable to create folder:" + ((RestException) t).getHttpStatusText());\r
+                }\r
+                else {\r
+                    app.displayError("System error creating folder:" + t.getMessage());\r
+                }\r
             }\r
 \r
-                       @Override\r
-                       protected void onUnauthorized(Response response) {\r
-                               app.sessionExpired();\r
-                       }\r
-       };\r
-        createFolder.setHeader("X-Auth-Token", app.getToken());\r
+            @Override\r
+            protected void onUnauthorized(Response response) {\r
+                app.sessionExpired();\r
+            }\r
+        };\r
+        createFolder.setHeader("X-Auth-Token", app.getUserToken());\r
         createFolder.setHeader("Accept", "*/*");\r
         createFolder.setHeader("Content-Length", "0");\r
         createFolder.setHeader("Content-Type", "application/directory");\r
         Scheduler.get().scheduleDeferred(createFolder);\r
-       }\r
-\r
-       /**\r
-        * Upon closing the dialog by clicking OK or pressing ENTER this method does\r
-        * the actual work of modifying folder properties or creating a new Folder\r
-        * depending on the value of the create field\r
-        */\r
-       protected void createOrUpdateFolder() {\r
-               if (create)\r
-                       createFolder();\r
-               else\r
-                       updateFolder();\r
-\r
-       }\r
-\r
-       private void updateFolder() {\r
+    }\r
+\r
+    /**\r
+     * Upon closing the dialog by clicking OK or pressing ENTER this method does\r
+     * the actual work of modifying folder properties or creating a new Folder\r
+     * depending on the value of the create field\r
+     */\r
+    protected void createOrUpdateFolder() {\r
+        if(create) {\r
+            createFolder();\r
+        }\r
+        else {\r
+            updateFolder();\r
+        }\r
+\r
+    }\r
+\r
+    private void updateFolder() {\r
         final String newName = folderName.getText().trim();\r
-        if (newName.length() == 0)\r
-               return;\r
-        if (!folder.isContainer() && !folder.getName().equals(newName)) {\r
+        if(newName.length() == 0) {\r
+            return;\r
+        }\r
+        if(!folder.isContainer() && !folder.getName().equals(newName)) {\r
             final String path = folder.getParent().getUri() + "/" + newName;\r
-            app.copyFolder(folder, folder.getOwner(), path, true, new Command() {\r
-                               \r
-                               @Override\r
-                               public void execute() {\r
+            app.copyFolder(folder, folder.getOwnerID(), path, true, new Command() {\r
+\r
+                @Override\r
+                public void execute() {\r
                     app.updateFolder(folder.getParent(), false, new Command() {\r
-                               \r
-                               @Override\r
-                               public void execute() {\r
-                                       app.updateMySharedRoot();\r
-                               }\r
-                       }, true);\r
-                               }\r
-                       });\r
+\r
+                        @Override\r
+                        public void execute() {\r
+                            app.updateMySharedRoot();\r
+                        }\r
+                    }, true);\r
+                }\r
+            });\r
         }\r
-        else\r
+        else {\r
             app.updateFolder(folder.getParent(), false, new Command() {\r
-                       \r
-                       @Override\r
-                       public void execute() {\r
-                               app.updateMySharedRoot();\r
-                       }\r
-               }, true);\r
-       }\r
+\r
+                @Override\r
+                public void execute() {\r
+                    app.updateMySharedRoot();\r
+                }\r
+            }, true);\r
+        }\r
+    }\r
 }\r
index 619f4b9..b598679 100644 (file)
  */\r
 package gr.grnet.pithos.web.client;\r
 \r
-import gr.grnet.pithos.web.client.commands.AddUserCommand;\r
-import gr.grnet.pithos.web.client.foldertree.Folder;\r
-import gr.grnet.pithos.web.client.grouptree.Group;\r
-\r
 import com.google.gwt.dom.client.NativeEvent;\r
 import com.google.gwt.event.dom.client.ClickEvent;\r
 import com.google.gwt.event.dom.client.ClickHandler;\r
@@ -45,13 +41,9 @@ import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.dom.client.KeyDownEvent;\r
 import com.google.gwt.user.client.Command;\r
 import com.google.gwt.user.client.Event.NativePreviewEvent;\r
-import com.google.gwt.user.client.ui.Anchor;\r
-import com.google.gwt.user.client.ui.Button;\r
-import com.google.gwt.user.client.ui.DialogBox;\r
-import com.google.gwt.user.client.ui.FlexTable;\r
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
-import com.google.gwt.user.client.ui.TextBox;\r
-import com.google.gwt.user.client.ui.VerticalPanel;\r
+import com.google.gwt.user.client.ui.*;\r
+import gr.grnet.pithos.web.client.commands.AddUserCommand;\r
+import gr.grnet.pithos.web.client.grouptree.Group;\r
 \r
 /**\r
  * The 'Folder properties' dialog box implementation.\r
@@ -61,57 +53,56 @@ public class GroupCreateDialog extends DialogBox {
     protected Pithos app;\r
 \r
     private Command callback;\r
-    \r
-       /**\r
-        * The widget that holds the folderName of the folder.\r
-        */\r
-       TextBox groupName = new TextBox();\r
-\r
-       final VerticalPanel inner;\r
-\r
-       public GroupCreateDialog(final Pithos app) {\r
-               this(app, null);\r
-       }\r
-       \r
-       /**\r
-        * The widget's constructor.\r
-        */\r
-       public GroupCreateDialog(final Pithos app, Command callback) {\r
+\r
+    /**\r
+     * The widget that holds the folderName of the folder.\r
+     */\r
+    TextBox groupNameTextBox = new TextBox();\r
+\r
+    final VerticalPanel inner;\r
+\r
+    public GroupCreateDialog(final Pithos app) {\r
+        this(app, null);\r
+    }\r
+\r
+    /**\r
+     * The widget's constructor.\r
+     */\r
+    public GroupCreateDialog(final Pithos app, Command callback) {\r
         this.app = app;\r
         this.callback = callback;\r
-        \r
-               Anchor close = new Anchor("close");\r
-               close.addStyleName("close");\r
-               close.addClickHandler(new ClickHandler() {\r
-                       \r
-                       @Override\r
-                       public void onClick(ClickEvent event) {\r
-                               hide();\r
-                       }\r
-               });\r
-\r
-               setAnimationEnabled(true);\r
-               setGlassEnabled(true);\r
-               setStyleName("pithos-DialogBox");\r
-\r
-               // Enable IE selection for the dialog (must disable it upon closing it)\r
-               Pithos.enableIESelection();\r
-\r
-               // Use this opportunity to set the dialog's caption.\r
-               setText("Create group");\r
-\r
-               // Outer contains inner and buttons\r
-               VerticalPanel outer = new VerticalPanel();\r
-               outer.add(close);\r
-               // Inner contains generalPanel and permPanel\r
-               inner = new VerticalPanel();\r
-               inner.addStyleName("inner");\r
-\r
-               VerticalPanel generalPanel = new VerticalPanel();\r
+\r
+        Anchor close = new Anchor("close");\r
+        close.addStyleName("close");\r
+        close.addClickHandler(new ClickHandler() {\r
+\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                hide();\r
+            }\r
+        });\r
+\r
+        setGlassEnabled(true);\r
+        setStyleName("pithos-DialogBox");\r
+\r
+        // Enable IE selection for the dialog (must disable it upon closing it)\r
+        Pithos.enableIESelection();\r
+\r
+        // Use this opportunity to set the dialog's caption.\r
+        setText("Create group");\r
+\r
+        // Outer contains inner and buttons\r
+        VerticalPanel outer = new VerticalPanel();\r
+        outer.add(close);\r
+        // Inner contains generalPanel and permPanel\r
+        inner = new VerticalPanel();\r
+        inner.addStyleName("inner");\r
+\r
+        VerticalPanel generalPanel = new VerticalPanel();\r
         FlexTable generalTable = new FlexTable();\r
         generalTable.setText(0, 0, "Name");\r
 \r
-        generalTable.setWidget(0, 1, groupName);\r
+        generalTable.setWidget(0, 1, groupNameTextBox);\r
 \r
         generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");\r
         generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");\r
@@ -121,69 +112,73 @@ public class GroupCreateDialog extends DialogBox {
 \r
         outer.add(inner);\r
 \r
-               // Create the 'Create/Update' button, along with a listener that hides the dialog\r
-               // when the button is clicked and quits the application.\r
-               String okLabel = "Create";\r
-               final Button ok = new Button(okLabel, new ClickHandler() {\r
-                       @Override\r
-                       public void onClick(ClickEvent event) {\r
-                               createGroup();\r
-                               closeDialog();\r
-                       }\r
-               });\r
-               ok.addStyleName("button");\r
-               outer.add(ok);\r
+        // Create the 'Create/Update' button, along with a listener that hides the dialog\r
+        // when the button is clicked and quits the application.\r
+        String okLabel = "Create";\r
+        final Button ok = new Button(okLabel, new ClickHandler() {\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                createGroup();\r
+                closeDialog();\r
+            }\r
+        });\r
+        ok.addStyleName("button");\r
+        outer.add(ok);\r
         outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
 \r
         setWidget(outer);\r
-       }\r
-\r
-       @Override\r
-       public void center() {\r
-               super.center();\r
-               groupName.setFocus(true);\r
-       }\r
-\r
-       @Override\r
-       protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
-               super.onPreviewNativeEvent(preview);\r
-\r
-               NativeEvent evt = preview.getNativeEvent();\r
-               if (evt.getType().equals(KeyDownEvent.getType().getName()))\r
-                       // Use the popup's key preview hooks to close the dialog when either\r
-                       // enter or escape is pressed.\r
-                       switch (evt.getKeyCode()) {\r
-                               case KeyCodes.KEY_ENTER:\r
-                                       createGroup();\r
+    }\r
+\r
+    @Override\r
+    public void center() {\r
+        super.center();\r
+        groupNameTextBox.setFocus(true);\r
+    }\r
+\r
+    @Override\r
+    protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
+        super.onPreviewNativeEvent(preview);\r
+\r
+        NativeEvent evt = preview.getNativeEvent();\r
+        if(evt.getType().equals(KeyDownEvent.getType().getName()))\r
+        // Use the popup's key preview hooks to close the dialog when either\r
+        // enter or escape is pressed.\r
+        {\r
+            switch(evt.getKeyCode()) {\r
+                case KeyCodes.KEY_ENTER:\r
+                    createGroup();\r
+                    closeDialog();\r
+                    break;\r
+                case KeyCodes.KEY_ESCAPE:\r
                     closeDialog();\r
-                                       break;\r
-                               case KeyCodes.KEY_ESCAPE:\r
-                                       closeDialog();\r
-                                       break;\r
-                       }\r
-       }\r
-\r
-\r
-       /**\r
-        * Enables IE selection prevention and hides the dialog\r
-        * (we disable the prevention on creation of the dialog)\r
-        */\r
-       public void closeDialog() {\r
-               Pithos.preventIESelection();\r
-               hide();\r
-               if (callback != null)\r
-                       callback.execute();\r
-       }\r
-\r
-       /**\r
-        * Generate an RPC request to create a new folder.\r
-        */\r
-       void createGroup() {\r
-               String name = groupName.getText().trim();\r
-               if (name.length() == 0)\r
-                       return;\r
-               Group group = app.addGroup(name);\r
-               \r
-               new AddUserCommand(app, null, group).execute();\r
-       }\r
+                    break;\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+    /**\r
+     * Enables IE selection prevention and hides the dialog\r
+     * (we disable the prevention on creation of the dialog)\r
+     */\r
+    public void closeDialog() {\r
+        Pithos.preventIESelection();\r
+        hide();\r
+        if(callback != null) {\r
+            callback.execute();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Generate an RPC request to create a new folder.\r
+     */\r
+    void createGroup() {\r
+        final String groupName = groupNameTextBox.getText().trim();\r
+        if(groupName.length() == 0) {\r
+            return;\r
+        }\r
+        Group group = app.addGroup(groupName);\r
+\r
+        new AddUserCommand(app, null, group).execute();\r
+    }\r
 }\r
diff --git a/src/gr/grnet/pithos/web/client/Helpers.java b/src/gr/grnet/pithos/web/client/Helpers.java
new file mode 100644 (file)
index 0000000..4b2b44d
--- /dev/null
@@ -0,0 +1,67 @@
+package gr.grnet.pithos.web.client;
+
+import com.google.gwt.json.client.JSONArray;
+import com.google.gwt.json.client.JSONString;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Helper methods.
+ */
+public final class Helpers {
+    private Helpers() {}
+
+    public static boolean isEmptySafe(CharSequence s) {
+        return s == null || s.length() == 0;
+    }
+
+    public static <K, V> HashMap<K, V> copyHashMap(HashMap<K, V> map) {
+        assert map != null;
+        return new HashMap<K, V>(map);
+    }
+
+    public static <T> List<T> safeList(List<T> list) {
+        if(list == null) {
+            return new ArrayList<T>();
+        }
+        return list;
+    }
+
+    public static <T> List<T> toList(T ...items) {
+        final List<T> list = new ArrayList<T>();
+        Collections.addAll(list, items);
+        return list;
+    }
+
+    public static JSONArray listToJSONArray(List<String> list) {
+        final JSONArray jsonArray = new JSONArray();
+        if(list == null) {
+            return jsonArray;
+        }
+
+        for(int i = 0; i < list.size(); i++) {
+            final JSONString jsonString = new JSONString(list.get(i));
+            jsonArray.set(i, jsonString);
+        }
+
+        return jsonArray;
+    }
+
+    public static String stripTrailing(String s, String trailing) {
+        while(s.endsWith(trailing)) {
+            s = s.substring(0, s.length() - trailing.length());
+        }
+        return s;
+    }
+
+    public static String upToIncludingLastPart(String s, String part) {
+        int index = s.lastIndexOf(part);
+        if(index == -1) {
+            return s;
+        }
+        return s.substring(0, index + part.length());
+    }
+}
index f7590e7..d6b5954 100644 (file)
@@ -44,8 +44,6 @@ import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONParser;
 import com.google.gwt.json.client.JSONValue;
 
-import gr.grnet.pithos.web.client.foldertree.Resource;
-
 public class Invitations extends Resource {
 
        private int invitationsLeft = 0;
index 5b142f3..55f60b8 100644 (file)
@@ -34,9 +34,6 @@
  */\r
 package gr.grnet.pithos.web.client;\r
 \r
-import gr.grnet.pithos.web.client.animation.FadeIn;\r
-import gr.grnet.pithos.web.client.animation.FadeOut;\r
-\r
 import com.google.gwt.core.client.GWT;\r
 import com.google.gwt.event.dom.client.ClickEvent;\r
 import com.google.gwt.event.dom.client.ClickHandler;\r
@@ -118,15 +115,7 @@ public class MessagePanel extends Composite {
 \r
                        @Override\r
                        public void onClick(ClickEvent event) {\r
-                               FadeOut anim = new FadeOut(simplePanel){\r
-\r
-                                       @Override\r
-                                       protected void onComplete() {\r
-                                               super.onComplete();\r
-                                               hideMessage();\r
-                                       }\r
-                               };\r
-                               anim.run(500);\r
+                               hideMessage();\r
                        }\r
                });\r
                inner.add(message);\r
@@ -142,14 +131,7 @@ public class MessagePanel extends Composite {
 \r
                        @Override\r
                        public void onClick(ClickEvent event) {\r
-                               FadeOut anim = new FadeOut(simplePanel){\r
-                                       @Override\r
-                                       protected void onComplete() {\r
-                                               super.onComplete();\r
-                                               hideMessage();\r
-                                       }\r
-                               };\r
-                               anim.run(500);\r
+                               hideMessage();\r
                        }\r
                });\r
                linkPanel.add(clearMessageLink);\r
@@ -181,8 +163,6 @@ public class MessagePanel extends Composite {
                message.setHTML("<table class='pithos-errorMessage'><tr><td>" + AbstractImagePrototype.create(images.error()).getHTML() + "</td><td>" + msg + "</td></tr></table>");\r
                feedbackLink.setVisible(true);\r
                setVisible(true);\r
-               FadeIn anim = new FadeIn(simplePanel);\r
-               anim.run(500);\r
        }\r
 \r
        /**\r
@@ -194,8 +174,6 @@ public class MessagePanel extends Composite {
                message.setHTML("<table class='pithos-warnMessage'><tr><td>" + AbstractImagePrototype.create(images.warn()).getHTML() + "</td><td>" + msg + "</td></tr></table>");\r
                feedbackLink.setVisible(false);\r
                setVisible(true);\r
-               FadeIn anim = new FadeIn(simplePanel);\r
-               anim.run(500);\r
        }\r
 \r
        /**\r
@@ -207,8 +185,6 @@ public class MessagePanel extends Composite {
                message.setHTML("<table class='pithos-infoMessage'><tr><td>" + AbstractImagePrototype.create(images.info()).getHTML() + "</td><td>" + msg + "</td></tr></table>");\r
                feedbackLink.setVisible(false);\r
                setVisible(true);\r
-               FadeIn anim = new FadeIn(simplePanel);\r
-               anim.run(500);\r
        }\r
 \r
        /**\r
index dd7e052..ffd3701 100644 (file)
  */
 package gr.grnet.pithos.web.client;
 
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.Response;
+import com.google.gwt.json.client.JSONObject;
+import gr.grnet.pithos.web.client.catalog.GetUserCatalogs;
+import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
+import gr.grnet.pithos.web.client.catalog.UserCatalogs;
 import gr.grnet.pithos.web.client.grouptree.Group;
 
 import java.util.List;
@@ -46,7 +52,6 @@ import com.google.gwt.regexp.shared.RegExp;
 import com.google.gwt.user.client.Event.NativePreviewEvent;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
 import com.google.gwt.user.client.ui.DialogBox;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
@@ -56,6 +61,7 @@ import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
 
 public class PermissionsAddDialog extends DialogBox {
+    final static RegExp EmailValidator = RegExp.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+[.][A-Z]{2,4}$", "i");
 
        private TextBox userBox = new TextBox();
 
@@ -106,8 +112,9 @@ public class PermissionsAddDialog extends DialogBox {
             permTable.setWidget(1, 0, userBox);
         }
         else {
-            for (Group group : _groups)
+            for (Group group : _groups) {
                 groupBox.addItem(group.getName(), group.getName());
+            }
             permTable.setWidget(1, 0, groupBox);
         }
                 
@@ -138,32 +145,64 @@ public class PermissionsAddDialog extends DialogBox {
        }
 
        protected void addPermission() {
+        final boolean readValue = read.getValue();
+        final boolean writeValue = write.getValue();
+
         String selected = null;
                if (userAdd) {
-                       selected = userBox.getText().trim();
-                       RegExp emailValidator = RegExp.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+[.][A-Z]{2,4}$", "i");
-                       if (!emailValidator.test(selected)) {
-                               app.displayWarning("Username must be a valid email address");
-                               return;
-                       }
+                       final String userDisplayName = userBox.getText().trim();
+                       addUserPermission(userDisplayName, readValue, writeValue);
+            return;
                } else if (groupBox.getSelectedIndex() > -1) {
                        String groupName = groupBox.getValue(groupBox.getSelectedIndex());
-                       selected = app.getUsername() + ":" + groupName;
+                       selected = app.getUserID() + ":" + groupName;
                }
         if (permList.getPermissions().get(selected) != null) {
             return;
         }
-        if (selected == null || selected.length() == 0 || selected.equals(app.getUsername() + ":")) {
+        if (selected == null || selected.length() == 0 || selected.equals(app.getUserID() + ":")) {
                app.displayWarning("You have to select a username or group");
                return;
         }
 
-               boolean readValue = read.getValue();
-               boolean writeValue = write.getValue();
-
                permList.addPermission(selected, readValue, writeValue);
        }
 
+    private boolean alreadyHasPermission(String selected) {
+        return permList.getPermissions().get(selected) != null;
+    }
+
+    private void addUserPermission(final String userDisplayName, final boolean readValue, final boolean writeValue) {
+        if (!EmailValidator.test(userDisplayName)) {
+            app.displayWarning("Username must be a valid email address");
+            return;
+        }
+
+        // Now get the userID
+        final String userID = app.getUserIDForDisplayName(userDisplayName);
+        if(userID != null) {
+            // Check if already have the permission
+            if(!alreadyHasPermission(userID)) {
+                permList.addPermission(userID, readValue, writeValue);
+            }
+        }
+        else {
+            // Must call server to obtain userID
+            new UpdateUserCatalogs(app, null, Helpers.toList(userDisplayName)) {
+                @Override
+                public void onSuccess(UserCatalogs requestedUserCatalogs, UserCatalogs updatedUserCatalogs) {
+                    final String userID = updatedUserCatalogs.getUserID(userDisplayName);
+                    if(userID == null) {
+                        app.displayWarning("Unknown user " + userDisplayName);
+                    }
+                    else if(!alreadyHasPermission(userID)) {
+                        permList.addPermission(userID, readValue, writeValue);
+                    }
+                }
+            }.scheduleDeferred();
+        }
+    }
+
        @Override
        protected void onPreviewNativeEvent(NativePreviewEvent preview) {
                super.onPreviewNativeEvent(preview);
index a1fa8a6..4f3a26f 100644 (file)
@@ -46,13 +46,13 @@ import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.CheckBox;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.PushButton;
 import com.google.gwt.user.client.ui.RadioButton;
 import com.google.gwt.user.client.ui.VerticalPanel;
+import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
+import gr.grnet.pithos.web.client.catalog.UserCatalogs;
 
 
 public class PermissionsList extends Composite {
@@ -72,8 +72,11 @@ public class PermissionsList extends Composite {
     private boolean readonly = false;
     
     Command changePermissionsCallback;
+
+    private final Pithos app;
        
-       public PermissionsList(final Images theImages, Map<String, Boolean[]> thePermissions, String theOwner, boolean inheritsPermissions, Command _changePermissionsCallback){
+       public PermissionsList(Pithos app, final Images theImages, Map<String, Boolean[]> thePermissions, String theOwner, boolean inheritsPermissions, Command _changePermissionsCallback){
+        this.app = app;
                changePermissionsCallback = _changePermissionsCallback;
                images = theImages;
                owner = theOwner;
@@ -105,8 +108,8 @@ public class PermissionsList extends Composite {
                return permissions;
        }
 
-       public void addPermission(String user, boolean read, boolean write){
-               permissions.put(user, new Boolean[] {Boolean.valueOf(read), Boolean.valueOf(write)});
+       public void addPermission(String userID, boolean read, boolean write){
+               permissions.put(userID, new Boolean[] {Boolean.valueOf(read), Boolean.valueOf(write)});
                hasChanges = true;
         updatePermissionTable();
         if (changePermissionsCallback != null)
@@ -119,16 +122,40 @@ public class PermissionsList extends Composite {
         */
        void updatePermissionTable(){
                int i = 1;
+        final int ii = i;
         for (int j=1; j<permTable.getRowCount(); j++)
             permTable.removeRow(j);
-               for(final String user : permissions.keySet()) {
-            if (!user.contains(":")) //not a group
-                permTable.setHTML(i, 0, "<span>" + AbstractImagePrototype.create(images.permUser()).getHTML() + "&nbsp;" + user + "</span>");
-            else
-                permTable.setHTML(i, 0, "<span>" + AbstractImagePrototype.create(images.permGroup()).getHTML() + "&nbsp;" + user.split(":")[1].trim() + "</span>");
+               for(final String userID : permissions.keySet()) {
+            if (!userID.contains(":")) {
+                 //not a group
+                final String displayName = app.getUserDisplayNameForID(userID);
+                if(displayName != null) {
+                    permTable.setHTML(
+                        i,
+                        0,
+                        "<span>" + AbstractImagePrototype.create(images.permUser()).getHTML() + "&nbsp;" + displayName + "</span>"
+                    );
+                }
+                else {
+                    new UpdateUserCatalogs(app, userID) {
+                        @Override
+                        public void onSuccess(UserCatalogs requestedUserCatalogs, UserCatalogs updatedUserCatalogs) {
+                            final String displayName = updatedUserCatalogs.getUserDisplayName(userID);
+                            permTable.setHTML(
+                                ii,
+                                0,
+                                "<span>" + AbstractImagePrototype.create(images.permUser()).getHTML() + "&nbsp;" + displayName + "</span>"
+                            );
+                        }
+                    }.scheduleDeferred();
+                }
+            }
+            else {
+                permTable.setHTML(i, 0, "<span>" + AbstractImagePrototype.create(images.permGroup()).getHTML() + "&nbsp;" + userID.split(":")[1].trim() + "</span>");
+            }
             permTable.getFlexCellFormatter().setStyleName(i, 0, "props-values");
 
-            Boolean[] userPerms = permissions.get(user);
+            Boolean[] userPerms = permissions.get(userID);
             Boolean readP = userPerms[0];
             Boolean writeP = userPerms[1];
 
@@ -146,7 +173,7 @@ public class PermissionsList extends Composite {
                 read.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
                     @Override
                     public void onValueChange(ValueChangeEvent<Boolean> booleanValueChangeEvent) {
-                        Boolean[] ps = permissions.get(user);
+                        Boolean[] ps = permissions.get(userID);
                         ps[0] = booleanValueChangeEvent.getValue();
                         ps[1] = !booleanValueChangeEvent.getValue();
                         hasChanges = true;
@@ -157,7 +184,7 @@ public class PermissionsList extends Composite {
                 write.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
                     @Override
                     public void onValueChange(ValueChangeEvent<Boolean> booleanValueChangeEvent) {
-                        Boolean[] ps = permissions.get(user);
+                        Boolean[] ps = permissions.get(userID);
                         ps[0] = !booleanValueChangeEvent.getValue();
                         ps[1] = booleanValueChangeEvent.getValue();
                         hasChanges = true;
@@ -170,7 +197,7 @@ public class PermissionsList extends Composite {
                 removeButton.addClickHandler(new ClickHandler() {
                     @Override
                     public void onClick(ClickEvent event) {
-                        permissions.remove(user);
+                        permissions.remove(userID);
                         updatePermissionTable();
                         hasChanges = true;
                         if (changePermissionsCallback != null)
index dd85f2f..bec05d5 100644 (file)
  */
 package gr.grnet.pithos.web.client;
 
-import gr.grnet.pithos.web.client.commands.UploadFileCommand;
-import gr.grnet.pithos.web.client.foldertree.AccountResource;
-import gr.grnet.pithos.web.client.foldertree.File;
-import gr.grnet.pithos.web.client.foldertree.Folder;
-import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
-import gr.grnet.pithos.web.client.foldertree.FolderTreeViewModel;
-import gr.grnet.pithos.web.client.foldertree.Resource;
-import gr.grnet.pithos.web.client.grouptree.Group;
-import gr.grnet.pithos.web.client.grouptree.GroupTreeView;
-import gr.grnet.pithos.web.client.grouptree.GroupTreeViewModel;
-import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeView;
-import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeViewModel;
-import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView;
-import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeViewModel;
-import gr.grnet.pithos.web.client.rest.DeleteRequest;
-import gr.grnet.pithos.web.client.rest.GetRequest;
-import gr.grnet.pithos.web.client.rest.HeadRequest;
-import gr.grnet.pithos.web.client.rest.PutRequest;
-import gr.grnet.pithos.web.client.rest.RestException;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.http.HttpStatus;
-
 import com.google.gwt.core.client.EntryPoint;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JsArrayString;
@@ -82,75 +53,122 @@ import com.google.gwt.resources.client.ClientBundle;
 import com.google.gwt.resources.client.CssResource;
 import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.resources.client.ImageResource.ImageOptions;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.Cookies;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.HasVerticalAlignment;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.HorizontalSplitPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.*;
+import com.google.gwt.user.client.ui.*;
 import com.google.gwt.view.client.SelectionChangeEvent;
 import com.google.gwt.view.client.SelectionChangeEvent.Handler;
 import com.google.gwt.view.client.SingleSelectionModel;
+import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
+import gr.grnet.pithos.web.client.catalog.UserCatalogs;
+import gr.grnet.pithos.web.client.commands.UploadFileCommand;
+import gr.grnet.pithos.web.client.foldertree.*;
+import gr.grnet.pithos.web.client.grouptree.Group;
+import gr.grnet.pithos.web.client.grouptree.GroupTreeView;
+import gr.grnet.pithos.web.client.grouptree.GroupTreeViewModel;
+import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeView;
+import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeViewModel;
+import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView;
+import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeViewModel;
+import gr.grnet.pithos.web.client.rest.*;
+import org.apache.http.HttpStatus;
+
+import java.util.*;
 
 /**
  * Entry point classes define <code>onModuleLoad()</code>.
  */
 public class Pithos implements EntryPoint, ResizeHandler {
 
-       public static final String HOME_CONTAINER = "pithos";
-
-       public static final String TRASH_CONTAINER = "trash";
-
-       public static final Configuration config = GWT.create(Configuration.class);
-       
-       public interface Style extends CssResource {
-               String commandAnchor();
-               
-               String statistics();
-               
-               @ClassName("gwt-HTML")
-               String html();
-               
-               String uploadAlert();
-
-               String uploadAlertLink();
-
-               String uploadAlertProgress();
-               
-               String uploadAlertPercent();
-               
-               String uploadAlertClose();
-       }
-       
-       public interface Resources extends ClientBundle {
-               @Source("Pithos.css")
-               Style pithosCss();
-               
-               @Source("gr/grnet/pithos/resources/close-popup.png")
-               ImageResource closePopup();
-       }
-
-       public static Resources resources = GWT.create(Resources.class);
-       
-       /**
-        * Instantiate an application-level image bundle. This object will provide
-        * programmatic access to all the images needed by widgets.
-        */
-       static Images images = (Images) GWT.create(Images.class);
-
-    public String getUsername() {
-        return username;
+    public static final Configuration config = GWT.create(Configuration.class);
+
+    public interface Style extends CssResource {
+        String commandAnchor();
+
+        String statistics();
+
+        @ClassName("gwt-HTML")
+        String html();
+
+        String uploadAlert();
+
+        String uploadAlertLink();
+
+        String uploadAlertProgress();
+
+        String uploadAlertPercent();
+
+        String uploadAlertClose();
+    }
+
+    public interface Resources extends ClientBundle {
+        @Source("Pithos.css")
+        Style pithosCss();
+
+        @Source("gr/grnet/pithos/resources/close-popup.png")
+        ImageResource closePopup();
+    }
+
+    public static Resources resources = GWT.create(Resources.class);
+
+    /**
+     * Instantiate an application-level image bundle. This object will provide
+     * programmatic access to all the images needed by widgets.
+     */
+    static Images images = (Images) GWT.create(Images.class);
+
+    public String getUserID() {
+        return userID;
+    }
+
+    public UserCatalogs getUserCatalogs() {
+        return userCatalogs;
+    }
+
+    public String getCurrentUserDisplayNameOrID() {
+        final String displayName = userCatalogs.getUserDisplayName(getUserID());
+        return displayName == null ? getUserID() : displayName;
+    }
+
+    public boolean hasUserDisplayNameForID(String userID) {
+        return userCatalogs.getUserDisplayName(userID) != null;
+    }
+
+    public boolean hasUserIDForDisplayName(String displayName) {
+        return userCatalogs.getUserID(displayName) != null;
+    }
+
+    public String getUserDisplayNameForID(String userID) {
+        return userCatalogs.getUserDisplayName(userID);
+    }
+
+    public String getUserIDForDisplayName(String displayName) {
+        return userCatalogs.getUserID(displayName);
+    }
+
+    public List<String> getUserDisplayNamesForIDs(List<String> userIDs) {
+        if(userIDs == null) {
+            userIDs = new ArrayList<String>();
+        }
+        final List<String> userDisplayNames = new ArrayList<String>();
+        for(String userID : userIDs) {
+            final String displayName = getUserDisplayNameForID(userID);
+            userDisplayNames.add(displayName);
+        }
+
+        return userDisplayNames;
+    }
+
+    public List<String> filterUserIDsWithUnknownDisplayName(Collection<String> userIDs) {
+        if(userIDs == null) {
+            userIDs = new ArrayList<String>();
+        }
+        final List<String> filtered = new ArrayList<String>();
+        for(String userID : userIDs) {
+            if(!this.userCatalogs.hasUserID(userID)) {
+                filtered.add(userID);
+            }
+        }
+        return filtered;
     }
 
     public void setAccount(AccountResource acct) {
@@ -170,19 +188,19 @@ public class Pithos implements EntryPoint, ResizeHandler {
     }
 
     public void updateMySharedRoot() {
-       mysharedTreeView.updateRoot();
+        mysharedTreeView.updateRoot();
     }
-    
+
     public void updateSharedFolder(Folder f, boolean showfiles, Command callback) {
-       mysharedTreeView.updateFolder(f, showfiles, callback);
+        mysharedTreeView.updateFolder(f, showfiles, callback);
     }
-    
+
     public void updateSharedFolder(Folder f, boolean showfiles) {
-       updateSharedFolder(f, showfiles, null);
+        updateSharedFolder(f, showfiles, null);
     }
 
     public void updateOtherSharedFolder(Folder f, boolean showfiles, Command callback) {
-       otherSharedTreeView.updateFolder(f, showfiles, callback);
+        otherSharedTreeView.updateFolder(f, showfiles, callback);
     }
 
     public MysharedTreeView getMySharedTreeView() {
@@ -190,81 +208,90 @@ public class Pithos implements EntryPoint, ResizeHandler {
     }
 
     /**
-        * An aggregate image bundle that pulls together all the images for this
-        * application into a single bundle.
-        */
-       public interface Images extends TopPanel.Images, FileList.Images, ToolsMenu.Images {
-
-               @Source("gr/grnet/pithos/resources/document.png")
-               ImageResource folders();
-
-               @Source("gr/grnet/pithos/resources/advancedsettings.png")
-               @ImageOptions(width=32, height=32)
-               ImageResource tools();
-       }
-
-       private Throwable error;
-       
-       /**
-        * The Application Clipboard implementation;
-        */
-       private Clipboard clipboard = new Clipboard();
-
-       /**
-        * The top panel that contains the menu bar.
-        */
-       private TopPanel topPanel;
-
-       /**
-        * The panel that contains the various system messages.
-        */
-       private MessagePanel messagePanel = new MessagePanel(this, Pithos.images);
-
-       /**
-        * The bottom panel that contains the status bar.
-        */
-       StatusPanel statusPanel = null;
-
-       /**
-        * The file list widget.
-        */
-       private FileList fileList;
-
-       /**
-        * The tab panel that occupies the right side of the screen.
-        */
-       private VerticalPanel inner = new VerticalPanel();
-
-
-       /**
-        * The split panel that will contain the left and right panels.
-        */
-       private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
-
-       /**
-        * The currently selected item in the application, for use by the Edit menu
-        * commands. Potential types are Folder, File, User and Group.
-        */
-       private Object currentSelection;
-
-       public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
-
-    private String username = null;
+     * An aggregate image bundle that pulls together all the images for this
+     * application into a single bundle.
+     */
+    public interface Images extends TopPanel.Images, FileList.Images, ToolsMenu.Images {
+
+        @Source("gr/grnet/pithos/resources/document.png")
+        ImageResource folders();
+
+        @Source("gr/grnet/pithos/resources/advancedsettings.png")
+        @ImageOptions(width = 32, height = 32)
+        ImageResource tools();
+    }
+
+    private Throwable error;
+
+    /**
+     * The Application Clipboard implementation;
+     */
+    private Clipboard clipboard = new Clipboard();
+
+    /**
+     * The top panel that contains the menu bar.
+     */
+    private TopPanel topPanel;
+
+    /**
+     * The panel that contains the various system messages.
+     */
+    private MessagePanel messagePanel = new MessagePanel(this, Pithos.images);
+
+    /**
+     * The bottom panel that contains the status bar.
+     */
+    StatusPanel statusPanel = null;
+
+    /**
+     * The file list widget.
+     */
+    private FileList fileList;
+
+    /**
+     * The tab panel that occupies the right side of the screen.
+     */
+    private VerticalPanel inner = new VerticalPanel();
+
+
+    /**
+     * The split panel that will contain the left and right panels.
+     */
+    private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
+
+    /**
+     * The currently selected item in the application, for use by the Edit menu
+     * commands. Potential types are Folder, File, User and Group.
+     */
+    private Object currentSelection;
+
+    public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
+
+    /**
+     * The ID that uniquely identifies the user in Pithos+.
+     * Currently this is a UUID. It used to be the user's email.
+     */
+    private String userID = null;
+
+    /**
+     * Hold mappings from user UUIDs to emails and vice-versa.
+     */
+    private UserCatalogs userCatalogs = new UserCatalogs();
 
     /**
      * The authentication token of the current user.
      */
-    private String token;
+    private String userToken;
 
     VerticalPanel trees;
-    
+
     SingleSelectionModel<Folder> folderTreeSelectionModel;
     FolderTreeViewModel folderTreeViewModel;
     FolderTreeView folderTreeView;
 
     SingleSelectionModel<Folder> mysharedTreeSelectionModel;
     MysharedTreeViewModel mysharedTreeViewModel;
-    MysharedTreeView mysharedTreeView = null;;
+    MysharedTreeView mysharedTreeView = null;
 
     protected SingleSelectionModel<Folder> otherSharedTreeSelectionModel;
     OtherSharedTreeViewModel otherSharedTreeViewModel;
@@ -275,50 +302,69 @@ public class Pithos implements EntryPoint, ResizeHandler {
 
     TreeView selectedTree;
     protected AccountResource account;
-    
+
     Folder trash;
-    
+
     List<Composite> treeViews = new ArrayList<Composite>();
 
-    @SuppressWarnings("rawtypes") List<SingleSelectionModel> selectionModels = new ArrayList<SingleSelectionModel>();
-    
+    @SuppressWarnings("rawtypes")
+    List<SingleSelectionModel> selectionModels = new ArrayList<SingleSelectionModel>();
+
     public Button upload;
-    
+
     private HTML numOfFiles;
-    
+
     private Toolbar toolbar;
-    
+
     private FileUploadDialog fileUploadDialog = new FileUploadDialog(this);
 
-       UploadAlert uploadAlert;
-       
-       Date lastModified;
+    UploadAlert uploadAlert;
 
-       @Override
-       public void onModuleLoad() {
-               if (parseUserCredentials())
+    Date lastModified;
+
+    @Override
+    public void onModuleLoad() {
+        if(parseUserCredentials()) {
             initialize();
-       }
+        }
+    }
+
+    static native void __ConsoleLog(String message) /*-{
+      try {
+        console.log(message);
+      } catch (e) {
+      }
+    }-*/;
+
+    public static void LOG(Object ...args) {
+        final StringBuilder sb = new StringBuilder();
+        for(Object arg : args) {
+            sb.append(arg);
+        }
+        if(sb.length() > 0) {
+            __ConsoleLog(sb.toString());
+        }
+    }
 
     private void initialize() {
-       lastModified = new Date(); //Initialize if-modified-since value with now.
-       resources.pithosCss().ensureInjected();
-       boolean bareContent = Window.Location.getParameter("noframe") != null;
-       String contentWidth = bareContent ? "100%" : "75%";
-
-       VerticalPanel outer = new VerticalPanel();
-        outer.setWidth("100%");
-       if (!bareContent) {
-               outer.addStyleName("pithos-outer");
-       }
-
-        if (!bareContent) {
-               topPanel = new TopPanel(this, Pithos.images);
-               topPanel.setWidth("100%");
-               outer.add(topPanel);
-               outer.setCellHorizontalAlignment(topPanel, HasHorizontalAlignment.ALIGN_CENTER);
+        lastModified = new Date(); //Initialize if-modified-since value with now.
+        resources.pithosCss().ensureInjected();
+        boolean bareContent = Window.Location.getParameter("noframe") != null;
+        String contentWidth = bareContent ? Const.PERCENT_100 : "75%";
+
+        VerticalPanel outer = new VerticalPanel();
+        outer.setWidth(Const.PERCENT_100);
+        if(!bareContent) {
+            outer.addStyleName("pithos-outer");
         }
-        
+
+        if(!bareContent) {
+            topPanel = new TopPanel(this, Pithos.images);
+            topPanel.setWidth(Const.PERCENT_100);
+            outer.add(topPanel);
+            outer.setCellHorizontalAlignment(topPanel, HasHorizontalAlignment.ALIGN_CENTER);
+        }
+
         messagePanel.setVisible(false);
         outer.add(messagePanel);
         outer.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
@@ -327,13 +373,15 @@ public class Pithos implements EntryPoint, ResizeHandler {
         HorizontalPanel header = new HorizontalPanel();
         header.addStyleName("pithos-header");
         header.setWidth(contentWidth);
-        if (bareContent)
-               header.addStyleName("pithos-header-noframe");
+        if(bareContent) {
+            header.addStyleName("pithos-header-noframe");
+        }
         upload = new Button("Upload", new ClickHandler() {
             @Override
             public void onClick(ClickEvent event) {
-               if (getSelection() != null)
-                       new UploadFileCommand(Pithos.this, null, getSelection()).execute();
+                if(getSelection() != null) {
+                    new UploadFileCommand(Pithos.this, null, getSelection()).execute();
+                }
             }
         });
         upload.addStyleName("pithos-uploadButton");
@@ -345,7 +393,7 @@ public class Pithos implements EntryPoint, ResizeHandler {
         header.add(toolbar);
         header.setCellHorizontalAlignment(toolbar, HasHorizontalAlignment.ALIGN_CENTER);
         header.setCellVerticalAlignment(toolbar, HasVerticalAlignment.ALIGN_MIDDLE);
-        
+
         HorizontalPanel folderStatistics = new HorizontalPanel();
         folderStatistics.addStyleName("pithos-folderStatistics");
         numOfFiles = new HTML();
@@ -362,31 +410,33 @@ public class Pithos implements EntryPoint, ResizeHandler {
         outer.setCellHorizontalAlignment(header, HasHorizontalAlignment.ALIGN_CENTER);
         // Inner contains the various lists
         inner.sinkEvents(Event.ONCONTEXTMENU);
-        inner.setWidth("100%");
+        inner.setWidth(Const.PERCENT_100);
 
         folderTreeSelectionModel = new SingleSelectionModel<Folder>();
         folderTreeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
             @Override
             public void onSelectionChange(SelectionChangeEvent event) {
-                if (folderTreeSelectionModel.getSelectedObject() != null) {
+                if(folderTreeSelectionModel.getSelectedObject() != null) {
                     deselectOthers(folderTreeView, folderTreeSelectionModel);
                     applyPermissions(folderTreeSelectionModel.getSelectedObject());
                     Folder f = folderTreeSelectionModel.getSelectedObject();
-                       updateFolder(f, true, new Command() {
-                               
-                               @Override
-                               public void execute() {
-                                       updateStatistics();
-                               }
-                       }, true);
-                       showRelevantToolbarButtons();
+                    updateFolder(f, true, new Command() {
+
+                        @Override
+                        public void execute() {
+                            updateStatistics();
+                        }
+                    }, true);
+                    showRelevantToolbarButtons();
+                }
+                else {
+                    if(getSelectedTree().equals(folderTreeView)) {
+                        setSelectedTree(null);
+                    }
+                    if(getSelectedTree() == null) {
+                        showRelevantToolbarButtons();
+                    }
                 }
-                               else {
-                                       if (getSelectedTree().equals(folderTreeView))
-                                               setSelectedTree(null);
-                                       if (getSelectedTree() == null)
-                                               showRelevantToolbarButtons();
-                               }
             }
         });
         selectionModels.add(folderTreeSelectionModel);
@@ -394,13 +444,13 @@ public class Pithos implements EntryPoint, ResizeHandler {
         folderTreeViewModel = new FolderTreeViewModel(this, folderTreeSelectionModel);
         folderTreeView = new FolderTreeView(folderTreeViewModel);
         treeViews.add(folderTreeView);
-        
+
         fileList = new FileList(this, images);
         inner.add(fileList);
 
         trees = new VerticalPanel();
-        trees.setWidth("100%");
-        
+        trees.setWidth(Const.PERCENT_100);
+
         // Add the left and right panels to the split panel.
         splitPanel.setLeftWidget(trees);
         FlowPanel right = new FlowPanel();
@@ -408,20 +458,21 @@ public class Pithos implements EntryPoint, ResizeHandler {
         right.add(inner);
         splitPanel.setRightWidget(right);
         splitPanel.setSplitPosition("219px");
-        splitPanel.setSize("100%", "100%");
+        splitPanel.setSize(Const.PERCENT_100, Const.PERCENT_100);
         splitPanel.addStyleName("pithos-splitPanel");
         splitPanel.setWidth(contentWidth);
         outer.add(splitPanel);
         outer.setCellHorizontalAlignment(splitPanel, HasHorizontalAlignment.ALIGN_CENTER);
 
-        if (!bareContent) {
-               statusPanel = new StatusPanel();
-               statusPanel.setWidth("100%");
-               outer.add(statusPanel);
-               outer.setCellHorizontalAlignment(statusPanel, HasHorizontalAlignment.ALIGN_CENTER);
+        if(!bareContent) {
+            statusPanel = new StatusPanel();
+            statusPanel.setWidth(Const.PERCENT_100);
+            outer.add(statusPanel);
+            outer.setCellHorizontalAlignment(statusPanel, HasHorizontalAlignment.ALIGN_CENTER);
+        }
+        else {
+            splitPanel.addStyleName("pithos-splitPanel-noframe");
         }
-        else
-               splitPanel.addStyleName("pithos-splitPanel-noframe");
 
         // Hook the window resize event, so that we can adjust the UI.
         Window.addResizeHandler(this);
@@ -435,158 +486,176 @@ public class Pithos implements EntryPoint, ResizeHandler {
         // this in a deferred command causes it to occur after all widgets'
         // sizes have been computed by the browser.
         Scheduler.get().scheduleIncremental(new RepeatingCommand() {
-                       
-                       @Override
-                       public boolean execute() {
-                               if (!isCloudbarReady())
-                                       return true;
+
+            @Override
+            public boolean execute() {
+                if(!isCloudbarReady()) {
+                    return true;
+                }
                 onWindowResized(Window.getClientHeight());
-                               return false;
-                       }
-               });
-        
+                return false;
+            }
+        });
+
         Scheduler.get().scheduleDeferred(new ScheduledCommand() {
             @Override
             public void execute() {
                 fetchAccount(new Command() {
-                                       
-                                       @Override
-                                       public void execute() {
-                               if (!account.hasHomeContainer())
-                                   createHomeContainer(account, this);
-                               else if (!account.hasTrashContainer())
-                                       createTrashContainer(this);
-                               else {
-                                       for (Folder f : account.getContainers())
-                                               if (f.getName().equals(Pithos.TRASH_CONTAINER)) {
-                                                       trash = f;
-                                                       break;
-                                               }
-                                   trees.add(folderTreeView);
-                                   folderTreeViewModel.initialize(account, new Command() {
-                                                               
-                                                               @Override
-                                                               public void execute() {
-                                                   createMySharedTree();
-                                                               }
-                                                       });
-
-                                   HorizontalPanel separator = new HorizontalPanel();
-                                   separator.addStyleName("pithos-statisticsSeparator");
-                                   separator.add(new HTML(""));
-                                   trees.add(separator);
-
-                                   groupTreeViewModel = new GroupTreeViewModel(Pithos.this);
-                                   groupTreeView = new GroupTreeView(groupTreeViewModel);
-                                   treeViews.add(groupTreeView);
-                                   trees.add(groupTreeView);
-                                   folderTreeView.showStatistics(account);
-                               }
-                                       }
-                               });
+
+                    @Override
+                    public void execute() {
+                        if(!account.hasHomeContainer()) {
+                            createHomeContainer(account, this);
+                        }
+                        else if(!account.hasTrashContainer()) {
+                            createTrashContainer(this);
+                        }
+                        else {
+                            for(Folder f : account.getContainers()) {
+                                if(f.getName().equals(Const.TRASH_CONTAINER)) {
+                                    trash = f;
+                                    break;
+                                }
+                            }
+                            trees.add(folderTreeView);
+                            folderTreeViewModel.initialize(account, new Command() {
+
+                                @Override
+                                public void execute() {
+                                    createMySharedTree();
+                                }
+                            });
+
+                            HorizontalPanel separator = new HorizontalPanel();
+                            separator.addStyleName("pithos-statisticsSeparator");
+                            separator.add(new HTML(""));
+                            trees.add(separator);
+
+                            groupTreeViewModel = new GroupTreeViewModel(Pithos.this);
+                            groupTreeView = new GroupTreeView(groupTreeViewModel);
+                            treeViews.add(groupTreeView);
+                            trees.add(groupTreeView);
+                            folderTreeView.showStatistics(account);
+                        }
+                    }
+                });
             }
         });
     }
-    
+
     public void scheduleResfresh() {
-               Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
-                       
-                       @Override
-                       public boolean execute() {
-                               final Folder f = getSelection();
-                               if (f == null)
-                                       return true;
-                               
-                       HeadRequest<Folder> head = new HeadRequest<Folder>(Folder.class, getApiPath(), getUsername(), "/" + f.getContainer()) {
-
-                                       @Override
-                                       public void onSuccess(Folder _result) {
-                                               lastModified = new Date();
-                                               if (getSelectedTree().equals(folderTreeView))
-                                                       updateFolder(f, true, new Command() {
-       
-                                                               @Override
-                                                               public void execute() {
-                                                                       scheduleResfresh();
-                                                               }
-                                                               
-                                                       }, false);
-                                               else if (getSelectedTree().equals(mysharedTreeView))
-                                                       updateSharedFolder(f, true, new Command() {
-       
-                                                               @Override
-                                                               public void execute() {
-                                                                       scheduleResfresh();
-                                                               }
-                                                       });
-                                       }
-
-                                       @Override
-                                       public void onError(Throwable t) {
-                                               if (t instanceof RestException && ((RestException) t).getHttpStatusCode() == HttpStatus.SC_NOT_MODIFIED)
-                                                       scheduleResfresh();
-                                               else if (retries >= MAX_RETRIES) {
-                                       GWT.log("Error heading folder", t);
-                                                       setError(t);
-                                       if (t instanceof RestException)
-                                           displayError("Error heading folder: " + ((RestException) t).getHttpStatusText());
-                                       else
-                                           displayError("System error heading folder: " + t.getMessage());
-                               }
-                               else {//retry
-                                       GWT.log("Retry " + retries);
-                                       Scheduler.get().scheduleDeferred(this);
-                               }
-                                       }
-
-                                       @Override
-                                       protected void onUnauthorized(Response response) {
-                                               if (retries >= MAX_RETRIES)
-                                                       sessionExpired();
-                               else //retry
-                                       Scheduler.get().scheduleDeferred(this);
-                                       }
-                               };
-                               head.setHeader("X-Auth-Token", getToken());
-                               head.setHeader("If-Modified-Since", DateTimeFormat.getFormat("EEE, dd MMM yyyy HH:mm:ss").format(lastModified, TimeZone.createTimeZone(0)) + " GMT");
-                               Scheduler.get().scheduleDeferred(head);
-                               
-                               return false;
-                       }
-               }, 3000);
+        Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
+
+            @Override
+            public boolean execute() {
+                final Folder f = getSelection();
+                if(f == null) {
+                    return true;
+                }
+
+                HeadRequest<Folder> head = new HeadRequest<Folder>(Pithos.this, Folder.class, getApiPath(), f.getOwnerID(), "/" + f.getContainer()) {
+
+                    @Override
+                    public void onSuccess(Folder _result) {
+                        lastModified = new Date();
+                        if(getSelectedTree().equals(folderTreeView)) {
+                            updateFolder(f, true, new Command() {
+
+                                @Override
+                                public void execute() {
+                                    scheduleResfresh();
+                                }
+
+                            }, false);
+                        }
+                        else if(getSelectedTree().equals(mysharedTreeView)) {
+                            updateSharedFolder(f, true, new Command() {
+
+                                @Override
+                                public void execute() {
+                                    scheduleResfresh();
+                                }
+                            });
+                        }
+                        else {
+                            scheduleResfresh();
+                        }
+                    }
+
+                    @Override
+                    public void onError(Throwable t) {
+                        if(t instanceof RestException && ((RestException) t).getHttpStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+                            scheduleResfresh();
+                        }
+                        else if(retries >= MAX_RETRIES) {
+                            GWT.log("Error heading folder", t);
+                            setError(t);
+                            if(t instanceof RestException) {
+                                displayError("Error heading folder: " + ((RestException) t).getHttpStatusText());
+                            }
+                            else {
+                                displayError("System error heading folder: " + t.getMessage());
+                            }
+                        }
+                        else {//retry
+                            GWT.log("Retry " + retries);
+                            Scheduler.get().scheduleDeferred(this);
+                        }
+                    }
+
+                    @Override
+                    protected void onUnauthorized(Response response) {
+                        if(retries >= MAX_RETRIES) {
+                            sessionExpired();
+                        }
+                        else //retry
+                        {
+                            Scheduler.get().scheduleDeferred(this);
+                        }
+                    }
+                };
+                head.setHeader(Const.X_AUTH_TOKEN, getUserToken());
+                head.setHeader(Const.IF_MODIFIED_SINCE, DateTimeFormat.getFormat(Const.DATE_FORMAT_1).format(lastModified, TimeZone.createTimeZone(0)) + " GMT");
+                Scheduler.get().scheduleDeferred(head);
+
+                return false;
+            }
+        }, 3000);
     }
 
     public void applyPermissions(Folder f) {
-       if (f != null) {
-               if (f.isInTrash()) {
-                       upload.setEnabled(false);
-                       disableUploadArea();
-               }
-               else {
-                       Boolean[] perms = f.getPermissions().get(username);
-                       if (f.getOwner().equals(username) || (perms != null && perms[1] != null && perms[1])) {
-                               upload.setEnabled(true);
-                               enableUploadArea();
-                       }
-                       else {
-                               upload.setEnabled(false);
-                               disableUploadArea();
-                       }
-               }
-       }
-       else {
-               upload.setEnabled(false);
-               disableUploadArea();
-       }
-       }
-
-       @SuppressWarnings({ "rawtypes", "unchecked" })
-       public void deselectOthers(TreeView _selectedTree, SingleSelectionModel model) {
-       selectedTree = _selectedTree;
-       
-        for (SingleSelectionModel s : selectionModels)
-            if (!s.equals(model) && s.getSelectedObject() != null)
+        if(f != null) {
+            if(f.isInTrash()) {
+                upload.setEnabled(false);
+                disableUploadArea();
+            }
+            else {
+                Boolean[] perms = f.getPermissions().get(userID);
+                if(f.getOwnerID().equals(userID) || (perms != null && perms[1] != null && perms[1])) {
+                    upload.setEnabled(true);
+                    enableUploadArea();
+                }
+                else {
+                    upload.setEnabled(false);
+                    disableUploadArea();
+                }
+            }
+        }
+        else {
+            upload.setEnabled(false);
+            disableUploadArea();
+        }
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void deselectOthers(TreeView _selectedTree, SingleSelectionModel model) {
+        selectedTree = _selectedTree;
+
+        for(SingleSelectionModel s : selectionModels) {
+            if(!s.equals(model) && s.getSelectedObject() != null) {
                 s.setSelected(s.getSelectedObject(), false);
+            }
+        }
     }
 
     public void showFiles(final Folder f) {
@@ -599,338 +668,359 @@ public class Pithos implements EntryPoint, ResizeHandler {
     }
 
     /**
-        * Parse and store the user credentials to the appropriate fields.
-        */
-       private boolean parseUserCredentials() {
+     * Parse and store the user credentials to the appropriate fields.
+     */
+    private boolean parseUserCredentials() {
         Configuration conf = (Configuration) GWT.create(Configuration.class);
-               Dictionary otherProperties = Dictionary.getDictionary("otherProperties");
-        String cookie = otherProperties.get("authCookie");
+        Dictionary otherProperties = Dictionary.getDictionary(Const.OTHER_PROPERTIES);
+        String cookie = otherProperties.get(Const.AUTH_COOKIE);
         String auth = Cookies.getCookie(cookie);
-        if (auth == null) {
+        if(auth == null) {
             authenticateUser();
             return false;
         }
-        if (auth.startsWith("\""))
-               auth = auth.substring(1);
-        if (auth.endsWith("\""))
-               auth = auth.substring(0, auth.length() - 1);
-               String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
-               if (authSplit.length != 2) {
-                   authenticateUser();
-                   return false;
-               }
-               username = authSplit[0];
-               token = authSplit[1];
+        if(auth.startsWith("\"")) {
+            auth = auth.substring(1);
+        }
+        if(auth.endsWith("\"")) {
+            auth = auth.substring(0, auth.length() - 1);
+        }
+        String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
+        if(authSplit.length != 2) {
+            authenticateUser();
+            return false;
+        }
+        userID = authSplit[0];
+        userToken = authSplit[1];
 
         String gotoUrl = Window.Location.getParameter("goto");
-               if (gotoUrl != null && gotoUrl.length() > 0) {
-                       Window.Location.assign(gotoUrl);
-                       return false;
-               }
-               return true;
+        if(gotoUrl != null && gotoUrl.length() > 0) {
+            Window.Location.assign(gotoUrl);
+            return false;
+        }
+        return true;
     }
 
     /**
-        * Redirect the user to the login page for authentication.
-        */
-       protected void authenticateUser() {
-               Dictionary otherProperties = Dictionary.getDictionary("otherProperties");
-        Window.Location.assign(otherProperties.get("loginUrl") + Window.Location.getHref());
-       }
-
-       public void fetchAccount(final Command callback) {
+     * Redirect the user to the login page for authentication.
+     */
+    protected void authenticateUser() {
+        Dictionary otherProperties = Dictionary.getDictionary(Const.OTHER_PROPERTIES);
+        Window.Location.assign(otherProperties.get(Const.LOGIN_URL) + Window.Location.getHref());
+    }
+
+    public void fetchAccount(final Command callback) {
+        LOG("Pithos::fetchAccount(), callback = ", callback);
         String path = "?format=json";
 
-        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, getApiPath(), username, path) {
+        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(this, AccountResource.class, getApiPath(), userID, path) {
             @Override
             public void onSuccess(AccountResource _result) {
                 account = _result;
-                if (callback != null)
-                       callback.execute();
+                if(callback != null) {
+                    callback.execute();
+                }
+                // Initialize the user catalog
+                new UpdateUserCatalogs(Pithos.this, Pithos.this.getUserID()).scheduleDeferred();
             }
 
             @Override
             public void onError(Throwable t) {
                 GWT.log("Error getting account", t);
-                               setError(t);
-                if (t instanceof RestException)
+                setError(t);
+                if(t instanceof RestException) {
                     displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
-                else
+                }
+                else {
                     displayError("System error fetching user data: " + t.getMessage());
+                }
             }
 
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               sessionExpired();
-                       }
+            @Override
+            protected void onUnauthorized(Response response) {
+                sessionExpired();
+            }
         };
-        getAccount.setHeader("X-Auth-Token", token);
+        getAccount.setHeader(Const.X_AUTH_TOKEN, userToken);
         Scheduler.get().scheduleDeferred(getAccount);
     }
 
     public void updateStatistics() {
-       HeadRequest<AccountResource> headAccount = new HeadRequest<AccountResource>(AccountResource.class, getApiPath(), username, "", account) {
+        HeadRequest<AccountResource> headAccount = new HeadRequest<AccountResource>(this, AccountResource.class, getApiPath(), userID, "", account) {
 
-                       @Override
-                       public void onSuccess(AccountResource _result) {
-                               folderTreeView.showStatistics(account);
-                       }
+            @Override
+            public void onSuccess(AccountResource _result) {
+                folderTreeView.showStatistics(account);
+            }
 
-                       @Override
-                       public void onError(Throwable t) {
+            @Override
+            public void onError(Throwable t) {
                 GWT.log("Error getting account", t);
-                               setError(t);
-                if (t instanceof RestException)
+                setError(t);
+                if(t instanceof RestException) {
                     displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
-                else
+                }
+                else {
                     displayError("System error fetching user data: " + t.getMessage());
-                       }
-
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               sessionExpired();
-                       }
-               };
-               headAccount.setHeader("X-Auth-Token", token);
-               Scheduler.get().scheduleDeferred(headAccount);
-       }
-
-       protected void createHomeContainer(final AccountResource _account, final Command callback) {
-        String path = "/" + Pithos.HOME_CONTAINER;
-        PutRequest createPithos = new PutRequest(getApiPath(), getUsername(), path) {
+                }
+            }
+
+            @Override
+            protected void onUnauthorized(Response response) {
+                sessionExpired();
+            }
+        };
+        headAccount.setHeader(Const.X_AUTH_TOKEN, userToken);
+        Scheduler.get().scheduleDeferred(headAccount);
+    }
+
+    protected void createHomeContainer(final AccountResource _account, final Command callback) {
+        String path = "/" + Const.HOME_CONTAINER;
+        PutRequest createPithos = new PutRequest(this, getApiPath(), getUserID(), path) {
             @Override
             public void onSuccess(Resource result) {
-               if (!_account.hasTrashContainer())
-                       createTrashContainer(callback);
-               else
-                       fetchAccount(callback);
+                if(!_account.hasTrashContainer()) {
+                    createTrashContainer(callback);
+                }
+                else {
+                    fetchAccount(callback);
+                }
             }
 
             @Override
             public void onError(Throwable t) {
                 GWT.log("Error creating pithos", t);
-                               setError(t);
-                if (t instanceof RestException)
+                setError(t);
+                if(t instanceof RestException) {
                     displayError("Error creating pithos: " + ((RestException) t).getHttpStatusText());
-                else
+                }
+                else {
                     displayError("System error Error creating pithos: " + t.getMessage());
+                }
             }
 
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               sessionExpired();
-                       }
+            @Override
+            protected void onUnauthorized(Response response) {
+                sessionExpired();
+            }
         };
-        createPithos.setHeader("X-Auth-Token", getToken());
+        createPithos.setHeader(Const.X_AUTH_TOKEN, getUserToken());
         Scheduler.get().scheduleDeferred(createPithos);
     }
 
     protected void createTrashContainer(final Command callback) {
-        String path = "/" + Pithos.TRASH_CONTAINER;
-        PutRequest createPithos = new PutRequest(getApiPath(), getUsername(), path) {
+        String path = "/" + Const.TRASH_CONTAINER;
+        PutRequest createPithos = new PutRequest(this, getApiPath(), getUserID(), path) {
             @Override
             public void onSuccess(Resource result) {
-                       fetchAccount(callback);
+                fetchAccount(callback);
             }
 
             @Override
             public void onError(Throwable t) {
                 GWT.log("Error creating pithos", t);
-                               setError(t);
-                if (t instanceof RestException)
+                setError(t);
+                if(t instanceof RestException) {
                     displayError("Error creating pithos: " + ((RestException) t).getHttpStatusText());
-                else
+                }
+                else {
                     displayError("System error Error creating pithos: " + t.getMessage());
+                }
             }
 
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               sessionExpired();
-                       }
+            @Override
+            protected void onUnauthorized(Response response) {
+                sessionExpired();
+            }
         };
-        createPithos.setHeader("X-Auth-Token", getToken());
+        createPithos.setHeader(Const.X_AUTH_TOKEN, getUserToken());
         Scheduler.get().scheduleDeferred(createPithos);
     }
 
     /**
-        * Creates an HTML fragment that places an image & caption together, for use
-        * in a group header.
-        *
-        * @param imageProto an image prototype for an image
-        * @param caption the group caption
-        * @return the header HTML fragment
-        */
-       private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
-               String captionHTML = "<table class='caption' cellpadding='0' " 
-               + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML() 
-               + "</td><td id =" + caption +" class='rcaption'><b style='white-space:nowrap'>&nbsp;" 
-               + caption + "</b></td></tr></table>";
-               return captionHTML;
-       }
-
-       protected void onWindowResized(int height) {
-               // Adjust the split panel to take up the available room in the window.
-               int newHeight = height - splitPanel.getAbsoluteTop() - 153;
-               if (newHeight < 1)
-                       newHeight = 1;
-               splitPanel.setHeight("" + newHeight);
-               inner.setHeight("" + newHeight);
-       }
-       
-       native boolean isCloudbarReady()/*-{
-               if ($wnd.$("div.cloudbar") && $wnd.$("div.cloudbar").height() > 0)
-                       return true;
-               return false;
-       }-*/;
-       
-       @Override
-       public void onResize(ResizeEvent event) {
-               int height = event.getHeight();
-               onWindowResized(height);
-       }
-
-       /**
-        * Display an error message.
-        *
-        * @param msg the message to display
-        */
-       public void displayError(String msg) {
-               messagePanel.displayError(msg);
-               onWindowResized(Window.getClientHeight());
-       }
-
-       /**
-        * Display a warning message.
-        *
-        * @param msg the message to display
-        */
-       public void displayWarning(String msg) {
-               messagePanel.displayWarning(msg);
-               onWindowResized(Window.getClientHeight());
-       }
-
-       /**
-        * Display an informational message.
-        *
-        * @param msg the message to display
-        */
-       public void displayInformation(String msg) {
-               messagePanel.displayInformation(msg);
-               onWindowResized(Window.getClientHeight());
-       }
-
-       /**
-        * Retrieve the fileList.
-        *
-        * @return the fileList
-        */
-       public FileList getFileList() {
-               return fileList;
-       }
-
-       /**
-        * Retrieve the topPanel.
-        *
-        * @return the topPanel
-        */
-       TopPanel getTopPanel() {
-               return topPanel;
-       }
-
-       /**
-        * Retrieve the clipboard.
-        *
-        * @return the clipboard
-        */
-       public Clipboard getClipboard() {
-               return clipboard;
-       }
-
-       public StatusPanel getStatusPanel() {
-               return statusPanel;
-       }
-
-       public String getToken() {
-               return token;
-       }
-
-       public static native void preventIESelection() /*-{
-               $doc.body.onselectstart = function() {
-                       return false;
-               };
-       }-*/;
-
-       public static native void enableIESelection() /*-{
-               if ($doc.body.onselectstart != null)
-                       $doc.body.onselectstart = null;
-       }-*/;
-
-       /**
-        * @return the absolute path of the API root URL
-        */
-       public String getApiPath() {
-               Configuration conf = (Configuration) GWT.create(Configuration.class);
-               return conf.apiPath();
-       }
-
-       /**
-        * History support for folder navigation
-        * adds a new browser history entry
-        *
-        * @param key
-        */
-       public void updateHistory(String key){
+     * Creates an HTML fragment that places an image & caption together, for use
+     * in a group header.
+     *
+     * @param imageProto an image prototype for an image
+     * @param caption    the group caption
+     * @return the header HTML fragment
+     */
+    private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
+        String captionHTML = "<table class='caption' cellpadding='0' "
+            + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML()
+            + "</td><td id =" + caption + " class='rcaption'><b style='white-space:nowrap'>&nbsp;"
+            + caption + "</b></td></tr></table>";
+        return captionHTML;
+    }
+
+    protected void onWindowResized(int height) {
+        // Adjust the split panel to take up the available room in the window.
+        int newHeight = height - splitPanel.getAbsoluteTop() - 153;
+        if(newHeight < 1) {
+            newHeight = 1;
+        }
+        splitPanel.setHeight("" + newHeight);
+        inner.setHeight("" + newHeight);
+    }
+
+    native boolean isCloudbarReady()/*-{
+      if ($wnd.$("div.cloudbar") && $wnd.$("div.cloudbar").height() > 0)
+        return true;
+      return false;
+    }-*/;
+
+    @Override
+    public void onResize(ResizeEvent event) {
+        int height = event.getHeight();
+        onWindowResized(height);
+    }
+
+    /**
+     * Display an error message.
+     *
+     * @param msg the message to display
+     */
+    public void displayError(String msg) {
+        messagePanel.displayError(msg);
+        onWindowResized(Window.getClientHeight());
+    }
+
+    /**
+     * Display a warning message.
+     *
+     * @param msg the message to display
+     */
+    public void displayWarning(String msg) {
+        messagePanel.displayWarning(msg);
+        onWindowResized(Window.getClientHeight());
+    }
+
+    /**
+     * Display an informational message.
+     *
+     * @param msg the message to display
+     */
+    public void displayInformation(String msg) {
+        messagePanel.displayInformation(msg);
+        onWindowResized(Window.getClientHeight());
+    }
+
+    /**
+     * Retrieve the fileList.
+     *
+     * @return the fileList
+     */
+    public FileList getFileList() {
+        return fileList;
+    }
+
+    /**
+     * Retrieve the topPanel.
+     *
+     * @return the topPanel
+     */
+    TopPanel getTopPanel() {
+        return topPanel;
+    }
+
+    /**
+     * Retrieve the clipboard.
+     *
+     * @return the clipboard
+     */
+    public Clipboard getClipboard() {
+        return clipboard;
+    }
+
+    public StatusPanel getStatusPanel() {
+        return statusPanel;
+    }
+
+    public String getUserToken() {
+        return userToken;
+    }
+
+    public static native void preventIESelection() /*-{
+      $doc.body.onselectstart = function () {
+        return false;
+      };
+    }-*/;
+
+    public static native void enableIESelection() /*-{
+      if ($doc.body.onselectstart != null)
+        $doc.body.onselectstart = null;
+    }-*/;
+
+    /**
+     * @return the absolute path of the API root URL
+     */
+    public String getApiPath() {
+        Configuration conf = (Configuration) GWT.create(Configuration.class);
+        return conf.apiPath();
+    }
+
+    /**
+     * History support for folder navigation
+     * adds a new browser history entry
+     *
+     * @param key
+     */
+    public void updateHistory(String key) {
 //             Replace any whitespace of the initial string to "+"
 //             String result = key.replaceAll("\\s","+");
 //             Add a new browser history entry.
 //             History.newItem(result);
-               History.newItem(key);
-       }
+        History.newItem(key);
+    }
 
     public void deleteFolder(final Folder folder, final Command callback) {
-       final PleaseWaitPopup pwp = new PleaseWaitPopup();
-       pwp.center();
+        final PleaseWaitPopup pwp = new PleaseWaitPopup();
+        pwp.center();
         String path = "/" + folder.getContainer() + "/" + folder.getPrefix() + "?delimiter=/" + "&t=" + System.currentTimeMillis();
-        DeleteRequest deleteFolder = new DeleteRequest(getApiPath(), folder.getOwner(), path) {
-                       
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               pwp.hide();
-                               sessionExpired();
-                       }
-                       
-                       @Override
-                       public void onSuccess(Resource result) {
+        DeleteRequest deleteFolder = new DeleteRequest(this, getApiPath(), folder.getOwnerID(), path) {
+
+            @Override
+            protected void onUnauthorized(Response response) {
+                pwp.hide();
+                sessionExpired();
+            }
+
+            @Override
+            public void onSuccess(Resource result) {
                 updateFolder(folder.getParent(), true, new Command() {
-                                       
-                                       @Override
-                                       public void execute() {
-                                               folderTreeSelectionModel.setSelected(folder.getParent(), true);
-                                               updateStatistics();
-                                               if (callback != null)
-                                                       callback.execute();
-                                               pwp.hide();
-                                       }
-                               }, true);
-                       }
-                       
-                       @Override
-                       public void onError(Throwable t) {
+
+                    @Override
+                    public void execute() {
+                        folderTreeSelectionModel.setSelected(folder.getParent(), true);
+                        updateStatistics();
+                        if(callback != null) {
+                            callback.execute();
+                        }
+                        pwp.hide();
+                    }
+                }, true);
+            }
+
+            @Override
+            public void onError(Throwable t) {
                 GWT.log("", t);
-                               setError(t);
-                if (t instanceof RestException) {
-                       if (((RestException) t).getHttpStatusCode() != Response.SC_NOT_FOUND)
-                               displayError("Unable to delete folder: "+((RestException) t).getHttpStatusText());
-                       else
-                               onSuccess(null);
+                setError(t);
+                if(t instanceof RestException) {
+                    if(((RestException) t).getHttpStatusCode() != Response.SC_NOT_FOUND) {
+                        displayError("Unable to delete folder: " + ((RestException) t).getHttpStatusText());
+                    }
+                    else {
+                        onSuccess(null);
+                    }
                 }
-                else
+                else {
                     displayError("System error unable to delete folder: " + t.getMessage());
-                               pwp.hide();
-                       }
-               };
-               deleteFolder.setHeader("X-Auth-Token", getToken());
-               Scheduler.get().scheduleDeferred(deleteFolder);
+                }
+                pwp.hide();
+            }
+        };
+        deleteFolder.setHeader(Const.X_AUTH_TOKEN, getUserToken());
+        Scheduler.get().scheduleDeferred(deleteFolder);
     }
 
     public FolderTreeView getFolderTreeView() {
@@ -938,10 +1028,10 @@ public class Pithos implements EntryPoint, ResizeHandler {
     }
 
     public void copyFiles(final Iterator<File> iter, final String targetUsername, final String targetUri, final Command callback) {
-        if (iter.hasNext()) {
+        if(iter.hasNext()) {
             File file = iter.next();
             String path = targetUri + "/" + file.getName();
-            PutRequest copyFile = new PutRequest(getApiPath(), targetUsername, path) {
+            PutRequest copyFile = new PutRequest(this, getApiPath(), targetUsername, path) {
                 @Override
                 public void onSuccess(Resource result) {
                     copyFiles(iter, targetUsername, targetUri, callback);
@@ -950,423 +1040,457 @@ public class Pithos implements EntryPoint, ResizeHandler {
                 @Override
                 public void onError(Throwable t) {
                     GWT.log("", t);
-                                       setError(t);
-                    if (t instanceof RestException) {
+                    setError(t);
+                    if(t instanceof RestException) {
                         displayError("Unable to copy file: " + ((RestException) t).getHttpStatusText());
                     }
-                    else
-                        displayError("System error unable to copy file: "+t.getMessage());
+                    else {
+                        displayError("System error unable to copy file: " + t.getMessage());
+                    }
                 }
 
-                               @Override
-                               protected void onUnauthorized(Response response) {
-                                       sessionExpired();
-                               }
+                @Override
+                protected void onUnauthorized(Response response) {
+                    sessionExpired();
+                }
             };
-            copyFile.setHeader("X-Auth-Token", getToken());
-            copyFile.setHeader("X-Copy-From", URL.encodePathSegment(file.getUri()));
-            if (!file.getOwner().equals(targetUsername))
-               copyFile.setHeader("X-Source-Account", URL.encodePathSegment(file.getOwner()));
-            copyFile.setHeader("Content-Type", file.getContentType());
+            copyFile.setHeader(Const.X_AUTH_TOKEN, getUserToken());
+            copyFile.setHeader(Const.X_COPY_FROM, URL.encodePathSegment(file.getUri()));
+            if(!file.getOwnerID().equals(targetUsername)) {
+                copyFile.setHeader(Const.X_SOURCE_ACCOUNT, URL.encodePathSegment(file.getOwnerID()));
+            }
+            copyFile.setHeader(Const.CONTENT_TYPE, file.getContentType());
             Scheduler.get().scheduleDeferred(copyFile);
         }
-        else  if (callback != null) {
+        else if(callback != null) {
             callback.execute();
         }
     }
 
     public void copyFolder(final Folder f, final String targetUsername, final String targetUri, boolean move, final Command callback) {
         String path = targetUri + "?delimiter=/";
-        PutRequest copyFolder = new PutRequest(getApiPath(), targetUsername, path) {
+        PutRequest copyFolder = new PutRequest(this, getApiPath(), targetUsername, path) {
             @Override
             public void onSuccess(Resource result) {
-               if (callback != null)
-                       callback.execute();
+                if(callback != null) {
+                    callback.execute();
+                }
             }
 
             @Override
             public void onError(Throwable t) {
                 GWT.log("", t);
-                               setError(t);
-               if (t instanceof RestException) {
+                setError(t);
+                if(t instanceof RestException) {
                     displayError("Unable to copy folder: " + ((RestException) t).getHttpStatusText());
                 }
-                else
+                else {
                     displayError("System error copying folder: " + t.getMessage());
+                }
             }
 
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               sessionExpired();
-                       }
+            @Override
+            protected void onUnauthorized(Response response) {
+                sessionExpired();
+            }
         };
-        copyFolder.setHeader("X-Auth-Token", getToken());
-        copyFolder.setHeader("Accept", "*/*");
-        copyFolder.setHeader("Content-Length", "0");
-        copyFolder.setHeader("Content-Type", "application/directory");
-        if (!f.getOwner().equals(targetUsername))
-               copyFolder.setHeader("X-Source-Account", f.getOwner());
-        if (move)
-            copyFolder.setHeader("X-Move-From", URL.encodePathSegment(f.getUri()));
-        else
-               copyFolder.setHeader("X-Copy-From", URL.encodePathSegment(f.getUri()));
+        copyFolder.setHeader(Const.X_AUTH_TOKEN, getUserToken());
+        copyFolder.setHeader(Const.ACCEPT, "*/*");
+        copyFolder.setHeader(Const.CONTENT_LENGTH, "0");
+        copyFolder.setHeader(Const.CONTENT_TYPE, "application/directory");
+        if(!f.getOwnerID().equals(targetUsername)) {
+            copyFolder.setHeader(Const.X_SOURCE_ACCOUNT, f.getOwnerID());
+        }
+        if(move) {
+            copyFolder.setHeader(Const.X_MOVE_FROM, URL.encodePathSegment(f.getUri()));
+        }
+        else {
+            copyFolder.setHeader(Const.X_COPY_FROM, URL.encodePathSegment(f.getUri()));
+        }
         Scheduler.get().scheduleDeferred(copyFolder);
     }
-    
+
     public void addSelectionModel(@SuppressWarnings("rawtypes") SingleSelectionModel model) {
-       selectionModels.add(model);
-    }
-
-       public OtherSharedTreeView getOtherSharedTreeView() {
-               return otherSharedTreeView;
-       }
-
-       public void updateTrash(boolean showFiles, Command callback) {
-               updateFolder(trash, showFiles, callback, true);
-       }
-
-       public void updateGroupsNode() {
-               groupTreeView.updateGroupNode(null);
-       }
-
-       public Group addGroup(String groupname) {
-               Group newGroup = new Group(groupname);
-               account.addGroup(newGroup);
-               groupTreeView.updateGroupNode(null);
-               return newGroup;
-       }
-
-       public void removeGroup(Group group) {
-               account.removeGroup(group);
-               updateGroupsNode();
-       }
-
-       public TreeView getSelectedTree() {
-               return selectedTree;
-       }
-       
-       public void setSelectedTree(TreeView selected) {
-               selectedTree = selected;
-       }
-
-       public Folder getSelection() {
-               if (selectedTree != null)
-                       return selectedTree.getSelection();
-               return null;
-       }
-
-       public void showFolderStatistics(int folderFileCount) {
-               numOfFiles.setHTML(String.valueOf(folderFileCount));
-       }
-
-       public GroupTreeView getGroupTreeView() {
-               return groupTreeView;
-       }
-
-       public void sessionExpired() {
-               new SessionExpiredDialog(this).center();
-       }
-
-       public void updateRootFolder(Command callback) {
-               updateFolder(account.getPithos(), false, callback, true);
-       }
-
-       void createMySharedTree() {
-               mysharedTreeSelectionModel = new SingleSelectionModel<Folder>();
-               mysharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
-                   @Override
-                   public void onSelectionChange(SelectionChangeEvent event) {
-                       if (mysharedTreeSelectionModel.getSelectedObject() != null) {
-                           deselectOthers(mysharedTreeView, mysharedTreeSelectionModel);
-                           upload.setEnabled(false);
-                           disableUploadArea();
-                           updateSharedFolder(mysharedTreeSelectionModel.getSelectedObject(), true);
-                                       showRelevantToolbarButtons();
-                       }
-                               else {
-                                       if (getSelectedTree().equals(mysharedTreeView))
-                                               setSelectedTree(null);
-                                       if (getSelectedTree() == null)
-                                               showRelevantToolbarButtons();
-                               }
-                   }
-               });
-               selectionModels.add(mysharedTreeSelectionModel);
-               mysharedTreeViewModel = new MysharedTreeViewModel(Pithos.this, mysharedTreeSelectionModel);
-               mysharedTreeViewModel.initialize(new Command() {
-                       
-                       @Override
-                       public void execute() {
-                           mysharedTreeView = new MysharedTreeView(mysharedTreeViewModel);
-                               trees.insert(mysharedTreeView, 2);
-                               treeViews.add(mysharedTreeView);
-                               createOtherSharedTree();
-                       }
-               });
-       }
-
-       void createOtherSharedTree() {
-               otherSharedTreeSelectionModel = new SingleSelectionModel<Folder>();
-               otherSharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
-                   @Override
-                   public void onSelectionChange(SelectionChangeEvent event) {
-                       if (otherSharedTreeSelectionModel.getSelectedObject() != null) {
-                           deselectOthers(otherSharedTreeView, otherSharedTreeSelectionModel);
-                           applyPermissions(otherSharedTreeSelectionModel.getSelectedObject());
-                           updateOtherSharedFolder(otherSharedTreeSelectionModel.getSelectedObject(), true, null);
-                                       showRelevantToolbarButtons();
-                       }
-                               else {
-                                       if (getSelectedTree().equals(otherSharedTreeView))
-                                               setSelectedTree(null);
-                                       if (getSelectedTree() == null)
-                                               showRelevantToolbarButtons();
-                               }
-                   }
-               });
-               selectionModels.add(otherSharedTreeSelectionModel);
-               otherSharedTreeViewModel = new OtherSharedTreeViewModel(Pithos.this, otherSharedTreeSelectionModel);
-               otherSharedTreeViewModel.initialize(new Command() {
-                       
-                       @Override
-                       public void execute() {
-                           otherSharedTreeView = new OtherSharedTreeView(otherSharedTreeViewModel);
-                               trees.insert(otherSharedTreeView, 1);
-                               treeViews.add(otherSharedTreeView);
-                               scheduleResfresh();
-                       }
-               });
-       }
-
-       public native void log1(String message)/*-{
-               $wnd.console.log(message);
-       }-*/;
-
-       public String getErrorData() {
-               if (error != null)
-                       return error.toString();
-               return "";
-       }
-       
-       public void setError(Throwable t) {
-               error = t;
-       }
-       
-       public void showRelevantToolbarButtons() {
-               toolbar.showRelevantButtons();
-       }
-
-       public FileUploadDialog getFileUploadDialog() {
-               if (fileUploadDialog == null)
-                       fileUploadDialog = new FileUploadDialog(this);
-               return fileUploadDialog;
-       }
-
-       public void hideUploadIndicator() {
-               upload.removeStyleName("pithos-uploadButton-loading");
-               upload.setTitle("");
-       }
-       
-       public void showUploadIndicator() {
-               upload.addStyleName("pithos-uploadButton-loading");
-               upload.setTitle("Upload in progress. Click for details.");
-       }
-
-       public void scheduleFolderHeadCommand(final Folder folder, final Command callback) {
-               if (folder == null) {
-                       if (callback != null)
-                               callback.execute();
-               }
-               else {
-                       HeadRequest<Folder> headFolder = new HeadRequest<Folder>(Folder.class, getApiPath(), folder.getOwner(), folder.getUri(), folder) {
-       
-                               @Override
-                               public void onSuccess(Folder _result) {
-                                       if (callback != null)
-                                               callback.execute();
-                               }
-       
-                               @Override
-                               public void onError(Throwable t) {
-                               if (t instanceof RestException) {
-                                       if (((RestException) t).getHttpStatusCode() == Response.SC_NOT_FOUND) {
-                               final String path = folder.getUri();
-                               PutRequest newFolder = new PutRequest(getApiPath(), folder.getOwner(), path) {
-                                   @Override
-                                   public void onSuccess(Resource _result) {
-                                       scheduleFolderHeadCommand(folder, callback);
-                                   }
-       
-                                   @Override
-                                   public void onError(Throwable _t) {
-                                       GWT.log("", _t);
-                                                               setError(_t);
-                                       if(_t instanceof RestException){
-                                           displayError("Unable to create folder: " + ((RestException) _t).getHttpStatusText());
-                                       }
-                                       else
-                                           displayError("System error creating folder: " + _t.getMessage());
-                                   }
-       
-                                               @Override
-                                               protected void onUnauthorized(Response response) {
-                                                       sessionExpired();
-                                               }
-                               };
-                               newFolder.setHeader("X-Auth-Token", getToken());
-                               newFolder.setHeader("Content-Type", "application/folder");
-                               newFolder.setHeader("Accept", "*/*");
-                               newFolder.setHeader("Content-Length", "0");
-                               Scheduler.get().scheduleDeferred(newFolder);
-                                       }
-                                       else
-                                               displayError("Error heading folder: " + ((RestException) t).getHttpStatusText());
-                               }
-                               else
-                                   displayError("System error heading folder: " + t.getMessage());
-       
-                               GWT.log("Error heading folder", t);
-                                       setError(t);
-                               }
-       
-                               @Override
-                               protected void onUnauthorized(Response response) {
-                                       sessionExpired();
-                               }
-                       };
-                       headFolder.setHeader("X-Auth-Token", getToken());
-                       Scheduler.get().scheduleDeferred(headFolder);
-               }
-       }
-
-       public void scheduleFileHeadCommand(File f, final Command callback) {
-               HeadRequest<File> headFile = new HeadRequest<File>(File.class, getApiPath(), f.getOwner(), f.getUri(), f) {
-
-                       @Override
-                       public void onSuccess(File _result) {
-                               if (callback != null)
-                                       callback.execute();
-                       }
-
-                       @Override
-                       public void onError(Throwable t) {
-                       GWT.log("Error heading file", t);
-                               setError(t);
-                       if (t instanceof RestException)
-                           displayError("Error heading file: " + ((RestException) t).getHttpStatusText());
-                       else
-                           displayError("System error heading file: " + t.getMessage());
-                       }
-
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               sessionExpired();
-                       }
-               };
-               headFile.setHeader("X-Auth-Token", getToken());
-               Scheduler.get().scheduleDeferred(headFile);
-       }
-
-       public boolean isMySharedSelected() {
-               return getSelectedTree().equals(getMySharedTreeView());
-       }
-       
-       private Folder getUploadFolder() {
-               if (folderTreeView.equals(getSelectedTree()) || otherSharedTreeView.equals(getSelectedTree())) {
-                       return getSelection();
-               }
-               return null;
-       }
-       
-       private void updateUploadFolder() {
-               updateUploadFolder(null);
-       }
-       
-       private void updateUploadFolder(final JsArrayString urls) {
-               if (folderTreeView.equals(getSelectedTree()) || otherSharedTreeView.equals(getSelectedTree())) {
-                       Folder f = getSelection();
-                       if (getSelectedTree().equals(getFolderTreeView()))
-                               updateFolder(f, true, new Command() {
-                               
-                                       @Override
-                                       public void execute() {
-                                               updateStatistics();
-                                               if (urls != null)
-                                                       selectUploadedFiles(urls);
-                                       }
-                               }, false);
-                       else
-                               updateOtherSharedFolder(f, true, null);
-               }
-       }
-
-       public native void disableUploadArea() /*-{
-               var uploader = $wnd.$("#uploader").pluploadQueue();
-               var dropElm = $wnd.document.getElementById('rightPanel');
-               $wnd.plupload.removeAllEvents(dropElm, uploader.id);
-       }-*/;
-
-       public native void enableUploadArea() /*-{
-               var uploader = $wnd.$("#uploader").pluploadQueue();
-               var dropElm = $wnd.document.getElementById('rightPanel');
-               $wnd.plupload.removeAllEvents(dropElm, uploader.id);
-               if (uploader.runtime == 'html5') {
-                       uploader.settings.drop_element = 'rightPanel';
-                       uploader.trigger('PostInit');
-               }
-       }-*/;
-       
-       public void showUploadAlert(int nOfFiles) {
-               if (uploadAlert == null)
-                       uploadAlert = new UploadAlert(this, nOfFiles);
-               if (!uploadAlert.isShowing())
-                       uploadAlert.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
-                               
-                               @Override
-                               public void setPosition(int offsetWidth, int offsetHeight) {
-                                       uploadAlert.setPopupPosition((Window.getClientWidth() - offsetWidth)/2, statusPanel.getAbsoluteTop() - offsetHeight);
-                               }
-                       });
-               uploadAlert.setNumOfFiles(nOfFiles);
-       }
-       
-       public void hideUploadAlert() {
-               if (uploadAlert != null && uploadAlert.isShowing())
-                       uploadAlert.hide();
-       }
-       
-       public void selectUploadedFiles(JsArrayString urls) {
-               List<String> selectedUrls = new ArrayList<String>();
-               for (int i=0; i<urls.length(); i++)
-                       selectedUrls.add(urls.get(i));
-               fileList.selectByUrl(selectedUrls);
-       }
-       
-       public void emptyContainer(final Folder container) {
-               String path = "/" + container.getName() + "?delimiter=/";
-               DeleteRequest delete = new DeleteRequest(getApiPath(), getUsername(), path) {
-                       
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               sessionExpired();
-                       }
-                       
-                       @Override
-                       public void onSuccess(Resource result) {
-                               updateFolder(container, true, null, true);
-                       }
-                       
-                       @Override
-                       public void onError(Throwable t) {
+        selectionModels.add(model);
+    }
+
+    public OtherSharedTreeView getOtherSharedTreeView() {
+        return otherSharedTreeView;
+    }
+
+    public void updateTrash(boolean showFiles, Command callback) {
+        updateFolder(trash, showFiles, callback, true);
+    }
+
+    public void updateGroupsNode() {
+        groupTreeView.updateGroupNode(null);
+    }
+
+    public Group addGroup(String groupName) {
+        final Group group = new Group(groupName);
+        account.addGroup(group);
+        groupTreeView.updateGroupNode(null);
+        return group;
+    }
+
+    public void removeGroup(Group group) {
+        account.removeGroup(group);
+        updateGroupsNode();
+    }
+
+    public TreeView getSelectedTree() {
+        return selectedTree;
+    }
+
+    public void setSelectedTree(TreeView selected) {
+        selectedTree = selected;
+    }
+
+    public Folder getSelection() {
+        if(selectedTree != null) {
+            return selectedTree.getSelection();
+        }
+        return null;
+    }
+
+    public void showFolderStatistics(int folderFileCount) {
+        numOfFiles.setHTML(String.valueOf(folderFileCount));
+    }
+
+    public GroupTreeView getGroupTreeView() {
+        return groupTreeView;
+    }
+
+    public void sessionExpired() {
+        new SessionExpiredDialog(this).center();
+    }
+
+    public void updateRootFolder(Command callback) {
+        updateFolder(account.getPithos(), false, callback, true);
+    }
+
+    void createMySharedTree() {
+        mysharedTreeSelectionModel = new SingleSelectionModel<Folder>();
+        mysharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
+            @Override
+            public void onSelectionChange(SelectionChangeEvent event) {
+                if(mysharedTreeSelectionModel.getSelectedObject() != null) {
+                    deselectOthers(mysharedTreeView, mysharedTreeSelectionModel);
+                    upload.setEnabled(false);
+                    disableUploadArea();
+                    updateSharedFolder(mysharedTreeSelectionModel.getSelectedObject(), true);
+                    showRelevantToolbarButtons();
+                }
+                else {
+                    if(getSelectedTree().equals(mysharedTreeView)) {
+                        setSelectedTree(null);
+                    }
+                    if(getSelectedTree() == null) {
+                        showRelevantToolbarButtons();
+                    }
+                }
+            }
+        });
+        selectionModels.add(mysharedTreeSelectionModel);
+        mysharedTreeViewModel = new MysharedTreeViewModel(Pithos.this, mysharedTreeSelectionModel);
+        mysharedTreeViewModel.initialize(new Command() {
+
+            @Override
+            public void execute() {
+                mysharedTreeView = new MysharedTreeView(mysharedTreeViewModel);
+                trees.insert(mysharedTreeView, 2);
+                treeViews.add(mysharedTreeView);
+                createOtherSharedTree();
+            }
+        });
+    }
+
+    void createOtherSharedTree() {
+        otherSharedTreeSelectionModel = new SingleSelectionModel<Folder>();
+        otherSharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
+            @Override
+            public void onSelectionChange(SelectionChangeEvent event) {
+                if(otherSharedTreeSelectionModel.getSelectedObject() != null) {
+                    deselectOthers(otherSharedTreeView, otherSharedTreeSelectionModel);
+                    applyPermissions(otherSharedTreeSelectionModel.getSelectedObject());
+                    updateOtherSharedFolder(otherSharedTreeSelectionModel.getSelectedObject(), true, null);
+                    showRelevantToolbarButtons();
+                }
+                else {
+                    if(getSelectedTree().equals(otherSharedTreeView)) {
+                        setSelectedTree(null);
+                    }
+                    if(getSelectedTree() == null) {
+                        showRelevantToolbarButtons();
+                    }
+                }
+            }
+        });
+        selectionModels.add(otherSharedTreeSelectionModel);
+        otherSharedTreeViewModel = new OtherSharedTreeViewModel(Pithos.this, otherSharedTreeSelectionModel);
+        otherSharedTreeViewModel.initialize(new Command() {
+
+            @Override
+            public void execute() {
+                otherSharedTreeView = new OtherSharedTreeView(otherSharedTreeViewModel);
+                trees.insert(otherSharedTreeView, 1);
+                treeViews.add(otherSharedTreeView);
+                scheduleResfresh();
+            }
+        });
+    }
+
+    public native void log1(String message)/*-{
+      $wnd.console.log(message);
+    }-*/;
+
+    public String getErrorData() {
+        if(error != null) {
+            return error.toString();
+        }
+        return "";
+    }
+
+    public void setError(Throwable t) {
+        error = t;
+    }
+
+    public void showRelevantToolbarButtons() {
+        toolbar.showRelevantButtons();
+    }
+
+    public FileUploadDialog getFileUploadDialog() {
+        if(fileUploadDialog == null) {
+            fileUploadDialog = new FileUploadDialog(this);
+        }
+        return fileUploadDialog;
+    }
+
+    public void hideUploadIndicator() {
+        upload.removeStyleName("pithos-uploadButton-loading");
+        upload.setTitle("");
+    }
+
+    public void showUploadIndicator() {
+        upload.addStyleName("pithos-uploadButton-loading");
+        upload.setTitle("Upload in progress. Click for details.");
+    }
+
+    public void scheduleFolderHeadCommand(final Folder folder, final Command callback) {
+        if(folder == null) {
+            if(callback != null) {
+                callback.execute();
+            }
+        }
+        else {
+            HeadRequest<Folder> headFolder = new HeadRequest<Folder>(this, Folder.class, getApiPath(), folder.getOwnerID(), folder.getUri(), folder) {
+
+                @Override
+                public void onSuccess(Folder _result) {
+                    if(callback != null) {
+                        callback.execute();
+                    }
+                }
+
+                @Override
+                public void onError(Throwable t) {
+                    if(t instanceof RestException) {
+                        if(((RestException) t).getHttpStatusCode() == Response.SC_NOT_FOUND) {
+                            final String path = folder.getUri();
+                            PutRequest newFolder = new PutRequest(Pithos.this, getApiPath(), folder.getOwnerID(), path) {
+                                @Override
+                                public void onSuccess(Resource _result) {
+                                    scheduleFolderHeadCommand(folder, callback);
+                                }
+
+                                @Override
+                                public void onError(Throwable _t) {
+                                    GWT.log("", _t);
+                                    setError(_t);
+                                    if(_t instanceof RestException) {
+                                        displayError("Unable to create folder: " + ((RestException) _t).getHttpStatusText());
+                                    }
+                                    else {
+                                        displayError("System error creating folder: " + _t.getMessage());
+                                    }
+                                }
+
+                                @Override
+                                protected void onUnauthorized(Response response) {
+                                    sessionExpired();
+                                }
+                            };
+                            newFolder.setHeader(Const.X_AUTH_TOKEN, getUserToken());
+                            newFolder.setHeader(Const.CONTENT_TYPE, "application/folder");
+                            newFolder.setHeader(Const.ACCEPT, "*/*");
+                            newFolder.setHeader(Const.CONTENT_LENGTH, "0");
+                            Scheduler.get().scheduleDeferred(newFolder);
+                        }
+                        else if(((RestException) t).getHttpStatusCode() == Response.SC_FORBIDDEN) {
+                            onSuccess(folder);
+                        }
+                        else {
+                            displayError("Error heading folder: " + ((RestException) t).getHttpStatusText());
+                        }
+                    }
+                    else {
+                        displayError("System error heading folder: " + t.getMessage());
+                    }
+
+                    GWT.log("Error heading folder", t);
+                    setError(t);
+                }
+
+                @Override
+                protected void onUnauthorized(Response response) {
+                    sessionExpired();
+                }
+            };
+            headFolder.setHeader(Const.X_AUTH_TOKEN, getUserToken());
+            Scheduler.get().scheduleDeferred(headFolder);
+        }
+    }
+
+    public void scheduleFileHeadCommand(File f, final Command callback) {
+        HeadRequest<File> headFile = new HeadRequest<File>(this, File.class, getApiPath(), f.getOwnerID(), f.getUri(), f) {
+
+            @Override
+            public void onSuccess(File _result) {
+                if(callback != null) {
+                    callback.execute();
+                }
+            }
+
+            @Override
+            public void onError(Throwable t) {
+                GWT.log("Error heading file", t);
+                setError(t);
+                if(t instanceof RestException) {
+                    displayError("Error heading file: " + ((RestException) t).getHttpStatusText());
+                }
+                else {
+                    displayError("System error heading file: " + t.getMessage());
+                }
+            }
+
+            @Override
+            protected void onUnauthorized(Response response) {
+                sessionExpired();
+            }
+        };
+        headFile.setHeader(Const.X_AUTH_TOKEN, getUserToken());
+        Scheduler.get().scheduleDeferred(headFile);
+    }
+
+    public boolean isMySharedSelected() {
+        return getSelectedTree().equals(getMySharedTreeView());
+    }
+
+    private Folder getUploadFolder() {
+        if(folderTreeView.equals(getSelectedTree()) || otherSharedTreeView.equals(getSelectedTree())) {
+            return getSelection();
+        }
+        return null;
+    }
+
+    private void updateUploadFolder() {
+        updateUploadFolder(null);
+    }
+
+    private void updateUploadFolder(final JsArrayString urls) {
+        if(folderTreeView.equals(getSelectedTree()) || otherSharedTreeView.equals(getSelectedTree())) {
+            Folder f = getSelection();
+            if(getSelectedTree().equals(getFolderTreeView())) {
+                updateFolder(f, true, new Command() {
+
+                    @Override
+                    public void execute() {
+                        updateStatistics();
+                        if(urls != null) {
+                            selectUploadedFiles(urls);
+                        }
+                    }
+                }, false);
+            }
+            else {
+                updateOtherSharedFolder(f, true, null);
+            }
+        }
+    }
+
+    public native void disableUploadArea() /*-{
+      var uploader = $wnd.$("#uploader").pluploadQueue();
+      var dropElm = $wnd.document.getElementById('rightPanel');
+      $wnd.plupload.removeAllEvents(dropElm, uploader.id);
+    }-*/;
+
+    public native void enableUploadArea() /*-{
+      var uploader = $wnd.$("#uploader").pluploadQueue();
+      var dropElm = $wnd.document.getElementById('rightPanel');
+      $wnd.plupload.removeAllEvents(dropElm, uploader.id);
+      if (uploader.runtime == 'html5') {
+        uploader.settings.drop_element = 'rightPanel';
+        uploader.trigger('PostInit');
+      }
+    }-*/;
+
+    public void showUploadAlert(int nOfFiles) {
+        if(uploadAlert == null) {
+            uploadAlert = new UploadAlert(this, nOfFiles);
+        }
+        if(!uploadAlert.isShowing()) {
+            uploadAlert.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
+
+                @Override
+                public void setPosition(int offsetWidth, int offsetHeight) {
+                    uploadAlert.setPopupPosition((Window.getClientWidth() - offsetWidth) / 2, statusPanel.getAbsoluteTop() - offsetHeight);
+                }
+            });
+        }
+        uploadAlert.setNumOfFiles(nOfFiles);
+    }
+
+    public void hideUploadAlert() {
+        if(uploadAlert != null && uploadAlert.isShowing()) {
+            uploadAlert.hide();
+        }
+    }
+
+    public void selectUploadedFiles(JsArrayString urls) {
+        List<String> selectedUrls = new ArrayList<String>();
+        for(int i = 0; i < urls.length(); i++) {
+            selectedUrls.add(urls.get(i));
+        }
+        fileList.selectByUrl(selectedUrls);
+    }
+
+    public void emptyContainer(final Folder container) {
+        String path = "/" + container.getName() + "?delimiter=/";
+        DeleteRequest delete = new DeleteRequest(this, getApiPath(), getUserID(), path) {
+
+            @Override
+            protected void onUnauthorized(Response response) {
+                sessionExpired();
+            }
+
+            @Override
+            public void onSuccess(Resource result) {
+                updateFolder(container, true, null, true);
+            }
+
+            @Override
+            public void onError(Throwable t) {
                 GWT.log("Error deleting trash", t);
-                               setError(t);
-                if (t instanceof RestException)
+                setError(t);
+                if(t instanceof RestException) {
                     displayError("Error deleting trash: " + ((RestException) t).getHttpStatusText());
-                else
+                }
+                else {
                     displayError("System error deleting trash: " + t.getMessage());
-                       }
-               };
-               delete.setHeader("X-Auth-Token", getToken());
-               Scheduler.get().scheduleDeferred(delete);
-       }
+                }
+            }
+        };
+        delete.setHeader(Const.X_AUTH_TOKEN, getUserToken());
+        Scheduler.get().scheduleDeferred(delete);
+    }
 }
index ba31c1b..78bdac1 100644 (file)
@@ -6,7 +6,6 @@ import com.google.gwt.user.client.ui.PopupPanel;
 public class PleaseWaitPopup extends PopupPanel {
 
        public PleaseWaitPopup() {
-               setAnimationEnabled(true);
                setGlassEnabled(true);
                setModal(true);
                add(new Label("Please wait ..."));
  * or implied, of GRNET S.A.
  */
 
-package gr.grnet.pithos.web.client.foldertree;
+package gr.grnet.pithos.web.client;
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.http.client.Response;
 import com.google.gwt.i18n.client.DateTimeFormat;
 import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
-import com.google.gwt.json.client.JSONNumber;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONString;
-
+import com.google.gwt.json.client.*;
 import gr.grnet.pithos.web.client.Invitations;
 import gr.grnet.pithos.web.client.SharingUsers;
+import gr.grnet.pithos.web.client.foldertree.AccountResource;
+import gr.grnet.pithos.web.client.foldertree.File;
+import gr.grnet.pithos.web.client.foldertree.FileVersions;
+import gr.grnet.pithos.web.client.foldertree.Folder;
 
 import java.util.Date;
 
 public abstract class Resource {
 
-    protected static String unmarshallString(JSONObject obj, String key){
-        if(obj.get(key) != null) {
-            JSONString s = obj.get(key).isString();
-            if(s != null)
+    protected static String unmarshallString(JSONObject obj, String key) {
+        final JSONValue jsonValue = obj.get(key);
+        if(jsonValue != null) {
+            JSONString s = jsonValue.isString();
+            if(s != null) {
                 return s.stringValue();
+            }
         }
         return null;
     }
 
-    protected static int unmarshallInt(JSONObject obj, String key){
-        if(obj.get(key) != null)
-            if(obj.get(key).isNumber() != null)
-                return (int) obj.get(key).isNumber().doubleValue();
+    protected static int unmarshallInt(JSONObject obj, String key) {
+        final JSONValue jsonValue = obj.get(key);
+        if(jsonValue != null) {
+            final JSONNumber jsonNumber = jsonValue.isNumber();
+            if(jsonNumber != null) {
+                return (int) jsonNumber.doubleValue();
+            }
+        }
         return -1;
     }
 
-    protected static long unmarshallLong(JSONObject obj, String key){
-        if(obj.get(key) != null) {
-            JSONNumber value = obj.get(key).isNumber();
-            if(value != null)
-                return (long) value.doubleValue();
+    protected static long unmarshallLong(JSONObject obj, String key) {
+        final JSONValue jsonValue = obj.get(key);
+        if(jsonValue != null) {
+            final JSONNumber jsonNumber = jsonValue.isNumber();
+            if(jsonNumber != null) {
+                return (long) jsonNumber.doubleValue();
+            }
         }
         return -1;
     }
 
-    protected static boolean unmarshallBoolean(JSONObject obj, String key){
-        if(obj.get(key) != null)
-            if(obj.get(key).isBoolean() != null)
-                return obj.get(key).isBoolean().booleanValue();
+    protected static boolean unmarshallBoolean(JSONObject obj, String key) {
+        final JSONValue jsonValue = obj.get(key);
+        if(jsonValue != null) {
+            final JSONBoolean aBoolean = jsonValue.isBoolean();
+            if(aBoolean != null) {
+                return aBoolean.booleanValue();
+            }
+        }
         return false;
     }
 
-    protected static Date unmarshallDate(JSONObject obj, String key){
-        if(obj.get(key) != null) {
-            JSONString s = obj.get(key).isString();
-            if (s != null)
-                               try {
-                                       return DateTimeFormat.getFormat(PredefinedFormat.ISO_8601).parse(s.stringValue());
-                               } catch (IllegalArgumentException e) {
-                                       GWT.log("", e);
-                               }
+    protected static Date unmarshallDate(JSONObject obj, String key) {
+        final JSONValue jsonValue = obj.get(key);
+        if(jsonValue != null) {
+            JSONString jsonString = jsonValue.isString();
+            if(jsonString != null) {
+                try {
+                    return DateTimeFormat.getFormat(PredefinedFormat.ISO_8601).parse(jsonString.stringValue());
+                }
+                catch(IllegalArgumentException e) {
+                    GWT.log("", e);
+                }
+            }
         }
         return null;
     }
 
     public static native String getDate(Long ms)/*-{
-        return (new Date(ms)).toUTCString();
+      return (new Date(ms)).toUTCString();
     }-*/;
 
     @SuppressWarnings("unchecked")
-       public static <T> T createFromResponse(Class<T> aClass, String owner, Response response, T result) {
-       T result1 = null;
-        if (aClass.equals(AccountResource.class)) {
-            result1 = (T) AccountResource.createFromResponse(owner, response, (AccountResource) result);
+    public static <T> T createFromResponse(Pithos app, Class<T> aClass, String owner, Response response, T result) {
+        T result1 = null;
+        if(aClass.equals(AccountResource.class)) {
+            result1 = (T) AccountResource.createFromResponse(app, owner, response, (AccountResource) result);
         }
-        else if (aClass.equals(Folder.class)) {
+        else if(aClass.equals(Folder.class)) {
             result1 = (T) Folder.createFromResponse(owner, response, (Folder) result);
         }
-        else if (aClass.equals(File.class)) {
+        else if(aClass.equals(File.class)) {
             result1 = (T) File.createFromResponse(owner, response, (File) result);
         }
-        else if (aClass.equals(SharingUsers.class)) {
-               result1 = (T) SharingUsers.createFromResponse(response, (SharingUsers) result);
+        else if(aClass.equals(SharingUsers.class)) {
+            result1 = (T) SharingUsers.createFromResponse(response, (SharingUsers) result);
         }
-        else if (aClass.equals(FileVersions.class)) {
-               result1 = (T) FileVersions.createFromResponse(response);
+        else if(aClass.equals(FileVersions.class)) {
+            result1 = (T) FileVersions.createFromResponse(response);
         }
-        else if (aClass.equals(Invitations.class)) {
-               result1 = (T) Invitations.createFromResponse(response);
+        else if(aClass.equals(Invitations.class)) {
+            result1 = (T) Invitations.createFromResponse(response);
         }
         return result1;
     }
-    
+
     public abstract Date getLastModified();
 }
index 199c81a..0e99374 100644 (file)
@@ -55,7 +55,6 @@ public class SessionExpiredDialog extends DialogBox {
         app = _app;
                // Set the dialog's caption.
                setText("Session Expired");
-               setAnimationEnabled(true);
                setGlassEnabled(true);
                setStyleName("pithos-DialogBox");
 
index 52cffcb..575928b 100644 (file)
@@ -34,9 +34,8 @@
  */
 package gr.grnet.pithos.web.client;
 
-import gr.grnet.pithos.web.client.foldertree.Resource;
-
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -47,7 +46,7 @@ import com.google.gwt.json.client.JSONParser;
 import com.google.gwt.json.client.JSONValue;
 
 public class SharingUsers extends Resource {
-       private List<String> users;
+       private List<String> userIDs;
 
        public static SharingUsers createFromResponse(Response response, SharingUsers result) {
                SharingUsers u;
@@ -60,21 +59,21 @@ public class SharingUsers extends Resource {
        }
 
        private void populate(Response response) {
-               users = new ArrayList<String>();
+               userIDs = new ArrayList<String>();
         JSONValue json = JSONParser.parseStrict(response.getText());
         JSONArray array = json.isArray();
         if (array != null) {
             for (int i=0; i<array.size(); i++) {
                 JSONObject o = array.get(i).isObject();
                 if (o != null) {
-                       users.add(unmarshallString(o, "name"));
+                       userIDs.add(unmarshallString(o, "name"));
                 }
             }
         }
        }
 
-       public List<String> getUsers() {
-               return users;
+       public List<String> getUserIDs() {
+               return Collections.unmodifiableList(userIDs);
        }
 
        @Override
index f8d084b..6d1b695 100644 (file)
@@ -78,8 +78,8 @@ public class Toolbar extends Composite {
                        public void onClick(ClickEvent event) {
                                Folder folder = app.getSelectedTree().getSelection();
                                if (folder != null) {
-                               Boolean[] permissions = folder.getPermissions().get(app.getUsername());
-                               boolean canWrite = folder.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
+                               Boolean[] permissions = folder.getPermissions().get(app.getUserID());
+                               boolean canWrite = folder.getOwnerID().equals(app.getUserID()) || (permissions!= null && permissions[1] != null && permissions[1]);
                                
                                if (!folder.isInTrash() && canWrite)
                                        new NewFolderCommand(app, null, folder).execute();
@@ -98,8 +98,8 @@ public class Toolbar extends Composite {
                        public void onClick(ClickEvent event) {
                                Folder folder = app.getSelectedTree().getSelection();
                                if (folder != null) {
-                               Boolean[] permissions = folder.getPermissions().get(app.getUsername());
-                               boolean canWrite = folder.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
+                               Boolean[] permissions = folder.getPermissions().get(app.getUserID());
+                               boolean canWrite = folder.getOwnerID().equals(app.getUserID()) || (permissions!= null && permissions[1] != null && permissions[1]);
                                boolean isFolderTreeSelected = app.getSelectedTree().equals(app.getFolderTreeView());
                                
                                if (!folder.isInTrash() && canWrite && isFolderTreeSelected && !folder.isContainer())
@@ -167,8 +167,8 @@ public class Toolbar extends Composite {
                                        
                                        @Override
                                        public void execute() {
-                                       Boolean[] permissions = folder.getPermissions().get(app.getUsername());
-                                       boolean canWrite = folder.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
+                                       Boolean[] permissions = folder.getPermissions().get(app.getUserID());
+                                       boolean canWrite = folder.getOwnerID().equals(app.getUserID()) || (permissions!= null && permissions[1] != null && permissions[1]);
                                        boolean isFolderTreeSelected = app.getSelectedTree().equals(app.getFolderTreeView());
                                        boolean otherSharedTreeSelected = app.getSelectedTree().equals(app.getOtherSharedTreeView());
                                        
index 481e44e..79a2b08 100644 (file)
@@ -54,7 +54,6 @@ import gr.grnet.pithos.web.client.grouptree.User;
 
 import java.util.List;
 
-import com.google.gwt.http.client.URL;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
@@ -92,13 +91,12 @@ public class ToolsMenu extends PopupPanel {
                // The popup's constructor's argument is a boolean specifying that it
                // auto-close itself when the user clicks outside of it.
                super(true);
-               setAnimationEnabled(true);
                images = newImages;
         MenuBar contextMenu = new MenuBar(true);
 
         if (folder != null) {
-               Boolean[] permissions = folder.getPermissions().get(app.getUsername());
-               boolean canWrite = folder.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
+               Boolean[] permissions = folder.getPermissions().get(app.getUserID());
+               boolean canWrite = folder.getOwnerID().equals(app.getUserID()) || (permissions!= null && permissions[1] != null && permissions[1]);
                boolean isFolderTreeSelected = selectedTree.equals(app.getFolderTreeView());
                boolean isMysharedTreeSelected = app.isMySharedSelected();
                
@@ -137,12 +135,12 @@ public class ToolsMenu extends PopupPanel {
                                        if (item instanceof List) {
                                                @SuppressWarnings("unchecked")
                                                        List<File> _files = (List<File>) item;
-                                               if (_files.get(0).getOwner().equals(folder.getOwner()))
+                                               if (_files.get(0).getOwnerID().equals(folder.getOwnerID()))
                                                        showPaste = true;
                                        }
                                        else {
                                                Folder f = (Folder) item;
-                                               if (f.getOwner().equals(folder.getOwner()))
+                                               if (f.getOwnerID().equals(folder.getOwnerID()))
                                                        showPaste = true;
                                        }
                                        if (showPaste) {
@@ -196,7 +194,7 @@ public class ToolsMenu extends PopupPanel {
                                                        @Override
                                                        public void execute() {
                                                        for (File f: files)
-                                                               Window.open(app.getApiPath() + f.getOwner() + f.getUri(), "_blank", "");
+                                                               Window.open(app.getApiPath() + f.getOwnerID() + f.getUri(), "_blank", "");
                                                        }
                                                }));
                                        empty = false;
index 5616a77..5490dea 100644 (file)
@@ -56,7 +56,6 @@ public class UploadAlert extends PopupPanel {
                // The popup's constructor's argument is a boolean specifying that it
                // auto-close itself when the user clicks outside of it.
                super(false);
-               setAnimationEnabled(true);
                addStyleName(Pithos.resources.pithosCss().uploadAlert());
                FlowPanel content = new FlowPanel();
                setNumOfFiles(_numOfFiles);
index b3634a8..66d4e6b 100644 (file)
@@ -36,7 +36,6 @@ package gr.grnet.pithos.web.client;
 
 import gr.grnet.pithos.web.client.FileVersionsDialog.Images;
 import gr.grnet.pithos.web.client.foldertree.File;
-import gr.grnet.pithos.web.client.foldertree.Resource;
 import gr.grnet.pithos.web.client.foldertree.Version;
 import gr.grnet.pithos.web.client.rest.PostRequest;
 import gr.grnet.pithos.web.client.rest.RestException;
@@ -46,8 +45,6 @@ import java.util.List;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.ScrollHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.http.client.Response;
 import com.google.gwt.http.client.URL;
 import com.google.gwt.i18n.client.DateTimeFormat;
@@ -58,11 +55,6 @@ import com.google.gwt.user.client.ui.CustomScrollPanel;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.NativeVerticalScrollbar;
-import com.google.gwt.user.client.ui.ScrollPanel;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.VerticalScrollbar;
-import com.google.gwt.user.client.ui.Widget;
 
 public class VersionsList extends Composite {
 
@@ -124,7 +116,7 @@ public class VersionsList extends Composite {
                        downloadHtml.addClickHandler(new ClickHandler() {
                                @Override
                                public void onClick(ClickEvent event) {
-                                       String fileUrl = app.getApiPath() + file.getOwner() + file.getUri() + "?version=" + v.getVersion();
+                                       String fileUrl = app.getApiPath() + file.getOwnerID() + file.getUri() + "?version=" + v.getVersion();
                                        Window.open(fileUrl, "_BLANK", "");
                                }
                        });
@@ -140,7 +132,7 @@ public class VersionsList extends Composite {
 
        void restoreVersion(int version) {
                String path = file.getUri() + "?update=";
-               PostRequest restoreVersion = new PostRequest(app.getApiPath(), file.getOwner(), path) {
+               PostRequest restoreVersion = new PostRequest(app, app.getApiPath(), file.getOwnerID(), path) {
                        
                        @Override
                        public void onSuccess(Resource result) {
@@ -165,7 +157,7 @@ public class VersionsList extends Composite {
                                app.sessionExpired();
                        }
                };
-               restoreVersion.setHeader("X-Auth-Token", app.getToken());
+               restoreVersion.setHeader("X-Auth-Token", app.getUserToken());
                restoreVersion.setHeader("X-Source-Object", URL.encodePathSegment(file.getUri()));
                restoreVersion.setHeader("X-Source-Version", String.valueOf(version));
                restoreVersion.setHeader("Content-Range", "bytes 0-/*");
diff --git a/src/gr/grnet/pithos/web/client/animation/FadeIn.java b/src/gr/grnet/pithos/web/client/animation/FadeIn.java
deleted file mode 100644 (file)
index 9967260..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011-2012 GRNET S.A. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- *   1. Redistributions of source code must retain the above
- *      copyright notice, this list of conditions and the following
- *      disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above
- *      copyright notice, this list of conditions and the following
- *      disclaimer in the documentation and/or other materials
- *      provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and
- * documentation are those of the authors and should not be
- * interpreted as representing official policies, either expressed
- * or implied, of GRNET S.A.
- */
-package gr.grnet.pithos.web.client.animation;
-
-import com.google.gwt.animation.client.Animation;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Widget;
-
-
-public class FadeIn extends Animation {
-       Widget widget;
-       int initialOpacity = 100;
-       double currOpacity = 100;
-
-       public FadeIn(Widget aWidget){
-               widget = aWidget;
-       }
-
-       @Override
-       protected void onUpdate(double progress) {
-               if(currOpacity > 0.0){
-                       double progress1 = 1.0 - progress;
-                       currOpacity = initialOpacity * progress1;
-                       DOM.setStyleAttribute(widget.getElement(), "opacity", ""+new Double(1d - currOpacity / 100d));
-               }
-       }
-
-}
diff --git a/src/gr/grnet/pithos/web/client/animation/FadeOut.java b/src/gr/grnet/pithos/web/client/animation/FadeOut.java
deleted file mode 100644 (file)
index 474de0a..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2011-2012 GRNET S.A. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- *   1. Redistributions of source code must retain the above
- *      copyright notice, this list of conditions and the following
- *      disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above
- *      copyright notice, this list of conditions and the following
- *      disclaimer in the documentation and/or other materials
- *      provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and
- * documentation are those of the authors and should not be
- * interpreted as representing official policies, either expressed
- * or implied, of GRNET S.A.
- */
-package gr.grnet.pithos.web.client.animation;
-
-import com.google.gwt.animation.client.Animation;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Widget;
-
-
-public class FadeOut extends Animation {
-       Widget widget;
-
-       int initialOpacity = 100;
-       double currOpacity = 100;
-
-       public FadeOut(Widget aWidget){
-               widget = aWidget;
-       }
-
-       @Override
-       protected void onUpdate(double progress) {
-               if(currOpacity>0.0){
-                       double progress1 = 1.0 - progress;
-                       currOpacity = initialOpacity*progress1;
-                       DOM.setStyleAttribute(widget.getElement(), "opacity", ""+new Double(currOpacity/100d));
-               }
-       }
-
-       /*
-       protected void onComplete() {
-               super.onComplete();
-               hpanel.clear();
-               html = new HTML("&nbsp;");
-               hpanel.getParent().setVisible(false);
-       }
-       */
-
-}
diff --git a/src/gr/grnet/pithos/web/client/catalog/GetUserCatalogs.java b/src/gr/grnet/pithos/web/client/catalog/GetUserCatalogs.java
new file mode 100644 (file)
index 0000000..e234304
--- /dev/null
@@ -0,0 +1,149 @@
+package gr.grnet.pithos.web.client.catalog;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.http.client.*;
+import com.google.gwt.json.client.JSONArray;
+import com.google.gwt.json.client.JSONObject;
+import com.google.gwt.json.client.JSONParser;
+import com.google.gwt.json.client.JSONValue;
+import gr.grnet.pithos.web.client.Helpers;
+import gr.grnet.pithos.web.client.Pithos;
+
+import java.util.List;
+
+/**
+ * The request via which we obtain user catalog info.
+ */
+public class GetUserCatalogs implements Scheduler.ScheduledCommand {
+    private final String url;
+    private final String userToken;
+    private final List<String> ids;
+    private final List<String> names;
+
+    public static final int SuccessCode = 200;
+    public static final String CallEndPoint = "/user_catalogs";
+    public static final String RequestField_uuids = "uuids";
+    public static final String RequestField_displaynames = "displaynames";
+    public static final String ResponseField_displayname_catalog = "displayname_catalog";
+    public static final String ResponseField_uuid_catalog = "uuid_catalog";
+
+    public GetUserCatalogs(Pithos app) {
+        this(app, null, null);
+    }
+
+    public GetUserCatalogs(Pithos app, String userID) {
+        this(app, Helpers.toList(userID), null);
+    }
+
+    public GetUserCatalogs(Pithos app, List<String> ids) {
+        this(app, ids, null);
+    }
+
+    public GetUserCatalogs(Pithos app, List<String> ids, List<String> names) {
+        assert app != null;
+
+        // FIXME: Probably use Window.Location.getHost()
+        // https://server.com/v1/ --> https://server.com
+        String path = app.getApiPath();
+        path = Helpers.stripTrailing(path, "/");
+        path = Helpers.upToIncludingLastPart(path, "/");
+        path = Helpers.stripTrailing(path, "/");
+
+        // https://server.com/user_catalogs
+        this.url = path + CallEndPoint;
+
+        this.ids = Helpers.safeList(ids);
+        this.names = Helpers.safeList(names);
+        this.userToken = app.getUserToken();
+    }
+
+    public String getURL() {
+        return url;
+    }
+
+    private JSONObject makeRequestData() {
+        final JSONObject root = new JSONObject();
+        final JSONArray uuids = Helpers.listToJSONArray(ids);
+        final JSONArray displaynames = Helpers.listToJSONArray(names);
+
+        root.put(RequestField_uuids, uuids);
+        root.put(RequestField_displaynames, displaynames);
+
+        return root;
+    }
+
+    public UserCatalogs parseResult(JSONObject result) {
+        final UserCatalogs userCatalogs = new UserCatalogs();
+        final JSONObject uuid_catalog = result.get(ResponseField_uuid_catalog).isObject();
+        final JSONObject displayname_catalog = result.get(ResponseField_displayname_catalog).isObject();
+
+        for(String uuid: uuid_catalog.keySet()) {
+            final String name = uuid_catalog.get(uuid).isString().stringValue();
+            userCatalogs.updateWithIDAndName(uuid, name);
+        }
+
+        for(String name: displayname_catalog.keySet()) {
+            final String uuid = displayname_catalog.get(name).isString().stringValue();
+            userCatalogs.updateWithIDAndName(uuid, name);
+        }
+
+        return userCatalogs;
+    }
+
+    public void onSuccess(Request request, Response response, JSONObject result, UserCatalogs userCatalogs) {
+    }
+
+    public void onBadStatusCode(Request request, Response response) {
+    }
+
+    public void onError(Request request, Throwable t) {
+        GWT.log("GetUserCatalogs", t);
+    }
+
+    @Override
+    public void execute() {
+        final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, getURL());
+        rb.setHeader("X-Auth-Token", userToken);
+        final String requestData = makeRequestData().toString();
+
+        try {
+            rb.sendRequest(requestData, new RequestCallback() {
+                @Override
+                public void onResponseReceived(Request request, Response response) {
+                    final int statusCode = response.getStatusCode();
+
+                    if(statusCode != SuccessCode) {
+                        GetUserCatalogs.this.onBadStatusCode(request, response);
+                        return;
+                    }
+
+                    final String responseText = response.getText();
+                    final JSONValue jsonValue = JSONParser.parseStrict(responseText);
+                    final JSONObject result = jsonValue.isObject();
+
+                    if(result == null) {
+                        GetUserCatalogs.this.onError(request, new Exception("GetUserCatalogs: json result is not an object"));
+                        return;
+                    }
+
+                    final UserCatalogs userCatalogs = parseResult(result);
+
+                    GetUserCatalogs.this.onSuccess(request, response, result, userCatalogs);
+                }
+
+                @Override
+                public void onError(Request request, Throwable exception) {
+                    GetUserCatalogs.this.onError(request, exception);
+                }
+            });
+        }
+        catch(Exception e) {
+            GWT.log("GetUserCatalogs", e);
+        }
+    }
+
+    public void scheduleDeferred() {
+        Scheduler.get().scheduleDeferred(this);
+    }
+}
diff --git a/src/gr/grnet/pithos/web/client/catalog/UpdateUserCatalogs.java b/src/gr/grnet/pithos/web/client/catalog/UpdateUserCatalogs.java
new file mode 100644 (file)
index 0000000..645905e
--- /dev/null
@@ -0,0 +1,67 @@
+package gr.grnet.pithos.web.client.catalog;
+
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.Response;
+import com.google.gwt.json.client.JSONObject;
+import gr.grnet.pithos.web.client.Helpers;
+import gr.grnet.pithos.web.client.Pithos;
+
+import java.util.List;
+
+/**
+ * This is a wrapper around GetUserCatalogs that takes care of updating
+ * the application-wide user catalogs.
+ */
+public class UpdateUserCatalogs implements Scheduler.ScheduledCommand {
+    private final GetUserCatalogs getUserCatalogs;
+    private final Pithos app;
+
+    public UpdateUserCatalogs(Pithos app) {
+        this(app, null, null);
+    }
+
+    public UpdateUserCatalogs(Pithos app, String userID) {
+        this(app, Helpers.toList(userID), null);
+    }
+
+    public UpdateUserCatalogs(Pithos app, List<String> ids) {
+        this(app, ids, null);
+    }
+
+    public void onSuccess(UserCatalogs requestedUserCatalogs, UserCatalogs updatedUserCatalogs) {
+    }
+
+    public void onError(Request request, Throwable t) {
+        getUserCatalogs.onError(request, t);
+    }
+
+    public UpdateUserCatalogs(Pithos app, List<String> ids, List<String> names) {
+        this.app = app;
+        this.getUserCatalogs = new GetUserCatalogs(app, ids, names) {
+            @Override
+            public void onSuccess(Request request, Response response, JSONObject result, UserCatalogs userCatalogs) {
+                UpdateUserCatalogs.this.app.getUserCatalogs().updateFrom(userCatalogs);
+                UpdateUserCatalogs.this.onSuccess(userCatalogs, UpdateUserCatalogs.this.app.getUserCatalogs());
+            }
+
+            @Override
+            public void onError(Request request, Throwable t) {
+                UpdateUserCatalogs.this.onError(request, t);
+            }
+        };
+    }
+
+    @Override
+    public void execute() {
+        this.getUserCatalogs.execute();
+    }
+
+    public void scheduleDeferred() {
+        Scheduler.get().scheduleDeferred(this);
+    }
+
+    public void scheduleEntry() {
+        Scheduler.get().scheduleEntry(this);
+    }
+}
diff --git a/src/gr/grnet/pithos/web/client/catalog/UserCatalogs.java b/src/gr/grnet/pithos/web/client/catalog/UserCatalogs.java
new file mode 100644 (file)
index 0000000..4fb2a6a
--- /dev/null
@@ -0,0 +1,68 @@
+package gr.grnet.pithos.web.client.catalog;
+
+import gr.grnet.pithos.web.client.Helpers;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Holds one-to-one mappings from user IDs to respective user display names.
+ *
+ * The iterator returns map entries with id as the key and name as the value.
+ */
+public class UserCatalogs implements Iterable<Map.Entry<String, String>>{
+    private HashMap<String, String> id2name = new HashMap<String, String>();
+    private HashMap<String, String> name2id = new HashMap<String, String>();
+
+    public UserCatalogs() {
+        this(new HashMap<String, String>(), new HashMap<String, String>());
+    }
+
+    private UserCatalogs(HashMap<String, String> id2name, HashMap<String, String> name2id) {
+        this.id2name = id2name;
+        this.name2id = name2id;
+    }
+
+    public UserCatalogs updateWithIDAndName(String id, String name) {
+        this.id2name.put(id, name);
+        this.name2id.put(name, id);
+
+        return this;
+    }
+
+    public UserCatalogs updateFrom(UserCatalogs other) {
+        for(Map.Entry<String, String> otherIDAndName : other) {
+            this.updateWithIDAndName(otherIDAndName.getKey(), otherIDAndName.getValue());
+        }
+        return this;
+    }
+
+    public UserCatalogs copy() {
+        return new UserCatalogs(
+            Helpers.copyHashMap(id2name),
+            Helpers.copyHashMap(name2id)
+        );
+    }
+
+    public boolean hasUserID(String id) {
+        return id2name.containsKey(id);
+    }
+
+    public boolean hasUserDisplayName(String displayName) {
+        return name2id.containsKey(displayName);
+    }
+
+    public String getUserDisplayName(String userID) {
+        return id2name.get(userID);
+    }
+
+    public String getUserID(String displayName) {
+        return name2id.get(displayName);
+    }
+
+    @Override
+    public Iterator<Map.Entry<String, String>> iterator() {
+        return id2name.entrySet().iterator();
+    }
+}
index 5fe90a8..264e5c7 100644 (file)
@@ -36,17 +36,9 @@ package gr.grnet.pithos.web.client.commands;
 
 import gr.grnet.pithos.web.client.AddUserDialog;
 import gr.grnet.pithos.web.client.Pithos;
-import gr.grnet.pithos.web.client.foldertree.Resource;
 import gr.grnet.pithos.web.client.grouptree.Group;
-import gr.grnet.pithos.web.client.rest.PostRequest;
-import gr.grnet.pithos.web.client.rest.RestException;
 
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.http.client.Response;
-import com.google.gwt.http.client.URL;
 import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.PopupPanel;
 
 /**
index 19ec973..456cc06 100644 (file)
@@ -34,8 +34,9 @@
  */
 package gr.grnet.pithos.web.client.commands;
 
+import gr.grnet.pithos.web.client.Const;
 import gr.grnet.pithos.web.client.Pithos;
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Resource;
 import gr.grnet.pithos.web.client.grouptree.Group;
 import gr.grnet.pithos.web.client.rest.PostRequest;
 import gr.grnet.pithos.web.client.rest.RestException;
@@ -75,7 +76,7 @@ public class DeleteGroupCommand implements Command {
                containerPanel.hide();
         if (Window.confirm("Are you sure you want to delete group " + group.getName())) {
                String path = "?update=";
-               PostRequest updateGroup = new PostRequest(app.getApiPath(), app.getUsername(), path) {
+               PostRequest updateGroup = new PostRequest(app, app.getApiPath(), app.getUserID(), path) {
                                
                                @Override
                                public void onSuccess(Resource result) {
@@ -98,8 +99,8 @@ public class DeleteGroupCommand implements Command {
                                        app.sessionExpired();
                                }
                        };
-                       updateGroup.setHeader("X-Auth-Token", app.getToken());
-                       updateGroup.setHeader("X-Account-Group-" + URL.encodePathSegment(group.getName()), "~");
+                       updateGroup.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
+                       updateGroup.setHeader(Const.X_ACCOUNT_GROUP_ + URL.encodePathSegment(group.getName()), "~");
                        Scheduler.get().scheduleDeferred(updateGroup);
         }
        }
index 9e677b9..8aa805a 100644 (file)
 package gr.grnet.pithos.web.client.commands;
 
 import gr.grnet.pithos.web.client.Pithos;
-import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.foldertree.Folder;
-import gr.grnet.pithos.web.client.foldertree.Resource;
-import gr.grnet.pithos.web.client.rest.DeleteRequest;
-import gr.grnet.pithos.web.client.rest.GetRequest;
-import gr.grnet.pithos.web.client.rest.RestException;
 
-import java.util.Iterator;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.http.client.Response;
-import com.google.gwt.http.client.URL;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.ui.PopupPanel;
 
index e46eeb6..ccbcda8 100644 (file)
@@ -39,7 +39,7 @@ import gr.grnet.pithos.web.client.Clipboard;
 import gr.grnet.pithos.web.client.Pithos;
 import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.foldertree.Folder;
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Resource;
 import gr.grnet.pithos.web.client.rest.PutRequest;
 import gr.grnet.pithos.web.client.rest.RestException;
 
@@ -77,7 +77,7 @@ public class PasteCommand implements Command {
             final Folder tobeCopied = (Folder) clipboardItem;
             if (operation == Clipboard.COPY) {
                String targetUri = folder.getUri() + "/" + tobeCopied.getName();
-                app.copyFolder(tobeCopied, folder.getOwner(), targetUri, false, new Command() {
+                app.copyFolder(tobeCopied, folder.getOwnerID(), targetUri, false, new Command() {
                     @Override
                     public void execute() {
                         app.getClipboard().clear();
@@ -93,7 +93,7 @@ public class PasteCommand implements Command {
             }
             else {
                String targetUri = folder.getUri() + "/" + tobeCopied.getName();
-                app.copyFolder(tobeCopied, folder.getOwner(), targetUri, true, new Command() {
+                app.copyFolder(tobeCopied, folder.getOwnerID(), targetUri, true, new Command() {
                     @Override
                     public void execute() {
                         app.getClipboard().clear();
@@ -107,7 +107,7 @@ public class PasteCommand implements Command {
                        List<File> tobeCopied = (List<File>) clipboardItem;
             Iterator<File> iter = tobeCopied.iterator();
             if (operation == Clipboard.COPY) {
-                app.copyFiles(iter, folder.getOwner(), folder.getUri(), new Command() {
+                app.copyFiles(iter, folder.getOwnerID(), folder.getUri(), new Command() {
                     @Override
                     public void execute() {
                         app.getClipboard().clear();
@@ -137,7 +137,7 @@ public class PasteCommand implements Command {
         if (iter.hasNext()) {
             File file = iter.next();
             String path = folder.getUri() + "/" + file.getName();
-            PutRequest copyFile = new PutRequest(app.getApiPath(), folder.getOwner(), path) {
+            PutRequest copyFile = new PutRequest(app, app.getApiPath(), folder.getOwnerID(), path) {
                 @Override
                 public void onSuccess(Resource result) {
                     moveFiles(iter, callback);
@@ -159,7 +159,7 @@ public class PasteCommand implements Command {
                                        app.sessionExpired();
                                }
             };
-            copyFile.setHeader("X-Auth-Token", app.getToken());
+            copyFile.setHeader("X-Auth-Token", app.getUserToken());
             copyFile.setHeader("X-Move-From", URL.encodePathSegment(file.getUri()));
             copyFile.setHeader("Content-Type", file.getContentType());
             Scheduler.get().scheduleDeferred(copyFile);
index 7bc14fa..d39a3ab 100644 (file)
  */
 package gr.grnet.pithos.web.client.commands;
 
-import gr.grnet.pithos.web.client.Pithos;
-import gr.grnet.pithos.web.client.foldertree.Resource;
-import gr.grnet.pithos.web.client.grouptree.Group;
-import gr.grnet.pithos.web.client.grouptree.User;
-import gr.grnet.pithos.web.client.rest.PostRequest;
-import gr.grnet.pithos.web.client.rest.RestException;
-
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.http.client.Response;
 import com.google.gwt.http.client.URL;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.ui.PopupPanel;
+import gr.grnet.pithos.web.client.Const;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.Resource;
+import gr.grnet.pithos.web.client.grouptree.Group;
+import gr.grnet.pithos.web.client.grouptree.User;
+import gr.grnet.pithos.web.client.rest.PostRequest;
+import gr.grnet.pithos.web.client.rest.RestException;
 
 /**
  * Display the 'new folder' dialog for creating a new folder.
- *
  */
 public class RemoveUserCommand implements Command {
-       private PopupPanel containerPanel;
+    private PopupPanel containerPanel;
 
     User user;
 
     Pithos app;
 
-       /**
-        * @param aContainerPanel
-        */
-       public RemoveUserCommand(Pithos _app, PopupPanel aContainerPanel, User _user){
+    /**
+     * @param aContainerPanel
+     */
+    public RemoveUserCommand(Pithos _app, PopupPanel aContainerPanel, User _user) {
         app = _app;
-               containerPanel = aContainerPanel;
-           user = _user;
-       }
+        containerPanel = aContainerPanel;
+        user = _user;
+    }
+
+    @Override
+    public void execute() {
+        if(containerPanel != null) {
+            containerPanel.hide();
+        }
+        final String groupName = user.getGroup();
+        final Group group = app.getAccount().getGroup(groupName);
+        if(group == null) {
+            return;
+        }
+        group.removeUser(user);
+        String path = "?update=";
+        PostRequest updateGroup = new PostRequest(app, app.getApiPath(), app.getUserID(), path) {
+
+            @Override
+            public void onSuccess(Resource result) {
+                app.fetchAccount(new Command() {
+
+                    @Override
+                    public void execute() {
+                        Group updatedGroup2 = app.getAccount().getGroup(groupName);
+                        if(updatedGroup2 != null) {
+                            app.updateGroupNode(updatedGroup2);
+                        }
+                        else {
+                            app.updateGroupNode(null);
+                        }
+                    }
+                });
+            }
 
-       @Override
-       public void execute() {
-        if (containerPanel != null)
-                   containerPanel.hide();
-       final String groupName = user.getGroup();
-       final Group group = app.getAccount().getGroup(groupName);
-       if (group == null)
-               return;
-       group.removeMember(user.getName());
-       String path = "?update=";
-       PostRequest updateGroup = new PostRequest(app.getApiPath(), app.getUsername(), path) {
-                       
-                       @Override
-                       public void onSuccess(Resource result) {
-                               app.fetchAccount(new Command() {
-                                       
-                                       @Override
-                                       public void execute() {
-                                               Group updatedGroup2 = app.getAccount().getGroup(groupName);
-                                               if (updatedGroup2 != null)
-                                                       app.updateGroupNode(updatedGroup2);
-                                               else {
-                                                       app.updateGroupNode(null);
-                                               }
-                                       }
-                               });
-                       }
-                       
-                       @Override
-                       public void onError(Throwable t) {
-                               GWT.log("", t);
-                               app.setError(t);
-                               if (t instanceof RestException) {
-                                       app.displayError("Unable to update group:" + ((RestException) t).getHttpStatusText());
-                               }
-                               else
-                                       app.displayError("System error updating group:" + t.getMessage());
-                       }
+            @Override
+            public void onError(Throwable t) {
+                GWT.log("", t);
+                app.setError(t);
+                if(t instanceof RestException) {
+                    app.displayError("Unable to update group:" + ((RestException) t).getHttpStatusText());
+                }
+                else {
+                    app.displayError("System error updating group:" + t.getMessage());
+                }
+            }
 
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               app.sessionExpired();
-                       }
-               };
-               updateGroup.setHeader("X-Auth-Token", app.getToken());
-               String groupMembers = "";
-               if (!group.getMembers().isEmpty()) {
-                       for (String u : group.getMembers())
-                               groupMembers += (URL.encodePathSegment(u) + ",");
-               }
-               else
-                       groupMembers = "~";
-               updateGroup.setHeader("X-Account-Group-" + URL.encodePathSegment(group.getName()), groupMembers);
-               Scheduler.get().scheduleDeferred(updateGroup);
-       }
+            @Override
+            protected void onUnauthorized(Response response) {
+                app.sessionExpired();
+            }
+        };
+        updateGroup.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
+        final String groupMembers;
+        if(!group.getUsers().isEmpty()) {
+            groupMembers = group.encodeUserIDsForXAccountGroup();
+        }
+        else {
+            groupMembers = "~";
+        }
+        updateGroup.setHeader(Const.X_ACCOUNT_GROUP_ + URL.encodePathSegment(group.getName()), groupMembers);
+        Scheduler.get().scheduleDeferred(updateGroup);
+    }
 }
index 564189a..ff8d56a 100644 (file)
@@ -37,12 +37,11 @@ package gr.grnet.pithos.web.client.commands;
 import java.util.Iterator;
 import java.util.List;
 
+import gr.grnet.pithos.web.client.Const;
 import gr.grnet.pithos.web.client.Pithos;
 import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.foldertree.Folder;
-import gr.grnet.pithos.web.client.foldertree.Resource;
-import gr.grnet.pithos.web.client.rest.DeleteRequest;
-import gr.grnet.pithos.web.client.rest.GetRequest;
+import gr.grnet.pithos.web.client.Resource;
 import gr.grnet.pithos.web.client.rest.PutRequest;
 import gr.grnet.pithos.web.client.rest.RestException;
 
@@ -110,15 +109,15 @@ public class RestoreTrashCommand implements Command {
        }
 
     private void untrashFolder(final Folder f, final Command callback) {
-        String path = "/" + Pithos.HOME_CONTAINER + "/" + f.getPrefix();
-        app.copyFolder(f, app.getUsername(), path, true, callback);
+        String path = "/" + Const.HOME_CONTAINER + "/" + f.getPrefix();
+        app.copyFolder(f, app.getUserID(), path, true, callback);
     }
 
     protected void untrashFiles(final Iterator<File> iter, final Command callback) {
         if (iter.hasNext()) {
             File file = iter.next();
-            String path = "/" + Pithos.HOME_CONTAINER + "/" + file.getPath();
-            PutRequest untrashFile = new PutRequest(app.getApiPath(), app.getUsername(), path) {
+            String path = "/" + Const.HOME_CONTAINER + "/" + file.getPath();
+            PutRequest untrashFile = new PutRequest(app, app.getApiPath(), app.getUserID(), path) {
                 @Override
                 public void onSuccess(Resource result) {
                     untrashFiles(iter, callback);
@@ -140,7 +139,7 @@ public class RestoreTrashCommand implements Command {
                                        app.sessionExpired();
                                }
             };
-            untrashFile.setHeader("X-Auth-Token", app.getToken());
+            untrashFile.setHeader("X-Auth-Token", app.getUserToken());
             untrashFile.setHeader("X-Move-From", URL.encodePathSegment(file.getUri()));
             untrashFile.setHeader("Content-Type", file.getContentType());
             
index cf5371c..b5ece80 100644 (file)
  */
 package gr.grnet.pithos.web.client.commands;
 
+import gr.grnet.pithos.web.client.Const;
 import gr.grnet.pithos.web.client.Pithos;
 import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.foldertree.Folder;
-import gr.grnet.pithos.web.client.foldertree.Resource;
-import gr.grnet.pithos.web.client.rest.DeleteRequest;
-import gr.grnet.pithos.web.client.rest.GetRequest;
+import gr.grnet.pithos.web.client.Resource;
 import gr.grnet.pithos.web.client.rest.PutRequest;
 import gr.grnet.pithos.web.client.rest.RestException;
 
@@ -120,15 +119,15 @@ public class ToTrashCommand implements Command{
        }
 
     private void trashFolder(final Folder f, final Command callback) {
-       String path = "/" + Pithos.TRASH_CONTAINER + "/" + f.getPrefix();
-       app.copyFolder(f, app.getUsername(), path, true, callback);
+       String path = "/" + Const.TRASH_CONTAINER + "/" + f.getPrefix();
+       app.copyFolder(f, app.getUserID(), path, true, callback);
     }
   
     protected void trashFiles(final Iterator<File> iter, final Command callback) {
         if (iter.hasNext()) {
             File file = iter.next();
-            String path = "/" + Pithos.TRASH_CONTAINER + "/" + file.getPath();
-            PutRequest trashFile = new PutRequest(app.getApiPath(), app.getUsername(), path) {
+            String path = "/" + Const.TRASH_CONTAINER + "/" + file.getPath();
+            PutRequest trashFile = new PutRequest(app, app.getApiPath(), app.getUserID(), path) {
                 @Override
                 public void onSuccess(Resource result) {
                     trashFiles(iter, callback);
@@ -150,7 +149,7 @@ public class ToTrashCommand implements Command{
                                        app.sessionExpired();
                                }
             };
-            trashFile.setHeader("X-Auth-Token", app.getToken());
+            trashFile.setHeader("X-Auth-Token", app.getUserToken());
             trashFile.setHeader("X-Move-From", URL.encodePathSegment(file.getUri()));
             trashFile.setHeader("Content-Type", file.getContentType());
             Scheduler.get().scheduleDeferred(trashFile);
index bc2db06..e4011a0 100644 (file)
 
 package gr.grnet.pithos.web.client.foldertree;
 
-import gr.grnet.pithos.web.client.Pithos;
-import gr.grnet.pithos.web.client.grouptree.Group;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
 import com.google.gwt.http.client.Header;
 import com.google.gwt.http.client.Response;
 import com.google.gwt.http.client.URL;
@@ -52,12 +45,22 @@ import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONParser;
 import com.google.gwt.json.client.JSONValue;
+import gr.grnet.pithos.web.client.Const;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.Resource;
+import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
+import gr.grnet.pithos.web.client.catalog.UserCatalogs;
+import gr.grnet.pithos.web.client.grouptree.Group;
+import gr.grnet.pithos.web.client.grouptree.User;
+
+import java.util.*;
 
 /**
  * Created by IntelliJ IDEA. User: chstath Date: 5/19/11 Time: 2:55 PM To change this template use File | Settings |
  * File Templates.
  */
 public class AccountResource extends Resource {
+    private final Pithos app;
 
     private long numberOfContainers = 0;
 
@@ -70,13 +73,17 @@ public class AccountResource extends Resource {
     private Date lastLogin = null;
 
     private Date lastModified = null;
-    
+
     private List<Folder> containers = new ArrayList<Folder>();
 
     private Date currentLogin = null;
 
     private List<Group> groups = new ArrayList<Group>();
 
+    public AccountResource(Pithos app) {
+        this.app = app;
+    }
+
     public long getQuota() {
         return quota;
     }
@@ -102,7 +109,7 @@ public class AccountResource extends Resource {
     }
 
     @Override
-       public Date getLastModified() {
+    public Date getLastModified() {
         return lastModified;
     }
 
@@ -138,145 +145,208 @@ public class AccountResource extends Resource {
         this.currentLogin = currentLogin;
     }
 
+    private void doAddUsersByIDs(final List<String> userIDs, final String groupName) {
+        app.LOG("AccountResource::doAddUsersByIDs(), group = ", groupName);
+        final Group group = new Group(groupName);
+        for(String userID : userIDs) {
+            final String userDisplayName = app.getUserDisplayNameForID(userID);
+            final User user = new User(userID, userDisplayName, groupName);
+            group.addUser(user);
+            app.LOG("AccountResource::doAddUsersByIDs(),   user = (", userID, ", ", userDisplayName, ")");
+
+        }
+        groups.add(group);
+
+    }
+
     public void populate(String owner, Response response) {
         DateTimeFormat df = DateTimeFormat.getFormat(PredefinedFormat.RFC_2822);
         groups.clear();
-        for (Header h : response.getHeaders()) {
-               if (h != null) {
-                       String name = h.getName();
-                       if (name.startsWith("X-Account-Group-")) {
-                           String groupName = URL.decodePathSegment(name.substring("X-Account-Group-".length()));
-                           Group g = new Group(groupName);
-                           String[] members = h.getValue().split(",");
-                           for (String s : members)
-                               g.addMember(URL.decodePathSegment(s).trim());
-                           groups.add(g);
-                       }
-                       else if (name.equals("X-Account-Container-Count")) {
-                           numberOfContainers = Long.valueOf(h.getValue());
-                       }
-                       else if (name.equals("X-Account-Object-Count")) {
-                           numberOfObjects = Long.valueOf(h.getValue());
-                       }
-                       else if (name.equals("X-Account-Bytes-Used")) {
-                           bytesUsed = Long.valueOf(h.getValue());
-                       }
-                       else if (name.equals("X-Account-Policy-Quota")) {
-                           quota = Long.valueOf(h.getValue());
-                       }
-                       else if (name.equals("X-Account-Last-Login")) {
-                           lastLogin = df.parse(h.getValue());
-                       }
-                       else if (name.equals("Last-Modified")) {
-                           lastModified = df.parse(h.getValue());
-                       }
-               }
+
+        final Map<String, List<String>> parsedGroups = new HashMap<String, List<String>>();
+
+        for(Header h : response.getHeaders()) {
+            if(h != null) {
+                String name = h.getName();
+                if(name.startsWith(Const.X_ACCOUNT_GROUP_)) {
+                    final String groupName = URL.decodePathSegment(name.substring(Const.X_ACCOUNT_GROUP_.length()));
+                    final String[] users = h.getValue().split(",");
+                    final List<String> userIDs = new ArrayList<String>();
+                    for(String user : users) {
+                        final String userID = URL.decodePathSegment(user).trim();
+                        userIDs.add(userID);
+                    }
+                    parsedGroups.put(groupName, userIDs);
+                }
+                else if(name.equals(Const.X_ACCOUNT_CONTAINER_COUNT)) {
+                    numberOfContainers = Long.valueOf(h.getValue());
+                }
+                else if(name.equals(Const.X_ACCOUNT_OBJECT_COUNT)) {
+                    numberOfObjects = Long.valueOf(h.getValue());
+                }
+                else if(name.equals(Const.X_ACCOUNT_BYTES_USED)) {
+                    bytesUsed = Long.valueOf(h.getValue());
+                }
+                else if(name.equals(Const.X_ACCOUNT_POLICY_QUOTA)) {
+                    quota = Long.valueOf(h.getValue());
+                }
+                else if(name.equals(Const.X_ACCOUNT_LAST_LOGIN)) {
+                    lastLogin = df.parse(h.getValue());
+                }
+                else if(name.equals(Const.LAST_MODIFIED)) {
+                    lastModified = df.parse(h.getValue());
+                }
+            }
+        }
+        
+        // Gather all unknown users for the groups
+        final List<String> userIDsWithUnknownDisplayName = new ArrayList<String>();
+        for(Map.Entry<String, List<String>> parsedGroupEntry : parsedGroups.entrySet()) {
+            final List<String> groupUserIDs = parsedGroupEntry.getValue();
+            userIDsWithUnknownDisplayName.addAll(app.filterUserIDsWithUnknownDisplayName(groupUserIDs));
+        }
+        if(userIDsWithUnknownDisplayName.size() == 0) {
+            for(Map.Entry<String, List<String>> parsedGroupEntry : parsedGroups.entrySet()) {
+                final String groupName = parsedGroupEntry.getKey();
+                final List<String> groupUserIDs = parsedGroupEntry.getValue();
+                doAddUsersByIDs(groupUserIDs, groupName);
+            }
+        }
+        else {
+            new UpdateUserCatalogs(app, userIDsWithUnknownDisplayName) {
+                @Override
+                public void onSuccess(UserCatalogs requestedUserCatalogs, UserCatalogs updatedUserCatalogs) {
+                    for(Map.Entry<String, List<String>> parsedGroupEntry : parsedGroups.entrySet()) {
+                        final String groupName = parsedGroupEntry.getKey();
+                        final List<String> groupUserIDs = parsedGroupEntry.getValue();
+                        doAddUsersByIDs(groupUserIDs, groupName);
+                    }
+                }
+            }.scheduleEntry();
         }
 
-        if (response.getText() != null && response.getText().length() > 0) {
-               containers.clear();
-               JSONValue json = JSONParser.parseStrict(response.getText());
-               JSONArray array = json.isArray();
-               if (array != null) {
-                   for (int i=0; i<array.size(); i++) {
-                       JSONObject o = array.get(i).isObject();
-                       if (o != null) {
-                           Folder f = new Folder();
-                           f.populate(null, o, owner, null);
-                           containers.add(f);
-                       }
-                   }
-               }
+        if(response.getText() != null && response.getText().length() > 0) {
+            containers.clear();
+            JSONValue json = JSONParser.parseStrict(response.getText());
+            JSONArray array = json.isArray();
+            if(array != null) {
+                for(int i = 0; i < array.size(); i++) {
+                    JSONObject o = array.get(i).isObject();
+                    if(o != null) {
+                        Folder f = new Folder();
+                        f.populate(null, o, owner, null);
+                        containers.add(f);
+                    }
+                }
+            }
         }
     }
 
-    public static AccountResource createFromResponse(String owner, Response response, AccountResource result) {
-       AccountResource a;
-       if (result == null)
-               a = new AccountResource();
-       else
-               a = result;
+    public static AccountResource createFromResponse(Pithos app, String owner, Response response, AccountResource result) {
+        AccountResource a;
+        if(result == null) {
+            a = new AccountResource(app);
+        }
+        else {
+            a = result;
+        }
         a.populate(owner, response);
         return a;
     }
 
-    private String getSize(Long size, Double division){
-        Double res = Double.valueOf(size.toString())/division;
-        NumberFormat nf = NumberFormat.getFormat("######.#");
+    private String getSize(Long size, Double division) {
+        Double res = Double.valueOf(size.toString()) / division;
+        NumberFormat nf = NumberFormat.getFormat(Const.NUMBER_FORMAT_1);
         return nf.format(res);
     }
 
     public String getFileSizeAsString() {
-        if (bytesUsed < 1024)
+        if(bytesUsed < 1024) {
             return String.valueOf(bytesUsed) + "B";
-        else if (bytesUsed < 1024*1024)
+        }
+        else if(bytesUsed < 1024 * 1024) {
             return getSize(bytesUsed, 1024D) + "KB";
-        else if (bytesUsed < 1024*1024*1024)
-            return getSize(bytesUsed,(1024D*1024D)) + "MB";
-        return getSize(bytesUsed , (1024D*1024D*1024D)) + "GB";
+        }
+        else if(bytesUsed < 1024 * 1024 * 1024) {
+            return getSize(bytesUsed, (1024D * 1024D)) + "MB";
+        }
+        return getSize(bytesUsed, (1024D * 1024D * 1024D)) + "GB";
     }
 
     public String getQuotaAsString() {
-        if (quota < 1024)
+        if(quota < 1024) {
             return String.valueOf(quota) + "B";
-        else if (quota < 1024 * 1024)
+        }
+        else if(quota < 1024 * 1024) {
             return getSize(quota, 1024D) + "KB";
-        else if (quota < 1024 * 1024 * 1024)
-            return getSize(quota,(1024D * 1024D)) + "MB";
-        return getSize(quota , (1024D * 1024D * 1024D)) + "GB";
+        }
+        else if(quota < 1024 * 1024 * 1024) {
+            return getSize(quota, (1024D * 1024D)) + "MB";
+        }
+        return getSize(quota, (1024D * 1024D * 1024D)) + "GB";
     }
 
     public List<Group> getGroups() {
         return groups;
     }
-    
+
     public boolean hasHomeContainer() {
-       for (Folder f : containers)
-               if (f.getName().equals(Pithos.HOME_CONTAINER))
-                       return true;
-       return false;
+        for(Folder f : containers) {
+            if(f.getName().equals(Const.HOME_CONTAINER)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     public boolean hasTrashContainer() {
-       for (Folder f : containers)
-               if (f.getName().equals(Pithos.TRASH_CONTAINER))
-                       return true;
-       return false;
+        for(Folder f : containers) {
+            if(f.getName().equals(Const.TRASH_CONTAINER)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void addGroup(Group group) {
+        groups.add(group);
+    }
+
+    public void removeGroup(Group group) {
+        groups.remove(group);
     }
 
-       public void addGroup(Group newGroup) {
-               groups.add(newGroup);
-       }
-
-       public void removeGroup(Group group) {
-               groups.remove(group);
-       }
-
-       public Folder getTrash() {
-               for (Folder c : containers) {
-                       if (c.getName().equals(Pithos.TRASH_CONTAINER))
-                               return c;
-               }
-               return null;
-       }
-
-       public double getUsedPercentage() {
-               if (quota == 0)
-                       return 0;
-               return ((double) bytesUsed) / quota;
-       }
-
-       public Folder getPithos() {
-               for (Folder f : containers)
-                       if (f.getName().equals(Pithos.HOME_CONTAINER))
-                               return f;
-               return null;
-       }
-
-       public Group getGroup(String groupName) {
-               for (Group g : groups)
-                       if (g.getName().equalsIgnoreCase(groupName))
-                               return g;
-               return null;
-       }
+    public Folder getTrash() {
+        for(Folder c : containers) {
+            if(c.getName().equals(Const.TRASH_CONTAINER)) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    public double getUsedPercentage() {
+        if(quota == 0) {
+            return 0;
+        }
+        return ((double) bytesUsed) / quota;
+    }
+
+    public Folder getPithos() {
+        for(Folder f : containers) {
+            if(f.getName().equals(Const.HOME_CONTAINER)) {
+                return f;
+            }
+        }
+        return null;
+    }
+
+    public Group getGroup(String groupName) {
+        for(Group g : groups) {
+            if(g.getName().equalsIgnoreCase(groupName)) {
+                return g;
+            }
+        }
+        return null;
+    }
 }
index c5b667f..a8a02da 100644 (file)
@@ -47,6 +47,7 @@ import com.google.gwt.i18n.client.NumberFormat;
 import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONValue;
+import gr.grnet.pithos.web.client.Resource;
 
 public class File extends Resource {
     private String name;
@@ -65,7 +66,7 @@ public class File extends Resource {
 
     private String path;
 
-    private String owner;
+    private String ownerID;
 
     private String container;
 
@@ -110,8 +111,8 @@ public class File extends Resource {
         return "/" + container + "/" + path;
     }
 
-    public String getOwner() {
-        return owner;
+    public String getOwnerID() {
+        return ownerID;
     }
 
     public String getPath() {
@@ -148,7 +149,7 @@ public class File extends Resource {
                name = path.substring(parent.getPrefix().length() + 1);
         else
             name = path;
-        this.owner = _owner;
+        this.ownerID = _owner;
         hash = unmarshallString(o, "hash");
         bytes = unmarshallLong(o, "bytes");
         version = unmarshallInt(o, "x_object_version");
@@ -222,7 +223,7 @@ public class File extends Resource {
     }
 
     private void populate(String _owner, Response response) {
-        this.owner = _owner;
+        this.ownerID = _owner;
         published = false;
         publicUri = null;
         permissions.clear();
index a7b5ac2..40a6c98 100644 (file)
@@ -44,6 +44,7 @@ import com.google.gwt.json.client.JSONNumber;
 import com.google.gwt.json.client.JSONParser;
 import com.google.gwt.json.client.JSONString;
 import com.google.gwt.json.client.JSONValue;
+import gr.grnet.pithos.web.client.Resource;
 
 public class FileVersions extends Resource {
        private List<Version> versions;
index 5ce0b72..f2c5a6f 100644 (file)
@@ -35,7 +35,7 @@
 
 package gr.grnet.pithos.web.client.foldertree;
 
-import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.Const;
 
 import java.util.Date;
 import java.util.HashMap;
@@ -52,6 +52,7 @@ import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONParser;
 import com.google.gwt.json.client.JSONValue;
+import gr.grnet.pithos.web.client.Resource;
 
 public class Folder extends Resource {
     /*
@@ -80,7 +81,7 @@ public class Folder extends Resource {
 
     private Set<File> files = new LinkedHashSet<File>();
 
-    private String owner;
+    private String ownerID;
 
     private Map<String, Boolean[]> permissions = new HashMap<String, Boolean[]>();
 
@@ -145,7 +146,7 @@ public class Folder extends Resource {
     }
 
     public void populate(String _owner, Response response) {
-        this.owner = _owner;
+        this.ownerID = _owner;
         String header = response.getHeader("Last-Modified");
         if (header != null)
                        try {
@@ -223,7 +224,7 @@ public class Folder extends Resource {
             container = name;
             prefix = "";
         }
-        this.owner = _owner;
+        this.ownerID = _owner;
 
         inheritedPermissionsFrom = unmarshallString(o, "x_object_shared_by");
         String rawPermissions = unmarshallString(o, "x_object_sharing");
@@ -246,7 +247,7 @@ public class Folder extends Resource {
     public boolean equals(Object other) {
         if (other instanceof Folder) {
             Folder o = (Folder) other;
-            return (owner == null ? true : owner.equals(o.getOwner())) 
+            return (ownerID == null ? true : ownerID.equals(o.getOwnerID()))
                        && (getUri().equals(o.getUri()));
         }
         return false;
@@ -285,8 +286,8 @@ public class Folder extends Resource {
         return permissions;
     }
 
-    public String getOwner() {
-        return owner;
+    public String getOwnerID() {
+        return ownerID;
     }
 
        public boolean isShared() {
@@ -299,7 +300,7 @@ public class Folder extends Resource {
         * @return
         */
        public boolean isTrash() {
-               return isContainer() && name.equals(Pithos.TRASH_CONTAINER);
+               return isContainer() && name.equals(Const.TRASH_CONTAINER);
        }
        
        /**
@@ -308,11 +309,11 @@ public class Folder extends Resource {
         * @return
         */
        public boolean isInTrash() {
-               return container.equals(Pithos.TRASH_CONTAINER);
+               return container.equals(Const.TRASH_CONTAINER);
        }
 
        public boolean isHome() {
-               return isContainer() && name.equals(Pithos.HOME_CONTAINER);
+               return isContainer() && name.equals(Const.HOME_CONTAINER);
        }
 
        public boolean contains(Folder folder) {
index 48b1227..fb4d31f 100644 (file)
@@ -152,7 +152,7 @@ public class FolderTreeViewModel implements TreeViewModel {
             final Folder f = iter.next();
 
             String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
-            GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwner(), path, f) {
+            GetRequest<Folder> getFolder = new GetRequest<Folder>(app, Folder.class, app.getApiPath(), f.getOwnerID(), path, f) {
                 @Override
                 public void onSuccess(Folder _result) {
                     fetchFolder(iter, callback);
@@ -182,7 +182,7 @@ public class FolderTreeViewModel implements TreeViewModel {
                                Scheduler.get().scheduleDeferred(this);
                                }
             };
-            getFolder.setHeader("X-Auth-Token", app.getToken());
+            getFolder.setHeader("X-Auth-Token", app.getUserToken());
             Scheduler.get().scheduleDeferred(getFolder);
         }
         else if (callback != null)
@@ -236,7 +236,7 @@ public class FolderTreeViewModel implements TreeViewModel {
 
     public void fetchFolder(final Folder f, final ListDataProvider<Folder> dataProvider, final boolean showfiles, final Command callback) {
         String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
-        GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwner(), path, f) {
+        GetRequest<Folder> getFolder = new GetRequest<Folder>(app, Folder.class, app.getApiPath(), f.getOwnerID(), path, f) {
             @Override
             public void onSuccess(final Folder _result) {
                 if (showfiles)
@@ -281,7 +281,7 @@ public class FolderTreeViewModel implements TreeViewModel {
                        Scheduler.get().scheduleDeferred(this);
                        }
         };
-        getFolder.setHeader("X-Auth-Token", app.getToken());
+        getFolder.setHeader("X-Auth-Token", app.getUserToken());
         Scheduler.get().scheduleDeferred(getFolder);
     }
 }
index d367048..aef15f5 100644 (file)
 package gr.grnet.pithos.web.client.grouptree;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
-public class Group {
-    private String name;
+public final class Group {
+    private final String name;
 
-    private List<String> members = new ArrayList<String>();
+    private final List<User> users = new ArrayList<User>();
 
-    public Group(String _name) {
-        name = _name;
+    public Group(String name) {
+        this.name = name;
     }
 
-    public List<String> getMembers() {
-        return members;
+    public List<User> getUsers() {
+        return Collections.unmodifiableList(users);
     }
 
     public String getName() {
         return name;
     }
 
-    public void addMember(String user) {
-        members.add(user);
+    public void addUser(User user) {
+        this.users.add(user);
     }
 
-       public void removeMember(String username) {
-               members.remove(username);
+       public void removeUser(User user) {
+               this.users.remove(user);
        }
+
+    public String encodeUserIDsForXAccountGroup() {
+        final StringBuilder sb = new StringBuilder();
+        for(int i=0; i<users.size(); i++) {
+            final User user = users.get(i);
+            sb.append(user.getUserID());
+            if(i < users.size() - 1) {
+                sb.append(",");
+            }
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        return "Group(" + name + ", " + users.size()+ " users)";
+    }
+
 }
index 6a7ab66..56634e9 100644 (file)
@@ -64,7 +64,6 @@ public class GroupContextMenu extends PopupPanel {
                // The popup's constructor's argument is a boolean specifying that it
                // auto-close itself when the user clicks outside of it.
                super(true);
-               setAnimationEnabled(true);
                images = newImages;
         MenuBar contextMenu = new MenuBar(true);
         
index ea3f05c..379c21f 100644 (file)
 
 package gr.grnet.pithos.web.client.grouptree;
 
-import gr.grnet.pithos.web.client.Pithos;
-import gr.grnet.pithos.web.client.commands.CreateGroupCommand;
-import gr.grnet.pithos.web.client.foldertree.File;
-import gr.grnet.pithos.web.client.grouptree.GroupTreeView.Templates;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-
 import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.cell.client.Cell;
 import com.google.gwt.event.dom.client.ContextMenuEvent;
@@ -53,46 +44,57 @@ import com.google.gwt.view.client.ListDataProvider;
 import com.google.gwt.view.client.SelectionChangeEvent;
 import com.google.gwt.view.client.SingleSelectionModel;
 import com.google.gwt.view.client.TreeViewModel;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.commands.CreateGroupCommand;
+import gr.grnet.pithos.web.client.foldertree.File;
+import gr.grnet.pithos.web.client.grouptree.GroupTreeView.Templates;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 
 public class GroupTreeViewModel implements TreeViewModel {
+    final Group CreateGroupPlaceholder = new Group("Create new group...");
 
     protected Pithos app;
 
-       private Cell<Group> groupCell = new AbstractCell<Group>(ContextMenuEvent.getType().getName()) {
+    private Cell<Group> groupCell = new AbstractCell<Group>(ContextMenuEvent.getType().getName()) {
 
-               @Override
-               public void render(Context context,     Group value, SafeHtmlBuilder sb) {
+        @Override
+        public void render(Context context, Group group, SafeHtmlBuilder sb) {
             String html = AbstractImagePrototype.create(GroupTreeView.images.group()).getHTML();
             sb.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
-            sb.append(Templates.INSTANCE.nameSpan(value.getName()));
-               }
-               
+            sb.append(Templates.INSTANCE.nameSpan(group.getName()));
+        }
+
         @Override
         public void onBrowserEvent(Cell.Context context, com.google.gwt.dom.client.Element parent, Group group, com.google.gwt.dom.client.NativeEvent event, com.google.gwt.cell.client.ValueUpdater<Group> valueUpdater) {
-               if (!group.equals(createGroup)) {
-                   GroupTreeViewModel.this.groupSelectionModel.setSelected(group, true);
-                   if (event.getType().equals(ContextMenuEvent.getType().getName())) {
-                       GroupContextMenu menu = new GroupContextMenu(app, GroupTreeView.images, group);
-                       menu.setPopupPosition(event.getClientX(), event.getClientY());
-                       menu.show();
-                   }
-               }
+            if(!group.equals(CreateGroupPlaceholder)) {
+                GroupTreeViewModel.this.groupSelectionModel.setSelected(group, true);
+                if(event.getType().equals(ContextMenuEvent.getType().getName())) {
+                    GroupContextMenu menu = new GroupContextMenu(app, GroupTreeView.images, group);
+                    menu.setPopupPosition(event.getClientX(), event.getClientY());
+                    menu.show();
+                }
+            }
         }
-       };
+    };
 
     private Cell<User> userCell = new AbstractCell<User>(ContextMenuEvent.getType().getName()) {
 
-               @Override
-               public void render(Context context,     User value, SafeHtmlBuilder sb) {
+        @Override
+        public void render(Context context, User user, final SafeHtmlBuilder sb) {
             String html = AbstractImagePrototype.create(GroupTreeView.images.user()).getHTML();
             sb.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
-            sb.append(Templates.INSTANCE.nameSpan(value.getName()));
-               }
+            final String userDisplayName = user.getUserDisplayName();
+            sb.append(Templates.INSTANCE.nameSpan(userDisplayName));
+        }
 
         @Override
         public void onBrowserEvent(Cell.Context context, com.google.gwt.dom.client.Element parent, User user, com.google.gwt.dom.client.NativeEvent event, com.google.gwt.cell.client.ValueUpdater<User> valueUpdater) {
             GroupTreeViewModel.this.userSelectionModel.setSelected(user, true);
-            if (event.getType().equals(ContextMenuEvent.getType().getName())) {
+            if(event.getType().equals(ContextMenuEvent.getType().getName())) {
                 UserContextMenu menu = new UserContextMenu(app, GroupTreeView.images, user);
                 menu.setPopupPosition(event.getClientX(), event.getClientY());
                 menu.show();
@@ -103,114 +105,127 @@ public class GroupTreeViewModel implements TreeViewModel {
     protected ListDataProvider<Group> groupsDataProvider = new ListDataProvider<Group>();
 
     protected Map<Group, ListDataProvider<User>> userDataProviderMap = new HashMap<Group, ListDataProvider<User>>();
-    
+
     SingleSelectionModel<Group> groupSelectionModel;
     SingleSelectionModel<User> userSelectionModel;
-    
-    final Group createGroup = new Group("Create new group...");
 
     public GroupTreeViewModel(Pithos _app) {
         app = _app;
 
-       groupSelectionModel = new SingleSelectionModel<Group>();
-       app.addSelectionModel(groupSelectionModel);
-       groupSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
-                       
-                       @Override
-                       public void onSelectionChange(SelectionChangeEvent event) {
-                               Group selected = groupSelectionModel.getSelectedObject();
-                               if (selected != null) {
-                                       app.deselectOthers(app.getGroupTreeView(), groupSelectionModel);
-                                       app.showFiles(new HashSet<File>());
-                                       app.disableUploadArea();
-                                       app.upload.setEnabled(false);
-                                       app.showRelevantToolbarButtons();
-                                       if (selected.equals(createGroup)) {
-                                               new CreateGroupCommand(app, null).execute();
-                                               groupSelectionModel.setSelected(createGroup, false);
-                                       }
-                               }
-                               else {
-                                       if (app.getSelectedTree().equals(app.getGroupTreeView()))
-                                               app.setSelectedTree(null);
-                                       if (app.getSelectedTree() == null)
-                                               app.showRelevantToolbarButtons();
-                               }
-                       }
-               });
-
-       userSelectionModel = new SingleSelectionModel<User>();
-       app.addSelectionModel(userSelectionModel);
-       userSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
-                       
-                       @Override
-                       public void onSelectionChange(SelectionChangeEvent event) {
-                               if (userSelectionModel.getSelectedObject() != null) {
-                                       app.deselectOthers(app.getGroupTreeView(), userSelectionModel);
-                                       app.showFiles(new HashSet<File>());
-                                       app.showRelevantToolbarButtons();
-                               }
-                               else {
-                                       if (app.getSelectedTree().equals(app.getGroupTreeView()))
-                                               app.setSelectedTree(null);
-                                       if (app.getSelectedTree() == null)
-                                               app.showRelevantToolbarButtons();
-                               }
-                       }
-               });
-}
+        groupSelectionModel = new SingleSelectionModel<Group>();
+        app.addSelectionModel(groupSelectionModel);
+        groupSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
+
+            @Override
+            public void onSelectionChange(SelectionChangeEvent event) {
+                Group selected = groupSelectionModel.getSelectedObject();
+                if(selected != null) {
+                    app.deselectOthers(app.getGroupTreeView(), groupSelectionModel);
+                    app.showFiles(new HashSet<File>());
+                    app.disableUploadArea();
+                    app.upload.setEnabled(false);
+                    app.showRelevantToolbarButtons();
+                    if(selected.equals(CreateGroupPlaceholder)) {
+                        new CreateGroupCommand(app, null).execute();
+                        groupSelectionModel.setSelected(CreateGroupPlaceholder, false);
+                    }
+                }
+                else {
+                    if(app.getSelectedTree().equals(app.getGroupTreeView())) {
+                        app.setSelectedTree(null);
+                    }
+                    if(app.getSelectedTree() == null) {
+                        app.showRelevantToolbarButtons();
+                    }
+                }
+            }
+        });
+
+        userSelectionModel = new SingleSelectionModel<User>();
+        app.addSelectionModel(userSelectionModel);
+        userSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
+
+            @Override
+            public void onSelectionChange(SelectionChangeEvent event) {
+                if(userSelectionModel.getSelectedObject() != null) {
+                    app.deselectOthers(app.getGroupTreeView(), userSelectionModel);
+                    app.showFiles(new HashSet<File>());
+                    app.showRelevantToolbarButtons();
+                }
+                else {
+                    if(app.getSelectedTree().equals(app.getGroupTreeView())) {
+                        app.setSelectedTree(null);
+                    }
+                    if(app.getSelectedTree() == null) {
+                        app.showRelevantToolbarButtons();
+                    }
+                }
+            }
+        });
+    }
 
     @Override
     public <T> NodeInfo<?> getNodeInfo(T value) {
-        if (value == null) {
-               groupsDataProvider.getList().clear();
-                       groupsDataProvider.getList().addAll(app.getAccount().getGroups());
-                       groupsDataProvider.getList().add(createGroup);
+        app.LOG("GroupTreeViewModel::getNodeInfo(), value = ", value);
+        if(value == null) {
+            groupsDataProvider.getList().clear();
+            groupsDataProvider.getList().addAll(app.getAccount().getGroups());
+            groupsDataProvider.getList().add(CreateGroupPlaceholder);
             return new DefaultNodeInfo<Group>(groupsDataProvider, groupCell, groupSelectionModel, null);
         }
-       Group g = (Group) value;
-               if (userDataProviderMap.get(g) == null) {
-                       userDataProviderMap.put(g, new ListDataProvider<User>());
-               }
-               final ListDataProvider<User> dataProvider = userDataProviderMap.get(g);
-               dataProvider.getList().clear();
-               for (String u : g.getMembers())
-                       dataProvider.getList().add(new User(u, g.getName()));
-       return new DefaultNodeInfo<User>(dataProvider, userCell, userSelectionModel, null);
+        final Group group = (Group) value;
+        if(userDataProviderMap.get(group) == null) {
+            userDataProviderMap.put(group, new ListDataProvider<User>());
+        }
+        final ListDataProvider<User> dataProvider = userDataProviderMap.get(group);
+        dataProvider.getList().clear();
+        final List<User> users = group.getUsers();
+        for(User user : users) {
+            app.LOG("GroupTreeViewModel::getNodeInfo(), Add ", user);
+            dataProvider.getList().add(user);
+        }
+
+
+        return new DefaultNodeInfo<User>(dataProvider, userCell, userSelectionModel, null);
     }
 
-       @Override
+    @Override
     public boolean isLeaf(Object o) {
-        if (o instanceof User) {
-                       return true;
+        if(o instanceof User) {
+            return true;
+        }
+        else if(o instanceof Group) {
+            return ((Group) o).getUsers().isEmpty();
         }
-        else if (o instanceof Group)
-               return ((Group) o).getMembers().isEmpty();
         return false;
     }
-       
-       public void updateGroupNode(Group group) {
-               if (group == null) {
-                       groupsDataProvider.getList().clear();
-                       groupsDataProvider.getList().addAll(app.getAccount().getGroups());
-                       groupsDataProvider.getList().add(createGroup);
-               }
-               else {
-                       if (userDataProviderMap.get(group) == null) {
-                               userDataProviderMap.put(group, new ListDataProvider<User>());
-                       }
-                       final ListDataProvider<User> dataProvider = userDataProviderMap.get(group);
-                       dataProvider.getList().clear();
-                       for (String u : group.getMembers())
-                               dataProvider.getList().add(new User(u, group.getName()));
-               }
-       }
-
-       public Object getSelectedObject() {
-               if (groupSelectionModel.getSelectedObject() != null)
-                       return groupSelectionModel.getSelectedObject();
-               if (userSelectionModel.getSelectedObject() != null)
-                       return userSelectionModel.getSelectedObject();
-               return null;
-       }
+
+    public void updateGroupNode(Group group) {
+        if(group == null) {
+            groupsDataProvider.getList().clear();
+            groupsDataProvider.getList().addAll(app.getAccount().getGroups());
+            groupsDataProvider.getList().add(CreateGroupPlaceholder);
+        }
+        else {
+            if(userDataProviderMap.get(group) == null) {
+                userDataProviderMap.put(group, new ListDataProvider<User>());
+            }
+            final ListDataProvider<User> dataProvider = userDataProviderMap.get(group);
+            dataProvider.getList().clear();
+            for(User user : group.getUsers()) {
+                app.LOG("GroupTreeViewModel::updateGroupNode(), group = ", group, ". Add ", user);
+                dataProvider.getList().add(user);
+            }
+        }
+    }
+
+    public Object getSelectedObject() {
+        if(groupSelectionModel.getSelectedObject() != null) {
+            return groupSelectionModel.getSelectedObject();
+        }
+        if(userSelectionModel.getSelectedObject() != null) {
+            return userSelectionModel.getSelectedObject();
+        }
+        return null;
+    }
 }
index 067fbd2..f6798ae 100644 (file)
 package gr.grnet.pithos.web.client.grouptree;
 
 
-public class User {
-    private String name;
-    
-    private String group;
-
-    public User(String _name, String _group) {
-        name = _name;
-        group = _group;
+public final class User {
+    private final String userID;
+    private final String userDisplayName;
+    private final String group;
+
+    public User(String userID, String userDisplayName, String group) {
+        this.userID = userID;
+        this.userDisplayName = userDisplayName;
+        this.group = group;
+    }
+
+    public String getUserID() {
+        return userID;
     }
 
-    public String getName() {
-        return name;
+    public String getUserDisplayName() {
+        return userDisplayName;
     }
 
-       public String getGroup() {
+    public String getGroup() {
                return group;
        }
+
+    @Override
+    public boolean equals(Object o) {
+        if(this == o) {
+            return true;
+        }
+        if(o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        User user = (User) o;
+
+        if(group != null ? !group.equals(user.group) : user.group != null) {
+            return false;
+        }
+        if(userID != null ? !userID.equals(user.userID) : user.userID != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = userID != null ? userID.hashCode() : 0;
+        result = 31 * result + (group != null ? group.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "User(" + userID + ", " + userDisplayName + ", " + group + ")";
+    }
 }
index fa75f97..3c56dee 100644 (file)
@@ -62,7 +62,6 @@ public class UserContextMenu extends PopupPanel {
                // The popup's constructor's argument is a boolean specifying that it
                // auto-close itself when the user clicks outside of it.
                super(true);
-               setAnimationEnabled(true);
                images = newImages;
         MenuBar contextMenu = new MenuBar(true);
         
index b98cb95..cfa6dea 100644 (file)
@@ -40,39 +40,24 @@ import gr.grnet.pithos.web.client.Pithos;
 import gr.grnet.pithos.web.client.foldertree.AccountResource;
 import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.foldertree.Folder;
-import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
 import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeView.Templates;
-import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView;
-import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeViewModel;
 import gr.grnet.pithos.web.client.rest.GetRequest;
 import gr.grnet.pithos.web.client.rest.RestException;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.cell.client.Cell;
-import com.google.gwt.cell.client.TextCell;
 import com.google.gwt.cell.client.ValueUpdater;
-import com.google.gwt.cell.client.Cell.Context;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.event.dom.client.ContextMenuEvent;
 import com.google.gwt.http.client.Response;
 import com.google.gwt.http.client.URL;
-import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
-import com.google.gwt.text.shared.SafeHtmlRenderer;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.view.client.ListDataProvider;
-import com.google.gwt.view.client.SelectionChangeEvent;
-import com.google.gwt.view.client.SelectionChangeEvent.Handler;
 import com.google.gwt.view.client.SingleSelectionModel;
 import com.google.gwt.view.client.TreeViewModel;
 
@@ -134,7 +119,7 @@ public class MysharedTreeViewModel implements TreeViewModel {
 
        private void fetchSharedContainers(final Command callback) {
         String path = "?format=json&shared=&public=";
-        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, app.getApiPath(), app.getUsername(), path) {
+        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(app, AccountResource.class, app.getApiPath(), app.getUserID(), path) {
             @Override
             public void onSuccess(final AccountResource _result) {
                                firstLevelDataProvider.getList().clear();
@@ -165,7 +150,7 @@ public class MysharedTreeViewModel implements TreeViewModel {
                                app.sessionExpired();
                        }
         };
-        getAccount.setHeader("X-Auth-Token", app.getToken());
+        getAccount.setHeader("X-Auth-Token", app.getUserToken());
         Scheduler.get().scheduleDeferred(getAccount);
        }
 
@@ -185,7 +170,7 @@ public class MysharedTreeViewModel implements TreeViewModel {
             final Folder f = iter.next();
 
             String path = "/" + f.getContainer() + "?format=json&shared=&public=&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
-            GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwner(), path, f) {
+            GetRequest<Folder> getFolder = new GetRequest<Folder>(app, Folder.class, app.getApiPath(), f.getOwnerID(), path, f) {
                 @Override
                 public void onSuccess(Folder _result) {
                     fetchFolder(iter, callback);
@@ -206,7 +191,7 @@ public class MysharedTreeViewModel implements TreeViewModel {
                                        app.sessionExpired();
                                }
             };
-            getFolder.setHeader("X-Auth-Token", app.getToken());
+            getFolder.setHeader("X-Auth-Token", app.getUserToken());
             Scheduler.get().scheduleDeferred(getFolder);
         }
         else if (callback != null)
@@ -223,7 +208,7 @@ public class MysharedTreeViewModel implements TreeViewModel {
 
     public void fetchFolder(final Folder f, final boolean showfiles, final Command callback) {
         String path = "/" + f.getContainer() + "?format=json&shared=&public=" + URL.encodeQueryString(f.getPrefix());
-        GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwner(), path, f) {
+        GetRequest<Folder> getFolder = new GetRequest<Folder>(app, Folder.class, app.getApiPath(), f.getOwnerID(), path, f) {
             @Override
             public void onSuccess(final Folder _result) {
                for (File file : _result.getFiles()) {
@@ -254,7 +239,7 @@ public class MysharedTreeViewModel implements TreeViewModel {
                                app.sessionExpired();
                        }
         };
-        getFolder.setHeader("X-Auth-Token", app.getToken());
+        getFolder.setHeader("X-Auth-Token", app.getUserToken());
         Scheduler.get().scheduleDeferred(getFolder);
     }
 
index b2ba2aa..1c1a244 100644 (file)
 
 package gr.grnet.pithos.web.client.othersharedtree;
 
-import gr.grnet.pithos.web.client.FolderContextMenu;
-import gr.grnet.pithos.web.client.Pithos;
-import gr.grnet.pithos.web.client.SharingUsers;
-import gr.grnet.pithos.web.client.foldertree.AccountResource;
-import gr.grnet.pithos.web.client.foldertree.File;
-import gr.grnet.pithos.web.client.foldertree.Folder;
-import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeView;
-import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView.Templates;
-import gr.grnet.pithos.web.client.rest.GetRequest;
-import gr.grnet.pithos.web.client.rest.RestException;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
 import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.cell.client.Cell;
 import com.google.gwt.cell.client.TextCell;
@@ -59,58 +42,75 @@ import com.google.gwt.cell.client.ValueUpdater;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.event.dom.client.ContextMenuEvent;
+import com.google.gwt.http.client.Request;
 import com.google.gwt.http.client.Response;
 import com.google.gwt.http.client.URL;
+import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
 import com.google.gwt.text.shared.SafeHtmlRenderer;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.view.client.ListDataProvider;
-import com.google.gwt.view.client.SelectionChangeEvent;
-import com.google.gwt.view.client.SelectionChangeEvent.Handler;
 import com.google.gwt.view.client.SingleSelectionModel;
 import com.google.gwt.view.client.TreeViewModel;
+import gr.grnet.pithos.web.client.FolderContextMenu;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.SharingUsers;
+import gr.grnet.pithos.web.client.catalog.GetUserCatalogs;
+import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
+import gr.grnet.pithos.web.client.catalog.UserCatalogs;
+import gr.grnet.pithos.web.client.foldertree.AccountResource;
+import gr.grnet.pithos.web.client.foldertree.Folder;
+import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView.Templates;
+import gr.grnet.pithos.web.client.rest.GetRequest;
+import gr.grnet.pithos.web.client.rest.RestException;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 public class OtherSharedTreeViewModel implements TreeViewModel {
 
     protected Pithos app;
 
-    String dummy = "No shares by others yet";
+    final String dummy = "No shares by others yet";
 
     private Cell<Folder> folderCell = new AbstractCell<Folder>(ContextMenuEvent.getType().getName()) {
 
-       @Override
+        @Override
         public void render(Context context, Folder folder, SafeHtmlBuilder safeHtmlBuilder) {
             String html = AbstractImagePrototype.create(OtherSharedTreeView.images.folderYellow()).getHTML();
-               safeHtmlBuilder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
+            safeHtmlBuilder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
             safeHtmlBuilder.append(Templates.INSTANCE.nameSpan(folder.getName()));
         }
 
         @Override
         public void onBrowserEvent(Context context, com.google.gwt.dom.client.Element parent, final Folder folder, com.google.gwt.dom.client.NativeEvent event, ValueUpdater<Folder> valueUpdater) {
-            if (event.getType().equals(ContextMenuEvent.getType().getName())) {
-               final int x = event.getClientX();
-               final int y = event.getClientY();
+            if(event.getType().equals(ContextMenuEvent.getType().getName())) {
+                final int x = event.getClientX();
+                final int y = event.getClientY();
                 OtherSharedTreeViewModel.this.selectionModel.setSelected(folder, true);
                 app.scheduleFolderHeadCommand(folder, new Command() {
-                                       
-                                       @Override
-                                       public void execute() {
-                               FolderContextMenu menu = new FolderContextMenu(app, OtherSharedTreeView.images, app.getSelectedTree(), folder);
-                               menu.setPopupPosition(x, y);
-                               menu.show();
-                                       }
-                               });
+
+                    @Override
+                    public void execute() {
+                        FolderContextMenu menu = new FolderContextMenu(app, OtherSharedTreeView.images, app.getSelectedTree(), folder);
+                        menu.setPopupPosition(x, y);
+                        menu.show();
+                    }
+                });
             }
         }
     };
 
-    protected ListDataProvider<String> userLevelDataProvider = new ListDataProvider<String>();
+    protected ListDataProvider<String> userLevelDataProviderForIDs = new ListDataProvider<String>();
+//    protected ListDataProvider<String> userLevelDataProviderForDisplayNames = new ListDataProvider<String>();
 
     protected Map<String, ListDataProvider<Folder>> userDataProviderMap = new HashMap<String, ListDataProvider<Folder>>();
     private Map<Folder, ListDataProvider<Folder>> dataProviderMap = new HashMap<Folder, ListDataProvider<Folder>>();
-    
+
     protected SingleSelectionModel<Folder> selectionModel;
 
     public OtherSharedTreeViewModel(Pithos _app, SingleSelectionModel<Folder> selectionModel) {
@@ -120,39 +120,48 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
 
     @Override
     public <T> NodeInfo<?> getNodeInfo(T value) {
-        if (value == null) {
-               fetchSharingUsers(null);
-            return new DefaultNodeInfo<String>(userLevelDataProvider, new TextCell(new SafeHtmlRenderer<String>() {
-
-                               @Override
-                               public SafeHtml render(String object) {
+        if(value == null) {
+//            LOG("getNodeInfo(null), calling fetchSharingUsers(null)");
+            fetchSharingUsers(null);
+//            LOG("getNodeInfo(null), called fetchSharingUsers(null)");
+            return new DefaultNodeInfo<String>(userLevelDataProviderForIDs, new TextCell(new SafeHtmlRenderer<String>() {
+                @Override
+                public SafeHtml render(String object) {
+                    final String displayName = app.getUserDisplayNameForID(object);
+//                    LOG("render(userID = "+object+"), displayName = " + displayName);
                     SafeHtmlBuilder builder = new SafeHtmlBuilder();
-                    render(object, builder);
+                    render(displayName, builder);
                     return builder.toSafeHtml();
-                               }
+                }
 
-                               @Override
-                               public void render(String object, SafeHtmlBuilder builder) {
-                    if (!object.equals(dummy)) {
-                       String html = AbstractImagePrototype.create(OtherSharedTreeView.images.myShared()).getHTML();
-                       builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
+                @Override
+                public void render(String object, SafeHtmlBuilder builder) {
+                    if(!object.equals(dummy)) {
+//                        LOG("render(userID [not dummy] = "+object+")");
+                        String html = AbstractImagePrototype.create(OtherSharedTreeView.images.myShared()).getHTML();
+                        builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
                     }
+                    final String displayName = app.getUserDisplayNameForID(object);
                     builder.append(OtherSharedTreeView.Templates.INSTANCE.nameSpan(object));
-                               }
-                       }), null, null);
+                }
+            }), null, null);
         }
-        else if (value instanceof String) {
-                       String username = (String) value;
-                       if (userDataProviderMap.get(username) == null) {
-                               userDataProviderMap.put(username, new ListDataProvider<Folder>());
-                       }
-                       final ListDataProvider<Folder> dataProvider = userDataProviderMap.get(username);
-                       fetchSharedContainers(username, dataProvider, null);
-                       return new DefaultNodeInfo<Folder>(dataProvider, folderCell, selectionModel, null);
+        else if(value instanceof String) {
+//            LOG("getNodeInfo(String "+value+"), called with userID");
+            final String userID = (String) value;
+
+            if(userDataProviderMap.get(userID) == null) {
+                userDataProviderMap.put(userID, new ListDataProvider<Folder>());
+            }
+            final ListDataProvider<Folder> userIDDataProvider = userDataProviderMap.get(userID);
+            fetchSharedContainers(userID, userIDDataProvider, null);
+
+            return new DefaultNodeInfo<Folder>(userIDDataProvider, folderCell, selectionModel, null);
         }
         else {
+//            LOG("getNodeInfo(Folder "+value+"), called with a folder");
             final Folder f = (Folder) value;
-            if (dataProviderMap.get(f) == null) {
+            if(dataProviderMap.get(f) == null) {
                 dataProviderMap.put(f, new ListDataProvider<Folder>());
             }
             final ListDataProvider<Folder> dataProvider = dataProviderMap.get(f);
@@ -161,144 +170,196 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
         }
     }
 
+//    native void LOG(String message) /*-{
+//      console.log(message );
+//    }-*/;
+
     private void fetchSharingUsers(final Command callback) {
-        GetRequest<SharingUsers> getSharingUsers = new GetRequest<SharingUsers>(SharingUsers.class, app.getApiPath(), "", "?format=json") {
+        GetRequest<SharingUsers> getSharingUsers = new GetRequest<SharingUsers>(app, SharingUsers.class, app.getApiPath(), "", "?format=json") {
             @Override
             public void onSuccess(final SharingUsers _result) {
-                userLevelDataProvider.getList().clear();
-                userLevelDataProvider.getList().addAll(_result.getUsers());
-                if (userLevelDataProvider.getList().isEmpty())
-                       userLevelDataProvider.getList().add(dummy);
-                Iterator<String> iter = _result.getUsers().iterator();
-                fetchSharedContainers(iter, callback);
+                userLevelDataProviderForIDs.getList().clear();
+
+                final List<String> userIDs = _result.getUserIDs();
+//                for(String userID : userIDs) {
+//                    LOG("fetchSharingUsers(): userID =" + userID);
+//                }
+                final List<String> userIDsWithUnknownDisplayNames = app.filterUserIDsWithUnknownDisplayName(userIDs);
+//                for(String userID : userIDsWithUnknownDisplayNames) {
+//                    LOG("fetchSharingUsers(): userID (with unknown name) =" + userID);
+//                }
+
+                userLevelDataProviderForIDs.getList().addAll(userIDs);
+                if(userLevelDataProviderForIDs.getList().isEmpty()) {
+                    userLevelDataProviderForIDs.getList().add(dummy);
+//                    userLevelDataProviderForDisplayNames.getList().add(dummy);
+                } else {
+//                    userLevelDataProviderForDisplayNames.getList().addAll(app.getUserDisplayNamesForIDs(userIDs));
+                }
+
+                if(userIDsWithUnknownDisplayNames.size() == 0) {
+                    // All display names are known, so we proceed directly
+                    fetchSharedContainers(userLevelDataProviderForIDs.getList().iterator(), callback);
+                } else {
+                    // First fetch unknown display names and then proceed
+                    new UpdateUserCatalogs(app, userIDsWithUnknownDisplayNames) {
+                        @Override
+                        public void onSuccess(UserCatalogs requestedUserCatalogs, UserCatalogs updatedUserCatalogs) {
+                            fetchSharedContainers(userLevelDataProviderForIDs.getList().iterator(), callback);
+                        }
+
+                        @Override
+                        public void onError(Request request, Throwable t) {
+                            super.onError(request, t);
+                            app.setError(t);
+                        }
+                    }.scheduleDeferred();
+                }
             }
 
             @Override
             public void onError(Throwable t) {
                 GWT.log("Error getting folder", t);
-                               app.setError(t);
-                if (t instanceof RestException)
+                app.setError(t);
+                if(t instanceof RestException) {
                     app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
-                else
+                }
+                else {
                     app.displayError("System error fetching folder: " + t.getMessage());
+                }
             }
 
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               app.sessionExpired();
-                       }
+            @Override
+            protected void onUnauthorized(Response response) {
+                app.sessionExpired();
+            }
         };
-        getSharingUsers.setHeader("X-Auth-Token", app.getToken());
+        getSharingUsers.setHeader("X-Auth-Token", app.getUserToken());
         Scheduler.get().scheduleDeferred(getSharingUsers);
-       }
-
-       protected void fetchSharedContainers(final Iterator<String> iter, final Command callback) {
-               if (iter.hasNext()) {
-                       String username = iter.next();
-                       if (userDataProviderMap.get(username) == null) {
-                               userDataProviderMap.put(username, new ListDataProvider<Folder>());
-                       }
-                       final ListDataProvider<Folder> dataProvider = userDataProviderMap.get(username);
-                       fetchSharedContainers(username, dataProvider, new Command() {
-                               
-                               @Override
-                               public void execute() {
-                                       fetchSharedContainers(iter, callback);
-                                       
-                               }
-                       });
-               }
-               else
-                       if (callback != null)
-                               callback.execute();
-       }
-
-       @Override
+    }
+
+    protected void fetchSharedContainers(final Iterator<String> userIDsIterator, final Command callback) {
+        if(userIDsIterator.hasNext()) {
+            String userID = userIDsIterator.next();
+            if(userDataProviderMap.get(userID) == null) {
+                userDataProviderMap.put(userID, new ListDataProvider<Folder>());
+            }
+            final ListDataProvider<Folder> dataProvider = userDataProviderMap.get(userID);
+            fetchSharedContainers(userID, dataProvider, new Command() {
+
+                @Override
+                public void execute() {
+                    fetchSharedContainers(userIDsIterator, callback);
+
+                }
+            });
+        }
+        else if(callback != null) {
+            callback.execute();
+        }
+    }
+
+    @Override
     public boolean isLeaf(Object o) {
-               if (o == null)
-                       return userLevelDataProvider.getList().isEmpty();
-               else if (o instanceof Folder) {
-            Folder f = (Folder) o;
-            return f.getSubfolders().isEmpty();
+        if(o == null) {
+            boolean result =  userLevelDataProviderForIDs.getList().isEmpty();
+//            LOG("isLeaf(null) ==> " + result);
+            return result;
+        }
+        else if(o instanceof Folder) {
+            Folder folder = (Folder) o;
+            boolean result = folder.getSubfolders().isEmpty();
+//            LOG("isLeaf(Folder "+folder+") ==> " + result);
+            return result;
+        }
+        else {
+            ListDataProvider<Folder> dp = userDataProviderMap.get(o);
+            if(dp != null) {
+                boolean result =  dp.getList().isEmpty();
+//                LOG("isLeaf("+o.getClass().getName()+" "+o+") ==> " + result);
+                return result;
+            }
+//            LOG("isLeaf("+o.getClass().getName()+" "+o+") ==> (true)");
+            return true;
         }
-               else {
-                       ListDataProvider<Folder> dp = userDataProviderMap.get(o);
-                       if (dp != null)
-                               return dp.getList().isEmpty();
-                       return true;
-               }
     }
 
-       private void fetchSharedContainers(final String username, final ListDataProvider<Folder> dataProvider, final Command callback) {
-               GetRequest<AccountResource> getUserSharedContainers = new GetRequest<AccountResource>(AccountResource.class, app.getApiPath(), username, "?format=json") {
-
-                       @Override
-                       public void onSuccess(AccountResource _result) {
-                       final ListDataProvider<Folder> tempProvider = new ListDataProvider<Folder>();
-                               Iterator<Folder> iter = _result.getContainers().iterator();
-                               fetchFolder(username, iter, tempProvider, new Command() {
-                                       
-                                       @Override
-                                       public void execute() {
-                                               dataProvider.getList().clear();
-                                               dataProvider.getList().addAll(tempProvider.getList());
-                                               if (callback != null)
-                                                       callback.execute();
-                                       }
-                               });
-                       }
-
-                       @Override
-                       public void onError(Throwable t) {
+    private void fetchSharedContainers(final String userID, final ListDataProvider<Folder> dataProvider, final Command callback) {
+        GetRequest<AccountResource> getUserSharedContainers = new GetRequest<AccountResource>(app, AccountResource.class, app.getApiPath(), userID, "?format=json") {
+
+            @Override
+            public void onSuccess(AccountResource _result) {
+                final ListDataProvider<Folder> tempProvider = new ListDataProvider<Folder>();
+                Iterator<Folder> folderIterator = _result.getContainers().iterator();
+                fetchFolder(userID, folderIterator, tempProvider, new Command() {
+
+                    @Override
+                    public void execute() {
+                        dataProvider.getList().clear();
+                        dataProvider.getList().addAll(tempProvider.getList());
+                        if(callback != null) {
+                            callback.execute();
+                        }
+                    }
+                });
+            }
+
+            @Override
+            public void onError(Throwable t) {
                 GWT.log("Error getting account", t);
-                               app.setError(t);
-                if (t instanceof RestException)
+                app.setError(t);
+                if(t instanceof RestException) {
                     app.displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
-                else
+                }
+                else {
                     app.displayError("System error fetching user data: " + t.getMessage());
-                       }
+                }
+            }
 
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               app.sessionExpired();
-                       }
-               };
-               getUserSharedContainers.setHeader("X-Auth-Token", app.getToken());
-               Scheduler.get().scheduleDeferred(getUserSharedContainers);
-       }
+            @Override
+            protected void onUnauthorized(Response response) {
+                app.sessionExpired();
+            }
+        };
+        getUserSharedContainers.setHeader("X-Auth-Token", app.getUserToken());
+        Scheduler.get().scheduleDeferred(getUserSharedContainers);
+    }
 
-       protected void fetchFolder(final String username, final Iterator<Folder> iter, final ListDataProvider<Folder> dataProvider, final Command callback) {
-        if (iter.hasNext()) {
-            final Folder f = iter.next();
+    protected void fetchFolder(final String userID, final Iterator<Folder> folderIterator, final ListDataProvider<Folder> dataProvider, final Command callback) {
+        if(folderIterator.hasNext()) {
+            final Folder f = folderIterator.next();
 
             String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
-            GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), username, path, f) {
+            GetRequest<Folder> getFolder = new GetRequest<Folder>(app, Folder.class, app.getApiPath(), userID, path, f) {
                 @Override
                 public void onSuccess(Folder _result) {
-                               dataProvider.getList().add(_result);
-                    fetchFolder(username, iter, dataProvider, callback);
+                    dataProvider.getList().add(_result);
+                    fetchFolder(userID, folderIterator, dataProvider, callback);
                 }
 
                 @Override
                 public void onError(Throwable t) {
                     GWT.log("Error getting folder", t);
-                                       app.setError(t);
-                    if (t instanceof RestException)
+                    app.setError(t);
+                    if(t instanceof RestException) {
                         app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
-                    else
+                    }
+                    else {
                         app.displayError("System error fetching folder: " + t.getMessage());
+                    }
                 }
 
-                               @Override
-                               protected void onUnauthorized(Response response) {
-                                       app.sessionExpired();
-                               }
+                @Override
+                protected void onUnauthorized(Response response) {
+                    app.sessionExpired();
+                }
             };
-            getFolder.setHeader("X-Auth-Token", app.getToken());
+            getFolder.setHeader("X-Auth-Token", app.getUserToken());
             Scheduler.get().scheduleDeferred(getFolder);
         }
-        else if (callback != null)
+        else if(callback != null) {
             callback.execute();
+        }
     }
 
     public Folder getSelection() {
@@ -306,7 +367,7 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
     }
 
     public void updateFolder(Folder folder, boolean showfiles, Command callback) {
-        if (dataProviderMap.get(folder) == null) {
+        if(dataProviderMap.get(folder) == null) {
             dataProviderMap.put(folder, new ListDataProvider<Folder>());
         }
         final ListDataProvider<Folder> dataProvider = dataProviderMap.get(folder);
@@ -315,20 +376,22 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
 
     public void fetchFolder(final Folder f, final ListDataProvider<Folder> dataProvider, final boolean showfiles, final Command callback) {
         String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
-        GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwner(), path, f) {
+        GetRequest<Folder> getFolder = new GetRequest<Folder>(app, Folder.class, app.getApiPath(), f.getOwnerID(), path, f) {
             @Override
             public void onSuccess(final Folder _result) {
-                if (showfiles)
+                if(showfiles) {
                     app.showFiles(_result);
+                }
                 Iterator<Folder> iter = _result.getSubfolders().iterator();
-                fetchFolder(_result.getOwner(), iter, dataProvider, new Command() {
+                fetchFolder(_result.getOwnerID(), iter, dataProvider, new Command() {
                     @Override
                     public void execute() {
                         dataProvider.getList().clear();
                         dataProvider.getList().addAll(_result.getSubfolders());
                         app.getOtherSharedTreeView().updateChildren(f);
-                        if (callback != null)
-                               callback.execute();
+                        if(callback != null) {
+                            callback.execute();
+                        }
                     }
                 });
             }
@@ -336,23 +399,25 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
             @Override
             public void onError(Throwable t) {
                 GWT.log("Error getting folder", t);
-                               app.setError(t);
-                if (t instanceof RestException)
+                app.setError(t);
+                if(t instanceof RestException) {
                     app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
-                else
+                }
+                else {
                     app.displayError("System error fetching folder: " + t.getMessage());
+                }
             }
 
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               app.sessionExpired();
-                       }
+            @Override
+            protected void onUnauthorized(Response response) {
+                app.sessionExpired();
+            }
         };
-        getFolder.setHeader("X-Auth-Token", app.getToken());
+        getFolder.setHeader("X-Auth-Token", app.getUserToken());
         Scheduler.get().scheduleDeferred(getFolder);
     }
-    
+
     public void initialize(Command callback) {
-       fetchSharingUsers(callback);
+        fetchSharingUsers(callback);
     }
 }
index b6b71ee..bea8c44 100644 (file)
@@ -35,7 +35,8 @@
 
 package gr.grnet.pithos.web.client.rest;
 
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.Resource;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -55,6 +56,8 @@ public abstract class DeleteRequest implements ScheduledCommand {
        
        protected static final int MAX_RETRIES = 3; 
 
+    private final Pithos app;
+
        protected int retries = 0; 
 
        private String api;
@@ -69,7 +72,8 @@ public abstract class DeleteRequest implements ScheduledCommand {
 
     public abstract void onError(Throwable t);
 
-    public DeleteRequest(String api, String owner, String path) {
+    public DeleteRequest(Pithos app, String api, String owner, String path) {
+        this.app = app;
         this.api = api;
         this.owner = owner;
         this.path = path;
@@ -90,7 +94,7 @@ public abstract class DeleteRequest implements ScheduledCommand {
 
                 @Override
                 public Resource deserialize(Response response) {
-                    return Resource.createFromResponse(Resource.class, owner, response, null);
+                    return Resource.createFromResponse(app, Resource.class, owner, response, null);
                 }
 
                 @Override
index 7bec14f..ab5d519 100644 (file)
@@ -35,7 +35,8 @@
 
 package gr.grnet.pithos.web.client.rest;
 
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.Resource;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -51,9 +52,11 @@ public abstract class GetRequest<T extends Resource> implements ScheduledCommand
        
        protected static final int MAX_RETRIES = 3; 
 
-       protected int retries = 0; 
+       protected int retries = 0;
 
-       protected Class<T> aClass;
+    private final Pithos app;
+
+       protected Class<T> resourceClass;
 
     private String api;
 
@@ -71,8 +74,9 @@ public abstract class GetRequest<T extends Resource> implements ScheduledCommand
 
     public abstract void onError(Throwable t);
 
-    public GetRequest(Class<T> aClass, String api, String owner, String path, int okCode, T result) {
-        this.aClass = aClass;
+    public GetRequest(Pithos app, Class<T> resourceClass, String api, String owner, String path, int okCode, T result) {
+        this.app = app;
+        this.resourceClass = resourceClass;
         this.api = api;
         this.owner = owner;
         this.path = path;
@@ -80,12 +84,12 @@ public abstract class GetRequest<T extends Resource> implements ScheduledCommand
         this.result = result;
     }
 
-    public GetRequest(Class<T> aClass, String api, String owner, String path) {
-        this(aClass, api, owner, path, -1, null);
+    public GetRequest(Pithos app, Class<T> resourceClass, String api, String owner, String path) {
+        this(app, resourceClass, api, owner, path, -1, null);
     }
 
-    public GetRequest(Class<T> aClass, String api, String owner, String path, T result) {
-        this(aClass, api, owner, path, -1, result);
+    public GetRequest(Pithos app, Class<T> resourceClass, String api, String owner, String path, T result) {
+        this(app, resourceClass, api, owner, path, -1, result);
     }
 
     @Override
@@ -95,6 +99,7 @@ public abstract class GetRequest<T extends Resource> implements ScheduledCommand
        else
                path += "?t=" + System.currentTimeMillis();
         RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, api + owner + path);
+
         for (String header : headers.keySet()) {
             builder.setHeader(header, headers.get(header));
         }
@@ -107,7 +112,7 @@ public abstract class GetRequest<T extends Resource> implements ScheduledCommand
 
                 @Override
                 public T deserialize(Response response) {
-                    return Resource.createFromResponse(aClass, owner, response, result);
+                    return Resource.createFromResponse(app, resourceClass, owner, response, result);
                 }
 
                 @Override
index 1e4cdf0..1148554 100644 (file)
@@ -35,7 +35,8 @@
 
 package gr.grnet.pithos.web.client.rest;
 
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.Resource;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -51,6 +52,8 @@ public abstract class HeadRequest<T extends Resource> implements ScheduledComman
 
        protected static final int MAX_RETRIES = 3; 
 
+    private final Pithos app;
+
        protected int retries = 0; 
 
        protected Class<T> aClass;
@@ -73,7 +76,8 @@ public abstract class HeadRequest<T extends Resource> implements ScheduledComman
 
     public abstract void onError(Throwable t);
 
-    public HeadRequest(Class<T> aClass, String api, String owner, String path, int okCode, T result) {
+    public HeadRequest(Pithos app, Class<T> aClass, String api, String owner, String path, int okCode, T result) {
+        this.app = app;
         this.aClass = aClass;
         this.api = api;
         this.owner = owner;
@@ -82,12 +86,12 @@ public abstract class HeadRequest<T extends Resource> implements ScheduledComman
         this.result = result;
     }
 
-    public HeadRequest(Class<T> aClass, String api, String owner, String path) {
-        this(aClass, api, owner, path, Response.SC_NO_CONTENT, null);
+    public HeadRequest(Pithos app, Class<T> aClass, String api, String owner, String path) {
+        this(app, aClass, api, owner, path, Response.SC_NO_CONTENT, null);
     }
 
-    public HeadRequest(Class<T> aClass, String api, String owner, String path, T result) {
-        this(aClass, api, owner, path, Response.SC_NO_CONTENT, result);
+    public HeadRequest(Pithos app, Class<T> aClass, String api, String owner, String path, T result) {
+        this(app, aClass, api, owner, path, Response.SC_NO_CONTENT, result);
     }
 
     @Override
@@ -109,7 +113,7 @@ public abstract class HeadRequest<T extends Resource> implements ScheduledComman
 
                 @Override
                 public T deserialize(Response response) {
-                    return Resource.createFromResponse(aClass, owner, response, result);
+                    return Resource.createFromResponse(app, aClass, owner, response, result);
                 }
 
                 @Override
index fe3da92..a5437a5 100644 (file)
@@ -35,7 +35,8 @@
 
 package gr.grnet.pithos.web.client.rest;
 
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.Resource;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -49,6 +50,8 @@ import com.google.gwt.http.client.Response;
 
 public abstract class PostRequest implements ScheduledCommand {
 
+    private final Pithos app;
+
     private String api;
 
     protected String owner;
@@ -63,13 +66,15 @@ public abstract class PostRequest implements ScheduledCommand {
 
     public abstract void onError(Throwable t);
 
-    public PostRequest(String api, String owner, String path) {
+    public PostRequest(Pithos app, String api, String owner, String path) {
+        this.app = app;
         this.api = api;
         this.owner = owner;
         this.path = path;
     }
 
-    public PostRequest(String api, String owner, String path, String data) {
+    public PostRequest(Pithos app, String api, String owner, String path, String data) {
+        this.app = app;
         this.api = api;
         this.owner = owner;
         this.path = path;
@@ -91,7 +96,7 @@ public abstract class PostRequest implements ScheduledCommand {
 
                 @Override
                 public Resource deserialize(Response response) {
-                    return Resource.createFromResponse(Resource.class, owner, response, null);
+                    return Resource.createFromResponse(app, Resource.class, owner, response, null);
                 }
 
                 @Override
index 3c57792..73ee55d 100644 (file)
@@ -70,7 +70,8 @@
 
 package gr.grnet.pithos.web.client.rest;
 
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.Resource;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -83,6 +84,8 @@ import com.google.gwt.http.client.Response;
 
 public abstract class PutRequest implements ScheduledCommand {
 
+    private final Pithos app;
+
     private String api;
 
     protected String owner;
@@ -95,7 +98,8 @@ public abstract class PutRequest implements ScheduledCommand {
 
     public abstract void onError(Throwable t);
 
-    public PutRequest(String api, String owner, String path) {
+    public PutRequest(Pithos app, String api, String owner, String path) {
+        this.app = app;
         this.api = api;
         this.owner = owner;
         this.path = path;
@@ -116,7 +120,7 @@ public abstract class PutRequest implements ScheduledCommand {
 
                 @Override
                 public Resource deserialize(Response response) {
-                    return Resource.createFromResponse(Resource.class, owner, response, null);
+                    return Resource.createFromResponse(app, Resource.class, owner, response, null);
                 }
 
                 @Override
index 689affe..91da6da 100644 (file)
@@ -38,7 +38,7 @@ package gr.grnet.pithos.web.client.rest;
 import com.google.gwt.http.client.Request;
 import com.google.gwt.http.client.RequestCallback;
 import com.google.gwt.http.client.Response;
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Resource;
 
 public abstract class RestRequestCallback<T extends Resource> implements RequestCallback {
 
index 42640dd..e51ceb3 100644 (file)
@@ -36,7 +36,7 @@
 package gr.grnet.pithos.web.client.tagtree;
 
 import gr.grnet.pithos.web.client.foldertree.File;
-import gr.grnet.pithos.web.client.foldertree.Resource;
+import gr.grnet.pithos.web.client.Resource;
 
 import java.util.Date;
 import java.util.LinkedHashSet;
index 5f4fd79..96e71e8 100644 (file)
@@ -147,7 +147,7 @@ public class TagTreeViewModel implements TreeViewModel {
         if (iter.hasNext()) {
             Folder f = iter.next();
             String path = f.getUri() + "?format=json&meta=" + t.getName();
-            GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), app.getUsername(), path) {
+            GetRequest<Folder> getFolder = new GetRequest<Folder>(app, Folder.class, app.getApiPath(), app.getUserID(), path) {
                 @Override
                 public void onSuccess(Folder _result) {
                     files.addAll(_result.getFiles());
@@ -169,7 +169,7 @@ public class TagTreeViewModel implements TreeViewModel {
                                        app.sessionExpired();
                                }
             };
-            getFolder.setHeader("X-Auth-Token", app.getToken());
+            getFolder.setHeader("X-Auth-Token", app.getUserToken());
             Scheduler.get().scheduleDeferred(getFolder);
         }
         else {
diff --git a/version b/version
new file mode 100644 (file)
index 0000000..f304084
--- /dev/null
+++ b/version
@@ -0,0 +1 @@
+0.13