org.sakaiproject.kernel.mailman.impl.MailmanManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.kernel.mailman.impl.MailmanManagerImpl.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sakaiproject.kernel.mailman.impl;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.cyberneko.html.parsers.DOMParser;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.component.ComponentContext;
import org.sakaiproject.kernel.api.message.MessageRoute;
import org.sakaiproject.kernel.api.proxy.ProxyClientService;
import org.sakaiproject.kernel.mailman.MailmanManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.html.HTMLCollection;
import org.w3c.dom.html.HTMLTableElement;
import org.w3c.dom.html.HTMLTableRowElement;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

/**
 * @scr.component immediate="true" label="MailManagerImpl"
 *                description="Interface to mailman"
 * @scr.property name="service.description"
 *                value="Handles management of mailman integration"
 * @scr.property name="service.vendor" value="The Sakai Foundation"
 * @scr.service interface="org.sakaiproject.kernel.mailman.MailmanManager"
 */
public class MailmanManagerImpl implements MailmanManager, ManagedService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MailmanManagerImpl.class);

    /** @scr.reference */
    private ProxyClientService proxyClientService;

    /** @scr.property value="example.com" type="String" */
    private static final String MAILMAN_HOST = "mailman.host";

    /** @scr.property value="/cgi-bin/mailman" type="String" */
    private static final String MAILMAN_PATH = "mailman.path";

    /** @scr.property value="password" type="String" */
    private static final String LIST_ADMIN_PASSWORD = "mailman.listadmin.password";

    private ImmutableMap<String, String> configMap = ImmutableMap.of();

    private String getMailmanUrl(String stub) {
        return "http://" + configMap.get(MAILMAN_HOST) + configMap.get(MAILMAN_PATH) + stub;
    }

    public void createList(String listName, String ownerEmail, String password) throws MailmanException {
        HttpClient client = new HttpClient(proxyClientService.getHttpConnectionManager());
        PostMethod post = new PostMethod(getMailmanUrl("/create"));
        NameValuePair[] parametersBody = new NameValuePair[] { new NameValuePair("listname", listName),
                new NameValuePair("owner", ownerEmail), new NameValuePair("password", password),
                new NameValuePair("confirm", password),
                new NameValuePair("auth", configMap.get(LIST_ADMIN_PASSWORD)), new NameValuePair("langs", "en"),
                new NameValuePair("notify", "1"), new NameValuePair("autogen", "0"),
                new NameValuePair("moderate", "0"), new NameValuePair("doit", "Create List") };
        post.setRequestBody(parametersBody);
        try {
            int result = client.executeMethod(post);
            if (result != HttpServletResponse.SC_OK) {
                throw new MailmanException("Unable to create list");
            }
        } catch (HttpException e) {
            throw new MailmanException("HTTP Exception communicating with mailman server", e);
        } catch (IOException e) {
            throw new MailmanException("IOException communicating with mailman server", e);
        } finally {
            post.releaseConnection();
        }
    }

    public void deleteList(String listName, String listPassword) throws MailmanException {
        HttpClient client = new HttpClient(proxyClientService.getHttpConnectionManager());
        PostMethod post = new PostMethod(getMailmanUrl("/rmlist/" + listName));
        NameValuePair[] parametersBody = new NameValuePair[] { new NameValuePair("password", listPassword),
                new NameValuePair("delarchives", "0"), new NameValuePair("doit", "Delete this list") };
        post.setRequestBody(parametersBody);
        try {
            int result = client.executeMethod(post);
            if (result != HttpServletResponse.SC_OK) {
                throw new MailmanException("Unable to create list");
            }
        } catch (HttpException e) {
            throw new MailmanException("HTTP Exception communicating with mailman server", e);
        } catch (IOException e) {
            throw new MailmanException("IOException communicating with mailman server", e);
        } finally {
            post.releaseConnection();
        }
    }

    public boolean listHasMember(String listName, String listPassword, String memberEmail) throws MailmanException {
        HttpClient client = new HttpClient(proxyClientService.getHttpConnectionManager());
        GetMethod get = new GetMethod(getMailmanUrl("/admin/" + listName + "members"));
        NameValuePair[] parameters = new NameValuePair[] { new NameValuePair("findmember", memberEmail),
                new NameValuePair("setmemberopts_btn", ""), new NameValuePair("adminpw", listPassword) };
        get.setQueryString(parameters);
        try {
            int result = client.executeMethod(get);
            if (result != HttpServletResponse.SC_OK) {
                throw new MailmanException("Unable to search for member");
            }
            Document dom = parseHtml(get);
            NodeList inputs = dom.getElementsByTagName("INPUT");
            String unsubString = URLEncoder.encode(memberEmail, "utf8") + "_unsub";
            for (int i = 0; i < inputs.getLength(); i++) {
                Node input = inputs.item(i);
                try {
                    if (input.getAttributes().getNamedItem("name").getTextContent().equals(unsubString)) {
                        return true;
                    }
                } catch (NullPointerException npe) {
                }
            }
        } catch (SAXException e) {
            throw new MailmanException("Error parsing mailman response", e);
        } catch (HttpException e) {
            throw new MailmanException("HTTP Exception communicating with mailman server", e);
        } catch (IOException e) {
            throw new MailmanException("IOException communicating with mailman server", e);
        } finally {
            get.releaseConnection();
        }
        return false;
    }

    public boolean addMember(String listName, String listPassword, String memberEmail) throws MailmanException {
        HttpClient client = new HttpClient(proxyClientService.getHttpConnectionManager());
        GetMethod get = new GetMethod(getMailmanUrl("/admin/" + listName + "/members/add"));
        NameValuePair[] parameters = new NameValuePair[] { new NameValuePair("subscribe_or_invite", "0"),
                new NameValuePair("send_welcome_msg_to_this_batch", "0"),
                new NameValuePair("notification_to_list_owner", "0"),
                new NameValuePair("subscribees_upload", memberEmail), new NameValuePair("adminpw", listPassword) };
        get.setQueryString(parameters);
        try {
            int result = client.executeMethod(get);
            if (result != HttpServletResponse.SC_OK) {
                throw new MailmanException("Unable to add member");
            }
            Document dom = parseHtml(get);
            NodeList inputs = dom.getElementsByTagName("h5");
            if (inputs.getLength() == 0) {
                throw new MailmanException("Unable to read result status");
            }
            return "Successfully subscribed:".equals(inputs.item(0).getTextContent());
        } catch (SAXException e) {
            throw new MailmanException("Error parsing mailman response", e);
        } catch (HttpException e) {
            throw new MailmanException("HTTP Exception communicating with mailman server", e);
        } catch (IOException e) {
            throw new MailmanException("IOException communicating with mailman server", e);
        } finally {
            get.releaseConnection();
        }
    }

    public boolean removeMember(String listName, String listPassword, String memberEmail) throws MailmanException {
        HttpClient client = new HttpClient(proxyClientService.getHttpConnectionManager());
        GetMethod get = new GetMethod(getMailmanUrl("/admin/" + listName + "/members/remove"));
        NameValuePair[] parameters = new NameValuePair[] { new NameValuePair("send_unsub_ack_to_this_batch", "0"),
                new NameValuePair("send_unsub_notifications_to_list_owner", "0"),
                new NameValuePair("unsubscribees_upload", memberEmail),
                new NameValuePair("adminpw", listPassword) };
        get.setQueryString(parameters);
        try {
            int result = client.executeMethod(get);
            if (result != HttpServletResponse.SC_OK) {
                throw new MailmanException("Unable to add member");
            }
            Document dom = parseHtml(get);
            NodeList inputs = dom.getElementsByTagName("h5");
            if (inputs.getLength() == 0) {
                inputs = dom.getElementsByTagName("h3");
                if (inputs.getLength() == 0) {
                    throw new MailmanException("Unable to read result status");
                }
            }
            return "Successfully Unsubscribed:".equals(inputs.item(0).getTextContent());
        } catch (HttpException e) {
            throw new MailmanException("HTTP Exception communicating with mailman server", e);
        } catch (IOException e) {
            throw new MailmanException("IOException communicating with mailman server", e);
        } catch (SAXException e) {
            throw new MailmanException("Error parsing mailman response", e);
        } finally {
            get.releaseConnection();
        }
    }

    private Document parseHtml(HttpMethodBase method) throws SAXException, IOException {
        DOMParser parser = new DOMParser();
        parser.parse(new InputSource(method.getResponseBodyAsStream()));
        return parser.getDocument();
    }

    public List<String> getLists() throws MailmanException {
        HttpClient client = new HttpClient(proxyClientService.getHttpConnectionManager());
        GetMethod get = new GetMethod(getMailmanUrl("/admin"));
        List<String> lists = new ArrayList<String>();
        try {
            int result = client.executeMethod(get);
            if (result != HttpServletResponse.SC_OK) {
                LOGGER.warn("Got " + result + " from http request");
                throw new MailmanException("Unable to list mailinglists");
            }
            DOMParser parser = new DOMParser();
            parser.parse(new InputSource(get.getResponseBodyAsStream()));
            Document doc = parser.getDocument();
            NodeList tableNodes = doc.getElementsByTagName("table");
            if (tableNodes.getLength() < 2) {
                throw new MailmanException("Unrecognised page format.");
            }
            HTMLTableElement mainTable = (HTMLTableElement) tableNodes.item(0);
            HTMLCollection rows = mainTable.getRows();
            for (int i = 4; i < rows.getLength(); i++) {
                lists.add(parseListNameFromRow((HTMLTableRowElement) rows.item(i)));
            }
        } catch (SAXException e) {
            throw new MailmanException("Error parsing mailman response", e);
        } catch (HttpException e) {
            throw new MailmanException("HTTP Exception communicating with mailman server", e);
        } catch (IOException e) {
            throw new MailmanException("IOException communicating with mailman server", e);
        } finally {
            get.releaseConnection();
        }
        return lists;
    }

    private String parseListNameFromRow(HTMLTableRowElement item) throws MailmanException {
        HTMLCollection cells = item.getCells();
        if (cells.getLength() != 2) {
            throw new MailmanException("Unexpected table row format");
        }
        return cells.item(0).getTextContent();
    }

    void setServer(String mailmanHost) {
        Builder<String, String> builder = ImmutableMap.builder();
        builder.putAll(configMap);
        builder.put(MAILMAN_HOST, mailmanHost);
        configMap = builder.build();
    }

    void setMailmanPath(String mailmanPath) {
        Builder<String, String> builder = ImmutableMap.builder();
        builder.putAll(configMap);
        builder.put(MAILMAN_PATH, mailmanPath);
        configMap = builder.build();
    }

    ProxyClientService getProxyClientService() {
        return proxyClientService;
    }

    void setProxyClientService(ProxyClientService proxyClientService) {
        this.proxyClientService = proxyClientService;
    }

    public boolean isServerActive() throws MailmanException {
        HttpClient client = new HttpClient(proxyClientService.getHttpConnectionManager());
        GetMethod get = new GetMethod(getMailmanUrl("/admin"));
        try {
            int result = client.executeMethod(get);
            if (result != HttpServletResponse.SC_OK) {
                LOGGER.warn("Got " + result + " from http request");
                return false;
            }
            return true;
        } catch (HttpException e) {
            throw new MailmanException("HTTP Exception communicating with mailman server", e);
        } catch (IOException e) {
            throw new MailmanException("IOException communicating with mailman server", e);
        } finally {
            get.releaseConnection();
        }
    }

    protected void activate(ComponentContext componentContext) {
        LOGGER.info("Got component initialization");
        Builder<String, String> builder = ImmutableMap.builder();
        for (Enumeration<?> e = componentContext.getProperties().keys(); e.hasMoreElements();) {
            String key = (String) e.nextElement();
            Object value = componentContext.getProperties().get(key);
            if (value instanceof String) {
                builder.put(key, (String) value);
            }
        }
        configMap = builder.build();
    }

    @SuppressWarnings("unchecked")
    public void updated(Dictionary config) throws ConfigurationException {
        LOGGER.info("Got config update");
        Builder<String, String> builder = ImmutableMap.builder();
        for (Enumeration<?> e = config.keys(); e.hasMoreElements();) {
            String k = (String) e.nextElement();
            builder.put(k, (String) config.get(k));
        }
        configMap = builder.build();
    }

    public MessageRoute generateMessageRouteForGroup(String groupName) {
        return new MailmanMessageRoute(groupName + "@" + configMap.get(MAILMAN_HOST), "smtp");
    }

}