public byte[] translate(
      AspectManager manager, String className, ClassLoader loader, byte[] classfileBuffer)
      throws Exception {
    if (isReEntry()) {
      return null;
    }
    setReEntry();
    super.setTransformationStarted();
    try {
      if (manager.isNonAdvisableClassName(className)) {
        return null;
      }

      AOPClassPool pool = (AOPClassPool) manager.registerClassLoader(loader);

      CtClass clazz = obtainCtClassInfo(pool, className, classfileBuffer);

      CtClass woven = instrumentClass(manager, pool, clazz, true);
      if (woven != null) {
        pool.lockInCache(woven);
        if (AspectManager.debugClasses) {
          SecurityActions.debugWriteFile(clazz);
        }
        byte[] rtn = woven.toBytecode();
        if (AspectManager.getPrune()) woven.prune();
        return rtn;
      } else {
        pool.soften(clazz);
      }
      return null;
    } catch (Exception ex) {
      if (!(ex instanceof NotFoundException)) {
        if (verbose) logger.error(ex);
        else logger.error(ex.getMessage() + ".. Do verbose mode if you want full stack trace.");
      }
      throw ex;
    } finally {
      clearReEntry();
    }
  }
  private CtClass instrumentClass(
      AspectManager manager, AOPClassPool pool, CtClass clazz, boolean isLoadedClass)
      throws NotFoundException, Exception {
    if (pool.isClassLoadedButNotWoven(clazz.getName())) {
      return null;
    }
    try {
      CtClass superClass = clazz.getSuperclass();
      if (superClass != null && !Instrumentor.implementsAdvised(clazz)) {
        ClassPool superPool = superClass.getClassPool();
        if (superPool instanceof AOPClassPool) {
          AspectManager aspectManager = manager;
          if (manager instanceof Domain && superPool != pool) {
            // We are in a scoped classloader and the superclass is not
            aspectManager = AspectManager.instance(superPool.getClassLoader());
          }
          instrumentClass(aspectManager, (AOPClassPool) superPool, superClass, false);
        }
      }

      if (manager.isNonAdvisableClassName(clazz.getName())) {
        return null;
      }

      if (clazz.isArray()) {
        if (verbose && logger.isDebugEnabled())
          logger.debug("cannot compile, isArray: " + clazz.getName());
        pool.flushClass(clazz.getName());
        return null;
      }
      if (clazz.isInterface()) {
        if (verbose && logger.isDebugEnabled())
          logger.debug("cannot compile, isInterface: " + clazz.getName());
        // pool.flushClass(info.getClassName());
        clazz.prune();
        return null;
      }
      if (clazz.isFrozen()) {
        if (isAdvised(pool, clazz)) return null;
        if (verbose && logger.isDebugEnabled())
          logger.debug("warning, isFrozen: " + clazz.getName() + " " + clazz.getClassPool());
        if (!isLoadedClass) {
          // What's the point of this?
          clazz = obtainCtClassInfo(pool, clazz.getName(), null);
        } else return null;
        // info.getClazz().defrost();
      }

      boolean transformed = clazz.isModified();
      if (!transformed) {
        ClassAdvisor advisor = AdvisorFactory.getClassAdvisor(clazz, manager);
        Instrumentor instrumentor =
            InstrumentorFactory.getInstrumentor(
                pool,
                manager,
                manager.dynamicStrategy.getJoinpointClassifier(),
                manager.dynamicStrategy.getDynamicTransformationObserver(clazz));

        if (!Instrumentor.isTransformable(clazz)) {
          if (verbose && logger.isDebugEnabled())
            logger.debug("cannot compile, implements Untransformable: " + clazz.getName());
          // Flushing the generated invocation classes breaks things further down the line
          // pool.flushClass(info.getClassName());
          return null;
        }

        manager.attachMetaData(advisor, clazz, true);
        manager.applyInterfaceIntroductions(advisor, clazz);
        transformed = instrumentor.transform(clazz, advisor);
      }
      if (transformed) {
        return clazz;
      }

      if (isLoadedClass) {
        pool.setClassLoadedButNotWoven(clazz.getName());
      }

      return null;
    } catch (Exception e) {
      throw new RuntimeException("Error converting class ", e);
    } finally {
    }
  }