package org.apache.solr.rest;
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestInfo;
import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
import org.noggit.ObjectBuilder;
import org.restlet.Request;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.ResourceException;
import org.restlet.routing.Router;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Supports runtime mapping of REST API endpoints to ManagedResource 
 * implementations; endpoints can be registered at either the /schema
 * or /config base paths, depending on which base path is more appropriate
 * for the type of managed resource.
 */
public class RestManager {
  
  public static final Logger log = LoggerFactory.getLogger(RestManager.class);
  
  public static final String SCHEMA_BASE_PATH = "/schema";
  public static final String CONFIG_BASE_PATH = "/config";
  public static final String MANAGED_ENDPOINT = "/managed";
  
  // used for validating resourceIds provided during registration
  private static final Pattern resourceIdRegex = Pattern.compile("(/config|/schema)(/.*)");

  private static final boolean DECODE = true;

  /**
   * Used internally to keep track of registrations during core initialization
   */
  private static class ManagedResourceRegistration {
    String resourceId;
    Class<? extends ManagedResource> implClass;
    List<ManagedResourceObserver> observers = new ArrayList<>();

    private ManagedResourceRegistration(String resourceId,
                                        Class<? extends ManagedResource> implClass, 
                                        ManagedResourceObserver observer)
    {
      this.resourceId = resourceId;
      this.implClass = implClass;
      
      if (observer != null) {
        this.observers.add(observer);
      }
    }  

    /** Returns resourceId, class, and number of observers of this registered resource */
    public Map<String,String> getInfo() {
      Map<String,String> info = new HashMap<>();
      info.put("resourceId", resourceId);
      info.put("class", implClass.getName());
      info.put("numObservers", String.valueOf(observers.size()));
      return info;
    }    
  }
  
  /**
   * Per-core registry of ManagedResources found during core initialization.
   * 
   * Registering of managed resources can happen before the RestManager is
   * fully initialized. To avoid timing issues, resources register themselves
   * and then the RestManager initializes all ManagedResources before the core
   * is activated.  
   */
  public static class Registry {
    
    private Map<String,ManagedResourceRegistration> registered = new TreeMap<>();


    // REST API endpoints that need to be protected against dynamic endpoint creation
    private final Set<String> reservedEndpoints = new HashSet<>();
    private final Pattern reservedEndpointsPattern;

    public Registry() {
      reservedEndpoints.add(CONFIG_BASE_PATH + MANAGED_ENDPOINT);
      reservedEndpoints.add(SCHEMA_BASE_PATH + MANAGED_ENDPOINT);

      for (String reservedEndpoint : SolrSchemaRestApi.getReservedEndpoints()) {
        reservedEndpoints.add(reservedEndpoint);
      }
      for (String reservedEndpoint : SolrConfigRestApi.getReservedEndpoints()) {
        reservedEndpoints.add(reservedEndpoint);
      }
      reservedEndpointsPattern = getReservedEndpointsPattern();
    }

    /**
     * Returns the set of non-registerable endpoints.
     */
    public Set<String> getReservedEndpoints() {
      return Collections.unmodifiableSet(reservedEndpoints);
    }

    /**
     * Returns a Pattern, to be used with Matcher.matches(), that will recognize
     * prefixes or full matches against reserved endpoints that need to be protected
     * against dynamic endpoint registration.  group(1) will contain the match
     * regardless of whether it's a full match or a prefix.
     */
    private Pattern getReservedEndpointsPattern() {
      // Match any of the reserved endpoints exactly, or followed by a slash and more stuff
      StringBuilder builder = new StringBuilder();
      builder.append("(");
      boolean notFirst = false;
      for (String reservedEndpoint : reservedEndpoints) {
        if (notFirst) {
          builder.append("|");
        } else {
          notFirst = true;
        }
        builder.append(reservedEndpoint);
      }
      builder.append(")(?:|/.*)");
      return Pattern.compile(builder.toString());
    }


    /**
     * Get a view of the currently registered resources. 
     */
    public Collection<ManagedResourceRegistration> getRegistered() {
      return Collections.unmodifiableCollection(registered.values());
    }
    
    /**
     * Register the need to use a ManagedResource; this method is typically called
     * by a Solr component during core initialization to register itself as an 
     * observer of a specific type of ManagedResource. As many Solr components may
     * share the same ManagedResource, this method only serves to associate the
     * observer with an endpoint and implementation class. The actual construction
     * of the ManagedResource and loading of data from storage occurs later once
     * the RestManager is fully initialized.
     * @param resourceId - An endpoint in the Rest API to manage the resource; must
     * start with /config and /schema.
     * @param implClass - Class that implements ManagedResource.
     * @param observer - Solr component that needs to know when the data being managed
     * by the ManagedResource is loaded, such as a TokenFilter.
     */
    public synchronized void registerManagedResource(String resourceId, 
        Class<? extends ManagedResource> implClass, ManagedResourceObserver observer) {
      
      if (resourceId == null)
        throw new IllegalArgumentException(
            "Must provide a non-null resourceId to register a ManagedResource!");

      Matcher resourceIdValidator = resourceIdRegex.matcher(resourceId);
      if (!resourceIdValidator.matches()) {
        String errMsg = String.format(Locale.ROOT,
            "Invalid resourceId '%s'; must start with %s or %s.",
            resourceId, CONFIG_BASE_PATH, SCHEMA_BASE_PATH);
        throw new SolrException(ErrorCode.SERVER_ERROR, errMsg);        
      }
         
      // protect reserved REST API endpoints from being used by another
      Matcher reservedEndpointsMatcher = reservedEndpointsPattern.matcher(resourceId);
      if (reservedEndpointsMatcher.matches()) {
        throw new SolrException(ErrorCode.SERVER_ERROR,
            reservedEndpointsMatcher.group(1)
            + " is a reserved endpoint used by the Solr REST API!");
      }

      // IMPORTANT: this code should assume there is no RestManager at this point
      
      // it's ok to re-register the same class for an existing path
      ManagedResourceRegistration reg = registered.get(resourceId);
      if (reg != null) {
        if (!reg.implClass.equals(implClass)) {
          String errMsg = String.format(Locale.ROOT,
              "REST API path %s already registered to instances of %s",
              resourceId, reg.implClass.getName());
          throw new SolrException(ErrorCode.SERVER_ERROR, errMsg);          
        } 
        
        if (observer != null) {
          reg.observers.add(observer);
          log.info("Added observer of type {} to existing ManagedResource {}", 
              observer.getClass().getName(), resourceId);
        }
      } else {
        registered.put(resourceId, 
            new ManagedResourceRegistration(resourceId, implClass, observer));
        log.info("Registered ManagedResource impl {} for path {}", 
            implClass.getName(), resourceId);
      }
    }    
  }  

  /**
   * Locates the RestManager using ThreadLocal SolrRequestInfo.
   */
  public static RestManager getRestManager(SolrRequestInfo solrRequestInfo) {
    if (solrRequestInfo == null)
      throw new ResourceException(Status.SERVER_ERROR_INTERNAL, 
          "No SolrRequestInfo in this Thread!");

    SolrQueryRequest req = solrRequestInfo.getReq();
    RestManager restManager = 
        (req != null) ? req.getCore().getRestManager() : null;
    
    if (restManager == null)
      throw new ResourceException(Status.SERVER_ERROR_INTERNAL, 
          "No RestManager found!");
    
    return restManager;
  }
  
  /**
   * The Restlet router needs a lightweight extension of ServerResource to delegate a request
   * to. ManagedResource implementations are heavy-weight objects that live for the duration of
   * a SolrCore, so this class acts as the proxy between Restlet and a ManagedResource when
   * doing request processing.
   *
   */
  public static class ManagedEndpoint extends BaseSolrResource
      implements GETable, PUTable, POSTable, DELETEable
  {
    /**
     * Determines the ManagedResource resourceId from the Restlet request.
     */
    public static String resolveResourceId(Request restletReq)  {
      String resourceId = restletReq.getResourceRef().
          getRelativeRef(restletReq.getRootRef().getParentRef()).getPath(DECODE);
      
      // all resources are registered with the leading slash
      if (!resourceId.startsWith("/"))
        resourceId = "/"+resourceId;


      return resourceId;
    }
    
    protected ManagedResource managedResource;
    protected String childId;    
    
    /**
     * Initialize objects needed to handle a request to the REST API. Specifically,
     * we lookup the RestManager using the ThreadLocal SolrRequestInfo and then
     * dynamically locate the ManagedResource associated with the request URI.
     */
    @Override
    public void doInit() throws ResourceException {
      super.doInit();      
      
      // get the relative path to the requested resource, which is
      // needed to locate ManagedResource impls at runtime
      String resourceId = resolveResourceId(getRequest());

      // supports a request for a registered resource or its child
      RestManager restManager = 
          RestManager.getRestManager(SolrRequestInfo.getRequestInfo());
      
      managedResource = restManager.getManagedResourceOrNull(resourceId);      
      if (managedResource == null) {
        // see if we have a registered endpoint one-level up ...
        int lastSlashAt = resourceId.lastIndexOf('/');
        if (lastSlashAt != -1) {
          String parentResourceId = resourceId.substring(0,lastSlashAt);          
          log.info("Resource not found for {}, looking for parent: {}",
              resourceId, parentResourceId);          
          managedResource = restManager.getManagedResourceOrNull(parentResourceId);
          if (managedResource != null) {
            // verify this resource supports child resources
            if (!(managedResource instanceof ManagedResource.ChildResourceSupport)) {
              String errMsg = String.format(Locale.ROOT,
                  "%s does not support child resources!", managedResource.getResourceId());
              throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, errMsg);
            }
            
            childId = resourceId.substring(lastSlashAt+1);
            log.info("Found parent resource {} for child: {}", 
                parentResourceId, childId);
          }
        }
      }    
      
      if (managedResource == null) {
        if (Method.PUT.equals(getMethod()) || Method.POST.equals(getMethod())) {
          // delegate create requests to the RestManager
          managedResource = restManager.endpoint;
        } else {        
          throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND, 
              "No REST managed resource registered for path "+resourceId);
        }
      }
      
      log.info("Found ManagedResource ["+managedResource+"] for "+resourceId);      
    }    
    
    @Override
    public Representation put(Representation entity) {
      try {
        managedResource.doPut(this, entity, parseJsonFromRequestBody(entity));
      } catch (Exception e) {
        getSolrResponse().setException(e);        
      }
      handlePostExecution(log);
      return new SolrOutputRepresentation();    
    }
    
    @Override
    public Representation post(Representation entity) {
      try {
        managedResource.doPost(this, entity, parseJsonFromRequestBody(entity));
      } catch (Exception e) {
        getSolrResponse().setException(e);        
      }
      handlePostExecution(log);
      return new SolrOutputRepresentation();    
    }    

    @Override
    public Representation delete() {
      // only delegate delete child resources to the ManagedResource
      // as deleting the actual resource is best handled by the
      // RestManager
      if (childId != null) {        
        try {
          managedResource.doDeleteChild(this, childId);
        } catch (Exception e) {
          getSolrResponse().setException(e);        
        }
      } else {
        try {
          RestManager restManager = 
              RestManager.getRestManager(SolrRequestInfo.getRequestInfo());
          restManager.deleteManagedResource(managedResource);
        } catch (Exception e) {
          getSolrResponse().setException(e);        
        }
      }
      handlePostExecution(log);
      return new SolrOutputRepresentation();    
    }    
        
    @Override
    public Representation get() { 
      try {
        managedResource.doGet(this, childId);
      } catch (Exception e) {
        getSolrResponse().setException(e);        
      }
      handlePostExecution(log);
      return new SolrOutputRepresentation();    
    }     
    
    /**
     * Parses and validates the JSON passed from the to the ManagedResource. 
     */
    protected Object parseJsonFromRequestBody(Representation entity) {
      if (entity.getMediaType() == null) {
        entity.setMediaType(MediaType.APPLICATION_JSON);
      }
      
      if (!entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
        String errMsg = String.format(Locale.ROOT,
            "Invalid content type %s; only %s is supported.",
            entity.getMediaType(), MediaType.APPLICATION_JSON.toString());
        log.error(errMsg);
        throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, errMsg);
      }
      
      String text = null;
      try {
        text = entity.getText();
      } catch (IOException ioExc) {
        String errMsg = "Failed to read entity text due to: "+ioExc;
        log.error(errMsg, ioExc);
        throw new ResourceException(Status.SERVER_ERROR_INTERNAL, errMsg, ioExc);
      }
      
      if (text == null || text.trim().length() == 0) {
        throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Empty request body!");      
      }

      Object parsedJson = null;
      try {
        parsedJson = ObjectBuilder.fromJSON(text);
      } catch (IOException ioExc) {
        String errMsg = String.format(Locale.ROOT,
            "Failed to parse request [%s] into JSON due to: %s",
            text, ioExc.toString());
        log.error(errMsg, ioExc);
        throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, errMsg, ioExc);
      }
      return parsedJson;
    }        
  } // end ManagedEndpoint class
  
  /**
   * The RestManager itself supports some endpoints for creating and listing managed resources.
   * Effectively, this resource provides the API endpoint for doing CRUD on the registry.
   */
  private static class RestManagerManagedResource extends ManagedResource {

    private static final String REST_MANAGER_STORAGE_ID = "/rest/managed";

    private final RestManager restManager;


    public RestManagerManagedResource(RestManager restManager) throws SolrException {
      super(REST_MANAGER_STORAGE_ID, restManager.loader, restManager.storageIO);
      this.restManager = restManager;
    }

    /**
     * Loads and initializes any ManagedResources that have been created but
     * are not associated with any Solr components.
     */
    @SuppressWarnings("unchecked")
    @Override
    protected void onManagedDataLoadedFromStorage(NamedList<?> managedInitArgs, Object managedData)
        throws SolrException {
      
      if (managedData == null) {
        // this is OK, just means there are no stored registrations
        // storing an empty list is safe and avoid future warnings about
        // the data not existing
        storeManagedData(new ArrayList<Map<String,String>>(0));
        return;
      }
      
      List<Object> managedList = (List<Object>)managedData;
      for (Object next : managedList) {
        Map<String,String> info = (Map<String,String>)next;        
        String implClass = info.get("class");
        String resourceId = info.get("resourceId");
        Class<? extends ManagedResource> clazz = solrResourceLoader.findClass(implClass, ManagedResource.class);
        ManagedResourceRegistration existingReg = restManager.registry.registered.get(resourceId);
        if (existingReg == null) {
          restManager.registry.registerManagedResource(resourceId, clazz, null);
        } // else already registered, no need to take any action        
      }      
    }
            
    /**
     * Creates a new ManagedResource in the RestManager.
     */
    @SuppressWarnings("unchecked")
    @Override
    public synchronized void doPut(BaseSolrResource endpoint, Representation entity, Object json) {      
      if (json instanceof Map) {
        String resourceId = ManagedEndpoint.resolveResourceId(endpoint.getRequest());
        Map<String,String> info = (Map<String,String>)json;
        info.put("resourceId", resourceId);
        storeManagedData(applyUpdatesToManagedData(json));
      } else {
        throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, 
            "Expected Map to create a new ManagedResource but received a "+json.getClass().getName());
      }          
      // PUT just returns success status code with an empty body
    }

    /**
     * Registers a new {@link ManagedResource}.
     *
     * Called during PUT/POST processing to apply updates to the managed data passed from the client.
     */
    @SuppressWarnings("unchecked")
    @Override
    protected Object applyUpdatesToManagedData(Object updates) {
      Map<String,String> info = (Map<String,String>)updates;      
      // this is where we'd register a new ManagedResource
      String implClass = info.get("class");
      String resourceId = info.get("resourceId");
      log.info("Creating a new ManagedResource of type {} at path {}", 
          implClass, resourceId);
      Class<? extends ManagedResource> clazz = 
          solrResourceLoader.findClass(implClass, ManagedResource.class);
      
      // add this new resource to the RestManager
      restManager.addManagedResource(resourceId, clazz);

      // we only store ManagedResources that don't have observers as those that do
      // are already implicitly defined
      List<Map<String,String>> managedList = new ArrayList<>();
      for (ManagedResourceRegistration reg : restManager.registry.getRegistered()) {
        if (reg.observers.isEmpty()) {
          managedList.add(reg.getInfo());
        }
      }          
      return managedList;
    }

    /**
     * Deleting of child resources not supported by this implementation.
     */
    @Override
    public void doDeleteChild(BaseSolrResource endpoint, String childId) {
      throw new ResourceException(Status.SERVER_ERROR_NOT_IMPLEMENTED);
    }

    @Override
    public void doGet(BaseSolrResource endpoint, String childId) {
      
      // filter results by /schema or /config
      String path = ManagedEndpoint.resolveResourceId(endpoint.getRequest());
      Matcher resourceIdMatcher = resourceIdRegex.matcher(path);
      if (!resourceIdMatcher.matches()) {
        // extremely unlikely but didn't want to squelch it either
        throw new ResourceException(Status.SERVER_ERROR_NOT_IMPLEMENTED, path);
      }
      
      String filter = resourceIdMatcher.group(1);
            
      List<Map<String,String>> regList = new ArrayList<>();
      for (ManagedResourceRegistration reg : restManager.registry.getRegistered()) {
        if (!reg.resourceId.startsWith(filter))
          continue; // doesn't match filter
        
        if (RestManagerManagedResource.class.isAssignableFrom(reg.implClass))
          continue; // internal, no need to expose to outside
        
        regList.add(reg.getInfo());          
      }
      
      endpoint.getSolrResponse().add("managedResources", regList);      
    }    
  } // end RestManagerManagedResource
  
  protected StorageIO storageIO;
  protected Registry registry;
  protected Map<String,ManagedResource> managed = new TreeMap<>();
  protected RestManagerManagedResource endpoint;
  protected SolrResourceLoader loader;
  
  // refs to these are needed to bind new ManagedResources created using the API
  protected Router schemaRouter;
  protected Router configRouter;
  
  /**
   * Initializes the RestManager with the storageIO being optionally created outside of this implementation
   * such as to use ZooKeeper instead of the local FS. 
   */
  public void init(SolrResourceLoader loader,
                   NamedList<String> initArgs, 
                   StorageIO storageIO) 
      throws SolrException
  {
    log.info("Initializing RestManager with initArgs: "+initArgs);

    if (storageIO == null)
      throw new IllegalArgumentException(
          "Must provide a valid StorageIO implementation to the RestManager!");
    
    this.storageIO = storageIO;
    this.loader = loader;
    
    registry = loader.getManagedResourceRegistry();
    
    // the RestManager provides metadata about managed resources via the /managed endpoint
    // and allows you to create new ManagedResources dynamically by PUT'ing to this endpoint
    endpoint = new RestManagerManagedResource(this);
    endpoint.loadManagedDataAndNotify(null); // no observers for my endpoint
    // responds to requests to /config/managed and /schema/managed
    managed.put(CONFIG_BASE_PATH+MANAGED_ENDPOINT, endpoint);
    managed.put(SCHEMA_BASE_PATH+MANAGED_ENDPOINT, endpoint);
            
    // init registered managed resources
    log.info("Initializing {} registered ManagedResources", registry.registered.size());
    for (ManagedResourceRegistration reg : registry.registered.values()) {
      // keep track of this for lookups during request processing
      managed.put(reg.resourceId, createManagedResource(reg));
    }
  }

  /**
   * If not already registered, registers the given {@link ManagedResource} subclass
   * at the given resourceId, creates an instance, and attaches it to the appropriate
   * Restlet router.  Returns the corresponding instance.
   */
  public synchronized ManagedResource addManagedResource(String resourceId, Class<? extends ManagedResource> clazz) {
    ManagedResource res = null;
    ManagedResourceRegistration existingReg = registry.registered.get(resourceId);
    if (existingReg == null) {
      registry.registerManagedResource(resourceId, clazz, null);
      res = createManagedResource(registry.registered.get(resourceId));
      managed.put(resourceId, res);
      log.info("Registered new managed resource {}", resourceId);
      
      // attach this new resource to the Restlet router
      Matcher resourceIdValidator = resourceIdRegex.matcher(resourceId);
      boolean validated = resourceIdValidator.matches();
      assert validated : "managed resourceId '" + resourceId
                       + "' should already be validated by registerManagedResource()";
      String routerPath = resourceIdValidator.group(1);      
      String path = resourceIdValidator.group(2);
      Router router = SCHEMA_BASE_PATH.equals(routerPath) ? schemaRouter : configRouter;
      if (router != null) {
        attachManagedResource(res, path, router);
      }
    } else {
      res = getManagedResource(resourceId);
    }
    return res;
  }


  /**
   * Creates a ManagedResource using registration information. 
   */
  protected ManagedResource createManagedResource(ManagedResourceRegistration reg) throws SolrException {
    ManagedResource res = null;
    try {
      Constructor<? extends ManagedResource> ctor = 
          reg.implClass.getConstructor(String.class, SolrResourceLoader.class, StorageIO.class);
      res = ctor.newInstance(reg.resourceId, loader, storageIO);
      res.loadManagedDataAndNotify(reg.observers);
    } catch (Exception e) {
      String errMsg = 
          String.format(Locale.ROOT,
              "Failed to create new ManagedResource %s of type %s due to: %s",
              reg.resourceId, reg.implClass.getName(), e);      
      throw new SolrException(ErrorCode.SERVER_ERROR, errMsg, e);
    }
    return res;
  }

  /**
   * Returns the {@link ManagedResource} subclass instance corresponding
   * to the given resourceId from the registry.
   *
   * @throws ResourceException if no managed resource is registered with
   *  the given resourceId.
   */
  public ManagedResource getManagedResource(String resourceId) {
    ManagedResource res = getManagedResourceOrNull(resourceId);
    if (res == null) {
      throw new ResourceException(Status.SERVER_ERROR_INTERNAL, 
          "No ManagedResource registered for path: "+resourceId);
    }
    return res;
  }

  /**
   * Returns the {@link ManagedResource} subclass instance corresponding
   * to the given resourceId from the registry, or null if no resource
   * has been registered with the given resourceId.
   */
  public synchronized ManagedResource getManagedResourceOrNull(String resourceId) {
    return managed.get(resourceId);
  }
  
  /**
   * Deletes a managed resource if it is not being used by any Solr components. 
   */
  public synchronized void deleteManagedResource(ManagedResource res) {
    String resourceId = res.getResourceId();
    ManagedResourceRegistration existingReg = registry.registered.get(resourceId);
    int numObservers = existingReg.observers.size();
    if (numObservers > 0) {
      String errMsg = 
          String.format(Locale.ROOT,
              "Cannot delete managed resource %s as it is being used by %d Solr components",
              resourceId, numObservers);
      throw new SolrException(ErrorCode.FORBIDDEN, errMsg);
    }
    
    registry.registered.remove(resourceId);
    managed.remove(resourceId);
    try {
      res.onResourceDeleted();
    } catch (IOException e) {
      // the resource is already deleted so just log this
      log.error("Error when trying to clean-up after deleting "+resourceId, e);
    }
  }
      
  /**
   * Attach managed resource paths to the given Restlet Router. 
   * @param router - Restlet Router
   */
  public synchronized void attachManagedResources(String routerPath, Router router) {
    
    if (CONFIG_BASE_PATH.equals(routerPath)) {
      this.configRouter = router;
    } else if (SCHEMA_BASE_PATH.equals(routerPath)) {
      this.schemaRouter = router;
    } else {
      throw new SolrException(ErrorCode.SERVER_ERROR, 
          routerPath+" not supported by the RestManager");
    }      
    
    int numAttached = 0;
    for (String resourceId : managed.keySet()) {
      if (resourceId.startsWith(routerPath)) {
        // the way restlet works is you attach a path w/o the routerPath
        String path = resourceId.substring(routerPath.length());
        attachManagedResource(managed.get(resourceId), path, router);
        ++numAttached;
      }
    }
    
    log.info("Attached {} ManagedResource endpoints to Restlet router: {}", 
        numAttached, routerPath);
  }
  
  /**
   * Attaches a ManagedResource and optionally a path for child resources
   * to the given Restlet Router.
   */
  protected void attachManagedResource(ManagedResource res, String path, Router router) {
    router.attach(path, res.getServerResourceClass());
    log.info("Attached managed resource at path: {}",path);
    
    // Determine if we should also route requests for child resources
    // ManagedResource.ChildResourceSupport is a marker interface that
    // indicates the ManagedResource also manages child resources at
    // a path one level down from the main resourceId
    if (ManagedResource.ChildResourceSupport.class.isAssignableFrom(res.getClass())) {
      router.attach(path+"/{child}", res.getServerResourceClass());
    }    
  }  
}
