net.sourceforge.subsonic.backend.controller.MultiController.java Source code

Java tutorial

Introduction

Here is the source code for net.sourceforge.subsonic.backend.controller.MultiController.java

Source

/*
 This file is part of Subsonic.
    
 Subsonic is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 Subsonic is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with Subsonic.  If not, see <http://www.gnu.org/licenses/>.
    
 Copyright 2009 (C) Sindre Mehus
 */
package net.sourceforge.subsonic.backend.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import net.sourceforge.subsonic.backend.Util;
import net.sourceforge.subsonic.backend.dao.DaoHelper;
import net.sourceforge.subsonic.backend.dao.PaymentDao;
import net.sourceforge.subsonic.backend.dao.SubscriptionDao;
import net.sourceforge.subsonic.backend.domain.Payment;
import net.sourceforge.subsonic.backend.domain.Subscription;
import net.sourceforge.subsonic.backend.service.EmailSession;
import net.sourceforge.subsonic.backend.service.LicenseGenerator;
import net.sourceforge.subsonic.backend.service.WhitelistGenerator;

/**
 * Multi-controller used for simple pages.
 *
 * @author Sindre Mehus
 */
public class MultiController extends MultiActionController {

    private static final Logger LOG = Logger.getLogger(RedirectionController.class);

    private static final String SUBSONIC_VERSION = "4.9";
    private static final String SUBSONIC_BETA_VERSION = "4.9.beta4";

    private static final Date LICENSE_DATE_THRESHOLD;

    private DaoHelper daoHelper;

    private PaymentDao paymentDao;
    private SubscriptionDao subscriptionDao;
    private WhitelistGenerator whitelistGenerator;
    private LicenseGenerator licenseGenerator;

    static {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, 2010);
        calendar.set(Calendar.MONTH, Calendar.JUNE);
        calendar.set(Calendar.DAY_OF_MONTH, 19);
        LICENSE_DATE_THRESHOLD = calendar.getTime();
    }

    public ModelAndView version(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String localVersion = request.getParameter("v");
        LOG.info(request.getRemoteAddr() + " asked for latest version. Local version: " + localVersion);

        PrintWriter writer = response.getWriter();

        writer.println("SUBSONIC_VERSION_BEGIN" + SUBSONIC_VERSION + "SUBSONIC_VERSION_END");
        writer.println("SUBSONIC_FULL_VERSION_BEGIN" + SUBSONIC_VERSION + "SUBSONIC_FULL_VERSION_END");
        writer.println("SUBSONIC_BETA_VERSION_BEGIN" + SUBSONIC_BETA_VERSION + "SUBSONIC_BETA_VERSION_END");

        return null;
    }

    public ModelAndView validateLicense(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String email = request.getParameter("email");
        Long date = ServletRequestUtils.getLongParameter(request, "date");

        boolean valid = isLicenseValid(email, date);
        Date expirationDate = getLicenseExpirationDate(email);
        LOG.info(request.getRemoteAddr() + " asked to validate license for " + email + ". Result: " + valid
                + ", expires: " + expirationDate);

        PrintWriter writer = response.getWriter();
        writer.println(valid);
        if (expirationDate != null) {
            writer.println(expirationDate.getTime());
        }

        return null;
    }

    public ModelAndView sendMail(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String from = request.getParameter("from");
        String to = request.getParameter("to");
        String subject = request.getParameter("subject");
        String text = request.getParameter("text");

        EmailSession session = new EmailSession();
        session.sendMessage(from, Arrays.asList(to), null, null, null, subject, text);

        LOG.info("Sent email on behalf of " + request.getRemoteAddr() + " to " + to + " with subject '" + subject
                + "'");

        return null;
    }

    public ModelAndView db(HttpServletRequest request, HttpServletResponse response) throws Exception {

        if (!authenticate(request, response)) {
            return null;
        }

        Map<String, Object> map = new HashMap<String, Object>();

        map.put("p", request.getParameter("p"));
        String query = request.getParameter("query");
        if (query != null) {
            map.put("query", query);

            try {
                List<?> result = daoHelper.getJdbcTemplate().query(query, new ColumnMapRowMapper());
                map.put("result", result);
            } catch (DataAccessException x) {
                map.put("error", ExceptionUtils.getRootCause(x).getMessage());
            }
        }

        return new ModelAndView("backend/db", "model", map);
    }

    public ModelAndView payment(HttpServletRequest request, HttpServletResponse response) throws Exception {

        if (!authenticate(request, response)) {
            return null;
        }

        int days = ServletRequestUtils.getIntParameter(request, "days", 30);

        SortedMap<Date, Money> payments = new TreeMap<Date, Money>();

        Calendar startOfDay = Calendar.getInstance();
        startOfDay.set(Calendar.HOUR_OF_DAY, 0);
        startOfDay.set(Calendar.MINUTE, 0);
        startOfDay.set(Calendar.SECOND, 0);
        startOfDay.set(Calendar.MILLISECOND, 0);

        Calendar endOfDay = Calendar.getInstance();
        endOfDay.setTime(startOfDay.getTime());
        endOfDay.add(Calendar.DATE, 1);

        for (int i = 0; i < days; i++) {
            payments.put(startOfDay.getTime(),
                    getAmountForPeriod(CurrencyUnit.EUR, startOfDay.getTime(), endOfDay.getTime()));
            startOfDay.add(Calendar.DATE, -1);
            endOfDay.add(Calendar.DATE, -1);
        }

        Money sum = computeSum(payments.values());
        Money average = sum.dividedBy(days, RoundingMode.HALF_UP);

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("payments", payments);
        map.put("sum", sum);
        map.put("average", average);

        return new ModelAndView("backend/payment", "model", map);
    }

    private Money computeSum(Collection<Money> moneys) {
        Money sum = Money.zero(CurrencyUnit.EUR);
        for (Money money : moneys) {
            sum = sum.plus(money);
        }
        return sum;
    }

    private Money getAmountForPeriod(CurrencyUnit currency, Date from, Date to) {
        List<Money> payments = new ArrayList<Money>();
        payments.addAll(paymentDao.getMoneyForPeriod(from, to));
        payments.addAll(subscriptionDao.getMoneyForPeriod(from, to));

        Map<CurrencyUnit, BigDecimal> currencyConversions = paymentDao.getCurrencyConversionsFor(currency);

        Money sum = Money.zero(currency);
        for (Money payment : payments) {
            if (currency.equals(payment.getCurrencyUnit())) {
                sum = sum.plus(payment);
            } else {
                BigDecimal conversionRate = currencyConversions.get(payment.getCurrencyUnit());
                if (conversionRate == null) {
                    LOG.warn("No conversion rate found for " + currency + " to " + payment.getCurrencyUnit()
                            + ". Skipping it.");
                } else {
                    sum = sum.plus(payment.convertedTo(currency, conversionRate, RoundingMode.HALF_UP));
                }
            }
        }
        return sum;
    }

    public ModelAndView requestLicense(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String email = request.getParameter("email");
        boolean valid = email != null && isLicenseValid(email, System.currentTimeMillis());
        if (valid) {
            EmailSession session = new EmailSession();
            licenseGenerator.sendLicenseTo(email, session);
        }

        Map<String, Object> map = new HashMap<String, Object>();

        map.put("email", email);
        map.put("valid", valid);

        return new ModelAndView("backend/requestLicense", "model", map);
    }

    public ModelAndView whitelist(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (!authenticate(request, response)) {
            return null;
        }

        Date newerThan = MultiController.LICENSE_DATE_THRESHOLD;
        Integer days = ServletRequestUtils.getIntParameter(request, "days");
        if (days != null) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, -days);
            newerThan = cal.getTime();
        }
        whitelistGenerator.generate(newerThan);
        return null;
    }

    private boolean authenticate(HttpServletRequest request, HttpServletResponse response)
            throws ServletRequestBindingException, IOException {
        String password = ServletRequestUtils.getRequiredStringParameter(request, "p");
        if (!password.equals(Util.getPassword("backendpwd.txt"))) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return false;
        }
        return true;
    }

    private boolean isLicenseValid(String email, Long date) {
        if (email == null || date == null) {
            return false;
        }

        if (paymentDao.isBlacklisted(email)) {
            return false;
        }

        // Always accept licenses that are older than 2010-06-19.
        if (date < LICENSE_DATE_THRESHOLD.getTime()) {
            return true;
        }

        return hasValidSubscription(email) || hasValidPayment(email) || paymentDao.isWhitelisted(email);
    }

    private Date getLicenseExpirationDate(String email) {
        if (email == null) {
            return null;
        }

        if (paymentDao.isBlacklisted(email) || paymentDao.isWhitelisted(email)) {
            return null;
        }

        Subscription subscription = subscriptionDao.getSubscriptionByEmail(email);
        Payment payment = paymentDao.getPaymentByEmail(email);

        Date subscriptionExpirationDate = subscription == null ? null : subscription.getValidTo();
        Date paymentExpirationDate = payment == null ? null : payment.getValidTo();

        return Util.latest(subscriptionExpirationDate, paymentExpirationDate);
    }

    private boolean hasValidPayment(String email) {
        Payment payment = paymentDao.getPaymentByEmail(email);
        if (payment == null) {
            return false;
        }
        Date now = new Date();
        return payment.getValidTo() == null || payment.getValidTo().after(now);
    }

    private boolean hasValidSubscription(String email) {
        Subscription subscription = subscriptionDao.getSubscriptionByEmail(email);
        if (subscription == null) {
            return false;
        }
        Date now = new Date();
        return subscription.getValidTo() == null || subscription.getValidTo().after(now);
    }

    public void setDaoHelper(DaoHelper daoHelper) {
        this.daoHelper = daoHelper;
    }

    public void setPaymentDao(PaymentDao paymentDao) {
        this.paymentDao = paymentDao;
    }

    public void setWhitelistGenerator(WhitelistGenerator whitelistGenerator) {
        this.whitelistGenerator = whitelistGenerator;
    }

    public void setLicenseGenerator(LicenseGenerator licenseGenerator) {
        this.licenseGenerator = licenseGenerator;
    }

    public void setSubscriptionDao(SubscriptionDao subscriptionDao) {
        this.subscriptionDao = subscriptionDao;
    }
}