Check if location updates are already enabled directly in the requestLocationUpdates() method

/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This code has been modified by Stefano Dacchille.
 */

package com.github.ignition.location;

import org.aspectj.lang.annotation.SuppressAjWarnings;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import com.github.ignition.location.annotations.IgnitedLocation;
import com.github.ignition.location.annotations.IgnitedLocationActivity;
import com.github.ignition.location.receivers.IgnitedLocationChangedReceiver;
import com.github.ignition.location.receivers.IgnitedPassiveLocationChangedReceiver;
import com.github.ignition.location.tasks.IgnitedLastKnownLocationAsyncTask;
import com.github.ignition.location.templates.ILastLocationFinder;
import com.github.ignition.location.templates.LocationUpdateRequester;
import com.github.ignition.location.templates.OnIgnitedLocationChangedListener;
import com.github.ignition.location.utils.PlatformSpecificImplementationFactory;
import com.github.ignition.support.IgnitedDiagnostics;

@SuppressAjWarnings
public aspect IgnitedLocationManager {
    public static final String LOG_TAG = IgnitedLocationManager.class.getSimpleName();

    declare parents : (@IgnitedLocationActivity *) implements OnIgnitedLocationChangedListener;

    private Criteria defaultCriteria;
    protected LocationUpdateRequester locationUpdateRequester;
    protected PendingIntent locationListenerPendingIntent, locationListenerPassivePendingIntent;
    protected LocationManager locationManager;
    protected IgnitedLocationListener bestInactiveLocationProviderListener;

    private Context context;
    private volatile Location currentLocation;
    private long locationUpdatesInterval, passiveLocationUpdatesInterval;
    private int locationUpdatesDistanceDiff, passiveLocationUpdatesDistanceDiff;
    private boolean requestLocationUpdates;
    private boolean locationUpdatesDisabled = true;

    private AsyncTask<Void, Void, Location> ignitedLastKnownLocationTask;
    private SharedPreferences prefs;
    private Handler handler;

    // Switch to another provider if gps doesn't return a location quickly enough.
    private Runnable removeGpsUpdates = new Runnable() {
        @Override
        public void run() {
            Log.d(LOG_TAG,
                    "It looks like GPS isn't available at this time (i.e.: maybe you're indoors). Removing GPS location updates and requesting network updates.");

            disableLocationUpdates(false);
            requestLocationUpdates(context);
        }
    };

    /**
     * If the Location Provider we're using to receive location updates is disabled while the app is
     * running, this Receiver will be notified, allowing us to re-register our Location Receivers
     * using the best available Location Provider is still available.
     */
    protected BroadcastReceiver locationProviderDisabledReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            boolean providerDisabled = !intent.getBooleanExtra(
                    LocationManager.KEY_PROVIDER_ENABLED, false);
            // Re-register the location listeners using the best available
            // Location Provider.
            if (providerDisabled) {
                disableLocationUpdates(false);
                requestLocationUpdates(context);
            }
        }
    };

    /**
     * If the battery state is low disable the passive location update receiver.
     */
    protected BroadcastReceiver refreshLocationUpdatesReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            disableLocationUpdates(false);
            requestLocationUpdates(context);
        }
    };

    after(Context context, IgnitedLocationActivity ignitedAnnotation) :
        execution(* Activity.onCreate(..)) && this(context)
        && @this(ignitedAnnotation) && within(@IgnitedLocationActivity *) {

        // Get a reference to the Context
        this.context = context;
        // Set pref file
        prefs = context.getSharedPreferences(IgnitedLocationConstants.SHARED_PREFERENCE_FILE,
                Context.MODE_PRIVATE);
        // Get references to the managers
        locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        handler = new Handler();

        // Specify the Criteria to use when requesting location updates while
        // the application is Active
        defaultCriteria = new Criteria();
        // Use gps if it's enabled and if battery level is at least 15%
        boolean useGps = prefs.getBoolean(IgnitedLocationConstants.SP_KEY_LOCATION_UPDATES_USE_GPS,
                IgnitedLocationConstants.USE_GPS_DEFAULT);
        if (useGps) {
            defaultCriteria.setAccuracy(Criteria.ACCURACY_FINE);
        } else {
            defaultCriteria.setPowerRequirement(Criteria.POWER_LOW);
        }

        // Setup the location update Pending Intent
        Intent activeIntent = new Intent(IgnitedLocationConstants.ACTIVE_LOCATION_UPDATE_ACTION);
        locationListenerPendingIntent = PendingIntent.getBroadcast(context, 0, activeIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        // Setup the passive location update Pending Intent
        Intent passiveIntent = new Intent(context, IgnitedPassiveLocationChangedReceiver.class);
        locationListenerPassivePendingIntent = PendingIntent.getBroadcast(context, 0,
                passiveIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        // Instantiate a Location Update Requester class based on the available
        // platform version. This will be used to request location updates.
        locationUpdateRequester = PlatformSpecificImplementationFactory
                .getLocationUpdateRequester(context);
    }

    private boolean isBatteryOk() {
        IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent intent = context.registerReceiver(null, filter);
        double currentLevel = 100.0;
        if (intent != null) {
            currentLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        }

        return currentLevel >= prefs.getInt(IgnitedLocationConstants.SP_KEY_MIN_BATTERY_LEVEL,
                IgnitedLocationConstants.MIN_BATTERY_LEVEL_DEFAULT);
    }

    before(Context context, IgnitedLocationActivity ignitedAnnotation) :
        execution(* Activity.onResume(..)) && this(context)
        && @this(ignitedAnnotation) && within(@IgnitedLocationActivity *) {
        // Get a reference to the Context if this context is null
        if (this.context == null) {
            this.context = context;
        }

        saveToPreferences(context, ignitedAnnotation);

        Log.d(LOG_TAG, "Retrieving last known location...");
        // Get the last known location. This isn't directly affecting the UI, so put it on a
        // worker thread.
        ignitedLastKnownLocationTask = new IgnitedLastKnownLocationAsyncTask(
                context, locationUpdatesDistanceDiff, locationUpdatesInterval);
        ignitedLastKnownLocationTask.execute();
    }

    /**
     * Save last settings to preferences.
     *
     * @param context
     * @param locationAnnotation
     */
    private void saveToPreferences(Context context, IgnitedLocationActivity locationAnnotation) {
        requestLocationUpdates = locationAnnotation.requestLocationUpdates();
        locationUpdatesDistanceDiff = locationAnnotation.locationUpdatesDistanceDiff();
        locationUpdatesInterval = locationAnnotation.locationUpdatesInterval();
        passiveLocationUpdatesDistanceDiff = locationAnnotation
                .passiveLocationUpdatesDistanceDiff();
        passiveLocationUpdatesInterval = locationAnnotation.passiveLocationUpdatesInterval();
        boolean enablePassiveLocationUpdates = locationAnnotation.enablePassiveUpdates();
        boolean useGps = locationAnnotation.useGps();

        Editor editor = prefs.edit();
        editor.putBoolean(IgnitedLocationConstants.SP_KEY_ENABLE_LOCATION_UPDATES,
                requestLocationUpdates);
        editor.putBoolean(IgnitedLocationConstants.SP_KEY_ENABLE_PASSIVE_LOCATION_UPDATES,
                enablePassiveLocationUpdates);
        editor.putBoolean(IgnitedLocationConstants.SP_KEY_LOCATION_UPDATES_USE_GPS, useGps);
        editor.putInt(IgnitedLocationConstants.SP_KEY_LOCATION_UPDATES_DISTANCE_DIFF,
                locationUpdatesDistanceDiff);
        editor.putLong(IgnitedLocationConstants.SP_KEY_LOCATION_UPDATES_INTERVAL,
                locationUpdatesInterval);
        editor.putInt(IgnitedLocationConstants.SP_KEY_PASSIVE_LOCATION_UPDATES_DISTANCE_DIFF,
                passiveLocationUpdatesDistanceDiff);
        editor.putLong(IgnitedLocationConstants.SP_KEY_PASSIVE_LOCATION_UPDATES_INTERVAL,
                passiveLocationUpdatesInterval);
        editor.putBoolean(IgnitedLocationConstants.SP_KEY_RUN_ONCE, true);
        editor.putInt(IgnitedLocationConstants.SP_KEY_MIN_BATTERY_LEVEL,
                locationAnnotation.minBatteryLevel());
        editor.putLong(IgnitedLocationConstants.SP_KEY_WAIT_FOR_GPS_FIX_INTERVAL,
                locationAnnotation.waitForGpsFix());
        editor.commit();

    }

    before(Activity activity, IgnitedLocationActivity ignitedAnnotation) : execution(* Activity.onPause(..))
        && @this(ignitedAnnotation) && this(activity)
        && within(@IgnitedLocationActivity *) && if (ignitedAnnotation.requestLocationUpdates()) {

        disableLocationUpdates(true);

        handler.removeCallbacks(removeGpsUpdates);

        boolean finishing = activity.isFinishing();
        if (finishing) {
            if (ignitedLastKnownLocationTask != null && ignitedLastKnownLocationTask.getStatus() != AsyncTask.Status.FINISHED) {
                ignitedLastKnownLocationTask.cancel(true);
            } else {
                PlatformSpecificImplementationFactory.getLastLocationFinder(context).cancel();
            }

            context = null;
        }
    }

    // after() : execution(* Activity.onDestroy(..)) && @this(IgnitedLocationActivity)
    // && within(@IgnitedLocationActivity *) {
    // }

    Location around() : get(@IgnitedLocation Location *) {
        return currentLocation;
    }

    void around(Location freshLocation) : set(@IgnitedLocation Location *) && args(freshLocation)
        && within(IgnitedPassiveLocationChangedReceiver) && !adviceexecution() {

        currentLocation = freshLocation;
        Log.d(LOG_TAG, "New location from " + currentLocation.getProvider() + " (lat, long): "
                + currentLocation.getLatitude() + ", " + currentLocation.getLongitude());
    }

    void around(Location freshLocation) : set(@IgnitedLocation Location *) && args(freshLocation)
        && (within(IgnitedLocationChangedReceiver) || within(com.github.ignition.location.utils.*)
                || within(IgnitedLastKnownLocationAsyncTask)) && !adviceexecution() {

        if (context == null) {
            return;
        }
        final Activity activity = (Activity) context;
        if (freshLocation == null) {
            activity.showDialog(R.id.ign_loc_dialog_wait_for_fix);
            return;
        }

        currentLocation = freshLocation;
        Log.d(LOG_TAG, "New location from " + currentLocation.getProvider() + " (lat, long): "
                + currentLocation.getLatitude() + ", " + currentLocation.getLongitude());
        boolean keepRequestingLocationUpdates = ((OnIgnitedLocationChangedListener) context)
                .onIgnitedLocationChanged(currentLocation);
        if (!keepRequestingLocationUpdates) {
            disableLocationUpdates(true);
            PlatformSpecificImplementationFactory.getLastLocationFinder(context).cancel();
            return;
        } else if (requestLocationUpdates
                && !freshLocation.getExtras().getBoolean(
                        ILastLocationFinder.LAST_LOCATION_TOO_OLD_EXTRA)) {
            // If we requested location updates, turn them on here.
            requestLocationUpdates(context);
        }

        // If gps is enabled location comes from gps, remove runnable that removes gps updates
        boolean lastLocation = freshLocation.getExtras().getBoolean(
                IgnitedLocationConstants.IGNITED_LAST_LOCATION_EXTRA);
        if (!lastLocation && defaultCriteria.getAccuracy() == Criteria.ACCURACY_FINE
                && currentLocation.getProvider().equals(LocationManager.GPS_PROVIDER)) {
            handler.removeCallbacks(removeGpsUpdates);
        }
    }

    /**
     * Start listening for location updates.
     */
    protected void requestLocationUpdates(Context context) {
        if (!locationUpdatesDisabled) {
            return;
        }
        Criteria locationUpdateCriteria;
        if (isBatteryOk()) {
            locationUpdateCriteria = defaultCriteria;
        } else {
            locationUpdateCriteria = lowBatteryConsumptionCriteria();
        }

        Log.d(LOG_TAG, "Disabling passive location updates");
        locationManager.removeUpdates(locationListenerPassivePendingIntent);

        Log.d(LOG_TAG, "Requesting location updates");
        // Normal updates while activity is visible.
        locationUpdateRequester.requestLocationUpdates(locationUpdatesInterval,
                locationUpdatesDistanceDiff, locationUpdateCriteria, locationListenerPendingIntent);

        // Register a receiver that listens for when the provider I'm using has
        // been disabled.
        IntentFilter locationProviderDisabledIntentFilter = new IntentFilter(
                IgnitedLocationConstants.ACTIVE_LOCATION_UPDATE_PROVIDER_DISABLED_ACTION);
        context.registerReceiver(locationProviderDisabledReceiver,
                locationProviderDisabledIntentFilter);

        IntentFilter refreshLocationUpdatesIntentFilter = new IntentFilter(
                IgnitedLocationConstants.UPDATE_LOCATION_UPDATES_CRITERIA_ACTION);
        context.registerReceiver(refreshLocationUpdatesReceiver, refreshLocationUpdatesIntentFilter);

        // Register a receiver that listens for when a better provider than I'm
        // using becomes available.
        String bestProvider = locationManager.getBestProvider(locationUpdateCriteria, false);
        String bestAvailableProvider = locationManager.getBestProvider(locationUpdateCriteria, true);
        if (bestProvider != null && !bestProvider.equals(bestAvailableProvider)) {
            bestInactiveLocationProviderListener = new IgnitedLocationListener(context);
            locationManager.requestLocationUpdates(bestProvider, 0, 0,
                    bestInactiveLocationProviderListener, context.getMainLooper());
        }

        if (bestAvailableProvider.equals(LocationManager.GPS_PROVIDER)) {
            Log.d(LOG_TAG, "Posting delayed remove GPS updates message");
            // Post a runnable that will remove gps updates if no gps location is returned after 1
            // minute in order to avoid draining the battery.
            handler.postDelayed(removeGpsUpdates, prefs.getLong(
                    IgnitedLocationConstants.SP_KEY_WAIT_FOR_GPS_FIX_INTERVAL,
                    IgnitedLocationConstants.WAIT_FOR_GPS_FIX_INTERVAL_DEFAULT));
        }

        locationUpdatesDisabled = false;
    }

    /**
     * Stop listening for location updates
     *
     * @param enablePassiveLocationUpdates
     */
    protected void disableLocationUpdates(boolean requestPassiveLocationUpdates) {
        if (locationUpdatesDisabled) {
            return;
        }

        Log.d(LOG_TAG, "Disabling location updates");
        context.unregisterReceiver(locationProviderDisabledReceiver);
        context.unregisterReceiver(refreshLocationUpdatesReceiver);

        locationUpdateRequester.removeLocationUpdates();
        if (bestInactiveLocationProviderListener != null) {
            locationManager.removeUpdates(bestInactiveLocationProviderListener);
        }

        boolean finishing = ((Activity) context).isFinishing();

        if (requestPassiveLocationUpdates && !finishing) {
            requestPassiveLocationUpdates();
        }

        locationUpdatesDisabled = true;
    }

    private void requestPassiveLocationUpdates() {
        if (IgnitedDiagnostics.SUPPORTS_FROYO
                && prefs.getBoolean(
                        IgnitedLocationConstants.SP_KEY_ENABLE_PASSIVE_LOCATION_UPDATES,
                        IgnitedLocationConstants.ENABLE_PASSIVE_LOCATION_UPDATES_DEFAULT)) {
            Log.d(LOG_TAG, "Requesting passive location updates");
            // Passive location updates from 3rd party apps when the Activity isn't
            // visible. Only for Android 2.2+.
            locationUpdateRequester.requestPassiveLocationUpdates(passiveLocationUpdatesInterval,
                    passiveLocationUpdatesDistanceDiff, locationListenerPassivePendingIntent);
        }
    }

    public boolean isLocationUpdatesDisabled() {
        return locationUpdatesDisabled;
    }

    public Criteria lowBatteryConsumptionCriteria() {
        Criteria criteria = new Criteria();
        criteria.setPowerRequirement(Criteria.POWER_LOW);
        criteria.setAccuracy(Criteria.NO_REQUIREMENT);
        return criteria;
    }

    /**
     * If the best Location Provider (usually GPS) is not available when we request location
     * updates, this listener will be notified if / when it becomes available. It calls
     * requestLocationUpdates to re-register the location listeners using the better Location
     * Provider.
     */
    private class IgnitedLocationListener implements LocationListener {
        private Context context;

        public IgnitedLocationListener(Context appContext) {
            this.context = appContext;
        }

        @Override
        public void onLocationChanged(Location l) {
        }

        @Override
        public void onProviderDisabled(String provider) {
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
            // Re-register the location listeners using the better Location
            // Provider.
            disableLocationUpdates(false);
            requestLocationUpdates(context);
        }
    }

}

/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This code has been modified by Stefano Dacchille.
 */

package com.github.ignition.location;

import org.aspectj.lang.annotation.SuppressAjWarnings;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import com.github.ignition.location.annotations.IgnitedLocation;
import com.github.ignition.location.annotations.IgnitedLocationActivity;
import com.github.ignition.location.receivers.IgnitedLocationChangedReceiver;
import com.github.ignition.location.receivers.IgnitedPassiveLocationChangedReceiver;
import com.github.ignition.location.tasks.IgnitedLastKnownLocationAsyncTask;
import com.github.ignition.location.templates.ILastLocationFinder;
import com.github.ignition.location.templates.LocationUpdateRequester;
import com.github.ignition.location.templates.OnIgnitedLocationChangedListener;
import com.github.ignition.location.utils.PlatformSpecificImplementationFactory;
import com.github.ignition.support.IgnitedDiagnostics;

@SuppressAjWarnings
public aspect IgnitedLocationManager {
    public static final String LOG_TAG = IgnitedLocationManager.class.getSimpleName();

    declare parents : (@IgnitedLocationActivity *) implements OnIgnitedLocationChangedListener;

    private Criteria defaultCriteria;
    protected LocationUpdateRequester locationUpdateRequester;
    protected PendingIntent locationListenerPendingIntent, locationListenerPassivePendingIntent;
    protected LocationManager locationManager;
    protected IgnitedLocationListener bestInactiveLocationProviderListener;

    private Context context;
    private volatile Location currentLocation;
    private long locationUpdatesInterval, passiveLocationUpdatesInterval;
    private int locationUpdatesDistanceDiff, passiveLocationUpdatesDistanceDiff;
    private boolean requestLocationUpdates;
    private boolean locationUpdatesDisabled = true;

    private AsyncTask<Void, Void, Location> ignitedLastKnownLocationTask;
    private SharedPreferences prefs;
    private Handler handler;

    // Switch to another provider if gps doesn't return a location quickly enough.
    private Runnable removeGpsUpdates = new Runnable() {
        @Override
        public void run() {
            Log.d(LOG_TAG,
                    "It looks like GPS isn't available at this time (i.e.: maybe you're indoors). Removing GPS location updates and requesting network updates.");

            disableLocationUpdates(false);
            requestLocationUpdates(context);
        }
    };

    /**
     * If the Location Provider we're using to receive location updates is disabled while the app is
     * running, this Receiver will be notified, allowing us to re-register our Location Receivers
     * using the best available Location Provider is still available.
     */
    protected BroadcastReceiver locationProviderDisabledReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            boolean providerDisabled = !intent.getBooleanExtra(
                    LocationManager.KEY_PROVIDER_ENABLED, false);
            // Re-register the location listeners using the best available
            // Location Provider.
            if (providerDisabled) {
                disableLocationUpdates(false);
                requestLocationUpdates(context);
            }
        }
    };

    /**
     * If the battery state is low disable the passive location update receiver.
     */
    protected BroadcastReceiver refreshLocationUpdatesReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            disableLocationUpdates(false);
            requestLocationUpdates(context);
        }
    };

    after(Context context, IgnitedLocationActivity ignitedAnnotation) :
        execution(* Activity.onCreate(..)) && this(context)
        && @this(ignitedAnnotation) && within(@IgnitedLocationActivity *) {

        // Get a reference to the Context
        this.context = context;
        // Set pref file
        prefs = context.getSharedPreferences(IgnitedLocationConstants.SHARED_PREFERENCE_FILE,
                Context.MODE_PRIVATE);
        // Get references to the managers
        locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        handler = new Handler();

        // Specify the Criteria to use when requesting location updates while
        // the application is Active
        defaultCriteria = new Criteria();
        // Use gps if it's enabled and if battery level is at least 15%
        boolean useGps = prefs.getBoolean(IgnitedLocationConstants.SP_KEY_LOCATION_UPDATES_USE_GPS,
                IgnitedLocationConstants.USE_GPS_DEFAULT);
        if (useGps) {
            defaultCriteria.setAccuracy(Criteria.ACCURACY_FINE);
        } else {
            defaultCriteria.setPowerRequirement(Criteria.POWER_LOW);
        }

        // Setup the location update Pending Intent
        Intent activeIntent = new Intent(IgnitedLocationConstants.ACTIVE_LOCATION_UPDATE_ACTION);
        locationListenerPendingIntent = PendingIntent.getBroadcast(context, 0, activeIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        // Setup the passive location update Pending Intent
        Intent passiveIntent = new Intent(context, IgnitedPassiveLocationChangedReceiver.class);
        locationListenerPassivePendingIntent = PendingIntent.getBroadcast(context, 0,
                passiveIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        // Instantiate a Location Update Requester class based on the available
        // platform version. This will be used to request location updates.
        locationUpdateRequester = PlatformSpecificImplementationFactory
                .getLocationUpdateRequester(context);
    }

    private boolean isBatteryOk() {
        IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent intent = context.registerReceiver(null, filter);
        double currentLevel = 100.0;
        if (intent != null) {
            currentLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        }

        return currentLevel >= prefs.getInt(IgnitedLocationConstants.SP_KEY_MIN_BATTERY_LEVEL,
                IgnitedLocationConstants.MIN_BATTERY_LEVEL_DEFAULT);
    }

    before(Context context, IgnitedLocationActivity ignitedAnnotation) :
        execution(* Activity.onResume(..)) && this(context)
        && @this(ignitedAnnotation) && within(@IgnitedLocationActivity *) {
        // Get a reference to the Context if this context is null
        if (this.context == null) {
            this.context = context;
        }

        saveToPreferences(context, ignitedAnnotation);

        Log.d(LOG_TAG, "Retrieving last known location...");
        // Get the last known location. This isn't directly affecting the UI, so put it on a
        // worker thread.
        ignitedLastKnownLocationTask = new IgnitedLastKnownLocationAsyncTask(
                context, locationUpdatesDistanceDiff, locationUpdatesInterval);
        ignitedLastKnownLocationTask.execute();
    }

    /**
     * Save last settings to preferences.
     *
     * @param context
     * @param locationAnnotation
     */
    private void saveToPreferences(Context context, IgnitedLocationActivity locationAnnotation) {
        requestLocationUpdates = locationAnnotation.requestLocationUpdates();
        locationUpdatesDistanceDiff = locationAnnotation.locationUpdatesDistanceDiff();
        locationUpdatesInterval = locationAnnotation.locationUpdatesInterval();
        passiveLocationUpdatesDistanceDiff = locationAnnotation
                .passiveLocationUpdatesDistanceDiff();
        passiveLocationUpdatesInterval = locationAnnotation.passiveLocationUpdatesInterval();
        boolean enablePassiveLocationUpdates = locationAnnotation.enablePassiveUpdates();
        boolean useGps = locationAnnotation.useGps();

        Editor editor = prefs.edit();
        editor.putBoolean(IgnitedLocationConstants.SP_KEY_ENABLE_LOCATION_UPDATES,
                requestLocationUpdates);
        editor.putBoolean(IgnitedLocationConstants.SP_KEY_ENABLE_PASSIVE_LOCATION_UPDATES,
                enablePassiveLocationUpdates);
        editor.putBoolean(IgnitedLocationConstants.SP_KEY_LOCATION_UPDATES_USE_GPS, useGps);
        editor.putInt(IgnitedLocationConstants.SP_KEY_LOCATION_UPDATES_DISTANCE_DIFF,
                locationUpdatesDistanceDiff);
        editor.putLong(IgnitedLocationConstants.SP_KEY_LOCATION_UPDATES_INTERVAL,
                locationUpdatesInterval);
        editor.putInt(IgnitedLocationConstants.SP_KEY_PASSIVE_LOCATION_UPDATES_DISTANCE_DIFF,
                passiveLocationUpdatesDistanceDiff);
        editor.putLong(IgnitedLocationConstants.SP_KEY_PASSIVE_LOCATION_UPDATES_INTERVAL,
                passiveLocationUpdatesInterval);
        editor.putBoolean(IgnitedLocationConstants.SP_KEY_RUN_ONCE, true);
        editor.putInt(IgnitedLocationConstants.SP_KEY_MIN_BATTERY_LEVEL,
                locationAnnotation.minBatteryLevel());
        editor.putLong(IgnitedLocationConstants.SP_KEY_WAIT_FOR_GPS_FIX_INTERVAL,
                locationAnnotation.waitForGpsFix());
        editor.commit();

    }

    before(Activity activity, IgnitedLocationActivity ignitedAnnotation) : execution(* Activity.onPause(..))
        && @this(ignitedAnnotation) && this(activity)
        && within(@IgnitedLocationActivity *) && if (ignitedAnnotation.requestLocationUpdates()) {

        disableLocationUpdates(true);

        handler.removeCallbacks(removeGpsUpdates);

        boolean finishing = activity.isFinishing();
        if (finishing) {
            if (ignitedLastKnownLocationTask != null && ignitedLastKnownLocationTask.getStatus() != AsyncTask.Status.FINISHED) {
                ignitedLastKnownLocationTask.cancel(true);
            } else {
                PlatformSpecificImplementationFactory.getLastLocationFinder(context).cancel();
            }

            context = null;
        }
    }

    // after() : execution(* Activity.onDestroy(..)) && @this(IgnitedLocationActivity)
    // && within(@IgnitedLocationActivity *) {
    // }

    Location around() : get(@IgnitedLocation Location *) {
        return currentLocation;
    }

    void around(Location freshLocation) : set(@IgnitedLocation Location *) && args(freshLocation)
        && within(IgnitedPassiveLocationChangedReceiver) && !adviceexecution() {

        currentLocation = freshLocation;
        Log.d(LOG_TAG, "New location from " + currentLocation.getProvider() + " (lat, long): "
                + currentLocation.getLatitude() + ", " + currentLocation.getLongitude());
    }

    void around(Location freshLocation) : set(@IgnitedLocation Location *) && args(freshLocation)
        && (within(IgnitedLocationChangedReceiver) || within(com.github.ignition.location.utils.*)
                || within(IgnitedLastKnownLocationAsyncTask)) && !adviceexecution() {

        if (context == null) {
            return;
        }
        final Activity activity = (Activity) context;
        if (freshLocation == null) {
            activity.showDialog(R.id.ign_loc_dialog_wait_for_fix);
            return;
        }

        currentLocation = freshLocation;
        Log.d(LOG_TAG, "New location from " + currentLocation.getProvider() + " (lat, long): "
                + currentLocation.getLatitude() + ", " + currentLocation.getLongitude());
        boolean keepRequestingLocationUpdates = ((OnIgnitedLocationChangedListener) context)
                .onIgnitedLocationChanged(currentLocation);
        if (!keepRequestingLocationUpdates) {
            if (!locationUpdatesDisabled) {
                disableLocationUpdates(true);
            }
            PlatformSpecificImplementationFactory.getLastLocationFinder(context).cancel();
            return;
                && locationUpdatesDisabled
        } else if (requestLocationUpdates
                && !freshLocation.getExtras().getBoolean(
                        ILastLocationFinder.LAST_LOCATION_TOO_OLD_EXTRA)) {
            // If we requested location updates, turn them on here.
            requestLocationUpdates(context);
        }

        // If gps is enabled location comes from gps, remove runnable that removes gps updates
        boolean lastLocation = freshLocation.getExtras().getBoolean(
                IgnitedLocationConstants.IGNITED_LAST_LOCATION_EXTRA);
        if (!lastLocation && defaultCriteria.getAccuracy() == Criteria.ACCURACY_FINE
                && currentLocation.getProvider().equals(LocationManager.GPS_PROVIDER)) {
            handler.removeCallbacks(removeGpsUpdates);
        }
    }

    /**
     * Start listening for location updates.
     */
    protected void requestLocationUpdates(Context context) {
        Criteria locationUpdateCriteria;
        if (isBatteryOk()) {
            locationUpdateCriteria = defaultCriteria;
        } else {
            locationUpdateCriteria = lowBatteryConsumptionCriteria();
        }

        Log.d(LOG_TAG, "Disabling passive location updates");
        locationManager.removeUpdates(locationListenerPassivePendingIntent);

        Log.d(LOG_TAG, "Requesting location updates");
        // Normal updates while activity is visible.
        locationUpdateRequester.requestLocationUpdates(locationUpdatesInterval,
                locationUpdatesDistanceDiff, locationUpdateCriteria, locationListenerPendingIntent);

        // Register a receiver that listens for when the provider I'm using has
        // been disabled.
        IntentFilter locationProviderDisabledIntentFilter = new IntentFilter(
                IgnitedLocationConstants.ACTIVE_LOCATION_UPDATE_PROVIDER_DISABLED_ACTION);
        context.registerReceiver(locationProviderDisabledReceiver,
                locationProviderDisabledIntentFilter);

        IntentFilter refreshLocationUpdatesIntentFilter = new IntentFilter(
                IgnitedLocationConstants.UPDATE_LOCATION_UPDATES_CRITERIA_ACTION);
        context.registerReceiver(refreshLocationUpdatesReceiver, refreshLocationUpdatesIntentFilter);

        // Register a receiver that listens for when a better provider than I'm
        // using becomes available.
        String bestProvider = locationManager.getBestProvider(locationUpdateCriteria, false);
        String bestAvailableProvider = locationManager.getBestProvider(locationUpdateCriteria, true);
        if (bestProvider != null && !bestProvider.equals(bestAvailableProvider)) {
            bestInactiveLocationProviderListener = new IgnitedLocationListener(context);
            locationManager.requestLocationUpdates(bestProvider, 0, 0,
                    bestInactiveLocationProviderListener, context.getMainLooper());
        }

        if (bestAvailableProvider.equals(LocationManager.GPS_PROVIDER)) {
            Log.d(LOG_TAG, "Posting delayed remove GPS updates message");
            // Post a runnable that will remove gps updates if no gps location is returned after 1
            // minute in order to avoid draining the battery.
            handler.postDelayed(removeGpsUpdates, prefs.getLong(
                    IgnitedLocationConstants.SP_KEY_WAIT_FOR_GPS_FIX_INTERVAL,
                    IgnitedLocationConstants.WAIT_FOR_GPS_FIX_INTERVAL_DEFAULT));
        }

        locationUpdatesDisabled = false;
    }

    /**
     * Stop listening for location updates
     *
     * @param enablePassiveLocationUpdates
     */
    protected void disableLocationUpdates(boolean requestPassiveLocationUpdates) {
        if (locationUpdatesDisabled) {
            return;
        }

        Log.d(LOG_TAG, "Disabling location updates");
        context.unregisterReceiver(locationProviderDisabledReceiver);
        context.unregisterReceiver(refreshLocationUpdatesReceiver);

        locationUpdateRequester.removeLocationUpdates();
        if (bestInactiveLocationProviderListener != null) {
            locationManager.removeUpdates(bestInactiveLocationProviderListener);
        }

        boolean finishing = ((Activity) context).isFinishing();

        if (requestPassiveLocationUpdates && !finishing) {
            requestPassiveLocationUpdates();
        }

        locationUpdatesDisabled = true;
    }

    private void requestPassiveLocationUpdates() {
        if (IgnitedDiagnostics.SUPPORTS_FROYO
                && prefs.getBoolean(
                        IgnitedLocationConstants.SP_KEY_ENABLE_PASSIVE_LOCATION_UPDATES,
                        IgnitedLocationConstants.ENABLE_PASSIVE_LOCATION_UPDATES_DEFAULT)) {
            Log.d(LOG_TAG, "Requesting passive location updates");
            // Passive location updates from 3rd party apps when the Activity isn't
            // visible. Only for Android 2.2+.
            locationUpdateRequester.requestPassiveLocationUpdates(passiveLocationUpdatesInterval,
                    passiveLocationUpdatesDistanceDiff, locationListenerPassivePendingIntent);
        }
    }

    public boolean isLocationUpdatesDisabled() {
        return locationUpdatesDisabled;
    }

    public Criteria lowBatteryConsumptionCriteria() {
        Criteria criteria = new Criteria();
        criteria.setPowerRequirement(Criteria.POWER_LOW);
        criteria.setAccuracy(Criteria.NO_REQUIREMENT);
        return criteria;
    }

    /**
     * If the best Location Provider (usually GPS) is not available when we request location
     * updates, this listener will be notified if / when it becomes available. It calls
     * requestLocationUpdates to re-register the location listeners using the better Location
     * Provider.
     */
    private class IgnitedLocationListener implements LocationListener {
        private Context context;

        public IgnitedLocationListener(Context appContext) {
            this.context = appContext;
        }

        @Override
        public void onLocationChanged(Location l) {
        }

        @Override
        public void onProviderDisabled(String provider) {
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
            // Re-register the location listeners using the better Location
            // Provider.
            disableLocationUpdates(false);
            requestLocationUpdates(context);
        }
    }

}


Changed heartbeat event

Changed heartbeat event

import java.io.*;
import java.util.*;
import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.net.InetAddress;
import java.lang.ClassLoader;
import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.mapred.TaskStatus;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.util.Progressable;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.util.DataChecksum;
import java.net.Socket;

import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.hdfs.DFSClient;

import org.apache.hadoop.mapred.TaskTrackerStatus;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.conf.Configuration;

/**
 *
 * @author Alejandro
 */

aspect AlojaAspect {

	private static final Log LOG = LogFactory.getLog(AlojaAspect.class);

	/*
	TYPES
	######################################################################################################################################
	######################################################################################################################################
	*/

    public static class Events {

        public static final int JobTracker = 11111;
        public static final int TaskTracker = 11112;
        public static final int NameNode = 11113;
        public static final int SecondaryNameNode = 11114;
        public static final int DataNode = 11115;
        public static final int Task = 11116;
        public static final int HeartBeat = 11119;
//        public static final int MapTask = 11117;
//        public static final int ReduceTask = 11118;
        public static final int MapOutputBuffer = 33333;
        public static final int MapTaskOutputSize = 44444;
    }

    public static class Values {

       	// Generic
		public static final int End = 0;
        public static final int Start = 1;

        // Events.TaskTracker
		public static final int RunMapper = 8;
        public static final int RunReducer = 9;
        public static final int ReducerCopyPhase = 10;
        public static final int ReducerSortPhase = 11;
        public static final int ReducerReducePhase = 12;

		// Events.MapOutputBuffer
        public static final int Flush = 1;
        public static final int SortAndSpill = 2;
        public static final int Sort = 3;
        public static final int CreateSpillIndexFile = 5;
        //public static final int TotalIndexCacheMemory = 6;
        public static final int SpillRecordDumped = 7;
        public static final int Combine = 4;
    }

	/*
	FUNCTIONS
	######################################################################################################################################
	######################################################################################################################################
	*/

	private static long getPID() {
		String name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
		return Long.parseLong(name.split("@")[0]);
	}

	private void generateEvent(Integer key, Integer value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	private void generateEvent(Integer key, String value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	/*private void generateEVent(Integer key[], Integer value) {

		StringBuffer output = new StringBuffer();

		output.append()

	}*/

	private void instrumentation(String event, String when) {

		instrumentation(event, when, "");

	}
	private void instrumentation(String event, String when, String additional) {
		try {
			//Add hostname
			String log = InetAddress.getLocalHost().getHostName();
			//Add PID
			log += "," + getPID();
			//Specify event
			log += "," + when + "," + event;
			//Specify event
			log += additional;
			//LOG.info(log);
			//writeLog(logFile,log);

		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	/*
	POINTCUTS
	######################################################################################################################################
	######################################################################################################################################
	*/

	//RegisterDataNode Pointcut

	pointcut startDataNode(): execution(* org.apache.hadoop.hdfs.server.datanode.DataNode.startDataNode(..));

	//RegisterNameNode Pointcut

	pointcut initializeNameNode():  execution(* org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(..));

	//RegisterSecondaryNamenode Pointcut

	pointcut initializeSecondaryNameNode(): execution(* org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.initialize(..));

	//RegisterTask - CHILD

	//pointcut initializeChild(): call(* org.apache.hadoop.mapred.Child.initMetrics(..)) && withincode(* org.apache.hadoop.mapred.Child.main(..));

	pointcut initializeChild(): execution(* org.apache.hadoop.mapred.Child.main(..));

	//Register JobTracker Pointcut

	pointcut registerJobTracker(): execution(* org.apache.hadoop.mapred.JobTracker.startTracker(..));

	//HEARTBEAT

	pointcut heartbeat(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId): execution(* org.apache.hadoop.mapred.JobTracker.heartbeat(..)) && args(status, restarted, initialContact, acceptNewTasks,responseId);

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	pointcut outputSize(): call (* *.getLen(..)) && withincode(* org.apache.hadoop.mapred.Task.calculateOutputSize());

	/*
		###########################################################################
		############################MAPPER#########################################
		###########################################################################
	*/

	//pointcut maptask(): execution(* org.apache.hadoop.mapred.MapTask.run(..));
	pointcut mapper(): call(* org.apache.hadoop.mapred.MapTask.runNewMapper(..)) && withincode(* org.apache.hadoop.mapred.MapTask.run(..));

	//  ############################SORT AND SPILL#################################

	//Start-End
	pointcut taskSortAndSpill(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	pointcut flush(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.flush());

	//Spill File Size
	pointcut sortAndSpillSpillFile(int numSpills, long size) : call (* *.getSpillFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, size);

	//SpillIndex File Size
	pointcut sortAndSpillSpillIndexFile(int numSpills, long partitions) : call (* *.getSpillIndexFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, partitions);

	//Sort
	pointcut sortAndSpillSort(int kvstart, int endPosition, Object reporter): call(* *.sort(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(..,kvstart,endPosition,reporter);

	//Init Writer
	//pointcut sortAndSpillInitWriter() : call (org.apache.hadoop.mapred.IFile.Writer.new(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Close Writer
	//pointcut sortAndSpillCloseWriter() : call (void org.apache.hadoop.mapred.IFile.Writer.close(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Write key-value
	pointcut sortAndSpillWrite(DataInputBuffer key, DataInputBuffer value): call (* *.append(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(key,value);

	//Combiner
	pointcut sortAndSpillCombiner(): call(* *.combine(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Spill Index File
	pointcut sortAndSpillSpillIndexWrite(): call(* *.writeToFile(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

	//REDUCETASK RUN
	pointcut reducer(): execution(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut initCodec(): call(* *.initCodec(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut setPhase(TaskStatus.Phase phase): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..)) && args(phase);

	//pointcut endCopy(): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	//pointcut endSort(): call(* *.getMapOutputKeyClass(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	pointcut defaultBlockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getDefaultBlockSize());
	//pointcut blockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getBlockSize(..));
	pointcut createDFSFile(String src,FsPermission permission,boolean overwrite,boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): execution (* org.apache.hadoop.hdfs.DFSClient.create(..)) && args(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize);
	pointcut runDataStreamer(): execution (* org.apache.hadoop.hdfs.DFSClient.DFSOutputStream.DataStreamer.run());
	//pointcut readEntireBufferFromDataNode(byte buf[],int off,int len): execution(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..)) && args(buf[],off,len);
	//pointcut readFromDataNode(): call (* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.blockSeekTo(..)) && withincode(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..));
	pointcut newBlockReader(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName): execution (* org.apache.hadoop.hdfs.DFSClient.BlockReader.newBlockReader(..)) && args(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName);

	/*
	Advices
	######################################################################################################################################
	######################################################################################################################################
	*/

	// RegiterJobTracker

	after() : registerJobTracker(){
		generateEvent(Events.JobTracker, Values.Start);

	}

	//RegisterTaskTracker ?

	//RegisterNameNode

	after() : initializeNameNode(){
		generateEvent(Events.NameNode, Values.Start);
	}

	//RegisterDataNode

	after() : startDataNode(){
		generateEvent(Events.DataNode, Values.Start);
	}

	//RegisterSecondaryNamenode

	after() : initializeSecondaryNameNode(){
		generateEvent(Events.SecondaryNameNode, Values.Start);
	}

	//HEARTBEAT
	after(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId) : heartbeat(status, restarted, initialContact, acceptNewTasks,responseId){
		// SAMPLE trackername: tracker_vagrant-99-01:localhost/127.0.0.1:38149
		generateEvent(Events.HeartBeat, status.getTrackerName().replace(':','-').replace('/','_'));
	}

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	//RegisterTask CHILD
	after() : initializeChild() { //We need the  PID of this task to be registered
		generateEvent(Events.Task, Values.Start);
	}

/*	after() returning(long size) : outputSize() {
		String s = "Task-outputSize";
		instrumentation(s,"after",", size: " + Long.toString(size));
	}

	/*
		###########################################################################
		############################Mapper#########################################
		###########################################################################
	*/

	/*before() : maptask(){
		generateEvent(Events.MapTask, Values.Start);
	}*/

	before() : mapper(){
		generateEvent(Events.TaskTracker, Values.RunMapper);
	}

	after() : mapper(){
		generateEvent(Events.TaskTracker, Values.End);
	}

	//  ############################SORT AND SPILL#################################

	before() : taskSortAndSpill(){
		generateEvent(Events.MapOutputBuffer, Values.SortAndSpill);
	}

	after() : taskSortAndSpill(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	//flush

	before() : flush(){
		generateEvent(Events.MapOutputBuffer, Values.Flush);
	}

	after() : flush(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	// Spill File Size

	after(int numSpills, long size) returning : sortAndSpillSpillFile(numSpills, size){
		String s = "sortAndSpillSpillFile";
		instrumentation(s,"after",", numSpills: " +Integer.toString(numSpills) + ";size: " + Long.toString((size*numSpills) + size));
	}

	// SpillIndex File Size

	after(int numSpills, long partitions) returning : sortAndSpillSpillIndexFile(numSpills, partitions){
		String s = "sortAndSpillSpillIndexFile";
		instrumentation(s,"after","," + Long.toString(numSpills * partitions));
	}

/*
	before(int length) : kvbufferState(length){

		String s = "kvbufferState";
		File logFile = getFile();
		instrumentation(logFile,s,"before");
		writeLog(logFile,Integer.toString(length));
	}

*/

	before(int kvstart, int endPosition, Object reporter) : sortAndSpillSort(kvstart,endPosition,reporter){
		generateEvent(Events.MapOutputBuffer, Values.Sort);
		//instrumentation(s,"before","," + Integer.toString(endPosition - kvstart));
	}
	after(int kvstart, int endPosition, Object reporter) returning : sortAndSpillSort(kvstart,endPosition,reporter){
		generateEvent(Events.MapOutputBuffer, Values.End);
		//instrumentation(s,"after","," + Integer.toString(endPosition - kvstart));
	}

	// Init writer
/*	after() returning : sortAndSpillInitWriter(){
		String s = "sortAndSpillInitWriter";
		instrumentation(s,"after");
	}

	// Close writer
	after() returning : sortAndSpillCloseWriter(){
		String s = "sortAndSpillCloseWriter";
		instrumentation(s,"after");
	}
*/

	after(DataInputBuffer key, DataInputBuffer value) returning : sortAndSpillWrite(key,value){
		generateEvent(Events.MapOutputBuffer, Values.SpillRecordDumped);
	}

	before() : sortAndSpillCombiner(){
		generateEvent(Events.MapOutputBuffer, Values.Combine);
	}

	after() returning : sortAndSpillCombiner(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	before() : sortAndSpillSpillIndexWrite(){
		generateEvent(Events.MapOutputBuffer, Values.CreateSpillIndexFile);
	}

	after() returning : sortAndSpillSpillIndexWrite(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

/*	before() : reducer(){
		String s = "Reducer";
		instrumentation(s,"before");
	}
*/

	before() : initCodec() {
		generateEvent(Events.TaskTracker, Values.RunReducer);
	}

	after() returning : initCodec() {
		generateEvent(Events.TaskTracker, Values.ReducerCopyPhase);
	}

	before(TaskStatus.Phase phase) : setPhase(phase) { //END OF A PHASE (SORT OR COPY)
			generateEvent(Events.TaskTracker, Values.End);
	}

	after(TaskStatus.Phase phase) returning: setPhase(phase) {
		if (phase == TaskStatus.Phase.SORT) {
			generateEvent(Events.TaskTracker, Values.ReducerSortPhase);
		}
		else if (phase == TaskStatus.Phase.REDUCE) {
			generateEvent(Events.TaskTracker, Values.ReducerReducePhase);
		}
	}

	after() : reducer(){ //END OF REDUCE PHASE
			generateEvent(Events.TaskTracker, Values.End);	}

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	after() returning(long blockSize) : defaultBlockSize() {
		String s = "Network-defaultBlockSize";
		instrumentation(s,"after",", size: " + Long.toString(blockSize));
	}
	// after() returning(long blockSize) : blockSize() {
	// 	String s = "Network-blockSize";
	// 	File logFile = getFile();
	// 	instrumentation(logFile,s,"after");
	// 	String log = ", size: " + Long.toString(blockSize);
	// 	writeLog(logFile,log);
	// }

	after(String src,FsPermission permission,boolean overwrite, boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): createDFSFile(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize) {
		String s = "Network-CreateDFSFile";

		//MODIFIED!!!!!!-----!!!!!!!!!!!
		instrumentation(s,"after",", path: " + src + ";permission: " + permission.toString() + ";overwrite: " + String.valueOf(overwrite) + ";createParent: " + String.valueOf(createParent) + ";replication: " + Short.toString(replication) + ";blockSize: " + Long.toString(blockSize) + ";buffersize: " + Integer.toString(buffersize));
	}
	before(): runDataStreamer() {
		String s = "DataStreamer";
		instrumentation(s,"after");
	}

	// before(byte buf[],int off, int len) : readEntireBufferFromDataNode(buf[],off,len){
	// 	String s = "Network-ReadEntireBuffer";
	// 	instrumentation(s,"after",", bufferLength: " + Integer.toString(len));
	// }

	// after() returning(DatanodeInfo datanode) : readFromDataNode(){
	// 	String s = "Network-fromDataNode";
	// 	instrumentation(s,"after", ", from : " + datanode.getHostName());
	// }

	after(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName) : newBlockReader(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName) {
		String s = "Network-NewBlockReader";
		String extra = ", DataNode: " + sock.getInetAddress().getCanonicalHostName();
		extra += ";file: " + file;
		//extra += ", length: " + Long.toString(len) + "B";
		extra += ";" + Long.toString(len);
		extra += ";blockId: " + Long.toString(blockId);
		extra += ";startOffset: " + Long.toString(startOffset);
		instrumentation(s,"after",extra);
	}
}

import java.io.*;
import java.util.*;
import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.net.InetAddress;
import java.lang.ClassLoader;
import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.mapred.TaskStatus;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.util.Progressable;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.util.DataChecksum;
import java.net.Socket;

import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.hdfs.DFSClient;

import org.apache.hadoop.mapred.TaskTrackerStatus;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.conf.Configuration;

/**
 *
 * @author Alejandro
 */

aspect AlojaAspect {

	private static final Log LOG = LogFactory.getLog(AlojaAspect.class);

	/*
	TYPES
	######################################################################################################################################
	######################################################################################################################################
	*/

    public static class Events {

        public static final int JobTracker = 11111;
        public static final int TaskTracker = 11112;
        public static final int NameNode = 11113;
        public static final int SecondaryNameNode = 11114;
        public static final int DataNode = 11115;
        public static final int Task = 11116;
//        public static final int MapTask = 11117;
//        public static final int ReduceTask = 11118;
        public static final int MapOutputBuffer = 33333;
        public static final int MapTaskOutputSize = 44444;
    }

    public static class Values {

       	// Generic
		public static final int End = 0;
        public static final int Start = 1;

        // Events.TaskTracker
		public static final int RunMapper = 8;
        public static final int RunReducer = 9;
        public static final int ReducerCopyPhase = 10;
        public static final int ReducerSortPhase = 11;
        public static final int ReducerReducePhase = 12;

		// Events.JobTracker
		public static final int HeartBeat = 13;

		// Events.MapOutputBuffer
        public static final int Flush = 1;
        public static final int SortAndSpill = 2;
        public static final int Sort = 3;
        public static final int CreateSpillIndexFile = 5;
        //public static final int TotalIndexCacheMemory = 6;
        public static final int SpillRecordDumped = 7;
        public static final int Combine = 4;
    }

	/*
	FUNCTIONS
	######################################################################################################################################
	######################################################################################################################################
	*/

	private static long getPID() {
		String name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
		return Long.parseLong(name.split("@")[0]);
	}

	private void generateEvent(Integer key, Integer value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	private void generateEvent(Integer key, String value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	/*private void generateEVent(Integer key[], Integer value) {

		StringBuffer output = new StringBuffer();

		output.append()

	}*/

	private void instrumentation(String event, String when) {

		instrumentation(event, when, "");

	}
	private void instrumentation(String event, String when, String additional) {
		try {
			//Add hostname
			String log = InetAddress.getLocalHost().getHostName();
			//Add PID
			log += "," + getPID();
			//Specify event
			log += "," + when + "," + event;
			//Specify event
			log += additional;
			//LOG.info(log);
			//writeLog(logFile,log);

		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	/*
	POINTCUTS
	######################################################################################################################################
	######################################################################################################################################
	*/

	//RegisterDataNode Pointcut

	pointcut startDataNode(): execution(* org.apache.hadoop.hdfs.server.datanode.DataNode.startDataNode(..));

	//RegisterNameNode Pointcut

	pointcut initializeNameNode():  execution(* org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(..));

	//RegisterSecondaryNamenode Pointcut

	pointcut initializeSecondaryNameNode(): execution(* org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.initialize(..));

	//RegisterTask - CHILD

	//pointcut initializeChild(): call(* org.apache.hadoop.mapred.Child.initMetrics(..)) && withincode(* org.apache.hadoop.mapred.Child.main(..));

	pointcut initializeChild(): execution(* org.apache.hadoop.mapred.Child.main(..));

	//Register JobTracker Pointcut

	pointcut registerJobTracker(): execution(* org.apache.hadoop.mapred.JobTracker.startTracker(..));

	//HEARTBEAT

	pointcut heartbeat(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId): execution(* org.apache.hadoop.mapred.JobTracker.heartbeat(..)) && args(status, restarted, initialContact, acceptNewTasks,responseId);

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	pointcut outputSize(): call (* *.getLen(..)) && withincode(* org.apache.hadoop.mapred.Task.calculateOutputSize());

	/*
		###########################################################################
		############################MAPPER#########################################
		###########################################################################
	*/

	//pointcut maptask(): execution(* org.apache.hadoop.mapred.MapTask.run(..));
	pointcut mapper(): call(* org.apache.hadoop.mapred.MapTask.runNewMapper(..)) && withincode(* org.apache.hadoop.mapred.MapTask.run(..));

	//  ############################SORT AND SPILL#################################

	//Start-End
	pointcut taskSortAndSpill(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	pointcut flush(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.flush());

	//Spill File Size
	pointcut sortAndSpillSpillFile(int numSpills, long size) : call (* *.getSpillFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, size);

	//SpillIndex File Size
	pointcut sortAndSpillSpillIndexFile(int numSpills, long partitions) : call (* *.getSpillIndexFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, partitions);

	//Sort
	pointcut sortAndSpillSort(int kvstart, int endPosition, Object reporter): call(* *.sort(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(..,kvstart,endPosition,reporter);

	//Init Writer
	//pointcut sortAndSpillInitWriter() : call (org.apache.hadoop.mapred.IFile.Writer.new(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Close Writer
	//pointcut sortAndSpillCloseWriter() : call (void org.apache.hadoop.mapred.IFile.Writer.close(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Write key-value
	pointcut sortAndSpillWrite(DataInputBuffer key, DataInputBuffer value): call (* *.append(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(key,value);

	//Combiner
	pointcut sortAndSpillCombiner(): call(* *.combine(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Spill Index File
	pointcut sortAndSpillSpillIndexWrite(): call(* *.writeToFile(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

	//REDUCETASK RUN
	pointcut reducer(): execution(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut initCodec(): call(* *.initCodec(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut setPhase(TaskStatus.Phase phase): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..)) && args(phase);

	//pointcut endCopy(): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	//pointcut endSort(): call(* *.getMapOutputKeyClass(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	pointcut defaultBlockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getDefaultBlockSize());
	//pointcut blockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getBlockSize(..));
	pointcut createDFSFile(String src,FsPermission permission,boolean overwrite,boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): execution (* org.apache.hadoop.hdfs.DFSClient.create(..)) && args(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize);
	pointcut runDataStreamer(): execution (* org.apache.hadoop.hdfs.DFSClient.DFSOutputStream.DataStreamer.run());
	//pointcut readEntireBufferFromDataNode(byte buf[],int off,int len): execution(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..)) && args(buf[],off,len);
	//pointcut readFromDataNode(): call (* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.blockSeekTo(..)) && withincode(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..));
	pointcut newBlockReader(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName): execution (* org.apache.hadoop.hdfs.DFSClient.BlockReader.newBlockReader(..)) && args(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName);

	/*
	Advices
	######################################################################################################################################
	######################################################################################################################################
	*/

	// RegiterJobTracker

	after() : registerJobTracker(){
		generateEvent(Events.JobTracker, Values.Start);

	}

	//RegisterTaskTracker ?

	//RegisterNameNode

	after() : initializeNameNode(){
		generateEvent(Events.NameNode, Values.Start);
	}

	//RegisterDataNode

	after() : startDataNode(){
		generateEvent(Events.DataNode, Values.Start);
	}

	//RegisterSecondaryNamenode

	after() : initializeSecondaryNameNode(){
		generateEvent(Events.SecondaryNameNode, Values.Start);
	}

	//HEARTBEAT
	after(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId) : heartbeat(status, restarted, initialContact, acceptNewTasks,responseId){
		// SAMPLE trackername: tracker_vagrant-99-01:localhost/127.0.0.1:38149
		generateEvent(Events.JobTracker, status.getTrackerName().replace(':','-').replace('/','_'));
	}

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	//RegisterTask CHILD
	after() : initializeChild() { //We need the  PID of this task to be registered
		generateEvent(Events.Task, Values.Start);
	}

/*	after() returning(long size) : outputSize() {
		String s = "Task-outputSize";
		instrumentation(s,"after",", size: " + Long.toString(size));
	}

	/*
		###########################################################################
		############################Mapper#########################################
		###########################################################################
	*/

	/*before() : maptask(){
		generateEvent(Events.MapTask, Values.Start);
	}*/

	before() : mapper(){
		generateEvent(Events.TaskTracker, Values.RunMapper);
	}

	after() : mapper(){
		generateEvent(Events.TaskTracker, Values.End);
	}

	//  ############################SORT AND SPILL#################################

	before() : taskSortAndSpill(){
		generateEvent(Events.MapOutputBuffer, Values.SortAndSpill);
	}

	after() : taskSortAndSpill(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	//flush

	before() : flush(){
		generateEvent(Events.MapOutputBuffer, Values.Flush);
	}

	after() : flush(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	// Spill File Size

	after(int numSpills, long size) returning : sortAndSpillSpillFile(numSpills, size){
		String s = "sortAndSpillSpillFile";
		instrumentation(s,"after",", numSpills: " +Integer.toString(numSpills) + ";size: " + Long.toString((size*numSpills) + size));
	}

	// SpillIndex File Size

	after(int numSpills, long partitions) returning : sortAndSpillSpillIndexFile(numSpills, partitions){
		String s = "sortAndSpillSpillIndexFile";
		instrumentation(s,"after","," + Long.toString(numSpills * partitions));
	}

/*
	before(int length) : kvbufferState(length){

		String s = "kvbufferState";
		File logFile = getFile();
		instrumentation(logFile,s,"before");
		writeLog(logFile,Integer.toString(length));
	}

*/

	before(int kvstart, int endPosition, Object reporter) : sortAndSpillSort(kvstart,endPosition,reporter){
		generateEvent(Events.MapOutputBuffer, Values.Sort);
		//instrumentation(s,"before","," + Integer.toString(endPosition - kvstart));
	}
	after(int kvstart, int endPosition, Object reporter) returning : sortAndSpillSort(kvstart,endPosition,reporter){
		generateEvent(Events.MapOutputBuffer, Values.End);
		//instrumentation(s,"after","," + Integer.toString(endPosition - kvstart));
	}

	// Init writer
/*	after() returning : sortAndSpillInitWriter(){
		String s = "sortAndSpillInitWriter";
		instrumentation(s,"after");
	}

	// Close writer
	after() returning : sortAndSpillCloseWriter(){
		String s = "sortAndSpillCloseWriter";
		instrumentation(s,"after");
	}
*/

	after(DataInputBuffer key, DataInputBuffer value) returning : sortAndSpillWrite(key,value){
		generateEvent(Events.MapOutputBuffer, Values.SpillRecordDumped);
	}

	before() : sortAndSpillCombiner(){
		generateEvent(Events.MapOutputBuffer, Values.Combine);
	}

	after() returning : sortAndSpillCombiner(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	before() : sortAndSpillSpillIndexWrite(){
		generateEvent(Events.MapOutputBuffer, Values.CreateSpillIndexFile);
	}

	after() returning : sortAndSpillSpillIndexWrite(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

/*	before() : reducer(){
		String s = "Reducer";
		instrumentation(s,"before");
	}
*/

	before() : initCodec() {
		generateEvent(Events.TaskTracker, Values.RunReducer);
	}

	after() returning : initCodec() {
		generateEvent(Events.TaskTracker, Values.ReducerCopyPhase);
	}

	before(TaskStatus.Phase phase) : setPhase(phase) { //END OF A PHASE (SORT OR COPY)
			generateEvent(Events.TaskTracker, Values.End);
	}

	after(TaskStatus.Phase phase) returning: setPhase(phase) {
		if (phase == TaskStatus.Phase.SORT) {
			generateEvent(Events.TaskTracker, Values.ReducerSortPhase);
		}
		else if (phase == TaskStatus.Phase.REDUCE) {
			generateEvent(Events.TaskTracker, Values.ReducerReducePhase);
		}
	}

	after() : reducer(){ //END OF REDUCE PHASE
			generateEvent(Events.TaskTracker, Values.End);	}

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	after() returning(long blockSize) : defaultBlockSize() {
		String s = "Network-defaultBlockSize";
		instrumentation(s,"after",", size: " + Long.toString(blockSize));
	}
	// after() returning(long blockSize) : blockSize() {
	// 	String s = "Network-blockSize";
	// 	File logFile = getFile();
	// 	instrumentation(logFile,s,"after");
	// 	String log = ", size: " + Long.toString(blockSize);
	// 	writeLog(logFile,log);
	// }

	after(String src,FsPermission permission,boolean overwrite, boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): createDFSFile(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize) {
		String s = "Network-CreateDFSFile";

		//MODIFIED!!!!!!-----!!!!!!!!!!!
		instrumentation(s,"after",", path: " + src + ";permission: " + permission.toString() + ";overwrite: " + String.valueOf(overwrite) + ";createParent: " + String.valueOf(createParent) + ";replication: " + Short.toString(replication) + ";blockSize: " + Long.toString(blockSize) + ";buffersize: " + Integer.toString(buffersize));
	}
	before(): runDataStreamer() {
		String s = "DataStreamer";
		instrumentation(s,"after");
	}

	// before(byte buf[],int off, int len) : readEntireBufferFromDataNode(buf[],off,len){
	// 	String s = "Network-ReadEntireBuffer";
	// 	instrumentation(s,"after",", bufferLength: " + Integer.toString(len));
	// }

	// after() returning(DatanodeInfo datanode) : readFromDataNode(){
	// 	String s = "Network-fromDataNode";
	// 	instrumentation(s,"after", ", from : " + datanode.getHostName());
	// }

	after(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName) : newBlockReader(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName) {
		String s = "Network-NewBlockReader";
		String extra = ", DataNode: " + sock.getInetAddress().getCanonicalHostName();
		extra += ";file: " + file;
		//extra += ", length: " + Long.toString(len) + "B";
		extra += ";" + Long.toString(len);
		extra += ";blockId: " + Long.toString(blockId);
		extra += ";startOffset: " + Long.toString(startOffset);
		instrumentation(s,"after",extra);
	}
}


In some case, the KStateMachines aspect may throw a NullPointerException. Add a test to avoid such an exception.

/*
 *     ParallelJ, framework for parallel computing
 *
 *     Copyright (C) 2010, 2011, 2012 Atos Worldline or third-party contributors as
 *     indicated by the @author tags or express copyright attribution
 *     statements applied by the authors.
 *
 *     This library is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU Lesser General Public
 *     License as published by the Free Software Foundation; either
 *     version 2.1 of the License.
 *
 *     This library 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
 *     Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public
 *     License along with this library; if not, write to the Free Software
 *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
package org.parallelj.internal.util.sm.impl;

import javax.xml.bind.annotation.XmlTransient;

import org.aspectj.lang.reflect.MethodSignature;
import org.parallelj.internal.util.sm.StateListener;
import org.parallelj.internal.util.sm.impl.KStateMachine.KVertex;
import org.parallelj.internal.util.sm.impl.KStateMachine.Occurrence;

public privileged aspect KStateMachines {

	/**
	 *
	 */
	public static interface Adapter {

	}

	/**
	 * Inter type declaration in order to link annotated classes and state
	 * machine occurrence.
	 */
	@XmlTransient
	public Occurrence Adapter.occurrence;

	declare parents:
		(@org.parallelj.internal.util.sm.StateMachine *) implements Adapter;

	public static privileged aspect PerMachine pertypewithin(@org.parallelj.internal.util.sm.StateMachine *) {

		KStateMachine machine;

		after() : staticinitialization(@org.parallelj.internal.util.sm.StateMachine *) {
			this.machine = new KStateMachine(thisJoinPoint.getSignature()
					.getDeclaringType());
			System.out.println(this.machine);
		}

		after(Object self): execution((@org.parallelj.internal.util.sm.StateMachine *).new(..)) && this(self) {
			((Adapter) self).occurrence = this.machine.newOccurrence(self);
		}

		void around(Object self): execution(@org.parallelj.internal.util.sm.Trigger * *(..)) && this(self) {
			Occurrence occurrence = ((Adapter) self).occurrence;
			KVertex previous = occurrence.getCurrent();
			KTrigger trigger = this.machine
					.getTrigger(((MethodSignature) thisJoinPoint.getSignature())
							.getName());
			occurrence.trigger(trigger.trigger(occurrence,
					thisJoinPoint.getArgs()));
			KVertex current = occurrence.getCurrent();
			if (previous != current && current != null) {
				occurrence.getSupport().fireStateChanded(current.value);
			}
		}
	}

	void around(Object machine, StateListener listener): execution(* org.parallelj.internal.util.sm.StateMachines.addStateListener(..)) && args(machine, listener, ..) {
		Occurrence occurrence = ((Adapter) machine).occurrence;
		occurrence.getSupport().addStateListener(listener);
	}

	void around(Object machine, StateListener listener): execution(* org.parallelj.internal.util.sm.StateMachines.removeStateListener(..)) && args(machine, listener, ..) {
		Occurrence occurrence = ((Adapter) machine).occurrence;
		occurrence.getSupport().removeStateListener(listener);
	}

}

/*
 *     ParallelJ, framework for parallel computing
 *
 *     Copyright (C) 2010, 2011, 2012 Atos Worldline or third-party contributors as
 *     indicated by the @author tags or express copyright attribution
 *     statements applied by the authors.
 *
 *     This library is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU Lesser General Public
 *     License as published by the Free Software Foundation; either
 *     version 2.1 of the License.
 *
 *     This library 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
 *     Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public
 *     License along with this library; if not, write to the Free Software
 *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
package org.parallelj.internal.util.sm.impl;

import javax.xml.bind.annotation.XmlTransient;

import org.aspectj.lang.reflect.MethodSignature;
import org.parallelj.internal.util.sm.StateListener;
import org.parallelj.internal.util.sm.impl.KStateMachine.KVertex;
import org.parallelj.internal.util.sm.impl.KStateMachine.Occurrence;

public privileged aspect KStateMachines {

	/**
	 *
	 */
	public static interface Adapter {

	}

	/**
	 * Inter type declaration in order to link annotated classes and state
	 * machine occurrence.
	 */
	@XmlTransient
	public Occurrence Adapter.occurrence;

	declare parents:
		(@org.parallelj.internal.util.sm.StateMachine *) implements Adapter;

	public static privileged aspect PerMachine pertypewithin(@org.parallelj.internal.util.sm.StateMachine *) {

		KStateMachine machine;

		after() : staticinitialization(@org.parallelj.internal.util.sm.StateMachine *) {
			this.machine = new KStateMachine(thisJoinPoint.getSignature()
					.getDeclaringType());
			System.out.println(this.machine);
		}

		after(Object self): execution((@org.parallelj.internal.util.sm.StateMachine *).new(..)) && this(self) {
			((Adapter) self).occurrence = this.machine.newOccurrence(self);
		}

		void around(Object self): execution(@org.parallelj.internal.util.sm.Trigger * *(..)) && this(self) {
			Occurrence occurrence = ((Adapter) self).occurrence;
			KVertex previous = occurrence.getCurrent();
			KTrigger trigger = this.machine
					.getTrigger(((MethodSignature) thisJoinPoint.getSignature())
							.getName());
			occurrence.trigger(trigger.trigger(occurrence,
					thisJoinPoint.getArgs()));
			KVertex current = occurrence.getCurrent();
			if (previous != current) {
				occurrence.getSupport().fireStateChanded(current.value);
			}
		}
	}

	void around(Object machine, StateListener listener): execution(* org.parallelj.internal.util.sm.StateMachines.addStateListener(..)) && args(machine, listener, ..) {
		Occurrence occurrence = ((Adapter) machine).occurrence;
		occurrence.getSupport().addStateListener(listener);
	}

	void around(Object machine, StateListener listener): execution(* org.parallelj.internal.util.sm.StateMachines.removeStateListener(..)) && args(machine, listener, ..) {
		Occurrence occurrence = ((Adapter) machine).occurrence;
		occurrence.getSupport().removeStateListener(listener);
	}

}


Add missing AspectJ blurb that was not copied from Spring.

/*
 * Copyright (C) 2011 Archie L. Cobbs and other authors. All rights reserved.
 *
 * $Id$
 */

package org.dellroad.stuff.vaadin;

import java.io.ObjectStreamException;
import java.io.Serializable;

import org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect;

/**
 * Aspect that autowires classes marked with the {@link VaadinConfigurable @VaadinConfigurable} annotation to a
 * {@link SpringContextApplication} application context.
 *
 *

 * This aspect does the same thing that Spring's {@code AnnotationBeanConfigurerAspect} aspect does,
 * except that this aspect configures beans using the application context associated with the current
 * {@link SpringContextApplication} Vaadin application rather than the one associated with the overall
 * servlet context (i.e., its parent).
 *

 *
 *

 * As a result, objects so annotated will be configured for their specific {@link SpringContextApplication}
 * instance, and therefore can only be instantiated by threads associated with a current {@link SpringContextApplication}
 * (see {@link ContextApplication#get}). This will be the case when executing within a {@link SpringContextApplication}
 * Vaadin application HTTP request or an invocation of {@link ContextApplication#invoke} on same.
 *

 *
 *

 * This implementation is derived from Spring's {@code AnnotationBeanConfigurerAspect} implementation
 * and therefore shares its license (also Apache).
 *

 *
 * @see SpringContextApplication
 * @see ContextApplication#get
 * @see VaadinConfigurable
 */
public aspect VaadinConfigurableAspect extends AbstractDependencyInjectionAspect {

// Stuff copied from AbstractInterfaceDrivenDependencyInjectionAspect.aj

    public pointcut beanConstruction(Object bean) :
        initialization(VaadinConfigurableObject+.new(..)) && this(bean);

    public pointcut beanDeserialization(Object bean) :
        execution(Object VaadinConfigurableDeserializationSupport+.readResolve()) &&
        this(bean);

    public pointcut leastSpecificSuperTypeConstruction() : initialization(VaadinConfigurableObject.new(..));

    declare parents:
        VaadinConfigurableObject+ && Serializable+ implements VaadinConfigurableDeserializationSupport;

    static interface VaadinConfigurableDeserializationSupport extends Serializable {
    }

    public Object VaadinConfigurableDeserializationSupport.readResolve() throws ObjectStreamException {
        return this;
    }

// Stuff copied from AnnotationBeanConfigurerAspect.aj

    public pointcut inConfigurableBean() : @this(VaadinConfigurable);

    public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);

    declare parents: @VaadinConfigurable * implements VaadinConfigurableObject;

    private pointcut preConstructionConfigurationSupport(VaadinConfigurable c) : @this(c) && if(c.preConstruction());

	declare parents: @VaadinConfigurable Serializable+ implements VaadinConfigurableDeserializationSupport;

// Our implementation

    @Override
    public void configureBean(Object bean) {
        SpringContextApplication.get().configureBean(bean);
    }
}

/*
 * Copyright (C) 2011 Archie L. Cobbs and other authors. All rights reserved.
 *
 * $Id$
 */

package org.dellroad.stuff.vaadin;

import java.io.ObjectStreamException;
import java.io.Serializable;

import org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect;

/**
 * Aspect that autowires classes marked with the {@link VaadinConfigurable @VaadinConfigurable} annotation to a
 * {@link SpringContextApplication} application context.
 *
 *

 * This aspect does the same thing that Spring's {@code AnnotationBeanConfigurerAspect} aspect does,
 * except that this aspect configures beans using the application context associated with the current
 * {@link SpringContextApplication} Vaadin application rather than the one associated with the overall
 * servlet context (i.e., its parent).
 *

 *
 *

 * As a result, objects so annotated will be configured for their specific {@link SpringContextApplication}
 * instance, and therefore can only be instantiated by threads associated with a current {@link SpringContextApplication}
 * (see {@link ContextApplication#get}). This will be the case when executing within a {@link SpringContextApplication}
 * Vaadin application HTTP request or an invocation of {@link ContextApplication#invoke} on same.
 *

 *
 *

 * This implementation is derived from Spring's {@code AnnotationBeanConfigurerAspect} implementation
 * and therefore shares its license (also Apache).
 *

 *
 * @see SpringContextApplication
 * @see ContextApplication#get
 * @see VaadinConfigurable
 */
public aspect VaadinConfigurableAspect extends AbstractDependencyInjectionAspect {

// Stuff copied from AbstractInterfaceDrivenDependencyInjectionAspect.aj

    public pointcut beanConstruction(Object bean) :
        initialization(VaadinConfigurableObject+.new(..)) && this(bean);

    public pointcut beanDeserialization(Object bean) :
        execution(Object VaadinConfigurableDeserializationSupport+.readResolve()) &&
        this(bean);

    public pointcut leastSpecificSuperTypeConstruction() : initialization(VaadinConfigurableObject.new(..));

    static interface VaadinConfigurableDeserializationSupport extends Serializable {
    }

    public Object VaadinConfigurableDeserializationSupport.readResolve() throws ObjectStreamException {
        return this;
    }

// Stuff copied from AnnotationBeanConfigurerAspect.aj

    public pointcut inConfigurableBean() : @this(VaadinConfigurable);

    public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);

    declare parents: @VaadinConfigurable * implements VaadinConfigurableObject;

    private pointcut preConstructionConfigurationSupport(VaadinConfigurable c) : @this(c) && if(c.preConstruction());

	declare parents: @VaadinConfigurable Serializable+ implements VaadinConfigurableDeserializationSupport;

// Our implementation

    @Override
    public void configureBean(Object bean) {
        SpringContextApplication.get().configureBean(bean);
    }
}


fix for SPR-2521

fix for SPR-2521

git-svn-id: b619a0c99665f88f1afe72824344cefe9a1c8c90@11518 fd5a2b45-1f63-4059-99e9-3c7cb7fd75c8

/*
 * Copyright 2002-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.transaction.aspectj;

import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;

/**
 * Concrete AspectJ transaction aspect using Spring Transactional annotation
 * for JDK 1.5+.
 *
 *

 * When using this aspect, you must annotate the implementation class
 * (and/or methods within that class), not the interface (if any) that
 * the class implements. AspectJ follows Java's rule that annotations on
 * interfaces are not inherited.
 *

 *
A @Transactional annotation on a class specifies the default transaction
 * semantics for the execution of any public operation in the class.

 *
A @Transactional annotation on a method within the class overrides the
 * default transaction semantics given by the class annotation (if present).
 * Methods with public, protected, and default visibility may all be annotated.
 * Annotating protected and default visibility methods directly is the only way
 * to get transaction demarcation for the execution of such operations.

 *
 * @author Rod Johnson
 * @author Ramnivas Laddad
 * @author Adrian Colyer
 * @since 2.0
 * @see org.springframework.transaction.annotation.Transactional
 */
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {

	public AnnotationTransactionAspect() {
		super(new AnnotationTransactionAttributeSource());
	}

	/**
	 * Matches the execution of any public method in a type with the
	 * Transactional annotation, or any subtype of a type with the
	 * Transactional annotation.
	 */
	private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
		execution(public * ((@Transactional *)+).*(..)) && @this(Transactional);

	/**
	 * Matches the execution of any non-private method with the
	 * Transactional annotation.
	 */
	private pointcut executionOfTransactionalNonPrivateMethod() :
		execution(!private * *(..)) && @annotation(Transactional);

	/**
	 * Definition of pointcut from super aspect - matched join points
	 * will have Spring transaction management applied.
	 */
	protected pointcut transactionalMethodExecution(Object txObject) :
		(executionOfAnyPublicMethodInAtTransactionalType()
		 || executionOfTransactionalNonPrivateMethod() )
		 && this(txObject);

	/**
	 * Annotating private methods with @Transactional has no effect...
	 */
	declare warning
	    // note, we should be able to say the following in one execution pcd, but
	    // aj doesn't like it...
		: execution(@Transactional * *(..)) &&
		  execution(private * *(..))
		: "@Transactional annotation on private method will be ignored";
}

/*
 * Copyright 2002-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.transaction.aspectj;

import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;

/**
 * Concrete AspectJ transaction aspect using Spring Transactional annotation
 * for JDK 1.5+.
 *
 *

 * When using this aspect, you must annotate the implementation class
 * (and/or methods within that class), not the interface (if any) that
 * the class implements. AspectJ follows Java's rule that annotations on
 * interfaces are not inherited.
 *

 *
A @Transactional annotation on a class specifies the default transaction
 * semantics for the execution of any public operation in the class.

 *
A @Transactional annotation on a method within the class overrides the
 * default transaction semantics given by the class annotation (if present).
 * Methods with public, protected, and default visibility may all be annotated.
 * Annotating protected and default visibility methods directly is the only way
 * to get transaction demarcation for the execution of such operations.

 *
 * @author Rod Johnson
 * @author Ramnivas Laddad
 * @author Adrian Colyer
 * @since 2.0
 * @see org.springframework.transaction.annotation.Transactional
 */
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {

	public AnnotationTransactionAspect() {
		super(new AnnotationTransactionAttributeSource());
	}

	/**
	 * Matches the execution of any public method in a type with the
	 * Transactional annotation, or any subtype of a type with the
	 * Transactional annotation.
	 */
	private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
		execution(public * ((@Transactional *)+).*(..));

	/**
	 * Matches the execution of any non-private method with the
	 * Transactional annotation.
	 */
	private pointcut executionOfTransactionalNonPrivateMethod() :
		execution(!private * *(..)) && @annotation(Transactional);

	/**
	 * Definition of pointcut from super aspect - matched join points
	 * will have Spring transaction management applied.
	 */
	protected pointcut transactionalMethodExecution(Object txObject) :
		(executionOfAnyPublicMethodInAtTransactionalType()
		 || executionOfTransactionalNonPrivateMethod())
		 && this(txObject);

	/**
	 * Annotating private methods with @Transactional has no effect...
	 */
	declare warning
	    // note, we should be able to say the following in one execution pcd, but
	    // aj doesn't like it...
		: execution(@Transactional * *(..)) &&
		  execution(private * *(..))
		: "@Transactional annotation on private method will be ignored";
}


added svn:ignore settings, added license header

/**
 * palava - a java-php-bridge
 * Copyright (C) 2007-2010  CosmoCode GmbH
 *
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

package de.cosmocode.palava.jpa.jta;

import de.cosmocode.palava.jta.AbstractUserTransactionAspect;

import de.cosmocode.palava.jpa.Transactional;

public aspect UserTransactionAspect extends AbstractUserTransactionAspect {

    protected pointcut transactional(): execution(@Transactional * *.*(..));

}