package net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs; import static pt.ist.fenixframework.plugins.luceneIndexing.queryBuilder.Builder.matches; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.text.MessageFormat; import java.util.List; import java.util.Properties; import java.util.ResourceBundle; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.mail.Flags.Flag; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.NoSuchProviderException; import javax.mail.Session; import javax.mail.Store; import net.sourceforge.fenixedu._development.PropertiesManager; import net.sourceforge.fenixedu.domain.jobs.JobExecutionRequestor; import net.sourceforge.fenixedu.domain.softwareLicenseManagement.LicenseRequest; import net.sourceforge.fenixedu.domain.softwareLicenseManagement.LicenseRequest.LicenseRequestIndexFields; import net.sourceforge.fenixedu.util.LanguageUtils; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; import pt.ist.fenixframework.plugins.luceneIndexing.DomainIndexer; import pt.ist.fenixframework.plugins.luceneIndexing.queryBuilder.dsl.SearchState; import com.qubit.fenixframework.plugins.job.JobExecutionResult; import com.qubit.fenixframework.plugins.job.JobExecutor; public class SPSSEmailReader implements JobExecutor { private static final String NO_INBOX_FOUND = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.error.noInboxFound"; private static final String CODE_MATCHED_BUT_UNABLE_TO_MATCH_LICENSE = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.error.codeMatchedButUnableToMatchLicense"; private static final String UNEXPECTED_ERROR = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.error.unexpectedError"; private static final String IDENTIFICATION_NAME = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.name"; private static final String CODE_FOUND_FOR = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.match.foundCodeFor"; private static final String CODE_FOUND_WITH_ERRORS = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.match.foundCodeWithErrors"; private static final String TOO_MANY_LICENSES = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.error.tooManyLicenses"; private static final String NO_LICENSES = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.error.noLicenses"; private static final String LOCK_CODE_OR_LICENSE_ARE_NULL = "net.sourceforge.fenixedu.domain.softwareLicenseManagement.jobs.SPSSEmailReader.error.lockCodeOrLicenseAreNull"; private static final String REPLY_ERROR_WRONG_VERSION = "VERSAO_ERRADA"; private static final String REPLY_ERROR_WRONG_LOCK_CODE = "LOCK_CODE_ERRADO"; private String getLocalizedMessage(String message, String... args) { String text = ResourceBundle.getBundle("resources.ManagerResources", LanguageUtils.getLocale()).getString(message); MessageFormat format = new MessageFormat(text); return format.format(args); } @Override public JobExecutionResult execute(JobExecutionRequestor arguments, PrintStream out) { Pattern pattern = Pattern.compile(".*([^<]*).*", Pattern.MULTILINE); Pattern replyPattern = Pattern.compile( "]*>", Pattern.MULTILINE); Properties props = new Properties(); String host = PropertiesManager.getProperty("spssReader.host"); String username = PropertiesManager.getProperty("spssReader.user"); String password = PropertiesManager.getProperty("spssReader.pass"); String protocol = PropertiesManager.getProperty("spssReader.protocol"); LocalDate now = new LocalDate(); int currentYear = now.getYear(); int month = now.getMonthOfYear(); int startGap = month > 6 ? 0 : -1; int endGap = month > 6 ? 1 : 0; LocalDate start = new LocalDate(currentYear + startGap, 6, 1); LocalDate end = new LocalDate(currentYear + endGap, 5, 31); Session session = Session.getDefaultInstance(props, null); Store store; try { store = session.getStore(protocol); store.connect(host, username, password); Folder inbox = store.getFolder("INBOX"); if (inbox == null) { out.println(getLocalizedMessage(NO_INBOX_FOUND)); return null; } inbox.open(Folder.READ_WRITE); Message[] messages = inbox.getMessages(); for (int i = 0; i < messages.length; i++) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); messages[i].writeTo(stream); String email = stream.toString("iso-8859-1"); Matcher matcher = pattern.matcher(email); if (matcher.find()) { String key = matcher.group(1).replaceAll("\n", "").replaceAll("=\r", "").replaceAll("\r", ""); Matcher reply = replyPattern.matcher(email); if (reply.find()) { String licenseUsername = reply.group(1); String licenseLockCode = reply.group(2); String licenseVersion = reply.group(3); if (REPLY_ERROR_WRONG_LOCK_CODE.equalsIgnoreCase(licenseLockCode) || REPLY_ERROR_WRONG_VERSION.equalsIgnoreCase(licenseLockCode)) { out.println(getLocalizedMessage(CODE_FOUND_WITH_ERRORS, licenseUsername, licenseLockCode)); LicenseRequest license = getLicense(licenseLockCode, licenseVersion, out); if (license != null && license.isPending()) { license.setActive(Boolean.FALSE); } } else { out.println(getLocalizedMessage(CODE_FOUND_FOR, licenseUsername, licenseLockCode, licenseVersion)); LicenseRequest license = getLicense(licenseLockCode, licenseVersion, out); if (license != null) { if (license.isPending()) { license.getRequestedVersion().getLicenseModel().registerKey(key); license.setBegin(start); license.setEnd(end); } else { messages[i].setFlag(Flag.DELETED, true); } } } } else { out.println(getLocalizedMessage(CODE_MATCHED_BUT_UNABLE_TO_MATCH_LICENSE, email)); } } } inbox.close(true); store.close(); } catch (NoSuchProviderException e) { out.println(getLocalizedMessage(UNEXPECTED_ERROR)); e.printStackTrace(out); } catch (MessagingException e) { out.println(getLocalizedMessage(UNEXPECTED_ERROR)); e.printStackTrace(out); } catch (IOException e) { out.println(getLocalizedMessage(UNEXPECTED_ERROR)); e.printStackTrace(out); } return null; } private LicenseRequest getLicense(String licenseLockCode, String licenseVersion, PrintStream out) { if (StringUtils.isEmpty(licenseLockCode) || StringUtils.isEmpty(licenseVersion)) { out.println(getLocalizedMessage(LOCK_CODE_OR_LICENSE_ARE_NULL, licenseLockCode, licenseVersion)); return null; } DomainIndexer seeker = DomainIndexer.getInstance(); SearchState searchQuery = matches(LicenseRequestIndexFields.LOCK_CODE, licenseLockCode).and().matches( LicenseRequestIndexFields.VERSION_NUMBER, licenseVersion); List search = seeker.search(LicenseRequest.class, searchQuery, DomainIndexer.DEFAULT_MAX_SIZE); if (search.isEmpty()) { out.println(getLocalizedMessage(NO_LICENSES, licenseLockCode, licenseVersion)); return null; } else if (search.size() == 1) { return search.get(0); } else { LicenseRequest request = null; for (LicenseRequest licenseRequest : search) { if (licenseRequest.isPending()) { if (request != null) { out.println(getLocalizedMessage(TOO_MANY_LICENSES, licenseLockCode, licenseVersion)); return null; } else { request = licenseRequest; } } } return request; } } @Override public String getExecutionDescription() { return getLocalizedMessage(IDENTIFICATION_NAME); } @Override public boolean isToRepeatOnFail() { return false; } @Override public Class getContextArgumentsType() { return JobExecutionRequestor.class; } }