All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aspectj.ajdt.internal.compiler.WeaverAdapter Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.aspectj.ajdt.internal.compiler;

import java.util.Iterator;
import java.util.Map;

import org.aspectj.asm.internal.CharOperation;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IProgressListener;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.aspectj.weaver.IClassFileProvider;
import org.aspectj.weaver.IUnwovenClassFile;
import org.aspectj.weaver.IWeaveRequestor;
import org.eclipse.core.runtime.OperationCanceledException;

/**
 * @author colyer This class provides the weaver with a source of class files to weave (via the iterator and IClassFileProvider
 *         interfaces). It receives results back from the weaver via the IWeaveRequestor interface.
 */
public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Iterator {

	private final AbstractCompilerAdapter compilerAdapter;
	private Iterator resultIterator;
	private int classFileIndex = 0;
	private InterimCompilationResult nowProcessing;
	private InterimCompilationResult lastReturnedResult;
	private final WeaverMessageHandler weaverMessageHandler;
	private final IProgressListener progressListener;
	private boolean finalPhase = false;
	private int localIteratorCounter;

	// Fields related to progress monitoring
	private int progressMaxTypes;
	private String progressPhasePrefix;
	private double fromPercent;
	private final double toPercent = 100.0;
	private int progressCompletionCount;

	public WeaverAdapter(AbstractCompilerAdapter forCompiler, WeaverMessageHandler weaverMessageHandler,
			IProgressListener progressListener) {
		this.compilerAdapter = forCompiler;
		this.weaverMessageHandler = weaverMessageHandler;
		this.progressListener = progressListener;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.aspectj.weaver.IClassFileProvider#getClassFileIterator()
	 */
	public Iterator getClassFileIterator() {
		classFileIndex = 0;
		localIteratorCounter = 0;
		nowProcessing = null;
		lastReturnedResult = null;
		resultIterator = compilerAdapter.getResultsPendingWeave().iterator();
		return this;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.aspectj.weaver.IClassFileProvider#getRequestor()
	 */
	public IWeaveRequestor getRequestor() {
		return this;
	}

	public boolean isApplyAtAspectJMungersOnly() {
		return false;
	}

	// Iteration
	// ================================================================

	/*
	 * (non-Javadoc)
	 *
	 * @see java.util.Iterator#hasNext()
	 */
	public boolean hasNext() {
		if (nowProcessing == null) {
			if (!resultIterator.hasNext())
				return false;
			nowProcessing = resultIterator.next();
			classFileIndex = 0;
		}
		while (nowProcessing.unwovenClassFiles().length == 0) {
			if (!resultIterator.hasNext())
				return false;
			nowProcessing = resultIterator.next();
		}
		if (classFileIndex < nowProcessing.unwovenClassFiles().length) {
			return true;
		} else {
			classFileIndex = 0;
			if (!resultIterator.hasNext())
				return false;
			nowProcessing = resultIterator.next();
			while (nowProcessing.unwovenClassFiles().length == 0) {
				if (!resultIterator.hasNext())
					return false;
				nowProcessing = resultIterator.next();
			}
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.util.Iterator#next()
	 */
	public Object next() {
		if (!hasNext())
			return null; // sets up indices correctly
		if (finalPhase) {
			if ((lastReturnedResult != null) && (lastReturnedResult != nowProcessing)) {
				// we're done with the lastReturnedResult
				finishedWith(lastReturnedResult);
			}
		}
		localIteratorCounter++;
		lastReturnedResult = nowProcessing;
		weaverMessageHandler.setCurrentResult(nowProcessing.result());
		// weaverMessageHandler.handleMessage(new Message("weaving " + nowProcessing.fileName(),IMessage.INFO, null, null));
		return nowProcessing.unwovenClassFiles()[classFileIndex++];
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.util.Iterator#remove()
	 */
	public void remove() {
		throw new UnsupportedOperationException();
	}

	// IWeaveRequestor
	// =====================================================================================

	// weave phases as indicated by bcelWeaver...
	public void processingReweavableState() {

		// progress reporting logic
		fromPercent = 50.0; // Assume weaving takes 50% of the progress bar...
		// recordProgress("processing reweavable state");
	}

	public void addingTypeMungers() {

		// progress reporting logic
		// At this point we have completed one iteration through all the classes/aspects
		// we'll be dealing with, so let us remember this max value for localIteratorCounter
		// (for accurate progress reporting)
		// recordProgress("adding type mungers");
		progressMaxTypes = localIteratorCounter;
	}

	public void weavingAspects() {

		// progress reporting logic
		progressPhasePrefix = "woven aspect ";
		progressCompletionCount = 0; // Start counting from *now*
	}

	public void weavingClasses() {
		finalPhase = true;

		// progress reporting logic
		progressPhasePrefix = "woven class ";
	}

	public void weaveCompleted() {
		if ((lastReturnedResult != null) && (!lastReturnedResult.result().hasBeenAccepted)) {
			finishedWith(lastReturnedResult);
		}
		lastReturnedResult = null;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.aspectj.weaver.IWeaveRequestor#acceptResult(org.aspectj.weaver.bcel.UnwovenClassFile)
	 */
	public void acceptResult(IUnwovenClassFile result) {
		char[] key = result.getClassNameAsChars();
		removeFromMap(lastReturnedResult.result().compiledTypes, key);
		AjClassFile ajcf = new AjClassFile(key, result.getBytes());
		lastReturnedResult.result().record(ajcf.fileName(), ajcf);
		if (!weaverMessageHandler.isIgnoring(IMessage.INFO) || progressListener != null) {
			StringBuilder msg = new StringBuilder();
			msg.append(progressPhasePrefix).append(result.getClassName()).append(" (from ").append(nowProcessing.fileName())
					.append(")");
			weaverMessageHandler.handleMessage(MessageUtil.info(msg.toString()));
			if (progressListener != null) {
				progressCompletionCount++;

				// Smoothly take progress from 'fromPercent' to 'toPercent'
				recordProgress(fromPercent + ((progressCompletionCount / (double) progressMaxTypes) * (toPercent - fromPercent)),
						msg.toString());
				// progressPhasePrefix+result.getClassName()+" (from "+nowProcessing.fileName()+")");

				if (progressListener.isCancelledRequested()) {
					throw new AbortCompilation(true, new OperationCanceledException("Weaving cancelled as requested"));
				}
			}
		}
	}

	// helpers...
	// =================================================================

	private void finishedWith(InterimCompilationResult result) {
		compilerAdapter.acceptResult(result.result());
	}

	private boolean removeFromMap(Map aMap, char[] key) {
		// jdt uses char[] as a key in the hashtable, which is not very useful as equality is based on being
		// the same array, not having the same content.
		// String skey = new String(key);
		// OPTIMIZE what is this code for?
		if (aMap.remove(key) != null) {
			return true;
		}
		char[] victim = null;
		for (Object o : aMap.keySet()) {
			char[] thisKey = (char[]) o;
			if (CharOperation.equals(thisKey, key)) {
				// if (skey.equals(new String(thisKey))) {
				victim = thisKey;
				break;
			}
		}
		if (victim != null) {
			aMap.remove(victim);
			return true;
		}
		return false;
	}

	private void recordProgress(double percentage, String message) {
		if (progressListener != null) {
			progressListener.setProgress(percentage / 100);
			progressListener.setText(message);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy