예제 #1
1
  /**
   * reads all methods by the action-annotations for building agent-actions
   *
   * @param p_class class
   * @param p_root root class
   * @return stream of all methods with inheritance
   */
  private static Stream<Method> methods(final Class<?> p_class, final Class<?> p_root) {
    final Pair<Boolean, IAgentAction.EAccess> l_classannotation = CCommon.isActionClass(p_class);
    if (!l_classannotation.getLeft())
      return p_class.getSuperclass() == null
          ? Stream.of()
          : methods(p_class.getSuperclass(), p_root);

    final Predicate<Method> l_filter =
        IAgentAction.EAccess.WHITELIST.equals(l_classannotation.getRight())
            ? i -> !CCommon.isActionFiltered(i, p_root)
            : i -> CCommon.isActionFiltered(i, p_root);

    return Stream.concat(
        Arrays.stream(p_class.getDeclaredMethods())
            .parallel()
            .map(
                i -> {
                  i.setAccessible(true);
                  return i;
                })
            .filter(i -> !Modifier.isAbstract(i.getModifiers()))
            .filter(i -> !Modifier.isInterface(i.getModifiers()))
            .filter(i -> !Modifier.isNative(i.getModifiers()))
            .filter(i -> !Modifier.isStatic(i.getModifiers()))
            .filter(l_filter),
        methods(p_class.getSuperclass(), p_root));
  }
예제 #2
0
  /**
   * checks if an action is usable
   *
   * @param p_action action object
   * @return boolean usable flag
   */
  private static boolean actionusable(final IAction p_action) {
    if ((p_action.name() == null)
        || (p_action.name().isEmpty())
        || (p_action.name().get(0).trim().isEmpty())) {
      LOGGER.warning(CCommon.languagestring(CCommon.class, "actionnameempty"));
      return false;
    }

    if (!Character.isLetter(p_action.name().get(0).charAt(0))) {
      LOGGER.warning(CCommon.languagestring(CCommon.class, "actionletter", p_action));
      return false;
    }

    if (!Character.isLowerCase(p_action.name().get(0).charAt(0))) {
      LOGGER.warning(CCommon.languagestring(CCommon.class, "actionlowercase", p_action));
      return false;
    }

    if (p_action.minimalArgumentNumber() < 0) {
      LOGGER.warning(CCommon.languagestring(CCommon.class, "actionargumentsnumber", p_action));
      return false;
    }

    return true;
  }
예제 #3
0
  /**
   * returns actions by a class
   *
   * @note class must be an inheritance of the IAgent interface
   * @param p_class class list
   * @return action stream
   */
  @SuppressWarnings("unchecked")
  public static Stream<IAction> actionsFromAgentClass(final Class<?>... p_class) {
    return p_class == null || p_class.length == 0
        ? Stream.of()
        : Arrays.stream(p_class)
            .parallel()
            .filter(IAgent.class::isAssignableFrom)
            .flatMap(i -> CCommon.methods(i, i))
            .map(
                i -> {
                  try {
                    return (IAction) new CMethodAction(i);
                  } catch (final IllegalAccessException l_exception) {
                    LOGGER.warning(
                        CCommon.languagestring(CCommon.class, "actioninstantiate", i, l_exception));
                    return null;
                  }
                })

            // action can be instantiate
            .filter(Objects::nonNull)

            // check usable action name
            .filter(CCommon::actionusable);
  }
예제 #4
0
    /**
     * creates a compression stream
     *
     * @param p_datastream data-counting stream
     * @return compression output stream
     * @throws IOException throws on any io error
     */
    public final OutputStream get(final DataOutputStream p_datastream) throws IOException {
      switch (this) {
        case BZIP:
          return new BZip2CompressorOutputStream(p_datastream);

        case GZIP:
          return new GzipCompressorOutputStream(p_datastream);

        case DEFLATE:
          return new DeflateCompressorOutputStream(p_datastream);

        case PACK200:
          return new Pack200CompressorOutputStream(p_datastream);

        case XZ:
          return new XZCompressorOutputStream(p_datastream);

        default:
          throw new CIllegalStateException(CCommon.languagestring(this, "unknown", this));
      }
    }
예제 #5
0
  /**
   * get all classes within an Java package as action
   *
   * @param p_package full-qualified package name or empty for default package
   * @return action stream
   */
  @SuppressWarnings("unchecked")
  public static Stream<IAction> actionsFromPackage(final String... p_package) {
    return ((p_package == null) || (p_package.length == 0)
            ? Stream.of(MessageFormat.format("{0}.{1}", PACKAGEROOT, "action.buildin"))
            : Arrays.stream(p_package))
        .flatMap(
            j -> {
              try {
                return ClassPath.from(Thread.currentThread().getContextClassLoader())
                    .getTopLevelClassesRecursive(j)
                    .parallelStream()
                    .map(ClassPath.ClassInfo::load)
                    .filter(i -> !Modifier.isAbstract(i.getModifiers()))
                    .filter(i -> !Modifier.isInterface(i.getModifiers()))
                    .filter(i -> Modifier.isPublic(i.getModifiers()))
                    .filter(IAction.class::isAssignableFrom)
                    .map(
                        i -> {
                          try {
                            return (IAction) i.newInstance();
                          } catch (final IllegalAccessException
                              | InstantiationException l_exception) {
                            LOGGER.warning(
                                CCommon.languagestring(
                                    CCommon.class, "actioninstantiate", i, l_exception));
                            return null;
                          }
                        })

                    // action can be instantiate
                    .filter(Objects::nonNull)

                    // check usable action name
                    .filter(CCommon::actionusable);
              } catch (final IOException l_exception) {
                throw new UncheckedIOException(l_exception);
              }
            });
  }
예제 #6
0
/** class for any helper calls */
public final class CCommon {
  /** package name */
  public static final String PACKAGEROOT = "org.lightjason.agentspeak";
  /** logger */
  private static final Logger LOGGER = CCommon.logger(CCommon.class);
  /** language resource bundle */
  private static final ResourceBundle LANGUAGE =
      ResourceBundle.getBundle(
          MessageFormat.format("{0}.{1}", PACKAGEROOT, "language"),
          Locale.getDefault(),
          new CUTF8Control());
  /** properties of the package */
  private static final ResourceBundle PROPERTIES =
      ResourceBundle.getBundle(
          MessageFormat.format("{0}.{1}", PACKAGEROOT, "configuration"),
          Locale.getDefault(),
          new CUTF8Control());

  /** private ctor - avoid instantiation */
  private CCommon() {}

  /**
   * returns a logger instance
   *
   * @param p_class class type
   * @return logger
   */
  public static Logger logger(final Class<?> p_class) {
    return Logger.getLogger(p_class.getName());
  }

  /**
   * list of usable languages
   *
   * @return list of language pattern
   */
  public static String[] languages() {
    return Arrays.stream(PROPERTIES.getString("translation").split(","))
        .map(i -> i.trim().toLowerCase())
        .toArray(String[]::new);
  }

  /**
   * returns the language bundle
   *
   * @return bundle
   */
  public static ResourceBundle languagebundle() {
    return LANGUAGE;
  }

  /**
   * returns the property data of the package
   *
   * @return bundle object
   */
  public static ResourceBundle configuration() {
    return PROPERTIES;
  }

  // ---------------------------------------------------------------------------------------------------------------------------------------------------------

  /**
   * get all classes within an Java package as action
   *
   * @param p_package full-qualified package name or empty for default package
   * @return action stream
   */
  @SuppressWarnings("unchecked")
  public static Stream<IAction> actionsFromPackage(final String... p_package) {
    return ((p_package == null) || (p_package.length == 0)
            ? Stream.of(MessageFormat.format("{0}.{1}", PACKAGEROOT, "action.buildin"))
            : Arrays.stream(p_package))
        .flatMap(
            j -> {
              try {
                return ClassPath.from(Thread.currentThread().getContextClassLoader())
                    .getTopLevelClassesRecursive(j)
                    .parallelStream()
                    .map(ClassPath.ClassInfo::load)
                    .filter(i -> !Modifier.isAbstract(i.getModifiers()))
                    .filter(i -> !Modifier.isInterface(i.getModifiers()))
                    .filter(i -> Modifier.isPublic(i.getModifiers()))
                    .filter(IAction.class::isAssignableFrom)
                    .map(
                        i -> {
                          try {
                            return (IAction) i.newInstance();
                          } catch (final IllegalAccessException
                              | InstantiationException l_exception) {
                            LOGGER.warning(
                                CCommon.languagestring(
                                    CCommon.class, "actioninstantiate", i, l_exception));
                            return null;
                          }
                        })

                    // action can be instantiate
                    .filter(Objects::nonNull)

                    // check usable action name
                    .filter(CCommon::actionusable);
              } catch (final IOException l_exception) {
                throw new UncheckedIOException(l_exception);
              }
            });
  }

  /**
   * returns actions by a class
   *
   * @note class must be an inheritance of the IAgent interface
   * @param p_class class list
   * @return action stream
   */
  @SuppressWarnings("unchecked")
  public static Stream<IAction> actionsFromAgentClass(final Class<?>... p_class) {
    return p_class == null || p_class.length == 0
        ? Stream.of()
        : Arrays.stream(p_class)
            .parallel()
            .filter(IAgent.class::isAssignableFrom)
            .flatMap(i -> CCommon.methods(i, i))
            .map(
                i -> {
                  try {
                    return (IAction) new CMethodAction(i);
                  } catch (final IllegalAccessException l_exception) {
                    LOGGER.warning(
                        CCommon.languagestring(CCommon.class, "actioninstantiate", i, l_exception));
                    return null;
                  }
                })

            // action can be instantiate
            .filter(Objects::nonNull)

            // check usable action name
            .filter(CCommon::actionusable);
  }

  /**
   * checks if an action is usable
   *
   * @param p_action action object
   * @return boolean usable flag
   */
  private static boolean actionusable(final IAction p_action) {
    if ((p_action.name() == null)
        || (p_action.name().isEmpty())
        || (p_action.name().get(0).trim().isEmpty())) {
      LOGGER.warning(CCommon.languagestring(CCommon.class, "actionnameempty"));
      return false;
    }

    if (!Character.isLetter(p_action.name().get(0).charAt(0))) {
      LOGGER.warning(CCommon.languagestring(CCommon.class, "actionletter", p_action));
      return false;
    }

    if (!Character.isLowerCase(p_action.name().get(0).charAt(0))) {
      LOGGER.warning(CCommon.languagestring(CCommon.class, "actionlowercase", p_action));
      return false;
    }

    if (p_action.minimalArgumentNumber() < 0) {
      LOGGER.warning(CCommon.languagestring(CCommon.class, "actionargumentsnumber", p_action));
      return false;
    }

    return true;
  }

  /**
   * reads all methods by the action-annotations for building agent-actions
   *
   * @param p_class class
   * @param p_root root class
   * @return stream of all methods with inheritance
   */
  private static Stream<Method> methods(final Class<?> p_class, final Class<?> p_root) {
    final Pair<Boolean, IAgentAction.EAccess> l_classannotation = CCommon.isActionClass(p_class);
    if (!l_classannotation.getLeft())
      return p_class.getSuperclass() == null
          ? Stream.of()
          : methods(p_class.getSuperclass(), p_root);

    final Predicate<Method> l_filter =
        IAgentAction.EAccess.WHITELIST.equals(l_classannotation.getRight())
            ? i -> !CCommon.isActionFiltered(i, p_root)
            : i -> CCommon.isActionFiltered(i, p_root);

    return Stream.concat(
        Arrays.stream(p_class.getDeclaredMethods())
            .parallel()
            .map(
                i -> {
                  i.setAccessible(true);
                  return i;
                })
            .filter(i -> !Modifier.isAbstract(i.getModifiers()))
            .filter(i -> !Modifier.isInterface(i.getModifiers()))
            .filter(i -> !Modifier.isNative(i.getModifiers()))
            .filter(i -> !Modifier.isStatic(i.getModifiers()))
            .filter(l_filter),
        methods(p_class.getSuperclass(), p_root));
  }

  /**
   * filter of a class to use it as action
   *
   * @param p_class class for checking
   * @return boolean flag of check result
   */
  private static Pair<Boolean, IAgentAction.EAccess> isActionClass(final Class<?> p_class) {
    if (!p_class.isAnnotationPresent(IAgentAction.class))
      return new ImmutablePair<>(false, IAgentAction.EAccess.BLACKLIST);

    final IAgentAction l_annotation = p_class.getAnnotation(IAgentAction.class);
    return new ImmutablePair<>(
        (l_annotation.classes().length == 0)
            || (Arrays.stream(p_class.getAnnotation(IAgentAction.class).classes())
                .parallel()
                .anyMatch(p_class::equals)),
        l_annotation.access());
  }

  /**
   * class filter of an action to use it
   *
   * @param p_method method for checking
   * @param p_root root class
   * @return boolean flag of check result
   */
  private static boolean isActionFiltered(final Method p_method, final Class<?> p_root) {
    return p_method.isAnnotationPresent(IAgentActionFilter.class)
        && ((p_method.getAnnotation(IAgentActionFilter.class).classes().length == 0)
            || (Arrays.stream(p_method.getAnnotation(IAgentActionFilter.class).classes())
                .parallel()
                .anyMatch(p_root::equals)));
  }

  // ---------------------------------------------------------------------------------------------------------------------------------------------------------

  /**
   * concats an URL with a path
   *
   * @param p_base base URL
   * @param p_string additional path
   * @return new URL
   * @throws URISyntaxException thrown on syntax error
   * @throws MalformedURLException thrown on malformat
   */
  public static URL concaturl(final URL p_base, final String p_string)
      throws MalformedURLException, URISyntaxException {
    return new URL(p_base.toString() + p_string).toURI().normalize().toURL();
  }

  /**
   * returns root path of the resource
   *
   * @return URL of file or null
   */
  public static URL resourceurl() {
    return CCommon.class.getClassLoader().getResource("");
  }

  /**
   * returns a file from a resource e.g. Jar file
   *
   * @param p_file file
   * @return URL of file or null
   * @throws URISyntaxException thrown on syntax error
   * @throws MalformedURLException thrown on malformat
   */
  public static URL resourceurl(final String p_file)
      throws URISyntaxException, MalformedURLException {
    return resourceurl(new File(p_file));
  }

  /**
   * returns a file from a resource e.g. Jar file
   *
   * @param p_file file relative to the CMain
   * @return URL of file or null
   * @throws URISyntaxException is thrown on URI errors
   * @throws MalformedURLException is thrown on malformat
   */
  private static URL resourceurl(final File p_file)
      throws URISyntaxException, MalformedURLException {
    if (p_file.exists()) return p_file.toURI().normalize().toURL();
    return CCommon.class
        .getClassLoader()
        .getResource(p_file.toString().replace(File.separator, "/"))
        .toURI()
        .normalize()
        .toURL();
  }

  // ---------------------------------------------------------------------------------------------------------------------------------------------------------

  /**
   * returns the language depend string on any object
   *
   * @param p_source any object
   * @param p_label label name
   * @param p_parameter parameter
   * @return translated string
   * @tparam T object type
   */
  public static <T> String languagestring(
      final T p_source, final String p_label, final Object... p_parameter) {
    return languagestring(p_source.getClass(), p_label, p_parameter);
  }

  /**
   * returns a string of the resource file
   *
   * @param p_class class for static calls
   * @param p_label label name of the object
   * @param p_parameter object array with substitutions
   * @return resource string
   */
  public static String languagestring(
      final Class<?> p_class, final String p_label, final Object... p_parameter) {
    try {
      return MessageFormat.format(LANGUAGE.getString(languagelabel(p_class, p_label)), p_parameter);
    } catch (final MissingResourceException l_exception) {
      return "";
    }
  }

  /**
   * returns the label of a class and string to get access to the resource
   *
   * @param p_class class for static calls
   * @param p_label label name of the object
   * @return label name
   */
  private static String languagelabel(final Class<?> p_class, final String p_label) {
    return (p_class.getCanonicalName().toLowerCase(Locale.ROOT)
            + "."
            + p_label.toLowerCase(Locale.ROOT))
        .replaceAll("[^a-zA-Z0-9_\\.]+", "")
        .replace(PACKAGEROOT + ".", "");
  }

  // ---------------------------------------------------------------------------------------------------------------------------------------------------------

  /**
   * class to read UTF-8 encoded property file
   *
   * @note Java default encoding for property files is ISO-Latin-1
   */
  private static final class CUTF8Control extends ResourceBundle.Control {

    public final ResourceBundle newBundle(
        final String p_basename,
        final Locale p_locale,
        final String p_format,
        final ClassLoader p_loader,
        final boolean p_reload)
        throws IllegalAccessException, InstantiationException, IOException {
      final InputStream l_stream;
      final String l_resource =
          this.toResourceName(this.toBundleName(p_basename, p_locale), "properties");

      if (!p_reload) l_stream = p_loader.getResourceAsStream(l_resource);
      else {

        final URL l_url = p_loader.getResource(l_resource);
        if (l_url == null) return null;

        final URLConnection l_connection = l_url.openConnection();
        if (l_connection == null) return null;

        l_connection.setUseCaches(false);
        l_stream = l_connection.getInputStream();
      }

      final ResourceBundle l_bundle =
          new PropertyResourceBundle(new InputStreamReader(l_stream, "UTF-8"));
      l_stream.close();
      return l_bundle;
    }
  }
}