Logo Search packages:      
Sourcecode: aspectj version File versions  Download package

ShadowMunger.java

/* *******************************************************************
 * 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 v1.0 
 * which accompanies this distribution and is available at 
 * http://www.eclipse.org/legal/epl-v10.html 
 *  
 * Contributors: 
 *     PARC     initial implementation 
 * ******************************************************************/

package org.aspectj.weaver;

import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.PartialOrder;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.Pointcut;
import org.aspectj.weaver.patterns.TypePattern;

/**
 * For every shadow munger, nothing can be done with it until it is concretized. Then...
 * 
 * (Then we call fast match.)
 * 
 * For every shadow munger, for every shadow, first match is called, then (if match returned true) the shadow munger is specialized
 * for the shadow, which may modify state. Then implement is called.
 */
00041 public abstract class ShadowMunger implements PartialOrder.PartialComparable, IHasPosition {

      public static final ShadowMunger[] NONE = new ShadowMunger[0];

      private static int VERSION_1 = 1; // ShadowMunger version for serialization

      protected static final int ShadowMungerAdvice = 1;
      protected static final int ShadowMungerDeow = 2;

      public String handle = null;

      private int shadowMungerKind;

      protected int start, end;
      protected ISourceContext sourceContext;
      private ISourceLocation sourceLocation;
      private ISourceLocation binarySourceLocation;
      private File binaryFile;
      private ResolvedType declaringType;
      private boolean isBinary;
      private boolean checkedIsBinary;

      protected Pointcut pointcut;

      protected ShadowMunger() {
      }

      public ShadowMunger(Pointcut pointcut, int start, int end, ISourceContext sourceContext, int shadowMungerKind) {
            this.shadowMungerKind = shadowMungerKind;
            this.pointcut = pointcut;
            this.start = start;
            this.end = end;
            this.sourceContext = sourceContext;
      }

      /**
       * All overriding methods should call super
       */
00079       public boolean match(Shadow shadow, World world) {
            if (world.isXmlConfigured() && world.isAspectIncluded(declaringType)) {
                  TypePattern scoped = world.getAspectScope(declaringType);
                  if (scoped != null) {
                        // Check the 'cached' exclusion map
                        Set<ResolvedType> excludedTypes = world.getExclusionMap().get(declaringType);
                        ResolvedType type = shadow.getEnclosingType().resolve(world);
                        if (excludedTypes != null && excludedTypes.contains(type)) {
                              return false;
                        }
                        boolean b = scoped.matches(type, TypePattern.STATIC).alwaysTrue();
                        if (!b) {
                              if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
                                    world.getMessageHandler().handleMessage(
                                                MessageUtil.info("Type '" + type.getName() + "' not woven by aspect '" + declaringType.getName()
                                                            + "' due to scope exclusion in XML definition"));
                              }
                              if (excludedTypes == null) {
                                    excludedTypes = new HashSet<ResolvedType>();
                                    excludedTypes.add(type);
                                    world.getExclusionMap().put(declaringType, excludedTypes);
                              } else {
                                    excludedTypes.add(type);
                              }
                              return false;
                        }
                  }
            }
            return pointcut.match(shadow).maybeTrue();
      }

00110       public int fallbackCompareTo(Object other) {
            return toString().compareTo(toString());
      }

      public int getEnd() {
            return end;
      }

      public int getStart() {
            return start;
      }

      public ISourceLocation getSourceLocation() {
            if (sourceLocation == null) {
                  if (sourceContext != null) {
                        sourceLocation = sourceContext.makeSourceLocation(this);
                  }
            }
            if (isBinary()) {
                  if (binarySourceLocation == null) {
                        binarySourceLocation = getBinarySourceLocation(sourceLocation);
                  }
                  return binarySourceLocation;
            }
            return sourceLocation;
      }

      public Pointcut getPointcut() {
            return pointcut;
      }

      // pointcut may be updated during rewriting...
      public void setPointcut(Pointcut pointcut) {
            this.pointcut = pointcut;
      }

      /**
       * Invoked when the shadow munger of a resolved type are processed.
       * 
       * @param aType
       */
00151       public void setDeclaringType(ResolvedType aType) {
            declaringType = aType;
      }

      public ResolvedType getDeclaringType() {
            return declaringType;
      }

      /**
       * Returns the binarySourceLocation for the given sourcelocation. This isn't cached because it's used when faulting in the
       * binary nodes and is called with ISourceLocations for all advice, pointcuts and deows contained within the
       * resolvedDeclaringAspect.
       */
00164       public ISourceLocation getBinarySourceLocation(ISourceLocation sl) {
            if (sl == null) {
                  return null;
            }
            String sourceFileName = null;
            if (getDeclaringType() instanceof ReferenceType) {
                  String s = ((ReferenceType) getDeclaringType()).getDelegate().getSourcefilename();
                  int i = s.lastIndexOf('/');
                  if (i != -1) {
                        sourceFileName = s.substring(i + 1);
                  } else {
                        sourceFileName = s;
                  }
            }
            ISourceLocation sLoc = new SourceLocation(getBinaryFile(), sl.getLine(), sl.getEndLine(),
                        ((sl.getColumn() == 0) ? ISourceLocation.NO_COLUMN : sl.getColumn()), sl.getContext(), sourceFileName);
            return sLoc;
      }

      /**
       * Returns the File with pathname to the class file, for example either C:\temp
       * \ajcSandbox\workspace\ajcTest16957.tmp\simple.jar!pkg\BinaryAspect.class if the class file is in a jar file, or
       * C:\temp\ajcSandbox\workspace\ajcTest16957.tmp!pkg\BinaryAspect.class if the class file is in a directory
       */
00188       private File getBinaryFile() {
            if (binaryFile == null) {
                  String s = getDeclaringType().getBinaryPath();
                  if (s.indexOf("!") == -1) {
                        File f = getDeclaringType().getSourceLocation().getSourceFile();
                        // Replace the source file suffix with .class
                        int i = f.getPath().lastIndexOf('.');
                        String path = null;
                        if (i != -1) {
                              path = f.getPath().substring(0, i) + ".class";
                        } else {
                              path = f.getPath() + ".class";
                        }
                        binaryFile = new File(s + "!" + path);
                  } else {
                        binaryFile = new File(s);
                  }
            }
            return binaryFile;
      }

      /**
       * Returns whether or not this shadow munger came from a binary aspect - keep a record of whether or not we've checked if we're
       * binary otherwise we keep calculating the same thing many times
       */
00213       public boolean isBinary() {
            if (!checkedIsBinary) {
                  ResolvedType rt = getDeclaringType();
                  if (rt != null) {
                        isBinary = ((rt.getBinaryPath() == null) ? false : true);
                  }
                  checkedIsBinary = true;
            }
            return isBinary;
      }

      public abstract ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause);

      public abstract void specializeOn(Shadow shadow);

      /**
       * Implement this munger at the specified shadow, returning a boolean to indicate success.
       * 
       * @param shadow the shadow where this munger should be applied
       * @return true if the implement was successful
       */
      public abstract boolean implementOn(Shadow shadow);

      public abstract ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap);

      /**
       * @return a Collection of ResolvedTypes for all checked exceptions that might be thrown by this munger
       */
      public abstract Collection getThrownExceptions();

      /**
       * Does the munger have to check that its exception are accepted by the shadow ? It is not the case for annotation style around
       * advice, for example: that can throw Throwable, even if the advised method does not throw any exceptions.
       * 
       * @return true if munger has to check that its exceptions can be thrown based on the shadow
       */
      public abstract boolean mustCheckExceptions();

      public void write(DataOutputStream stream) throws IOException {
            stream.writeInt(VERSION_1);
            stream.writeInt(shadowMungerKind); // determines real subclass
            stream.writeInt(start);
            stream.writeInt(end);
            PersistenceSupport.write(stream, sourceContext);
            PersistenceSupport.write(stream, sourceLocation);
            PersistenceSupport.write(stream, binarySourceLocation);
            PersistenceSupport.write(stream, binaryFile);
            declaringType.write(stream);
            stream.writeBoolean(isBinary);
            stream.writeBoolean(checkedIsBinary);
            pointcut.write(stream);
      }
      //
      // public static ShadowMunger read(VersionedDataInputStream stream, World world) throws IOException {
      // stream.readInt();
      // int kind = stream.readInt();
      // ShadowMunger newShadowMunger = null;
      // switch (kind) {
      // case ShadowMungerAdvice:
      // // world.getWeavingSupport().createAdviceMunger(attribute, pointcut, signature)
      // case ShadowMungerDeow:
      // newShadowMunger = Checker.read(stream, world);
      // default:
      // throw new IllegalStateException("Unexpected type of shadow munger found on deserialization: " + kind);
      // }
      // newShadowMunger.binaryFile = null;
      // }
}

Generated by  Doxygen 1.6.0   Back to index