package net.networksaremadeofstring.cyllell; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.json.JSONArray; import org.json.JSONObject; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.database.Cursor; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.view.ActionMode; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; public class ViewNodes_Fragment extends SherlockFragment { Cuts Cut = null; JSONObject Nodes = null; HashMap<String, String> NodeMap; List<Node> listOfNodes = new ArrayList<Node>(); ListView list; ProgressDialog dialog; NodeListAdaptor NodeAdapter; Handler updateListNotify; Handler handler; Thread GetFullDetails; private SharedPreferences settings = null; Boolean CutInProgress = false; Boolean Paused = false; Thread dataPreload; String instanceTime = ""; int selectedNode = 0; ActionMode mActionMode; AlertDialog nodeContextualDialog; Dialog rawJSON; public void onActivityCreated(Bundle savedInstanceState) { Log.e("onActivityCreated","Called"); super.onCreate(savedInstanceState); setRetainInstance(true); settings = this.getActivity().getSharedPreferences("Cyllell", 0); if(settings.getBoolean("NodesFirstView", true) == true) { Toast.makeText(getActivity(),"Perform a short press to see OHAI info or perform a long press to edit nodes.", Toast.LENGTH_LONG).show(); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean("NodesFirstView", false); editor.commit(); } list = (ListView) this.getActivity().findViewById(R.id.nodesListView); list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); try { Cut = new Cuts(this.getActivity()); } catch (Exception e) { e.printStackTrace(); } dialog = new ProgressDialog(this.getActivity()); dialog.setTitle("Contacting Chef"); dialog.setMessage("Please wait: Prepping Authentication protocols"); dialog.setIndeterminate(true); if(listOfNodes.size() < 1) { dialog.show(); } updateListNotify = new Handler() { public void handleMessage(Message msg) { int tag = msg.getData().getInt("tag", 999999); if(msg.what == 0) { if(tag != 999999) { //Log.i("TAG - Handler", Integer.toString(tag)); listOfNodes.get(tag).SetSpinnerVisible(); //list.invalidate(); } } else if(msg.what == 1) { //Get rid of the lock CutInProgress = false; //the notifyDataSetChanged() will handle the rest } else if (msg.what == 99) { if(tag != 999999) { Toast.makeText(ViewNodes_Fragment.this.getActivity(), "An error occured during that operation.", Toast.LENGTH_LONG).show(); //Log.i("TAG - Handler", Integer.toString(tag)); listOfNodes.get(tag).SetErrorState(); } } NodeAdapter.notifyDataSetChanged(); } }; handler = new Handler() { public void handleMessage(Message msg) { //Once we've checked the data is good to use start processing it if(msg.what == 0) { OnClickListener listener = new OnClickListener() { public void onClick(View v) { GetMoreDetails((Integer)v.getTag()); } }; OnLongClickListener listenerLong = new OnLongClickListener() { public boolean onLongClick(View v) { selectForCAB((Integer)v.getTag()); return true; } }; NodeAdapter = new NodeListAdaptor(getActivity(), listOfNodes,listener,listenerLong); list = (ListView) getActivity().findViewById(R.id.nodesListView); if(list != null) { if(NodeAdapter != null) { list.setAdapter(NodeAdapter); } else { //Log.e("NodeAdapter","NodeAdapter is null"); } } else { //Log.e("List","List is null"); } dialog.dismiss(); } else if(msg.what == 200) { dialog.setMessage("Sending request to Chef..."); } else if(msg.what == 201) { dialog.setMessage("Parsing JSON....."); } else if(msg.what == 202) { dialog.setMessage("Populating UI!"); } else if(msg.what == 300) { //Toast.makeText(ViewNodes_Fragment.this.getActivity(), "Making Request", Toast.LENGTH_SHORT).show(); dialog = new ProgressDialog(ViewNodes_Fragment.this.getActivity()); dialog.setTitle("Contacting Chef"); dialog.setMessage("Changing Environment"); dialog.setIndeterminate(true); dialog.show(); } else if(msg.what == 301) { dialog.dismiss(); Toast.makeText(ViewNodes_Fragment.this.getActivity(), "Node Updated!", Toast.LENGTH_SHORT).show(); if(nodeContextualDialog != null && nodeContextualDialog.isShowing()) { nodeContextualDialog.dismiss(); } listOfNodes.get(selectedNode).SetSelected(false); selectedNode = 0; NodeAdapter.notifyDataSetChanged(); } else if(msg.what == 302) { dialog.dismiss(); Toast.makeText(ViewNodes_Fragment.this.getActivity(), "There was a problem updating that node.", Toast.LENGTH_SHORT).show(); } else if(msg.what == 303) { dialog.dismiss(); Toast.makeText(ViewNodes_Fragment.this.getActivity(), "You are not authorized to update that node.\r\n[Hosted Chef RBAC]", Toast.LENGTH_SHORT).show(); } //-------------- Edit Run List else if(msg.what == 400) { //Toast.makeText(ViewNodes_Fragment.this.getActivity(), "Making Request", Toast.LENGTH_SHORT).show(); dialog = new ProgressDialog(ViewNodes_Fragment.this.getActivity()); dialog.setTitle("Contacting Chef"); dialog.setMessage("Adding to run list...."); dialog.setIndeterminate(true); dialog.show(); } else if(msg.what == 401) { dialog.dismiss(); Toast.makeText(ViewNodes_Fragment.this.getActivity(), "Node Updated!", Toast.LENGTH_SHORT).show(); nodeContextualDialog.dismiss(); listOfNodes.get(selectedNode).SetSelected(false); selectedNode = 0; NodeAdapter.notifyDataSetChanged(); } else if(msg.what == 402) { dialog.dismiss(); Toast.makeText(ViewNodes_Fragment.this.getActivity(), "There was a problem updating that node.", Toast.LENGTH_SHORT).show(); } else if(msg.what == 403) { dialog.dismiss(); Toast.makeText(ViewNodes_Fragment.this.getActivity(), "You are not authorized to update that node.\r\n[Hosted Chef RBAC]", Toast.LENGTH_SHORT).show(); } //-------------- End Edit Run List //-------------- RAW JSON else if(msg.what == 500) { ((TextView) rawJSON.findViewById(R.id.JSON)).setText(msg.getData().getString("RawJSON")); ((ProgressBar) rawJSON.findViewById(R.id.gettinJSONProgressBar)).setVisibility(8); ((Button) rawJSON.findViewById(R.id.saveRawJSON)).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { try { final String URI = listOfNodes.get(selectedNode).GetURI(); final JSONObject newJSON = new JSONObject(((TextView) rawJSON.findViewById(R.id.JSON)).getText().toString()); handler.sendEmptyMessage(400); Thread ProcessRequest = new Thread() { public void run() { try { if(Cut.UpdateNodewithRawJSON(URI,newJSON)) { handler.sendEmptyMessage(301); } else { handler.sendEmptyMessage(302); } } catch (org.apache.http.client.HttpResponseException e) { Log.e("StatusCode",Integer.toString(e.getStatusCode())); if(e.getStatusCode() == 401 || e.getStatusCode() == 403) { handler.sendEmptyMessage(403); } else { e.printStackTrace(); handler.sendEmptyMessage(402); } } catch (Exception e) { e.printStackTrace(); handler.sendEmptyMessage(402); } } }; ProcessRequest.start(); } catch(Exception e) { e.printStackTrace(); handler.sendEmptyMessage(501); } } }); } else if(msg.what == 501) { dialog.dismiss(); Toast.makeText(ViewNodes_Fragment.this.getActivity(), "Error: Invalid JSON", Toast.LENGTH_SHORT).show(); } //-------------- END RAW JSON else { //Close the Progress dialog dialog.dismiss(); //Alert the user that something went terribly wrong AlertDialog alertDialog = new AlertDialog.Builder(ViewNodes_Fragment.this.getActivity()).create(); alertDialog.setTitle("API Error"); alertDialog.setMessage("There was an error communicating with the API:\n" + msg.getData().getString("exception")); alertDialog.setButton2("Back", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { ViewNodes_Fragment.this.getActivity().finish(); } }); alertDialog.setIcon(R.drawable.icon); alertDialog.show(); } } }; dataPreload = new Thread() { public void run() { if(listOfNodes.size() > 0) { handler.sendEmptyMessage(0); } else { try { handler.sendEmptyMessage(200); Nodes = Cut.GetNodes(); handler.sendEmptyMessage(201); JSONArray Keys = Nodes.names(); for(int i = 0; i < Nodes.length(); i++) { String URI = Nodes.getString(Keys.get(i).toString()).replaceFirst("^(https://|http://).*/nodes/", ""); //Log.i("URI", URI); listOfNodes.add(new Node(Keys.get(i).toString(), URI)); } handler.sendEmptyMessage(202); handler.sendEmptyMessage(0); } catch (Exception e) { Message msg = new Message(); Bundle data = new Bundle(); data.putString("exception", e.getMessage()); msg.setData(data); msg.what = 1; handler.sendMessage(msg); } } return; } }; dataPreload.start(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.e("onCreateView","Called"); return inflater.inflate(R.layout.nodeslanding, container, false); } public void GetMoreDetails(final int Tag) { GetFullDetails = new Thread() { public void run() { try { //Log.i("TAG", Integer.toString(Tag)); Message msg = new Message(); Bundle data = new Bundle(); data.putInt("tag", Tag); msg.setData(data); msg.what = 0; //Set the spinner going updateListNotify.sendMessage(msg); Cuts threadCut = new Cuts(ViewNodes_Fragment.this.getActivity()); listOfNodes.get(Tag).SetFullDetails(threadCut.CanonicalizeNode(threadCut.GetNode(listOfNodes.get(Tag).GetURI()))); updateListNotify.sendEmptyMessage(1); } catch (Exception e) { //Log.e("GetMoreDetails","An actual exception occured!"); e.printStackTrace(); Message msg = new Message(); Bundle data = new Bundle(); data.putInt("tag", Tag); msg.setData(data); msg.what = 99; updateListNotify.sendMessage(msg); } return; } }; GetFullDetails.start(); } public void selectForCAB(int id) { selectedNode = id; mActionMode = getSherlockActivity().startActionMode(mActionModeCallback); listOfNodes.get(selectedNode).SetSelected(true); NodeAdapter.notifyDataSetChanged(); } private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { // Called when the action mode is created; startActionMode() was called @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate a menu resource providing context menu items MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.cab_nodes, menu); mode.setTitle("knife node edit " + listOfNodes.get(selectedNode).GetName()); //mode.setSubtitle("'knife node edit'"); /*menu.getItem(0).setShowAsActionFlags(4); menu.getItem(1).setShowAsActionFlags(4);*/ return true; } // Called each time the action mode is shown. Always called after onCreateActionMode, but // may be called multiple times if the mode is invalidated. @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; // Return false if nothing is done } // Called when the user selects a contextual menu item @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.EditRawJSON: { Context mContext = getActivity(); rawJSON = new Dialog(mContext); rawJSON.setContentView(R.layout.edit_raw_json); rawJSON.setTitle("Edit Node JSON"); rawJSON.show(); final String URI = listOfNodes.get(selectedNode).GetURI(); Thread GetRawJSON = new Thread() { private Message msg = new Message(); private Bundle data = new Bundle(); public void run() { try { JSONObject Node = Cut.GetNode(URI); data.putString("RawJSON", Node.toString(3)); msg.setData(data); msg.what = 500; handler.sendMessage(msg); } catch (org.apache.http.client.HttpResponseException e) { Log.e("StatusCode",Integer.toString(e.getStatusCode())); if(e.getStatusCode() == 401 || e.getStatusCode() == 403) { handler.sendEmptyMessage(403); } else { e.printStackTrace(); handler.sendEmptyMessage(402); } } catch (Exception e) { e.printStackTrace(); handler.sendEmptyMessage(402); } } }; GetRawJSON.start(); return true; } case R.id.EditRunList: { Cursor dbResults = ((MainLanding) getActivity()).cacheDB.getRoles(); final CharSequence[] items = new CharSequence[dbResults.getCount()]; int i = 0; while(dbResults.moveToNext()) { items[i] = dbResults.getString(0); i++; } AlertDialog.Builder builder = new AlertDialog.Builder(ViewNodes_Fragment.this.getActivity()); builder.setTitle("Add Roles to Runlist"); builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { final String URI = listOfNodes.get(selectedNode).GetURI(); final String Role = items[item].toString(); handler.sendEmptyMessage(400); Thread ProcessRequest = new Thread() { /*private Boolean continueThread = true; private Message msg = new Message(); private Bundle data = new Bundle();*/ public void run() { try { if(Cut.AddRunList(URI, Role)) { handler.sendEmptyMessage(301); } else { handler.sendEmptyMessage(302); } } catch (org.apache.http.client.HttpResponseException e) { Log.e("StatusCode",Integer.toString(e.getStatusCode())); if(e.getStatusCode() == 401 || e.getStatusCode() == 403) { handler.sendEmptyMessage(403); } else { e.printStackTrace(); handler.sendEmptyMessage(402); } } catch (Exception e) { e.printStackTrace(); handler.sendEmptyMessage(402); } } }; ProcessRequest.start(); } }); nodeContextualDialog = builder.create(); nodeContextualDialog.show(); return true; } case R.id.EditEnv: { Cursor dbResults = ((MainLanding) getActivity()).cacheDB.getEnvironments(); final CharSequence[] items = new CharSequence[dbResults.getCount()]; int i = 0; while(dbResults.moveToNext()) { items[i] = dbResults.getString(0); i++; } AlertDialog.Builder builder = new AlertDialog.Builder(ViewNodes_Fragment.this.getActivity()); builder.setTitle("Set Environment"); builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { final String URI = listOfNodes.get(selectedNode).GetURI(); final String Env = items[item].toString(); handler.sendEmptyMessage(300); Thread ProcessRequest = new Thread() { /*private Boolean continueThread = true; private Message msg = new Message(); private Bundle data = new Bundle();*/ public void run() { try { if(Cut.SetEnvironment(URI, Env)) { handler.sendEmptyMessage(301); } else { handler.sendEmptyMessage(302); } } catch (org.apache.http.client.HttpResponseException e) { Log.e("StatusCode",Integer.toString(e.getStatusCode())); if(e.getStatusCode() == 401 || e.getStatusCode() == 403) { handler.sendEmptyMessage(303); } else { e.printStackTrace(); handler.sendEmptyMessage(302); } } catch (Exception e) { e.printStackTrace(); handler.sendEmptyMessage(302); } } }; ProcessRequest.start(); } }); nodeContextualDialog = builder.create(); nodeContextualDialog.show(); return true; } default: listOfNodes.get(selectedNode).SetSelected(false); selectedNode = 0; NodeAdapter.notifyDataSetChanged(); return false; } } // Called when the user exits the action mode @Override public void onDestroyActionMode(ActionMode mode) { listOfNodes.get(selectedNode).SetSelected(false); selectedNode = 0; mActionMode = null; NodeAdapter.notifyDataSetChanged(); } }; public void onDestroyView() { super.onDestroyView(); dialog.dismiss(); } public void onDestroy() { super.onDestroy(); dialog.dismiss(); } }