Пример #1
0
  public static int getArrayDimensions(final MetaClass type) {
    if (!type.isArray()) return 0;

    final String internalName = type.getInternalName();
    for (int i = 0; i < internalName.length(); i++) {
      if (internalName.charAt(i) != '[') return i;
    }
    return 0;
  }
Пример #2
0
  public static int scoreMethods(
      final MetaClass[] arguments, final MetaParameter[] parmTypes, final boolean isVarArgs) {
    int score = 0;
    for (int i = 0; i != arguments.length; i++) {
      final MetaClass actualParamType;
      if (isVarArgs && !arguments[arguments.length - 1].isArray() && i >= parmTypes.length - 1)
        actualParamType = parmTypes[parmTypes.length - 1].getType().getComponentType();
      else actualParamType = parmTypes[i].getType();

      if (arguments[i] == null) {
        if (!actualParamType.isPrimitive()) {
          score += 6;
        } else {
          score = 0;
          break;
        }
      } else if (actualParamType.equals(arguments[i])) {
        score += 7;
      } else if (actualParamType.isPrimitive() && actualParamType.asBoxed().equals(arguments[i])) {
        score += 6;
      } else if (arguments[i].isPrimitive() && arguments[i].asUnboxed().equals(actualParamType)) {
        score += 6;
      } else if (actualParamType.isAssignableFrom(arguments[i])) {
        score += 5;
      } else if (isNumericallyCoercible(arguments[i], actualParamType)) {
        score += 4;
      } else if (actualParamType.asBoxed().isAssignableFrom(arguments[i].asBoxed())
          && !Object_MetaClass.equals(arguments[i])) {
        score += 3 + scoreInterface(actualParamType, arguments[i]);
      } else if (canConvert(actualParamType, arguments[i])) {
        if (actualParamType.isArray() && arguments[i].isArray()) {
          final MetaClass outerComponentTypeActual = actualParamType.getOuterComponentType();
          final MetaClass outerComponentTypeArg = arguments[i].getOuterComponentType();

          if (canConvert(outerComponentTypeActual, outerComponentTypeArg)) {
            score += 1;
          } else {
            continue;
          }
        } else if (actualParamType.equals(char_MetaClass)
            && arguments[i].equals(String_MetaClass)) {
          score += 1;
        }

        score += 1;
      } else if (actualParamType.equals(Object_MetaClass)
          || arguments[i].equals(NullType_MetaClass)) {
        score += 1;
      } else {
        score = 0;
        break;
      }
    }
    return score;
  }
Пример #3
0
  public static void assertAssignableTypes(
      final Context context, final MetaClass from, final MetaClass to) {
    if (!to.asBoxed().isAssignableFrom(from.asBoxed())) {
      if (to.isArray()
          && from.isArray()
          && GenUtil.getArrayDimensions(to) == GenUtil.getArrayDimensions(from)
          && to.getOuterComponentType().isAssignableFrom(from.getOuterComponentType())) {
        return;
      }

      if (!context.isPermissiveMode()) {
        if (classAliases.contains(from.getFullyQualifiedName())
            && classAliases.contains(to.getFullyQualifiedName())) {
          // handle convertibility between MetaClass API and java Class reference.
          return;
        }

        throw new InvalidTypeException(
            to.getFullyQualifiedName() + " is not assignable from " + from.getFullyQualifiedName());
      }
    }
  }
Пример #4
0
  public static ReachableTypes getAllReachableClasses(final GeneratorContext context) {
    if (System.getProperty(SYSPROP_USE_REACHABILITY_ANALYSIS) == null
        || !Boolean.getBoolean(SYSPROP_USE_REACHABILITY_ANALYSIS)) {

      log.warn("reachability analysis disabled. errai may generate unnecessary code.");
      log.warn(
          "enable reachability analysis with -D" + SYSPROP_USE_REACHABILITY_ANALYSIS + "=true");
      return ReachableTypes.EVERYTHING_REACHABLE_INSTANCE;
    }

    ReachabilityCache cache;
    if (reachabilityCache == null || (cache = reachabilityCache.get()) == null) {
      reachabilityCache = new SoftReference<ReachabilityCache>(cache = new ReachabilityCache());
    }

    if (cache.isCacheValid(context)) {
      return cache.getCache(context);
    }

    final EnvironmentConfig config = getEnvironmentConfig();

    long time = System.currentTimeMillis();

    final Set<String> packages = new HashSet<String>();

    if (isJUnitTest()) {
      packages.addAll(RebindUtils.findTranslatablePackagesInModule(context));
    } else {
      packages.addAll(RebindUtils.getOuterTranslatablePackages(context));
    }

    class Reachability {
      private final Set<String> packages;
      private final Set<String> negativeHits = new HashSet<String>();

      Reachability(final Set<String> packages) {
        this.packages = new HashSet<String>(packages);
      }

      public boolean isReachablePackage(final String pkg) {
        if (pkg == null || packages.contains(pkg)) {
          return true;
        }
        if (negativeHits.contains(pkg)) {
          return false;
        }

        for (final String p : packages) {
          if (pkg.startsWith(p)) {
            packages.add(pkg);
            return true;
          }
        }

        negativeHits.add(pkg);
        return false;
      }
    }

    final Set<String> allDependencies =
        Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(100));
    final Collection<MetaClass> allCachedClasses = MetaClassFactory.getAllCachedClasses();
    final ClassLoader classLoader = EnvUtil.class.getClassLoader();

    final ExecutorService executor =
        Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    final Reachability reachability = new Reachability(packages);

    try {
      for (final MetaClass mc : allCachedClasses) {
        String fullyQualifiedName = mc.getFullyQualifiedName();
        int splitPoint;
        while ((splitPoint = fullyQualifiedName.lastIndexOf('$')) != -1) {
          fullyQualifiedName = fullyQualifiedName.substring(0, splitPoint);
        }

        if (mc.isPrimitive() || mc.isArray()) {
          continue;
        } else if (isReachabilityExcluded(mc.getPackageName())) {
          continue;
        } else if (!config.getExplicitTypes().contains(fullyQualifiedName)
            && !reachability.isReachablePackage(mc.getPackageName())) {
          continue;
        }

        final URL resource =
            classLoader.getResource(fullyQualifiedName.replaceAll("\\.", "/") + ".java");

        if (resource != null) {
          InputStream stream = null;
          try {
            stream = new BufferedInputStream(resource.openStream());
            final byte[] readBuffer = new byte[stream.available()];
            stream.read(readBuffer);

            if (log.isDebugEnabled()) {
              log.debug("scanning " + fullyQualifiedName + " for reachable types ...");
            }
            executor.execute(new ReachabilityRunnable(readBuffer, allDependencies));
          } catch (IOException e) {
            log.warn("could not open resource: " + resource.getFile());
          } finally {
            if (stream != null) {
              stream.close();
            }
          }
        } else {
          log.warn("source for " + fullyQualifiedName + " is missing.");
        }
      }
    } catch (Throwable e) {
      e.printStackTrace();
    }

    try {
      executor.shutdown();
      executor.awaitTermination(60, TimeUnit.MINUTES);
    } catch (InterruptedException e) {
      log.warn("the reachability analysis was interrupted", e);
      cache.putCache(context, ReachableTypes.EVERYTHING_REACHABLE_INSTANCE);
      return ReachableTypes.EVERYTHING_REACHABLE_INSTANCE;
    }

    if (log.isDebugEnabled()) {
      log.debug("*** REACHABILITY ANALYSIS (production mode: " + EnvUtil.isProdMode() + ") ***");
      for (final String s : allDependencies) {
        log.debug(" -> " + s);
      }

      time = System.currentTimeMillis() - time;

      log.debug("*** END OF REACHABILITY ANALYSIS (" + time + "ms) *** ");
    }

    final ReachableTypes reachableTypes = new ReachableTypes(allDependencies, true);
    cache.putCache(context, reachableTypes);
    return reachableTypes;
  }