private Map<String, Plugin> loadPluginsFromClasspath(Settings settings) {
   Map<String, Plugin> plugins = newHashMap();
   Enumeration<URL> pluginUrls = null;
   try {
     pluginUrls = settings.getClassLoader().getResources("es-plugin.properties");
   } catch (IOException e) {
     logger.warn("Failed to find plugins from classpath", e);
   }
   while (pluginUrls.hasMoreElements()) {
     URL pluginUrl = pluginUrls.nextElement();
     Properties pluginProps = new Properties();
     InputStream is = null;
     try {
       is = pluginUrl.openStream();
       pluginProps.load(is);
       String sPluginClass = pluginProps.getProperty("plugin");
       Class<?> pluginClass = settings.getClassLoader().loadClass(sPluginClass);
       Plugin plugin = (Plugin) pluginClass.newInstance();
       plugins.put(plugin.name(), plugin);
     } catch (Exception e) {
       logger.warn("Failed to load plugin from [" + pluginUrl + "]", e);
     } finally {
       if (is != null) {
         try {
           is.close();
         } catch (IOException e) {
           // ignore
         }
       }
     }
   }
   return plugins;
 }
 @Override
 public Map<String, Model> dependencies(ModelContext modelContext) {
   Map<String, Model> models = newHashMap();
   for (ResolvedType resolvedType : dependencyProvider.dependentModels(modelContext)) {
     ModelContext parentContext = ModelContext.fromParent(modelContext, resolvedType);
     Optional<Model> model = modelFor(parentContext).or(mapModel(parentContext, resolvedType));
     if (model.isPresent()) {
       models.put(model.get().getName(), model.get());
     }
   }
   return models;
 }
  @Inject
  public PluginsService(Settings settings, Environment environment) {
    super(settings);
    this.environment = environment;

    loadPluginsIntoClassLoader();

    // first, find all the ones that are in the classpath
    Map<String, Plugin> plugins = Maps.newHashMap();
    plugins.putAll(loadPluginsFromClasspath(settings));

    logger.info("Loaded {}", plugins.keySet());

    this.plugins = ImmutableMap.copyOf(plugins);
  }
  @Override
  public com.google.common.base.Optional<Model> modelFor(ModelContext modelContext) {
    ResolvedType propertiesHost = modelContext.alternateFor(modelContext.resolvedType(resolver));
    if (isContainerType(propertiesHost)
        || isMapType(propertiesHost)
        || propertiesHost.getErasedType().isEnum()
        || isBaseType(Types.typeNameFor(propertiesHost.getErasedType()))
        || modelContext.hasSeenBefore(propertiesHost)) {
      LOG.debug(
          "Skipping model of type {} as its either a container type, map, enum or base type, or its already "
              + "been handled",
          resolvedTypeSignature(propertiesHost).or("<null>"));
      return Optional.absent();
    }
    ImmutableMap<String, ModelProperty> propertiesIndex =
        uniqueIndex(properties(modelContext, propertiesHost), byPropertyName());
    LOG.debug(
        "Inferred {} properties. Properties found {}",
        propertiesIndex.size(),
        Joiner.on(", ").join(propertiesIndex.keySet()));

    SortedSet<Map.Entry<String, ModelProperty>> sortedProperties =
        new TreeSet<Map.Entry<String, ModelProperty>>(
            new Comparator<Map.Entry<String, ModelProperty>>() {
              @Override
              public int compare(
                  Map.Entry<String, ModelProperty> e1, Map.Entry<String, ModelProperty> e2) {
                if ((e1.getValue().getPosition().compareTo(e2.getValue().getPosition()) == 0)) {
                  return e1.getValue().getName().compareTo(e2.getValue().getName());
                }
                return new Integer(e1.getValue().getPosition())
                    .compareTo(e2.getValue().getPosition());
              }
            });

    sortedProperties.addAll(propertiesIndex.entrySet());

    Map<String, ModelProperty> properties = new LinkedHashMap<String, ModelProperty>();

    // Map<String, ModelProperty> properties = newTreeMap();
    // properties.putAll(propertiesIndex);
    for (Map.Entry<String, ModelProperty> value : sortedProperties) {
      properties.put(value.getKey(), value.getValue());
    }
    return Optional.of(modelBuilder(propertiesHost, properties, modelContext));
  }