@Override
  public void enhanceThisClass(final ApplicationClass applicationClass) throws Exception {
    final CtClass ctClass = makeClass(applicationClass);
    if (ctClass.isInterface()) {
      return;
    }

    final Map<CtField, InjectionInfo> fieldsToInject = scanForInjections(ctClass);

    // in all methods, replace the field accesses with a call to spring
    for (final CtMethod ctMethod : ctClass.getDeclaredMethods()) {
      ctMethod.instrument(
          new ExprEditor() {
            @Override
            public void edit(final FieldAccess fieldAccess) {
              try {
                final InjectionInfo injectionInfo = fieldsToInject.get(fieldAccess.getField());

                if (injectionInfo != null && fieldAccess.isReader()) {

                  switch (injectionInfo.injectionMethod) {
                    case BY_NAME:
                      fieldAccess.replace(
                          "$_ = ($r)play.utils.Java.invokeStatic(play.modules.spring.Spring.class, \"getBean\", new Object[] {\""
                              + injectionInfo.beanName
                              + "\"});");
                      break;
                    case BY_TYPE:
                      fieldAccess.replace(
                          "$_ = ($r)play.utils.Java.invokeStatic(play.modules.spring.Spring.class, \"getBeanOfType\", new Object[] {$type});");
                      break;
                  }
                }
              } catch (final Exception e) {
                Logger.error(
                    e,
                    "Error in SpringEnhancer. %s.%s has not been properly enhanced (fieldAccess %s).",
                    applicationClass.name,
                    ctMethod.getName(),
                    fieldAccess);
                throw new UnexpectedException("Error enhancing injected field", e);
              }
            }
          });
    }

    applicationClass.enhancedByteCode = ctClass.toBytecode();
    ctClass.defrost();
  }
Exemple #2
0
 private void preprocessMethods(CtClass cc, boolean insertLoad, boolean wrapFieldAccess)
     throws CannotCompileException {
   CtMethod[] methods = cc.getDeclaredMethods();
   for (int i = 0; i < methods.length; i++) {
     CtMethod m = methods[i];
     if (wrapFieldAccess) {
       m.instrument(
           new ExprEditor() {
             public void edit(FieldAccess fa) throws CannotCompileException {
               try {
                 if ((fa.getField().getModifiers() & (Modifier.TRANSIENT | Modifier.STATIC)) == 0
                     && fa.getField().getDeclaringClass().subtypeOf(persistentInterface)) {
                   if (fa.isWriter()) {
                     fa.replace("{ $0.loadAndModify(); $proceed($$); }");
                   }
                   // isSelfReader is my extension of JAssist, if you
                   // use original version of JAssist comment the
                   // branch below or replace "else if" with "else".
                   // In first case Perst will not be able to handle
                   // access to foreign (non-this) fields. You should use
                   // getter/setter methods instead.
                   // In second case access to foreign fields still will be possible,
                   // but with significant degradation of performance and
                   // increased code size, because in this case before ALL access
                   // to fields of persistent capable object call of load() method
                   // will be inserted.
                   else if (!fa.isSelfReader()) {
                     fa.replace("{ $0.load(); $_ = $proceed($$); }");
                   }
                 }
               } catch (NotFoundException x) {
               }
             }
           });
     }
     if (insertLoad
         && !"recursiveLoading".equals(m.getName())
         && (m.getModifiers() & (Modifier.STATIC | Modifier.ABSTRACT)) == 0) {
       m.insertBefore("load();");
     }
   }
 }