Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The Sling API defines a new Tenant interface to represant tenants and a TenantProvider service interface which provides access to tenants.

Proposed API

SlingHttpServletRequest

The SlingHttpServletRequest interface is extended to return the Tenant applicable for the request.

Code Block
titleSlingHttpServletRequest.java

public interface SlingHttpServletRequest extends HttpServletRequest {

    ...

    /**
     * Returns the {@link Tenant} applicable to this request or
     * <code>null</code> if no tenant can be resolved for this request.
     */
    Tenant getTenant();

    ...
}

SlingHttpServletRequestWrapper

The SlingHttpServletRequestWrapper interface is extended to return the Tenant applicable for the request.

...

titleSlingHttpServletRequestWrapper.java

The tenant applicable to a given request is available through the new SlingHttpServletRequest.getTenant() method.

Basically a tenant has just three defined properties which are mainly intended to identify the tenant and list it for human consumption:

  • A globally unique identifier
  • A (short) name, which is not required to be unique
  • A (longer) description

In addition a tenant may provide a number of application specific properties. The properties are name value pairs, where the names are strings and the values may be of any type.

One application of the tenant and its property will be the JcrResourceResolverFactory. A new getResourceResolver(Session, Tenant) method is defined, where the tenant is used to inject configuration for the ResourceResolver returned. In a first step the resource.resolver.searchpath tenant property is used to enhance the globally configured search path. If the property is set and can be converted to a String[] the entries are merged with the global search path as follows:

Code Block

String[] globalPath = // globally configured search path
String[] tenantPath = // per-tenant search path
List<String> searchPath = // search path merged from globalPath and tenantPath

// add absolute tenantPath entries
for each entry in tenantPath
   if entry is absolute then searchPath.add(entry);
done

// add relative tenantPath entries
for each globalEntry in globalPath
   for each entry in tenantPath
      if entry is relative searchPath.add(globalEntry + "/" + entry);
   done
   searchPath.add(globalEntry);
done

Example: For a globalPath of "/apps", "/libs" and a tenantPath of "/tenant", "c1", "shared" the merged search path will be [ "/tenant", "/apps/c1", "/apps/shared", "/apps", "/libs/cq", "/libs/shared", "/libs"].

If the resource.resolver.searchpath property of the tenant does not exist or if no tenant is available to the JcrResourceResolverFactory the global search path configuration is used unmodified.

In the future more properties might be used to augment the configuration of a resource resolver returned for a given tenant.

Proposed API

...

Tenant

The Tenant interface is defined in the org.apache.sling.api.tenant.Tenant package of the Sling API bundle org.apache.sling.api.

...

Code Block
titleTenantProvider.java
/**
 * The <code>TenantProvider</code> defines the service interface of for a sevice
 * which may be asked for {@link Tenant tenant instances}.
 * <p>
 * For now this provider interface provides access to a tenant applying to a
 * particular request as well as to all tenants known to this provider.
 */
public interface TenantProvider {

    /**
     * Returns the {@link Tenant} with the given <code>tenantId</code> or
     * <code>null</code> if no such tenant exists.
     */
    Tenant getTenantById(String tenantId);

    /**
     * Returns an iterator of all {@link Tenant tenants} known to this provider.
     * If no tenants are known the iterator is empty.
     */
    Iterator<Tenant> getTenants();

    /**
     * Returns an iterator of {@link Tenant tenants} whose names match the given
     * <code>tenantName</code>. Since the name of a tenant is not required to be
     * globally unique, this method may return more than one tenant.
     * <p>
     * If no tenants are known with the requested name the iterator is empty.
     */
    Iterator<Tenant> getTenantsByName(String tenantName);

    /**
     * Returns an iterator of {@link Tenant tenants} matching the given
     * <code>tenantFilter</code>.
     * <p>
     * The <code>tenantFilter</code> is a valid OSGi filter string as defined in
     * Section 3.2.6, Filter Syntax, of the OSGi Core Specification, Release 4.
     * <p>
     * If no tenants match the <code>tenantFilter</code> or the
     * <code>tenantFilter</code> is not a valid filter string the iterator is
     * empty.
     */
    Iterator<Tenant> getTenantsByFilter(String tenantFilter);
}

SlingHttpServletRequest

The SlingHttpServletRequest interface is extended to return the Tenant applicable for the request.

Code Block
titleSlingHttpServletRequest.java

public interface SlingHttpServletRequest extends HttpServletRequest {
    ...
    /**
     * Returns the {@link Tenant} applicable to this request or
     * <code>null</code> if no tenant can be resolved for this request.
     */
    Tenant getTenant();
    ...
}

SlingHttpServletRequestWrapper

The SlingHttpServletRequestWrapper interface is extended to return the Tenant applicable for the request.

Code Block
titleSlingHttpServletRequestWrapper.java

public class SlingHttpServletRequestWrapper extends HttpServletRequestWrapper
        implements SlingHttpServletRequest {
    ...
    public Tenant getTenant() {
        return getSlingRequest().getTenant();
    }
    ...
}
Code Block
JcrResourceResolverFactory.java
JcrResourceResolverFactory.java

public interface JcrResourceResolverFactory {
    ...
    ResourceResolver getResourceResolver(Session session, Tenant tenant);
    ...
}