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

org.aspectj.ajdt.ajc.AjdtCommand Maven / Gradle / Ivy

There is a newer version: 1.9.22.1
Show newest version
/* *******************************************************************
 * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
 * 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:
 *     PARC     initial implementation
 * ******************************************************************/


package org.aspectj.ajdt.ajc;

import org.aspectj.ajdt.internal.core.builder.*;
import org.aspectj.bridge.*;
import org.aspectj.weaver.Dump;
import org.aspectj.org.eclipse.jdt.internal.core.builder.MissingSourceFileException;

/**
 * ICommand adapter for the AspectJ compiler.
 * Not thread-safe.
 */
public class AjdtCommand implements ICommand {

    /** Message String for any AbortException thrown from ICommand API's */
    public static final String ABORT_MESSAGE = "ABORT";

//    private boolean canRepeatCommand = true;

	AjBuildManager buildManager = null;
	String[] savedArgs = null;

	/**
     * Run AspectJ compiler, wrapping any exceptions thrown as
     * ABORT messages (containing ABORT_MESSAGE String).
     * @param args the String[] for the compiler
     * @param handler the IMessageHandler for any messages
	 * @see org.aspectj.bridge.ICommand#runCommand(String[], IMessageHandler)
     * @return false if handler has errors or the command failed
	 */
	public boolean runCommand(String[] args, IMessageHandler handler) {
		buildManager = new AjBuildManager(handler);
		savedArgs = new String[args.length];
        System.arraycopy(args, 0, savedArgs, 0, savedArgs.length);
        return doCommand(handler, false);
    }

    /**
     * Run AspectJ compiler, wrapping any exceptions thrown as
     * ABORT messages (containing ABORT_MESSAGE String).
     * @param handler the IMessageHandler for any messages
     * @see org.aspectj.bridge.ICommand#repeatCommand(IMessageHandler)
     * @return false if handler has errors or the command failed
     */
	public boolean repeatCommand(IMessageHandler handler) {
		if (null == buildManager) {
            MessageUtil.abort(handler, "repeatCommand called before runCommand");
            return false;
        }
        return doCommand(handler, true);
    }

    /**
     * Delegate of both runCommand and repeatCommand.
     * This invokes the argument parser each time
     * (even when repeating).
     * If the parser detects errors, this signals an
     * abort with the usage message and returns false.
     * @param handler the IMessageHandler sink for any messages
     * @param repeat if true, do incremental build, else do batch build
     * @return false if handler has any errors or command failed
     */
    protected boolean doCommand(IMessageHandler handler, boolean repeat) {
        try {
            if (handler instanceof IMessageHolder) {
                Dump.saveMessageHolder((IMessageHolder) handler);
            }
			// buildManager.setMessageHandler(handler);
            CountingMessageHandler counter = new CountingMessageHandler(handler);
            if (counter.hasErrors()) {
                return false;
            }
            // regenerate configuration b/c world might have changed (?)
            AjBuildConfig config = genBuildConfig(savedArgs, counter);
            if (!config.shouldProceed()) {
            	return true;
            }
            if (!config.hasSources()) {
                MessageUtil.error(counter, "no sources specified");
            }
            if (counter.hasErrors())  {
                // Do *not* print usage for config errors (just like ECJ does it). Otherwise the user would have to
                // scroll up several screens in order to actually see the error messages.
                // String usage = BuildArgParser.getUsage();
                // MessageUtil.abort(handler, usage);
                return false;
            }
            //System.err.println("errs: " + counter.hasErrors());
            boolean result = ((repeat
                        		? buildManager.incrementalBuild(config, handler)
                        		: buildManager.batchBuild(config, handler))
                    		   && !counter.hasErrors());
			Dump.dumpOnExit();
			return result;
        } catch (AbortException ae) {
            if (ae.isSilent()) {
                throw ae;
            } else {
                MessageUtil.abort(handler, ABORT_MESSAGE, ae);
            }
        } catch (MissingSourceFileException t) {
            MessageUtil.error(handler, t.getMessage());
        } catch (Throwable t) {
            MessageUtil.abort(handler, ABORT_MESSAGE, t);
			Dump.dumpWithException(t);
        }
        return false;
    }

    /**
     * This creates a build configuration for the arguments.
     * Errors reported to the handler:
     * 
    *
  1. The parser detects some directly
  2. *
  3. The parser grabs some from the error stream * emitted by its superclass
  4. *
  5. The configuration has a self-test
  6. *
* In the latter two cases, the errors do not have * a source location context for locating the error. */ public static AjBuildConfig genBuildConfig(String[] args, CountingMessageHandler handler) { BuildArgParser parser = new BuildArgParser(handler); AjBuildConfig config = parser.genBuildConfig(args); ISourceLocation location = null; if (config.getConfigFile() != null) { location = new SourceLocation(config.getConfigFile(), 0); } String message = parser.getOtherMessages(true); if (null != message) { IMessage.Kind kind = inferKind(message); IMessage m = new Message(message, kind, null, location); handler.handleMessage(m); } // message = config.configErrors(); // if (null != message) { // IMessage.Kind kind = inferKind(message); // IMessage m = new Message(message, kind, null, location); // handler.handleMessage(m); // } return config; } /** * Heuristically infer the type of output message logged by the AspectJ compiler. This is a simple keyword matcher * looking for substrings like "[error]", "[warning]", "AspectJ-specific options:", "AspectJ-specific non-standard * options:", "Warning options:". * * @param message AspectJ compiler message * @return inferred message kind, either of ERROR, WARNING, USAGE, INFO */ protected static IMessage.Kind inferKind(String message) { // XXX dubious if (message.contains("[error]")) { return IMessage.ERROR; } else if (message.contains("[warning]")) { return IMessage.WARNING; } else if ( containsAll(message, "Usage: ", "AspectJ-specific options:", "Classpath options:") || containsAll(message, "Warning options:", "-nowarn", "localHiding", "uselessTypeCheck") || containsAll(message, "AspectJ-specific non-standard options:", "-XnoInline", "-Xjoinpoints:") ) { return IMessage.USAGE; } else { return IMessage.INFO; } } private static boolean containsAll(String message, String... searchStrings) { for (String searchString : searchStrings) if (!message.contains(searchString)) return false; return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy