MailAddressResolver.java 6.2 KB
Newer Older
K
kohsuke 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * The MIT License
 * 
 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Luca Domenico Milanesio
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
24 25
package hudson.tasks;

K
kohsuke 已提交
26 27 28
import hudson.Extension;
import hudson.ExtensionList;
import hudson.ExtensionListView;
29
import hudson.ExtensionPoint;
30
import jenkins.model.Jenkins;
K
kohsuke 已提交
31
import hudson.model.User;
32 33
import hudson.model.UserProperty;
import hudson.scm.SCM;
34 35

import java.util.List;
36
import java.util.logging.Level;
37
import java.util.logging.Logger;
K
kohsuke 已提交
38
import java.util.regex.Matcher;
K
kohsuke 已提交
39
import java.util.regex.Pattern;
40 41 42 43 44

/**
 * Infers e-mail addresses for the user when none is specified.
 *
 * <p>
45
 * This is an extension point of Jenkins. Plugins that contribute a new implementation
K
kohsuke 已提交
46
 * of this class should put {@link Extension} on your implementation class, like this:
47 48
 *
 * <pre>
K
kohsuke 已提交
49 50 51
 * &#64;Extension
 * class MyMailAddressResolver extends {@link MailAddressResolver} {
 *   ...
52 53 54
 * }
 * </pre>
 *
55 56
 * <h2>Techniques</h2>
 * <p>
57
 * User identity in Jenkins is global, and not specific to a particular job. As a result, mail address resolution
58 59 60 61 62 63 64 65
 * only receives {@link User}, which by itself doesn't really have that much information in it.
 *
 * <p>
 * So the common technique for a mail address resolution is to define your own {@link UserProperty} types and
 * add it to {@link User} objects where more context is available. For example, an {@link SCM} implementation
 * can have a lot more information about a particular user during a check out, so that would be a good place
 * to capture information as {@link UserProperty}, which then later used by a {@link MailAddressResolver}. 
 *
66
 * @author Kohsuke Kawaguchi
67
 * @since 1.192
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
 */
public abstract class MailAddressResolver implements ExtensionPoint {
    /**
     * Infers e-mail address of the given user.
     *
     * <p>
     * This method is called when a {@link User} without explicitly configured e-mail
     * address is used, as an attempt to infer e-mail address.
     *
     * <p>
     * The normal strategy is to look at {@link User#getProjects() the projects that the user
     * is participating}, then use the repository information to infer the e-mail address.
     *
     * <p>
     * When multiple resolvers are installed, they are consulted in order and
     * the search will be over when an address is inferred by someone.
     *
     * <p>
     * Since {@link MailAddressResolver} is singleton, this method can be invoked concurrently
     * from multiple threads.
     *
     * @return
     *      null if the inference failed.
     */
    public abstract String findMailAddressFor(User u);
    
94
    public static String resolve(User u) {
95 96 97
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine("Resolving e-mail address for \""+u+"\" ID="+u.getId());
        }
98

K
kohsuke 已提交
99
        for (MailAddressResolver r : all()) {
100
            String email = r.findMailAddressFor(u);
101
            if(email!=null) {
102 103 104
                if (LOGGER.isLoggable(Level.FINE)) {
                    LOGGER.fine(r+" resolved "+u.getId()+" to "+email);
                }
105 106
                return email;
            }
107
        }
K
kohsuke 已提交
108 109

        // fall back logic
110
        String extractedAddress = extractAddressFromId(u.getFullName());
K
kohsuke 已提交
111
        if (extractedAddress != null)
112
            return extractedAddress;
K
kohsuke 已提交
113

114
        if(u.getFullName().contains("@"))
K
kohsuke 已提交
115
            // this already looks like an e-mail ID
116
            return u.getFullName();
K
kohsuke 已提交
117

118
        String ds = Mailer.descriptor().getDefaultSuffix();
K
kohsuke 已提交
119 120 121 122 123 124 125
        if(ds!=null) {
            // another common pattern is "DOMAIN\person" in Windows. Only
            // do this when this full name is not manually set. see HUDSON-5164
            Matcher m = WINDOWS_DOMAIN_REGEXP.matcher(u.getFullName());
            if (m.matches() && u.getFullName().replace('\\','_').equals(u.getId()))
                return m.group(1)+ds; // user+defaultSuffix

K
kohsuke 已提交
126
            return u.getId()+ds;
K
kohsuke 已提交
127
        } else
K
kohsuke 已提交
128 129 130 131 132 133 134 135 136 137 138
            return null;
    }

    /**
     * Tries to extract an email address from the user id, or returns null
     */
    private static String extractAddressFromId(String id) {
        Matcher m = EMAIL_ADDRESS_REGEXP.matcher(id);
        if(m.matches())
    		return m.group(1);
    	return null;
139 140
    }

K
kohsuke 已提交
141 142 143 144 145 146
    /**
     * Matches strings like "Kohsuke Kawaguchi &lt;kohsuke.kawaguchi@sun.com>"
     * @see #extractAddressFromId(String)
     */
    private static final Pattern EMAIL_ADDRESS_REGEXP = Pattern.compile("^.*<([^>]+)>.*$");

K
kohsuke 已提交
147 148 149 150
    /**
     * Matches something like "DOMAIN\person"
     */
    private static final Pattern WINDOWS_DOMAIN_REGEXP = Pattern.compile("[^\\\\ ]+\\\\([^\\\\ ]+)");
151 152 153

    /**
     * All registered {@link MailAddressResolver} implementations.
K
kohsuke 已提交
154 155 156
     *
     * @deprecated as of 1.286
     *      Use {@link #all()} for read access and {@link Extension} for registration.
157
     */
K
kohsuke 已提交
158
    public static final List<MailAddressResolver> LIST = ExtensionListView.createList(MailAddressResolver.class);
159

K
kohsuke 已提交
160 161 162 163
    /**
     * Returns all the registered {@link MailAddressResolver} descriptors.
     */
    public static ExtensionList<MailAddressResolver> all() {
164
        return Jenkins.getInstance().getExtensionList(MailAddressResolver.class);
165
    }
166 167

    private static final Logger LOGGER = Logger.getLogger(MailAddressResolver.class.getName());
168
}