/*
* Copyright WSO2, Inc. (http://wso2.com)
*
* Licensed 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.cloud.gateway.agent.internal;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.cloud.gateway.agent.observer.CGServiceObserver;
import org.wso2.carbon.cloud.gateway.agent.service.CGAgentAdminService;
import org.wso2.carbon.cloud.gateway.common.CGConstant;
import org.wso2.carbon.cloud.gateway.common.CGException;
import org.wso2.carbon.cloud.gateway.common.CGUtils;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.util.SystemFilter;
import org.wso2.carbon.user.api.AuthorizationManager;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.UserCoreConstants;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.util.UserCoreUtil;
import org.wso2.carbon.user.mgt.UserMgtConstants;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.ConfigurationContextService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @scr.component name="org.wso2.carbon.cloud.gateway.agent.internal.CGAgentServiceComponent" immediate="true"
* @scr.reference name="user.realmservice.default"
* interface="org.wso2.carbon.user.core.service.RealmService"
* cardinality="1..1"
* policy="dynamic" bind="setRealmService"
* unbind="unsetRealmService"
* @scr.reference name="config.context.service"
* interface="org.wso2.carbon.utils.ConfigurationContextService"
* cardinality="1..1"
* policy="dynamic"
* bind="setConfigurationContextService"
* unbind="unsetConfigurationContextService"
*/
@SuppressWarnings({"UnusedDeclaration"})
public class CGAgentServiceComponent {
private static Log log = LogFactory.getLog(CGAgentServiceComponent.class);
private ConfigurationContextService configurationContextService;
private RealmService realmService;
private long initialReconnectDuration;
private double reconnectionProgressionFactor;
protected void activate(ComponentContext context) {
if (this.configurationContextService == null) {
log.error("Cloud not activated the CGAgentServiceComponent. " +
"ConfigurationContextService is null!");
return;
}
initialReconnectDuration = CGUtils.getLongProperty(CGConstant.INITIAL_RECONNECT_DURATION, 10000);
reconnectionProgressionFactor = CGUtils.getDoubleProperty(CGConstant.PROGRESSION_FACTOR, 2.0);
String[] publishOptimizedList = UserCoreUtil.optimizePermissions(
CGConstant.CG_PUBLISH_PERMISSION_LIST);
String[] unpublishOptimizedList = UserCoreUtil.optimizePermissions(
CGConstant.CG_UNPUBLISH_PERMISSION_LIST);
try {
// add the publish and un publish roles
UserRealm realm = realmService.getBootstrapRealm();
String publisherRole = UserCoreConstants.INTERNAL_DOMAIN + CarbonConstants.DOMAIN_SEPARATOR + CGConstant.CG_PUBLISH_ROLE_NAME;
String unpublisherRole = UserCoreConstants.INTERNAL_DOMAIN + CarbonConstants.DOMAIN_SEPARATOR + CGConstant.CG_UNPUBLISH_ROLE_NAME;
AuthorizationManager authorizationManager = realm.getAuthorizationManager();
/* // Commenting the source to avoid database deadlock when clustered setup starts with shared database
authorizationManager.clearRoleActionOnAllResources(publisherRole,
UserMgtConstants.EXECUTE_ACTION);
authorizationManager.clearRoleActionOnAllResources(unpublisherRole,
UserMgtConstants.EXECUTE_ACTION);*/
for (String permission : publishOptimizedList) {
authorizationManager.authorizeRole(publisherRole, permission,
UserMgtConstants.EXECUTE_ACTION);
}
for (String permission : unpublishOptimizedList) {
authorizationManager.authorizeRole(unpublisherRole, permission,
UserMgtConstants.EXECUTE_ACTION);
}
String cgUserName = CGUtils.getStringProperty(CGConstant.CG_USER_NAME, CGConstant.DEFAULT_CG_USER);
String cgUserPassword = CGUtils.getStringProperty(CGConstant.CG_USER_PASSWORD,
CGConstant.DEFAULT_CG_USER_PASSWORD);
UserStoreManager manager = realm.getUserStoreManager();
if (!manager.isExistingRole(publisherRole)) {
manager.addRole(publisherRole, new String[]{realm.getRealmConfiguration().getAdminUserName()}, null);
}
if (!manager.isExistingRole(unpublisherRole)) {
manager.addRole(unpublisherRole, new String[]{realm.getRealmConfiguration().getAdminUserName()}, null);
}
new Thread(new ServiceRePublishingTask(), "Cloud-Gateway-re-publishing-thread").start();
} catch (Exception e) {
log.error("Cloud not activated the CGAgentServiceComponent. ", e);
return;
}
if (log.isDebugEnabled()) {
log.debug("Activated the CGAgentServiceComponent");
}
}
protected void deactivate(ComponentContext context) {
}
protected void setConfigurationContextService(ConfigurationContextService configCtxService) {
this.configurationContextService = configCtxService;
}
protected void unsetConfigurationContextService(ConfigurationContextService contextService) {
if (this.configurationContextService != null) {
this.configurationContextService = null;
}
}
protected void setRealmService(RealmService realmService) {
this.realmService = realmService;
}
protected void unsetRealmService(RealmService realmService) {
if (this.realmService != null) {
this.realmService = null;
}
}
private class ServiceRePublishingTask implements Runnable {
private CarbonContext carbonContext;
public ServiceRePublishingTask() {
this.carbonContext = CarbonContext.getThreadLocalCarbonContext();
}
public void run() {
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(carbonContext.getTenantDomain());
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(carbonContext.getTenantId());
long retryDuration = initialReconnectDuration;
while (true) {
if (CGUtils.isServerAlive("localhost",
CarbonUtils.getTransportPort(configurationContextService, "http"))) {
List<String> pendingServices = getPendingService();
CGAgentAdminService adminService = new CGAgentAdminService();
for (String serviceName : pendingServices) {
try {
boolean isAutomatic = adminService.getServiceStatus(serviceName).equals(
CGConstant.CG_SERVICE_STATUS_AUTO_MATIC);
String serverName = adminService.getPublishedServer(serviceName);
adminService.unPublishService(serviceName, serverName, true);
adminService.publishService(serviceName, serverName, isAutomatic);
} catch (CGException e) {
log.error("Error while re-publishing the previously published service '" + serviceName + "'," +
" you will need to re-publish the service manually!", e);
}
log.info("Service '" + serviceName + "', re-published successfully");
}
// register observers for automatic published services
CGServiceObserver observer = new CGServiceObserver();
configurationContextService.getServerConfigContext().getAxisConfiguration().addObservers(observer);
break;
} else {
// re-try until success
retryDuration = (long) (retryDuration * reconnectionProgressionFactor);
try {
Thread.sleep(retryDuration);
} catch (InterruptedException ignore) {
}
}
}
}
private List<String> getPendingService() {
AxisConfiguration axisConfig = configurationContextService.getServerConfigContext().getAxisConfiguration();
List<String> pendingServices = new ArrayList<String>();
for (Map.Entry<String, AxisService> entry : axisConfig.getServices().entrySet()) {
AxisService axisService = entry.getValue();
CGAgentAdminService service = new CGAgentAdminService();
String status = null;
try {
status = service.getServiceStatus(axisService.getName());
} catch (CGException e) {
log.error("Exception occurred while retrieving status for the " + axisService.getName());
}
if (SystemFilter.isAdminService(axisService) || SystemFilter.isHiddenService(axisService) ||
axisService.isClientSide() || status.equals(CGConstant.CG_SERVICE_STATUS_UNPUBLISHED)) {
continue;
}
pendingServices.add(axisService.getName());
}
return pendingServices;
}
}
}