Android Open Source - GOAC Start Transfer






From Project

Back to project page GOAC.

License

The source code is released under:

MIT License

If you think the Android project GOAC listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.globus.globustransfer;
/*from  ww  w . j  a va 2 s .co m*/




import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.globusonline.transfer.APIError;
import org.globusonline.transfer.JSONTransferAPIClient;
import org.globusonline.transfer.JSONTransferAPIClient.Result;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

public class StartTransfer extends Activity {

  protected String mUsername;
  protected String mSamlCookie;
  private static JSONTransferAPIClient sClient;
  private Context mContext;
  private String mEndpointACurrentPath = "/";
  private String mEndpointBCurrentPath = "/";
  private ProgressBar mEndpointLoadProgressBar;
  private ProgressBar mEndpointAProgressBar, mEndpointBProgressBar;
  private Dialog mSettingsDialog, mCreateFolderDialog, mDeleteFilesDialog,
      mMakeTransferDialog;
  private ToggleButton mEndpointsVisibleToggleButton, mHiddenToggleButton;
  private Button mCreateFolderOkButton, mDeleteFilesOkButton,
      mMakeTransferOkButton, mSettingOkButton;
  private Button mSelectEndpointAButton, mSelectEndpointBButton;
  private Button mDeleteAButton, mDeleteBButton;
  private Button mUpAButton, mUpBButton;
  private Button mTransferAButton, mTransferBButton;
  private Button mCreateAButton, mCreateBButton;
  private Button mRefreshAButton, mRefreshBButton;
  private ArrayList<String> mEndpoints;
  private ArrayList<String> mFileListA, mFileListB;
  private SharedPreferences mSharedPreferences;
  private ListView mAListView, mBListView;
  private TextView mATextView, mBTextView;
  private TextView mPathATextView, mPathBTextView;
  private List<String> mSelectedFilesA, mSelectedFilesB;
  private EditText mCreateFolderEditText, mDeleteFilesEditText,
      mMakeTransferEditText;
  private String mFolderName, mTransferName, mDeletionName, mNode;
  private Map<String, Long> mLastTimePressedA, mLastTimePressedB;
  private Map<String, Float> mFilesSizeA, mFilesSizeB;
  private static long mInterval = 900;
  private Boolean mEndpointsTemp, mHiddenTemp;
  private JSONObject mActivationRequirements;
  private Dialog mActivateDialog;

  @SuppressWarnings("unchecked")
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_start_transfer);

    // The username and cookie are retrieved from the Intent
    Intent mIntent = getIntent();
    Bundle mInfo = mIntent.getExtras();

    mActivationRequirements = null;

    mLastTimePressedA = new HashMap<String, Long>();
    mLastTimePressedB = new HashMap<String, Long>();

    mFilesSizeA = new HashMap<String, Float>();
    mFilesSizeB = new HashMap<String, Float>();

    mSelectedFilesA = new ArrayList<String>();
    mSelectedFilesB = new ArrayList<String>();

    mFileListA = new ArrayList<String>();
    mFileListB = new ArrayList<String>();

    mUsername = mInfo.getString("username");
    mSamlCookie = mInfo.getString("samlCookie");

    mContext = this;
    mEndpointLoadProgressBar = (ProgressBar) findViewById(R.id.endpoints_progress_bar);
    mEndpointLoadProgressBar.setMax(4);

    mAListView = (ListView) findViewById(R.id.endpoint_A_list_view);
    mBListView = (ListView) findViewById(R.id.endpoint_B_list_view);

    mRefreshAButton = (Button) findViewById(R.id.refresh_A_button);
    mRefreshBButton = (Button) findViewById(R.id.refresh_B_button);

    mTransferAButton = (Button) findViewById(R.id.transfer_A_to_B_button);
    mTransferBButton = (Button) findViewById(R.id.transfer_B_to_A_button);

    mSelectEndpointAButton = (Button) findViewById(R.id.select_endpoint_A_button);
    mSelectEndpointBButton = (Button) findViewById(R.id.select_endpoint_B_button);

    mUpAButton = (Button) findViewById(R.id.back_A_button);
    mUpBButton = (Button) findViewById(R.id.back_B_button);

    mATextView = (TextView) findViewById(R.id.textView1);
    mBTextView = (TextView) findViewById(R.id.textView2);

    mPathATextView = (TextView) findViewById(R.id.path_A);
    mPathBTextView = (TextView) findViewById(R.id.path_B);

    mEndpointAProgressBar = (ProgressBar) findViewById(R.id.endpoints_A_directory_progress);
    mEndpointBProgressBar = (ProgressBar) findViewById(R.id.endpoints_B_directory_progress);

    mDeleteAButton = (Button) findViewById(R.id.delete_A_button);
    mDeleteBButton = (Button) findViewById(R.id.delete_B_button);

    // The Settings Dialog is initialized
    mSettingsDialog = new Dialog(this);
    mSettingsDialog.setCanceledOnTouchOutside(false);
    mSettingsDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    mSettingsDialog.setContentView(R.layout.settings_dialog);

    mAListView.setOnItemClickListener(mMessageClickedHandlerA);
    mBListView.setOnItemClickListener(mMessageClickedHandlerB);

    mSettingOkButton = (Button) mSettingsDialog
        .findViewById(R.id.ok_button);
    mCreateAButton = (Button) findViewById(R.id.create_folder_A_button);
    mCreateBButton = (Button) findViewById(R.id.create_folder_B_button);
    mSharedPreferences = getSharedPreferences(
        getString(R.string.preferences_name), MODE_PRIVATE);
    mEndpointsVisibleToggleButton = (ToggleButton) mSettingsDialog
        .findViewById(R.id.toggleButton1);

    mHiddenToggleButton = (ToggleButton) mSettingsDialog
        .findViewById(R.id.toggleButton2);

    mEndpointsVisibleToggleButton.setChecked(mSharedPreferences.getBoolean(
        "EndpointsActiveOnly", true));
    mHiddenToggleButton.setChecked(mSharedPreferences.getBoolean(
        "ShowHiddenFiles", false));

    mEndpointsVisibleToggleButton
        .setOnCheckedChangeListener(new OnCheckedChangeListener() {

          @Override
          public void onCheckedChanged(CompoundButton arg0,
              boolean isChecked) {

            SharedPreferences.Editor mEditor = mSharedPreferences
                .edit();
            if (isChecked) {

              mEditor.putBoolean("EndpointsActiveOnly", true);

            } else {

              mEditor.putBoolean("EndpointsActiveOnly", false);

            }
            mEditor.commit();
          }

        });

    mHiddenToggleButton
        .setOnCheckedChangeListener(new OnCheckedChangeListener() {

          @Override
          public void onCheckedChanged(CompoundButton arg0,
              boolean isChecked) {

            SharedPreferences.Editor mEditor = mSharedPreferences
                .edit();
            if (isChecked) {

              mEditor.putBoolean("ShowHiddenFiles", true);

            } else {

              mEditor.putBoolean("ShowHiddenFiles", false);

            }
            mEditor.commit();
          }

        });

    mSettingOkButton.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View arg0) {
        mSettingsDialog.dismiss();
        if (mSharedPreferences.getBoolean("EndpointsActiveOnly", true) != mEndpointsTemp) {
          new GetEndpointsList().execute();

        } else if (mSharedPreferences.getBoolean("ShowHiddenFiles",
            false) != mHiddenTemp) {
          if (mSelectEndpointAButton.getText().toString() != getString(R.string.select_endpoint_prompt)) {
            new GetEndpointsDirectory("a", mSelectEndpointAButton
                .getText().toString()).execute();
          }
          if (mSelectEndpointBButton.getText().toString() != getString(R.string.select_endpoint_prompt)) {
            new GetEndpointsDirectory("b", mSelectEndpointBButton
                .getText().toString()).execute();
          }

        }

      }

    });

    try {
      
      // Creates a client to communicate with the GO API
      sClient = new JSONTransferAPIClient(mUsername, null, mSamlCookie);
    } catch (Exception e) {
      e.printStackTrace();

    }

    // When the activity is restarted (e.g. the screen's orientation
    // changes) all the relative information is reloaded
    if (savedInstanceState != null) {

      mEndpoints = savedInstanceState
          .getStringArrayList("endpoints_list");
      mPathATextView.setText(savedInstanceState
          .getString("path_a_text_view"));
      mPathBTextView.setText(savedInstanceState
          .getString("path_b_text_view"));
      mEndpointACurrentPath = savedInstanceState.getString("path_a");
      mEndpointBCurrentPath = savedInstanceState.getString("path_b");
      mSelectEndpointAButton.setText(savedInstanceState
          .getString("endpoint_a"));
      mSelectEndpointBButton.setText(savedInstanceState
          .getString("endpoint_b"));
      mSelectedFilesA = savedInstanceState
          .getStringArrayList("selected_files_a");
      mSelectedFilesB = savedInstanceState
          .getStringArrayList("selected_files_b");

      mFileListA = savedInstanceState.getStringArrayList("dir_a");

      mFilesSizeA = (Map<String, Float>) savedInstanceState
          .getSerializable("filesizeA");

      if (!mFileListA.isEmpty()) {
        ArrayAdapter mAdapterA = new CustomAdapter(mContext,
            android.R.layout.simple_list_item_1, mFileListA);

        mAListView.setAdapter(mAdapterA);
      }

      mFileListB = savedInstanceState.getStringArrayList("dir_b");

      mFilesSizeB = (Map<String, Float>) savedInstanceState
          .getSerializable("filesizeB");

      if (!mFileListB.isEmpty()) {
        ArrayAdapter mAdapterB = new CustomAdapter(mContext,
            android.R.layout.simple_list_item_1, mFileListB);

        mBListView.setAdapter(mAdapterB);
      }
      if (!mSelectedFilesB.isEmpty()
          && mSelectEndpointAButton.getText().toString() != getString(R.string.select_endpoint_prompt)) {
        mTransferBButton
            .setBackgroundResource(R.drawable.transfer_up_active);
      }
      if (!mSelectedFilesA.isEmpty()
          && mSelectEndpointBButton.getText().toString() != getString(R.string.select_endpoint_prompt)) {
        mTransferAButton
            .setBackgroundResource(R.drawable.transfer_down_active);
      }
    } else {
      new GetEndpointsList().execute();
    }
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.start_transfer, menu);
    return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.refresh_menu_item:

      // If the Refresh Button is pressed the endpoint's List is reloaded
      new GetEndpointsList().execute();
      return true;
    case R.id.transfer_settings_menu_item:

      // If the Settings Button is pressed the Settings Menu is loaded
      mEndpointsTemp = mSharedPreferences.getBoolean(
          "EndpointsActiveOnly", true);
      mHiddenTemp = mSharedPreferences.getBoolean("ShowHiddenFiles",
          false);
      mSettingsDialog.show();
    default:
      return super.onOptionsItemSelected(item);
    }
  }

  /**
   * It creates a short-lived message on the screen.
   * 
   * @param text
   *            The contents of the message
   * @param duration
   *            The duration of the appearance of the message on the screen
   */
  public void makeToast(String text, int duration) {
    Toast.makeText(this, text, duration).show();
  }

  /***
   * Function which is called when an endpoint is selected from the list. The
   * path is set to "/" , the endpoint's name is set on the corresponding text
   * field and if some files on the other endpoint are selected, the
   * corresponding transfer button is activated.
   * */
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);
    if (data.getExtras().containsKey("endpoint")
        && data.getExtras().containsKey("endId")) {
      if (data.getStringExtra("endId").contentEquals("a")) {
        if (!mSelectedFilesB.isEmpty()) {
          mTransferBButton
              .setBackgroundResource(R.drawable.transfer_up_active);
        }
        mSelectEndpointAButton.setText(data.getStringExtra("endpoint"));
        mEndpointACurrentPath = "/";
        mPathATextView.setText(getString(R.string.path_placeholder));
        new GetEndpointsDirectory("a", data.getStringExtra("endpoint"))
            .execute();

      } else if (data.getStringExtra("endId").contentEquals("b")) {
        if (!mSelectedFilesA.isEmpty()) {
          mTransferAButton
              .setBackgroundResource(R.drawable.transfer_down_active);
        }
        mSelectEndpointBButton.setText(data.getStringExtra("endpoint"));
        mEndpointBCurrentPath = "/";
        mPathBTextView.setText(getString(R.string.path_placeholder));
        new GetEndpointsDirectory("b", data.getStringExtra("endpoint"))
            .execute();
      }

    }
  }

  /**
   * On click listener for List View A. If one file or folder is pressed its
   * background color changes to blue if it was white before and it is added
   * to the Selected Files list. If it was already on the list its background
   * color turns white and it is deleted from the list. If a folder is pressed
   * twice in less than 0.9 seconds the path is set to that folder.
   */
  private OnItemClickListener mMessageClickedHandlerA = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position,
        long id) {

      long mPressTime = System.currentTimeMillis();
      long mTimeDifference;
      TextView mFileNameTextView = (TextView) v
          .findViewById(R.id.file_name_in_list_text_view);

      String mFilename = mFileNameTextView.getText().toString();

      if (mLastTimePressedA.containsKey(mFilename)) {
        mTimeDifference = mPressTime - mLastTimePressedA.get(mFilename);
      } else {
        mTimeDifference = mInterval + 1;
      }
      if (mTimeDifference <= mInterval && mFilename.endsWith("/")) {

        mEndpointACurrentPath = mEndpointACurrentPath.concat(mFilename);
        new GetEndpointsDirectory("a", mSelectEndpointAButton.getText()
            .toString()).execute();

      } else {

        if (!mSelectedFilesA.contains(mFilename)) {
          v.setBackgroundColor(getResources().getColor(
              R.color.android_light_blue));
          mSelectedFilesA.add(mFilename);
          if (mSelectEndpointBButton.getText().toString() != getString(R.string.select_endpoint_prompt))
            mTransferAButton
                .setBackgroundResource((R.drawable.transfer_down_active));
        } else {
          v.setBackgroundColor(Color.WHITE);
          mSelectedFilesA.remove(mFilename);
          if (mSelectedFilesA.isEmpty()) {
            mTransferAButton.setBackgroundResource(R.drawable.down);
          }

        }
      }
      mLastTimePressedA.put(mFilename, mPressTime);
    }

  };

  /**
   * On click listener for List View ?. If one file or folder is pressed its
   * background color changes to blue if it was white before and it is added
   * to the Selected Files list. If it was already on the list its background
   * color turns white and it is deleted from the list. If a folder is pressed
   * twice in less than 0.9 seconds the path is set to that folder.
   */
  private OnItemClickListener mMessageClickedHandlerB = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position,
        long id) {
      long mPressTime = System.currentTimeMillis();
      long mTimeDifference;
      TextView mFilenameTextView = (TextView) v
          .findViewById(R.id.file_name_in_list_text_view);

      String mFilename = mFilenameTextView.getText().toString();

      if (mLastTimePressedB.containsKey(mFilename)) {
        mTimeDifference = mPressTime - mLastTimePressedB.get(mFilename);
      } else {
        mTimeDifference = mInterval + 1;
      }
      if (mTimeDifference <= mInterval && mFilename.endsWith("/")) {

        mEndpointBCurrentPath = mEndpointBCurrentPath.concat(mFilename);
        new GetEndpointsDirectory("b", mSelectEndpointBButton.getText()
            .toString()).execute();

      } else {
        if (!mSelectedFilesB.contains(mFilename)) {
          v.setBackgroundColor(getResources().getColor(
              R.color.android_light_blue));

          mSelectedFilesB.add(mFilename);
          if (mSelectEndpointAButton.getText().toString() != getString(R.string.select_endpoint_prompt))
            mTransferBButton
                .setBackgroundResource((R.drawable.transfer_up_active));
        } else {
          v.setBackgroundColor(Color.WHITE);
          mSelectedFilesB.remove(mFilename);
          if (mSelectedFilesB.isEmpty()) {
            mTransferBButton.setBackgroundResource(R.drawable.up);
          }
        }
      }
      mLastTimePressedB.put(mFilename, mPressTime);

    }
  };

  /**
   * Goes up one folder level. If the current path is the root path it notifies
   * the user with a Toast that they can not go further up.
   * 
   * @param view
   *            The ListView (representing an endpoint's directory) we want to
   *            act on
   */
  public void goBack(View view)

  {
    int mIdButton = ((Button) view).getId();
    String mNoEndpoint = getString(R.string.select_endpoint_prompt);

    if (mIdButton == R.id.back_A_button) {

      // If no endpoint is selected the user is notified with a warning Toast
      // message
      if (mSelectEndpointAButton.getText() == mNoEndpoint) {
        makeToast(getString(R.string.no_endpoint_selected_warning),
            Toast.LENGTH_SHORT);
      } else {

        if (!mEndpointACurrentPath.contentEquals("/")) {

          mEndpointACurrentPath = backPath(mEndpointACurrentPath);
          new GetEndpointsDirectory("a", mSelectEndpointAButton
              .getText().toString()).execute();
        } else {
          // If the current path is the root path the user is notified
          // with a warning Toast message
          String text = getString(R.string.root_folder_warning)
              .toString();
          makeToast(text, Toast.LENGTH_SHORT);
        }
      }

    } else if (mIdButton == R.id.back_B_button) {

      // If no endpoint is selected the user is notified with a warning Toast
      // message
      if (mSelectEndpointBButton.getText() == mNoEndpoint) {
        makeToast(
            getString(R.string.no_endpoint_selected_warning,
                Toast.LENGTH_SHORT), Toast.LENGTH_SHORT);
      } else {
        if (!mEndpointBCurrentPath.contentEquals("/")) {
          mEndpointBCurrentPath = backPath(mEndpointBCurrentPath);
          new GetEndpointsDirectory("b", mSelectEndpointBButton
              .getText().toString()).execute();
        } else {
          // If the current path is the root path the user is notified
          // with a warning Toast message
          String text = getString(R.string.root_folder_warning)
              .toString();
          makeToast(text, Toast.LENGTH_SHORT);
        }
      }

    }

  }

  /**
   * Creates a Deletion Dialog asking from the user for a label for deleting
   * the files selected in the corresponding View (endpoint). It gives
   * appropriate error messages with Toasts when there is no endpoint selected
   * in the View or if no files are selected.If the user clicks on the "OK"
   * Button of the Dialog -having typed a valid label or no label at all- it
   * calls the execute method of the FileDeletion class.
   * 
   * @param view
   *            The ListView (representing an endpoint's directory) we want to
   *            act on
   */
  public void deleteFiles(final View view) {

    if (view.getId() == mDeleteAButton.getId()) {
      {
        mNode = "a";

        // If no endpoint is selected the user is notified with a warning Toast
        // message
        if (mSelectEndpointAButton
            .getText()
            .toString()
            .contentEquals(
                getString(R.string.select_endpoint_prompt))) {
          makeToast(getString(R.string.no_endpoint_selected_warning),
              Toast.LENGTH_SHORT);
          return;
        }

        // If no files are selected the user in notified with a wanring Toast
        // message
        if (mSelectedFilesA.isEmpty()) {
          makeToast(getString(R.string.no_files_selected_warning),
              Toast.LENGTH_SHORT);
          return;
        }

      }

    } else if (view.getId() == mDeleteBButton.getId()) {
      mNode = "b";

      // If no endpoint is selected the user is notified with a  warning Toast
      // message
      if (mSelectEndpointBButton.getText().toString()
          .contentEquals(getString(R.string.select_endpoint_prompt))) {
        makeToast(getString(R.string.no_endpoint_selected_warning),
            Toast.LENGTH_SHORT);
        return;
      }

      // If no files are selected the user in notified with a warning Toast
      // message
      if (mSelectedFilesB.isEmpty()) {
        makeToast(getString(R.string.no_files_selected_warning),
            Toast.LENGTH_SHORT);
        return;
      }
    }

    // The Delete Files Dialog is initialized
    mDeleteFilesDialog = new Dialog(this);
    mDeleteFilesDialog.setCanceledOnTouchOutside(false);
    mDeleteFilesDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    mDeleteFilesDialog.setContentView(R.layout.select_deletion_name);
    mDeleteFilesEditText = (EditText) mDeleteFilesDialog
        .findViewById(R.id.deletion_name_edit_text);
    mDeleteFilesOkButton = (Button) mDeleteFilesDialog
        .findViewById(R.id.ok_button);

    mDeleteFilesDialog.show();

    // This onClickListener defines what happens when the user presses the
    // OK button on the Deletion Dialog
    mDeleteFilesOkButton.setOnClickListener(new OnClickListener()

    {

      @Override
      public void onClick(View arg0) {

        mDeletionName = mDeleteFilesEditText.getText().toString();
        mDeleteFilesEditText.setText("");

        // If the deletion task's label contains escape characters
        // (which result to an error) the user in informed with a warning Toast
        // message
        if (mDeletionName.contains("\n")) {
          makeToast(
              getString(R.string.no_escape_characters_allowed_warning),
              Toast.LENGTH_SHORT);
        } else {
          mDeleteFilesDialog.dismiss();

          new FileDeletion(mNode, mDeletionName).execute();
        }
      }

    });

  }

  /**
   * Creates a folder creation Dialog asking from the user for the name of the
   * folder to be created in the corresponding view (endpoint). It gives
   * appropriate error messages with Toasts when there in no endpoint selected
   * in the view. If the user clicks on the "OK" button of the dialog -having
   * typed a valid folder name- it calls the execute method of the
   * directoryCreation class.
   * 
   * @param view
   *            The ListView (representing an endpoint's directory) we want to
   *            act on
   */
  public void createNewFolder(View view) {

    int mIdButton = ((Button) view).getId();
    String mNoEndpoint = getString(R.string.select_endpoint_prompt);
    if (mIdButton == R.id.create_folder_A_button) {
      mNode = "a";

      // If no endpoint is selected the user is notified with a warning Toast
      // message
      if (mSelectEndpointAButton.getText() == mNoEndpoint) {
        makeToast(getString(R.string.no_endpoint_selected_warning),
            Toast.LENGTH_SHORT);
        return;
      }
    } else if (mIdButton == R.id.create_folder_B_button) {
      mNode = "b";
      // If no endpoint is selected the user is notified with a warning Toast
      // message
      if (mSelectEndpointBButton.getText() == mNoEndpoint) {
        makeToast(getString(R.string.no_endpoint_selected_warning),
            Toast.LENGTH_SHORT);
        return;
      }
    }

    // The Create Folder Dialog is initialized
    mCreateFolderDialog = new Dialog(this);
    mCreateFolderDialog.setCanceledOnTouchOutside(false);
    mCreateFolderDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    mCreateFolderDialog.setContentView(R.layout.select_folder_name);
    mCreateFolderEditText = (EditText) mCreateFolderDialog
        .findViewById(R.id.folder_name_edit_text);
    mCreateFolderOkButton = (Button) mCreateFolderDialog
        .findViewById(R.id.ok_button);
    mCreateFolderDialog.show();

    // This onClickListener defines what happens when the user presses the
    // OK Button on the Create Folder Dialog
    mCreateFolderOkButton.setOnClickListener(new OnClickListener()

    {

      @Override
      public void onClick(View arg0) {

        mFolderName = mCreateFolderEditText.getText().toString();

        // If no folder name is typed the user is informed with a warning Toast
        // message
        if (mFolderName.isEmpty()) {
          makeToast(getString(R.string.no_folder_title_warning),
              Toast.LENGTH_SHORT);
        }

        // If the folder's name contains escape characters
        // (which result to an error) the user in informed with a warning Toast
        // message
        else if (mFolderName.contains("\n")) {
          makeToast(
              getString(R.string.no_escape_characters_allowed_warning),
              Toast.LENGTH_SHORT);
        } else {

          mCreateFolderDialog.dismiss();
          new DirectoryCreation(mNode, mFolderName).execute();
        }
      }

    });

  }

  /**
   * It initiates with an Intent the Endpoint Activity, waiting to get back a
   * result with the name of the Enpoint selected by the user.
   * 
   * @param view
   *            The Endpoint Selection Button that was clicked
   */
  public void startEndpointList(View view) {
    String mEndpoint = null;

    // The endpoint (A or B) that called the startEndpointList function is
    // defined
    if (view.getId() == mSelectEndpointAButton.getId())
      mEndpoint = "a";
    else if (view.getId() == mSelectEndpointBButton.getId())
      mEndpoint = "b";

    // An intent is created in order to call the Endpoint Activity
    Intent mIntent = new Intent(mContext, EndpointActivity.class);
    mIntent.putStringArrayListExtra("endpointslist", mEndpoints);
    mIntent.putExtra("endId", mEndpoint);

    try {

      // The Endpoint Activity is called and a String Array List
      // containing the endpoint's directory contents is expected
      startActivityForResult(mIntent, 1);
    } catch (Exception e) {

    }
  }

  /**
   * Returns the path of the folder being one level up from the current
   * folder.
   * 
   * @param path
   *            The current path
   * @return The path of the folder one level up
   */
  public String backPath(String path) {
    String mDelims = "/";
    String[] mTokens = path.split(mDelims);
    String mResult = "/";
    int mTemp;
    if (path.endsWith("/"))
      mTemp = 1;
    else
      mTemp = 2;
    for (int i = 0; i < mTokens.length; i++) {

      if (i > 0 && i < (mTokens.length - mTemp)) {
        mResult = mResult.concat(mTokens[i] + "/");
      }
    }

    return mResult;

  }

  /**
   * It refreshes the directory contents of the ListView selected.
   * 
   * @param view
   *            The ListView (representing an endpoint's directory) we want to
   *            act on
   */
  public void refresh(View view) {
    if (view.getId() == R.id.refresh_A_button) {
      if (!mSelectEndpointAButton.getText().toString()
          .contentEquals(getString(R.string.select_endpoint_prompt))) {
        mAListView.setAdapter(null);
        mAListView.setVisibility(View.INVISIBLE);
        mEndpointAProgressBar.setVisibility(View.VISIBLE);
        new GetEndpointsDirectory("a", mSelectEndpointAButton.getText()
            .toString()).execute();
      } else {
        makeToast(getString(R.string.no_endpoint_selected_warning),
            Toast.LENGTH_SHORT);
      }

    } else if (view.getId() == R.id.refresh_B_button) {
      if (!mSelectEndpointBButton.getText().toString()
          .contentEquals(getString(R.string.select_endpoint_prompt))) {
        mBListView.setAdapter(null);
        mBListView.setVisibility(View.INVISIBLE);
        mEndpointBProgressBar.setVisibility(View.VISIBLE);
        new GetEndpointsDirectory("b", mSelectEndpointBButton.getText()
            .toString()).execute();
      } else {
        makeToast(getString(R.string.no_endpoint_selected_warning),
            Toast.LENGTH_SHORT);
      }
    }

  }

  /**
   * Returns a string containing the size of a file converted to KBs, MBs, GBs
   * or just bytes according to its size.
   * 
   * @param size
   *            The given file size in bytes
   * @return The file size along with the appropriate unit of size
   */
  public String sizeFromBytes(Float size) {

    String mSizeResult = "0b";

    final float KB = 1024;
    final float MB = 1024 * KB;
    final float GB = 1024 * MB;

    if (size < KB) {
      mSizeResult = String.format("%.0f", size).concat(" b");
    } else if (KB <= size && size < MB) {
      size = size / KB;

      mSizeResult = String.format("%.0f", size).concat(" KB");
    } else if (MB <= size && size < GB) {
      size = size / MB;

      mSizeResult = String.format("%.0f", size).concat(" MB");
    } else if (size >= GB) {
      size = size / GB;
      mSizeResult = String.format("%.1f", size).concat(" GB");
    }

    return mSizeResult.concat(" ");
  }

  /**
   * Creates a dialog asking from the user to type a label for the transfer to
   * be initiated. If the source or the destination Endpoints have not been
   * selected, or if the are no files selected in the source Endpoint
   * directory List View, it warns the user with Toasts containing the
   * corresponding warning messages. If the the user types a valid label or no
   * label at all and clicks the "OK" button in the dialog, the execute method
   * of the fileTransfer class is called.
   * 
   * @param view
   *            The Transfer Button clicked
   */
  public void makeTransfer(View view) {
    int mIdButton = ((Button) view).getId();
    String mNoEndpoint = getString(R.string.select_endpoint_prompt);

    if (mSelectEndpointBButton.getText() == mNoEndpoint
        || mSelectEndpointAButton.getText() == mNoEndpoint) {

      return;
    }
    if (mIdButton == R.id.transfer_A_to_B_button) {
      mNode = "a";
      if (mSelectedFilesA.isEmpty()) {

        return;
      }
    } else if (mIdButton == R.id.transfer_B_to_A_button) {
      mNode = "b";
      if (mSelectedFilesB.isEmpty()) {

        return;
      }
    }

    mMakeTransferDialog = new Dialog(this);
    mMakeTransferDialog.setCanceledOnTouchOutside(false);
    mMakeTransferDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    mMakeTransferDialog.setContentView(R.layout.make_transfer_dialog);
    mMakeTransferEditText = (EditText) mMakeTransferDialog
        .findViewById(R.id.transfer_name_edit_text);
    mMakeTransferOkButton = (Button) mMakeTransferDialog
        .findViewById(R.id.ok_button);
    mMakeTransferDialog.show();
    mMakeTransferOkButton.setOnClickListener(new OnClickListener()

    {

      @Override
      public void onClick(View arg0) {

        mTransferName = mMakeTransferEditText.getText().toString();
        mMakeTransferEditText.setText("");
        if (mTransferName.contains("\n")) {
          makeToast(
              getString(R.string.no_escape_characters_allowed_warning),
              Toast.LENGTH_SHORT);
        } else {
          mMakeTransferDialog.dismiss();
          new FilesTransfer(mNode, mTransferName).execute();
        }
      }

    });

  }

  /**
   * 
   * This adapter is a custom adapter used for populating the List View
   * representing the endpoints' directories. In every row of the List it puts
   * the name of the file/folder, along with its appropriate icon based on
   * whether it is a file or a folder, its size if it is a file or the word
   * "Folder" if it is a folder, as well as paints the background light blue
   * or white, depending on whether the specific file or folder is selected by
   * the user or not.
   * 
   * @author christos
   * 
   */
  public class CustomAdapter extends ArrayAdapter<String> {

    private Context mLocalContext;

    public CustomAdapter(Context context, int textViewResourceId,
        List<String> objects) {
      super(context, textViewResourceId, objects);
      this.mLocalContext = context;

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

      String mFile = (String) this.getItem(position);
      View mRow = convertView;

      if (mRow == null) {
        LayoutInflater vi = (LayoutInflater) mLocalContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mRow = vi.inflate(R.layout.directory_list_view, null);
      }

      TextView mFilenameTextView = (TextView) mRow
          .findViewById(R.id.file_name_in_list_text_view);
      ImageView mFileTypeImageView = (ImageView) mRow
          .findViewById(R.id.file_type_in_list);
      TextView mFileSize = (TextView) mRow
          .findViewById(R.id.file_size_in_text_view);

      // If the file's name ends with "/" it is assigned the folder icon;
      // otherwise it is assigned the file icon
      if (mFile.endsWith("/")) {
        mFileTypeImageView.setImageResource(R.drawable.folder);
        mFileSize.setText(getString(R.string.folder));
      } else {
        mFileTypeImageView.setImageResource(R.drawable.file);
        float mTemp = 0;

        // The file's size is retrieved
        if (parent.getId() == R.id.endpoint_A_list_view) {
          if (mFilesSizeA.containsKey(mFile))
            mTemp = mFilesSizeA.get(mFile);
        } else if (parent.getId() == R.id.endpoint_B_list_view) {
          if (mFilesSizeB.containsKey(mFile))
            mTemp = mFilesSizeB.get(mFile);
        }

        // The file's size is converted to the appropriate unit of size
        String mSizeString = sizeFromBytes(mTemp);

        // The file's size is set
        mFileSize.setText(mSizeString);

      }

      // The file/folder's background color is set to either light blue or
      // white, depending on whether it is selected or not
      if (parent.getId() == R.id.endpoint_A_list_view) {
        if (mSelectedFilesA.contains(mFile)) {
          mRow.setBackgroundColor(getResources().getColor(
              R.color.android_light_blue));
        } else {
          mRow.setBackgroundColor(Color.WHITE);
        }
      } else if (parent.getId() == R.id.endpoint_B_list_view) {
        if (mSelectedFilesB.contains(mFile)) {
          mRow.setBackgroundColor(getResources().getColor(
              R.color.android_light_blue));
        } else {
          mRow.setBackgroundColor(Color.WHITE);

        }

      }

      // The file's name text view is set
      mFilenameTextView.setText(mFile);
      return mRow;
    }

  }

  /**
   * This class attempts to create a new directory by POSTing a JSON object
   * containing the new folder's name to endpoint/<canonical_name>/mkdir. It
   * informs the user with a Toast for the request's result, and if it's
   * successful it refreshes the corresponding endpoint's directory.
   * 
   * @author christos
   * 
   */
  public class DirectoryCreation extends AsyncTask<String, Void, String> {

    String mLocalNode, mLocalfolderName;

    /**
     * Constructor. It sets the node where the directory should be created
     * and the name of the new folder.
     * 
     * @param node
     *            The node (Endpoint A or B) where the directory should be
     *            created
     * @param folderName
     *            The name of the new folder
     */
    public DirectoryCreation(String node, String folderName) {
      this.mLocalNode = node;
      this.mLocalfolderName = folderName;

    }

    @Override
    protected String doInBackground(String... args) {

      String mResult = getString(R.string.error);
      String mTargetPath = "";
      String mEndpoint = "";

      // The path and the endpoint's name are retrieved
      if (mLocalNode.contentEquals("a")) {
        mTargetPath = mEndpointACurrentPath;
        mEndpoint = mSelectEndpointAButton.getText().toString();
      } else if (mLocalNode.contentEquals("b")) {
        mTargetPath = mEndpointBCurrentPath;
        mEndpoint = mSelectEndpointBButton.getText().toString();

      }

      // The endpoint's canonical name is split into user's name and
      // endpoint's name in order to replace
      // "#" with "%23" for encoding reasons
      String mDelims = "#";
      String[] tokens = mEndpoint.split(mDelims);
      Result mQueryResult;
      try {

        JSONObject mSubmit = new JSONObject();
        mSubmit.put("path", mTargetPath + mLocalfolderName);
        mSubmit.put("DATA_TYPE", "mkdir");

        // The directory creation request is POSTed to the API along
        // with a JSON Object containing
        // information about the path and the new folder's name
        mQueryResult = sClient.postResult("/endpoint/" + tokens[0]
            + "%23" + tokens[1] + "/mkdir", mSubmit);
        JSONObject mJsonObject = mQueryResult.document;

        if (!mJsonObject.getString("DATA_TYPE").equals("mkdir_result")) {
          return mResult;
        }

        // The message String is retrieved and returned
        mResult = mJsonObject.getString("message");
        return mResult;
      } catch (MalformedURLException e) {

        e.printStackTrace();
        mResult = e.getMessage();
      } catch (IOException e) {

        e.printStackTrace();
        mResult = e.getMessage();
      } catch (GeneralSecurityException e) {

        e.printStackTrace();
        mResult = e.getMessage();
      } catch (JSONException e) {

        e.printStackTrace();
        mResult = e.getMessage();
      } catch (APIError e) {

        e.printStackTrace();
        mResult = e.message;

      }

      return mResult;
    }

    @Override
    protected void onPostExecute(String result) {

      super.onPostExecute(result);

      // The user is informed of the outcome of their request with a Toast message
      makeToast(result, Toast.LENGTH_LONG);

      // If the directory is successfully created, the endpoint's contents
      // are reloaded
      if (result.contentEquals("The directory was created successfully")) {
        if (mLocalNode.contentEquals("a")) {
          mAListView.setAdapter(null);
          mAListView.setVisibility(View.INVISIBLE);
          mEndpointAProgressBar.setVisibility(View.VISIBLE);
          new GetEndpointsDirectory(mLocalNode,
              mSelectEndpointAButton.getText().toString())
              .execute();
        } else if (mLocalNode.contentEquals("b")) {
          mBListView.setAdapter(null);
          mBListView.setVisibility(View.INVISIBLE);
          mEndpointBProgressBar.setVisibility(View.VISIBLE);
          new GetEndpointsDirectory(mLocalNode,
              mSelectEndpointBButton.getText().toString())
              .execute();

        }

      }

    }

  }

  /**
   * This class tries to delete the files selected by the user. It first gets
   * a submission id by sending GET /submission_id. Once the submission id is
   * acquired, it POSTs a JSON Object to /delete, containing the submission
   * id, the deletion task's name, the endpoint's name, an JSONArray
   * containing the paths of the files/folders that are to be deleted and a
   * flag indicating whether there should be recursive file deletion or not.
   * It informs the user for the request's result with a Toast.
   * 
   * @author christos
   */
  public class FileDeletion extends AsyncTask<String, Void, List<String>> {

    String mLocalNode;
    String mLocalDeletionName;

    /**
     * Constructor. Sets the node (Endpoint A or B) we want to delete
     * files/folders from and the name of the deletion task.
     * 
     * @param node
     *            The node (Endpoint A or B) we want do delete files/folders
     *            from
     * @param deletionName
     *            The name of the deletion task
     */
    public FileDeletion(String node, String deletionName) {
      this.mLocalNode = node;
      this.mLocalDeletionName = deletionName;
    }

    @Override
    protected void onPreExecute() {

      super.onPreExecute();

      // The user is informed with a Toast message that the deletion
      // request has been submitted
      makeToast(getString(R.string.delete_request_submitted),
          Toast.LENGTH_SHORT);
    }

    @Override
    protected List<String> doInBackground(String... args) {

      String mId;
      List<String> mMessage = new ArrayList<String>();
      boolean mContainsFolders = false;
      try {
        List<String> mTargetPath = new ArrayList<String>();
        String mEndpoint = null;
        Result mQueryResult;

        // A GET request is send to the API in order to acquire a
        // submission id, necessary for submitting any transfer
        // or deletion task.
        mQueryResult = sClient.getResult("/submission_id");

        JSONObject mJsonObject = mQueryResult.document;

        if (!mJsonObject.getString("DATA_TYPE").equals("submission_id")) {
          mMessage.add(getString(R.string.error));
          return mMessage;
        }
        mId = mJsonObject.getString("value");

        // The selected files for deletion are added to the Target Path
        // List.
        // A flag indicates whether there are any folders selected or not
        if (mLocalNode.contentEquals("a")) {
          for (int i = 0; i < mSelectedFilesA.size(); i++) {
            mTargetPath.add(mEndpointACurrentPath
                .concat(mSelectedFilesA.get(i)));
            if (mSelectedFilesA.get(i).endsWith("/"))
              mContainsFolders = true;
          }
          mEndpoint = mSelectEndpointAButton.getText().toString();
        } else if (mLocalNode.contentEquals("b")) {
          for (int i = 0; i < mSelectedFilesB.size(); i++) {
            mTargetPath.add(mEndpointBCurrentPath
                .concat(mSelectedFilesB.get(i)));
            if (mSelectedFilesB.get(i).endsWith("/"))
              mContainsFolders = true;
          }
          mEndpoint = mSelectEndpointBButton.getText().toString();

        }

        Result mResult;

        // All the paths of the files to be deleted are put in a
        // JSON Array
        JSONArray mJArray = new JSONArray();
        for (int i = 0; i < mTargetPath.size(); i++) {
          JSONObject mTemp = new JSONObject();
          mTemp.put("path", mTargetPath.get(i));
          mTemp.put("DATA_TYPE", "delete_item");
          mJArray.put(mTemp);
        }

        // A JSON Object is created containing the submission id, the
        // endpoint to delete files from,
        // a flag indicating the existence of folders, the deletion
        // task's label and the JSON Array containing
        // the files' and folders' paths
        JSONObject mSubmit = new JSONObject();
        mSubmit.put("submission_id", mId);
        mSubmit.put("endpoint", mEndpoint);
        mSubmit.put("recursive", mContainsFolders);

        if (!mLocalDeletionName.isEmpty()) {
          mSubmit.put("label", mLocalDeletionName);
        }

        mSubmit.put("DATA_TYPE", "delete");
        mSubmit.put("ingore_missing", false);
        mSubmit.put("DATA", mJArray);

        // The deletion request is POSTed to the API along with the JSON
        // Object containing all the relevant information
        mResult = sClient.postResult("delete", mSubmit);
        JSONObject mJsonObject2 = mResult.document;

        // The message String returned by the API is retrieved and returned
        mMessage.add(mJsonObject2.getString("message"));
        mMessage.add(mJsonObject2.getString("code"));

        return mMessage;
      } catch (MalformedURLException e) {
        e.printStackTrace();
        mMessage.add(e.getMessage());
      } catch (IOException e) {
        e.printStackTrace();
        mMessage.add(e.getMessage());
      } catch (GeneralSecurityException e) {
        e.printStackTrace();
        mMessage.add(e.getMessage());
      } catch (JSONException e) {
        e.printStackTrace();
        mMessage.add(e.getMessage());
      } catch (APIError e) {
        e.printStackTrace();
        mMessage.add(e.message);
      }

      return mMessage;
    }

    @Override
    protected void onPostExecute(List<String> result) {

      super.onPostExecute(result);

      // The user is informed of their request's outcome with a Toast message
      makeToast(result.get(0), Toast.LENGTH_LONG);

    }

  }

  /**
   * This class attempts to get the contents of a specific endpoint's
   * directory by sending a GET request to endpoint/<canonical_name>/ls along
   * with request parameters containing the path we want to access. It makes
   * the corresponding ListView invisible and puts a progress bar on its place
   * while communicating with the Server. If it gets the directory's contents
   * successfully it presents them through the corresponding List View.
   * Otherwise it informs the user for any error that may have occurred, and
   * if the case is that the Endpoint is not activated, it calls the execute
   * function of the AutoActivate class.
   * 
   * 
   * @author christos
   * 
   */
  public class GetEndpointsDirectory extends
      AsyncTask<String, Void, ArrayList<String>> {

    String mLocalNode;
    String mLocalEndpoint;

    /**
     * Constructor. It sets the node (Endpoint A or B) we want to the
     * directory information about and the name of the endpoint.
     * 
     * @param node
     * @param endpoint
     */
    public GetEndpointsDirectory(String node, String endpoint) {
      this.mLocalNode = node;
      this.mLocalEndpoint = endpoint;
    }

    @Override
    protected void onPreExecute() {

      super.onPreExecute();

      if (mLocalNode.contentEquals("a")) {

        mAListView.setAdapter(null);
        mTransferAButton.setBackgroundResource(R.drawable.down);
        mPathATextView.setText(mEndpointACurrentPath);
        mAListView.setVisibility(View.INVISIBLE);
        mEndpointAProgressBar.setVisibility(View.VISIBLE);
        mLastTimePressedA.clear();
        mFilesSizeA.clear();

      } else if (mLocalNode.contentEquals("b")) {

        mBListView.setAdapter(null);
        mTransferBButton.setBackgroundResource(R.drawable.up);
        mPathBTextView.setText(mEndpointBCurrentPath);
        mBListView.setVisibility(View.INVISIBLE);
        mEndpointBProgressBar.setVisibility(View.VISIBLE);
        mLastTimePressedB.clear();
        mFilesSizeB.clear();

      }
    }

    @Override
    protected ArrayList<String> doInBackground(String... args) {

      ArrayList<String> mDirectoryList = new ArrayList<String>();
      Map<String, String> mRequestParams = new HashMap<String, String>();

      // The current path of the endpoint is retrieved
      if (mLocalNode.contentEquals("a")) {
        mRequestParams.put("path", mEndpointACurrentPath);
      } else if (mLocalNode.contentEquals("b")) {
        mRequestParams.put("path", mEndpointBCurrentPath);
      }

      // The "show hidden files" filter is set according the user's
      // settings
      if (!mSharedPreferences.getBoolean("ShowHiddenFiles", false)) {
        mRequestParams.put("show_hidden", "False");
      }

      // The endpoint's canonical name is split into user's name and
      // endpoint's name in order to replace
      // "#" with "%23" for encoding reasons
      String mDelims = "#";
      String[] mTokens = mLocalEndpoint.split(mDelims);
      Result mQueryResult;
      try {

        // The GET request is sent to the API along with a JSON Object
        // containing all the relative parameters
        mQueryResult = sClient.getResult("/endpoint/" + mTokens[0]
            + "%23" + mTokens[1] + "/ls", mRequestParams);
        JSONObject jO = mQueryResult.document;

        if (!jO.getString("DATA_TYPE").equals("file_list")) {

          mDirectoryList.add("");
          return mDirectoryList;
        }

        // The JSON Array DATA is retrieved
        JSONArray mJsonArray = jO.getJSONArray("DATA");
        JSONObject mJsonObject;

        for (int i = 0; i < mJsonArray.length(); i++) {
          mJsonObject = mJsonArray.getJSONObject(i);
          String mLocalEndpoint;
          Float mSize;

          // If the file is a directory (folder) an "/" is postfixed
          // to its name
          if (mJsonObject.getString("type").contentEquals("dir")) {

            mLocalEndpoint = mJsonObject.getString("name") + "/";
          } else {
            mLocalEndpoint = mJsonObject.getString("name");
            mSize = Float.parseFloat(mJsonObject.getString("size"));
            if (mLocalNode.contentEquals("a")) {
              mFilesSizeA.put(mLocalEndpoint, mSize);
            } else if (mLocalNode.contentEquals("b")) {
              mFilesSizeB.put(mLocalEndpoint, mSize);
            }
          }
          // The file/folder is added to the directory list
          mDirectoryList.add(mLocalEndpoint);
        }

        // The list containing all the contents of the current path is
        // returned
        return mDirectoryList;
      } catch (MalformedURLException e) {

        e.printStackTrace();
        mDirectoryList.add("Error");
        mDirectoryList.add(e.getMessage());
      } catch (IOException e) {

        e.printStackTrace();
        mDirectoryList.add("Error");
        mDirectoryList.add(e.getMessage());
      } catch (GeneralSecurityException e) {

        e.printStackTrace();
        mDirectoryList.add("Error");
        mDirectoryList.add(e.getMessage());
      } catch (JSONException e) {

        e.printStackTrace();
        mDirectoryList.add("Error");
        mDirectoryList.add(e.getMessage());
      } catch (APIError e) {

        e.printStackTrace();
        mDirectoryList.add("Error");
        mDirectoryList.add(e.message);

      }

      return mDirectoryList;

    }

    @Override
    protected void onPostExecute(ArrayList<String> result) {

      super.onPostExecute(result);

      // The Custom Adapter we have created populates the list with the
      // files and folders
      // as they were retrieved from the communication with the API
      ArrayAdapter adapter = new CustomAdapter(mContext,
          android.R.layout.simple_list_item_1, result);
      String mCode = "";
      if (result.size() > 0) {
        mCode = result.get(0);
      }

      if (mLocalNode.contentEquals("a")) {

        if (!mCode.contentEquals("Error")) {
          mAListView.setAdapter(adapter);
          mFileListA = result;

        } else {

          // If the endpoint is not activated, the user is informed
          // with a Toast message and the execute method
          // of the AutoActivate class is called
          makeToast(result.get(1), Toast.LENGTH_LONG);
          if (result.get(1).endsWith("not activated"))
            new AutoActivate("a", mLocalEndpoint)
                .execute(mActivationRequirements);
        }

        mAListView.setVisibility(View.VISIBLE);
        mEndpointAProgressBar.setVisibility(View.GONE);
        mSelectedFilesA.clear();

      } else if (mLocalNode.contentEquals("b")) {

        if (!mCode.contentEquals("Error")) {
          mBListView.setAdapter(adapter);
          mFileListB = result;
        } else {
          
          // If the endpoint is not activated, the user is informed
          // with a Toast message and the execute method
          // of the AutoActivate class is called
          makeToast(result.get(1), Toast.LENGTH_LONG);
          if (result.get(1).endsWith("not activated"))
            new AutoActivate("b", mLocalEndpoint)
                .execute(mActivationRequirements);
        }
        mBListView.setVisibility(View.VISIBLE);
        mEndpointBProgressBar.setVisibility(View.GONE);
        mSelectedFilesB.clear();

      }

    }

  }

  /**
   * 
   * 
   * This class attempts to get the list of all the endpoints visible to the
   * user by sending a GET request to endpoint_list. It hides all the view
   * from the screen while communicating with the server and instead shows a
   * progress bar.
   * 
   * @author christos
   */
  public class GetEndpointsList extends
      AsyncTask<String, Void, ArrayList<String>> {

    @Override
    protected void onPreExecute() {
      mEndpointLoadProgressBar.setProgress(0);
      super.onPreExecute();

      // Everything on the screen temporarily disappears and a Progress
      // Bar along with a Text message take their place
      mSelectEndpointAButton.setVisibility(View.INVISIBLE);
      mSelectEndpointBButton.setVisibility(View.INVISIBLE);
      mAListView.setVisibility(View.INVISIBLE);
      mBListView.setVisibility(View.INVISIBLE);
      mATextView.setVisibility(View.INVISIBLE);
      mBTextView.setVisibility(View.INVISIBLE);
      mUpAButton.setVisibility(View.INVISIBLE);
      mUpBButton.setVisibility(View.INVISIBLE);
      mCreateAButton.setVisibility(View.INVISIBLE);
      mCreateBButton.setVisibility(View.INVISIBLE);
      mDeleteAButton.setVisibility(View.INVISIBLE);
      mDeleteBButton.setVisibility(View.INVISIBLE);
      mRefreshAButton.setVisibility(View.INVISIBLE);
      mRefreshBButton.setVisibility(View.INVISIBLE);
      mEndpointLoadProgressBar.setVisibility(View.VISIBLE);
      mPathATextView.setVisibility(View.INVISIBLE);
      mPathBTextView.setVisibility(View.INVISIBLE);
      mTransferAButton.setVisibility(View.INVISIBLE);
      mTransferBButton.setVisibility(View.INVISIBLE);

      TextView mLoadMessage = (TextView) findViewById(R.id.loading_endpoints_textview);
      mLoadMessage.setVisibility(View.VISIBLE);

    }

    @Override
    protected ArrayList<String> doInBackground(String... arg0) {

      List<String> mEndpoints = new ArrayList<String>();

      Map<String, String> mRequestParams = new HashMap<String, String>();
      mRequestParams.put("limit", "0");
      mRequestParams.put("fields", "canonical_name");

      // It is decided whether all of the endpoints will be returned or
      // only the active ones, based on the user's settings
      if (mSharedPreferences.getBoolean("EndpointsActiveOnly", true)) {
        mRequestParams.put("filter", "activated:true");
      }

      // The Bar's Progress is updated
      mEndpointLoadProgressBar.setProgress(1);
      Result mQueryResult;
      try {

        // The GET request is sent to the API along with all the
        // relevant parameters
        mQueryResult = sClient.getResult("/endpoint_list",
            mRequestParams);

        mEndpointLoadProgressBar.setProgress(2);
        JSONObject mJsonObject = mQueryResult.document;

        if (!mJsonObject.getString("DATA_TYPE").equals("endpoint_list")) {
          mEndpoints.add(getString(R.string.error));
          return (ArrayList<String>) mEndpoints;
        }

        // The DATA JSON Array is retrieved
        JSONArray mJsonArray = mJsonObject.getJSONArray("DATA");

        mEndpointLoadProgressBar.setProgress(3);
        
        // The endpoints are added to the mEndpoints Array List
        for (int i = 0; i < mJsonArray.length(); i++) {

          String endpoint = mJsonArray.getJSONObject(i).getString(
              "canonical_name");
          mEndpoints.add(endpoint);

        }

        mEndpointLoadProgressBar.setProgress(4);

      } catch (MalformedURLException e) {
        e.printStackTrace();
        mEndpoints.add(getString(R.string.error));
        mEndpoints.add(e.getMessage());
      } catch (IOException e) {
        e.printStackTrace();
        mEndpoints.add(getString(R.string.error));
        mEndpoints.add(e.getMessage());
      } catch (GeneralSecurityException e) {
        e.printStackTrace();
        mEndpoints.add(getString(R.string.error));
        mEndpoints.add(e.getMessage());
      } catch (JSONException e) {
        e.printStackTrace();
        mEndpoints.add(getString(R.string.error));
        mEndpoints.add(e.getMessage());
      } catch (APIError e) {
        e.printStackTrace();
        mEndpoints.add(getString(R.string.error));
        mEndpoints.add(e.message);
      }

      return (ArrayList<String>) mEndpoints;
    }

    @Override
    protected void onPostExecute(ArrayList<String> result) {

      super.onPostExecute(result);

      // The Progress Bar and Text disappear and everything else appears
      // back on the screen
      mSelectEndpointAButton.setVisibility(View.VISIBLE);
      mSelectEndpointBButton.setVisibility(View.VISIBLE);
      mAListView.setVisibility(View.VISIBLE);
      mBListView.setVisibility(View.VISIBLE);
      mATextView.setVisibility(View.VISIBLE);
      mBTextView.setVisibility(View.VISIBLE);
      mUpAButton.setVisibility(View.VISIBLE);
      mUpBButton.setVisibility(View.VISIBLE);
      mCreateAButton.setVisibility(View.VISIBLE);
      mCreateBButton.setVisibility(View.VISIBLE);
      mDeleteAButton.setVisibility(View.VISIBLE);
      mDeleteBButton.setVisibility(View.VISIBLE);
      mRefreshAButton.setVisibility(View.VISIBLE);
      mRefreshBButton.setVisibility(View.VISIBLE);
      mPathATextView.setVisibility(View.VISIBLE);
      mPathBTextView.setVisibility(View.VISIBLE);
      mTransferAButton.setVisibility(View.VISIBLE);
      mTransferBButton.setVisibility(View.VISIBLE);

      mEndpoints = (ArrayList<String>) result.clone();
      TextView loadMessage = (TextView) findViewById(R.id.loading_endpoints_textview);
      loadMessage.setVisibility(View.GONE);
      mEndpointLoadProgressBar.setVisibility(View.GONE);

    }

  }

  /**
   * This class attempts to transfer the files selected by the user from the
   * one Endpoint to the other. It first gets a submission id by sending GET
   * /submission_id. Once the submission id is acquired, it POSTs a JSON
   * Object to /transfer, containing the submission id, the transfer task's
   * name(if any), the source endpoint's name, the destination endpoint's name
   * and a JSONArray containing the paths of the files/folders that are to be
   * transfered along with the paths that they are bound to be transferred to.
   * It informs the user for the request's result with a Toast.
   * 
   * 
   * 
   * @author christos
   * 
   */
  public class FilesTransfer extends AsyncTask<String, Void, List<String>> {

    String mLocalNode;
    String mLocaltransferName;

    /**
     * Constructor. It sets the node (Endpoint A or B) that we want to
     * transfer files from as well as the name of the transfer task. *
     * 
     * @param node
     * @param transferName
     */
    public FilesTransfer(String node, String transferName) {
      this.mLocalNode = node;
      this.mLocaltransferName = transferName;
    }

    @Override
    protected void onPreExecute() {

      super.onPreExecute();

      // The user is informed that their transfer request has been
      // submitted
      makeToast(getString(R.string.transfer_request_submitted),
          Toast.LENGTH_SHORT);
    }

    @Override
    protected List<String> doInBackground(String... arg0) {

      String mId;
      List<String> mMessage = new ArrayList<String>();
      try {

        Map<String, String> mPaths = new HashMap<String, String>();
        String mSourceEndpoint = null;
        String mDestinationEndpoint = null;
        Result mQueryResult;

        // A GET request is send to the API in order to acquire a
        // submission id, necessary for submitting any transfer
        // or deletion task
        mQueryResult = sClient.getResult("/submission_id");

        JSONObject mJsonObject = mQueryResult.document;

        if (!mJsonObject.getString("DATA_TYPE").equals("submission_id")) {
          mMessage.add(getString(R.string.error));
          return mMessage;
        }
        mId = mJsonObject.getString("value");

        // The mPaths HashMap is populated with the paths of the files
        // folders to be transferred
        if (mLocalNode.contentEquals("a")) {
          for (int i = 0; i < mSelectedFilesA.size(); i++) {

            mPaths.put(mEndpointACurrentPath.concat(mSelectedFilesA
                .get(i)), mEndpointBCurrentPath
                .concat(mSelectedFilesA.get(i)));

          }

          mSourceEndpoint = mSelectEndpointAButton.getText()
              .toString();
          mDestinationEndpoint = mSelectEndpointBButton.getText()
              .toString();

        }
        
        // The mPaths HashMap is populated with the paths of the files
        // folders to be transferred
        else if (mLocalNode.contentEquals("b")) {
          for (int i = 0; i < mSelectedFilesB.size(); i++) {

            mPaths.put(mEndpointBCurrentPath.concat(mSelectedFilesB
                .get(i)), mEndpointACurrentPath
                .concat(mSelectedFilesB.get(i)));
          }
          mSourceEndpoint = mSelectEndpointBButton.getText()
              .toString();
          mDestinationEndpoint = mSelectEndpointAButton.getText()
              .toString();

        }

        Result mResult;
        JSONArray mJsonArray = new JSONArray();

        // A JSON Array is created containing for every transfer the
        // source path, the destination path
        // and a flag defining whether the item sent is a file or a
        // folder
        for (Map.Entry<String, String> entry : mPaths.entrySet()) {
          JSONObject temp = new JSONObject();
          String mSourcePath = entry.getKey();
          String mDestinationPath = entry.getValue();
          temp.put("source_path", mSourcePath);
          temp.put("DATA_TYPE", "transfer_item");
          temp.put("destination_path", mDestinationPath);
          if (mSourcePath.endsWith("/"))
            temp.put("recursive", true);
          else
            temp.put("recursice", false);
          mJsonArray.put(temp);
        }

        // A JSON Object is created containing the submission id the
        // source and destination endpoints, the transfer task's
        // label (if any) and the JSON Array DATA created above
        JSONObject mSubmit = new JSONObject();
        mSubmit.put("submission_id", mId);
        mSubmit.put("source_endpoint", mSourceEndpoint);
        mSubmit.put("destination_endpoint", mDestinationEndpoint);
        mSubmit.put("DATA_TYPE", "transfer");

        if (!mLocaltransferName.isEmpty()) {
          mSubmit.put("label", mLocaltransferName);
        }

        mSubmit.put("DATA", mJsonArray);

        // The transfer request is POSTed to the API along with a JSON
        // Object containing all the relevant information
        mResult = sClient.postResult("transfer", mSubmit);
        JSONObject jsonObject = mResult.document;

        // The message String is retrieved and returned
        mMessage.add(jsonObject.getString("message"));
        mMessage.add(jsonObject.getString("code"));

        return mMessage;
      } catch (MalformedURLException e) {
        e.printStackTrace();
        mMessage.add(e.getMessage());
      } catch (IOException e) {
        e.printStackTrace();
        mMessage.add(e.getMessage());
      } catch (GeneralSecurityException e) {
        e.printStackTrace();
        mMessage.add(e.getMessage());
      } catch (JSONException e) {
        e.printStackTrace();
        mMessage.add(e.getMessage());
      } catch (APIError e) {
        e.printStackTrace();
        mMessage.add(e.message);
      }

      return mMessage;
    }

    @Override
    protected void onPostExecute(List<String> result) {

      super.onPostExecute(result);

      // The user is informed of their request's outcome with a Toast
      // message
      makeToast(result.get(0), Toast.LENGTH_LONG);

    }

  }

  /**
   * This class attempts to autoactivate an Endpoint, in case it is not
   * activated, by POSTing and empty JSON Object to
   * endpoint/<canonical_name>/autoactivate. In case the Endpoint can not be
   * auto activated, it creates a dialog prompting the user to enter the
   * credentials needed for the Endpoint to be activated. If the user types
   * the necessary credentials and clicks the "Activate" button, the execution
   * function of the Activate class is called.
   * 
   * @author christos
   * 
   */
  public class AutoActivate extends
      AsyncTask<JSONObject, Void, ArrayList<String>> {

    String mLocalNode;
    String mEndpoint;

    /**
     * Constructor. Sets the node (Endpoint A or B) to be autoactivated and
     * the Endpoint's name.
     * 
     * @param node
     *            The node to be autoactivated
     * @param endpoint
     *            The Endpoint's name to be autoactivated
     */
    public AutoActivate(String node, String endpoint) {
      this.mLocalNode = node;
      this.mEndpoint = endpoint;
      mActivationRequirements = null;
    }

    @Override
    protected ArrayList<String> doInBackground(JSONObject... args) {

      ArrayList<String> mResult = new ArrayList<String>();

      // The endpoint's canonical name is split into user's name and
      // endpoint's name in order to replace
      // "#" with "%23" for encoding reasons
      String mDelims = "#";
      String[] mTokens = mEndpoint.split(mDelims);

      Result mQueryResult;
      try {

        JSONObject mEmptyJsonObject = args[0];

        // The user's request is POSTed to the API along with an empty
        // JSON Object
        mQueryResult = sClient.postResult("/endpoint/" + mTokens[0]
            + "%23" + mTokens[1] + "/autoactivate",
            mEmptyJsonObject);
        JSONObject mJsonObject = mQueryResult.document;

        if (!mJsonObject.getString("DATA_TYPE").equals(
            "activation_result")) {
          mResult.add(getString(R.string.error));
          mResult.add(getString(R.string.error));
          return mResult;
        }

        // The message returned from the API is retrieved
        mResult.add(mJsonObject.getString("code"));
        mResult.add(mJsonObject.getString("message"));

        // If the message does not state that the endpoint has been auto
        // activated, the mJsonObject is retrieved
        // because it containts information about the -manual-
        // activation requirements
        if (!mResult.get(0).startsWith("AutoActivated")) {
          mActivationRequirements = mJsonObject;

        }

      } catch (MalformedURLException e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.getMessage());
      } catch (IOException e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.getMessage());
      } catch (GeneralSecurityException e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.getMessage());
      } catch (JSONException e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.getMessage());
      } catch (APIError e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.message);

      }

      return mResult;
    }

    @Override
    protected void onPostExecute(ArrayList<String> result) {

      super.onPostExecute(result);

      final JSONArray mJSONArray;

      // If the endpoint has been autoactivated the user is informed with
      // a Toast message
      // and its contents are loaded
      if (result.get(0).startsWith("AutoActivated")) {
        new GetEndpointsDirectory(mLocalNode, mEndpoint).execute();
        makeToast(result.get(1), Toast.LENGTH_LONG);
      }
      // If the endpoint has not been auto activated a Dialog Window is
      // created prompting the user to
      // type the necessary information in order to activate the endpoint
      else {
        String title = "";

        mActivateDialog = new Dialog(mContext);
        mActivateDialog.setCanceledOnTouchOutside(false);
        mActivateDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        mActivateDialog.setContentView(R.layout.activate_dialog);
        TextView mTitleTextView = (TextView) mActivateDialog
            .findViewById(R.id.activate_title_id);

        LinearLayout layout = (LinearLayout) mActivateDialog
            .findViewById(R.id.linear);

        final Map<Integer, EditText> mEditTextMap = new HashMap<Integer, EditText>();
        final Map<Integer, TextView> mTextViewMap = new HashMap<Integer, TextView>();
        try {
          mJSONArray = mActivationRequirements.getJSONArray("DATA");
          int size = mJSONArray.length();
          title = mActivationRequirements.getString("endpoint");
          for (int i = 0; i < size; i++) {
            JSONObject mTempObject = mJSONArray.getJSONObject(i);
            if (!mTempObject.getString("type").contentEquals(
                "delegate_proxy")) {

              TextView mTextView = new TextView(mContext);
              EditText mEditText = new EditText(mContext);

              // If the field is marked as "required" a * is put
              // next to the field's name
              if (!mTempObject.getBoolean("required")) {
                mTextView.setText(mTempObject
                    .getString("ui_name"));
              } else {
                mTextView.setText("*"
                    + mTempObject.getString("ui_name"));
              }
              String mValue = mTempObject.getString("value");

              if (!mValue.contentEquals("null")) {
                mEditText.setText(mValue);

              }
              mTextView.setLayoutParams(new LayoutParams(
                  ViewGroup.LayoutParams.WRAP_CONTENT,
                  ViewGroup.LayoutParams.WRAP_CONTENT));
              mEditText.setLayoutParams(new LayoutParams(
                  ViewGroup.LayoutParams.MATCH_PARENT,
                  ViewGroup.LayoutParams.WRAP_CONTENT));
              if (mTempObject.getBoolean("private")) {
                mEditText
                    .setInputType(InputType.TYPE_CLASS_TEXT
                        | InputType.TYPE_TEXT_VARIATION_PASSWORD);
              }

              mEditTextMap.put(i, mEditText);

              mTextViewMap.put(i, mTextView);
              layout.addView(mTextView);
              layout.addView(mEditText);

            }
          }

          // If the endpoint can not be activated through the
          // application the user is informed
          // with an appropriate message on the Activation Window
          mTitleTextView.setText("Activate Endpoint:" + title);
          if (mEditTextMap.isEmpty()) {
            TextView mTextView = new TextView(mContext);
            mTextView.setText(getString(R.string.oauth));
            mTextView.setLayoutParams(new LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
            layout.addView(mTextView);

          }

          Button mOkButton = (Button) mActivateDialog
              .findViewById(R.id.ok_button);

          mOkButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

              // If the Window contains nothing but a message
              // informing the user that the endpoint
              // can not be activated, when the OK Button is
              // pressed the Dialog disappears nothing happens
              if (mEditTextMap.isEmpty()) {
                mActivateDialog.dismiss();
              } else {
                boolean mReady = true;

                for (Entry<Integer, EditText> entry : mEditTextMap
                    .entrySet()) {

                  String mEditTextValue = entry.getValue()
                      .getText().toString();
                  int key = entry.getKey();
                  String mTextViewValue = mTextViewMap
                      .get(key).getText().toString();

                  if (mTextViewValue.startsWith("*")
                      && mEditTextValue.isEmpty()) {
                    mReady = false;

                  }

                }
                // If the user has filled all the necessary
                // fields, the Activate Dialog
                // is dismissed and the execute method of the
                // Activate class is called
                if (mReady) {

                  try {
                    for (Entry<Integer, EditText> entry : mEditTextMap
                        .entrySet()) {
                      int key = entry.getKey();
                      JSONObject mJSONObject = mJSONArray
                          .getJSONObject(key);
                      mJSONObject.put("value", entry
                          .getValue().getText()
                          .toString());
                      mJSONArray.put(key, mJSONObject);
                      Log.d("VALUE", mJSONObject
                          .getString("value"));
                    }

                    mActivationRequirements.remove("DATA");
                    mActivationRequirements.put("DATA",
                        mJSONArray);

                  } catch (JSONException e) {

                    e.printStackTrace();
                  }

                  mActivateDialog.dismiss();
                  new Activate(mLocalNode, mEndpoint)
                      .execute(mActivationRequirements);
                }
                // If some of the required fields have not been
                // filled, the user is informed
                // with a Toast message
                else {

                  makeToast(
                      getString(R.string.fields_not_filled_warning),
                      Toast.LENGTH_SHORT);
                }

              }

            }

          });

          mActivateDialog.show();

        } catch (JSONException e) {

          e.printStackTrace();
        }

      }

    }

  }

  /**
   * This class attempts to activate an endpoint by POSTing a JSON Object
   * containing the Credentials Required as they were filled by the user to
   * endpoint/<canonical_name>/activate. It informs the user of the result
   * with a Toast message.
   * 
   * @author christos
   * 
   */
  public class Activate extends
      AsyncTask<JSONObject, Void, ArrayList<String>> {

    String mLocalNode;
    String mEndpoint;

    public Activate(String node, String endpoint) {
      this.mLocalNode = node;
      this.mEndpoint = endpoint;

    }

    @Override
    protected ArrayList<String> doInBackground(JSONObject... args) {

      ArrayList<String> mResult = new ArrayList<String>();

      // The endpoint's canonical name is split into user's name and
      // endpoint's name in order to replace
      // "#" with "%23" for encoding reasons
      String mDelims = "#";
      String[] mTokens = mEndpoint.split(mDelims);

      Result mQueryResult;
      try {
        JSONObject mRequirementsJsonObject = args[0];
        
        //The user's activate request is POSTed to the API along with the requirements JSON Object
        mQueryResult = sClient.postResult("/endpoint/" + mTokens[0]
            + "%23" + mTokens[1] + "/activate",
            mRequirementsJsonObject);
        JSONObject mJsonObject = mQueryResult.document;

        if (!mJsonObject.getString("DATA_TYPE").equals(
            "activation_result")) {
          mResult.add(getString(R.string.error));
          mResult.add(getString(R.string.error));
          return mResult;
        }

        //The returned from the API message and code are retrieved and returned
        mResult.add(mJsonObject.getString("code"));
        mResult.add(mJsonObject.getString("message"));

      } catch (MalformedURLException e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.getMessage());
      } catch (IOException e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.getMessage());
      } catch (GeneralSecurityException e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.getMessage());
      } catch (JSONException e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.getMessage());
      } catch (APIError e) {

        e.printStackTrace();
        mResult.add(getString(R.string.error));
        mResult.add(e.message);

      }

      return mResult;
    }

    @Override
    protected void onPostExecute(ArrayList<String> result) {

      super.onPostExecute(result);

      //The user is informed of their request's outcome with a Toast message 
      makeToast(result.get(1), Toast.LENGTH_LONG);

    }

  }

  /**
   * Android build-in function that we override in order to save data when the
   * activity is temporarily destroyed
   */
  @Override
  public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putStringArrayList("endpoints_list", mEndpoints);
    outState.putString("path_a", mEndpointACurrentPath);
    outState.putString("path_b", mEndpointBCurrentPath);
    outState.putString("path_a_text_view", mPathATextView.getText()
        .toString());
    outState.putString("path_b_text_view", mPathBTextView.getText()
        .toString());
    outState.putStringArrayList("selected_files_a",
        (ArrayList<String>) mSelectedFilesA);
    outState.putStringArrayList("selected_files_b",
        (ArrayList<String>) mSelectedFilesB);
    outState.putString("endpoint_a", mSelectEndpointAButton.getText()
        .toString());
    outState.putString("endpoint_b", mSelectEndpointBButton.getText()
        .toString());
    outState.putStringArrayList("dir_a", mFileListA);
    outState.putStringArrayList("dir_b", mFileListB);
    outState.putSerializable("filesizeA", (Serializable) mFilesSizeA);
    outState.putSerializable("filesizeB", (Serializable) mFilesSizeB);
  }
}




Java Source Code List

org.globus.globustransfer.EndpointActivity.java
org.globus.globustransfer.MainActivity.java
org.globus.globustransfer.MenuActivity.java
org.globus.globustransfer.MonitorActivity.java
org.globus.globustransfer.StartTransfer.java
org.globusonline.transfer.APIError.java
org.globusonline.transfer.BCTransferAPIClient.java
org.globusonline.transfer.BaseTransferAPIClient.java
org.globusonline.transfer.JSONTransferAPIClient.java
org.json.JSONArray.java
org.json.JSONException.java
org.json.JSONObject.java
org.json.JSONString.java
org.json.JSONTokener.java