Package ch.ethz.prose.tools

Source Code of ch.ethz.prose.tools.RemoteAspectManagerImpl

//
//  This file is part of the prose package.
//
//  The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (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.mozilla.org/MPL/
//
//  Software distributed under the License is distributed on an "AS IS" basis,
//  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
//  for the specific language governing rights and limitations under the
//  License.
//
//  The Original Code is prose.
//
//  The Initial Developers of the Original Code are Andrei Popovici and
//  Angela Nicoara. Portions created by Andrei Popovici and Angela Nicoara
//  are Copyright (C) 2002 Andrei Popovici and Angela Nicoara.
//  All Rights Reserved.
//
//  Contributor(s):
//  $Id: RemoteAspectManagerImpl.java,v 1.4 2008/11/18 11:43:39 anicoara Exp $
//  =====================================================================
//

package ch.ethz.prose.tools;

import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import ch.ethz.prose.Aspect;
import ch.ethz.prose.DefaultAspect;
import ch.ethz.prose.AspectManager;
import ch.ethz.prose.ProseSystem;
import ch.ethz.inf.util.Logger;
import ch.ethz.jvmai.JVMAspectInterface;
import ch.ethz.jvmai.SunBCELRepositoryInterface;
import ch.ethz.prose.crosscut.MethodRedefineCut;
import ch.ethz.prose.query.QueryManager;
import ch.ethz.prose.query.AspectSurrogate;
import ch.ethz.prose.crosscut.Crosscut;

/** Class <code>RemoteAspectManagerImpl</code> a  simple implementation for the
* <code>RemoteAspectManager</code> prose instance.
*
* <code>RemoteAspectManagerImpl</code> DOES NOT export the created objects;
* @version  $Revision: 1.4 $
* @author  Andrei Popovici
* @author  Angela Nicoara
*/
public class RemoteAspectManagerImpl  implements RemoteAspectManager {
  private SunBCELRepositoryInterface ai;  // only used for the remote insertion (event notification JVMDI + JVMTI)
  private boolean isReal;
  private boolean isRemote;
  private AspectManager extMgr;
  private QueryManager qMgr;

  public RemoteAspectManagerImpl(boolean real) throws RemoteException {
    isReal = real;
  }

  public void init() throws RemoteException {
    if (extMgr==null) {
      if (isReal)
        extMgr = ProseSystem.getAspectManager();
      else
        extMgr = ProseSystem.getTestAspectManager();
      qMgr = new QueryManager(extMgr);

      if( extMgr.getJoinPointManager().getAspectInterface() instanceof SunBCELRepositoryInterface) {  // gerry
        ai = (SunBCELRepositoryInterface) extMgr.getJoinPointManager().getAspectInterface();
      }
    }
  }

  /**
   * Insert an extension into the underlying <code>ProseSystem</code>.
   */
  public void insert(Aspect ext) throws RemoteException {
    init();
    insert(ext,null);
  }

  public void withdraw(AspectSurrogate ext) throws RemoteException,ClassNotFoundException {
    init();
    withdraw(ext,null);
  }

  public void insert(Aspect ext, Object txId) throws RemoteException {
    try {
      init();

      // Workaround for MethodRedefineCuts and crosscutting aspects.
      // The BCEL based implementation needs access to the aspects class file(s)
      // to redefine the advice methods bodies.

      if( ai != null ) {
        // transfer ext and member classes to
        // AspectInterfaces BCEL repository
        putFullAspectIntoBCELRepository(ext);
      }

      if (txId == null)
        extMgr.insert(ext);
      else
        extMgr.insert(ext,txId);
    }
    catch (Throwable t) {
      // t.printStackTrace();
      throw new RemoteException(t.toString());
    }
  }

  /**
   * Makes the declared fields of a class available to PROSE BCEL repository.
   *
   * @param cls The class
   */
  private void putFieldsIntoBCELRepository(Class cls) {
    //System.err.println("RemoteAspectManagerImpl - putFieldsIntoBCELRepository => CLASS = " + cls.getName());
    // get all fields that it declares
    Field[] declaredFields = cls.getDeclaredFields();
    for(int i = 0; i < declaredFields.length; i++) {
      //System.err.println("RemoteAspectManagerImpl - putFieldsIntoBCELRepository + FIELDS.type = " + declaredFields[i].getType());
      // Don't send classes primitive types
      if(!declaredFields[i].getType().isPrimitive())
        putClassFileIntoBCELRepository(declaredFields[i].getType());
    }
  }

  /**
   * Makes the methods parameters of a class available
   * to PROSE BCEL repository.
   *
   * @param cls The class
   */
  private void putMethodParametersIntoBCELRepository(Class cls) {
    //System.err.println("RemoteAspectManagerImpl - putMethodParametersIntoBCELRepository => CLASS = " + cls.getName());
    Method[] methods = cls.getDeclaredMethods();
    for(int i=0; i<methods.length; i++) {
      //System.err.println("RemoteAspectManagerImpl - putMethodParametersIntoBCELRepository => METHODS = " + methods[i]);
      Class[] param = methods[i].getParameterTypes();
      for(int j=0; j < param.length; j++) {
        putClassFileIntoBCELRepository(param[j]);
        //System.err.println("RemoteAspectManagerImpl - putMethodParametersIntoBCELRepository => PARAM types: " + param[j].getName());
        //System.err.println("RemoteAspectManagerImpl - putMethodParametersIntoBCELRepository => PARAM length: " + param.length);
      }
      // Put also the return type into the repository
      putClassFileIntoBCELRepository(methods[i].getReturnType());
    }
  }

  /**
   * Makes the crosscuts of an aspect available to the
   * PROSE BCEL repository.
   *
   * @param ext The aspect
   */
  private void putCrosscutsIntoBCELRepository(Aspect ext) {
    //System.err.println("RemoteAspectManagerImpl - putCrosscutsIntoBCELRepository => CLASS = " + ext.toString());
    try{
      Method m = null;
      Class cls = ext.getClass();
      if (DefaultAspect.class.isAssignableFrom(cls)) {
        do {
          cls = cls.getSuperclass();
        } while( ! DefaultAspect.class.equals(cls));
      }
      //System.err.println("RemoteAspectManagerImpl - putCrosscutsIntoBCELRepository => CROSSCUT = " + cls.getName());

      m = cls.getDeclaredMethod("crosscuts",new Class[]{});
      m.setAccessible(true);
      Crosscut[] cc = (Crosscut[]) m.invoke(ext, new Object[]{});

      //System.err.println("RemoteAspectManagerImpl - putCrosscutsIntoBCELRepository => Number of CROSSCUTS => " + cc.length);
      for (int i=0; i < cc.length; i++){
        //System.err.println("RemoteAspectManagerImpl - putCrosscutsIntoBCELRepository - CROSSCUT = " + cc[i].toString());
        Class ccls = cc[i].getClass();
        putFieldsIntoBCELRepository(ccls);
        putMethodParametersIntoBCELRepository(ccls);
        putClassFileIntoBCELRepository(ccls);
      }
    } catch(Exception e) { System.err.println("RemoteAspectManagerImpl - putCrosscutIntoBCELRepository: " + e); }
  }

  /**
   * Makes an aspect available to PROSEs BCEL repository.
   * <P>
   * The aspect, all classes of its fields and all member/inner
   * classes will be added to the repository.
   * <P>
   * This fetches the aspects, its fields and inner classes,
   * the public inner classes and fields of its super classes and its
   * anonymous inner classes.
   *
   * @param ext the aspect
   */
  private void putFullAspectIntoBCELRepository(Aspect ext) {

    // 1. get all crosscuts and put them into the BCEL repository
    putCrosscutsIntoBCELRepository(ext);

    Class clazz = ext.getClass();
    do {
      // 2. put the class into the repository
      putClassFileIntoBCELRepository(clazz);

      // 3. put the types of the methods parameters into the repository
      putMethodParametersIntoBCELRepository(clazz);

      // 4. put its fields into the repository
      putFieldsIntoBCELRepository(clazz);

      // 5. put its declared inner classes into the repository
      Class[] declaredClasses = clazz.getDeclaredClasses();
      for(int i = 0; i < declaredClasses.length; i++) {
        Class innerClass = declaredClasses[i];
        putClassFileIntoBCELRepository(innerClass);
        putFieldsIntoBCELRepository(innerClass);
        putMethodParametersIntoBCELRepository(innerClass);
      }

      // 6. put its anonymous inner classes into the repository
      String extName = clazz.getName();
      int j = 1;
      InputStream classFile;
      // Anonymous inner classes are numbered beginning from 1.
      // Following approach reconstructs the filenames and tries to get
      // the according files. If no file is found, all anonymous inner classes are
      // already processed.
      while(null != (classFile = ext.getClass().getResourceAsStream( extName.replace('.','/') + "$" + j + ".class"))) {
        String clsName = extName + "$" + j;
        //System.err.println(">> RemoteAspectManagerImpl - putFullAspectIntoBCELRepository => anonymous CLASS = " + clsName);
        //System.err.println(">> RemoteAspectManagerImpl - putFullAspectIntoBCELRepository => class = " + classFile.getClass().getName());       
        ai.addBCELClassDefiniton(classFile, clsName);
        j++;
      }

      // 7. do the same thing for its super class (until the class 'Aspect' is reached)
      //    looking for 'DefaultAspect' might be more efficient. But this is
      //    safe, in case an aspect class was directly derived from 'Aspect'.
      clazz = clazz.getSuperclass();
    } while(!clazz.equals(Aspect.class));
  }

  /**
   * Makes a class file available to PROSEs BCEL repository.
   * <P>
   * (for this method, the client must be connected to a PROSE VM
   * that uses a HotSwap based execution monitor)
   *
   * @param cls the class that will be transfered
   */
  private void putClassFileIntoBCELRepository(Class cls) {
    //System.err.println("RemoteAspectManagerImpl - putClassFileIntoBCELRepository => CLASS = " + cls.getName());
    //System.err.println("RemoteAspectManagerImpl - putClassFileIntoBCELRepository => class name: " + cls.getName() + " converted to " + cls.getName().replace('.','/') + ".class");

    //InputStream classFile = cls.getResourceAsStream( cls.getName().replace('.','/') + ".class");      //BEFORE - BUGFIX - aspects package

    InputStream classFile = null;                                      //PLUS - BUGFIX - aspects package
    if (null != cls.getClassLoader())                                     //PLUS - BUGFIX - aspects package
      classFile = cls.getClassLoader().getResourceAsStream( cls.getName().replace('.','/') + ".class");   //PLUS - BUGFIX - aspects package
    else                                                   //PLUS - BUGFIX - aspects package
      classFile = cls.getResourceAsStream( cls.getName().replace('.','/') + ".class");          //PLUS - BUGFIX - aspects package
    if( null != classFile && null != ai) {
      ((SunBCELRepositoryInterface) ai).addBCELClassDefiniton( classFile, cls.getName());
      Logger.message("transfered class file " + cls.getName() );
    }
    else {
      Logger.warning("RemoteAspectManager.putClassFileInBCELRepository failed for " + cls + " (AspectInterface: " + ai + ")");
    }
  }

  public void withdraw(AspectSurrogate ext,Object txId) throws RemoteException,ClassNotFoundException {
    init();
    Aspect asp = qMgr.reconstructAspect(ext);

    List x = new Vector((extMgr.getAllAspects()));
    int extIndx = x.indexOf(asp);
    if (extIndx >= 0) {
      if (txId == null) {
        extMgr.withdraw((Aspect)(x.get(extIndx)));
      }
      else
        extMgr.withdraw((Aspect)(x.get(extIndx)),txId);
    }
    else {
      Logger.message("extension " + ext + " not known");
      throw new RuntimeException( "extension " + ext + " not known");
    }
  }

  public void commit(Object txId) throws RemoteException {
    init();
    extMgr.commit(txId);
  }

  public void abort(Object txId) throws RemoteException {
    init();
    extMgr.abort(txId);
  }

  /**
   * Return a list of the current inserted extensions.
   */
  public List allAspects() throws RemoteException {
    init();
    return qMgr.queryAllAspects();
  }

  public List allJoinpoints() throws RemoteException {
    init();
    return qMgr.queryAllJoinpoints();
  }

  /**
   * Return a List of Tupel objects (without duplicates) that represents the result of querying the system
   * with a list of Aspects.
   */
  public List queryAspects(List aspectList, int selectFields, int groupBy) throws RemoteException  {
    init();
    return qMgr.queryAspects(aspectList,selectFields,groupBy);
  }

  /**
   * Return a List of Tupel objects (without duplicates) that represents the result of querying the system
   * with a list of Crosscuts.
   */
  public List queryCrosscuts(List crosscutList, int selectFields, int groupBy) throws RemoteException {
    init();
    return qMgr.queryCrosscuts(crosscutList,selectFields,groupBy);
  }

  /**
   * Return a List of Tupel objects (without duplicates) that represents the result of querying the system
   * with a list of JoinPointRequests.
   */
  public List queryJoinpoints(List joinpointList, int selectFields, int groupBy) throws RemoteException {
    init();
    return qMgr.queryJoinpoints(joinpointList,selectFields,groupBy);
  }

}
TOP

Related Classes of ch.ethz.prose.tools.RemoteAspectManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.