com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

Using the CarbonContext API

PrivilegedCarbonContext

PrivilegedCarbonContext is a special subclass of CarbonContext, which allows you to perform privileged operations such as, setting the tenant ID and domain, starting or ending tenant flows and more. This class can only be used by Carbon components that have the permission to get hold of an instance of the PrivilegedCarbonContext. An instance of PrivilegedCarbonContext can only be obtained using the static methods outlined below.

Obtaining the PrivilegedCarbonContext

The following method has to be statically invoked, and will return an instance of PrivilegedCarbonContext.

getThreadLocalCarbonContext()

Obtains the PrivilegedCarbonContext by using data stored in the current thread: PrivilegedCarbonContext.getThreadLocalCarbonContext(). As a result, in cases like the deployers, where you can be sure that the deployment scheduler thread would set the ThreadLocal data, you should directly call the getThreadLocalCarbonContext method. You should have an idea, under which thread you are executing. It is better to resolve the CarbonContext outside that util method, as opposed to resolving the CarbonContext within the method.

Setting information into PrivilegedCarbonContext

If the data backed by the PrivilegedCarbonContext has been created for the first time, you have to populate information (such as, tenant ID, tenant domain etc.) needed by the downstream code, so that the code can simply get hold of an instance of CarbonContext or PrivilegedCarbonContext, and start using it. Populating this data can be done using the following setter methods.

setTenantId(int tenantId)

This method sets the tenant ID in the CarbonContext. The tenant domain corresponding to this tenant ID will not be resolved.

setTenantId(int tenantId, boolean resolveTenantDomain)

This method sets the tenant ID in the CarbonContext. The tenant domain corresponding to this tenant ID will be resolved, if resolveTenantDomain is set to true.

setUsername(String username)

If there is a user logged in, this method sets that user's username in the PrivilegedCarbonContext.

setTenantDomain(String tenantDomain)

This method sets the tenant domain on this CarbonContext instance. This method will not automatically resolve the tenant ID based on the tenant domain.

setTenantDomain(String tenantDomain, boolean resolveTenantId)

This method sets the tenant domain on this CarbonContext instance. If resolveTenantId is set to true, the tenant ID corresponding to the tenantDomain will be resolved internally.

setApplicationName(String applicationName)

This method sets the name of the webapp or service to which the request was destined.

setUserRealm(UserRealm userRealm)

This method sets the tenant specific UserRealm.

setRegistry(RegistryType type, Registry registry)

This method sets the tenant specific registry.

RegistryTypes

  • USER_CONFIGURATION - The configuration registry of the currently logged in user.
  • USER_GOVERNANCE - The governance registry of the currently logged in user.
  • SYSTEM_CONFIGURATION - The configuration registry of the system.
  • LOCAL_REPOSITORY - The local repository of the system.

Switching tenant flows

During an execution flow, sometimes you will need to switch from super tenant mode to tenant mode, do some work as that tenant, and then get back to super tenant mode. In such a scenario, you will do the following:

  1. Start the Tenant Flow.

  2. Set the tenant ID and the tenant domain in the new CarbonContext data holder that gets created when you start the tenant flow.

  3. Carryout the respective action.

  4. End the tenant flow.

Always follow the following template when you carryout the latter mentioned steps:

try{
   PrivilegedCarbonContext.startTenantFlow();
   PrivilegedCarbonContext privilegedCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext()
   privilegedCarbonContext.setTenantId(tenantId);
   privilegedCarbonContext.setTenantDomain(tenantDomain);
   // set other stuff like registry etc. if needed

  doSomething();
} finally {
   PrivilegedCarbonContext.endTenantFlow();
}

Inside the doSomething() method, now if you call CarbonContext or PrivilegedCarbonContext.getThreadLocalCarbonContext, you will get the newly created data. The code that started the tenant flow is referred to as the upstream code, and all the code that gets called after starting the tenant flow are referred to as the downstream code. One example where you may start a tenant flow is when the super tenant runs tasks on behalf of a tenant. In the latter mentioned instance it may have a loop; and within that loop start a tenant flow for tenants, run the task as that tenant, get back to the super tenant mode (endTenantFlow), switch back to another tenant(startTenantFlow), run the task of the second tenant, get back to super tenant mode, and so on.

In most situations you will not need to start a tenant flow since you will not generally switch to tenant mode from super tenant mode.

PrivilegedCarbonContext.startTenantFlow()

This method starts a new tenant flow, and creates a new holder for tenant data. Thereafter, until endTenantFlow is called, the getCarbonContext() and getThreadLocalCarbonContext()methods will return the data related to the newly created tenant data holder. Once startTenantFlow is called, set the tenant ID, tenant domain and other tenant specific data.

PrivilegedCarbonContext.endTenantFlow()

This methods will end the tenant flow and restore the previous CarbonContext.

The following diagram depicts during an execution of a thread, how we can start as a super tenant, then switch to tenant 'x' and carryout some actions, and later switch to tenant 'y' and carryout some actions and continue.

Getting Information from PrivilegedCarbonContext

getTenantDomain(boolean resolve)

This method retrieves the tenant domain, and if resolve is set to true, it will try to resolve the domain using the tenant ID.

getTenantId(boolean resolve)

This method retrieves the tenant ID, and if resolve is set to true, it will try to resolve the tenant ID using the tenant domain.

getRegistry(RegistryType type)

This method retrieves the Registry of the tenant of type RegistryType.

RegistryTypes

  • SYSTEM_CONFIGURATION - The system configuration registry of the tenant.
  • SYSTEM_GOVERNANCE - The governance registry of the tenant.
Object getOSGiService(Class clazz)

This method obtains the first instance of the OSGi services found for the interface or class clazz.

Note that this method is depreciated in Carbon 4.3.0. The new method is getOSGiService(Class clazz, Hashtable<String, String> props). 

List<Object> getOSGiServices(Class clazz)

This method obtai ns all OSGi service instances found for interface or class clazz. 

Note that this method is depreciated in Carbon 4.3.0. The new method is List<Object> getOSGiServices(Class clazz, Hashtable<String, String> props).

Miscellaneous Methods

public static void unloadTenant(int tenantId)

This method unloads the tenant.

public static void destroyCurrentContext()

This method destroys the current ThreadLocal CarbonContext.

CarbonContext

The CarbonContext is designed for normal tenants to retrieve information from the Carbon runtime. In the super tenant mode, for this to work the relevant data has to be set so that tenants can retrieve information using the CarbonContext.

Obtaining the CarbonContext

getThreadLocalCarbonContext()

This method obtains the CarbonContext by using the data stored in the current thread: The CarbonContext.getThreadLocalCarbonContext().

Retrieving information

The following methods allow tenants to retrieve information relevant to those tenants from the Carbon runtime.

public int getTenantId()

This method retrieves the tenant ID.

String getUsername()

This method retrieves the tenant's username.

String getTenantDomain()

This method retrieves the tenant domain.

Registry getRegistry(RegistryType type)

This method retrieves the tenant specific registry.

Registry Types

  • USER_CONFIGURATION - The configuration registry of the currently logged in user.
  • USER_GOVERNANCE - The governance registry of the currently logged in user.
  • SYSTEM_CONFIGURATION - The configuration registry of the system.
  • SYSTEM_GOVERNANCE - The governance registry of the system.
  • LOCAL_REPOSITORY - The local repository of the system.
UserRealm getUserRealm()

This method retrieves the user realm of the current tenant.

CarbonQueue<?> getQueue(String name)

This method obtains a named queue instance.

Context getJNDIContext(Hashtable properties) throws NamingException

This method obtains a JNDI-context with the given initialization properties.

Method description
properties - the properties required to create the JNDI-context instance.
NamingException - if the operation fails, the naming exception will be thrown.

Context getJNDIContext() throws NamingException

This method obtains a JNDI-context.

Method description
NamingException - if the operation fails, the naming exception will be thrown.

String[] discover(URI[] scopes)

This method is used to discover a set of service endpoints belonging the defined scopes. Therefore, when this method is executed the list of service endpoints will be returned.

Method description
scopes - the scopes in which to look-up for the service.

com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.