package org.nishen.alma.toolkit.tasks;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.ClientErrorException;
import javax.ws.rs.ServerErrorException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBElement;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException;
import org.nishen.alma.toolkit.entity.user.ObjectFactory;
import org.nishen.alma.toolkit.entity.user.User;
import org.nishen.alma.toolkit.entity.ws.Error;
import org.nishen.alma.toolkit.entity.ws.WebServiceResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;
/**
* Task to set the expiry and purge dates of a User.
*
* @author nishen
*/
public class TaskSetUserPurgeDates implements Task
{
private static final Logger log = LoggerFactory.getLogger(TaskSetUserPurgeDates.class);
private static final String TASKNAME = "setUserPurgeDates";
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
private Provider<WebTarget> webTargetProvider = null;
private String userListFilename = null;
private Date expiryDate = null;
private Date purgeDate = null;
private ObjectFactory of = new ObjectFactory();
/**
* @param args command line args passed in.
* @param config the properties loaded in at run time.
*/
@Inject
private TaskSetUserPurgeDates(@Named("app.cmdline") final String[] args,
@Named("app.config") final Properties config,
@Named("ws.url.alma") Provider<WebTarget> webTargetProvider)
{
// extract relevant command line arguments
if (args != null && args.length > 0)
for (int x = 0; x < args.length; x++)
{
if (args[x].equals("-expiry"))
{
String date = null;
if (args.length > (x + 1))
{
try
{
date = args[++x];
expiryDate = sdf.parse(date);
}
catch (ParseException pe)
{
log.error("unable to parse expirydate: {}", date);
}
}
}
else if (args[x].equals("-purge"))
{
String date = null;
if (args.length > (x + 1))
{
try
{
date = args[++x];
purgeDate = sdf.parse(date);
}
catch (ParseException pe)
{
log.error("unable to parse purge date: {}", date);
}
}
}
else if (args[x].equals("-users"))
{
if (args.length > (x + 1))
userListFilename = args[++x];
}
}
this.webTargetProvider = webTargetProvider;
log.debug("initialised {}", this.getClass().getCanonicalName());
}
@Override
public void run()
{
log.info("executing task: {}", this.getClass().getSimpleName());
List<String> userList = null;
if (expiryDate == null)
{
log.error("expiry date required.");
return;
}
if (purgeDate == null)
{
log.error("purge date required.");
return;
}
log.info("expiry date: {}", expiryDate);
log.info("purge date: {}", purgeDate);
try
{
File userListFile = new File(userListFilename);
userList = getUserList(userListFile);
}
catch (FileNotFoundException nfe)
{
log.error("cannot find or open file: {}", nfe.getMessage(), nfe);
return;
}
try
{
WebTarget target = webTargetProvider.get();
target = target.path("users");
ExecutorService executor = Executors.newFixedThreadPool(10);
for (String primaryId : userList)
{
executor.execute(new SetUserPurgeDate(target, primaryId, expiryDate, purgeDate));
}
executor.shutdown();
executor.awaitTermination(1L, TimeUnit.HOURS);
}
catch (InterruptedException ie)
{
log.error("executor awaiting termination was interrupted: {}", ie);
log.debug("{}", ie);
}
catch (Exception e)
{
log.error("execution failure: {}", e);
log.debug("{}", e);
}
}
@Override
public Map<String, String> getUsageOptions()
{
Map<String, String> options = new HashMap<String, String>();
options.put("-expiry YYYY-MM-DD", "expiry date");
options.put("-purge YYYY-MM-DD", "purge date");
options.put("-users filename", "list of user identifiers to process");
return options;
}
private List<String> getUserList(File file) throws FileNotFoundException
{
List<String> result = new ArrayList<String>(50000);
Scanner scanner = null;
scanner = new Scanner(file);
scanner.nextLine(); // header line
while (scanner.hasNextLine())
{
String line = scanner.nextLine();
if (line == null || "".equals(line))
continue;
String[] parts = line.split(",");
if (parts == null || parts.length < 1)
continue;
result.add(parts[0]);
}
scanner.close();
return result;
}
private static XMLGregorianCalendar makeDate(Date date)
{
DatatypeFactory dtf = null;
try
{
dtf = DatatypeFactory.newInstance();
}
catch (DatatypeConfigurationException e)
{
log.warn("unable to init DatatypeFactory: {}", e.getMessage());
}
Calendar d = Calendar.getInstance();
d.setTime(date);
log.trace("makeDate [from database]: {}", d.toString());
XMLGregorianCalendar c = dtf.newXMLGregorianCalendar();
c.setYear(d.get(Calendar.YEAR));
c.setMonth(d.get(Calendar.MONTH) + 1);
c.setDay(d.get(Calendar.DAY_OF_MONTH));
c.setTimezone(0);
c.normalize();
log.trace("makeDate [xml gregorian]: {}", c.toString());
return c;
}
public static String getTaskName()
{
return TASKNAME;
}
private class SetUserPurgeDate implements Runnable
{
private WebTarget target;
private String primaryId;
private Date expiryDate;
private Date purgeDate;
public SetUserPurgeDate(WebTarget target, String primaryId, Date expiryDate, Date purgeDate)
{
this.target = target;
this.primaryId = primaryId;
this.expiryDate = expiryDate;
this.purgeDate = purgeDate;
}
public void run()
{
try
{
log.debug("processing user: {}", primaryId);
WebTarget t = target.path(primaryId);
User user = t.request(MediaType.APPLICATION_XML_TYPE).get(User.class);
log.debug("fetched user: {}", user.getPrimaryId());
user.setExpiryDate(makeDate(expiryDate));
user.setPurgeDate(makeDate(purgeDate));
JAXBElement<User> jaxbUser = of.createUser(user);
user = t.request(MediaType.APPLICATION_XML).put(Entity.entity(jaxbUser, MediaType.APPLICATION_XML),
User.class);
log.info("updated user [{}] - {}/{}", user.getPrimaryId(), user.getExpiryDate(), user.getPurgeDate());
}
catch (ClientErrorException cee)
{
try
{
WebServiceResult error = cee.getResponse().readEntity(WebServiceResult.class);
for (Error e : error.getErrorList().getError())
{
String mesg = e.getErrorMessage();
if (mesg != null)
mesg = mesg.replaceAll("\n", " ");
}
}
catch (MessageBodyProviderNotFoundException e)
{
String error = cee.getResponse().readEntity(String.class);
Object[] args = new Object[] { primaryId, error };
log.error("TaskSetUserPurgeDates[{}] error: {}", args);
}
}
catch (ServerErrorException see)
{
Object[] args = new Object[] { primaryId, see.getResponse().getStatusInfo().getStatusCode(),
see.getMessage() };
log.error("TaskSetUserPurgeDates[{}] {}: {}", args);
}
catch (Exception e)
{
Object[] args = new Object[] { primaryId, e.getMessage(), e };
log.error("TaskSetUserPurgeDates[{}]: {}", args);
}
}
}
}