/**
* ESUP-Portail Helpdesk - Copyright (c) 2004-2009 ESUP-Portail consortium.
*/
package org.esupportail.helpdesk.batch;
import org.esupportail.commons.batch.BatchException;
import org.esupportail.commons.exceptions.ConfigException;
import org.esupportail.commons.services.application.ApplicationService;
import org.esupportail.commons.services.application.ApplicationUtils;
import org.esupportail.commons.services.application.VersionningUtils;
import org.esupportail.commons.services.database.DatabaseUtils;
import org.esupportail.commons.services.exceptionHandling.ExceptionUtils;
import org.esupportail.commons.services.i18n.I18nUtils;
import org.esupportail.commons.services.ldap.LdapUtils;
import org.esupportail.commons.services.logging.Logger;
import org.esupportail.commons.services.logging.LoggerImpl;
import org.esupportail.commons.services.portal.PortalUtils;
import org.esupportail.commons.services.smtp.SmtpUtils;
import org.esupportail.commons.utils.BeanUtils;
import org.esupportail.helpdesk.domain.DomainService;
import org.esupportail.helpdesk.domain.beans.Ticket;
import org.esupportail.helpdesk.services.archiving.Archiver;
import org.esupportail.helpdesk.services.expiration.Expirator;
import org.esupportail.helpdesk.services.feed.ErrorHolder;
import org.esupportail.helpdesk.services.feed.Feeder;
import org.esupportail.helpdesk.services.indexing.Indexer;
import org.esupportail.helpdesk.services.recall.Recaller;
import org.springframework.context.support.FileSystemXmlApplicationContext;
/**
* A class with a main method called by ant targets.
*/
public class Batch {
/**
* A logger.
*/
private static final Logger LOG = new LoggerImpl(Batch.class);
/**
* The name of the domain service bean.
*/
private static final String DOMAIN_SERVICE_BEAN = "domainService";
/**
* The name of the indexer bean.
*/
private static final String INDEXER_BEAN = "indexer";
/**
* The name of the archiver bean.
*/
private static final String ARCHIVER_BEAN = "archiver";
/**
* The name of the expirator bean.
*/
private static final String EXPIRATOR_BEAN = "expirator";
/**
* The name of the recaller bean.
*/
private static final String RECALLER_BEAN = "recaller";
/**
* The name of the feeder bean.
*/
private static final String FEEDER_BEAN = "feeder";
/**
* Bean constructor.
*/
private Batch() {
throw new UnsupportedOperationException();
}
/**
* Print the syntax and exit.
*/
private static void syntax() {
System.out.println(
"syntax: java -Dconfig.location=</path/to/config.properties> -jar <jarName> <options>"
+ "\nwhere option can be:"
+ "\n- test-beans: test the required beans"
+ "\n- init-data: init database (RESET!)"
+ "\n- upgrade-data: upgrade database"
+ "\n- update-index: update the index"
+ "\n- rebuild-index: rebuild the index"
+ "\n- unlock-index: unlock the index"
+ "\n- archive-tickets: archive old closed tickets"
+ "\n- unlock-archive-tickets: unlock archive-tickets"
+ "\n- expire-tickets: expire non approved tickets"
+ "\n- expire-tickets-no-email: expire non approved tickets"
+ "\n- unlock-expire-tickets: unlock expire-tickets"
+ "\n- recall-tickets: recall postponed tickets"
+ "\n- unlock-recall-tickets: unlock recall-tickets"
+ "\n- test-department-selection: test the department selection"
+ "\n- test-user-info: test the user info"
+ "\n- test-search: test the search engine"
+ "\n- send-ticket-reports: send ticket reports"
+ "\n- send-faq-reports: send FAQ reports"
+ "\n- feed: feed the database"
+ "\n- delete-all-tickets: delete all the tickets"
+ "\n- delete-ticket: delete one ticket ans its associated files"
);
}
/**
* @return the domain service
*/
private static DomainService getDomainService() {
return (DomainService) BeanUtils.getBean(DOMAIN_SERVICE_BEAN);
}
/**
* Test the required beans.
*/
private static void testBeans() {
DatabaseUtils.test();
ApplicationUtils.createApplicationService();
I18nUtils.createI18nService();
LdapUtils.createLdapService();
PortalUtils.createPortalService();
SmtpUtils.createSmtpService();
VersionningUtils.createVersionningService();
}
/**
* Initialize the database.
*/
private static void initDatabase() {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
// DatabaseUtils.create();
VersionningUtils.createVersionningService().initDatabase();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
doUpgradeDatabase();
}
/**
* Upgrade the database.
*/
private static void doUpgradeDatabase() {
while (true) {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
boolean recall = VersionningUtils.createVersionningService().upgradeDatabase();
DatabaseUtils.commit();
DatabaseUtils.close();
if (!recall) {
return;
}
} catch (Throwable t) {
closeAndRethrowException(t);
}
}
}
/**
* @param t
* @throws ConfigException
*/
private static void closeAndRethrowException(final Throwable t) throws ConfigException {
ConfigException ex = null;
if (t instanceof ConfigException) {
ex = (ConfigException) t;
} else {
ex = new ConfigException(t);
}
DatabaseUtils.close();
throw ex;
}
/**
* @return the indexer
*/
private static Indexer getIndexer() {
return (Indexer) BeanUtils.getBean(INDEXER_BEAN);
}
/**
* Rebuild or update the index.
* @param rebuild true to rebuild, false to simply update
*/
private static void updateIndex(final boolean rebuild) {
Indexer indexer = getIndexer();
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
if (rebuild) {
indexer.removeIndex();
}
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
int totalIndexedEntries = 0;
int indexedEntries = 0;
do {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
indexedEntries = indexer.updateIndex(!rebuild);
totalIndexedEntries += indexedEntries;
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
} while (indexedEntries > 0);
if (totalIndexedEntries > 0) {
LOG.info(totalIndexedEntries + " entry(ies) indexed.");
} else {
LOG.info("no entry indexed.");
}
}
/**
* Unlock the index.
*/
private static void unlockIndex() {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
getIndexer().unlockIndex();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* @return the archiver
*/
private static Archiver getArchiver() {
return (Archiver) BeanUtils.getBean(ARCHIVER_BEAN);
}
/**
* Archive tickets.
*/
private static void archiveTickets() {
Archiver archiver = getArchiver();
boolean recall;
do {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
recall = archiver.archive();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
} while (recall);
}
/**
* Unlock archive-tickets.
*/
private static void unlockArchiveTickets() {
Archiver archiver = getArchiver();
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
archiver.unlock();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* @return the expirator
*/
private static Expirator getExpirator() {
return (Expirator) BeanUtils.getBean(EXPIRATOR_BEAN);
}
/**
* Expire non approved tickets.
* @param alerts
*/
private static void expireTickets(final boolean alerts) {
Expirator expirator = getExpirator();
boolean recall;
do {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
recall = expirator.expire(alerts);
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
} while (recall);
}
/**
* Unlock expire-tickets.
*/
private static void unlockExpireTickets() {
Expirator expirator = getExpirator();
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
expirator.unlock();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* @return the recaller
*/
private static Recaller getRecaller() {
return (Recaller) BeanUtils.getBean(RECALLER_BEAN);
}
/**
* Recall postponed tickets.
*/
private static void recallTickets() {
Recaller recaller = getRecaller();
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
recaller.recall();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Unlock recall-tickets.
*/
private static void unlockRecallTickets() {
Recaller recaller = getRecaller();
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
recaller.unlock();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Send reports.
*/
private static void sendTicketReports() {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
getDomainService().sendTicketReports();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Send FAQ updates.
*/
private static void sendFaqReports() {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
getDomainService().sendFaqReports();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Test the user info.
*/
private static void testUserInfo() {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
getDomainService().testUserInfo();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Feed the database.
*/
private static void feed() {
try {
boolean versionChecked = false;
Feeder feeder = (Feeder) BeanUtils.getBean(FEEDER_BEAN);
ErrorHolder errorHolder = new ErrorHolder();
while (true) {
DatabaseUtils.open();
DatabaseUtils.begin();
if (!versionChecked) {
VersionningUtils.checkVersion(true, false);
versionChecked = true;
}
boolean commit = feeder.feed(errorHolder);
if (commit) {
DatabaseUtils.commit();
} else {
DatabaseUtils.rollback();
}
DatabaseUtils.close();
if (!commit || errorHolder.hasErrors()) {
break;
}
}
if (errorHolder.hasErrors()) {
errorHolder.addInfo(errorHolder.getErrorNumber() + " total error(s) found");
LOG.error(errorHolder.getStrings());
} else {
errorHolder.addInfo("no error found");
LOG.info(errorHolder.getStrings());
}
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Test the search engine.
*/
private static void testSearch() {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
Indexer indexer = (Indexer) BeanUtils.getBean(
INDEXER_BEAN);
indexer.test();
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Test the user info.
*/
private static void testConsistency() {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
DomainService domainService = getDomainService();
for (Ticket ticket : domainService.getTickets(0, Integer.MAX_VALUE)) {
if (!ticket.getDepartment().equals(ticket.getCategory().getDepartment())) {
LOG.error("error for ticket #" + ticket.getId());
}
}
DatabaseUtils.rollback();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Delete all the tickets.
*/
private static void deleteAllTickets() {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
getDomainService().deleteAllTickets();
getIndexer().updateIndex(true);
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Delete one ticket ans possibly associated files.
*/
private static void deleteTicket(final String id, final boolean deleteFiles) {
try {
DatabaseUtils.open();
DatabaseUtils.begin();
VersionningUtils.checkVersion(true, false);
Ticket ticketToDelete = getDomainService().getTicket(Long.parseLong(id));
if (ticketToDelete != null) {
getDomainService().deleteTicket(ticketToDelete, deleteFiles);
}
getIndexer().updateIndex(true);
DatabaseUtils.commit();
DatabaseUtils.close();
} catch (Throwable t) {
DatabaseUtils.rollback();
DatabaseUtils.close();
throw new BatchException(t);
}
}
/**
* Dispatch depending on the arguments.
* @param args
*/
protected static void dispatch(final String[] args) {
switch (args.length) {
case 0:
syntax();
break;
case 1:
if ("test-beans".equals(args[0])) {
testBeans();
} else if ("init-data".equals(args[0])) {
initDatabase();
} else if ("upgrade-data".equals(args[0])) {
doUpgradeDatabase();
}else if ("update-index".equals(args[0])) {
updateIndex(false);
} else if ("rebuild-index".equals(args[0])) {
updateIndex(true);
} else if ("unlock-index".equals(args[0])) {
unlockIndex();
} else if ("archive-tickets".equals(args[0])) {
archiveTickets();
} else if ("unlock-archive-tickets".equals(args[0])) {
unlockArchiveTickets();
} else if ("expire-tickets".equals(args[0])) {
expireTickets(true);
} else if ("expire-tickets-no-email".equals(args[0])) {
expireTickets(false);
} else if ("unlock-expire-tickets".equals(args[0])) {
unlockExpireTickets();
} else if ("recall-tickets".equals(args[0])) {
recallTickets();
} else if ("unlock-recall-tickets".equals(args[0])) {
unlockRecallTickets();
} else if ("test-user-info".equals(args[0])) {
testUserInfo();
} else if ("feed".equals(args[0])) {
feed();
} else if ("send-reports".equals(args[0])) {
throw new IllegalArgumentException(
"argument send-reports is obsolete, please use send-ticket-reports instead");
} else if ("send-ticket-reports".equals(args[0])) {
sendTicketReports();
} else if ("send-faq-reports".equals(args[0])) {
sendFaqReports();
} else if ("test-search".equals(args[0])) {
testSearch();
} else if ("test-consistency".equals(args[0])) {
testConsistency();
} else if ("delete-all-tickets".equals(args[0])) {
deleteAllTickets();
} else {
syntax();
}
break;
case 2:
if ("delete-ticket".equals(args[0])) {
deleteTicket(args[1], true);
}
break;
default:
syntax();
break;
}
}
/**
* The main method, called by ant.
* @param args
*/
public static void main(final String[] args) {
if (args.length == 0) {
syntax();
}
else {
try {
//creation d'un context Spring
//ATTENTION : A cause d'un pb de résolution de properties dans les balises import de Spring en version < 3.1
// on est obligé d'utiliser SpringXmlContextBootstrapper pour lire les properties puis mimer les imports via des beans de type
// ConfigLocationProvider.
// SpringXmlContextBootstrapper est appelé lors du new FileSystemXmlApplicationContext() et positionne le context Spring dans le
// thread local utilisé par BeanUtils de esup-commons
new FileSystemXmlApplicationContext("classpath:properties/applicationContext.xml");
ApplicationService applicationService = (ApplicationService) BeanUtils.getBean("applicationService");
LOG.info(applicationService.getName() + " v" + applicationService.getVersion());
dispatch(args);
} catch (Throwable t) {
ExceptionUtils.catchException(t);
}
}
}
}