com.rightscale.app.dashboard.ShowServerMonitoring.java Source code

Java tutorial

Introduction

Here is the source code for com.rightscale.app.dashboard.ShowServerMonitoring.java

Source

// Dashboard: an Android front-end to the RightScale dashboard
// Copyright (C) 2009 Tony Spataro <code@tracker.xeger.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package com.rightscale.app.dashboard;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;

import net.xeger.rest.RestException;
import net.xeger.rest.RestServerException;
import net.xeger.rest.Session;
import net.xeger.rest.ui.ContentTransfer;
import net.xeger.rest.ui.ImageConsumer;
import net.xeger.rest.ui.ImageProducer;

import com.rightscale.provider.*;
import com.rightscale.provider.rest.*;

public class ShowServerMonitoring extends AbstractServerActivity implements ImageProducer, ImageConsumer {
    static private final String[] FROM = { "graph_name" };
    static private final int[] TO = { android.R.id.text1 };

    public static final String MONITORS = "monitors";

    public static final String THUMB = "thumb";
    public static final String SMALL = "small";
    public static final String LARGE = "large";

    public static final String DAY = "day";
    public static final String NOW = "now";

    static public final String[] SIZES = { THUMB, SMALL, LARGE };
    static public final String[] PERIODS = { DAY, NOW };

    static public final String DEFAULT_SIZE = SMALL;
    static public final String DEFAULT_PERIOD = NOW;

    private URI _selectedGraphUri = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.show_server_monitoring);
    }

    public void showGraph(String template, String size, String period) {
        URI uri = URI.create(template);
        Map<String, String> query = parseQueryParams(uri);
        query.put("size", size);
        query.put("period", period);

        StringBuffer qstr = new StringBuffer();
        for (String key : query.keySet()) {
            if (qstr.length() > 0)
                qstr.append('&');
            qstr.append(key);
            qstr.append('=');
            qstr.append(query.get(key));
        }

        int qmark = template.indexOf('?');
        if (qmark < 0) {
            throw new IllegalArgumentException("URI does not contain query-string marker: " + template);

        }

        String prefix = template.substring(0, qmark);
        //TODO thread safety
        _selectedGraphUri = URI.create(prefix + '?' + qstr);
        ContentTransfer.loadImage(this, this, new Handler());
    }

    private Map<String, String> parseQueryParams(URI uri) {
        Map<String, String> queryParams = new HashMap<String, String>();

        String query = uri.getRawQuery();
        String[] items = query.split("&");
        for (String item : items) {
            String[] pair = item.split("=");
            if (pair.length >= 2) {
                queryParams.put(pair[0], pair[1]);
            }
        }

        return queryParams;
    }

    private Cursor _cursor;

    public void consumeContent(Cursor cursor, String tag) {
        super.consumeContent(cursor, tag);

        if (tag == MONITORS) {
            _cursor = cursor;
            startManagingCursor(cursor);
            SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item,
                    cursor, FROM, TO);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            Spinner spinner = (Spinner) findViewById(R.id.show_server_monitoring_spinner);
            spinner.setEnabled(true);
            spinner.setAdapter(adapter);
            spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    int colHref = _cursor.getColumnIndexOrThrow("href");
                    _cursor.moveToPosition(position);
                    String href = _cursor.getString(colHref);
                    showGraph(href, DEFAULT_SIZE, DEFAULT_PERIOD);
                }

                public void onNothingSelected(AdapterView<?> arg0) {
                    //TODO: clear the monitoring graph (fade out, oooh!)
                }
            });
        }
    }

    public void loadContent() {
        //NOTE: we don't call super since most server info isn't needed
        _helper.onLoadContent();
        ContentTransfer.load(this, this, new Handler(), MONITORS);
    }

    public Cursor produceContent(String tag) throws RestException {
        if (tag == MONITORS) {
            ContentResolver cr = getContentResolver();
            String[] whereArgs = { _helper.getAccountId(), getServerId() };
            return cr.query(_helper.getContentRoute("server_monitors"), Dashboard.SERVER_MONITORS_COLUMNS,
                    "account_id = ? AND server_id = ?", whereArgs, null);
        } else {
            return super.produceContent(tag);
        }
    }

    public void consumeImage(Bitmap bitmap, String tag) {
        ImageView view = (ImageView) findViewById(R.id.show_server_monitoring_graph);

        if (bitmap != null) {
            view.setScaleType(ImageView.ScaleType.FIT_CENTER);
            view.setImageBitmap(bitmap);
        } else {
            view.setScaleType(ImageView.ScaleType.CENTER);
            view.setImageDrawable(
                    getBaseContext().getResources().getDrawable(android.R.drawable.ic_menu_close_clear_cancel));
        }
    }

    public Bitmap produceImage(String tag) throws RestException {
        //TODO thread safety
        if (_selectedGraphUri == null) {
            return null;
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 1;

        try {
            Bitmap bitmap = null;
            InputStream in = null;
            in = openHttpConnection(_selectedGraphUri);
            bitmap = BitmapFactory.decodeStream(in, null, options);
            in.close();
            return bitmap;
        } catch (IOException e) {
            throw new RestException(e);
        }
    }

    public InputStream openHttpConnection(URI uri) throws RestException {
        try {
            Session session = com.rightscale.provider.Dashboard.createSession(getBaseContext());

            HttpClient client = ((DashboardSession) session).createAnonymousClient();

            HttpGet get = session.createGet(uri);
            HttpResponse response = client.execute(get);
            int status = response.getStatusLine().getStatusCode();

            if (status == 200) {
                return response.getEntity().getContent();
            } else {
                StatusLine sl = response.getStatusLine();
                throw new RestServerException(sl.getReasonPhrase(), sl.getStatusCode());
            }
        } catch (IOException e) {
            throw new net.xeger.rest.RestNetworkException(e);
        }

    }

    public void consumeContentError(Throwable t, String tag) {
        Spinner spinner = (Spinner) findViewById(R.id.show_server_monitoring_spinner);
        spinner.setEnabled(false);

        consumeImage(null, null);

        //We get RestException (422) when there is no monitoring for a server, and for some reason we see it
        //as RestAuthException here. In this particular view, rather than displaying an error dialog, we
        //just swallow the error (but hide the throbber).
        if (t.getCause() instanceof RestException) {
            _helper.hideThrobber(true);

        } else {
            _helper.onConsumeContentError(t);
        }
    }

    public void consumeImageError(Throwable error, String tag) {
        consumeContentError(error, tag);
    }
}