Package org.wso2.carbon.core.multitenancy.utils

Source Code of org.wso2.carbon.core.multitenancy.utils.TenantAxisUtils

/*
*  Copyright (c) 2005-2009, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. 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.
*
*/
package org.wso2.carbon.core.multitenancy.utils;

import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.transport.TransportListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import org.wso2.carbon.core.internal.CarbonCoreDataHolder;
import org.wso2.carbon.core.multitenancy.SuperTenantCarbonContext;
import org.wso2.carbon.core.multitenancy.TenantAxisConfigurator;
import org.wso2.carbon.core.multitenancy.transports.DummyTransportListener;
import org.wso2.carbon.core.multitenancy.transports.TenantTransportInDescription;
import org.wso2.carbon.core.multitenancy.transports.TenantTransportSender;
import org.wso2.carbon.core.transports.TransportPersistenceManager;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.user.core.tenant.Tenant;
import org.wso2.carbon.user.core.tenant.TenantManager;
import org.wso2.carbon.utils.Axis2ConfigurationContextObserver;
import org.wso2.carbon.utils.ServerConstants;
import org.wso2.carbon.utils.multitenancy.CarbonContextHolder;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* Utility methods for Tenant Operations at Axis2-level.
*/
@SuppressWarnings("unused")
public class TenantAxisUtils {

    private static final Log log = LogFactory.getLog(TenantAxisUtils.class);
    private static final String TENANT_CONFIGURATION_CONTEXTS = "tenant.config.contexts";
    private static CarbonCoreDataHolder dataHolder = CarbonCoreDataHolder.getInstance();

    /**
     * Get tenant ID from config context
     *
     * @param configCtx The config context
     * @return The tenant ID
     * @deprecated use {@link MultitenantUtils#getTenantId(ConfigurationContext)}
     */
    public static int getTenantId(ConfigurationContext configCtx) {
        return MultitenantUtils.getTenantId(configCtx);
    }

    public static AxisConfiguration getTenantAxisConfiguration(String tenant,
                                                               ConfigurationContext mainConfigCtx) {
        ConfigurationContext tenantConfigCtx = getTenantConfigurationContext(tenant, mainConfigCtx);
        if (tenantConfigCtx != null) {
            return tenantConfigCtx.getAxisConfiguration();
        }
        return null;
    }

    public static ConfigurationContext
    getTenantConfigurationContextFromUrl(String url, ConfigurationContext mainConfigCtx) {
        String tenantDomain = MultitenantUtils.getTenantDomainFromUrl(url);
        return getTenantConfigurationContext(tenantDomain, mainConfigCtx);
    }

    public static ConfigurationContext
    getTenantConfigurationContext(String tenantDomain, ConfigurationContext mainConfigCtx) {
        synchronized (tenantDomain.intern()) { // lock based on tenant domain
            Map<String, ConfigurationContext> tenantConfigContexts = getTenantConfigurationContexts(mainConfigCtx);
            ConfigurationContext tenantConfigCtx =
            tenantConfigContexts.get(tenantDomain);
            if (tenantConfigCtx == null) {
                try {
                    tenantConfigCtx = createTenantConfigurationContext(mainConfigCtx, tenantDomain);
                } catch (Exception e) {
                    throw new RuntimeException("Cannot create tenant ConfigurationContext for tenant " +
                                               tenantDomain, e);
                }
            }
            try {
                tenantConfigCtx.getAxisConfiguration().
                        addParameter(MultitenantConstants.LAST_ACCESSED, System.currentTimeMillis());

                Map<String, ConfigurationContext> tenantConfigCtxs =
                        getTenantConfigurationContexts(mainConfigCtx);

                // if everything is succesfull we add the configuration context to the map
                tenantConfigContexts.put(tenantDomain, tenantConfigCtx);
            } catch (AxisFault e) {
                log.error("Cannot set last accessed time for tenant " + tenantDomain, e);
            }
            return tenantConfigCtx;
        }
    }

    public static long getLastAccessed(String tenantDomain, ConfigurationContext mainConfigCtx) {
        Map<String, ConfigurationContext> tenantConfigContexts = getTenantConfigurationContexts(mainConfigCtx);
        ConfigurationContext tenantConfigCtx =
        tenantConfigContexts.get(tenantDomain);
        if (tenantConfigCtx != null) {
            Parameter lastAccessedParam =
                    tenantConfigCtx.getAxisConfiguration().
                            getParameter(MultitenantConstants.LAST_ACCESSED);
            return lastAccessedParam == null ? -1 : (Long) lastAccessedParam.getValue();
        }
        return -1;
    }

    public static void setTenantAccessed(String tenantDomain, ConfigurationContext mainConfigCtx) {
        getTenantConfigurationContext(tenantDomain, mainConfigCtx);
    }

    /**
     * @param url               will have pattern <some-string>/t/<tenant>/<service>?<some-params>
     * @param mainConfigContext The main ConfigurationContext from the server
     * @return The tenant's AxisService
     * @throws org.apache.axis2.AxisFault If an error occurs while retrieving the AxisService
     */
    public static AxisService getAxisService(String url, ConfigurationContext mainConfigContext)
            throws AxisFault {
        String[] strings = url.split("/");
        boolean foundTenantDelimiter = false;
        String tenant = null;
        String service = null;
        for (String str : strings) {
            if (!foundTenantDelimiter && str.equals("t")) {
                foundTenantDelimiter = true;
                continue;
            }
            if (foundTenantDelimiter & tenant == null) {
                tenant = str;
                continue;
            }
            if (tenant != null) {
                if (service == null) {
                    service = str;
                } else {
                    service += "/" + str;
                }
            }
        }
        if (service != null) {
            service = service.split("\\?")[0];
            AxisConfiguration tenantAxisConfig =
                    getTenantAxisConfiguration(tenant, mainConfigContext);
            if (tenantAxisConfig != null) {
                return tenantAxisConfig.getServiceForActivation(service);
            }
        }
        return null;
    }

    /**
     * Get all the tenant ConfigurationContexts
     *
     * @param mainConfigCtx Super-tenant Axis2 ConfigurationContext
     * @return the tenant ConfigurationContexts as a Map of "tenant domain -> ConfigurationContext"
     */
    @SuppressWarnings("unchecked")
    public static Map<String, ConfigurationContext>
    getTenantConfigurationContexts(ConfigurationContext mainConfigCtx) {
        Map<String, ConfigurationContext> tenantConfigContexts = (Map<String, ConfigurationContext>)
                mainConfigCtx.getProperty(TENANT_CONFIGURATION_CONTEXTS);
        if (tenantConfigContexts == null) {
            tenantConfigContexts = new ConcurrentHashMap<String, ConfigurationContext>();
            mainConfigCtx.setProperty(TENANT_CONFIGURATION_CONTEXTS, tenantConfigContexts);
        }
        return tenantConfigContexts;
    }

    /**
     * Set the transports for the tenants
     *
     * @param mainConfigCtx The main config context
     * @throws AxisFault If an error occurs while initializing tenant transports
     */
    @SuppressWarnings("unchecked")
    public static void initializeTenantTransports(ConfigurationContext mainConfigCtx)
            throws AxisFault {
        AxisConfiguration mainAxisConfig = mainConfigCtx.getAxisConfiguration();
        Map<String, ConfigurationContext> tenantConfigContexts =
                getTenantConfigurationContexts(mainConfigCtx);
        if (tenantConfigContexts != null) {
            for (Map.Entry<String, ConfigurationContext> entry : tenantConfigContexts.entrySet()) {
                String tenantDomain = entry.getKey();
                ConfigurationContext tenantConfigCtx = entry.getValue();
                AxisConfiguration tenantAxisConfig = tenantConfigCtx.getAxisConfiguration();
                // Add the transports that are made available in the main axis2.xml file
                setTenantTransports(mainAxisConfig, tenantDomain, tenantAxisConfig);
            }
        }
    }

    public static void setTenantTransports(AxisConfiguration mainAxisConfig, String tenantDomain,
                                           AxisConfiguration tenantAxisConfig) throws AxisFault {
        for (String transport : mainAxisConfig.getTransportsIn().keySet()) {
            TenantTransportInDescription tenantTransportIn =
                    new TenantTransportInDescription(transport);
            tenantTransportIn
                    .setMainTransportInDescription(mainAxisConfig.getTransportsIn().get(transport));
            TransportListener mainTransportListener =
                    mainAxisConfig.getTransportIn(transport).getReceiver();
            tenantTransportIn.setReceiver(new DummyTransportListener(mainTransportListener,
                                                                     tenantDomain));
            tenantAxisConfig.addTransportIn(tenantTransportIn);
        }
    }

    /**
     * Create Tenant Axis2 ConfigurationContexts & add them to the main Axis2 ConfigurationContext
     *
     * @param mainConfigCtx Super-tenant Axis2 ConfigurationContext
     * @param tenantDomain  Tenant domain (e.g. foo.com)
     * @return The newly created Tenant ConfigurationContext
     * @throws Exception If an error occurs while creating tenant ConfigurationContext
     */
    public static ConfigurationContext
    createTenantConfigurationContext(ConfigurationContext mainConfigCtx,
                                     String tenantDomain) throws Exception {
        int tenantId = getTenantId(tenantDomain);
        if (tenantId == 0 || tenantId == -1) {
            throw new Exception("Tenant " + tenantDomain + " does not exist");
        }
        AxisConfiguration mainAxisConfig = mainConfigCtx.getAxisConfiguration();

        try {
            UserRegistry tenantConfigRegistry =
                    dataHolder.getRegistryService().getConfigSystemRegistry(tenantId);
            UserRegistry tenantLocalUserRegistry =
                    dataHolder.getRegistryService().getLocalRepository(tenantId);
            TenantAxisConfigurator tenantAxisConfigurator =
                    new TenantAxisConfigurator(mainAxisConfig, tenantDomain, tenantId,
                                               tenantConfigRegistry, tenantLocalUserRegistry);
            doPreConfigContextCreation(tenantId);
            ConfigurationContext tenantConfigCtx =
                    ConfigurationContextFactory.createConfigurationContext(tenantAxisConfigurator);

            tenantConfigCtx.setServicePath("axis2services");
            tenantConfigCtx.setContextRoot("local:/");

            AxisConfiguration tenantAxisConfig = tenantConfigCtx.getAxisConfiguration();

            TenantTransportSender transportSender = new TenantTransportSender(mainConfigCtx);
            //adding new transport outs
            // adding the two tenant specific transport senders
            TransportOutDescription httpOutDescription = new TransportOutDescription(Constants.TRANSPORT_HTTP);
            httpOutDescription.setSender(transportSender);
            tenantAxisConfig.addTransportOut(httpOutDescription);

            // adding the two tenant specific transport senders
            TransportOutDescription httpsOutDescription = new TransportOutDescription(Constants.TRANSPORT_HTTPS);
            httpsOutDescription.setSender(transportSender);
            tenantAxisConfig.addTransportOut(httpsOutDescription);

            // Set the work directory
            tenantConfigCtx.setProperty(ServerConstants.WORK_DIR,
                                        mainConfigCtx.getProperty(ServerConstants.WORK_DIR));
            SuperTenantCarbonContext.getCurrentContext(tenantConfigCtx).setTenantId(tenantId);
            new TransportPersistenceManager(tenantAxisConfig).
                    updateEnabledTransports(tenantAxisConfig.getTransportsIn().values(),
                                            tenantAxisConfig.getTransportsOut().values());

            CarbonContextHolder.getThreadLocalCarbonContextHolder().setTenantId(tenantId);
            // Notify all observers
            BundleContext bundleContext = dataHolder.getBundleContext();
            if (bundleContext != null) {
                ServiceTracker tracker =
                        new ServiceTracker(bundleContext,
                                           Axis2ConfigurationContextObserver.class.getName(), null);
                tracker.open();
                Object[] services = tracker.getServices();
                if (services != null) {
                    for (Object service : services) {
                        ((Axis2ConfigurationContextObserver) service).createdConfigurationContext(tenantConfigCtx);
                    }
                }
                tracker.close();
            }
            return tenantConfigCtx;
        } catch (Exception e) {
            String msg = "Error occurred while running deployment for tenant ";
            log.error(msg + tenantDomain, e);
            throw new Exception(msg, e);
        }
    }

    /**
     * Get the list of all active tenants in the system
     *
     * @param mainConfigCtx The main super-tenant ConfigurationContext
     * @return The list of active tenants
     * @throws Exception If an error occurs while retrieving tenants
     */
    public static List<Tenant> getActiveTenants(ConfigurationContext mainConfigCtx)
            throws Exception {
        Map<String, ConfigurationContext> tenantConfigContexts =
                getTenantConfigurationContexts(mainConfigCtx);
        List<Tenant> tenants = new ArrayList<Tenant>();
        try {
            TenantManager tenantManager =
                    dataHolder.getRealmService().getTenantManager();
            for (ConfigurationContext tenantCfgCtx : tenantConfigContexts.values()) {
                Tenant tenant = (Tenant)tenantManager.getTenant(MultitenantUtils.getTenantId(tenantCfgCtx));
                tenants.add(tenant);
            }
        } catch (Exception e) {
            String msg = "Error occurred while getting active tenant list";
            log.error(msg, e);
            throw new Exception(msg, e);
        }
        return tenants;
    }

    /**
     * Get the tenantID given the domain
     *
     * @param tenantDomain The tenant domain
     * @return The tenant ID
     * @throws Exception If an error occurs while retrieving tenant ID
     */
    private static int getTenantId(String tenantDomain) throws Exception {
        return dataHolder.getRealmService().getTenantManager().getTenantId(tenantDomain);
    }

    /**
     * Traverse the list of tenants and cleanup tenants which have been idling for longer than
     * <code>tenantIdleTimeMillis</code>
     *
     * @param tenantIdleTimeMillis The maximum tenant idle time in milliseconds
     */
    public static void cleanupTenants(long tenantIdleTimeMillis) {
        ConfigurationContext mainServerConfigContext =
                CarbonCoreDataHolder.getInstance().getMainServerConfigContext();
        if (mainServerConfigContext == null) {
            return;
        }
        Map<String, ConfigurationContext> tenantConfigContexts =
                getTenantConfigurationContexts(mainServerConfigContext);
        for (Map.Entry<String, ConfigurationContext> entry : tenantConfigContexts.entrySet()) {
            String tenantDomain = entry.getKey();
            ConfigurationContext tenantCfgCtx = entry.getValue();
            Parameter lastAccessed =
                    tenantCfgCtx.getAxisConfiguration().getParameter(MultitenantConstants.LAST_ACCESSED);
            if (lastAccessed == null ||
                System.currentTimeMillis() - (Long) lastAccessed.getValue() >= tenantIdleTimeMillis) {
                terminateTenantConfigContext(tenantCfgCtx);
            }
        }
    }

    /**
     * Terminate the provided Tenant ConfigurationContext
     *
     * @param tenantCfgCtx The tenant ConfigurationContext which needs to be terminated
     */
    public static void terminateTenantConfigContext(ConfigurationContext tenantCfgCtx) {
        ConfigurationContext mainServerConfigContext =
                CarbonCoreDataHolder.getInstance().getMainServerConfigContext();
        Map<String, ConfigurationContext> tenantConfigContexts =
                getTenantConfigurationContexts(mainServerConfigContext);
        String tenantDomain = SuperTenantCarbonContext.getCurrentContext(tenantCfgCtx).getTenantDomain();
        try {
            doPreConfigContextTermination(tenantCfgCtx);
            tenantCfgCtx.shutdownModulesAndServices();
            tenantCfgCtx.terminate();
            doPostConfigContextTermination(tenantCfgCtx);
            tenantConfigContexts.remove(tenantDomain);
            log.info("Cleaned up tenant " + tenantDomain);
        } catch (AxisFault e) {
            log.error("Cannot cleanup ConfigurationContext of tenant " + tenantDomain, e);
        }
    }

    private static void doPreConfigContextCreation(int tenantId) {
        BundleContext bundleContext = CarbonCoreDataHolder.getInstance().getBundleContext();
        if (bundleContext != null) {
            ServiceTracker tracker =
                    new ServiceTracker(bundleContext,
                                       Axis2ConfigurationContextObserver.class.getName(), null);
            tracker.open();
            Object[] services = tracker.getServices();
            if (services != null) {
                for (Object service : services) {
                    ((Axis2ConfigurationContextObserver) service).
                            creatingConfigurationContext(tenantId);
                }
            }
            tracker.close();
        }
    }

    private static void doPreConfigContextTermination(ConfigurationContext tenantCfgCtx) {
        BundleContext bundleContext = CarbonCoreDataHolder.getInstance().getBundleContext();
        if (bundleContext != null) {
            ServiceTracker tracker =
                    new ServiceTracker(bundleContext,
                                       Axis2ConfigurationContextObserver.class.getName(), null);
            tracker.open();
            Object[] services = tracker.getServices();
            if (services != null) {
                for (Object service : services) {
                    ((Axis2ConfigurationContextObserver) service).
                            terminatingConfigurationContext(tenantCfgCtx);
                }
            }
            tracker.close();
        }
    }

    private static void doPostConfigContextTermination(ConfigurationContext tenantCfgCtx) {
        BundleContext bundleContext = CarbonCoreDataHolder.getInstance().getBundleContext();
        if (bundleContext != null) {
            ServiceTracker tracker =
                    new ServiceTracker(bundleContext,
                                       Axis2ConfigurationContextObserver.class.getName(), null);
            tracker.open();
            Object[] services = tracker.getServices();
            if (services != null) {
                for (Object service : services) {
                    ((Axis2ConfigurationContextObserver) service).
                            terminatedConfigurationContext(tenantCfgCtx);
                }
            }
            tracker.close();
        }
    }
}
TOP

Related Classes of org.wso2.carbon.core.multitenancy.utils.TenantAxisUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.