/**
   * Loads the plug-ins that may be available in the given URL.
   */
  private void loadPlugins(URL pluginUrl) {
    ZipInputStream zipIn = null;
    try {
      // Open a zip input from pluginUrl
      zipIn = new ZipInputStream(pluginUrl.openStream());
      // Try do find a plugin properties file in current zip stream  
      for (ZipEntry entry; (entry = zipIn.getNextEntry()) != null; ) {
        String zipEntryName = entry.getName();
        int lastIndex = zipEntryName.lastIndexOf(DEFAULT_APPLICATION_PLUGIN_PROPERTIES_FILE);
        if (lastIndex != -1
            && (lastIndex == 0
                || zipEntryName.charAt(lastIndex - 1) == '/')) {
          try {
            // Build application plugin family with its package 
            String applicationPluginFamily = zipEntryName.substring(0, lastIndex);
            applicationPluginFamily += APPLICATION_PLUGIN_FAMILY;
            ClassLoader classLoader = new URLClassLoader(new URL [] {pluginUrl}, getClass().getClassLoader());
            readPlugin(ResourceBundle.getBundle(applicationPluginFamily, Locale.getDefault(), classLoader), 
                "jar:" + pluginUrl.toString() + "!/" + URLEncoder.encode(zipEntryName, "UTF-8").replace("+", "%20"), 
                classLoader);
          } catch (MissingResourceException ex) {
            // Ignore malformed plugins
          }
        }
      }
    } catch (IOException ex) {
      // Ignore furniture plugin 
    } finally {
      if (zipIn != null) {
        try {
          zipIn.close();
        } catch (IOException ex) {
        }
      }
    }
  }