Program status incorrect using remote launching and Handlers on RunnableProgram status

https://github.com/XA-Labs/org.parallelj/issues/74

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

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.parallelj.Programs;
import org.parallelj.Programs.ProcessHelper;
import org.parallelj.internal.kernel.KProcess;
import org.parallelj.internal.kernel.KProcessor;
import org.parallelj.internal.kernel.KProgram;
import org.parallelj.internal.kernel.procedure.CallableProcedure;
import org.parallelj.internal.kernel.procedure.RunnableProcedure;
import org.parallelj.internal.reflect.ProgramAdapter.Adapter;
import org.parallelj.launching.LaunchingMessageKind;
import org.parallelj.launching.ReturnCodes;
import org.parallelj.mirror.ProgramType;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 * Implements the Job.execute(..) method
 *
 *
 */
privileged public aspect ProgramJobsAdapter {

	/*
	 * The Aspect JobsAdapter must be passed before this.
	 */
	declare precedence :
		org.parallelj.internal.kernel.Identifiers,
		org.parallelj.internal.reflect.ProgramAdapter,
		org.parallelj.internal.util.sm.impl.KStateMachines,
		org.parallelj.internal.util.sm.impl.KStateMachines.PerMachine,
		org.parallelj.Executables$PerExecutable,
		org.parallelj.internal.reflect.ProgramAdapter.PerProgram,
		org.parallelj.internal.log.Logs,
		org.parallelj.launching.quartz.JobsAdapter;

	/*
	 * Add the interface IProceduresInError to the KProcessor
	*/
	private interface IProceduresInError {
		public void addProcedureInError(String name, Exception exception);
	}
	public Map<String, Set<String>> IProceduresInError.proceduresInError=new HashMap<String, Set<String>>();

	public synchronized void IProceduresInError.addProcedureInError(String name, Exception exception) {
		Set<String> exceptions = ((IProceduresInError)this).proceduresInError.get(name);
		if (exceptions==null) {
			// This is the first "name" Procedure in error
			exceptions = new HashSet<String>();
		}
		if (!exceptions.contains(exception.getClass().getCanonicalName())) {
			exceptions.add(exception.getClass().getCanonicalName());
		}
		((IProceduresInError)this).proceduresInError.put(name, exceptions);
	}

	declare parents: org.parallelj.internal.kernel.KProcessor implements IProceduresInError;

	/**
	 * Launch a Program and initialize the Result as a JobDataMap.
	 *
	 * @param self
	 * @param context
	 * @throws JobExecutionException
	 */
	void around(Job self, JobExecutionContext context)
			throws JobExecutionException :
		execution( public void  Job+.execute(..) throws JobExecutionException)
			&& (within(@org.parallelj.Program *) || within(JobsAdapter))
				&& args(context) && this(self) {
		JobDataMap jobDataMap = new JobDataMap();
		context.setResult(jobDataMap);
		jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.SUCCESS);

		proceed(self, context);

		try {
			// Initialize an ExecutorService with the Capacity of the Program
			ProcessHelper<?> processHelper = Programs.as((Adapter) self);
			if (processHelper == null) {
				jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.NOTSTARTED);
				throw new JobExecutionException(LaunchingMessageKind.ELAUNCH0003.getFormatedMessage(self));
			}
			ProgramType programType = processHelper.getProcess().getProgram();
			ExecutorService service = null;
			// If an executorService was specified, we use it

			if (context.getJobDetail().getJobDataMap().get(Launch.DEFAULT_EXECUTOR_KEY) != null) {
				service = (ExecutorService)context.getJobDetail().getJobDataMap().get(Launch.DEFAULT_EXECUTOR_KEY);
			} else
			if (programType instanceof KProgram) {
				short programCapacity = ((KProgram) programType)
						.getCapacity();
				service = (programCapacity == Short.MAX_VALUE) ? Executors
						.newCachedThreadPool() : Executors
						.newFixedThreadPool(programCapacity);
			} else {
				service = Executors
						.newCachedThreadPool();
			}

			// Launch the program with the initialized ExecutorService
			processHelper.execute(service).join();

			KProcessor rootProcessor = ((KProcessor)processHelper.getProcess().getProcessor());
			IProceduresInError procedures = (IProceduresInError)rootProcessor;
			if(procedures.proceduresInError.size()>0) {
				jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.FAILURE);
			}

			ProgramFieldsBinder.getProgramOutputFields(this, context);
			service.shutdown();

			if (procedures.proceduresInError.size()>0){
				jobDataMap.put(QuartzUtils.PROCEDURES_IN_ERROR, procedures.proceduresInError);
				throw new JobExecutionException();
			}
		} catch (IllegalAccessException e) {
			jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.FAILURE);
			throw new JobExecutionException(e);
		} catch (NoSuchFieldException e) {
			jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.FAILURE);
			throw new JobExecutionException(e);
		}
	}

	/*
	 * Add the interface IExceptionTracking to all Runnable and Callable
	 */
    public interface IExceptionTracking {};
  	private Object IExceptionTracking.context = null;

    declare parents:
    	(java.lang.Runnable+ ) implements IExceptionTracking;
    declare parents:
    	(java.util.concurrent.Callable+ ) implements IExceptionTracking;

	// Interception around Runnable execution
  	after(Object self) returning (Runnable ret):
  		execution(* org.parallelj.internal.kernel.procedure.RunnableProcedure.RunnableCall.toRunnable())
      && this(self)  {
   	  ((IExceptionTracking)ret).context = ((org.parallelj.internal.kernel.KCall)self);
    }

	// Interception around Callable execution
  	after(Object self) returning (Runnable ret):
  		execution(* org.parallelj.internal.kernel.procedure.CallableProcedure.CallableCall.toRunnable())
      && this(self)  {
   	  ((IExceptionTracking)ret).context = ((org.parallelj.internal.kernel.KCall)self);
    }

	// Interception around Runnable execution
	 void around(Object self): call(void complete())
	&& within(org.parallelj.internal.kernel.procedure.RunnableProcedure.RunnableCall)
		&& this(self)  {

			RunnableProcedure.RunnableCall runnable = (RunnableProcedure.RunnableCall)((IExceptionTracking)self).context;
			RunnableProcedure procedure = (RunnableProcedure)runnable.getProcedure();
			if (procedure.getHandler() == null
					&& runnable.getException() != null) {
				// There is an error !!!
				KProcess process = ((RunnableProcedure.RunnableCall)((IExceptionTracking)self).context).getProcess();
				KProcessor rootProcessor = process.getProcessor();//.getRootProcessor();
				((IProceduresInError)rootProcessor).addProcedureInError(procedure.getType(), runnable.getException());
			}
		proceed(self);
	}

	// Interception around Callable execution
	 void around(Object self): call(void complete())
		 && within(org.parallelj.internal.kernel.procedure.CallableProcedure.CallableCall)
		&& this(self)  {

			CallableProcedure.CallableCall callable = (CallableProcedure.CallableCall)((IExceptionTracking)self).context;
			CallableProcedure procedure = (CallableProcedure)callable.getProcedure();

			if (
					procedure.getHandler() == null
					&& callable.getException() != null
					) {
				// There is an error !!!
				KProcess process = ((CallableProcedure.CallableCall)((IExceptionTracking)self).context).getProcess();
				KProcessor rootProcessor = process.getProcessor();//.getRootProcessor();
				((IProceduresInError)rootProcessor).addProcedureInError(procedure.getType(), callable.getException());
			}
		proceed(self);
	}

	/*
	 * Allow to get the procedures in error of a Process (the root Process !!!)
	 */
	public static synchronized Map<String, Set<String>> getProceduresInErrors(
			org.parallelj.mirror.Process process) {
		KProcessor rootProcessor = ((KProcessor) process.getProcessor());
		IProceduresInError procedures = (IProceduresInError) rootProcessor;
		return procedures.proceduresInError;
	}
}

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

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.parallelj.Programs;
import org.parallelj.Programs.ProcessHelper;
import org.parallelj.internal.kernel.KProcess;
import org.parallelj.internal.kernel.KProcessor;
import org.parallelj.internal.kernel.KProgram;
import org.parallelj.internal.kernel.procedure.CallableProcedure;
import org.parallelj.internal.kernel.procedure.RunnableProcedure;
import org.parallelj.internal.reflect.ProgramAdapter.Adapter;
import org.parallelj.launching.LaunchingMessageKind;
import org.parallelj.launching.ReturnCodes;
import org.parallelj.mirror.ProgramType;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 * Implements the Job.execute(..) method
 *
 *
 */
privileged public aspect ProgramJobsAdapter {

	/*
	 * The Aspect JobsAdapter must be passed before this.
	 */
	declare precedence :
		org.parallelj.internal.kernel.Identifiers,
		org.parallelj.internal.reflect.ProgramAdapter,
		org.parallelj.internal.util.sm.impl.KStateMachines,
		org.parallelj.internal.util.sm.impl.KStateMachines.PerMachine,
		org.parallelj.Executables$PerExecutable,
		org.parallelj.internal.reflect.ProgramAdapter.PerProgram,
		org.parallelj.internal.log.Logs,
		org.parallelj.launching.quartz.JobsAdapter;

	/*
	 * Add the interface IProceduresInError to the KProcessor
	*/
	private interface IProceduresInError {
		public void addProcedureInError(String name, Exception exception);
	}
	public Map<String, Set<String>> IProceduresInError.proceduresInError=new HashMap<String, Set<String>>();

	public synchronized void IProceduresInError.addProcedureInError(String name, Exception exception) {
		Set<String> exceptions = ((IProceduresInError)this).proceduresInError.get(name);
		if (exceptions==null) {
			// This is the first "name" Procedure in error
			exceptions = new HashSet<String>();
		}
		if (!exceptions.contains(exception.getClass().getCanonicalName())) {
			exceptions.add(exception.getClass().getCanonicalName());
		}
		((IProceduresInError)this).proceduresInError.put(name, exceptions);
	}

	declare parents: org.parallelj.internal.kernel.KProcessor implements IProceduresInError;

	/**
	 * Launch a Program and initialize the Result as a JobDataMap.
	 *
	 * @param self
	 * @param context
	 * @throws JobExecutionException
	 */
	void around(Job self, JobExecutionContext context)
			throws JobExecutionException :
		execution( public void  Job+.execute(..) throws JobExecutionException)
			&& (within(@org.parallelj.Program *) || within(JobsAdapter))
				&& args(context) && this(self) {
		JobDataMap jobDataMap = new JobDataMap();
		context.setResult(jobDataMap);
		jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.SUCCESS);

		proceed(self, context);

		try {
			// Initialize an ExecutorService with the Capacity of the Program
			ProcessHelper<?> processHelper = Programs.as((Adapter) self);
			if (processHelper == null) {
				jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.NOTSTARTED);
				throw new JobExecutionException(LaunchingMessageKind.ELAUNCH0003.getFormatedMessage(self));
			}
			ProgramType programType = processHelper.getProcess().getProgram();
			ExecutorService service = null;
			// If an executorService was specified, we use it

			if (context.getJobDetail().getJobDataMap().get(Launch.DEFAULT_EXECUTOR_KEY) != null) {
				service = (ExecutorService)context.getJobDetail().getJobDataMap().get(Launch.DEFAULT_EXECUTOR_KEY);
			} else
			if (programType instanceof KProgram) {
				short programCapacity = ((KProgram) programType)
						.getCapacity();
				service = (programCapacity == Short.MAX_VALUE) ? Executors
						.newCachedThreadPool() : Executors
						.newFixedThreadPool(programCapacity);
			} else {
				service = Executors
						.newCachedThreadPool();
			}

			// Launch the program with the initialized ExecutorService
			processHelper.execute(service).join();

			KProcessor rootProcessor = ((KProcessor)processHelper.getProcess().getProcessor());
			IProceduresInError procedures = (IProceduresInError)rootProcessor;
			if(procedures.proceduresInError.size()>0) {
				jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.FAILURE);
			}

			ProgramFieldsBinder.getProgramOutputFields(this, context);
			service.shutdown();

			if (procedures.proceduresInError.size()>0){
				jobDataMap.put(QuartzUtils.PROCEDURES_IN_ERROR, procedures.proceduresInError);
				throw new JobExecutionException();
			}
		} catch (IllegalAccessException e) {
			jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.FAILURE);
			throw new JobExecutionException(e);
		} catch (NoSuchFieldException e) {
			jobDataMap.put(QuartzUtils.RETURN_CODE, ReturnCodes.FAILURE);
			throw new JobExecutionException(e);
		}
	}

	/*
	 * Add the interface IExceptionTracking to all Runnable and Callable
	 */
    public interface IExceptionTracking {};
  	private Object IExceptionTracking.context = null;

    declare parents:
    	(java.lang.Runnable+ ) implements IExceptionTracking;
    declare parents:
    	(java.util.concurrent.Callable+ ) implements IExceptionTracking;

	// Interception around Runnable execution
  	after(Object self) returning (Runnable ret):
  		execution(* org.parallelj.internal.kernel.procedure.RunnableProcedure.RunnableCall.toRunnable())
      && this(self)  {
   	  ((IExceptionTracking)ret).context = ((org.parallelj.internal.kernel.KCall)self);
    }

	// Interception around Callable execution
  	after(Object self) returning (Runnable ret):
  		execution(* org.parallelj.internal.kernel.procedure.CallableProcedure.CallableCall.toRunnable())
      && this(self)  {
   	  ((IExceptionTracking)ret).context = ((org.parallelj.internal.kernel.KCall)self);
    }

	// Interception around Runnable execution
	 void around(Object self): call(void complete())
	&& within(org.parallelj.internal.kernel.procedure.RunnableProcedure.RunnableCall)
		&& this(self)  {

			RunnableProcedure.RunnableCall runnable = (RunnableProcedure.RunnableCall)((IExceptionTracking)self).context;
			RunnableProcedure procedure = (RunnableProcedure)runnable.getProcedure();
			if (runnable.getException() != null) {
				KProcess process = ((RunnableProcedure.RunnableCall)((IExceptionTracking)self).context).getProcess();
				KProcessor rootProcessor = process.getProcessor();//.getRootProcessor();
				((IProceduresInError)rootProcessor).addProcedureInError(procedure.getType(), runnable.getException());
			}
		proceed(self);
	}

	// Interception around Callable execution
	 void around(Object self): call(void complete())
		 && within(org.parallelj.internal.kernel.procedure.CallableProcedure.CallableCall)
		&& this(self)  {

			CallableProcedure.CallableCall callable = (CallableProcedure.CallableCall)((IExceptionTracking)self).context;
			CallableProcedure procedure = (CallableProcedure)callable.getProcedure();

			if (
					procedure.getHandler() == null
					&& callable.getException() != null
					) {
				// There is an error !!!
				KProcess process = ((CallableProcedure.CallableCall)((IExceptionTracking)self).context).getProcess();
				KProcessor rootProcessor = process.getProcessor();//.getRootProcessor();
				((IProceduresInError)rootProcessor).addProcedureInError(procedure.getType(), callable.getException());
			}
		proceed(self);
	}

	/*
	 * Allow to get the procedures in error of a Process (the root Process !!!)
	 */
	public static synchronized Map<String, Set<String>> getProceduresInErrors(
			org.parallelj.mirror.Process process) {
		KProcessor rootProcessor = ((KProcessor) process.getProcessor());
		IProceduresInError procedures = (IProceduresInError) rootProcessor;
		return procedures.proceduresInError;
	}
}


attempt to fix rollback/inactive bug

attempt to fix rollback/inactive bug

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * 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 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;
        }

        if (localTx && tx.isActive()) {
            if (tx.getRollbackOnly()) {
                LOG.trace("Transaction was marked as rollback only. Rolling back...");
                tx.rollback();
            } else {
                try {
                    tx.commit();
                    LOG.trace("Committed automatic transaction");
                } catch (PersistenceException e) {
                    LOG.error("Commit in automatic transaction context failed", e);
                    if (tx.isActive()) {
                        LOG.info("Rolling back {}", tx);
                        tx.rollback();
                    } else {
                        LOG.info("Can't roll back inactive transaction {}", tx);
                    }
                    throw e;
                }
            }
        }

        return returnValue;
    }

}

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * 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 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;
        }

        if (localTx && tx.isActive()) {
            if (tx.getRollbackOnly()) {
                LOG.trace("Transaction was marked as rollback only. Rolling back...");
                tx.rollback();
            } else {
                try {
                    tx.commit();
                    LOG.trace("Committed automatic transaction");
                } catch (PersistenceException e) {
                    LOG.error("Commit in automatic transaction context failed", e);
                    tx.rollback();
                    throw e;
                }
            }
        }

        return returnValue;
    }

}


log commits with debug instead of trace

log commits with debug instead of trace

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * 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 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.gag.annotation.remark.Hack;
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 * *.*(..));

    @SuppressWarnings("finally")
    @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 local = !tx.isActive();

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

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (Exception e) {
            try {
                if (local && (tx.isActive() || tx.getRollbackOnly())) {
                    LOG.debug("Rolling back local/active transaction {}", tx);
                    tx.rollback();
                } else if (!tx.getRollbackOnly()) {
                    LOG.debug("Setting transaction {} as rollback only", tx);
                    tx.setRollbackOnly();
                }
            } catch (PersistenceException inner) {
                LOG.error("Rollback failed", inner);
            } finally {
                // hack to support throwing checked exceptions
                return sneakyThrow(e);
            }
        }

        if (local && tx.isActive()) {
            if (tx.getRollbackOnly()) {
                LOG.debug("Rolling back marked transaction {}", tx);
                tx.rollback();
            } else {
                try {
                    tx.commit();
                    LOG.debug("Committed automatic transaction {}", tx);
                } catch (PersistenceException e) {
                    try {
                        LOG.debug("Rolling back transaction {}", tx);
                        tx.rollback();
                    } catch (PersistenceException inner) {
                        LOG.error("Rollback failed", inner);
                    }
                    throw e;
                }
            }
        } else {
            LOG.trace("Not committing non-local transaction {}", tx);
        }

        return returnValue;
    }

    @Hack("Why is this possible?")
    private Object sneakyThrow(Throwable t) {
        this.<RuntimeException>doSneakyThrow(t);
        return null;
    }

    @SuppressWarnings("unchecked")
    private <T extends Throwable> T doSneakyThrow(Throwable t) throws T {
        throw (T) t;
    }

}

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * 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 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.gag.annotation.remark.Hack;
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 * *.*(..));

    @SuppressWarnings("finally")
    @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 local = !tx.isActive();

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

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (Exception e) {
            try {
                if (local && (tx.isActive() || tx.getRollbackOnly())) {
                    LOG.debug("Rolling back local/active transaction {}", tx);
                    tx.rollback();
                } else if (!tx.getRollbackOnly()) {
                    LOG.debug("Setting transaction {} as rollback only", tx);
                    tx.setRollbackOnly();
                }
            } catch (PersistenceException inner) {
                LOG.error("Rollback failed", inner);
            } finally {
                // hack to support throwing checked exceptions
                return sneakyThrow(e);
            }
        }

        if (local && tx.isActive()) {
            if (tx.getRollbackOnly()) {
                LOG.debug("Rolling back marked transaction {}", tx);
                tx.rollback();
            } else {
                try {
                    tx.commit();
                    LOG.trace("Committed automatic transaction {}", tx);
                } catch (PersistenceException e) {
                    try {
                        LOG.debug("Rolling back transaction {}", tx);
                        tx.rollback();
                    } catch (PersistenceException inner) {
                        LOG.error("Rollback failed", inner);
                    }
                    throw e;
                }
            }
        } else {
            LOG.trace("Not committing non-local transaction {}", tx);
        }

        return returnValue;
    }

    @Hack("Why is this possible?")
    private Object sneakyThrow(Throwable t) {
        this.<RuntimeException>doSneakyThrow(t);
        return null;
    }

    @SuppressWarnings("unchecked")
    private <T extends Throwable> T doSneakyThrow(Throwable t) throws T {
        throw (T) t;
    }

}


[misc] Remove unused imports

[misc] Remove unused imports

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This 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, or (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package com.xpn.xwiki.doc;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.rendering.block.Block;
import org.xwiki.rendering.block.HeaderBlock;
import org.xwiki.rendering.block.XDOM;
import org.xwiki.rendering.block.match.ClassBlockMatcher;
import org.xwiki.rendering.listener.HeaderLevel;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.rendering.transformation.TransformationContext;
import org.xwiki.rendering.transformation.TransformationManager;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.api.DocumentSection;
import com.xpn.xwiki.internal.xml.XMLWriter;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.objects.classes.BaseClass;
import com.xpn.xwiki.objects.classes.PropertyClass;
import com.xpn.xwiki.plugin.query.XWikiCriteria;
import com.xpn.xwiki.web.Utils;

/**
 * Add a backward compatibility layer to the {@link com.xpn.xwiki.doc.XWikiDocument} class.
 *
 * @version $Id$
 */
privileged public aspect XWikiDocumentCompatibilityAspect
{
    /**
     * @deprecated since 3.0M3 use {@code Syntax.XWIKI_1_0} instead
     */
    @Deprecated
    public static final String XWikiDocument.XWIKI10_SYNTAXID = Syntax.XWIKI_1_0.toIdString();

    /**
     * @deprecated since 3.0M3 use {@code Syntax.XWIKI_2_0} instead
     */
    @Deprecated
    public static final String XWikiDocument.XWIKI20_SYNTAXID = Syntax.XWIKI_2_0.toIdString();

    /**
     * @deprecated use setStringListValue or setDBStringListProperty
     */
    @Deprecated
    public void XWikiDocument.setListValue(String className, String fieldName, List value)
    {
        BaseObject bobject = getObject(className);
        if (bobject == null) {
            bobject = new BaseObject();
            addObject(className, bobject);
        }
        bobject.setName(getFullName());
        bobject.setClassName(className);
        bobject.setListValue(fieldName, value);
        setContentDirty(true);
    }

    /**
     * This method to split section according to title.
     *
     * @return the sections in the current document
     * @throws XWikiException
     * @deprecated use {@link #getSections()} instead, since 1.6M1
     */
    @Deprecated
    public List<DocumentSection> XWikiDocument.getSplitSectionsAccordingToTitle() throws XWikiException
    {
        return getSections();
    }

    /**
     * @deprecated use {@link #getUniqueLinkedPages(XWikiContext)}
     */
    @Deprecated
    public List<String> XWikiDocument.getLinkedPages(XWikiContext context)
    {
        return new ArrayList<String>(getUniqueLinkedPages(context));
    }

    /**
     * @deprecated use {@link #getUniqueWikiLinkedPages(XWikiContext)} instead
     */
    @Deprecated
    public List<XWikiLink> XWikiDocument.getLinks(XWikiContext context) throws XWikiException
    {
        return getWikiLinkedPages(context);
    }

    /**
     * @deprecated use {@link #getUniqueWikiLinkedPages(XWikiContext)} instead
     */
    @Deprecated
    public List<XWikiLink> XWikiDocument.getWikiLinkedPages(XWikiContext context) throws XWikiException
    {
        return new ArrayList<XWikiLink>(getUniqueWikiLinkedPages(context));
    }

    /**
     * @deprecated use {@link #getBackLinkedPages(XWikiContext)} instead
     */
    @Deprecated
    public List<String> XWikiDocument.getBacklinks(XWikiContext context) throws XWikiException
    {
        return getBackLinkedPages(context);
    }

    /**
     * @param text the text to render
     * @param context the XWiki Context object
     * @return the given text rendered in the context of this document
     * @deprecated since 1.6M1 use {@link #getRenderedContent(String, String, com.xpn.xwiki.XWikiContext)}
     */
    @Deprecated
    public String XWikiDocument.getRenderedContent(String text, XWikiContext context)
    {
        return getRenderedContent(text, Syntax.XWIKI_1_0.toIdString(), context);
    }

    @Deprecated
    public String XWikiDocument.displaySearch(PropertyClass pclass, String prefix, XWikiCriteria criteria, XWikiContext context)
    {
        return (pclass == null) ? "" : pclass.displaySearch(pclass.getName(), prefix, criteria, context);
    }

    /**
     * @param context the XWiki context used to get access to the com.xpn.xwiki.render.XWikiRenderingEngine object
     * @return the document title. If a title has not been provided, look for a section title in the document's content
     *         and if not found return the page name. The returned title is also interpreted which means it's allowed to
     *         use Velocity, Groovy, etc syntax within a title.
     * @deprecated use {@link #getRenderedTitle(Syntax, XWikiContext)} instead
     */
    @Deprecated
    public String XWikiDocument.getDisplayTitle(XWikiContext context)
    {
        return getRenderedTitle(Syntax.XHTML_1_0, context);
    }

    /**
     * @deprecated since 2.2M1, use {@link #getXClass()} instead
     */
    @Deprecated
    public BaseClass XWikiDocument.getxWikiClass()
    {
        return getXClass();
    }

    /**
     * @deprecated since 2.2M2 use {@link #addXObjectFromRequest(XWikiContext)}
     */
    @Deprecated
    public BaseObject XWikiDocument.addObjectFromRequest(XWikiContext context) throws XWikiException
    {
        return addXObjectFromRequest(context);
    }

    /**
     * @deprecated since 2.2M2 use {@link #setXObjectsToRemove(List)} instead
     */
    @Deprecated
    public void XWikiDocument.setObjectsToRemove(ArrayList<BaseObject> objectsToRemove)
    {
        setXObjectsToRemove(objectsToRemove);
    }

    /**
     * @deprecated since 2.2M1, use {@link #setXClass(BaseClass)} instead
     */
    @Deprecated
    public void XWikiDocument.setxWikiClass(BaseClass xwikiClass)
    {
        setXClass(xwikiClass);
    }

    /**
     * @deprecated since 2.2M1 use {@link #getXObjects()} instead. Warning: if you used to modify the returned Map note
     *             that since 2.2M1 this will no longer work and you'll need to call the setXObject methods instead (or
     *             setxWikiObjects()). Obviously the best is to move to the new API.
     */
    @Deprecated
    public Map<String, Vector<BaseObject>> XWikiDocument.getxWikiObjects()
    {
        // Use a liked hash map to ensure we keep the order stored from the internal objects map.
        Map<String, Vector<BaseObject>> objects = new LinkedHashMap<String, Vector<BaseObject>>();

        for (Map.Entry<DocumentReference, List<BaseObject>> entry : getXObjects().entrySet()) {
            objects.put(this.compactWikiEntityReferenceSerializer.serialize(entry.getKey()), new Vector<BaseObject>(
                entry.getValue()));
        }

        return objects;
    }

    /**
     * @deprecated since 2.2M1 use {@link #setXObjects(Map)} instead
     */
    @Deprecated
    public void XWikiDocument.setxWikiObjects(Map<String, Vector<BaseObject>> objects)
    {
        // Use a liked hash map to ensure we keep the order stored from the internal objects map.
        Map<DocumentReference, List<BaseObject>> newObjects = new LinkedHashMap<DocumentReference, List<BaseObject>>();

        for (Map.Entry<String, Vector<BaseObject>> entry : objects.entrySet()) {
            newObjects.put(resolveClassReference(entry.getKey()), new ArrayList<BaseObject>(entry.getValue()));
        }

        setXObjects(newObjects);
    }

    /**
     * @deprecated since 2.2M1 use {@link #getXClasses(XWikiContext)} instead
     */
    @Deprecated
    public List<BaseClass> XWikiDocument.getxWikiClasses(XWikiContext context)
    {
        return getXClasses(context);
    }

    /**
     * @deprecated since 2.2M1 use {@link #setXObjects(DocumentReference, List)} instead
     */
    @Deprecated
    public void XWikiDocument.setObjects(String className, Vector<BaseObject> objects)
    {
        setXObjects(resolveClassReference(className), new ArrayList<BaseObject>(objects));
    }

    /**
     * @deprecated since 3.2M3, use {@link #getRenderedTitle(Syntax, XWikiContext)} instead
     */
    @Deprecated
    public String XWikiDocument.extractTitle()
    {
        String title = "";

        try {
            if (is10Syntax()) {
                title = extractTitle10();
            } else {
                List<HeaderBlock> blocks =
                    getXDOM().getBlocks(new ClassBlockMatcher(HeaderBlock.class), Block.Axes.DESCENDANT);
                if (!blocks.isEmpty()) {
                    HeaderBlock header = blocks.get(0);
                    if (header.getLevel().compareTo(HeaderLevel.LEVEL2) <= 0) {
                        XDOM headerXDOM = new XDOM(Collections.<Block> singletonList(header));

                        // transform
                        TransformationContext context = new TransformationContext(headerXDOM, getSyntax());
                        Utils.getComponent(TransformationManager.class).performTransformations(headerXDOM, context);

                        // render
                        Block headerBlock = headerXDOM.getChildren().get(0);
                        if (headerBlock instanceof HeaderBlock) {
                            title = renderXDOM(new XDOM(headerBlock.getChildren()), Syntax.XHTML_1_0);
                        }
                    }
                }
            }
        } catch (Exception e) {
            // Don't stop when there's a problem rendering the title.
        }

        return title;
    }

    /**
     * Regex for finding the first level 1 or 2 heading in the document title, to be used as the document title.
     *
     * @deprecated since 3.2M3
     **/
    @Deprecated
    private static final Pattern HEADING_PATTERN_10 = Pattern.compile("^\\s*+1(?:\\.1)?\\s++(.++)$", Pattern.MULTILINE);

    /**
     * @return the first level 1 or level 1.1 title text in the document's content or "" if none are found
     * @deprecated since 3.2M3
     */
    @Deprecated
    private String XWikiDocument.extractTitle10()
    {
        String content = getContent();
        Matcher m = HEADING_PATTERN_10.matcher(content);
        if (m.find()) {
            return m.group(1).trim();
        }

        return "";
    }

    /**
     * Convert a {@link Document} into an XML string. You should prefer
     * {@link #toXML(OutputStream, boolean, boolean, boolean, boolean, XWikiContext)} or
     * {@link #toXML(com.xpn.xwiki.internal.xml.XMLWriter, boolean, boolean, boolean, boolean, XWikiContext)} when
     * possible to avoid memory load.
     *
     * @param doc the {@link Document} to convert to a String
     * @param context current XWikiContext
     * @return an XML representation of the {@link Document}
     * @deprecated this method has nothing to do here and is apparently unused
     */
    @Deprecated
    public String XWikiDocument.toXML(Document doc, XWikiContext context)
    {
        String encoding = context.getWiki().getEncoding();

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            XMLWriter wr = new XMLWriter(os, new OutputFormat("", true, encoding));
            wr.write(doc);
            return os.toString(encoding);
        } catch (IOException e) {
            LOGGER.error("Exception while doc.toXML", e);
            return "";
        }
    }

    /**
     * @deprecated since 2.2M1 use {@link #cloneXObjects(XWikiDocument)} instead
     */
    @Deprecated
    public void XWikiDocument.clonexWikiObjects(XWikiDocument templatedoc)
    {
        cloneXObjects(templatedoc);
    }

    /**
     * @deprecated since 5.2M1 use {@link #removeAttachment(XWikiAttachment)} instead
     */
    @Deprecated
    public void XWikiDocument.deleteAttachment(XWikiAttachment attachment, XWikiContext context) throws XWikiException
    {
        deleteAttachment(attachment, true, context);
    }

    /**
     * @deprecated since 5.2M1 use {@link #removeAttachment(XWikiAttachment)} instead
     */
    @Deprecated
    public void XWikiDocument.deleteAttachment(XWikiAttachment attachment, boolean toRecycleBin, XWikiContext context)
        throws XWikiException
    {
        deleteAttachment(attachment, true, toRecycleBin, context);
    }

    /**
     * @deprecated since 5.2M1 use {@link #removeAttachment(XWikiAttachment)} instead
     */
    @Deprecated
    private void XWikiDocument.deleteAttachment(XWikiAttachment attachment, boolean saveDocument, boolean toRecycleBin,
        XWikiContext context) throws XWikiException
    {
        removeAttachment(attachment, toRecycleBin);

        if (saveDocument) {
            // Save the document
            context.getWiki().saveDocument(this, "Deleted attachment [" + attachment.getFilename() + "]", context);
        }
    }

    /**
     * Convert a full document reference into the proper relative document reference (wiki part is removed if it's the
     * same as document wiki) to store as parent.
     *
     * @deprecated since 2.2.3 use {@link #setParentReference(org.xwiki.model.reference.EntityReference)} instead
     */
    @Deprecated
    public void XWikiDocument.setParentReference(DocumentReference parentReference)
    {
        if (parentReference != null) {
            setParent(serializeReference(parentReference, this.compactWikiEntityReferenceSerializer,
                getDocumentReference()));
        } else {
            setParentReference((EntityReference) null);
        }
    }
}

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This 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, or (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package com.xpn.xwiki.doc;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.rendering.block.Block;
import org.xwiki.rendering.block.HeaderBlock;
import org.xwiki.rendering.block.XDOM;
import org.xwiki.rendering.block.match.ClassBlockMatcher;
import org.xwiki.rendering.listener.HeaderLevel;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.rendering.transformation.TransformationContext;
import org.xwiki.rendering.transformation.TransformationManager;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.api.DocumentSection;
import com.xpn.xwiki.internal.xml.XMLWriter;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.objects.classes.BaseClass;
import com.xpn.xwiki.objects.classes.PropertyClass;
import com.xpn.xwiki.plugin.query.XWikiCriteria;
import com.xpn.xwiki.web.Utils;

/**
 * Add a backward compatibility layer to the {@link com.xpn.xwiki.doc.XWikiDocument} class.
 *
 * @version $Id$
 */
privileged public aspect XWikiDocumentCompatibilityAspect
{
    /**
     * @deprecated since 3.0M3 use {@code Syntax.XWIKI_1_0} instead
     */
    @Deprecated
    public static final String XWikiDocument.XWIKI10_SYNTAXID = Syntax.XWIKI_1_0.toIdString();

    /**
     * @deprecated since 3.0M3 use {@code Syntax.XWIKI_2_0} instead
     */
    @Deprecated
    public static final String XWikiDocument.XWIKI20_SYNTAXID = Syntax.XWIKI_2_0.toIdString();

    /**
     * @deprecated use setStringListValue or setDBStringListProperty
     */
    @Deprecated
    public void XWikiDocument.setListValue(String className, String fieldName, List value)
    {
        BaseObject bobject = getObject(className);
        if (bobject == null) {
            bobject = new BaseObject();
            addObject(className, bobject);
        }
        bobject.setName(getFullName());
        bobject.setClassName(className);
        bobject.setListValue(fieldName, value);
        setContentDirty(true);
    }

    /**
     * This method to split section according to title.
     *
     * @return the sections in the current document
     * @throws XWikiException
     * @deprecated use {@link #getSections()} instead, since 1.6M1
     */
    @Deprecated
    public List<DocumentSection> XWikiDocument.getSplitSectionsAccordingToTitle() throws XWikiException
    {
        return getSections();
    }

    /**
     * @deprecated use {@link #getUniqueLinkedPages(XWikiContext)}
     */
    @Deprecated
    public List<String> XWikiDocument.getLinkedPages(XWikiContext context)
    {
        return new ArrayList<String>(getUniqueLinkedPages(context));
    }

    /**
     * @deprecated use {@link #getUniqueWikiLinkedPages(XWikiContext)} instead
     */
    @Deprecated
    public List<XWikiLink> XWikiDocument.getLinks(XWikiContext context) throws XWikiException
    {
        return getWikiLinkedPages(context);
    }

    /**
     * @deprecated use {@link #getUniqueWikiLinkedPages(XWikiContext)} instead
     */
    @Deprecated
    public List<XWikiLink> XWikiDocument.getWikiLinkedPages(XWikiContext context) throws XWikiException
    {
        return new ArrayList<XWikiLink>(getUniqueWikiLinkedPages(context));
    }

    /**
     * @deprecated use {@link #getBackLinkedPages(XWikiContext)} instead
     */
    @Deprecated
    public List<String> XWikiDocument.getBacklinks(XWikiContext context) throws XWikiException
    {
        return getBackLinkedPages(context);
    }

    /**
     * @param text the text to render
     * @param context the XWiki Context object
     * @return the given text rendered in the context of this document
     * @deprecated since 1.6M1 use {@link #getRenderedContent(String, String, com.xpn.xwiki.XWikiContext)}
     */
    @Deprecated
    public String XWikiDocument.getRenderedContent(String text, XWikiContext context)
    {
        return getRenderedContent(text, Syntax.XWIKI_1_0.toIdString(), context);
    }

    @Deprecated
    public String XWikiDocument.displaySearch(PropertyClass pclass, String prefix, XWikiCriteria criteria, XWikiContext context)
    {
        return (pclass == null) ? "" : pclass.displaySearch(pclass.getName(), prefix, criteria, context);
    }

    /**
     * @param context the XWiki context used to get access to the com.xpn.xwiki.render.XWikiRenderingEngine object
     * @return the document title. If a title has not been provided, look for a section title in the document's content
     *         and if not found return the page name. The returned title is also interpreted which means it's allowed to
     *         use Velocity, Groovy, etc syntax within a title.
     * @deprecated use {@link #getRenderedTitle(Syntax, XWikiContext)} instead
     */
    @Deprecated
    public String XWikiDocument.getDisplayTitle(XWikiContext context)
    {
        return getRenderedTitle(Syntax.XHTML_1_0, context);
    }

    /**
     * @deprecated since 2.2M1, use {@link #getXClass()} instead
     */
    @Deprecated
    public BaseClass XWikiDocument.getxWikiClass()
    {
        return getXClass();
    }

    /**
     * @deprecated since 2.2M2 use {@link #addXObjectFromRequest(XWikiContext)}
     */
    @Deprecated
    public BaseObject XWikiDocument.addObjectFromRequest(XWikiContext context) throws XWikiException
    {
        return addXObjectFromRequest(context);
    }

    /**
     * @deprecated since 2.2M2 use {@link #setXObjectsToRemove(List)} instead
     */
    @Deprecated
    public void XWikiDocument.setObjectsToRemove(ArrayList<BaseObject> objectsToRemove)
    {
        setXObjectsToRemove(objectsToRemove);
    }

    /**
     * @deprecated since 2.2M1, use {@link #setXClass(BaseClass)} instead
     */
    @Deprecated
    public void XWikiDocument.setxWikiClass(BaseClass xwikiClass)
    {
        setXClass(xwikiClass);
    }

    /**
     * @deprecated since 2.2M1 use {@link #getXObjects()} instead. Warning: if you used to modify the returned Map note
     *             that since 2.2M1 this will no longer work and you'll need to call the setXObject methods instead (or
     *             setxWikiObjects()). Obviously the best is to move to the new API.
     */
    @Deprecated
    public Map<String, Vector<BaseObject>> XWikiDocument.getxWikiObjects()
    {
        // Use a liked hash map to ensure we keep the order stored from the internal objects map.
        Map<String, Vector<BaseObject>> objects = new LinkedHashMap<String, Vector<BaseObject>>();

        for (Map.Entry<DocumentReference, List<BaseObject>> entry : getXObjects().entrySet()) {
            objects.put(this.compactWikiEntityReferenceSerializer.serialize(entry.getKey()), new Vector<BaseObject>(
                entry.getValue()));
        }

        return objects;
    }

    /**
     * @deprecated since 2.2M1 use {@link #setXObjects(Map)} instead
     */
    @Deprecated
    public void XWikiDocument.setxWikiObjects(Map<String, Vector<BaseObject>> objects)
    {
        // Use a liked hash map to ensure we keep the order stored from the internal objects map.
        Map<DocumentReference, List<BaseObject>> newObjects = new LinkedHashMap<DocumentReference, List<BaseObject>>();

        for (Map.Entry<String, Vector<BaseObject>> entry : objects.entrySet()) {
            newObjects.put(resolveClassReference(entry.getKey()), new ArrayList<BaseObject>(entry.getValue()));
        }

        setXObjects(newObjects);
    }

    /**
     * @deprecated since 2.2M1 use {@link #getXClasses(XWikiContext)} instead
     */
    @Deprecated
    public List<BaseClass> XWikiDocument.getxWikiClasses(XWikiContext context)
    {
        return getXClasses(context);
    }

    /**
     * @deprecated since 2.2M1 use {@link #setXObjects(DocumentReference, List)} instead
     */
    @Deprecated
    public void XWikiDocument.setObjects(String className, Vector<BaseObject> objects)
    {
        setXObjects(resolveClassReference(className), new ArrayList<BaseObject>(objects));
    }

    /**
     * @deprecated since 3.2M3, use {@link #getRenderedTitle(Syntax, XWikiContext)} instead
     */
    @Deprecated
    public String XWikiDocument.extractTitle()
    {
        String title = "";

        try {
            if (is10Syntax()) {
                title = extractTitle10();
            } else {
                List<HeaderBlock> blocks =
                    getXDOM().getBlocks(new ClassBlockMatcher(HeaderBlock.class), Block.Axes.DESCENDANT);
                if (!blocks.isEmpty()) {
                    HeaderBlock header = blocks.get(0);
                    if (header.getLevel().compareTo(HeaderLevel.LEVEL2) <= 0) {
                        XDOM headerXDOM = new XDOM(Collections.<Block> singletonList(header));

                        // transform
                        TransformationContext context = new TransformationContext(headerXDOM, getSyntax());
                        Utils.getComponent(TransformationManager.class).performTransformations(headerXDOM, context);

                        // render
                        Block headerBlock = headerXDOM.getChildren().get(0);
                        if (headerBlock instanceof HeaderBlock) {
                            title = renderXDOM(new XDOM(headerBlock.getChildren()), Syntax.XHTML_1_0);
                        }
                    }
                }
            }
        } catch (Exception e) {
            // Don't stop when there's a problem rendering the title.
        }

        return title;
    }

    /**
     * Regex for finding the first level 1 or 2 heading in the document title, to be used as the document title.
     *
     * @deprecated since 3.2M3
     **/
    @Deprecated
    private static final Pattern HEADING_PATTERN_10 = Pattern.compile("^\\s*+1(?:\\.1)?\\s++(.++)$", Pattern.MULTILINE);

    /**
     * @return the first level 1 or level 1.1 title text in the document's content or "" if none are found
     * @deprecated since 3.2M3
     */
    @Deprecated
    private String XWikiDocument.extractTitle10()
    {
        String content = getContent();
        Matcher m = HEADING_PATTERN_10.matcher(content);
        if (m.find()) {
            return m.group(1).trim();
        }

        return "";
    }

    /**
     * Convert a {@link Document} into an XML string. You should prefer
     * {@link #toXML(OutputStream, boolean, boolean, boolean, boolean, XWikiContext)} or
     * {@link #toXML(com.xpn.xwiki.internal.xml.XMLWriter, boolean, boolean, boolean, boolean, XWikiContext)} when
     * possible to avoid memory load.
     *
     * @param doc the {@link Document} to convert to a String
     * @param context current XWikiContext
     * @return an XML representation of the {@link Document}
     * @deprecated this method has nothing to do here and is apparently unused
     */
    @Deprecated
    public String XWikiDocument.toXML(Document doc, XWikiContext context)
    {
        String encoding = context.getWiki().getEncoding();

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            XMLWriter wr = new XMLWriter(os, new OutputFormat("", true, encoding));
            wr.write(doc);
            return os.toString(encoding);
        } catch (IOException e) {
            LOGGER.error("Exception while doc.toXML", e);
            return "";
        }
    }

    /**
     * @deprecated since 2.2M1 use {@link #cloneXObjects(XWikiDocument)} instead
     */
    @Deprecated
    public void XWikiDocument.clonexWikiObjects(XWikiDocument templatedoc)
    {
        cloneXObjects(templatedoc);
    }

    /**
     * @deprecated since 5.2M1 use {@link #removeAttachment(XWikiAttachment)} instead
     */
    @Deprecated
    public void XWikiDocument.deleteAttachment(XWikiAttachment attachment, XWikiContext context) throws XWikiException
    {
        deleteAttachment(attachment, true, context);
    }

    /**
     * @deprecated since 5.2M1 use {@link #removeAttachment(XWikiAttachment)} instead
     */
    @Deprecated
    public void XWikiDocument.deleteAttachment(XWikiAttachment attachment, boolean toRecycleBin, XWikiContext context)
        throws XWikiException
    {
        deleteAttachment(attachment, true, toRecycleBin, context);
    }

    /**
     * @deprecated since 5.2M1 use {@link #removeAttachment(XWikiAttachment)} instead
     */
    @Deprecated
    private void XWikiDocument.deleteAttachment(XWikiAttachment attachment, boolean saveDocument, boolean toRecycleBin,
        XWikiContext context) throws XWikiException
    {
        removeAttachment(attachment, toRecycleBin);

        if (saveDocument) {
            // Save the document
            context.getWiki().saveDocument(this, "Deleted attachment [" + attachment.getFilename() + "]", context);
        }
    }

    /**
     * Convert a full document reference into the proper relative document reference (wiki part is removed if it's the
     * same as document wiki) to store as parent.
     *
     * @deprecated since 2.2.3 use {@link #setParentReference(org.xwiki.model.reference.EntityReference)} instead
     */
    @Deprecated
    public void XWikiDocument.setParentReference(DocumentReference parentReference)
    {
        if (parentReference != null) {
            setParent(serializeReference(parentReference, this.compactWikiEntityReferenceSerializer,
                getDocumentReference()));
        } else {
            setParentReference((EntityReference) null);
        }
    }
}


made AbstractPalavaAspect deprecated

made AbstractPalavaAspect deprecated

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * 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 de.cosmocode.palava.core.aop;

import java.util.Collections;

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

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Stage;

/**
 * Abstract aspect which intercepts {@link Guice#createInjector(..)} calls
 * to get hands on the injector.
 *
 * @deprecated use {@link PalavaAspect}
 * @since 2.0
 * @author Willi Schoenborn
 */
@Deprecated
public abstract aspect AbstractPalavaAspect {

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

    private final Module module = new Module() {

        @Override
        public void configure(Binder binder) {
            final AbstractPalavaAspect self = AbstractPalavaAspect.this;
            LOG.trace("Injecting members on {}", self);
            Preconditions.checkState(!alreadyInjected, "Members have been already injected on %s", self);
            binder.requestInjection(self);
            alreadyInjected = true;
        }

    };

    private boolean alreadyInjected;

    private Module[] append(Module[] modules) {
        final Module[] array = new Module[modules.length + 1];
        System.arraycopy(modules, 0, array, 0, modules.length);
        array[modules.length] = module;
        return array;
    }

    private Iterable<Module> append(Iterable<? extends Module> modules) {
        return Iterables.concat(modules, Collections.singleton(module));
    }

    @SuppressAjWarnings("adviceDidNotMatch")
    Injector around(Module[] modules): call(Injector Guice.createInjector(Module...)) && args(modules) {
        return proceed(append(modules));
    }

    @SuppressAjWarnings("adviceDidNotMatch")
    Injector around(Iterable<? extends Module> modules):
        call(Injector Guice.createInjector(Iterable<? extends Module>)) && args(modules) {
        return proceed(append(modules));
    }

    @SuppressAjWarnings("adviceDidNotMatch")
    Injector around(Stage stage, Module[] modules):
        call(Injector Guice.createInjector(Stage, Module...)) && args(stage, modules) {
        return proceed(stage, append(modules));
    }

    @SuppressAjWarnings("adviceDidNotMatch")
    Injector around(Stage stage, Iterable<? extends Module> modules):
        call(Injector Guice.createInjector(Stage, Iterable<? extends Module>)) && args(stage, modules) {
        return proceed(stage, append(modules));
    }

    protected final void checkState() {
        Preconditions.checkState(alreadyInjected, "Members have not been injected on %s", this);
    }

}

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * 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 de.cosmocode.palava.core.aop;

import java.util.Collections;

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

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Stage;

/**
 * Abstract aspect which intercepts {@link Guice#createInjector(..)} calls
 * to get hands on the injector.
 *
 * @since 2.0
 * @author Willi Schoenborn
 */
public abstract aspect AbstractPalavaAspect {

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

    private final Module module = new Module() {

        @Override
        public void configure(Binder binder) {
            final AbstractPalavaAspect self = AbstractPalavaAspect.this;
            LOG.trace("Injecting members on {}", self);
            Preconditions.checkState(!alreadyInjected, "Members have been already injected on %s", self);
            binder.requestInjection(self);
            alreadyInjected = true;
        }

    };

    private boolean alreadyInjected;

    private Module[] append(Module[] modules) {
        final Module[] array = new Module[modules.length + 1];
        System.arraycopy(modules, 0, array, 0, modules.length);
        array[modules.length] = module;
        return array;
    }

    private Iterable<Module> append(Iterable<? extends Module> modules) {
        return Iterables.concat(modules, Collections.singleton(module));
    }

    @SuppressAjWarnings("adviceDidNotMatch")
    Injector around(Module[] modules): call(Injector Guice.createInjector(Module...)) && args(modules) {
        return proceed(append(modules));
    }

    @SuppressAjWarnings("adviceDidNotMatch")
    Injector around(Iterable<? extends Module> modules):
        call(Injector Guice.createInjector(Iterable<? extends Module>)) && args(modules) {
        return proceed(append(modules));
    }

    @SuppressAjWarnings("adviceDidNotMatch")
    Injector around(Stage stage, Module[] modules):
        call(Injector Guice.createInjector(Stage, Module...)) && args(stage, modules) {
        return proceed(stage, append(modules));
    }

    @SuppressAjWarnings("adviceDidNotMatch")
    Injector around(Stage stage, Iterable<? extends Module> modules):
        call(Injector Guice.createInjector(Stage, Iterable<? extends Module>)) && args(stage, modules) {
        return proceed(stage, append(modules));
    }

    protected final void checkState() {
        Preconditions.checkState(alreadyInjected, "Members have not been injected on %s", this);
    }

}


Fixed #3034. Review by community.

Fixed #3034. Review by community.

git-svn-id: f4ecfe233223879a4a16cd7937f11b5152963d8e@20893 5e8d7ff9-d8ef-0310-90f0-a4852d11357a

/*
 * Copyright 2005-2010 LAMP/EPFL
 */
// $Id$

package scala.tools.eclipse.contribution.weaving.jdt.core;

import org.eclipse.jface.viewers.IStructuredSelection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
import org.eclipse.jdt.internal.ui.refactoring.actions.RenameResourceAction;
import org.eclipse.jface.viewers.IStructuredSelection;

import scala.tools.eclipse.contribution.weaving.jdt.IScalaElement;

@SuppressWarnings("restriction")
public aspect RefactoringAvailabilityAspect {
  pointcut isAvailable(Object arg) :
    execution(static boolean RefactoringAvailabilityTester.is*Available(!IResource)) &&
    args(arg);

  pointcut isAvailable2(IResource[] arg1, IJavaElement[] arg2) :
    execution(static boolean RefactoringAvailabilityTester.is*Available(IResource[], IJavaElement[])) &&
    args(arg1, arg2);

  pointcut getResources(Object[] elements) :
    execution(static IResource[] RefactoringAvailabilityTester.getResources(Object[])) &&
    args(elements);

  pointcut getJavaElements(Object[] elements) :
    execution(static IJavaElement[] RefactoringAvailabilityTester.getJavaElements(Object[])) &&
    args(elements);

  pointcut getResources2(List elements) :
    execution(static IResource[] ReorgUtils.getResources(List)) &&
    args(elements);

  pointcut getJavaElements2(List elements) :
    execution(static IJavaElement[] ReorgUtils.getJavaElements(List)) &&
    args(elements);

  pointcut getResource(IStructuredSelection selection) :
    execution(static IResource RenameResourceAction.getResource(IStructuredSelection)) &&
    args(selection);

  boolean around(Object arg) :
    isAvailable(arg) {
    if (arg instanceof IScalaElement)
      return false;
    else if (arg instanceof IStructuredSelection)
      for(Iterator i = ((IStructuredSelection)arg).iterator(); i.hasNext();)
        if (i.next() instanceof IScalaElement)
          return false;

    return proceed(arg);
  }

  boolean around(IResource[] resources, IJavaElement[] elements) :
    isAvailable2(resources, elements) {
    if (elements == null || elements.length == 0)
      return proceed(resources, elements);

    int numElements = elements.length;
    boolean hasScalaElement = false;
    for (int i = 0; i < numElements; ++i)
      if (elements[i] instanceof IScalaElement) {
        hasScalaElement = true;
        break;
      }

    if (!hasScalaElement)
      return proceed(resources, elements);

    List newElements = new ArrayList();

    List newResources = new ArrayList();
    if (resources != null)
      newResources.addAll(Arrays.asList(resources));

    for (int i = 0; i < numElements; ++i) {
      IJavaElement elem = elements[i];
      if (elem instanceof IScalaElement) {
        try {
          IResource resource = elem.getCorrespondingResource();
          if (resource != null)
            newResources.add(resource);
        } catch (JavaModelException ex) {
          // Deliberately ignored
        }
      } else
        newElements.add(elem);
    }

    return proceed(
      (IResource[])newResources.toArray(new IResource[newResources.size()]),
      (IJavaElement[])newElements.toArray(new IJavaElement[newElements.size()]));
  }

  IResource[] around(Object[] elements) :
    getResources(elements) {
    List result= new ArrayList();
    for (int index= 0; index < elements.length; index++) {
      Object elem = elements[index];
      if (elem instanceof IResource)
        result.add(elem);
      else if (elem instanceof IScalaElement) {
        try {
          IResource resource = ((IJavaElement)elem).getCorrespondingResource();
          if (resource != null)
            result.add(resource);
        } catch (JavaModelException ex) {
          // Deliberately ignored
        }
      }
    }
    return (IResource[]) result.toArray(new IResource[result.size()]);
  }

  IJavaElement[] around(Object[] elements) :
    getJavaElements(elements) {
    List result= new ArrayList();
    for (int index= 0; index < elements.length; index++) {
      Object elem = elements[index];
      if ((elem instanceof IJavaElement) && !(elem instanceof IScalaElement))
        result.add(elem);
    }
    return (IJavaElement[]) result.toArray(new IJavaElement[result.size()]);
  }

  IResource[] around(List elements) :
    getResources2(elements) {
    List result= new ArrayList();
    for (Iterator i = elements.iterator(); i.hasNext(); ) {
      Object elem = i.next();
      if (elem instanceof IResource)
        result.add(elem);
      else if (elem instanceof IScalaElement) {
        try {
          IResource resource = ((IJavaElement)elem).getCorrespondingResource();
          if (resource != null)
            result.add(resource);
        } catch (JavaModelException ex) {
          // Deliberately ignored
        }
      }
    }
    return (IResource[]) result.toArray(new IResource[result.size()]);
  }

  IJavaElement[] around(List elements) :
    getJavaElements2(elements) {
    List result= new ArrayList();
    for (Iterator i = elements.iterator(); i.hasNext(); ) {
      Object elem = i.next();
      if ((elem instanceof IJavaElement) && !(elem instanceof IScalaElement))
        result.add(elem);
    }
    return (IJavaElement[]) result.toArray(new IJavaElement[result.size()]);
  }

  IResource around(IStructuredSelection selection) :
    getResource(selection) {
    if (selection.size() != 1)
      return null;
    Object first= selection.getFirstElement();
    if (first instanceof IScalaElement) {
      try {
        return ((IJavaElement)first).getCorrespondingResource();
      } catch (JavaModelException ex) {
        return null;
      }
    }
    else if (!(first instanceof IResource))
      return null;
    return (IResource)first;
  }
}

/*
 * Copyright 2005-2010 LAMP/EPFL
 */
// $Id$

package scala.tools.eclipse.contribution.weaving.jdt.core;

import org.eclipse.jface.viewers.IStructuredSelection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
import org.eclipse.jdt.internal.ui.refactoring.actions.RenameResourceAction;
import org.eclipse.jface.viewers.IStructuredSelection;

import scala.tools.eclipse.contribution.weaving.jdt.IScalaElement;

@SuppressWarnings("restriction")
public aspect RefactoringAvailabilityAspect {
  pointcut isAvailable(Object arg) :
    execution(static boolean RefactoringAvailabilityTester.is*Available(!IResource)) &&
    args(arg);

  pointcut isAvailable2(IResource[] arg1, IJavaElement[] arg2) :
    execution(static boolean RefactoringAvailabilityTester.is*Available(IResource[], IJavaElement[])) &&
    args(arg1, arg2);

  pointcut getResources(Object[] elements) :
    execution(static IResource[] RefactoringAvailabilityTester.getResources(Object[])) &&
    args(elements);

  pointcut getJavaElements(Object[] elements) :
    execution(static IJavaElement[] RefactoringAvailabilityTester.getJavaElements(Object[])) &&
    args(elements);

  pointcut getResources2(List elements) :
    execution(static IResource[] ReorgUtils.getResources(List)) &&
    args(elements);

  pointcut getJavaElements2(List elements) :
    execution(static IJavaElement[] ReorgUtils.getJavaElements(List)) &&
    args(elements);

  pointcut getResource(IStructuredSelection selection) :
    execution(static IResource RenameResourceAction.getResource(IStructuredSelection)) &&
    args(selection);

  boolean around(Object arg) :
    isAvailable(arg) {
    if (arg instanceof IScalaElement)
      return false;
    else if (arg instanceof IStructuredSelection)
      for(Iterator i = ((IStructuredSelection)arg).iterator(); i.hasNext();)
        if (i.next() instanceof IScalaElement)
          return false;

    return proceed(arg);
  }

  boolean around(IResource[] resources, IJavaElement[] elements) :
    isAvailable2(resources, elements) {
    if (elements == null || elements.length == 0)
      return proceed(resources, elements);
    else if (resources == null || resources.length == 0) {
      if (elements == null || elements.length == 0)
        return false;

      int limit = elements.length;
      IResource[] newResources = new IResource[limit];
      for (int i = 0; i < limit; ++i) {
        IJavaElement elem = elements[i];
        if (elem instanceof IResource)
          newResources[i] = (IResource)elem;
        else
          return false;
      }
      return proceed(newResources, null);
    }
    else {
      int limit = elements.length;
      IResource[] newResources = new IResource[resources.length+limit];
      System.arraycopy(resources, 0, newResources, 0, resources.length);
      for (int i = 0, j = resources.length; i < limit; ++i, ++j) {
        IJavaElement elem = elements[i];
        if (elem instanceof IResource)
          newResources[j] = (IResource)elem;
        else
          return false;
      }
      return proceed(newResources, null);
    }
  }

  IResource[] around(Object[] elements) :
    getResources(elements) {
    List result= new ArrayList();
    for (int index= 0; index < elements.length; index++) {
      Object elem = elements[index];
      if (elem instanceof IResource)
        result.add(elem);
      else if (elem instanceof IScalaElement) {
        try {
          IResource resource = ((IJavaElement)elem).getCorrespondingResource();
          if (resource != null)
            result.add(resource);
        } catch (JavaModelException ex) {
          // Deliberately ignored
        }
      }
    }
    return (IResource[]) result.toArray(new IResource[result.size()]);
  }

  IJavaElement[] around(Object[] elements) :
    getJavaElements(elements) {
    List result= new ArrayList();
    for (int index= 0; index < elements.length; index++) {
      Object elem = elements[index];
      if ((elem instanceof IJavaElement) && !(elem instanceof IScalaElement))
        result.add(elem);
    }
    return (IJavaElement[]) result.toArray(new IJavaElement[result.size()]);
  }

  IResource[] around(List elements) :
    getResources2(elements) {
    List result= new ArrayList();
    for (Iterator i = elements.iterator(); i.hasNext(); ) {
      Object elem = i.next();
      if (elem instanceof IResource)
        result.add(elem);
      else if (elem instanceof IScalaElement) {
        try {
          IResource resource = ((IJavaElement)elem).getCorrespondingResource();
          if (resource != null)
            result.add(resource);
        } catch (JavaModelException ex) {
          // Deliberately ignored
        }
      }
    }
    return (IResource[]) result.toArray(new IResource[result.size()]);
  }

  IJavaElement[] around(List elements) :
    getJavaElements2(elements) {
    List result= new ArrayList();
    for (Iterator i = elements.iterator(); i.hasNext(); ) {
      Object elem = i.next();
      if ((elem instanceof IJavaElement) && !(elem instanceof IScalaElement))
        result.add(elem);
    }
    return (IJavaElement[]) result.toArray(new IJavaElement[result.size()]);
  }

  IResource around(IStructuredSelection selection) :
    getResource(selection) {
    if (selection.size() != 1)
      return null;
    Object first= selection.getFirstElement();
    if (first instanceof IScalaElement) {
      try {
        return ((IJavaElement)first).getCorrespondingResource();
      } catch (JavaModelException ex) {
        return null;
      }
    }
    else if (!(first instanceof IResource))
      return null;
    return (IResource)first;
  }
}