public void afterPropertiesSet() throws Exception {
    if (pluginCacheMillis == Long.MIN_VALUE) {
      pluginCacheMillis = cacheMillis;
    }

    if (pluginManager == null || localResourceLoader == null) {
      return;
    }

    for (GrailsPlugin plugin : pluginManager.getAllPlugins()) {
      for (Resource pluginBundle : getPluginBundles(plugin)) {
        // If the plugin is an inline plugin, use the abosolute path to the plugin's i18n files.
        // Otherwise, use the relative path to the plugin from the application's perspective.
        String basePath;
        if (isInlinePlugin(plugin)) {
          basePath = getInlinePluginPath(plugin);
        } else {
          basePath = WEB_INF_PLUGINS_PATH.substring(1) + plugin.getFileSystemName();
        }

        final String baseName =
            GrailsStringUtils.substringBefore(
                GrailsStringUtils.getFileBasename(pluginBundle.getFilename()), "_");
        String pathToAdd = basePath + GRAILS_APP_I18N_PATH_COMPONENT + baseName;
        if (!pluginBaseNames.contains(pathToAdd)) {
          pluginBaseNames.add(pathToAdd);
        }
      }
    }
  }
 protected Resource findResourceInBinaryPlugins(PluginResourceInfo info) {
   if (pluginManager != null) {
     String fullPluginName = info.pluginName;
     for (GrailsPlugin plugin : pluginManager.getAllPlugins()) {
       if (plugin.getFileSystemName().equals(fullPluginName)
           && (plugin instanceof BinaryGrailsPlugin)) {
         return ((BinaryGrailsPlugin) plugin).getResource(info.uri);
       }
     }
   }
   return null;
 }
 /**
  * Returns the absolute path to the provided Grails plugin if it is being used "inline" or {@code
  * null} if the plugin is <b>not</b> being used "inline".
  *
  * @param grailsPlugin The Grails plugin.
  * @return The absolute path to the "inline" plugin or {@code null} if the plugin is not being
  *     used "inline".
  */
 protected String getInlinePluginPath(GrailsPlugin grailsPlugin) {
   if (Environment.isWarDeployed()) return null;
   try {
     final GrailsPluginInfo pluginInfo =
         pluginBuildSettings.getPluginInfoForName(grailsPlugin.getFileSystemShortName());
     if (pluginInfo != null) {
       return new File(
               pluginBuildSettings.getBuildSettings().getResourcesDir(),
               "plugins/" + pluginInfo.getFullName())
           .getCanonicalPath();
     }
   } catch (final IOException e) {
     LOG.debug(
         "Unable to retrieve plugin directory for plugin " + grailsPlugin.getFileSystemShortName(),
         e);
   }
   return null;
 }
  /**
   * Returns the i18n message bundles for the provided plugin or an empty array if the plugin does
   * not contain any .properties files in its grails-app/i18n folder.
   *
   * @param grailsPlugin The grails plugin that may or may not contain i18n internationalization
   *     files.
   * @return An array of {@code Resource} objects representing the internationalization files or an
   *     empty array if no files are found.
   */
  protected Resource[] getPluginBundles(GrailsPlugin grailsPlugin) {
    if (grailsPlugin instanceof BinaryGrailsPlugin) {
      return NO_RESOURCES;
    }

    try {
      String basePath;

      // If the plugin is inline, use the absolute path to the internationalization files
      // in order to convert to resources.  Otherwise, use the relative WEB-INF path.
      String inlinePath = getInlinePluginPath(grailsPlugin);
      if (inlinePath == null) {
        basePath = WEB_INF_PLUGINS_PATH + grailsPlugin.getFileSystemName();
      } else {
        basePath = inlinePath;
      }
      return resourceResolver.getResources(basePath + "/grails-app/i18n/*.properties");
    } catch (IOException e) {
      LOG.debug(
          "Could not resolve any resources for plugin " + grailsPlugin.getFileSystemName(), e);
      return NO_RESOURCES;
    }
  }