Beispiel #1
0
    private String fixTypes2(
        ArrayList<TypeVar> scc, HashSet<String> lowersSet, org.hotswap.agent.javassist.ClassPool cp)
        throws org.hotswap.agent.javassist.NotFoundException {
      Iterator<String> it = lowersSet.iterator();
      if (lowersSet.size() == 0) {
        return null; // only NullType
      } else if (lowersSet.size() == 1) {
        return it.next();
      } else {
        org.hotswap.agent.javassist.CtClass cc = cp.get(it.next());
        while (it.hasNext()) {
          cc = commonSuperClassEx(cc, cp.get(it.next()));
        }

        if (cc.getSuperclass() == null || isObjectArray(cc)) {
          cc = fixByUppers(scc, cp, new HashSet<TypeVar>(), cc);
        }

        if (cc.isArray()) {
          return org.hotswap.agent.javassist.bytecode.Descriptor.toJvmName(cc);
        } else {
          return cc.getName();
        }
      }
    }
Beispiel #2
0
    private org.hotswap.agent.javassist.CtClass fixByUppers(
        ArrayList<TypeVar> users,
        org.hotswap.agent.javassist.ClassPool cp,
        HashSet<TypeVar> visited,
        org.hotswap.agent.javassist.CtClass type)
        throws org.hotswap.agent.javassist.NotFoundException {
      if (users == null) {
        return type;
      }

      int size = users.size();
      for (int i = 0; i < size; i++) {
        TypeVar t = users.get(i);
        if (!visited.add(t)) {
          return type;
        }

        if (t.uppers != null) {
          int s = t.uppers.size();
          for (int k = 0; k < s; k++) {
            org.hotswap.agent.javassist.CtClass cc = cp.get(t.uppers.get(k));
            if (cc.subtypeOf(type)) {
              type = cc;
            }
          }
        }

        type = fixByUppers(t.usedBy, cp, visited, type);
      }

      return type;
    }
  @OnClassLoadEvent(classNameRegexp = "org.jboss.resteasy.plugins.server.servlet.FilterDispatcher")
  public static void patchFilterDispatcher(CtClass ctClass, ClassPool classPool)
      throws NotFoundException, CannotCompileException {

    CtClass fltCfgClass = classPool.get("javax.servlet.FilterConfig");
    CtField configField = new CtField(fltCfgClass, FIELD_NAME, ctClass);
    ctClass.addField(configField);

    CtClass setClass = classPool.get(java.util.Set.class.getName());
    CtField paramsField = new CtField(setClass, PARAMETER_FIELD_NAME, ctClass);
    ctClass.addField(paramsField);

    CtMethod methInit = ctClass.getDeclaredMethod("init");
    methInit.insertBefore(
        "{"
            + "   if(this."
            + PARAMETER_FIELD_NAME
            + " == null) {"
            + PluginManagerInvoker.buildInitializePlugin(ResteasyPlugin.class)
            + PluginManagerInvoker.buildCallPluginMethod(
                ResteasyPlugin.class, "registerDispatcher", "this", "java.lang.Object")
            + "   }"
            + "   this."
            + FIELD_NAME
            + " = $1;"
            + "   this."
            + PARAMETER_FIELD_NAME
            + " = "
            + ResteasyContextParams.class.getName()
            + ".init($1.getServletContext(), this."
            + PARAMETER_FIELD_NAME
            + "); "
            + "}");
  }
Beispiel #4
0
  // same as above for older jetty versions
  @OnClassLoadEvent(classNameRegexp = "org.mortbay.jetty.webapp.WebXmlConfiguration")
  public static void patchWebXmlConfiguration6x(CtClass ctClass)
      throws NotFoundException, CannotCompileException, ClassNotFoundException {
    try {
      // after application context initialized, but before processing started
      CtMethod doStart = ctClass.getDeclaredMethod("configureWebApp");

      // init the plugin
      String src =
          PluginManagerInvoker.buildInitializePlugin(
              JettyPlugin.class, "getWebAppContext().getClassLoader()");
      src +=
          PluginManagerInvoker.buildCallPluginMethod(
              "getWebAppContext().getClassLoader()",
              JettyPlugin.class,
              "init",
              "getWebAppContext()",
              "java.lang.Object");

      doStart.insertBefore(src);
    } catch (NotFoundException e) {
      LOGGER.warning(
          "org.mortbay.jetty.webapp.WebXmlConfiguration does not contain startContext method. Jetty plugin will be disabled.\n"
              + "*** This is Ok, Jetty plugin handles only special properties ***");
      return;
    }
  }
 @OnClassLoadEvent(classNameRegexp = ".*", events = LoadEvent.REDEFINE)
 public void entityReload(ClassLoader classLoader, CtClass clazz, Class original) {
   if (AnnotationHelper.hasAnnotation(original, PATH_ANNOTATION)
       || AnnotationHelper.hasAnnotation(clazz, PATH_ANNOTATION)) {
     LOGGER.debug(
         "Reload @Path annotated class {}, original classloader {}",
         clazz.getName(),
         original.getClassLoader());
     refresh(classLoader, 500);
   }
 }
Beispiel #6
0
  /**
   * Before actual webapp initialization starts in ContextHandler.doStart(), do some enhancements:
   *
   * <ul>
   *   <li>Initialize this plugin on the webapp classloader
   *   <li>Call plugin method initExtraPathClassLoader add urls and to start watching changed
   *       resources
   *   <li>Call plugin method registerExtraPathClassLoader to inject enhanced resource loader to the
   *       webapp classloader.
   * </ul>
   */
  @Transform(classNameRegexp = "org.apache.catalina.core.StandardContext")
  public static void patchStandardContext(CtClass ctClass)
      throws NotFoundException, CannotCompileException, ClassNotFoundException {
    try {
      // force disable caching
      ctClass.getDeclaredMethod("isCachingAllowed").setBody("return false;");
    } catch (NotFoundException e) {
      LOGGER.debug(
          "org.apache.catalina.core.StandardContext does not contain isCachingAllowed() method. Probably Ok.");
    }

    try {
      ctClass
          .getDeclaredMethod("stopInternal")
          .insertBefore(
              PluginManagerInvoker.buildCallCloseClassLoader("getLoader().getClassLoader()"));
    } catch (NotFoundException e) {
      LOGGER.debug(
          "org.apache.catalina.core.StandardContext does not contain stopInternal() method. Hotswap agent will not be able to free Tomcat plugin resources.");
    }
  }
Beispiel #7
0
  /** Before app context is stopped, clean the classloader (and associated plugin instance). */
  @OnClassLoadEvent(
      classNameRegexp =
          "(org.mortbay.jetty.webapp.WebAppContext)|(org.eclipse.jetty.webapp.WebAppContext)")
  public static void patchContextHandler6x(CtClass ctClass)
      throws NotFoundException, CannotCompileException, ClassNotFoundException {

    try {
      ctClass
          .getDeclaredMethod("doStop")
          .insertBefore(PluginManagerInvoker.buildCallCloseClassLoader("getClassLoader()"));
    } catch (NotFoundException e) {
      LOGGER.debug(
          "org.eclipse.jetty.webapp.WebAppContext does not contain doStop() method. Hotswap agent will not be able to free Jetty plugin resources.");
    }
  }
Beispiel #8
0
  /** Init the plugin from start method. */
  @Transform(classNameRegexp = "org.apache.catalina.loader.WebappLoader")
  public static void patchWebappLoader(CtClass ctClass)
      throws NotFoundException, CannotCompileException, ClassNotFoundException {

    try {
      CtMethod startInternalMethod = ctClass.getDeclaredMethod("startInternal");
      // init the plugin
      String src = PluginManagerInvoker.buildInitializePlugin(TomcatPlugin.class, "classLoader");

      startInternalMethod.insertAfter(src);
    } catch (NotFoundException e) {
      LOGGER.warning(
          "org.apache.catalina.loader.WebappLoader does not contain startInternal method. Tomcat plugin will be disabled.\n"
              + "*** This is Ok, Tomcat plugin handles only special properties ***");
      return;
    }
  }
  /** Run plugin the method. */
  public void onWatchEvent(
      PluginAnnotation<T> pluginAnnotation, WatchFileEvent event, ClassLoader classLoader) {
    final T annot = pluginAnnotation.getAnnotation();
    Object plugin = pluginAnnotation.getPlugin();

    // regular files filter
    if (watchEventDTO.isOnlyRegularFiles() && !event.isFile()) {
      LOGGER.trace("Skipping URI {} because it is not a regular file.", event.getURI());
      return;
    }

    // watch type filter
    if (!Arrays.asList(watchEventDTO.getEvents()).contains(event.getEventType())) {
      LOGGER.trace("Skipping URI {} because it is not a requested event.", event.getURI());
      return;
    }

    // resource name filter regexp
    if (watchEventDTO.getFilter() != null && watchEventDTO.getFilter().length() > 0) {
      if (!event.getURI().toString().matches(watchEventDTO.getFilter())) {
        LOGGER.trace(
            "Skipping URI {} because it does not match filter.",
            event.getURI(),
            watchEventDTO.getFilter());
        return;
      }
    }

    // we may need to crate CtClass on behalf of the client and close it after invocation.
    CtClass ctClass = null;

    // class file regexp
    if (watchEventDTO.isClassFileEvent()) {
      try {
        // TODO creating class only to check name may slow down if lot of handlers is in use.
        ctClass = createCtClass(event.getURI(), classLoader);
      } catch (Exception e) {
        LOGGER.error("Unable create CtClass for URI '{}'.", e, event.getURI());
        return;
      }

      // unable to create CtClass or it's name does not match
      if (ctClass == null || !ctClass.getName().matches(watchEventDTO.getClassNameRegexp())) return;
    }

    LOGGER.debug(
        "Executing resource changed method {} on class {} for event {}",
        pluginAnnotation.getMethod().getName(),
        plugin.getClass().getName(),
        event);

    List<Object> args = new ArrayList<Object>();
    for (Class<?> type : pluginAnnotation.getMethod().getParameterTypes()) {
      if (type.isAssignableFrom(ClassLoader.class)) {
        args.add(classLoader);
      } else if (type.isAssignableFrom(URI.class)) {
        args.add(event.getURI());
      } else if (type.isAssignableFrom(URL.class)) {
        try {
          args.add(event.getURI().toURL());
        } catch (MalformedURLException e) {
          LOGGER.error("Unable to convert URI '{}' to URL.", e, event.getURI());
          return;
        }
      } else if (type.isAssignableFrom(ClassPool.class)) {
        args.add(ClassPool.getDefault());
      } else if (type.isAssignableFrom(FileEvent.class)) {
        args.add(event.getEventType());
      } else if (watchEventDTO.isClassFileEvent() && type.isAssignableFrom(CtClass.class)) {
        args.add(ctClass);
      } else if (watchEventDTO.isClassFileEvent() && type.isAssignableFrom(String.class)) {
        args.add(ctClass.getName());
      } else {
        LOGGER.error(
            "Unable to call method {} on plugin {}. Method parameter type {} is not recognized.",
            pluginAnnotation.getMethod().getName(),
            plugin.getClass().getName(),
            type);
        return;
      }
    }
    try {
      pluginAnnotation.getMethod().invoke(plugin, args.toArray());

      // close CtClass if created from here
      if (ctClass != null) {
        ctClass.detach();
      }
    } catch (IllegalAccessException e) {
      LOGGER.error(
          "IllegalAccessException in method {} on plugin {}",
          e,
          pluginAnnotation.getMethod().getName(),
          plugin.getClass().getName());
    } catch (InvocationTargetException e) {
      LOGGER.error(
          "InvocationTargetException in method {} on plugin {}",
          e,
          pluginAnnotation.getMethod().getName(),
          plugin.getClass().getName());
    }
  }
Beispiel #10
0
 static boolean eq(
     org.hotswap.agent.javassist.CtClass one, org.hotswap.agent.javassist.CtClass two) {
   return one == two || one != null && two != null && one.getName().equals(two.getName());
 }
Beispiel #11
0
  /**
   * Finds the most specific common super class of the given classes. This method is a copy from
   * Type.
   */
  public static org.hotswap.agent.javassist.CtClass commonSuperClass(
      org.hotswap.agent.javassist.CtClass one, org.hotswap.agent.javassist.CtClass two)
      throws org.hotswap.agent.javassist.NotFoundException {
    org.hotswap.agent.javassist.CtClass deep = one;
    org.hotswap.agent.javassist.CtClass shallow = two;
    org.hotswap.agent.javassist.CtClass backupShallow = shallow;
    org.hotswap.agent.javassist.CtClass backupDeep = deep;

    // Phase 1 - Find the deepest hierarchy, set deep and shallow correctly
    for (; ; ) {
      // In case we get lucky, and find a match early
      if (eq(deep, shallow) && deep.getSuperclass() != null) {
        return deep;
      }

      org.hotswap.agent.javassist.CtClass deepSuper = deep.getSuperclass();
      org.hotswap.agent.javassist.CtClass shallowSuper = shallow.getSuperclass();

      if (shallowSuper == null) {
        // right, now reset shallow
        shallow = backupShallow;
        break;
      }

      if (deepSuper == null) {
        // wrong, swap them, since deep is now useless, its our tmp
        // before we swap it
        deep = backupDeep;
        backupDeep = backupShallow;
        backupShallow = deep;

        deep = shallow;
        shallow = backupShallow;
        break;
      }

      deep = deepSuper;
      shallow = shallowSuper;
    }

    // Phase 2 - Move deepBackup up by (deep end - deep)
    for (; ; ) {
      deep = deep.getSuperclass();
      if (deep == null) {
        break;
      }

      backupDeep = backupDeep.getSuperclass();
    }

    deep = backupDeep;

    // Phase 3 - The hierarchy positions are now aligned
    // The common super class is easy to find now
    while (!eq(deep, shallow)) {
      deep = deep.getSuperclass();
      shallow = shallow.getSuperclass();
    }

    return deep;
  }
Beispiel #12
0
 /** Finds the most specific common super class of the given classes by considering array types. */
 public static org.hotswap.agent.javassist.CtClass commonSuperClassEx(
     org.hotswap.agent.javassist.CtClass one, org.hotswap.agent.javassist.CtClass two)
     throws org.hotswap.agent.javassist.NotFoundException {
   if (one == two) {
     return one;
   } else if (one.isArray() && two.isArray()) {
     org.hotswap.agent.javassist.CtClass ele1 = one.getComponentType();
     org.hotswap.agent.javassist.CtClass ele2 = two.getComponentType();
     org.hotswap.agent.javassist.CtClass element = commonSuperClassEx(ele1, ele2);
     if (element == ele1) {
       return one;
     } else if (element == ele2) {
       return two;
     } else {
       return one.getClassPool()
           .get(element == null ? "java.lang.Object" : element.getName() + "[]");
     }
   } else if (one.isPrimitive() || two.isPrimitive()) {
     return null; // TOP
   } else if (one.isArray() || two.isArray()) {
     // two.isArray())
     return one.getClassPool().get("java.lang.Object");
   } else {
     return commonSuperClass(one, two);
   }
 }
Beispiel #13
0
 private static boolean isObjectArray(org.hotswap.agent.javassist.CtClass cc)
     throws org.hotswap.agent.javassist.NotFoundException {
   return cc.isArray() && cc.getComponentType().getSuperclass() == null;
 }