Package org.apache.james.transport.mailets

Source Code of org.apache.james.transport.mailets.ReplaceContent$ReplaceConfig

/****************************************************************
* 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.apache.james.transport.mailets;

import org.apache.mailet.base.StringUtils;
import org.apache.mailet.base.GenericMailet;
import org.apache.mailet.Mail;
import org.apache.mailet.MailetException;

import javax.mail.MessagingException;
import javax.mail.internet.ContentType;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
* Replace text contents
* <p>This mailet allow to specific regular expression to replace text in subject and content.
*
* <p>
* Each expression is defined as:
* <code>/REGEX_PATTERN/SUBSTITUTION_PATTERN/FLAGS/</code>
* </p>
*
* <p>
* <code>REGEX_PATTERN</code> is a regex used for the match<br>
* <code>SUBSTITUTION_PATTERN</code> is a substitution pattern<br>
* <code>FLAGS</code> flags supported for the pattern:<br>
*   i: case insensitive<br>
*   m: multi line<br>
*   x: extended (N/A)<br>
*   r: repeat - keep matching until a substitution is possible<br>
* </p>
*
* <p>To identify subject and body pattern we use the tags &lt;subjectPattern&gt; and &lt;bodyPattern&gt;</p>
*
* <p>
* Rules can be specified in external files.
* Lines must be CRLF terminated and lines starting with # are considered commments.
* Tags used to include external files are &lt;subjectPatternFile&gt; and
* &lt;bodyPatternFile&gt;
* If file path starts with # then the file is loaded as a reasource.
* </p>
*
* <p>
* Use of both files and direct patterns at the same time is allowed.
* </p>
*
* <p>
* This mailet allow also to enforce the resulting charset for messages processed.
* To do that the tag &lt;charset&gt; must be specified.
* </p>
*
* <p>
* NOTE:
* Regexp rules must be escaped by regexp excaping rules and applying this 2 additional rules:<br>
* - "/" char inside an expression must be prefixed with "\":
*   e.g: "/\//-//" replaces "/" with "-"<br>
* - when the rules are specified using &lt;subjectPattern&gt; or &lt;bodyPattern&gt; and
*   "/,/" has to be used in a pattern string it must be prefixed with a "\".
*   E.g: "/\/\/,//" replaces "/" with "," (the rule would be "/\//,//" but the "/,/" must
*   be escaped.<br>
* </p>
*/
public class ReplaceContent extends GenericMailet {
    private static final String PARAMETER_NAME_SUBJECT_PATTERN = "subjectPattern";
    private static final String PARAMETER_NAME_BODY_PATTERN = "bodyPattern";
    private static final String PARAMETER_NAME_SUBJECT_PATTERNFILE = "subjectPatternFile";
    private static final String PARAMETER_NAME_BODY_PATTERNFILE = "bodyPatternFile";
    private static final String PARAMETER_NAME_CHARSET = "charset";
   
    public static final int FLAG_REPEAT = 1;
   
    private static class ReplaceConfig {
        private Pattern[] subjectPatterns;
        private String[] subjectSubstitutions;
        private Integer[] subjectFlags;
        private Pattern[] bodyPatterns;
        private String[] bodySubstitutions;
        private Integer[] bodyFlags;
    }
   
    private String charset;
    private int debug = 0;
   
    /**
     * returns a String describing this mailet.
     *
     * @return A desciption of this mailet
     */
    public String getMailetInfo() {
        return "ReplaceContent";
    }

    /**
     * @return an array containing Pattern and Substitution of the input stream
     * @throws MailetException
     */
    protected static Object[] getPattern(String line) throws MailetException {
        String[] pieces = StringUtils.split(line, "/");
        if (pieces.length < 3) throw new MailetException("Invalid expression: " + line);
        int options = 0;
        //if (pieces[2].indexOf('x') >= 0) options += Pattern.EXTENDED;
        if (pieces[2].indexOf('i') >= 0) options += Pattern.CASE_INSENSITIVE;
        if (pieces[2].indexOf('m') >= 0) options += Pattern.MULTILINE;
        if (pieces[2].indexOf('s') >= 0) options += Pattern.DOTALL;
       
        int flags = 0;
        if (pieces[2].indexOf('r') >= 0) flags += FLAG_REPEAT;
       
        if (pieces[1].indexOf("\\r") >= 0) pieces[1] = pieces[1].replaceAll("\\\\r", "\r");
        if (pieces[1].indexOf("\\n") >= 0) pieces[1] = pieces[1].replaceAll("\\\\n", "\n");
        if (pieces[1].indexOf("\\t") >= 0) pieces[1] = pieces[1].replaceAll("\\\\t", "\t");
       
        return new Object[] {Pattern.compile(pieces[0], options), pieces[1] , new Integer(flags)};
    }
   
    protected static List[] getPatternsFromString(String pattern) throws MailetException {
        pattern = pattern.trim();
        if (pattern.length() < 2 && !pattern.startsWith("/") && !pattern.endsWith("/")) throw new MailetException("Invalid parameter value: " + PARAMETER_NAME_SUBJECT_PATTERN);
        pattern = pattern.substring(1, pattern.length() - 1);
        String[] patternArray = StringUtils.split(pattern, "/,/");
       
        List patterns = new ArrayList();
        List substitutions = new ArrayList();
        List flags = new ArrayList();
        for (int i = 0; i < patternArray.length; i++) {
            Object[] o = getPattern(patternArray[i]);
            patterns.add(o[0]);
            substitutions.add(o[1]);
            flags.add(o[2]);
        }
       
        return new List[] {patterns, substitutions, flags};
    }

    protected static List[] getPatternsFromStream(InputStream stream, String charset) throws MailetException, IOException {
        List patterns = new ArrayList();
        List substitutions = new ArrayList();
        List flags = new ArrayList();
        BufferedReader reader = new BufferedReader(charset != null ? new InputStreamReader(stream, charset) : new InputStreamReader(stream));
        //BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("q:\\correzioniout"), "utf-8"));
       
        String line;
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            if (line.length() > 0 && !line.startsWith("#")) {
                if (line.length() < 2 && !line.startsWith("/") && !line.endsWith("/")) throw new MailetException("Invalid expression: " + line);
                Object[] o = getPattern(line.substring(1, line.length() - 1));
                patterns.add(o[0]);
                substitutions.add(o[1]);
                flags.add(o[2]);
            }
        }
        reader.close();
        return new List[] {patterns, substitutions, flags};
    }
   
    /**
     * @param filepar File path list (or resources if the path starts with #) comma separated
     */
    private List[] getPatternsFromFileList(String filepar) throws MailetException, IOException {
        List patterns = new ArrayList();
        List substitutions = new ArrayList();
        List flags = new ArrayList();
        String[] files = filepar.split(",");
        for (int i = 0; i < files.length; i++) {
            files[i] = files[i].trim();
            if (debug > 0) log("Loading patterns from: " + files[i]);
            String charset = null;
            int pc = files[i].lastIndexOf('?');
            if (pc >= 0) {
                charset = files[i].substring(pc + 1);
                files[i] = files[i].substring(0, pc);
            }
            InputStream is = null;
            if (files[i].startsWith("#")) is = getClass().getResourceAsStream(files[i].substring(1));
            else {
                File f = new File(files[i]);
                if (f.isFile()) is = new FileInputStream(f);
            }
            if (is != null) {
                List[] o = getPatternsFromStream(is, charset);
                patterns.addAll(o[0]);
                substitutions.addAll(o[1]);
                flags.addAll(o[2]);
                is.close();
            }
        }
        return new List[] {patterns, substitutions, flags};
    }
   
    protected static String applyPatterns(Pattern[] patterns, String[] substitutions, Integer[] pflags, String text, int debug, GenericMailet logOwner) {
        for (int i = 0; i < patterns.length; i ++) {
            int flags = pflags[i].intValue();
            boolean changed = false;
            do {
                changed = false;
                String replaced = patterns[i].matcher(text).replaceAll(substitutions[i]);
                if (!replaced.equals(text)) {
                    if (debug > 0) logOwner.log("Subject rule match: " + patterns[i].pattern());
                    text = replaced;
                    changed = true;
                }
            } while ((flags & FLAG_REPEAT) > 0 && changed);
        }
       
        return text;
    }
   

    public void init() throws MailetException {
        charset = getInitParameter(PARAMETER_NAME_CHARSET);
        debug = Integer.parseInt(getInitParameter("debug", "0"));
    }
   
    private ReplaceConfig initPatterns() throws MailetException {
        try {
            List bodyPatternsList = new ArrayList();
            List bodySubstitutionsList = new ArrayList();
            List bodyFlagsList = new ArrayList();
            List subjectPatternsList = new ArrayList();
            List subjectSubstitutionsList = new ArrayList();
            List subjectFlagsList = new ArrayList();

            String pattern = getInitParameter(PARAMETER_NAME_SUBJECT_PATTERN);
            if (pattern != null) {
                List[] o = getPatternsFromString(pattern);
                subjectPatternsList.addAll(o[0]);
                subjectSubstitutionsList.addAll(o[1]);
                subjectFlagsList.addAll(o[2]);
            }
           
            pattern = getInitParameter(PARAMETER_NAME_BODY_PATTERN);
            if (pattern != null) {
                List[] o = getPatternsFromString(pattern);
                bodyPatternsList.addAll(o[0]);
                bodySubstitutionsList.addAll(o[1]);
                bodyFlagsList.addAll(o[2]);
            }
           
            String filepar = getInitParameter(PARAMETER_NAME_SUBJECT_PATTERNFILE);
            if (filepar != null) {
                List[] o = getPatternsFromFileList(filepar);
                subjectPatternsList.addAll(o[0]);
                subjectSubstitutionsList.addAll(o[1]);
                subjectFlagsList.addAll(o[2]);
            }
       
            filepar = getInitParameter(PARAMETER_NAME_BODY_PATTERNFILE);
            if (filepar != null) {
                List[] o = getPatternsFromFileList(filepar);
                bodyPatternsList.addAll(o[0]);
                bodySubstitutionsList.addAll(o[1]);
                bodyFlagsList.addAll(o[2]);
            }
           
            ReplaceConfig rConfig = new ReplaceConfig();
            rConfig.subjectPatterns = (Pattern[]) subjectPatternsList.toArray(new Pattern[0]);
            rConfig.subjectSubstitutions = (String[]) subjectSubstitutionsList.toArray(new String[0]);
            rConfig.subjectFlags = (Integer[]) subjectFlagsList.toArray(new Integer[0]);
            rConfig.bodyPatterns = (Pattern[]) bodyPatternsList.toArray(new Pattern[0]);
            rConfig.bodySubstitutions = (String[]) bodySubstitutionsList.toArray(new String[0]);
            rConfig.bodyFlags = (Integer[]) bodyFlagsList.toArray(new Integer[0]);
           
            return rConfig;
           
        } catch (FileNotFoundException e) {
            throw new MailetException("Failed initialization", e);
           
        } catch (MailetException e) {
            throw new MailetException("Failed initialization", e);
           
        } catch (IOException e) {
            throw new MailetException("Failed initialization", e);
           
        }
    }

    public void service(Mail mail) throws MailetException {
        ReplaceConfig rConfig = initPatterns();
       
        try {
            boolean mod = false;
            boolean contentChanged = false;
           
            if (rConfig.subjectPatterns != null && rConfig.subjectPatterns.length > 0) {
                String subject = mail.getMessage().getSubject();
                if (subject == null) subject = "";
                subject = applyPatterns(rConfig.subjectPatterns, rConfig.subjectSubstitutions, rConfig.subjectFlags, subject, debug, this);
                if (charset != null) mail.getMessage().setSubject(subject, charset);
                else mail.getMessage().setSubject(subject);
                mod = true;
            }
           
            if (rConfig.bodyPatterns != null && rConfig.bodyPatterns.length > 0) {
                Object bodyObj = mail.getMessage().getContent();
                if (bodyObj == null) bodyObj = "";
                if (bodyObj instanceof String) {
                    String body = (String) bodyObj;
                    body = applyPatterns(rConfig.bodyPatterns, rConfig.bodySubstitutions, rConfig.bodyFlags, body, debug, this);
                    String contentType = mail.getMessage().getContentType();
                    if (charset != null) {
                        ContentType ct = new ContentType(contentType);
                        ct.setParameter("charset", charset);
                        contentType = ct.toString();
                    }
                    mail.getMessage().setContent(body, contentType);
                    mod = true;
                    contentChanged = true;
                }
            }
           
            if (charset != null && !contentChanged) {
                ContentType ct = new ContentType(mail.getMessage().getContentType());
                ct.setParameter("charset", charset);
                String contentType = mail.getMessage().getContentType();
                mail.getMessage().setContent(mail.getMessage().getContent(), contentType);
            }
           
            if (mod) mail.getMessage().saveChanges();
           
        } catch (MessagingException e) {
            throw new MailetException("Error in replace", e);
           
        } catch (IOException e) {
            throw new MailetException("Error in replace", e);
        }
    }

}
TOP

Related Classes of org.apache.james.transport.mailets.ReplaceContent$ReplaceConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.