es.ugr.swad.swadroid.modules.Module.java Source code

Java tutorial

Introduction

Here is the source code for es.ugr.swad.swadroid.modules.Module.java

Source

/*
 *  This file is part of SWADroid.
 *
 *  Copyright (C) 2010 Juan Miguel Boyero Corral <juanmi1982@gmail.com>
 *
 *  SWADroid 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.
 *
 *  SWADroid 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 SWADroid.  If not, see <http://www.gnu.org/licenses/>.
 */

package es.ugr.swad.swadroid.modules;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONException;
import org.json.JSONObject;
import org.ksoap2.SoapFault;
import org.ksoap2.transport.HttpResponseException;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.SocketTimeoutException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.concurrent.TimeoutException;

import javax.net.ssl.SSLException;

import es.ugr.swad.swadroid.Constants;
import es.ugr.swad.swadroid.Preferences;
import es.ugr.swad.swadroid.R;
import es.ugr.swad.swadroid.gui.MenuActivity;
import es.ugr.swad.swadroid.utils.Utils;
import es.ugr.swad.swadroid.webservices.IWebserviceClient;
import es.ugr.swad.swadroid.webservices.RESTClient;
import es.ugr.swad.swadroid.webservices.SOAPClient;

/**
 * Superclass for encapsulate common behavior of all modules.
 * 
 * @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
 */
public abstract class Module extends MenuActivity {
    /**
     * Class Module's tag name for Logcat
     */
    private static final String TAG = Constants.APP_TAG + " Module";
    /**
     * Async Task for background jobs
     */
    private Connect connect;
    /**
     * Client for SWAD webservices
     */
    private IWebserviceClient webserviceClient;
    /**
     * Webservice result.
     */
    protected Object result;
    /**
     * Shows error messages.
     */
    private AlertDialog errorDialog = null;
    /**
     * Progress dialog
     */
    private ProgressDialog progressDialog = null;
    /**
     * Flag for show the progress dialog
     */
    private final boolean showDialog = false;
    /**
     * Connection available flag
     */
    protected static boolean isConnected;
    /**
     * METHOD_NAME param for webservice request.
     */
    private String METHOD_NAME = "";

    /**
     * Connects to SWAD and gets user data.
     * 
     * @throws NoSuchAlgorithmException
     * @throws IOException
     * @throws XmlPullParserException
     * @throws Exception
     */
    protected abstract void requestService() throws Exception;

    /**
     * Launches action in a separate thread while shows a progress dialog in UI
     * thread.
     */
    protected abstract void connect();

    /**
     * Launches action after executing connect() method
     */
    protected abstract void postConnect();

    /**
     * Error handler
     */
    protected abstract void onError();

    /**
     * Run connection. Launch Login activity when required
     */
    protected void runConnection() {
        isConnected = Utils.connectionAvailable(this);
        if (!isConnected) {
            Toast.makeText(this, R.string.errorMsgNoConnection, Toast.LENGTH_SHORT).show();
        } else {
            // If this is not the Login module, launch login check
            if (!(this instanceof Login)) {
                Intent loginActivity = new Intent(this, Login.class);
                startActivityForResult(loginActivity, Constants.LOGIN_REQUEST_CODE);
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onCreate()
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Check if debug mode is enabled

        try {
            getPackageManager().getApplicationInfo(getPackageName(), 0);
            isDebuggable = (ApplicationInfo.FLAG_DEBUGGABLE != 0);
        } catch (NameNotFoundException e1) {
            e1.printStackTrace();
        }

        // Initialize webservices client
        webserviceClient = null;

        super.onCreate(savedInstanceState);

        // Recover the launched async task if the activity is re-created
        connect = (Connect) getLastNonConfigurationInstance();
        if (connect != null) {
            connect.activity = new WeakReference<Module>(this);
        }
    }

    /*
     * @Override public Object onRetainNonConfigurationInstance() { return
     * connect; }
     */

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onPause()
     */
    @Override
    protected void onPause() {

        super.onPause();
        if (errorDialog != null) {
            errorDialog.dismiss();
        }

        if (progressDialog != null) {
            progressDialog.dismiss();
        }
    }

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onResume()
     */
    @Override
    protected void onResume() {
        super.onResume();

        if (showDialog) {
            if (progressDialog != null) {
                progressDialog.show();
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onStart()
     */
    @Override
    protected void onStart() {
        super.onStart();
    }

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onActivityResult()
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            switch (requestCode) {
            case Constants.LOGIN_REQUEST_CODE:
                // Toast.makeText(getApplicationContext(),
                // R.string.loginSuccessfulMsg,
                // Toast.LENGTH_SHORT).show();

                /*
                 * if(isDebuggable) Log.d(TAG,
                 * getString(R.string.loginSuccessfulMsg));
                 */

                if (!(this instanceof Login)) {
                    connect();
                }

                break;
            }
        } else {
            setResult(RESULT_CANCELED);
            finish();
        }
    }

    /**
     * Sets METHOD_NAME parameter.
     * 
     * @param METHOD_NAME METHOD_NAME parameter.
     */
    protected void setMETHOD_NAME(String METHOD_NAME) {
        this.METHOD_NAME = METHOD_NAME;
    }

    /**
     * Creates webservice request.
     */
    protected void createRequest(String clientType) {
        if (webserviceClient == null) {
            if (clientType.equals(SOAPClient.CLIENT_TYPE)) {
                webserviceClient = new SOAPClient();
            } else if (clientType.equals(RESTClient.CLIENT_TYPE)) {
                webserviceClient = new RESTClient();
            }

            webserviceClient.setMETHOD_NAME(METHOD_NAME);
        }

        webserviceClient.createRequest();
    }

    /**
     * Adds a parameter to webservice request.
     * 
     * @param param Parameter name.
     * @param value Parameter value.
     */
    protected void addParam(String param, Object value) {
        webserviceClient.addParam(param, value);
    }

    /**
     * Sends a SOAP request to the specified webservice in METHOD_NAME class
     * constant of the webservice client.
     * 
     * @param cl Class to be mapped
     * @param simple Flag for select simple or complex response
     * @throws Exception
     */
    protected void sendRequest(Class<?> cl, boolean simple) throws Exception {
        ((SOAPClient) webserviceClient).sendRequest(cl, simple);
        result = webserviceClient.getResult();
    }

    /**
     * Sends a REST request to the specified webservice in METHOD_NAME class
     * constant of the webservice client.
     * 
     * @param cl Class to be mapped
     * @param simple Flag for select simple or complex response
     * @param type Request type
     * @param json JSON object to be sended
     * @throws ClientProtocolException
     * @throws IOException
     * @throws JSONException
     */
    protected void sendRequest(Class<?> cl, boolean simple, RESTClient.REQUEST_TYPE type, JSONObject json)
            throws ClientProtocolException, CertificateException, IOException, JSONException {
        ((RESTClient) webserviceClient).sendRequest(cl, simple, RESTClient.REQUEST_TYPE.GET, json);
        result = webserviceClient.getResult();
    }

    protected void startConnection(boolean showDialog, String progressDescription, int progressTitle) {

        connect = new Connect(this, showDialog, progressDescription, progressTitle);
        connect.execute();
    }

    /**
     * Shows progress dialog when connecting to SWAD
     */
    class Connect extends AsyncTask<String, Void, Void> {
        /**
         * Activity that launched the task
         */
        WeakReference<Module> activity;
        /**
         * Exception pointer
         */
        Exception e;
        final String progressDescription;
        final int progressTitle;
        final boolean showDialog;

        /**
         * Shows progress dialog and connects to SWAD in background
         * 
         * @param activity Reference to Module activity
         * @param show Flag for show a progress dialog
         * @param progressDescription Description to be showed in dialog
         * @param progressTitle Title to be showed in dialog
         */
        public Connect(Module activity, boolean show, String progressDescription, int progressTitle) {

            super();
            this.progressDescription = progressDescription;
            this.progressTitle = progressTitle;
            showDialog = show;
            this.activity = new WeakReference<Module>(activity);
            this.e = null;
            progressDialog = new ProgressDialog(Module.this);
        }

        /*
         * (non-Javadoc)
         * @see android.app.Activity#onPreExecute()
         */
        @Override
        protected void onPreExecute() {
            if (showDialog && (progressDialog != null)) {
                progressDialog.setMessage(progressDescription);
                progressDialog.setTitle(progressTitle);
                progressDialog.show();
            }
        }

        /*
         * (non-Javadoc)
         * @see android.app.Activity#doInBackground()
         */
        @Override
        protected Void doInBackground(String... urls) {
            if (isDebuggable)
                Log.d(TAG, "doInBackground()");

            try {
                // Sends webservice request
                requestService();
                /**
                 * If an exception occurs, capture, points exception pointer to
                 * it and shows error message according to exception type.
                 */
            } catch (Exception ex) {
                e = ex;
            }

            return null;

        }

        /*
         * (non-Javadoc)
         * @see android.app.Activity#onPostExecute()
         */
        @Override
        protected void onPostExecute(Void unused) {
            String errorMsg;
            int httpStatusCode;
            boolean sendException = true;

            if ((progressDialog != null) && progressDialog.isShowing()) {
                progressDialog.dismiss();
            }

            if (e != null) {
                /**
                 * If an exception has occurred, shows error message according
                 * to exception type.
                 */
                if (e instanceof SoapFault) {
                    SoapFault es = (SoapFault) e;

                    if (es.faultstring.equals("Bad log in")) {
                        errorMsg = getString(R.string.errorBadLoginMsg);
                        sendException = false;
                    } else if (es.faultstring.equals("Bad web service key")) {
                        errorMsg = getString(R.string.errorBadLoginMsg);
                        sendException = false;

                        // Force logout and reset password (this will show again
                        // the login screen)
                        Login.setLogged(false);
                        Preferences.setUserPassword("");
                    } else if (es.faultstring.equals("Unknown application key")) {
                        errorMsg = getString(R.string.errorBadAppKeyMsg);
                    } else {
                        errorMsg = "Server error: " + es.getMessage();
                    }
                } else if ((e instanceof CertificateException) || (e instanceof SSLException)) {
                    errorMsg = getString(R.string.errorServerCertificateMsg);
                } else if (e instanceof XmlPullParserException) {
                    errorMsg = getString(R.string.errorServerResponseMsg);
                } else if ((e instanceof TimeoutException) || (e instanceof SocketTimeoutException)) {
                    errorMsg = getString(R.string.errorTimeoutMsg);
                    sendException = false;
                } else if (e instanceof HttpResponseException) {
                    httpStatusCode = ((HttpResponseException) e).getStatusCode();

                    Log.e(TAG, "httpStatusCode=" + httpStatusCode);

                    switch (httpStatusCode) {
                    case 500:
                        errorMsg = getString(R.string.errorInternalServerMsg);
                        break;

                    case 503:
                        errorMsg = getString(R.string.errorServiceUnavailableMsg);
                        sendException = false;
                        break;

                    default:
                        errorMsg = e.getMessage();
                        if ((errorMsg == null) || errorMsg.equals("")) {
                            errorMsg = getString(R.string.errorConnectionMsg);
                        }
                    }
                } else {
                    errorMsg = e.getMessage();
                    if ((errorMsg == null) || errorMsg.equals("")) {
                        errorMsg = getString(R.string.errorConnectionMsg);
                    }
                }

                // Request finalized with errors
                error(TAG, errorMsg, e, sendException);
                setResult(RESULT_CANCELED);

                // Launch database rollback
                if (dbHelper.isDbInTransaction()) {
                    dbHelper.endTransaction(false);
                }

                onError();
            } else {
                postConnect();
            }
        }
    }
}