/**
* =============================================================================
*
* ORCID (R) Open Source
* http://orcid.org
*
* Copyright (c) 2012-2014 ORCID, Inc.
* Licensed under an MIT-Style License (MIT)
* http://orcid.org/open-source-license
*
* This copyright and license information (including a link to the full license)
* shall be included in its entirety in all copies or substantial portion of
* the software.
*
* =============================================================================
*/
package org.orcid.core.cli;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.orcid.core.manager.ClientDetailsManager;
import org.orcid.jaxb.model.clientgroup.ClientType;
import org.orcid.jaxb.model.message.ScopePathType;
import org.orcid.persistence.jpa.entities.ClientDetailsEntity;
import org.orcid.persistence.jpa.entities.ClientScopeEntity;
import org.orcid.pojo.ajaxForm.PojoUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
/**
*
* @author Angel Montenegro
*
* */
public class AddScopesToExistingClients {
@Option(name = "-s", usage = "CSV new scopes to add, they must be valid values in the ScopePathType enum")
private String newScopes;
@Option(name = "-t", usage = "CSV client types, must be one in ClientType, if null, assume the change applies to all client types")
private String clientTypes;
@Option(name = "-c", usage = "CSV client Ids, must belong to existing clients")
private String clientIds;
private Set<ScopePathType> scopes = new HashSet<ScopePathType>();
private Set<ClientType> allowedClientTypes = new HashSet<ClientType>();
private Set<String> clientIdSet = new HashSet<String>();
private ClientDetailsManager clientDetailsManager;
private TransactionTemplate transactionTemplate;
private int clientsUpdated = 0;
public static void main(String [] args) {
AddScopesToExistingClients addScopesToExistingClients = new AddScopesToExistingClients();
CmdLineParser parser = new CmdLineParser(addScopesToExistingClients);
try {
parser.parseArgument(args);
addScopesToExistingClients.validateParameters(parser);
addScopesToExistingClients.init();
addScopesToExistingClients.process();
System.out.println();
System.out.println();
System.out.println(addScopesToExistingClients.getClientsUpdated() + " clients were updated");
System.out.println();
System.out.println();
} catch (CmdLineException e) {
System.err.println(e.getMessage());
parser.printUsage(System.err);
System.exit(1);
}
System.exit(0);
}
@SuppressWarnings("resource")
public void init() {
ApplicationContext context = new ClassPathXmlApplicationContext("orcid-core-context.xml");
clientDetailsManager = (ClientDetailsManager) context.getBean("clientDetailsManager");
transactionTemplate = (TransactionTemplate) context.getBean("transactionTemplate");
}
public void process() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
if(PojoUtil.isEmpty(clientIds) || !PojoUtil.isEmpty(clientTypes)) {
List<ClientDetailsEntity> clients = clientDetailsManager.getAll();
for (ClientDetailsEntity client : clients) {
// Only updater clients should be updated
if (isInAllowedClientTypes(client)) {
ClientDetailsEntity clientDetails = clientDetailsManager.findByClientId(client.getId());
updateScopes(clientDetails);
}
}
}
for (String clientId : clientIdSet) {
ClientDetailsEntity client = clientDetailsManager.findByClientId(clientId);
if(client == null) {
System.out.println();
System.out.println("Client with Id "+ clientId+ " doesnot exist. Ignoring!!");
} else {
updateScopes(client);
}
}
}
});
}
private boolean isInAllowedClientTypes(ClientDetailsEntity client) {
//Ignore the public client
if(client.getClientType() == null || ClientType.PUBLIC_CLIENT.equals(client.getClientType())) {
return false;
}
if(allowedClientTypes == null || allowedClientTypes.isEmpty())
return true;
for(ClientType clientType : allowedClientTypes) {
if(clientType.equals(client.getClientType()))
return true;
}
return false;
}
private void updateScopes(ClientDetailsEntity clientDetails) {
for(ScopePathType scope : scopes) {
boolean alreadyHaveReadPublicScope = false;
for (ClientScopeEntity existingScope : clientDetails.getClientScopes()) {
if (scope.value().equals(existingScope.getScopeType())) {
alreadyHaveReadPublicScope = true;
break;
}
}
if (!alreadyHaveReadPublicScope) {
ClientScopeEntity clientScope = new ClientScopeEntity();
clientScope.setClientDetailsEntity(clientDetails);
clientScope.setScopeType(scope.value());
clientScope.setDateCreated(new Date());
clientScope.setLastModified(new Date());
clientDetails.getClientScopes().add(clientScope);
clientDetailsManager.merge(clientDetails);
clientsUpdated += 1;
System.out.println("Client " + clientDetails.getId() + " has been updated");
} else {
System.out.println("Client " + clientDetails.getId() + " already have the " + scope.value() + " scope");
}
}
}
public void validateParameters(CmdLineParser parser) throws CmdLineException {
if(PojoUtil.isEmpty(newScopes)) {
throw new CmdLineException(parser, "-s parameter must not be null");
} else {
String [] scopesArray = newScopes.split(",");
for(String scope : scopesArray) {
try {
scopes.add(ScopePathType.fromValue(scope));
} catch(IllegalArgumentException ie) {
throw new CmdLineException(parser, "Invalid scope: " + scope);
}
}
}
if(!PojoUtil.isEmpty(clientTypes)) {
String [] clientTypesArray = clientTypes.split(",");
for(String clientType : clientTypesArray) {
try {
allowedClientTypes.add(ClientType.fromValue(clientType));
} catch(IllegalArgumentException ie) {
throw new CmdLineException(parser, "Invalid client type: " + clientType);
}
}
}
if(!PojoUtil.isEmpty(clientIds)) {
String [] clientIdArr = clientIds.split(",");
for(String clientId : clientIdArr) {
clientIdSet.add(clientId);
}
}
}
public int getClientsUpdated() {
return clientsUpdated;
}
}