/*
* Copyright (c) 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.identity.entitlement.policy.publisher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.entitlement.EntitlementException;
import org.wso2.carbon.identity.entitlement.PAPStatusDataHandler;
import org.wso2.carbon.identity.entitlement.PDPConstants;
import org.wso2.carbon.identity.entitlement.common.EntitlementConstants;
import org.wso2.carbon.identity.entitlement.dto.PolicyDTO;
import org.wso2.carbon.identity.entitlement.dto.PublisherDataHolder;
import org.wso2.carbon.identity.entitlement.dto.StatusHolder;
import org.wso2.carbon.identity.entitlement.internal.EntitlementServiceComponent;
import org.wso2.carbon.identity.entitlement.pap.EntitlementAdminEngine;
import org.wso2.carbon.identity.entitlement.policy.version.PolicyVersionManager;
import org.wso2.carbon.registry.api.Registry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* Policy publish executor
*/
public class PolicyPublishExecutor implements Runnable {
private static Log log = LogFactory.getLog(PolicyPublishExecutor.class);
private String[] policyIds;
private String[] subscriberIds;
private PolicyPublisher publisher;
private String version;
private String action;
private String verificationCode;
private boolean toPDP;
private String tenantDomain;
private int tenantId;
private String userName;
private int order;
private boolean enabled;
public PolicyPublishExecutor(String[] policyIds, String version, String action, boolean enabled, int order,
String[] subscriberIds, PolicyPublisher publisher,
boolean toPDP, String verificationCode) {
this.policyIds = policyIds;
if (toPDP) {
this.subscriberIds = new String[]{"PDPSubscriber"};
}
this.subscriberIds = subscriberIds;
this.action = action;
this.version = version;
this.publisher = publisher;
this.toPDP = toPDP;
this.order = order;
this.enabled = enabled;
this.verificationCode = verificationCode;
}
public void run() {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext context = PrivilegedCarbonContext.getThreadLocalCarbonContext();
context.setTenantDomain(tenantDomain);
context.setTenantId(tenantId);
context.setUsername(userName);
try {
publish();
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
public void publish() {
if ((policyIds == null || policyIds.length > 0) && verificationCode != null) {
loadVerificationCode(verificationCode);
}
String newVerificationCode = null;
ArrayList<String> notPublishedSubscribers = new ArrayList<String>();
PolicyPublisherModule policyPublisherModule = null;
Set<PolicyPublisherModule> publisherModules = publisher.getPublisherModules();
if (publisherModules == null) {
return;
}
PublisherDataHolder holder = null;
Set<PAPStatusDataHandler> papStatusDataHandler = publisher.getPapStatusDataHandlers();
for (String subscriberId : subscriberIds) {
// there is only one known subscriber, if policies are publishing to PDP
List<StatusHolder> subscriberHolders = new ArrayList<StatusHolder>();
List<StatusHolder> policyHolders = new ArrayList<StatusHolder>();
if (toPDP) {
policyPublisherModule = new CarbonPDPPublisher();
holder = new PublisherDataHolder(policyPublisherModule.getModuleName());
} else {
try {
holder = publisher.retrieveSubscriber(subscriberId, true);
} catch (EntitlementException e) {
log.error("Subscriber details can not be retrieved. So skip publishing policies " +
"for subscriber : " + subscriberId);
}
if (holder != null) {
for (PolicyPublisherModule publisherModule : publisherModules) {
if (publisherModule.getModuleName().equals(holder.getModuleName())) {
policyPublisherModule = publisherModule;
if (policyPublisherModule instanceof AbstractPolicyPublisherModule) {
try {
((AbstractPolicyPublisherModule) policyPublisherModule).init(holder);
} catch (Exception e) {
subscriberHolders.add(new StatusHolder(EntitlementConstants.StatusTypes.PUBLISH_POLICY,
subscriberId, version, "More than one Policy", action, false, e.getMessage()));
continue;
}
}
break;
}
}
}
}
if (policyPublisherModule == null) {
subscriberHolders.add(new StatusHolder(EntitlementConstants.StatusTypes.PUBLISH_POLICY,
subscriberId, version, "More than one Policy", action, false,
"No policy publish module is defined for subscriber : " + subscriberId));
continue;
}
// try with post verification module.
try {
PublisherVerificationModule verificationModule = publisher.getVerificationModule();
if (verificationModule != null && !verificationModule.doVerify(verificationCode)) {
newVerificationCode = verificationModule.getVerificationCode(holder);
notPublishedSubscribers.add(subscriberId);
break;
}
} catch (EntitlementException e) {
// ignore
log.error("Error while calling the post verification publisher module", e);
}
for (String policyId : policyIds) {
PolicyDTO policyDTO = null;
if (EntitlementConstants.PolicyPublish.ACTION_CREATE.equalsIgnoreCase(action) ||
EntitlementConstants.PolicyPublish.ACTION_UPDATE.equalsIgnoreCase(action)) {
PolicyVersionManager manager = EntitlementAdminEngine.getInstance().getVersionManager();
try {
policyDTO = manager.getPolicy(policyId, version);
} catch (EntitlementException e) {
// ignore
}
} else {
policyDTO = new PolicyDTO();
policyDTO.setPolicyId(policyId);
policyDTO.setVersion(version);
policyDTO.setPolicyOrder(order);
}
if (policyDTO == null) {
subscriberHolders.add(new StatusHolder(EntitlementConstants.StatusTypes.PUBLISH_POLICY,
subscriberId, version, policyId, action, false,
"Can not found policy under policy id : " + policyId));
policyHolders.add(new StatusHolder(EntitlementConstants.StatusTypes.PUBLISH_POLICY,
policyId, version, subscriberId, action, false,
"Can not found policy under policy id : " + policyId));
continue;
}
try {
policyPublisherModule.publish(policyDTO, action, enabled, order);
subscriberHolders.add(new StatusHolder(EntitlementConstants.StatusTypes.PUBLISH_POLICY,
subscriberId, version, policyId, action));
policyHolders.add(new StatusHolder(EntitlementConstants.StatusTypes.PUBLISH_POLICY,
policyId, version, subscriberId, action));
} catch (Exception e) {
subscriberHolders.add(new StatusHolder(EntitlementConstants.StatusTypes.PUBLISH_POLICY,
subscriberId, version, policyId, action, false, e.getMessage()));
policyHolders.add(new StatusHolder(EntitlementConstants.StatusTypes.PUBLISH_POLICY,
policyId, version, subscriberId, action, false, e.getMessage()));
}
for (PAPStatusDataHandler module : papStatusDataHandler) {
try {
module.handle(EntitlementConstants.Status.ABOUT_POLICY, policyId, policyHolders);
policyHolders = new ArrayList<StatusHolder>();
} catch (EntitlementException e) {
// ignore
log.error("Error while calling post publishers", e);
}
}
}
for (PAPStatusDataHandler module : papStatusDataHandler) {
try {
module.handle(EntitlementConstants.Status.ABOUT_SUBSCRIBER, subscriberId, subscriberHolders);
subscriberHolders = new ArrayList<StatusHolder>();
} catch (EntitlementException e) {
// ignore
log.error("Error while calling post publishers", e);
}
}
}
if (newVerificationCode != null) {
persistVerificationCode(newVerificationCode,
notPublishedSubscribers.toArray(new String[notPublishedSubscribers.size()]));
}
}
/**
* Helper method
*
* @param verificationCode verificationCode as String
* @param subscriberIds Array of subscriberIds
*/
private void persistVerificationCode(String verificationCode, String[] subscriberIds) {
Registry registry = EntitlementServiceComponent.
getGovernanceRegistry(CarbonContext.getThreadLocalCarbonContext().getTenantId());
try {
org.wso2.carbon.registry.api.Resource resource = registry.newResource();
resource.setProperty("subscriberIds", Arrays.asList(subscriberIds));
resource.setProperty("policyIds", Arrays.asList(policyIds));
resource.setProperty("action", action);
resource.setProperty("version", version);
resource.setProperty("order", Integer.toString(order));
registry.put(PDPConstants.ENTITLEMENT_POLICY_PUBLISHER_VERIFICATION + verificationCode,
resource);
} catch (org.wso2.carbon.registry.api.RegistryException e) {
log.error("Error while persisting verification code", e);
}
}
/**
* Helper method
*
* @param verificationCode verificationCode as String
*/
private void loadVerificationCode(String verificationCode) {
Registry registry = EntitlementServiceComponent.
getGovernanceRegistry(CarbonContext.getThreadLocalCarbonContext().getTenantId());
try {
org.wso2.carbon.registry.api.Resource resource = registry.
get(PDPConstants.ENTITLEMENT_POLICY_PUBLISHER_VERIFICATION + verificationCode);
List<String> list = resource.getPropertyValues("subscriberIds");
if (list != null) {
subscriberIds = list.toArray(new String[list.size()]);
}
list = resource.getPropertyValues("policyIds");
if (list != null) {
policyIds = list.toArray(new String[list.size()]);
}
String version = resource.getProperty("version");
if (version != null) {
this.version = version;
}
String action = resource.getProperty("action");
if (action != null) {
this.action = action;
}
String order = resource.getProperty("order");
if (order != null) {
this.order = Integer.parseInt(order);
}
} catch (org.wso2.carbon.registry.api.RegistryException e) {
log.error("Error while loading verification code", e);
}
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public void setUserName(String userName) {
this.userName = userName;
}
}