/*
* 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;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.identity.entitlement.common.EntitlementConstants;
import org.wso2.carbon.identity.entitlement.dto.PublisherPropertyDTO;
import org.wso2.carbon.identity.entitlement.dto.StatusHolder;
import org.wso2.carbon.identity.entitlement.internal.EntitlementServiceComponent;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.RegistryConstants;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* TODO
*/
public class SimplePAPStatusDataHandler implements PAPStatusDataHandler {
private static final String ENTITLEMENT_POLICY_STATUS = "/repository/identity/entitlement/status/policy/";
private static final String ENTITLEMENT_PUBLISHER_STATUS = "/repository/identity/entitlement/status/publisher/";
private static final int SEARCH_BY_USER = 0;
private static final int SEARCH_BY_POLICY = 1;
private static Log log = LogFactory.getLog(SimplePAPStatusDataHandler.class);
private int DEFAULT_MAX_RECODES = 50;
private int maxRecodes;
@Override
public void init(Properties properties) {
String maxRecodesString = (String) properties.get("maxRecodesToPersist");
if (maxRecodesString != null) {
try {
maxRecodes = Integer.parseInt(maxRecodesString);
} catch (Exception e) {
//ignore
}
}
if (maxRecodes == 0) {
maxRecodes = DEFAULT_MAX_RECODES;
}
}
@Override
public void handle(String about, String key, List<StatusHolder> statusHolder)
throws EntitlementException {
if (EntitlementConstants.Status.ABOUT_POLICY.equals(about)) {
String path = ENTITLEMENT_POLICY_STATUS + key;
// policy would be deleted.
for (StatusHolder holder : statusHolder) {
if (EntitlementConstants.StatusTypes.DELETE_POLICY.equals(holder.getType())) {
deletedPersistedData(path);
return;
}
}
persistStatus(path, statusHolder, false);
} else {
String path = ENTITLEMENT_PUBLISHER_STATUS + key;
// subscriber would be deleted.
for (StatusHolder holder : statusHolder) {
if (EntitlementConstants.StatusTypes.DELETE_POLICY.equals(holder.getType())) {
deletedPersistedData(path);
return;
}
}
persistStatus(path, statusHolder, false);
}
}
@Override
public void handle(String about, StatusHolder statusHolder) throws EntitlementException {
List<StatusHolder> list = new ArrayList<StatusHolder>();
list.add(statusHolder);
handle(about, statusHolder.getKey(), list);
}
@Override
public StatusHolder[] getStatusData(String about, String key, String type, String searchString)
throws EntitlementException {
if (EntitlementConstants.Status.ABOUT_POLICY.equals(about)) {
String path = ENTITLEMENT_POLICY_STATUS + key;
List<StatusHolder> holders = readStatus(path, EntitlementConstants.Status.ABOUT_POLICY);
List<StatusHolder> filteredHolders = new ArrayList<StatusHolder>();
if (holders != null) {
searchString = searchString.replace("*", ".*");
Pattern pattern = Pattern.compile(searchString, Pattern.CASE_INSENSITIVE);
for (StatusHolder holder : holders) {
String id = holder.getUser();
Matcher matcher = pattern.matcher(id);
if (!matcher.matches()) {
continue;
}
if (type != null && type.equals(holder.getType())) {
filteredHolders.add(holder);
} else if (type == null) {
filteredHolders.add(holder);
}
}
}
return filteredHolders.toArray(new StatusHolder[filteredHolders.size()]);
} else {
List<StatusHolder> filteredHolders = new ArrayList<StatusHolder>();
String path = ENTITLEMENT_PUBLISHER_STATUS + key;
List<StatusHolder> holders = readStatus(path, EntitlementConstants.Status.ABOUT_SUBSCRIBER);
if (holders != null) {
searchString = searchString.replace("*", ".*");
Pattern pattern = Pattern.compile(searchString, Pattern.CASE_INSENSITIVE);
for (StatusHolder holder : holders) {
String id = holder.getTarget();
Matcher matcher = pattern.matcher(id);
if (!matcher.matches()) {
continue;
}
filteredHolders.add(holder);
}
}
return filteredHolders.toArray(new StatusHolder[filteredHolders.size()]);
}
}
private synchronized void deletedPersistedData(String path) throws EntitlementException {
Registry registry = null;
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
registry = EntitlementServiceComponent.getRegistryService().
getGovernanceSystemRegistry(tenantId);
if (registry.resourceExists(path)) {
registry.delete(path);
}
} catch (RegistryException e) {
log.error(e);
throw new EntitlementException("Error while persisting policy status", e);
}
}
private synchronized void persistStatus(String path, List<StatusHolder> statusHolders, boolean isNew)
throws EntitlementException {
Resource resource = null;
Registry registry = null;
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
registry = EntitlementServiceComponent.getRegistryService().
getGovernanceSystemRegistry(tenantId);
if (registry.resourceExists(path) && !isNew) {
resource = registry.get(path);
String[] versions = registry.getVersions(path);
// remove all versions. As we have no way to disable versioning for specific resource
if (versions != null) {
for (String version : versions) {
long versionInt = 0;
String[] versionStrings = version.split(RegistryConstants.VERSION_SEPARATOR);
if (versionStrings != null && versionStrings.length == 2) {
try {
versionInt = Long.parseLong(versionStrings[1]);
} catch (Exception e) {
// ignore
}
}
if (versionInt != 0) {
registry.removeVersionHistory(version, versionInt);
}
}
}
} else {
resource = registry.newResource();
}
if (resource != null && statusHolders != null && statusHolders.size() > 0) {
resource.setVersionableChange(false);
populateStatusProperties(statusHolders.toArray(new StatusHolder[statusHolders.size()]), resource);
registry.put(path, resource);
}
} catch (RegistryException e) {
log.error(e);
throw new EntitlementException("Error while persisting policy status", e);
}
}
private synchronized List<StatusHolder> readStatus(String path, String about) throws EntitlementException {
Resource resource = null;
Registry registry = null;
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
registry = EntitlementServiceComponent.getRegistryService().
getGovernanceSystemRegistry(tenantId);
if (registry.resourceExists(path)) {
resource = registry.get(path);
}
} catch (RegistryException e) {
log.error(e);
throw new EntitlementException("Error while persisting policy status", e);
}
List<StatusHolder> statusHolders = new ArrayList<StatusHolder>();
if (resource != null && resource.getProperties() != null) {
Properties properties = resource.getProperties();
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
PublisherPropertyDTO dto = new PublisherPropertyDTO();
dto.setId((String) entry.getKey());
Object value = entry.getValue();
if (value instanceof ArrayList) {
List list = (ArrayList) entry.getValue();
if (list != null && list.size() > 0 && list.get(0) != null) {
StatusHolder statusHolder = new StatusHolder(about);
if (list.size() > 0 && list.get(0) != null) {
statusHolder.setType((String) list.get(0));
}
if (list.size() > 1 && list.get(1) != null) {
statusHolder.setTimeInstance((String) list.get(1));
} else {
continue;
}
if (list.size() > 2 && list.get(2) != null) {
String user = (String) list.get(2);
statusHolder.setUser(user);
} else {
continue;
}
if (list.size() > 3 && list.get(3) != null) {
statusHolder.setKey((String) list.get(3));
}
if (list.size() > 4 && list.get(4) != null) {
statusHolder.setSuccess(Boolean.parseBoolean((String) list.get(4)));
}
if (list.size() > 5 && list.get(5) != null) {
statusHolder.setMessage((String) list.get(5));
}
if (list.size() > 6 && list.get(6) != null) {
statusHolder.setTarget((String) list.get(6));
}
if (list.size() > 7 && list.get(7) != null) {
statusHolder.setTargetAction((String) list.get(7));
}
if (list.size() > 8 && list.get(8) != null) {
statusHolder.setVersion((String) list.get(8));
}
statusHolders.add(statusHolder);
}
}
}
}
if (statusHolders.size() > 0) {
StatusHolder[] array = statusHolders.toArray(new StatusHolder[statusHolders.size()]);
java.util.Arrays.sort(array, new StatusHolderComparator());
if (statusHolders.size() > maxRecodes) {
statusHolders = new ArrayList<StatusHolder>();
for (int i = 0; i < maxRecodes; i++) {
statusHolders.add(array[i]);
}
persistStatus(path, statusHolders, true);
} else {
statusHolders = new ArrayList<StatusHolder>(Arrays.asList(array));
}
}
return statusHolders;
}
/**
* @param statusHolders
* @param resource
*/
private void populateStatusProperties(StatusHolder[] statusHolders, Resource resource) {
if (statusHolders != null) {
for (StatusHolder statusHolder : statusHolders) {
if (statusHolder != null) {
List<String> list = new ArrayList<String>();
list.add(statusHolder.getType());
list.add(statusHolder.getTimeInstance());
list.add(statusHolder.getUser());
list.add(statusHolder.getKey());
list.add(Boolean.toString(statusHolder.isSuccess()));
if (statusHolder.getMessage() != null) {
list.add(statusHolder.getMessage());
} else {
list.add("");
}
if (statusHolder.getTarget() != null) {
list.add(statusHolder.getTarget());
} else {
list.add("");
}
if (statusHolder.getTargetAction() != null) {
list.add(statusHolder.getTargetAction());
} else {
list.add("");
}
if (statusHolder.getVersion() != null) {
list.add(statusHolder.getVersion());
} else {
list.add("");
}
resource.setProperty(UUID.randomUUID().toString(), list);
}
}
}
}
}