Fixed requesting location updates when a battery ok broadcast is received and GPS is used.

/*
 * 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.IgnitedAbstractLastLocationFinder;
import com.github.ignition.location.templates.IgnitedAbstractLocationUpdateRequester;
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, lowPowerCriteria;
    protected IgnitedAbstractLocationUpdateRequester locationUpdateRequester;
    protected PendingIntent locationListenerPendingIntent, locationListenerPassivePendingIntent;
    protected LocationManager locationManager;
    protected IgnitedLocationListener bestInactiveLocationProviderListener;

    private Context context;
    private volatile Location currentLocation;

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

    private long locationUpdatesInterval, passiveLocationUpdatesInterval;
    private int locationUpdatesDistanceDiff;
    private int passiveLocationUpdatesDistanceDiff;
    private boolean requestLocationUpdates;
    private boolean locationUpdatesDisabled = true;

    // 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, lowPowerCriteria());
        }
    };

    /**
     * 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, null);
            }
        }
    };

    /**
     * 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, null);
        }
    };

    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
        if (defaultCriteria == null) {
            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.putBoolean(IgnitedLocationConstants.SP_KEY_SHOW_WAIT_FOR_LOCATION_DIALOG,
                locationAnnotation.showWaitForLocationDialog());
        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, lng/acc): "
                + currentLocation.getLatitude() + ", " + currentLocation.getLongitude() + "/" + currentLocation.getAccuracy());
    }

    void around(Location freshLocation) : set(@IgnitedLocation Location *) && args(freshLocation)
        && (within(IgnitedLocationChangedReceiver) || within(IgnitedAbstractLastLocationFinder)
                || within(IgnitedLastKnownLocationAsyncTask)) && !adviceexecution() {

        if (context == null) {
            return;
        }
        final Activity activity = (Activity) context;
        boolean showWaitForLocationDialog = prefs.getBoolean(
                IgnitedLocationConstants.SP_KEY_SHOW_WAIT_FOR_LOCATION_DIALOG,
                IgnitedLocationConstants.SHOW_WAIT_FOR_LOCATION_DIALOG_DEFAULT);
        if (freshLocation == null && showWaitForLocationDialog) {
            activity.showDialog(R.id.ign_loc_dialog_wait_for_fix);
            return;
        }

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

        // If gps is enabled location comes from gps, remove runnable that removes gps updates
        boolean lastLocation = extras.containsKey(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 criteria) {
        if (!locationUpdatesDisabled) {
            return;
        }
        Criteria locationUpdateCriteria = criteria;
        if (criteria == null) {
            if (isBatteryOk()) {
                locationUpdateCriteria = defaultCriteria;
            } else {
                locationUpdateCriteria = lowPowerCriteria();
            }
        }
        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 lowPowerCriteria() {
        if (lowPowerCriteria == null) {
            lowPowerCriteria = new Criteria();
            lowPowerCriteria.setPowerRequirement(Criteria.POWER_LOW);
            lowPowerCriteria.setAccuracy(Criteria.NO_REQUIREMENT);
        }
        return lowPowerCriteria;
    }

    /**
     * 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, null);
        }
    }

}

/*
 * 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.IgnitedAbstractLastLocationFinder;
import com.github.ignition.location.templates.IgnitedAbstractLocationUpdateRequester;
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, lowPowerCriteria;
    protected IgnitedAbstractLocationUpdateRequester locationUpdateRequester;
    protected PendingIntent locationListenerPendingIntent, locationListenerPassivePendingIntent;
    protected LocationManager locationManager;
    protected IgnitedLocationListener bestInactiveLocationProviderListener;

    private Context context;
    private volatile Location currentLocation;

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

    private long locationUpdatesInterval, passiveLocationUpdatesInterval;
    private int locationUpdatesDistanceDiff;
    private int passiveLocationUpdatesDistanceDiff;
    private boolean requestLocationUpdates;
    private boolean locationUpdatesDisabled = true;

    // 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, lowPowerCriteria());
        }
    };

    /**
     * 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, null);
            }
        }
    };

    /**
     * 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, lowPowerCriteria());
        }
    };

    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
        if (defaultCriteria == null) {
            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.putBoolean(IgnitedLocationConstants.SP_KEY_SHOW_WAIT_FOR_LOCATION_DIALOG,
                locationAnnotation.showWaitForLocationDialog());
        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, lng/acc): "
                + currentLocation.getLatitude() + ", " + currentLocation.getLongitude() + "/" + currentLocation.getAccuracy());
    }

    void around(Location freshLocation) : set(@IgnitedLocation Location *) && args(freshLocation)
        && (within(IgnitedLocationChangedReceiver) || within(IgnitedAbstractLastLocationFinder)
                || within(IgnitedLastKnownLocationAsyncTask)) && !adviceexecution() {

        if (context == null) {
            return;
        }
        final Activity activity = (Activity) context;
        boolean showWaitForLocationDialog = prefs.getBoolean(
                IgnitedLocationConstants.SP_KEY_SHOW_WAIT_FOR_LOCATION_DIALOG,
                IgnitedLocationConstants.SHOW_WAIT_FOR_LOCATION_DIALOG_DEFAULT);
        if (freshLocation == null && showWaitForLocationDialog) {
            activity.showDialog(R.id.ign_loc_dialog_wait_for_fix);
            return;
        }

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

        // If gps is enabled location comes from gps, remove runnable that removes gps updates
        boolean lastLocation = extras.containsKey(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 criteria) {
        if (!locationUpdatesDisabled) {
            return;
        }
        Criteria locationUpdateCriteria = criteria;
        if (criteria == null) {
            if (isBatteryOk()) {
                locationUpdateCriteria = defaultCriteria;
            } else {
                locationUpdateCriteria = lowPowerCriteria();
            }
        }
        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 lowPowerCriteria() {
        if (lowPowerCriteria == null) {
            lowPowerCriteria = new Criteria();
            lowPowerCriteria.setPowerRequirement(Criteria.POWER_LOW);
            lowPowerCriteria.setAccuracy(Criteria.NO_REQUIREMENT);
        }
        return lowPowerCriteria;
    }

    /**
     * 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, null);
        }
    }

}


added AbstractPalavaAspect to allow createInjector interception

package de.cosmocode.palava.core.aop;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Guice;
import com.google.inject.Injector;

public abstract aspect AbstractPalavaAspect {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractPalavaAspect.class);

    private boolean alreadyInjected = false;

    pointcut createInjector(): call(Injector Guice.createInjector(..));

    @SuppressAjWarnings("adviceDidNotMatch")
    after() returning (Injector injector): createInjector() {
        LOG.trace("Injecting members on {}", this);
        Preconditions.checkState(!alreadyInjected, "Members have been already injected on {}", this);
        injector.injectMembers(this);
    }

}

error: pathspec 'src/main/java/de/cosmocode/palava/core/aop/AbstractPalavaAspect.aj' did not match any file(s) known to git


renamed TransactionAspect to EntityTransactionAspect

/**
 * 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.aspectj;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceException;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Provider;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;
import de.cosmocode.palava.jpa.Transactional;

public final aspect EntityTransactionAspect extends AbstractPalavaAspect issingleton() {

    private static final Logger LOG = LoggerFactory.getLogger(EntityTransactionAspect.class);

    private Provider<EntityManager> currentManager;

    @Inject
    public void setProvider(Provider<EntityManager> manager) {
        this.currentManager = Preconditions.checkNotNull(manager, "Manager");
    }

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

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        final EntityManager manager = currentManager.get();
        LOG.trace("Retrieved entitymanager {}", manager);
        final EntityTransaction tx = manager.getTransaction();
        LOG.trace("Using transaction {}", tx);
        final boolean localTx = !tx.isActive();

        if (localTx) {
            LOG.trace("Beginning automatic transaction");
            tx.begin();
        } else {
            LOG.trace("Transaction already active");
        }

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (RuntimeException e) {
            LOG.error("Exception inside automatic transaction context", e);
            tx.rollback();
            throw e;
        }

        try {
            if (localTx && tx.isActive()) {
                tx.commit();
                LOG.trace("Committed automatic transaction");
            }
            return returnValue;
        } catch (PersistenceException e) {
            LOG.error("Commit in automatic transaction context failed", e);
            tx.rollback();
            throw e;
        }
    }

}

error: pathspec 'src/main/java/de/cosmocode/palava/jpa/aspectj/EntityTransactionAspect.aj' did not match any file(s) known to git


Temporarily get the new AST to implement the old interface.

import java.util.ArrayList;
import java.util.List;
import mirah.lang.ast.Node;
import mirah.lang.ast.NodeScanner;
import mirah.lang.ast.NodeImpl;

class ChildCollector extends NodeScanner {
  private ArrayList<Node> children = new ArrayList<Node>();

  @Override
  public boolean enterDefault(Node node, Object arg) {
    if (node == arg) {
      return true;
    } else {
      children.add(node);
      return false;
    }
  }

  @Override
  public Object enterNullChild(Object arg){
    children.add(null);
    return null;
  }

  public ArrayList<Node> children() {
    return children;
  }
}

aspect DubyBootsrap {
  declare parents: Node extends duby.lang.compiler.Node;

  public List<Node> NodeImpl.child_nodes() {
    ChildCollector c = new ChildCollector();
    c.scan(this, this);
    return c.children();
  }
}

error: pathspec 'src/DubyBootstrap.aj' did not match any file(s) known to git


disable Aspectj by default

disable Aspectj by default

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/openvraas/openvraas-undertow.git/'


Request tracing aspect v0

Request tracing aspect v0

/**
 * Created with IntelliJ IDEA.
 * User: kockt
 * Date: 13-01-13
 * Time: 17:09
 * To change this template use File | Settings | File Templates.
 */
public aspect TraceRequestFlow {

    pointcut was_called(Object o):
            target(o) && call(* *(..)) && within(net.winstone);

    before() calling: was_called(o) {
        System.out.println(o);
    }

}

error: pathspec 'winstone/src/main/aspectj/TraceRequestFlow.aj' did not match any file(s) known to git


Interceptor

Interceptor

public aspect MethodInterceptor {

	//pointcut traced() : !within(MethodInterceptor) && execution(public * *.*(..)) ;
	pointcut traced() : !within(MethodInterceptor) && execution(* *.*(..)) ;

	before() : traced() {
		print("Executing", thisJoinPoint);
	}

	private void print(String prefix, Object message) {

		System.out.println(prefix + ": " + message);
	}
}

error: pathspec 'UMLGenerator/src/main/java/com/sjsu/umlgenerator/aspect/MethodInterceptor.aj' did not match any file(s) known to git


budget and quota chnages

budget and quota chnages

// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO.
// You may push code into the target .java compilation unit if you wish to edit any member(s).

package in.mycp.domain;

import in.mycp.domain.Company;

privileged aspect Company_Roo_JavaBean {

    public Integer Company.getQuota() {
        return this.quota;
    }

    public void Company.setQuota(Integer quota) {
        this.quota = quota;
    }

    public Integer Company.getMinBal() {
        return this.minBal;
    }

    public void Company.setMinBal(Integer minBal) {
        this.minBal = minBal;
    }

}

error: pathspec 'src/main/java/in/mycp/domain/Company_Roo_JavaBean.aj' did not match any file(s) known to git


添加debug时可以通过继承来使用的AbstractTrace.aj

添加debug时可以通过继承来使用的AbstractTrace.aj

新增 debug时，用于跟踪当前执行位置的AbstractTrace.aj
     使用示例：
// File：app/src/debug/java/tracing/lib/TraceMyClasses.aj
package tracing.lib;

aspect TraceMyClasses extends AbstractTrace {
        pointcut classes(): within(com.optimalorange.cooltechnologies.ui..*);
        pointcut constructors(): execution(new(..));
        pointcut methods(): execution(!abstract * *(..));
}

/*

Copyright (c) Xerox Corporation 1998-2002.  All rights reserved.

Use and copying of this software and preparation of derivative works based
upon this software are permitted.  Any distribution of this software or
derivative works must comply with all applicable United States export control
laws.

This software is made available AS IS, and Xerox Corporation makes no warranty
about the software, its performance or its conformity to any specification.

|<---            this code is formatted to fit into 80 columns             --->|
|<---            this code is formatted to fit into 80 columns             --->|
|<---            this code is formatted to fit into 80 columns             --->|

*/

package tracing.lib;

import org.aspectj.lang.JoinPoint;

import java.io.PrintStream;

/**
 * This class provides support for printing trace messages into a stream.
 * The trace messages consist of the class name, method name (if method)
 * and the list of parameter types.

 * The class is thread-safe. Different threads may use different output streams
 * by simply calling the method initStream(myStream).

 * This class should be extended.
 * It defines 3 abstract crosscuts for injecting the tracing functionality
 * into any constructors and methods of any application classes.

 *
 * One example of using this class might be
 *

 * import tracing.lib.AbstractTrace;
 * aspect TraceMyClasses extends AbstractTrace of eachJVM() {
 *   pointcut classes(): within(TwoDShape) || within(Circle) || within(Square);
 *   pointcut constructors(): execution(new(..));
 *   pointcut methods(): execution(!abstract * *(..));
 * }
 *

 * (Make sure .../aspectj/examples is in your classpath)
 */
public abstract aspect AbstractTrace {

    /**
     * Application classes - left unspecified.
     * Subclasses should concretize this crosscut with class names.
     */
    abstract pointcut classes();
    /**
     * Constructors - left unspecified.
     * Subclasses should concretize this crosscut with constructors.
     */
    abstract pointcut constructors();
    /**
     * Methods - left unspecified.
     * Subclasses should concretize this crosscut with method names.
     */
    abstract pointcut methods();

    before(): classes() && constructors() {
        doTraceEntry(thisJoinPoint, true);
    }
    after(): classes() && constructors() {
        doTraceExit(thisJoinPoint, true);
    }

    before(): classes() && methods() {
        doTraceEntry(thisJoinPoint, false);
    }
    after(): classes() && methods() {
        doTraceExit(thisJoinPoint, false);
    }

    /*
     * From here on, it's an ordinary class implementation.
     * The static state is thread-safe by using ThreadLocal variables.
     */

    /**
     * This method initializes this thread's trace output stream.
     * By default, the output stream is System.err, and it is the same for
     * all threads. In multithreaded applications, you may want to define
     * different output streams for the different threads. For doing it,
     * simply call this method in the beginning of each thread's main loop,
     * giving it different output streams.
     */
    public void initStream(PrintStream _stream) {
        setStream(_stream);
    }

    private ThreadLocal stream = new ThreadLocal() {
        protected Object initialValue() {
            return System.err;
        }
    };

    private ThreadLocal callDepth = new ThreadLocal() {
        protected Object initialValue() {
            return new Integer(0);
        }
    };

    private PrintStream getStream() {
        return (PrintStream) stream.get();
    }

    private void setStream(PrintStream s) {
        stream.set(s);
    }

    private int getCallDepth() {
        return ((Integer) (callDepth.get())).intValue();
    }

    private void setCallDepth(int n) {
        callDepth.set(new Integer(n));
    }

    private void doTraceEntry(JoinPoint jp, boolean isConstructor) {
        setCallDepth(getCallDepth() + 1);
        printEntering(jp, isConstructor);
    }

    private void doTraceExit(JoinPoint jp, boolean isConstructor) {
        printExiting(jp, isConstructor);
        setCallDepth(getCallDepth() - 1);
    }

    private void printEntering(JoinPoint jp, boolean isConstructor) {
        printIndent();
        getStream().print("--> ");
        getStream().print(jp);
        //        printParameterTypes(jp);
        getStream().println();
    }

    private void printExiting(JoinPoint jp, boolean isConstructor) {
        printIndent();
        getStream().print("<--  ");
        getStream().print(jp);
        //        printParameterTypes(jp);
        getStream().println();
    }

//      private void printParameterTypes(JoinPoint jp) {
//          Class[]  ptypes = jp.parameterTypes;

//          getStream().print("(");
//          for (int i = 0; i < ptypes.length; i++) {
//              getStream().print(ptypes[i].getName());
//              if (i < ptypes.length - 1) getStream().print(", ");
//          }
//          getStream().print(")");
//      }

    private void printIndent() {
        for (int i = 0; i < getCallDepth(); i++) {
            getStream().print(" ");
        }
    }

    /**
     * This method is not being used.
     * It's being included solely for illustrating how to access and use
     * the information in JoinPoint.
     * If you want, you can replace the calls to printParameterTypes (above)
     * by calls to this method.
     */
//      private void printParameters(JoinPoint jp) {
//          Class[]  ptypes = jp.parameterTypes;
//          String[] pnames = jp.parameterNames;
//          Object[] params = jp.parameters;

//          getStream().print("(");
//          for (int i = 0; i < ptypes.length; i++) {
//              getStream().print(ptypes[i].getName() + " " +
//                                pnames[i]           + "=" +
//                                params[i]);
//              if (i < ptypes.length - 1) getStream().print(", ");
//          }
//          getStream().print(")");
//      }

}

error: pathspec 'app/src/debug/java/tracing/lib/AbstractTrace.aj' did not match any file(s) known to git


Fixed null-pointer bug in DetectSwingSingleThreadRuleViolations.

/*
 * Package package net.sf.jabref.aspects.violations;
 * Created on Nov 6, 2004
 * Author mspiegel
 *
 */
package net.sf.jabref.aspects.violations;

import java.awt.Component;
import java.awt.EventQueue;

public aspect DetectSwingSingleThreadRuleViolations {

	pointcut guiUpdates(Component component)
		:	call(* java..Component+.*(..)) &&
		    !call(* net..jabref+.*(..)) && target(component);

	pointcut safeGuiCalls()
		: call (* javax..JComponent.repaint(..))
			|| call(* javax..JComponent.revalidate(..))
		    || call(* javax..JComponent.invalidate(..))
		    || call(* javax..*.add*Listener(..))
		    || call(* javax..*.remove*Listener(..));

	pointcut unsafeGuiCalls(Component component)
		: guiUpdates(component) && !safeGuiCalls();

    before(Component component) : unsafeGuiCalls(component)
    	&& if (!EventQueue.isDispatchThread() && (component != null) &&
    	        	component.isDisplayable() && !Thread.currentThread().getName().equals("main")) {
            System.err.println(
                    "Violation: Swing component method called from nonAWT thread"
                    + "\nCalled method: " + thisJoinPointStaticPart.getSignature()
                    + "\nCaller:" + thisEnclosingJoinPointStaticPart.getSignature()
                    + "\nSource Location:" + thisJoinPointStaticPart.getSourceLocation()
                    + "\nThread:" + Thread.currentThread()
                    + "\nChange code to use EventQueue.invokeLater() or EventQueue.invokeAndWait()"
                    + "\n");
    	}

}

/*
 * Package package net.sf.jabref.aspects.violations;
 * Created on Nov 6, 2004
 * Author mspiegel
 *
 */
package net.sf.jabref.aspects.violations;

import java.awt.Component;
import java.awt.EventQueue;

public aspect DetectSwingSingleThreadRuleViolations {

	pointcut guiUpdates(Component component)
		:	call(* java..Component+.*(..)) &&
		    !call(* net..jabref+.*(..)) && target(component);

	pointcut safeGuiCalls()
		: call (* javax..JComponent.repaint(..))
			|| call(* javax..JComponent.revalidate(..))
		    || call(* javax..JComponent.invalidate(..))
		    || call(* javax..*.add*Listener(..))
		    || call(* javax..*.remove*Listener(..));

	pointcut unsafeGuiCalls(Component component)
		: guiUpdates(component) && !safeGuiCalls();

    before(Component component) : unsafeGuiCalls(component)
    	&& if (!EventQueue.isDispatchThread() && component.isDisplayable() &&
    	        	!Thread.currentThread().getName().equals("main")) {
            System.err.println(
                    "Violation: Swing component method called from nonAWT thread"
                    + "\nCalled method: " + thisJoinPointStaticPart.getSignature()
                    + "\nCaller:" + thisEnclosingJoinPointStaticPart.getSignature()
                    + "\nSource Location:" + thisJoinPointStaticPart.getSourceLocation()
                    + "\nThread:" + Thread.currentThread()
                    + "\nChange code to use EventQueue.invokeLater() or EventQueue.invokeAndWait()"
                    + "\n");
    	}

}


+ aspect for injector

+ aspect for injector

package ru.agentlab.maia.context.logs;

public aspect AInjectorLogs {

//	before(IMaiaContextFactory factory) :
//		onCreateContext(factory) {
//		Logger logger = LoggerFactory.getLogger(factory.getClass());
//		logger.info("Try to create context...");
//	}
//
//	after(IMaiaContextFactory factory) returning (IMaiaContext result):
//		onCreateContext(factory) {
//		Logger logger = LoggerFactory.getLogger(factory.getClass());
//		logger.info("Context [" + result.getUuid() + "] successfully created");
//	}
}

error: pathspec 'aspects/ru.agentlab.maia.context.logs/aj-src/ru/agentlab/maia/context/logs/AInjectorLogs.aj' did not match any file(s) known to git


Instrumentation added for property Java 4-3 (JavaMOP)

package benchmark.competition.java.javaMOP;

import monitoring.impl.MonitorFactory;
import monitoring.intf.Monitor;
import properties.Property;
import properties.competition.JavaMOP;
import structure.impl.other.Verdict;
import structure.intf.QEA;

public aspect JavaMOPThreeAspect {

	private final Monitor monitor;

	private final int A = 1;
	private final int B = 2;
	private final int C = 3;

	public JavaMOPThreeAspect() {
		QEA qea = new JavaMOP().make(Property.JAVAMOP_THREE);
		monitor = MonitorFactory.create(qea);
	}

	pointcut A() : call(void CThread2.A());

	pointcut B() : call(void CThread2.B());

	pointcut C() : call(void CThread2.C());

	before() : A() {
		Verdict verdict;
		synchronized (monitor) {
			verdict = monitor.step(A);
		}
		if (verdict == Verdict.FAILURE) {
			System.err
			.println("Violation in JavaMOP 3. The functions A(), B(), C() must be called equal times.");
		}
	}

	before() : B() {
		Verdict verdict;
		synchronized (monitor) {
			verdict = monitor.step(B);
		}
		if (verdict == Verdict.FAILURE) {
			System.err
			.println("Violation in JavaMOP 3. The functions A(), B(), C() must be called equal times.");
		}
	}

	before() : C() {
		Verdict verdict;
		synchronized (monitor) {
			verdict = monitor.step(C);
		}
		if (verdict == Verdict.FAILURE) {
			System.err
			.println("Violation in JavaMOP 3. The functions A(), B(), C() must be called equal times.");
		}
	}

	pointcut endOfProgram() : execution(void SRSTest.main(String[]));

	after() : endOfProgram() {
		Verdict verdict = monitor.end();
		if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
			System.err
					.println("Violation in JavaMOP 3. The functions A(), B(), C() must be called equal times.");
		} else {
			System.err.println("Property JavaMOP 3 satisfied");
		}
	}
}

error: pathspec 'code/qea/src/benchmark/competition/java/javaMOP/JavaMOPThreeAspect.aj' did not match any file(s) known to git