public void getHelp(Caller caller, Workspace workspace, LinkedList<String> tokens) {

    WorkspaceService service = plugin.getWorkspaceService();
    String source = service.getWorkspaceName(caller.getSender());
    String firstToken = tokens.pollFirst();
    if (firstToken == null) firstToken = "";
    MetaClass callerScriptMetaClass = InvokerHelper.getMetaClass(CallerScript.class);
    MetaClass workspaceMetaClass = InvokerHelper.getMetaClass(Workspace.class);
    Map workspaceVars = null;
    if (workspace != null) workspaceVars = workspace.getBinding().getVariables();
    Map globalVars = service.getBinding().getVariables();
    PreparedScriptProperties properties = new PreparedScriptProperties();
    properties.setCaller(caller);
    properties.setServer(plugin.getServer());
    properties.setWorkspace(workspace);

    if (tokens.isEmpty()) { // get current method or class
      if (firstToken.equals("_")) {
        Object result = caller.getLastResult();
        String type = "null";
        if (result != null) type = result.getClass().getName();
        caller.sendPrintMessage("Last result: " + AQUA + type + RESET, source);
        return;
      }
      MetaProperty prop = callerScriptMetaClass.getMetaProperty(firstToken);
      if (prop != null) {
        caller.sendPrintMessage(
            String.format(
                "Script property %s: %s",
                YELLOW + prop.getName() + RESET, AQUA + prop.getType().getName() + RESET),
            source);
        return;
      }
      Class compClass = service.getImportTabCompleteClasses().get(firstToken);
      if (compClass != null) {
        String type = "Class";
        if (compClass.isInterface()) type = "Interface";
        else if (compClass.isEnum()) type = "Enum class";
        StringBuilder buf = new StringBuilder();
        Class superClass = compClass.getSuperclass();
        buf.append(type).append(" ").append(YELLOW).append(compClass.getName()).append(RESET);
        if (superClass != null) {
          buf.append(" extends ").append(AQUA).append(superClass.getName()).append(RESET);
        }
        caller.sendPrintMessage(buf, source);
        return;
      }
      for (MetaMethod metaMethod : callerScriptMetaClass.getMetaMethods()) {
        String name = metaMethod.getName();
        String methodEnd = "(";
        if (metaMethod.isValidMethod(new Class[] {Closure.class})) methodEnd = "{";
        else if (metaMethod.getParameterTypes().length == 0) methodEnd = "()";
        if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) {
          StringBuilder buf = new StringBuilder();
          buf.append("Script meta method ")
              .append(YELLOW)
              .append(metaMethod.getName())
              .append(RESET);
          buf.append(" returns ").append(AQUA).append(metaMethod.getReturnType().getName());
          buf.append(RESET).append('\n');
          Class[] types = metaMethod.getNativeParameterTypes();
          buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n');
          for (Class type : types)
            buf.append(AQUA).append(type.getName()).append('\n').append(RESET);
          buf.deleteCharAt(buf.length() - 1);
          caller.sendPrintMessage(buf, source);
        }
        int args = metaMethod.getParameterTypes().length;
        if ((name.startsWith("get") && args == 0 || name.startsWith("set") && args == 1)
            && name.length() > 3) {
          String propertyName = getPropertyName(name);
          if (propertyName != null && propertyName.equals(firstToken)) {
            caller.sendPrintMessage(
                String.format(
                    "Script meta getter %s returns %s",
                    YELLOW + name + "()" + RESET,
                    AQUA + metaMethod.getReturnType().getName() + RESET),
                source);
          }
        }
      }
      for (MetaMethod metaMethod : workspaceMetaClass.getMetaMethods()) {
        String name = metaMethod.getName();
        String methodEnd = "(";
        if (metaMethod.isValidMethod(new Class[] {Closure.class})) methodEnd = "{";
        else if (metaMethod.getParameterTypes().length == 0) methodEnd = "()";
        if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) {
          StringBuilder buf = new StringBuilder();
          buf.append("Workspace meta method ")
              .append(YELLOW)
              .append(metaMethod.getName())
              .append(RESET);
          buf.append(" returns ").append(AQUA).append(metaMethod.getReturnType().getName());
          buf.append(RESET).append('\n');
          Class[] types = metaMethod.getNativeParameterTypes();
          buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n');
          for (Class type : types)
            buf.append(AQUA).append(type.getName()).append(RESET).append('\n');
          buf.deleteCharAt(buf.length() - 1);
          caller.sendPrintMessage(buf, source);
        }
      }
      for (Method method : CallerScript.class.getMethods()) {
        String name = method.getName();
        String methodEnd = "(";
        Class<?>[] params = method.getParameterTypes();
        if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{";
        else if (params.length == 0) methodEnd = "()";
        if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) {
          StringBuilder buf = new StringBuilder();
          buf.append("Script method ").append(YELLOW).append(method.getName()).append(RESET);
          buf.append(" returns ").append(AQUA).append(method.getReturnType().getName());
          buf.append(RESET).append('\n');
          buf.append("arguments: ").append(YELLOW).append(params.length).append(RESET).append('\n');
          for (Class<?> type : params)
            buf.append(AQUA).append(type.getName()).append(RESET).append('\n');
          buf.deleteCharAt(buf.length() - 1);
          caller.sendPrintMessage(buf, source);
        }
        int args = params.length;
        if ((name.startsWith("get") && args == 0 || name.startsWith("set") && args == 1)
            && name.length() > 3) {
          String propertyName = getPropertyName(name);
          if (propertyName != null && propertyName.equals(firstToken)) {
            caller.sendPrintMessage(
                String.format(
                    "Script getter %s returns %s",
                    YELLOW + name + "()" + RESET, AQUA + method.getReturnType().getName() + RESET),
                source);
          }
        }
      }
      for (Method method : Workspace.class.getMethods()) {
        String name = method.getName();
        String methodEnd = "(";
        Class<?>[] params = method.getParameterTypes();
        if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{";
        else if (params.length == 0) methodEnd = "()";
        if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) {
          StringBuilder buf = new StringBuilder();
          buf.append("Workspace method ").append(YELLOW).append(method.getName()).append(RESET);
          buf.append(" returns ").append(AQUA).append(method.getReturnType().getName());
          buf.append(RESET).append('\n');
          buf.append("arguments: ").append(YELLOW).append(params.length).append(RESET).append('\n');
          for (Class<?> type : params)
            buf.append(AQUA).append(type.getName()).append(RESET).append('\n');
          buf.deleteCharAt(buf.length() - 1);
          caller.sendPrintMessage(buf, source);
        }
      }
      if (workspaceVars != null) {
        Object result = workspaceVars.get(firstToken);
        if (result != null || workspaceVars.containsKey(firstToken)) {
          caller.sendPrintMessage(
              String.format(
                  "Workspace variable %s: %s",
                  YELLOW + firstToken + RESET,
                  AQUA + (result == null ? "null" : result.getClass().getName()) + RESET),
              source);
          return;
        }
      }
      if (globalVars != null) {
        Object result = globalVars.get(firstToken);
        if (result != null || globalVars.containsKey(firstToken)) {
          caller.sendPrintMessage(
              String.format(
                  "Workspace variable %s: %s",
                  YELLOW + firstToken + RESET,
                  AQUA + (result == null ? "null" : result.getClass().getName()) + RESET),
              source);
          return;
        }
      }
      for (GroovyObject modifier : CallerScript.getDynamicModifiers()) {
        Object[] params = {properties};
        try {
          Map<?, ?> map =
              (Map) modifier.getMetaClass().invokeMethod(modifier, "getPropertyMapFor", params);
          Object result = map.get(firstToken);
          if (result != null || map.containsKey(firstToken)) {
            Class resultClass = result instanceof Class ? (Class) result : null;
            caller.sendPrintMessage(
                String.format(
                    "Dynamic variable %s: %s",
                    YELLOW + firstToken + RESET,
                    AQUA + (resultClass == null ? "unknown type" : resultClass.getName()) + RESET),
                source);
          }
        } catch (Exception ignored) {
        }
        try {
          Map<?, ?> map =
              (Map) modifier.getMetaClass().invokeMethod(modifier, "getMethodMapFor", params);
          String funToken = firstToken;
          if (funToken.endsWith("(")) funToken = firstToken.substring(0, funToken.length() - 1);
          Object result = map.get(funToken);
          if (result != null || map.containsKey(funToken)) {
            Class resultClass = result instanceof Class ? (Class) result : null;
            caller.sendPrintMessage(
                String.format(
                    "Dynamic function %s: %s",
                    YELLOW + firstToken + RESET,
                    AQUA + (resultClass == null ? "unknown type" : resultClass.getName()) + RESET),
                source);
          }
        } catch (Exception ignored) {
        }
      }
      return;
    }

    MetaClass metaClass =
        getFirstTokenMeta(
            caller,
            firstToken,
            caller.getSender(),
            service,
            callerScriptMetaClass,
            workspaceMetaClass,
            workspace,
            workspaceVars,
            globalVars,
            properties);
    boolean classHook =
        tokens.size() <= 1 && service.getImportTabCompleteClasses().containsKey(firstToken);

    metaClass = skipTokens(tokens, metaClass);
    if (metaClass == null) return;

    // select property or method of last metaclass
    String token = tokens.pollFirst();
    Class theClass = metaClass.getTheClass();
    MetaProperty metaProperty = metaClass.getMetaProperty(token);
    if (metaProperty != null) {
      caller.sendPrintMessage(
          String.format(
              "Meta property %s: %s",
              YELLOW + token + RESET, AQUA + metaProperty.getType().getName() + RESET),
          source);
    }
    for (MetaMethod metaMethod : metaClass.getMetaMethods()) {
      String name = metaMethod.getName();
      String methodEnd = "(";
      Class<?>[] params = metaMethod.getNativeParameterTypes();
      if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{";
      else if (params.length == 0) methodEnd = "()";
      if (token.equals(name) || token.equals(name + methodEnd)) {
        StringBuilder buf = new StringBuilder();
        buf.append("Meta method ").append(YELLOW).append(metaMethod.getName()).append(RESET);
        buf.append(" returns ").append(AQUA).append(metaMethod.getReturnType().getName());
        buf.append(RESET).append('\n');
        Class[] types = metaMethod.getNativeParameterTypes();
        buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n');
        for (Class type : types) buf.append(AQUA).append(type.getName()).append(RESET).append('\n');
        buf.deleteCharAt(buf.length() - 1);
        caller.sendPrintMessage(buf, source);
      }
      int args = params.length;
      if (name.startsWith("get") && args == 0 && name.length() > 3) {
        String propertyName = getPropertyName(name);
        if (propertyName != null && propertyName.equals(token)) {
          caller.sendPrintMessage(
              String.format(
                  "Meta getter %s returns %s",
                  YELLOW + name + "()" + RESET,
                  AQUA + metaMethod.getReturnType().getName() + RESET),
              source);
        }
      }
    }
    for (Method method : theClass.getMethods()) {
      String name = method.getName();
      String methodEnd = "(";
      Class<?>[] params = method.getParameterTypes();
      if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{";
      else if (params.length == 0) methodEnd = "()";
      if (token.equals(name) || token.equals(name + methodEnd)) {
        StringBuilder buf = new StringBuilder();
        buf.append("Method ").append(YELLOW).append(method.getName()).append(RESET);
        buf.append(" returns ").append(AQUA).append(method.getReturnType().getName());
        buf.append(RESET).append('\n');
        Class[] types = method.getParameterTypes();
        buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n');
        for (Class type : types) buf.append(AQUA).append(type.getName()).append(RESET).append('\n');
        buf.deleteCharAt(buf.length() - 1);
        caller.sendPrintMessage(buf, source);
      }
      int args = params.length;
      if (name.startsWith("get") && args == 0 && name.length() > 3) {
        String propertyName = getPropertyName(name);
        if (propertyName != null && propertyName.equals(token)) {
          caller.sendPrintMessage(
              String.format(
                  "Getter %s returns %s",
                  YELLOW + name + "()" + RESET, AQUA + method.getReturnType().getName() + RESET),
              source);
        }
      }
    }
    if (Enum.class.isAssignableFrom(theClass)) {
      Enum[] enumValues = getEnumValues(theClass);
      if (enumValues != null)
        for (Enum anEnum : enumValues) {
          String name = anEnum.name();
          if (name.equals(token)) {
            caller.sendPrintMessage(
                String.format(
                    "Enum value %s: %s", YELLOW + name + RESET, AQUA + theClass.getName() + RESET),
                source);
          }
        }
    }
    if (classHook) {
      MetaProperty property = InvokerHelper.getMetaClass(Class.class).getMetaProperty(token);
      if (property != null) {
        caller.sendPrintMessage(
            String.format(
                "Meta property %s: %s",
                YELLOW + token + RESET, AQUA + property.getType().getName() + RESET),
            source);
      }
      for (MetaMethod metaMethod : InvokerHelper.getMetaClass(Class.class).getMetaMethods()) {
        String name = metaMethod.getName();
        String methodEnd = "(";
        Class<?>[] params = metaMethod.getNativeParameterTypes();
        if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{";
        else if (params.length == 0) methodEnd = "()";
        if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) {
          StringBuilder buf = new StringBuilder();
          buf.append("Method ").append(YELLOW).append(metaMethod.getName()).append(RESET);
          buf.append(" returns ").append(AQUA).append(metaMethod.getReturnType().getName());
          buf.append(RESET).append('\n');
          Class[] types = metaMethod.getNativeParameterTypes();
          buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n');
          for (Class type : types)
            buf.append(AQUA).append(type.getName()).append(RESET).append('\n');
          buf.deleteCharAt(buf.length() - 1);
          caller.sendPrintMessage(buf, source);
        }
      }
      for (Method method : Class.class.getMethods()) {
        String name = method.getName();
        String methodEnd = "(";
        Class<?>[] params = method.getParameterTypes();
        if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{";
        else if (params.length == 0) methodEnd = "()";
        if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) {
          StringBuilder buf = new StringBuilder();
          buf.append("Method ").append(YELLOW).append(method.getName()).append(RESET);
          buf.append(" returns ").append(AQUA).append(method.getReturnType().getName());
          buf.append(RESET).append('\n');
          Class[] types = method.getParameterTypes();
          buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n');
          for (Class type : types)
            buf.append(AQUA).append(type.getName()).append(RESET).append('\n');
          buf.deleteCharAt(buf.length() - 1);
          caller.sendPrintMessage(buf, source);
        }
      }
    }
  }
示例#2
0
  public <T> Class<? extends T> generate(Class<T> type) {
    Map<Class, Class> cache = GENERATED_CLASSES.get(getClass());
    if (cache == null) {
      cache = new HashMap<Class, Class>();
      GENERATED_CLASSES.put(getClass(), cache);
    }
    Class generatedClass = cache.get(type);
    if (generatedClass != null) {
      return generatedClass;
    }

    if (Modifier.isPrivate(type.getModifiers())) {
      throw new GradleException(
          String.format(
              "Cannot create a proxy class for private class '%s'.", type.getSimpleName()));
    }
    if (Modifier.isAbstract(type.getModifiers())) {
      throw new GradleException(
          String.format(
              "Cannot create a proxy class for abstract class '%s'.", type.getSimpleName()));
    }

    Class<? extends T> subclass;
    try {
      ClassBuilder<T> builder = start(type);

      boolean isConventionAware = type.getAnnotation(NoConventionMapping.class) == null;
      boolean isDynamicAware = type.getAnnotation(NoDynamicObject.class) == null;

      builder.startClass(isConventionAware, isDynamicAware);

      if (isDynamicAware && !DynamicObjectAware.class.isAssignableFrom(type)) {
        builder.mixInDynamicAware();
      }
      if (isDynamicAware && !GroovyObject.class.isAssignableFrom(type)) {
        builder.mixInGroovyObject();
      }
      if (isDynamicAware) {
        builder.addDynamicMethods();
      }
      if (isConventionAware && !IConventionAware.class.isAssignableFrom(type)) {
        builder.mixInConventionAware();
      }

      Class noMappingClass = Object.class;
      for (Class<?> c = type; c != null && noMappingClass == Object.class; c = c.getSuperclass()) {
        if (c.getAnnotation(NoConventionMapping.class) != null) {
          noMappingClass = c;
        }
      }

      Collection<String> skipProperties =
          Arrays.asList("metaClass", "conventionMapping", "convention", "asDynamicObject");

      MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(type);
      for (MetaProperty property : metaClass.getProperties()) {
        if (skipProperties.contains(property.getName())) {
          continue;
        }
        if (property instanceof MetaBeanProperty) {
          MetaBeanProperty metaBeanProperty = (MetaBeanProperty) property;
          MetaMethod getter = metaBeanProperty.getGetter();
          if (getter == null) {
            continue;
          }
          if (Modifier.isFinal(getter.getModifiers())
              || Modifier.isPrivate(getter.getModifiers())) {
            continue;
          }
          if (getter.getReturnType().isPrimitive()) {
            continue;
          }
          Class declaringClass = getter.getDeclaringClass().getTheClass();
          if (declaringClass.isAssignableFrom(noMappingClass)) {
            continue;
          }
          builder.addGetter(metaBeanProperty);

          MetaMethod setter = metaBeanProperty.getSetter();
          if (setter == null) {
            continue;
          }
          if (Modifier.isFinal(setter.getModifiers())
              || Modifier.isPrivate(setter.getModifiers())) {
            continue;
          }

          builder.addSetter(metaBeanProperty);
        }
      }

      for (Constructor<?> constructor : type.getConstructors()) {
        if (Modifier.isPublic(constructor.getModifiers())) {
          builder.addConstructor(constructor);
        }
      }

      subclass = builder.generate();
    } catch (Throwable e) {
      throw new GradleException(
          String.format("Could not generate a proxy class for class %s.", type.getName()), e);
    }

    cache.put(type, subclass);
    return subclass;
  }