Revision 7dbfc514

b/AndroidManifest.xml
3 3
	android:versionCode="3" android:versionName="1.2" package="com.rackspace.cloud.android">
4 4
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
5 5
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
6
	<application android:name="AndroidCloudApplication" android:icon="@drawable/rackspace60"
6
	<application android:name=".AndroidCloudApplication" android:icon="@drawable/rackspace60"
7 7
		android:label="@string/app_name" android:debuggable="true">
8 8
		<activity android:name=".RackspaceCloudActivity"
9 9
			android:label="@string/app_name">
b/src/com/rackspace/cloud/android/AccessControlActivity.java
1
package com.rackspace.cloud.android;
2

  
3
import java.util.ArrayList;
4

  
5
import org.apache.http.HttpResponse;
6

  
7
import android.app.Activity;
8
import android.app.AlertDialog;
9
import android.app.Dialog;
10
import android.content.DialogInterface;
11
import android.content.Intent;
12
import android.os.AsyncTask;
13
import android.os.Bundle;
14
import android.view.LayoutInflater;
15
import android.view.View;
16
import android.view.View.OnClickListener;
17
import android.view.ViewGroup;
18
import android.widget.ArrayAdapter;
19
import android.widget.Button;
20
import android.widget.ImageView;
21
import android.widget.ListView;
22
import android.widget.TextView;
23

  
24
import com.rackspace.cloud.android.R;
25
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancer;
26
import com.rackspace.cloud.loadbalancer.api.client.NetworkItem;
27
import com.rackspace.cloud.loadbalancer.api.client.NetworkItemManager;
28
import com.rackspace.cloud.loadbalancer.api.client.http.LoadBalancersException;
29
import com.rackspace.cloud.servers.api.client.CloudServersException;
30
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
31

  
32
public class AccessControlActivity extends CloudListActivity {
33

  
34
	private final int REMOVE_RULE = 199;
35
	private final int ADD_RULE = 219;
36
	
37
	private LoadBalancer loadBalancer;
38
	private ArrayList<NetworkItem> networkItems;
39
	private int lastSelectedRulePosition;
40
	
41
	@Override
42
	public void onCreate(Bundle savedInstanceState) {
43
		super.onCreate(savedInstanceState);
44
		loadBalancer = (LoadBalancer) this.getIntent().getExtras().get("loadBalancer");
45
		setContentView(R.layout.accesscontrol);
46
		restoreState(savedInstanceState);
47
	}
48

  
49
	@Override
50
	protected void onSaveInstanceState(Bundle outState) {
51
		super.onSaveInstanceState(outState);
52
		outState.putSerializable("networkItems", networkItems);
53
	}
54

  
55
	@SuppressWarnings("unchecked")
56
	protected void restoreState(Bundle state) {
57
		super.restoreState(state);
58

  
59
		setupButton();
60
		
61
		if (state != null && state.containsKey("networkItems") && state.getSerializable("networkItems") != null) {
62
			networkItems = (ArrayList<NetworkItem>) state.getSerializable("networkItems");
63
			if (networkItems.size() == 0) {
64
				displayNoRulesCell();
65
			} else {
66
				getListView().setDividerHeight(1); // restore divider lines
67
				setListAdapter(new NetworkItemAdapter());
68
			}
69
		} else {
70
			loadNetworkItems();
71
		}
72
	}
73
	
74
	private void setupButton(){
75
		Button addRule = (Button)findViewById(R.id.add_rule_button);
76
		addRule.setOnClickListener(new OnClickListener() {
77
			
78
			@Override
79
			public void onClick(View v) {
80
				Intent viewIntent = new Intent(getContext(), AddAccessRuleActivity.class);
81
				viewIntent.putExtra("loadBalancer", loadBalancer);
82
				startActivityForResult(viewIntent, ADD_RULE);
83
			}
84
		});
85
	}
86

  
87
	protected void onListItemClick(ListView l, View v, int position, long id) {
88
		if (networkItems != null && networkItems.size() > 0) {
89
			lastSelectedRulePosition = position;
90
			showDialog(REMOVE_RULE);
91
		}
92
	}
93

  
94
	@Override
95
	protected Dialog onCreateDialog(int id) {
96
		switch (id) {
97
		case REMOVE_RULE: 
98
			return new AlertDialog.Builder(AccessControlActivity.this)
99
			.setIcon(R.drawable.alert_dialog_icon)
100
			.setTitle("Remove Rule")
101
			.setMessage("Would you like to remove this rule?")
102
			.setPositiveButton("Remove", new DialogInterface.OnClickListener() {
103
				public void onClick(DialogInterface dialog, int whichButton) {
104
					new DeleteNetworkItemTask().execute((Void[]) null);
105
				}
106
			})
107
			.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
108
				public void onClick(DialogInterface dialog, int whichButton) {
109
					// User clicked Cancel so do some stuff
110
				}
111
			})
112
			.create();          
113
		}
114
		return null;
115
	}
116
	
117
	private void setNetworkItemList(ArrayList<NetworkItem> networkItems) {
118
		if (networkItems == null) {
119
			networkItems = new ArrayList<NetworkItem>();
120
		}
121
		this.networkItems = new ArrayList<NetworkItem>();
122
		String[] networkItemNames = new String[networkItems.size()];
123

  
124
		if (networkItems != null) {
125
			for (int i = 0; i < networkItems.size(); i++) {
126
				NetworkItem networkItem = networkItems.get(i);
127
				this.networkItems.add(i, networkItem);
128
				networkItemNames[i] = networkItem.getName();
129
			}
130
		}
131

  
132
		if (networkItemNames.length == 0) {
133
			displayNoRulesCell();
134
		} else {
135
			getListView().setDividerHeight(1); // restore divider lines 
136
			setListAdapter(new NetworkItemAdapter());
137
		}
138
	}
139
	
140
	 private void displayLoadingCell() {
141
	    	String a[] = new String[1];
142
	    	a[0] = "Loading...";
143
	        setListAdapter(new ArrayAdapter<String>(this, R.layout.loadingcell, R.id.loading_label, a));
144
	        getListView().setTextFilterEnabled(true);
145
	        getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
146
	        getListView().setItemsCanFocus(false);
147
	    }
148

  
149
	private void displayNoRulesCell() {
150
		String a[] = new String[1];
151
		a[0] = "No Rules";
152
		setListAdapter(new ArrayAdapter<String>(this, R.layout.norulescell, R.id.no_rules_label, a));
153
		getListView().setTextFilterEnabled(true);
154
		getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
155
		getListView().setItemsCanFocus(false);
156
	}
157

  
158
	private void loadNetworkItems() {
159
		displayLoadingCell();
160
		new LoadNetworkItemsTask().execute((Void[]) null);
161
	}
162

  
163
	// * Adapter/
164
	class NetworkItemAdapter extends ArrayAdapter<NetworkItem> {
165
		NetworkItemAdapter() {
166
			super(AccessControlActivity.this, R.layout.accesscontrolcell, networkItems);
167
		}
168

  
169
		public View getView(int position, View convertView, ViewGroup parent) {
170

  
171
			NetworkItem networkItem = networkItems.get(position);
172
			LayoutInflater inflater = getLayoutInflater();
173
			View row = inflater.inflate(R.layout.accesscontrolcell, parent, false);
174

  
175
			TextView label = (TextView) row.findViewById(R.id.ip_address_text);
176
			label.setText(networkItem.getAddress());
177

  
178
			TextView sublabel = (TextView) row.findViewById(R.id.status_text);
179
			sublabel.setText(networkItem.getType());
180
			
181
			ImageView typeImage = (ImageView) row.findViewById(R.id.rule_type_image);
182
			int image;
183
			if(networkItem.getType().equals("ALLOW")){
184
				image = R.drawable.allow_rule;
185
			} else {
186
				image = R.drawable.deny_rule;
187
			}
188
			typeImage.setImageResource(image);
189

  
190

  
191
			return(row);
192
		}
193
	}
194

  
195
	private class LoadNetworkItemsTask extends AsyncTask<Void, Void, ArrayList<NetworkItem>> {
196
		private LoadBalancersException exception;
197

  
198
		@Override
199
		protected void onPreExecute(){
200
			//set to null so will reload on config changes
201
			networkItems = null;
202
		}
203

  
204
		@Override
205
		protected ArrayList<NetworkItem> doInBackground(Void... arg0) {
206
			ArrayList<NetworkItem> networkItems = null;
207
			try {
208
				networkItems = new NetworkItemManager(getContext()).createList(loadBalancer);
209
			} catch (LoadBalancersException e) {
210
				exception = e;				
211
			}
212
			return networkItems;
213
		}
214

  
215
		@Override
216
		protected void onPostExecute(ArrayList<NetworkItem> result) {
217
			if (exception != null) {
218
				showAlert("Error", exception.getMessage());
219
			}
220
			setNetworkItemList(result);
221
		}
222
	}
223
	
224
	private class DeleteNetworkItemTask extends AsyncTask<Void, Void, HttpBundle> {
225

  
226
			private CloudServersException exception;
227
			private NetworkItem networkItem;
228

  
229
			@Override
230
			//let user know their process has started
231
			protected void onPreExecute(){
232
				networkItem = networkItems.get(lastSelectedRulePosition);
233
				displayLoadingCell();
234
				//set to null so will reload on config change
235
				networkItems = null;
236
			}
237
			@Override
238
			protected HttpBundle doInBackground(Void... arg0) {
239
				HttpBundle bundle = null;
240
				try {
241
					bundle = new NetworkItemManager(getContext()).delete(loadBalancer, networkItem);
242
				} catch (CloudServersException e) {
243
					exception = e;
244
				}
245
				return bundle;
246
			}
247

  
248
			@Override
249
			protected void onPostExecute(HttpBundle bundle) {
250
				HttpResponse response = bundle.getResponse();
251
				if (response != null) {
252
					int statusCode = response.getStatusLine().getStatusCode();
253
					if (statusCode == 202 || statusCode == 200) {
254
						setResult(Activity.RESULT_OK);
255
						loadNetworkItems();
256
					} else {
257
						CloudServersException cse = parseCloudServersException(response);
258
						if ("".equals(cse.getMessage())) {
259
							showError("There was a problem deleting your rule.", bundle);
260
						} else {
261
							showError("There was a problem deleting your rule: " + cse.getMessage(), bundle);
262
						}
263
					}
264
				} else if (exception != null) {
265
					showError("There was a problem deleting your rule: " + exception.getMessage(), bundle);				
266
				}			
267
			}
268
		}
269

  
270

  
271

  
272
	protected void onActivityResult(int requestCode, int resultCode, Intent data){	
273
		if(requestCode == ADD_RULE && resultCode == RESULT_OK){
274
			loadNetworkItems();
275
		}
276
	}
277
}
b/src/com/rackspace/cloud/android/AddAccessRuleActivity.java
1
package com.rackspace.cloud.android;
2

  
3
import java.util.ArrayList;
4
import java.util.Arrays;
5
import java.util.regex.Matcher;
6
import java.util.regex.Pattern;
7

  
8
import org.apache.http.HttpResponse;
9

  
10
import android.app.Activity;
11
import android.os.AsyncTask;
12
import android.os.Bundle;
13
import android.text.Editable;
14
import android.text.TextWatcher;
15
import android.view.View;
16
import android.view.View.OnClickListener;
17
import android.widget.AdapterView;
18
import android.widget.AdapterView.OnItemSelectedListener;
19
import android.widget.ArrayAdapter;
20
import android.widget.Button;
21
import android.widget.EditText;
22
import android.widget.Spinner;
23

  
24
import com.rackspace.cloud.android.R;
25
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancer;
26
import com.rackspace.cloud.loadbalancer.api.client.NetworkItem;
27
import com.rackspace.cloud.loadbalancer.api.client.NetworkItemManager;
28
import com.rackspace.cloud.servers.api.client.CloudServersException;
29
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
30

  
31
public class AddAccessRuleActivity extends CloudActivity{
32

  
33
	private final String[] ACTIONS = {"Deny", "Allow"};
34
	
35
	private LoadBalancer loadBalancer;
36
	private String selectedAction;
37
	private String selectedAddresses;
38
	
39
	@Override
40
	public void onCreate(Bundle savedInstanceState) {
41
		super.onCreate(savedInstanceState);
42
		loadBalancer = (LoadBalancer) this.getIntent().getExtras().get("loadBalancer");
43
		setContentView(R.layout.addaccessrule);
44
		restoreState(savedInstanceState);
45
	}
46

  
47
	@Override
48
	protected void onSaveInstanceState(Bundle outState) {
49
		super.onSaveInstanceState(outState);
50
	}
51

  
52
	protected void restoreState(Bundle state) {
53
		super.restoreState(state);
54
		setupInputs();
55
	}
56
	
57
	private void setupInputs(){
58
		Spinner actionSpinner = (Spinner)findViewById(R.id.rule_action_spinner);
59
		
60
		ArrayAdapter<String> actionAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, ACTIONS);
61
		actionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
62
		actionSpinner.setAdapter(actionAdapter);
63

  
64
		actionSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
65

  
66
			@Override
67
			public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
68
				selectedAction = ACTIONS[pos];	
69
			}
70

  
71
			@Override
72
			public void onNothingSelected(AdapterView<?> arg0) {
73

  
74
			}
75

  
76
		});
77
		
78
		EditText address = (EditText)findViewById(R.id.rule_address);
79
		address.addTextChangedListener(new TextWatcher() {
80
			
81
			@Override
82
			public void onTextChanged(CharSequence s, int start, int before, int count) {
83
				selectedAddresses = s.toString();
84
			}
85
			
86
			@Override
87
			public void beforeTextChanged(CharSequence s, int start, int count,
88
					int after) {
89
				//do nothing
90
			}
91
			
92
			@Override
93
			public void afterTextChanged(Editable s) {
94
				//do nothing
95
			}
96
		});
97
		
98
		Button addRule = (Button)findViewById(R.id.add_rule_button);
99
		addRule.setOnClickListener(new OnClickListener() {
100
			
101
			@SuppressWarnings("unchecked")
102
			@Override
103
			public void onClick(View v) {
104
				if(!validAddress(selectedAddresses)){
105
					showAlert("Error", "Please enter a valid IP address.");
106
				} else if(!validAction(selectedAction)) {
107
					showAlert("Error", "Please select an action type.");
108
				} else{
109
					ArrayList<NetworkItem> networkItems = new ArrayList<NetworkItem>();
110
					String[] networkAddresses = selectedAddresses.split(",");
111
					for(int i = 0; i < networkAddresses.length; i++){
112
						NetworkItem networkItem = new NetworkItem();
113
						networkItem.setAddress(networkAddresses[i].trim());
114
						networkItem.setType(selectedAction);
115
						networkItems.add(networkItem);
116
					}
117
					new AddNetworkItemTask().execute(networkItems);
118
				}
119
			}
120
		});
121
	}
122
	
123
	//basic ip validation just checks that the string
124
	//is only composed of letters, numbers, ., : and , 
125
	private static boolean validAddress(String address){
126
		//if just white space return false;
127
		//check regex
128
		if(address != null && !address.trim().equals("")){
129
			Pattern pattern = Pattern.compile("[a-zA-Z0-9.:/, ]+");
130
			Matcher match = pattern.matcher(address);
131
			return match.matches();
132
		} else {
133
			return false;
134
		}
135
	}
136
	
137
	private Boolean validAction(String action){
138
		return action != null && Arrays.asList(ACTIONS).contains(action);
139
	}
140
	
141
	private class AddNetworkItemTask extends AsyncTask<ArrayList<NetworkItem>, Void, HttpBundle> {
142

  
143
		private CloudServersException exception;
144

  
145
		@Override
146
		protected void onPreExecute(){
147
			showDialog();
148
		}
149
		@Override
150
		protected HttpBundle doInBackground(ArrayList<NetworkItem>... networkItems) {
151
			HttpBundle bundle = null;
152
			try {
153
				bundle = new NetworkItemManager(getContext()).create(loadBalancer, networkItems[0]);
154
			} catch (CloudServersException e) {
155
				exception = e;
156
			}
157
			return bundle;
158
		}
159

  
160
		@Override
161
		protected void onPostExecute(HttpBundle bundle) {
162
			hideDialog();
163
			HttpResponse response = bundle.getResponse();
164
			if (response != null) {
165
				int statusCode = response.getStatusLine().getStatusCode();
166
				if (statusCode == 202 || statusCode == 200) {
167
					setResult(Activity.RESULT_OK);
168
					finish();
169
				} else {
170
					CloudServersException cse = parseCloudServersException(response);
171
					if ("".equals(cse.getMessage())) {
172
						showError("There was a problem creating your rule.", bundle);
173
					} else {
174
						showError("There was a problem creating your rule: " + cse.getMessage(), bundle);
175
					}
176
				}
177
			} else if (exception != null) {
178
				showError("There was a problem creating your rule: " + exception.getMessage(), bundle);				
179
			}			
180
		}
181
	}
182
}
b/src/com/rackspace/cloud/android/AddAccountActivity.java
1
package com.rackspace.cloud.android;
2

  
3
import android.content.Intent;
4
import android.os.Bundle;
5
import android.text.method.PasswordTransformationMethod;
6
import android.text.method.SingleLineTransformationMethod;
7
import android.view.View;
8
import android.view.View.OnClickListener;
9
import android.widget.AdapterView;
10
import android.widget.ArrayAdapter;
11
import android.widget.Button;
12
import android.widget.CheckBox;
13
import android.widget.EditText;
14
import android.widget.Spinner;
15

  
16
import com.rackspace.cloud.android.R;
17

  
18
public class AddAccountActivity extends CloudActivity implements OnClickListener{
19
	
20
	private final String[] PROVIDERS = {"Rackspace Cloud (US)", "Rackspace Cloud (UK)","Pithos+", "Pithos+ Dev","Custom"};
21
	private EditText usernameText;
22
	private EditText passwordText;
23
	private EditText customServer;
24
	private Spinner providerSpinner;
25
	private String authServer;
26
	boolean isHidden;
27
	
28
	public void onCreate(Bundle savedInstanceState) {
29
        super.onCreate(savedInstanceState);
30
        trackPageView(GoogleAnalytics.PAGE_PROVIDERS);
31
        setContentView(R.layout.createaccount);
32
        usernameText = (EditText) findViewById(R.id.username);
33
        passwordText = (EditText) findViewById(R.id.addaccount_apikey);
34
        customServer = (EditText) findViewById(R.id.custom_auth_server_edit);
35
        ((Button) findViewById(R.id.submit_new_account)).setOnClickListener(this);
36
        isHidden = true;
37
        customServer.setEnabled(false);
38
        if(savedInstanceState != null)
39
        	isHidden = savedInstanceState.containsKey("isHidden") && savedInstanceState.getBoolean("isHidden");
40
        setUpApiText(savedInstanceState);
41
        setUpCheckBox();
42
        loadProviderSpinner();
43
    } 
44
	
45
	protected void onSaveInstanceState(Bundle outState) {
46
		super.onSaveInstanceState(outState);
47
		outState.putBoolean("isHidden", isHidden);
48
	}
49
	
50
	//setup the API textedit to be password dots or regular text
51
	private void setUpApiText(Bundle state){
52
        isHidden = true;
53
        if(state != null)
54
        	isHidden = state.containsKey("isHidden") && state.getBoolean("isHidden");
55
		if(isHidden){
56
        	passwordText.setTransformationMethod(new PasswordTransformationMethod());
57
		}
58
		else{
59
			passwordText.setTransformationMethod(new SingleLineTransformationMethod());
60
		}
61
	}
62
	
63
	private void setUpCheckBox(){
64
		final CheckBox show_clear = (CheckBox) findViewById(R.id.show_clear);
65
		show_clear.setChecked(!isHidden);
66
        show_clear.setOnClickListener(new OnClickListener() {
67
        	@Override 
68
			public void onClick(View v) {
69
		        if (((CheckBox) v).isChecked()) {
70
		        	passwordText.setTransformationMethod(new SingleLineTransformationMethod());
71
		        	isHidden = false;
72
		        } else {
73
		        	passwordText.setTransformationMethod(new PasswordTransformationMethod());
74
		        	isHidden = true;
75
		        }
76
		        passwordText.requestFocus();
77
		    }	
78
		});
79
	}
80
	
81
	private void loadProviderSpinner(){
82
		//set the auth server default to us
83
		authServer = "https://auth.api.rackspacecloud.com/v2.0";
84
		providerSpinner = (Spinner) findViewById(R.id.provider_spinner);
85
		ArrayAdapter<String> imageAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, PROVIDERS);
86
		imageAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
87
		providerSpinner.setAdapter(imageAdapter);
88
		providerSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
89
		    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
90
		    	if(pos == 0){
91
					authServer = Preferences.COUNTRY_US_AUTH_SERVER_V2;
92
			        customServer.setEnabled(false);
93
				}
94
				else if(pos == 1){
95
					authServer = Preferences.COUNTRY_UK_AUTH_SERVER_V2;
96
			        customServer.setEnabled(false);
97
				}
98
				else if(pos == 2){
99
					authServer = Preferences.PITHOS_SERVER;
100
			        customServer.setEnabled(false);
101
				}
102
				else if(pos == 3){
103
					authServer = Preferences.PITHOS_DEV_SERVER;
104
			        customServer.setEnabled(false);
105
				}
106
				else{
107
			        customServer.setEnabled(true);
108
				}
109
		    }
110
		    public void onNothingSelected(AdapterView<?> parent) {
111
		    }
112
		});
113
	}
114
	
115
	public void onClick(View arg0) {
116

  
117
		if (hasValidInput()) {
118
			//showActivityIndicators();
119
			Intent result = new Intent();
120
			Bundle b = new Bundle();
121
			b.putString("username", usernameText.getText().toString());
122
			b.putString("apiKey", passwordText.getText().toString());
123
			b.putString("server", getAuthServer());
124
			result.putExtra("accountInfo", b);
125
			setResult(RESULT_OK, result);
126
			finish();
127
		} else {
128
			showAlert("Required Fields Missing", "Username and API Key are required.");
129
		}
130
		
131
	}
132
	
133
	private String getAuthServer(){
134
		if(customServer.isEnabled()){
135
			authServer = customServer.getText().toString();
136
		}
137
		return authServer;
138
	}
139
	
140
	private boolean hasValidInput() {
141
    	String username = usernameText.getText().toString();
142
    	String apiKey = passwordText.getText().toString();
143
    	return !"".equals(username) && !"".equals(apiKey);
144
    }
145

  
146
}
b/src/com/rackspace/cloud/android/AddContainerActivity.java
1
package com.rackspace.cloud.android;
2

  
3
import org.apache.http.HttpResponse;
4

  
5
import android.app.Activity;
6
import android.os.AsyncTask;
7
import android.os.Bundle;
8
import android.view.View;
9
import android.view.View.OnClickListener;
10
import android.widget.Button;
11
import android.widget.EditText;
12

  
13
import com.rackspace.cloud.android.R;
14
import com.rackspace.cloud.files.api.client.ContainerManager;
15
import com.rackspace.cloud.servers.api.client.CloudServersException;
16
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
17
/** 
18
 * 
19
 * @author Phillip Toohill
20
 *
21
 */
22
public class AddContainerActivity extends CloudActivity implements OnClickListener {
23

  
24
	private EditText containerName;	
25
	
26
	/** Called when the activity is first created. */
27
	@Override
28
	public void onCreate(Bundle savedInstanceState) {
29
		super.onCreate(savedInstanceState);
30
		trackPageView(GoogleAnalytics.PAGE_ADD_CONTAINER);
31
		setContentView(R.layout.createcontainer);
32
		restoreState(savedInstanceState);
33
	}
34
	
35
	protected void restoreState(Bundle state){
36
		super.restoreState(state);
37
		containerName = (EditText) findViewById(R.id.container_name);
38
		((Button) findViewById(R.id.save_button)).setOnClickListener(this);
39
	}
40
	
41
	public void onClick(View arg0) {
42
		if ("".equals(containerName.getText().toString())) {
43
			showAlert("Required Fields Missing", " Container name is required.");
44
		} else {
45
			trackEvent(GoogleAnalytics.CATEGORY_CONTAINER, GoogleAnalytics.EVENT_CREATE, "", -1);
46
			new CreateContainerTask().execute((Void[]) null);
47
		}
48
	}
49
	
50
	private class CreateContainerTask extends AsyncTask<Void, Void, HttpBundle> {
51
		private CloudServersException exception;
52

  
53
		protected void onPreExecute(){
54
			showDialog();
55
		}
56
		
57
		@Override
58
		protected HttpBundle doInBackground(Void... arg0) {
59
			HttpBundle bundle = null;
60
			try {
61
				bundle = (new ContainerManager(getContext())).create(containerName.getText());
62
			} catch (CloudServersException e) {
63
				exception = e;
64
			}
65
			return bundle;
66
		}
67

  
68
		@Override
69
		protected void onPostExecute(HttpBundle bundle) {
70
			hideDialog();
71
			HttpResponse response = bundle.getResponse();
72
			if (response != null) {
73
				int statusCode = response.getStatusLine().getStatusCode();
74
				if (statusCode == 201) {
75
					setResult(Activity.RESULT_OK);
76
					finish();
77
				} else {
78
					CloudServersException cse = parseCloudServersException(response);
79
					if ("".equals(cse.getMessage())) {
80
						showError("There was a problem creating your container.", bundle);
81
					} else {
82
						showError("There was a problem creating your container: " + cse.getMessage() + " See details for more information.", bundle);
83
					}
84
				}
85
			} else if (exception != null) {
86
				showError("There was a problem creating your container: " + exception.getMessage()+" See details for more information.", bundle);				
87
			}
88
			finish();
89
		}
90
	}
91

  
92

  
93

  
94
}
b/src/com/rackspace/cloud/android/AddExternalNodeActivity.java
1
package com.rackspace.cloud.android;
2

  
3
import java.util.regex.Matcher;
4
import java.util.regex.Pattern;
5

  
6
import android.content.Intent;
7
import android.os.Bundle;
8
import android.util.Log;
9
import android.view.View;
10
import android.view.View.OnClickListener;
11
import android.view.Window;
12
import android.widget.AdapterView;
13
import android.widget.AdapterView.OnItemSelectedListener;
14
import android.widget.ArrayAdapter;
15
import android.widget.Button;
16
import android.widget.EditText;
17
import android.widget.Spinner;
18
import android.widget.TextView;
19

  
20
import com.rackspace.cloud.android.R;
21
import com.rackspace.cloud.loadbalancer.api.client.Node;
22

  
23
public class AddExternalNodeActivity extends CloudActivity {
24

  
25
	private final String[] CONDITIONS = {"Enabled", "Disabled", "Draining"};
26
	private String selectedPort;
27
	private String selectedIp;
28
	private String selectedWeight;
29
	private boolean weighted;
30
	private String selectedCondition;
31
	private Spinner conditionSpinner;
32
	private EditText ipAddress;
33
	private EditText weightText;
34
	private Node node;
35
	
36
	public void onCreate(Bundle savedInstanceState) {
37
		super.onCreate(savedInstanceState);
38
		requestWindowFeature(Window.FEATURE_NO_TITLE);
39
		setContentView(R.layout.addexternalnode);
40
		weighted = (Boolean) this.getIntent().getExtras().get("weighted");
41
		node = (Node) this.getIntent().getExtras().get("node");
42
		selectedPort = (String) this.getIntent().getExtras().get("loadBalancerPort");
43
		restoreState(savedInstanceState);
44
	} 
45

  
46
	protected void restoreState(Bundle state) {
47
		super.restoreState(state);
48
		setupInputs();
49
	}
50

  
51
	private void setupInputs(){
52
		
53
		ipAddress = (EditText) findViewById(R.id.ip_address);
54
		
55
		weightText = (EditText) findViewById(R.id.node_weight_text);
56

  
57
		//if algorithm is not weighted then then node's weight will be null
58
		if(!weighted){
59
			TextView weightLabel = (TextView) findViewById(R.id.node_weight_label);
60
			weightLabel.setVisibility(View.GONE);
61
			weightText.setVisibility(View.GONE);
62
		}
63

  
64
		loadConditionSpinner();
65
		setUpButton();
66

  
67
		if(node != null){
68
			ipAddress.setText(node.getAddress());
69
			weightText.setText(node.getWeight());
70
			((EditText)findViewById(R.id.node_port_text)).setText(node.getPort());
71
			conditionSpinner.setSelection(getLocation(CONDITIONS, node.getCondition()));
72
		} else {
73
			Log.d("info", "node was null");
74
			((EditText)findViewById(R.id.node_port_text)).setText(selectedPort);
75
		}
76
	}
77
	
78
	private int getLocation(Object[] objects, Object object){
79
		for(int i = 0; i < objects.length; i++){
80
			if(object.equals(objects[i])){
81
				return i;
82
			}
83
		}
84
		return 0;
85
	}
86

  
87
	private void setUpButton(){
88
		Button submit = (Button) findViewById(R.id.add_node_button);
89
		submit.setOnClickListener(new OnClickListener() {
90

  
91
			@Override
92
			public void onClick(View v) {
93
				selectedIp = ipAddress.getText().toString().trim();
94
				selectedPort = ((EditText)findViewById(R.id.node_port_text)).getText().toString().trim();
95
				selectedWeight = weightText.getText().toString().trim();
96
				if(!validPort(selectedPort)){
97
					showAlert("Error", "Must have a protocol port number that is between 1 and 65535.");
98
				} else if(!(weightText.getVisibility() == View.GONE || (weightText.getVisibility() != View.GONE && validWeight(selectedWeight)))){
99
					showAlert("Error", "Weight must be between 1 and 100.");
100
				} else if(selectedIp.equals("")){
101
					//TODO use regex to validate the ip for IPV4 and IPV6
102
					showAlert("Error", "Enter an IP Address");
103
				} else if(!validIp(selectedIp)) {
104
					showAlert("Error", "Enter a valid IP Address");
105
				} else {
106
					Intent data = new Intent();
107
					data.putExtra("nodeIp", selectedIp);
108
					data.putExtra("nodePort", selectedPort);
109
					data.putExtra("nodeCondition", selectedCondition);
110
					data.putExtra("nodeWeight", selectedWeight);
111
					setResult(RESULT_OK, data);
112
					finish();
113
				}
114

  
115
			}
116
		});
117
	}
118

  
119
	private void loadConditionSpinner(){
120
		conditionSpinner = (Spinner) findViewById(R.id.node_condition_spinner);
121

  
122
		ArrayAdapter<String> conditionAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, CONDITIONS);
123
		conditionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
124
		conditionSpinner.setAdapter(conditionAdapter);
125

  
126
		conditionSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
127

  
128
			@Override
129
			public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
130
				selectedCondition = CONDITIONS[pos];	
131
			}
132

  
133
			@Override
134
			public void onNothingSelected(AdapterView<?> arg0) {
135

  
136
			}
137

  
138
		});
139
	}
140
	
141
	//basic ip validation just checks that the string
142
	//is only composed of letters, numbers, ., :
143
	private static boolean validIp(String ip){
144
		//Enter regex
145
		if(ip != null){
146
			Pattern pattern = Pattern.compile("[a-zA-Z0-9.:]+");
147
			Matcher match = pattern.matcher(ip);
148
			return match.matches();
149
		} else {
150
			return false;
151
		}
152
	}
153

  
154
	private boolean validPort(String port){
155
		boolean result;
156
		try{
157
			result = !port.equals("") && Integer.valueOf(port) > 0 && Integer.valueOf(port) < 65536;
158
		} catch (NumberFormatException e) {
159
	    	result = false;
160
	    }
161
	    return result;
162
	}
163

  
164
	private Boolean validWeight(String weight){
165
		if(weight.equals("")){
166
			return false;
167
		}
168
		else{
169
			int w;
170
			try{
171
				w = Integer.valueOf(weight);
172
			} catch (NumberFormatException e){
173
				return false;
174
			}
175
			return w >= 1 && w <= 100 ;
176
		}
177
	}
178

  
179
	public void onBackPressed(){
180
		setResult(RESULT_CANCELED);
181
		finish();
182
	}
183

  
184
}
185

  
b/src/com/rackspace/cloud/android/AddFileActivity.java
1
package com.rackspace.cloud.android;
2

  
3
import org.apache.http.HttpResponse;
4

  
5
import android.app.Activity;
6
import android.os.AsyncTask;
7
import android.os.Bundle;
8
import android.view.View;
9
import android.view.View.OnClickListener;
10
import android.widget.Button;
11
import android.widget.EditText;
12

  
13
import com.rackspace.cloud.android.R;
14
import com.rackspace.cloud.files.api.client.ContainerObjectManager;
15
import com.rackspace.cloud.servers.api.client.CloudServersException;
16
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
17

  
18
public class AddFileActivity extends CloudActivity implements OnClickListener{
19

  
20
	private EditText fileName;
21
	private EditText contents;
22
	private String containerName;
23
	private String path;
24

  
25
	/** Called when the activity is first created. */
26
	@Override
27
	public void onCreate(Bundle savedInstanceState) {
28
		super.onCreate(savedInstanceState);
29
		trackPageView(GoogleAnalytics.PAGE_ADD_OBJECT);
30
		setContentView(R.layout.addtextfile);
31
		restoreState(savedInstanceState);
32
	}
33

  
34
	protected void restoreState(Bundle state){
35
		super.restoreState(state);
36
		containerName = (String) this.getIntent().getExtras().get("Cname");
37
		path = (String) this.getIntent().getExtras().get("curPath");
38
		setUpInputs();
39
	}
40

  
41
	@Override
42
	protected void onSaveInstanceState(Bundle outState) {
43
		super.onSaveInstanceState(outState);
44
	}
45

  
46
	private void setUpInputs(){
47
		((Button) findViewById(R.id.new_file_button)).setOnClickListener(this);
48
		fileName = ((EditText)findViewById(R.id.file_name_text));
49
		fileName.append(".txt");
50
		contents = ((EditText)findViewById(R.id.new_file_text));
51
	}
52

  
53
	public void onClick(View arg0) {
54
		if ("".equals(fileName.getText().toString())) {
55
			showAlert("Required Fields Missing", " File name is required.");
56
		} else {
57
			trackEvent(GoogleAnalytics.CATEGORY_FILE, GoogleAnalytics.EVENT_CREATE, "", -1);
58
			new SaveFileTask().execute((Void[]) null);
59
		}
60
	}
61

  
62
	private class SaveFileTask extends AsyncTask<Void, Void, HttpBundle> {
63
		private CloudServersException exception;
64

  
65
		protected void onPreExecute(){
66
			showDialog();
67
		}
68

  
69
		@Override
70
		protected HttpBundle doInBackground(Void... arg0) {
71
			HttpBundle bundle = null;
72
			try {
73
				bundle = (new ContainerObjectManager(getContext())).addObject(containerName, path, fileName.getText().toString(), "text/plain", contents.getText().toString());
74
			} catch (CloudServersException e) {
75
				exception = e;
76
			}
77
			return bundle;
78
		}
79

  
80
		@Override
81
		protected void onPostExecute(HttpBundle bundle) {
82
			hideDialog();
83
			HttpResponse response = bundle.getResponse();
84
			if (response != null) {
85
				int statusCode = response.getStatusLine().getStatusCode();
86
				if (statusCode == 201) {
87
					setResult(Activity.RESULT_OK);
88
					finish();
89
				} else {
90
					CloudServersException cse = parseCloudServersException(response);
91
					if ("".equals(cse.getMessage())) {
92
						showError("There was a problem creating your file.", bundle);
93
					} else {
94
						showError("There was a problem creating your file: " + cse.getMessage() +  " See details for more information", bundle);
95
					}
96
				}
97
			} else if (exception != null) {
98
				showError("There was a problem creating your file: " + exception.getMessage()+ " See details for more information", bundle);				
99
			}			
100
		}
101
	}
102
}
b/src/com/rackspace/cloud/android/AddLoadBalancerActivity.java
1
package com.rackspace.cloud.android;
2

  
3
import java.util.ArrayList;
4

  
5
import org.apache.http.HttpResponse;
6

  
7
import android.app.Activity;
8
import android.content.Intent;
9
import android.os.AsyncTask;
10
import android.os.Bundle;
11
import android.text.Editable;
12
import android.text.TextWatcher;
13
import android.util.Log;
14
import android.view.View;
15
import android.view.View.OnClickListener;
16
import android.widget.AdapterView;
17
import android.widget.AdapterView.OnItemSelectedListener;
18
import android.widget.ArrayAdapter;
19
import android.widget.Button;
20
import android.widget.EditText;
21
import android.widget.Spinner;
22
import android.widget.TableRow;
23

  
24
import com.rackspace.cloud.android.R;
25
import com.rackspace.cloud.loadbalancer.api.client.Algorithm;
26
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancer;
27
import com.rackspace.cloud.loadbalancer.api.client.LoadBalancerManager;
28
import com.rackspace.cloud.loadbalancer.api.client.Node;
29
import com.rackspace.cloud.loadbalancer.api.client.Protocol;
30
import com.rackspace.cloud.loadbalancer.api.client.VirtualIp;
31
import com.rackspace.cloud.servers.api.client.Account;
32
import com.rackspace.cloud.servers.api.client.CloudServersException;
33
import com.rackspace.cloud.servers.api.client.Server;
34
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
35

  
36
public class AddLoadBalancerActivity extends CloudActivity implements OnItemSelectedListener {
37

  
38
	private static final String[] VIP_TYPES = {"Public", "ServiceNet", "Shared"};
39

  
40
	private static final int ADD_NODES_ACTIVITY_CODE = 165;
41
	private static final int SHARED_VIP_ACTIVITY_CODE = 235;
42

  
43
	private ArrayList<Node> nodes;
44
	private ArrayList<Server> possibleNodes;
45
	private LoadBalancer loadBalancer;
46
	private Protocol[] protocols;
47
	private Protocol selectedProtocol;
48
	private Algorithm[] algorithms;
49
	private Algorithm selectedAlgorithm;
50
	private VirtualIp selectedVip;
51
	private EditText portEditText;
52
	private Spinner protocolSpinner;
53
	private Spinner protocolSubSpinner;
54
	private Spinner algorithmSpinner;
55
	private Spinner vipSpinner;
56
	private Spinner regionSpinner;
57
	private Button selectVipButton;
58
	private Button selectNodesButton;
59
	private String selectedVipType;
60
	private String selectedRegion;
61
	private String selectedName;
62
	private String selectedPort;
63

  
64
	@Override
65
	public void onCreate(Bundle savedInstanceState) {
66
		super.onCreate(savedInstanceState);
67
		trackPageView(GoogleAnalytics.PAGE_ADD_LOADBALANCER);
68
		setContentView(R.layout.view_add_loadbalancer);
69
		restoreState(savedInstanceState);
70
	}
71

  
72
	@SuppressWarnings("unchecked")
73
	protected void restoreState(Bundle state) {
74
		super.restoreState(state);
75

  
76
		if(state != null && state.containsKey("nodes")){
77
			nodes = (ArrayList<Node>) state.getSerializable("nodes");
78
		}
79
		else{
80
			nodes = new ArrayList<Node>();
81
		}
82
		
83
		if(state != null && state.containsKey("possibleNodes")){
84
			possibleNodes = (ArrayList<Server>) state.getSerializable("possibleNodes");
85
		}
86
		else{
87
			possibleNodes = new ArrayList<Server>();
88
		}
89

  
90
		if(state != null && state.containsKey("selectedVip")){
91
			selectedVip = (VirtualIp) state.getSerializable("selectedVip");
92
		}
93
		
94
		setupText();
95
		loadProtocolSpinner();
96
		loadProtocolSubSpinner();
97
		loadAlgorithmSpinner();
98
		loadVipSpinner();
99
		loadRegionSpinner();
100
		setUpButtons();
101
	}
102

  
103
	@Override
104
	protected void onSaveInstanceState(Bundle outState) {
105
		super.onSaveInstanceState(outState);
106
		outState.putSerializable("nodes", nodes);
107
		outState.putSerializable("possibleNodes", possibleNodes);
108
		outState.putSerializable("selectedVip", selectedVip);
109
	}
110

  
111
	public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
112
		if (parent == protocolSpinner) {
113
			TableRow customProtocol = (TableRow)findViewById(R.id.custom_protocol_row);
114
			if(position < protocols.length){
115
				selectedProtocol = protocols[position];
116
				selectedPort = protocols[position].getDefaultPort();
117
				customProtocol.setVisibility(View.GONE);
118
			} else {
119
				customProtocol.setVisibility(View.VISIBLE);
120
			}
121
			updateVipIndicatorLight();
122
		} else if (parent == algorithmSpinner){
123
			selectedAlgorithm = algorithms[position];
124
		} else if (parent == vipSpinner){
125
			selectedVipType = VIP_TYPES[position];
126
			if(VIP_TYPES[position].equals("Shared")){
127
				((TableRow) findViewById(R.id.select_vip_layout)).setVisibility(View.VISIBLE);
128
			} else {
129
				((TableRow) findViewById(R.id.select_vip_layout)).setVisibility(View.GONE);
130
			}
131
			updateVipIndicatorLight();
132
		} else if (parent == regionSpinner){
133
			selectedRegion = Account.getAccount().getLoadBalancerRegions()[position];
134
			updateVipIndicatorLight();
135
		} else if (parent == protocolSubSpinner){
136
			selectedProtocol = protocols[position];
137
			updateVipIndicatorLight();
138
		}
139
	}
140

  
141
	public void onNothingSelected(AdapterView<?> parent) {
142

  
143
	}
144

  
145
	private void setUpButtons(){
146
		selectVipButton = (Button) findViewById(R.id.selected_shared_vip);
147
		updateVipIndicatorLight();
148
		selectVipButton.setOnClickListener(new OnClickListener() {
149
			@Override
150
			public void onClick(View v) {
151
				Intent viewIntent = new Intent(getApplicationContext(), SharedVipActivity.class);
152
				viewIntent.putExtra("loadBalancerPort", selectedPort);
153
				viewIntent.putExtra("loadBalancerRegion", selectedRegion);
154
				viewIntent.putExtra("selectedVip", selectedVip);
155
				startActivityForResult(viewIntent, SHARED_VIP_ACTIVITY_CODE);				
156
			}
157
		});
158
		((TableRow) findViewById(R.id.select_vip_layout)).setVisibility(View.GONE);
159

  
160
		selectNodesButton = (Button) findViewById(R.id.add_nodes_button);
161
		updateNodesIndicatorLight();
162
		selectNodesButton.setOnClickListener(new OnClickListener() {
163
			@Override
164
			public void onClick(View v) {
165
				Intent viewIntent = new Intent(getApplicationContext(), AddNodesActivity.class);
166
				viewIntent.putExtra("nodes", nodes);
167
				if(validPort(selectedPort)){
168
					viewIntent.putExtra("loadBalancerPort", selectedPort);
169
				}
170
				viewIntent.putExtra("possibleNodes", possibleNodes);
171
				startActivityForResult(viewIntent, ADD_NODES_ACTIVITY_CODE);
172
			}
173
		});
174

  
175
		Button addLoadBalancer = (Button) findViewById(R.id.add_lb_button);
176
		addLoadBalancer.setOnClickListener(new OnClickListener() {
177

  
178
			@Override
179
			public void onClick(View v) {
180
				selectedName = ((EditText)findViewById(R.id.edit_lb_name_text)).getText().toString();
181
				//selectedPort = ((EditText)findViewById(R.id.edit_port_text)).getText().toString();
182
				if(!validName()){
183
					showAlert("Error", "Load balancer name cannot be blank.");
184
				} else if(!validPort(selectedPort)){
185
					showAlert("Error", "Must have a protocol port number that is between 1 and 65535.");
186
				} else if(!validVip()){
187
					showAlert("Error", "Please select a valid Virtual IP.");
188
				} else if(!validNodes()){
189
					showAlert("Error", "You must select at least one enabled cloud server or add and enable at least one external node.");
190
				} else {
191
					loadBalancer = new LoadBalancer();
192
					loadBalancer.setName(selectedName);
193
					loadBalancer.setProtocol(selectedProtocol.getName());
194
					loadBalancer.setPort(selectedPort);
195
					loadBalancer.setVirtualIpType(selectedVipType);
196
					loadBalancer.setAlgorithm(selectedAlgorithm.getName());
197
					loadBalancer.setRegion(selectedRegion);
198
					loadBalancer.setNodes(nodes);
199
					if(selectedVip != null){
200
						ArrayList<VirtualIp> vips = new ArrayList<VirtualIp>();
201
						vips.add(selectedVip);
202
						loadBalancer.setVirtualIps(vips);
203
					}
204
					trackEvent(GoogleAnalytics.CATEGORY_LOAD_BALANCER, GoogleAnalytics.EVENT_CREATE, "", -1);
205
					new AddLoadBalancerTask().execute();
206
					Log.d("info", "the port is " + selectedPort);
207
				}
208
			}
209
		});
210
	}
211

  
212
	private boolean validName(){
213
		return !selectedName.equals("");
214
	}
215

  
216
	private boolean validPort(String selectedPort){
217
		boolean result;
218
		try{
219
			result = !selectedPort.equals("") && Integer.valueOf(selectedPort) > 0 && Integer.valueOf(selectedPort) < 65536; 
220
		} catch (NumberFormatException e){
221
			result = false;
222
		}
223
		return result;
224
	}
225

  
226
	private boolean validNodes(){
227
		boolean exist = nodes != null && nodes.size() > 0;
228
		boolean enabled = false;
229
		for(Node n: nodes){
230
			enabled = enabled || n.getCondition().equalsIgnoreCase("enabled");
231
		}
232
		return exist && enabled;
233
	}
234

  
235
	private boolean validVip(){
236
		/*
237
		 * assign selectedVipType to the
238
		 * first value in the list, the default
239
		 * if its null
240
		 */
241
		if(selectedVipType == null){
242
			selectedVipType = VIP_TYPES[0];
243
		}
244
		return !selectedVipType.equalsIgnoreCase("Shared") 
245
		||(selectedVip != null && !selectedVip.getLoadBalancer().getPort().equals(selectedPort) 
246
				&& selectedVip.getLoadBalancer().getRegion().equals(selectedRegion));
247
	}
248
	
249
	private void updateNodesIndicatorLight(){
250
		if(validNodes()){
251
			selectNodesButton.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0);
252
		} else {
253
			selectNodesButton.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_notification_overlay,0);
254
		}
255
	}
256

  
257
	private void updateVipIndicatorLight(){
258
		if(validVip()){
259
			selectVipButton.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0);
260
		} else {
261
			selectVipButton.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_notification_overlay,0);
262
		}
263
	}
264

  
265
	private void setupText(){
266
		portEditText = (EditText)findViewById(R.id.edit_port_text);
267
		portEditText.addTextChangedListener(new TextWatcher() {
268

  
269
			@Override
270
			public void onTextChanged(CharSequence s, int start, int before, int count) {
271
				selectedPort = s.toString();
272
				updateVipIndicatorLight();
273
			}		
274
			@Override
275
			public void beforeTextChanged(CharSequence s, int start, int count,
276
					int after) {
277
				// do nothing
278
			}
279
			@Override
280
			public void afterTextChanged(Editable s) {
281
				// do nothing
282
			}
283
		});
284
	}
285

  
286
	private void loadRegionSpinner() {
287
		regionSpinner = (Spinner) findViewById(R.id.edit_region_spinner);
288
		regionSpinner.setOnItemSelectedListener(this);
289

  
290
		ArrayAdapter<String> regionAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, 
291
				Account.getAccount().getLoadBalancerRegions());
292
		regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
293
		regionSpinner.setAdapter(regionAdapter);
294
	}
295

  
296
	private void loadVipSpinner() {
297
		vipSpinner = (Spinner) findViewById(R.id.edit_vip_spinner);
298
		vipSpinner.setOnItemSelectedListener(this);
299

  
300
		ArrayAdapter<String> vipAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, VIP_TYPES);
301
		vipAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
302
		vipSpinner.setAdapter(vipAdapter);
303
	}
304

  
305
	private void loadProtocolSpinner() {
306
		protocolSpinner = (Spinner) findViewById(R.id.edit_protocol_spinner);
307
		protocolSpinner.setOnItemSelectedListener(this);
308
		String protocolNames[] = new String[Protocol.getProtocols().size() + 1]; 
309
		protocols = new Protocol[Protocol.getProtocols().size()];
310

  
311
		int httpIndex = 0;
312
		for(int i = 0; i < Protocol.getProtocols().size(); i++){
313
			protocols[i] = Protocol.getProtocols().get(i);
314
			protocolNames[i] = Protocol.getProtocols().get(i).getName() + " (" + Protocol.getProtocols().get(i).getDefaultPort() + ")";
315
			if(Protocol.getProtocols().get(i).getName().equals("HTTP")){
316
				httpIndex = i;
317
			}
318
		}
319
		protocolNames[protocolNames.length - 1] = "Custom";
320

  
321
		ArrayAdapter<String> protocolAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, protocolNames);
322
		protocolAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
323
		protocolSpinner.setAdapter(protocolAdapter);
324
		protocolSpinner.setSelection(httpIndex);
325

  
326
	}
327

  
328
	/*
329
	 * this is the spinner for protocol selection that 
330
	 * appears if custom is chosen from protocolSpinner
331
	 */
332
	private void loadProtocolSubSpinner() {
333
		protocolSubSpinner = (Spinner) findViewById(R.id.edit_protocol_sub_spinner);
334
		protocolSubSpinner.setOnItemSelectedListener(this);
335
		String protocolNames[] = new String[Protocol.getProtocols().size()]; 
336

  
337
		for(int i = 0; i < Protocol.getProtocols().size(); i++){
338
			protocolNames[i] = Protocol.getProtocols().get(i).getName();
339
		}
340

  
341
		ArrayAdapter<String> protocolAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, protocolNames);
342
		protocolAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
343
		protocolSubSpinner.setAdapter(protocolAdapter);
344
	}
345

  
346
	private void loadAlgorithmSpinner() {
347
		algorithmSpinner = (Spinner) findViewById(R.id.edit_algorithm_spinner);
348
		algorithmSpinner.setOnItemSelectedListener(this);
349
		String algorithmNames[] = new String[Algorithm.getAlgorithms().size()]; 
350
		algorithms = new Algorithm[Algorithm.getAlgorithms().size()];
351

  
352
		for(int i = 0; i < Algorithm.getAlgorithms().size(); i++){
353
			algorithms[i] = Algorithm.getAlgorithms().get(i);
354
			algorithmNames[i] = getPrettyAlgoName(Algorithm.getAlgorithms().get(i).getName());
355
		}
356

  
357
		ArrayAdapter<String> algorithmAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, algorithmNames);
358
		algorithmAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
359
		algorithmSpinner.setAdapter(algorithmAdapter);
360
	}
361

  
362
	private String getPrettyAlgoName(String name){
363
		if(name == null || name.length() == 0){
364
			return "";
365
		} else {
366
			String result = name.charAt(0) + "";
367
			boolean previousWasSpace = false;;
368
			for(int i = 1; i < name.length(); i++){
369
				char curLetter = name.charAt(i);
370
				if(curLetter == '_'){
371
					result += " ";
372
					previousWasSpace = true;
373
				} else {
374
					if(previousWasSpace){
375
						result += Character.toUpperCase(curLetter);
376
					} else {
377
						result += Character.toLowerCase(curLetter);
378
					}
379
					previousWasSpace = false;
380
				}
381
			}
382
			return result;
383
		}
384
	}
385
	
386
	private class AddLoadBalancerTask extends AsyncTask<Void, Void, HttpBundle> {
387
		private CloudServersException exception;
388

  
389
		protected void onPreExecute(){
390
			showDialog();
391
		}
392

  
393
		@Override
394
		protected HttpBundle doInBackground(Void... arg0) {
395
			HttpBundle bundle = null;
396
			try {
397
				bundle = (new LoadBalancerManager(getContext())).create(loadBalancer, LoadBalancer.getRegionUrl(selectedRegion));
398
			} catch (CloudServersException e) {
399
				exception = e;
400
			}
401
			return bundle;
402
		}
403

  
404
		@Override
405
		protected void onPostExecute(HttpBundle bundle) {
406
			hideDialog();
407
			HttpResponse response = bundle.getResponse();
408
			if (response != null) {
409
				int statusCode = response.getStatusLine().getStatusCode();
410
				if (statusCode == 202) {
411
					setResult(Activity.RESULT_OK);
412
					finish();
413
				} else {
414
					CloudServersException cse = parseCloudServersException(response);
415
					if ("".equals(cse.getMessage())) {
416
						showError("There was a problem creating your load balancer.", bundle);
417
					} else {
418
						//if container with same name already exists
419
						showError("There was a problem creating your load balancer: " + cse.getMessage() + "\n See details for more information", bundle);
420
					}
421
				}
422
			} else if (exception != null) {
423
				showError("There was a problem creating your container: " + exception.getMessage()+"\n See details for more information.", bundle);				
424
			}
425
			finish();
426
		}
427
	}
428

  
429
	private void printNodes(ArrayList<Node> nodes){
430
		for(Node n : nodes){
431
			Log.d("info", "node is: " + n.getAddress());
432
		}
433
	}
434
	
435
	@SuppressWarnings("unchecked")
436
	@Override
437
	protected void onActivityResult (int requestCode, int resultCode, Intent data){
438
		if(requestCode == ADD_NODES_ACTIVITY_CODE && resultCode == RESULT_OK){
439
			//set node list
440
			nodes = ((ArrayList<Node>)data.getSerializableExtra("nodes"));
441
			updateNodesIndicatorLight();
442
			printNodes(nodes);
443
		}
444
		else if(requestCode == ADD_NODES_ACTIVITY_CODE && resultCode == RESULT_CANCELED){
445
			//don't change list
446
		}
447
		else if(requestCode == SHARED_VIP_ACTIVITY_CODE){
448
			if(data != null){
449
				selectedVip = (VirtualIp)data.getSerializableExtra("selectedVip");
450
			}
451
			updateVipIndicatorLight();
452
		}
453
	}
454
}
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff