java/com/googlecode/prolog_cafe/lang/PrologClassLoader.java [17:204]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public class PrologClassLoader extends ClassLoader {
  private final ConcurrentHashMap<Key, CacheEntry> predicateCache =
      new ConcurrentHashMap<>();

  /** Initialize using the {@link ClassLoader#getSystemClassLoader()}. */
  public PrologClassLoader() {
  }

  /**
   * Initialize using a specific parent ClassLoader.
   *
   * @param parent source for all predicates in this context.
   */
  public PrologClassLoader(ClassLoader parent) {
    super(parent);
  }

  /**
   * Check whether the predicate class for the given arguments is defined.
   *
   * @param pkg package name
   * @param functor predicate name
   * @param arity predicate arity
   * @return <code>true</code> if the predicate <code>pkg:functor/arity</code>
   *         is defined, otherwise <code>false</code>.
   */
  public boolean definedPredicate(String pkg, String functor, int arity) {
    try {
      return findPredicate(pkg, functor, arity) instanceof ValidPredicate;
    } catch (ClassNotFoundException cnfe) {
      return false;
    }
  }

  /**
   * Allocate a predicate and configure it with the specified arguments.
   *
   * @param pkg package the predicate is in.
   * @param functor name of the predicate.
   * @param args arguments to pass. The arity is derived from the arguments.
   * @return the predicate encapsulating the logic and the arguments.
   */
  public Predicate predicate(String pkg, String functor, Term... args) {
    return predicate(pkg, functor, Success.SUCCESS, args);
  }

  /**
   * Allocate a predicate and configure it with the specified arguments.
   *
   * @param pkg package the predicate is in.
   * @param functor name of the predicate.
   * @param cont operation to execute if the predicate is successful. Usually
   *        this is {@link Success#SUCCESS}.
   * @param args arguments to pass. The arity is derived from the arguments.
   * @return the predicate encapsulating the logic and the arguments.
   */
  public Predicate predicate(String pkg, String functor, Operation cont, Term... args) {
    int arity = args.length;
    try {
      CacheEntry ent = findPredicate(pkg, functor, arity);
      if (ent instanceof ValidPredicate) {
        Object[] a = new Object[arity + 1];
        for (int i = 0; i < arity; i++)
          a[i] = args[i];
        a[arity] = cont;
        return ((ValidPredicate) ent).constructor.newInstance(a);
      }
    } catch (Exception cause) {
      ExistenceException err2 = new ExistenceException(
          "procedure",
          term(pkg, functor, arity),
          cause.toString());
      err2.initCause(cause);
      throw err2;
    }
    throw new ExistenceException("procedure", term(pkg, functor, arity), "NOT_FOUND");
  }

  private static StructureTerm term(String pkg, String functor, int arity) {
    return new StructureTerm(":",
      SymbolTerm.create(pkg),
      new StructureTerm("/",
        SymbolTerm.create(functor),
        new IntegerTerm(arity)));
  }

  private CacheEntry findPredicate(String pkg, String functor, int arity)
      throws ClassNotFoundException {
    Key key = new Key(pkg, functor, arity);
    CacheEntry entry = predicateCache.get(key);
    if (entry == null) {
      Class<?> clazz;
      try {
        clazz = Class.forName(
            encode(pkg, functor, arity),
            false /* avoid resolve */,
            this);
      } catch (ClassNotFoundException cnfe) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw cnfe;
      }

      if (!Predicate.class.isAssignableFrom(clazz)) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException(clazz.getName(),
          new ClassCastException("Does not extend " + Predicate.class));
      }

      Class<?>[] params = new Class[arity + 1];
      for (int i = 0; i < arity; i++)
        params[i] = Term.class;
      params[arity] = Operation.class;

      Constructor<Predicate> cons;
      try {
        cons = (Constructor<Predicate>) clazz.getDeclaredConstructor(params);
      } catch (NoSuchMethodException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Wrong constructor on " + clazz.getName(), e);

      } catch (SecurityException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Constructor not visible " + clazz.getName(), e);
      }
      cons.setAccessible(true);

      try {
        Class.forName(clazz.getName(), true /* resolve now */, this);
      } catch (ClassNotFoundException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);

      } catch (RuntimeException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);

      } catch (LinkageError e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);
      }

      entry = new ValidPredicate(cons);
      predicateCache.put(key, entry);
    }
    return entry;
  }

  private static final class Key {
    final String pkg;
    final String functor;
    final int arity;

    Key(String pkg, String functor, int arity) {
      this.pkg = pkg;
      this.functor = functor;
      this.arity = arity;
    }

    @Override
    public int hashCode() {
      int h = pkg.hashCode();
      h = (h * 31) + functor.hashCode();
      h = (h * 31) + arity;
      return h;
    }

    @Override
    public boolean equals(Object other) {
      if (other instanceof Key) {
        Key b = (Key) other;
        return arity == b.arity && pkg.equals(b.pkg) && functor.equals(b.functor);
      }
      return false;
    }
  }

  private static abstract class CacheEntry {
  }

  private static class NotFound extends CacheEntry {
    static final NotFound INSTANCE = new NotFound();
  }

  private static class ValidPredicate extends CacheEntry {
    final Constructor<Predicate> constructor;

    ValidPredicate(Constructor<Predicate> c) {
      constructor = c;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



src/lang/PrologClassLoader.java [17:204]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public class PrologClassLoader extends ClassLoader {
  private final ConcurrentHashMap<Key, CacheEntry> predicateCache =
      new ConcurrentHashMap<>();

  /** Initialize using the {@link ClassLoader#getSystemClassLoader()}. */
  public PrologClassLoader() {
  }

  /**
   * Initialize using a specific parent ClassLoader.
   *
   * @param parent source for all predicates in this context.
   */
  public PrologClassLoader(ClassLoader parent) {
    super(parent);
  }

  /**
   * Check whether the predicate class for the given arguments is defined.
   *
   * @param pkg package name
   * @param functor predicate name
   * @param arity predicate arity
   * @return <code>true</code> if the predicate <code>pkg:functor/arity</code>
   *         is defined, otherwise <code>false</code>.
   */
  public boolean definedPredicate(String pkg, String functor, int arity) {
    try {
      return findPredicate(pkg, functor, arity) instanceof ValidPredicate;
    } catch (ClassNotFoundException cnfe) {
      return false;
    }
  }

  /**
   * Allocate a predicate and configure it with the specified arguments.
   *
   * @param pkg package the predicate is in.
   * @param functor name of the predicate.
   * @param args arguments to pass. The arity is derived from the arguments.
   * @return the predicate encapsulating the logic and the arguments.
   */
  public Predicate predicate(String pkg, String functor, Term... args) {
    return predicate(pkg, functor, Success.SUCCESS, args);
  }

  /**
   * Allocate a predicate and configure it with the specified arguments.
   *
   * @param pkg package the predicate is in.
   * @param functor name of the predicate.
   * @param cont operation to execute if the predicate is successful. Usually
   *        this is {@link Success#SUCCESS}.
   * @param args arguments to pass. The arity is derived from the arguments.
   * @return the predicate encapsulating the logic and the arguments.
   */
  public Predicate predicate(String pkg, String functor, Operation cont, Term... args) {
    int arity = args.length;
    try {
      CacheEntry ent = findPredicate(pkg, functor, arity);
      if (ent instanceof ValidPredicate) {
        Object[] a = new Object[arity + 1];
        for (int i = 0; i < arity; i++)
          a[i] = args[i];
        a[arity] = cont;
        return ((ValidPredicate) ent).constructor.newInstance(a);
      }
    } catch (Exception cause) {
      ExistenceException err2 = new ExistenceException(
          "procedure",
          term(pkg, functor, arity),
          cause.toString());
      err2.initCause(cause);
      throw err2;
    }
    throw new ExistenceException("procedure", term(pkg, functor, arity), "NOT_FOUND");
  }

  private static StructureTerm term(String pkg, String functor, int arity) {
    return new StructureTerm(":",
      SymbolTerm.create(pkg),
      new StructureTerm("/",
        SymbolTerm.create(functor),
        new IntegerTerm(arity)));
  }

  private CacheEntry findPredicate(String pkg, String functor, int arity)
      throws ClassNotFoundException {
    Key key = new Key(pkg, functor, arity);
    CacheEntry entry = predicateCache.get(key);
    if (entry == null) {
      Class<?> clazz;
      try {
        clazz = Class.forName(
            encode(pkg, functor, arity),
            false /* avoid resolve */,
            this);
      } catch (ClassNotFoundException cnfe) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw cnfe;
      }

      if (!Predicate.class.isAssignableFrom(clazz)) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException(clazz.getName(),
          new ClassCastException("Does not extend " + Predicate.class));
      }

      Class<?>[] params = new Class[arity + 1];
      for (int i = 0; i < arity; i++)
        params[i] = Term.class;
      params[arity] = Operation.class;

      Constructor<Predicate> cons;
      try {
        cons = (Constructor<Predicate>) clazz.getDeclaredConstructor(params);
      } catch (NoSuchMethodException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Wrong constructor on " + clazz.getName(), e);

      } catch (SecurityException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Constructor not visible " + clazz.getName(), e);
      }
      cons.setAccessible(true);

      try {
        Class.forName(clazz.getName(), true /* resolve now */, this);
      } catch (ClassNotFoundException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);

      } catch (RuntimeException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);

      } catch (LinkageError e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);
      }

      entry = new ValidPredicate(cons);
      predicateCache.put(key, entry);
    }
    return entry;
  }

  private static final class Key {
    final String pkg;
    final String functor;
    final int arity;

    Key(String pkg, String functor, int arity) {
      this.pkg = pkg;
      this.functor = functor;
      this.arity = arity;
    }

    @Override
    public int hashCode() {
      int h = pkg.hashCode();
      h = (h * 31) + functor.hashCode();
      h = (h * 31) + arity;
      return h;
    }

    @Override
    public boolean equals(Object other) {
      if (other instanceof Key) {
        Key b = (Key) other;
        return arity == b.arity && pkg.equals(b.pkg) && functor.equals(b.functor);
      }
      return false;
    }
  }

  private static abstract class CacheEntry {
  }

  private static class NotFound extends CacheEntry {
    static final NotFound INSTANCE = new NotFound();
  }

  private static class ValidPredicate extends CacheEntry {
    final Constructor<Predicate> constructor;

    ValidPredicate(Constructor<Predicate> c) {
      constructor = c;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



