source: contrib/MailArchiver/sources/src/serpro/mailarchiver/service/web/DefaultArchiveOperation.java @ 6785

Revision 6785, 66.2 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado codigo do MailArchiver?. Documentação na subpasta DOCS.

Line 
1/**
2 * MailArchiver is an application that provides services for storing and managing e-mail messages through a Web Services SOAP interface.
3 * Copyright (C) 2012  Marcio Andre Scholl Levien and Fernando Alberto Reuter Wendt and Jose Ronaldo Nogueira Fonseca Junior
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/******************************************************************************\
20*
21*  This product was developed by
22*
23*        SERVIÇO FEDERAL DE PROCESSAMENTO DE DADOS (SERPRO),
24*
25*  a government company established under Brazilian law (5.615/70),
26*  at Department of Development of Porto Alegre.
27*
28\******************************************************************************/
29
30package serpro.mailarchiver.service.web;
31
32import java.io.ByteArrayInputStream;
33import java.io.IOException;
34import java.io.InputStream;
35import java.io.UnsupportedEncodingException;
36import java.nio.charset.Charset;
37import java.nio.file.Path;
38import java.security.MessageDigest;
39import java.security.NoSuchAlgorithmException;
40import java.util.Arrays;
41import java.util.Date;
42import java.util.Map.Entry;
43import java.util.Stack;
44import java.util.UUID;
45import java.util.regex.Matcher;
46import java.util.regex.Pattern;
47
48import javax.jdo.annotations.PersistenceAware;
49
50import org.apache.james.mime4j.codec.DecodeMonitor;
51import org.apache.james.mime4j.codec.DecoderUtil;
52import org.apache.james.mime4j.io.LineNumberInputStream;
53import org.apache.james.mime4j.message.SimpleContentHandler;
54import org.apache.james.mime4j.parser.MimeStreamParser;
55import org.apache.james.mime4j.stream.BodyDescriptor;
56import org.apache.james.mime4j.stream.MimeConfig;
57import org.apache.james.mime4j.util.CharsetUtil;
58
59import org.apache.lucene.document.DateTools;
60import org.apache.lucene.document.DateTools.Resolution;
61import org.apache.lucene.document.Document;
62import org.apache.lucene.index.FieldInfo.IndexOptions;
63
64import org.springframework.beans.factory.annotation.Autowired;
65
66import com.google.common.base.Supplier;
67import com.google.common.io.Files;
68
69import net.htmlparser.jericho.Element;
70import net.htmlparser.jericho.Source;
71import net.htmlparser.jericho.TextExtractor;
72
73import serpro.mailarchiver.domain.metaarchive.*;
74import serpro.mailarchiver.service.BaseService;
75import serpro.mailarchiver.service.dto.TMessage;
76import serpro.mailarchiver.service.find.FFolder;
77import serpro.mailarchiver.service.find.FMessage;
78import serpro.mailarchiver.session.Session;
79import serpro.mailarchiver.util.Charsets;
80import serpro.mailarchiver.util.Logger;
81import serpro.mailarchiver.util.jdo.PersistenceManager;
82import serpro.mailarchiver.util.transaction.WithReadWriteTx;
83
84@PersistenceAware
85public class DefaultArchiveOperation
86    extends BaseService
87    implements ArchiveOperation
88{
89    private static class ExpungedException extends RuntimeException {}
90
91    private static class RepeatedException extends RuntimeException {}
92
93    private static final Logger log = Logger.getLocalLogger();
94
95    private static final String CR = "\015";
96    private static final String LF = "\012";
97    private static final String CRLF = "\015\012";
98
99    @Autowired
100    private FFolder findFolder;
101
102    @Autowired
103    private FMessage findMessage;
104
105    @WithReadWriteTx
106    @Override
107    public TMessage apply(String folderId, String message) throws ServiceFault {
108
109        PersistenceManager pm = getPersistenceManager();
110
111        Folder folder = findFolder.byId(folderId);
112
113        if(folder == null) {
114            ServiceFault.folderNotFound()
115                    .setActor("archive")
116                    .setMessage("Destination folder not found.")
117                    .addValue("folderId", folderId)
118                    .raise();
119        }
120
121        MimeConfig config = new MimeConfig();
122        config.setStrictParsing(false);
123        config.setMaxLineLen(-1);
124        config.setMaxContentLen(-1);
125        config.setMaxHeaderLen(-1);
126        config.setMaxHeaderCount(-1);
127
128        Message rootMessage = null;
129
130        MessageHandler handler = null;
131
132        try {
133            handler = new MessageHandler(folder);
134
135            MimeStreamParser parser = new MimeStreamParser(config);
136            parser.setContentHandler(handler);
137            parser.setContentDecoding(true);
138
139            byte[] ba = message.getBytes(Charsets.Windows_1252);
140
141            switch(ba[ba.length - 1]) {
142                case 0x0A: //LF
143                    break;
144
145                case 0x0D: //CR
146                    ba = Arrays.copyOf(ba, ba.length + 1);
147                    ba[ba.length - 1] = 0x0A;
148                    break;
149
150                default:
151                    ba = Arrays.copyOf(ba, ba.length + 2);
152                    ba[ba.length - 2] = 0x0D;
153                    ba[ba.length - 1] = 0x0A;
154                    break;
155            }
156
157            parser.parse(new ByteArrayInputStream(ba));
158
159            //debug
160            //MimeTokenStream mimeTokenStream = parser.getMimeTokenStream();
161            //LineNumberInputStream.Entity lineNumberRootEntity = mimeTokenStream.getLineNumberRootEntity();
162            //String dump = lineNumberRootEntity.dump("root entity");
163            //System.out.println(dump);
164
165            rootMessage = handler.getRootMessage();
166            rootMessage.sync();
167
168            rootMessage.setFolder(folder);
169
170            rootMessage.setUnseen(true);
171            rootMessage.setUnanswered(true);
172
173            UnstructuredField importanceField = (UnstructuredField)rootMessage.getField("importance");
174            if(importanceField != null) {
175                String importance = importanceField.getText().toLowerCase().trim();
176                if("high".equals(importance)) {
177                    rootMessage.setImportanceHigh(true);
178                }
179                else if("low".equals(importance)) {
180                    rootMessage.setImportanceLow(true);
181                }
182                else {
183                    rootMessage.setImportanceNormal(true);
184                }
185            }
186
187            pm.makePersistent(rootMessage);
188
189            Path msgFile = folder.getAbsolutePath().resolve(rootMessage.getOid() + ".eml");
190
191            Files.write(ba, msgFile.toFile());
192
193            Document luceneDoc = handler.getLuceneDoc();
194
195            Session.getLuceneIndex().addMessage(luceneDoc);
196
197            final Message rootMsg = rootMessage;
198
199            log.info("Mensagem arquivada com sucesso:%n%n%1$s", new Supplier<Object[]>() {
200                @Override
201                public Object[] get() {
202                    String msgDOM = rootMsg.dumpTree();
203                    //debug
204                    //System.out.println(msgDOM);
205                    return new Object[] { msgDOM };
206                }
207            });
208        }
209        catch(ExpungedException e) {
210            ServiceFault.expungedMessage()
211                    .setActor("archive")
212                    .raise();
213        }
214        catch(RepeatedException e) {
215            rootMessage = handler.getRootMessage();
216        }
217        catch(Throwable t) {
218            ServiceFault.archiveFailure()
219                    .setActor("archive")
220                    .setMessage("Archive failure.")
221                    .setCause(t)
222                    .raise();
223        }
224
225        return new TMessage(rootMessage);
226    }
227
228    private class MessageHandler extends SimpleContentHandler {
229
230        private static final int MSG_FLAG_EXPUNGED = 0x0008;
231
232        private Stack<Entity> entityStack;
233        private Stack<Multipart> multipartStack;
234
235        private final Folder folder;
236
237        private Message rootMessage;
238        private LineNumberInputStream.Entity rootLnisEntity;
239
240        private Document luceneDoc;
241
242        private boolean parsingRoot;
243
244        Message getRootMessage() {
245            return rootMessage;
246        }
247
248        Document getLuceneDoc() {
249            return luceneDoc;
250        }
251
252        public MessageHandler(Folder folder) {
253            this.folder = folder;
254            entityStack = new Stack<Entity>();
255            multipartStack = new Stack<Multipart>();
256        }
257
258        //message_id
259        private void addStoredNotAnalyzedIndexField(String name, String value) {
260            org.apache.lucene.document.Field field = new org.apache.lucene.document.Field(
261                    name, value,
262                    org.apache.lucene.document.Field.Store.YES,
263                    org.apache.lucene.document.Field.Index.NOT_ANALYZED);
264            field.setIndexOptions(IndexOptions.DOCS_ONLY);
265            luceneDoc.add(field);
266        }
267
268        //date, from_mbox, sender_mbox, to_mbox, cc_mbox, bcc_mbox
269        private void addNotAnalyzedIndexField(String name, String value) {
270            org.apache.lucene.document.Field field = new org.apache.lucene.document.Field(
271                    name, value,
272                    org.apache.lucene.document.Field.Store.NO,
273                    org.apache.lucene.document.Field.Index.NOT_ANALYZED);
274            field.setIndexOptions(IndexOptions.DOCS_ONLY);
275            luceneDoc.add(field);
276        }
277
278        //subject, from, sender, to, cc, bcc, body
279        private void addAnalyzedIndexField(String name, String value) {
280            org.apache.lucene.document.Field field = new org.apache.lucene.document.Field(
281                    name, value,
282                    org.apache.lucene.document.Field.Store.NO,
283                    org.apache.lucene.document.Field.Index.ANALYZED);
284            field.setIndexOptions(IndexOptions.DOCS_ONLY);
285            luceneDoc.add(field);
286        }
287
288        private String decodeEncodedWords(String text) {
289            String decoded = DecoderUtil.decodeEncodedWords(text, new DecodeMonitor() {
290                @Override
291                public boolean warn(String error, String dropDesc) {
292                    log.warn("error: %s\ndropDesc: %s", error, dropDesc);
293                    return false;
294                }
295            });
296            //debug
297            //if( ! decoded.equals(text)) {
298            //    System.out.println(String.format("original: %s\ndecoded: %s", text, decoded));
299            //}
300            return decoded;
301        }
302
303        @Override
304        public void startMessage(LineNumberInputStream.Entity lnisEntity) {
305
306            if(entityStack.empty()) {
307                //o empilhamento da mensagem raiz é postergado até
308                //a leitura do primeiro header para verificar expungimento
309
310                rootLnisEntity = lnisEntity;
311                return;
312            }
313
314            final MessageBody messageBody = new MessageBody();
315            messageBody.setEntity(entityStack.peek());
316
317            final EmbeddedMessage embeddedMessage = new EmbeddedMessage(lnisEntity);
318            embeddedMessage.setComposite(messageBody);
319
320            entityStack.push(embeddedMessage);
321
322            log.debug("Mime Parse Event: START EMBEDDED MESSAGE\n\n%s", new Supplier<Object[]>() {
323                @Override
324                public Object[] get() {
325                    String domPath = embeddedMessage.dumpPath();
326                    //System.out.println("START EMBEDDED MESSAGE");
327                    //System.out.println(domPath);
328                    return new Object[] { domPath };
329                }
330            });
331        }
332
333        @Override
334        public void startMultipart(BodyDescriptor bd) {
335
336            final Multipart multipart = new Multipart();
337            multipart.setEntity(entityStack.peek());
338
339            multipartStack.push(multipart);
340
341            log.debug("Mime Parse Event: START MULTIPART\n\n%s", new Supplier<Object[]>() {
342                @Override
343                public Object[] get() {
344                    String domPath = multipart.dumpPath();
345                    //System.out.println("START MULTIPART");
346                    //System.out.println(domPath);
347                    return new Object[] { domPath };
348                }
349            });
350        }
351
352        @Override
353        public void preamble(InputStream is) {
354
355            Multipart multipart = multipartStack.peek();
356            multipart.setPreambleStream(is);
357        }
358
359        @Override
360        public void startBodyPart(LineNumberInputStream.Entity lnisEntity) {
361
362            final BodyPart bodyPart = new BodyPart(lnisEntity);
363            bodyPart.setComposite(multipartStack.peek());
364
365            entityStack.push(bodyPart);
366
367            log.debug("Mime Parse Event: START BODY PART\n\n%s", new Supplier<Object[]>() {
368                @Override
369                public Object[] get() {
370                    String domPath = bodyPart.dumpPath();
371                    //System.out.println("START BODY PART");
372                    //System.out.println(domPath);
373                    return new Object[] { domPath };
374                }
375            });
376        }
377
378        @Override
379        public void headers(org.apache.james.mime4j.dom.Header hd) {
380
381            if(entityStack.empty()) {
382
383                parsingRoot = true;
384
385                //o empilhamento da mensagem raiz é postergado até a leitura do primeiro header para
386                //verificar se a mensagem está marcada como expungida pelo Thunderbird, isto é,
387                //se a mesma foi apagada ou movida de uma pasta que não foi compactada após este evento
388                org.apache.james.mime4j.dom.field.UnstructuredField field =
389                        (org.apache.james.mime4j.dom.field.UnstructuredField) hd.getField("X-Mozilla-Status");
390
391                if(field != null) {
392                    if((Integer.parseInt(field.getValue(), 16) & MSG_FLAG_EXPUNGED) > 0) {
393                        log.debug(">>EXPUNGED<<%n%n%s", hd.toString());
394                        throw new ExpungedException();
395                    }
396                }
397
398                try {
399                    MessageDigest md = MessageDigest.getInstance("MD5");
400
401                    md.update(folder.getOid().getBytes("UTF-8"));
402                    md.update(hd.toString().getBytes("UTF-8"));
403
404                    char[] hexDigest = new char[32];
405                    int i = 0;
406                    for(byte b : md.digest()) {
407                        hexDigest[i++] = Character.forDigit((char)((b & 0xf0) >>> 4), 16);
408                        hexDigest[i++] = Character.forDigit((char)(b & 0x0f), 16);
409                    }
410
411                    String digest = new String(hexDigest);
412
413                    String guid = digest.substring(0, 8) +
414                            "-" + digest.substring(8, 12) +
415                            "-" + digest.substring(12, 16) +
416                            "-" + digest.substring(16, 20) +
417                            "-" + digest.substring(20, 32);
418
419                    rootMessage = findMessage.byId(guid);
420
421                    if(rootMessage == null) {
422                        rootMessage = new Message(rootLnisEntity);
423                        rootMessage.setOid(guid);
424
425                        luceneDoc = new Document();
426                    }
427                    else if(rootMessage.getFolder() == folder) {
428                        log.warn(">>REPEATED<<%n%nFolder:%s%n%n%s", folder.getRelativePath(), hd.toString());
429                        throw new RepeatedException();
430                    }
431                    else {
432                        rootMessage = new Message(rootLnisEntity);
433                        rootMessage.setOid(UUID.randomUUID().toString());
434
435                        luceneDoc = new Document();
436                    }
437                }
438                catch(NoSuchAlgorithmException ex) {
439                }
440                catch(UnsupportedEncodingException ex) {
441                }
442
443                entityStack.push(rootMessage);
444
445                addStoredNotAnalyzedIndexField("message_id", rootMessage.getOid());
446
447                log.debug("Mime Parse Event: START MESSAGE\n\n%s", new Supplier<Object[]>() {
448                    @Override
449                    public Object[] get() {
450                        String domPath = rootMessage.dumpPath();
451                        //System.out.println("START MESSAGE");
452                        //System.out.println(domPath);
453                        return new Object[] { domPath };
454                    }
455                });
456            }
457            else {
458                parsingRoot = false;
459            }
460
461            for(org.apache.james.mime4j.stream.Field f : hd) {
462
463                final String fldName = f.getName();
464
465                //<editor-fold defaultstate="collapsed" desc=" unstructured field ">
466                if(f instanceof org.apache.james.mime4j.dom.field.UnstructuredField) {
467
468                    //**********************************************************
469                    //
470                    //  UNSTRUCTURED FIELD
471                    //
472                    //  "Subject", "Message-Id", "Resent-Msg-Id",
473                    //  "Comments", "Keywords", etc
474                    //
475                    //**********************************************************
476
477                    org.apache.james.mime4j.dom.field.UnstructuredField uf =
478                            (org.apache.james.mime4j.dom.field.UnstructuredField) f;
479
480                    final UnstructuredField field = new UnstructuredField();
481                    field.setName(fldName);
482
483                    field.setValid(uf.isValidField());
484                    if(!field.isValid()) {
485                        org.apache.james.mime4j.dom.field.ParseException e = uf.getParseException();
486                        if(e != null) {
487                            field.addParseExceptionStackTrace(e);
488                        }
489                    }
490
491                    String value = uf.getValue();
492                    if(value != null) {
493                        if(("Message-ID".equalsIgnoreCase(fldName))
494                        || ("Resent-Message-ID".equalsIgnoreCase(fldName))) {
495
496                            Matcher m = Pattern.compile("<([^>]+)>").matcher(value);
497                            if(m.find()) {
498                                field.setText(m.group(1));
499                            }
500                            else {
501                                log.error("%s field does not match msg-id format: %s", fldName, value);
502                                field.setText(value);
503                            }
504                        }
505                        else {
506                            value = decodeEncodedWords(value);
507                            field.setText(value);
508                        }
509                    }
510
511                    field.setEntity(entityStack.peek());
512
513                    if(parsingRoot && (value != null)) {
514                        if("subject".equalsIgnoreCase(fldName)) {
515                            addAnalyzedIndexField("subject", value);
516                        }
517                    }
518
519                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
520                        @Override
521                        public Object[] get() {
522                            String domPath = field.dumpPath();
523                            //System.out.println("UNSTRUCTURED FIELD");
524                            //System.out.println(domPath);
525                            return new Object[] { domPath };
526                        }
527                    });
528                }
529                //</editor-fold>
530
531
532                //<editor-fold defaultstate="collapsed" desc=" mime version field ">
533                else if(f instanceof org.apache.james.mime4j.dom.field.MimeVersionField) {
534
535                    //**********************************************************
536                    //
537                    //  MIME VERSION FIELD
538                    //
539                    //**********************************************************
540
541                    org.apache.james.mime4j.dom.field.MimeVersionField mvf =
542                            (org.apache.james.mime4j.dom.field.MimeVersionField) f;
543
544                    final UnstructuredField field = new UnstructuredField();
545                    field.setName(fldName);
546
547                    field.setValid(mvf.isValidField());
548                    if(!field.isValid()) {
549                        org.apache.james.mime4j.dom.field.ParseException e = mvf.getParseException();
550                        if(e != null) {
551                            field.addParseExceptionStackTrace(e);
552                        }
553                    }
554
555                    String mimeVersion = mvf.getMajorVersion() + "." + mvf.getMinorVersion();
556                    field.setText(mimeVersion);
557
558                    field.setEntity(entityStack.peek());
559
560                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
561                        @Override
562                        public Object[] get() {
563                            String domPath = field.dumpPath();
564                            //System.out.println("UNSTRUCTURED FIELD");
565                            //System.out.println(domPath);
566                            return new Object[] { domPath };
567                        }
568                    });
569                }
570                //</editor-fold>
571
572
573                //<editor-fold defaultstate="collapsed" desc=" content md5 field ">
574                else if(f instanceof org.apache.james.mime4j.dom.field.ContentMD5Field) {
575
576                    //**********************************************************
577                    //
578                    //  CONTENT MD5 FIELD
579                    //
580                    //**********************************************************
581
582                    org.apache.james.mime4j.dom.field.ContentMD5Field cmd5f =
583                            (org.apache.james.mime4j.dom.field.ContentMD5Field) f;
584
585                    final UnstructuredField field = new UnstructuredField();
586                    field.setName(fldName);
587
588                    field.setValid(cmd5f.isValidField());
589                    if(!field.isValid()) {
590                        org.apache.james.mime4j.dom.field.ParseException e = cmd5f.getParseException();
591                        if(e != null) {
592                            field.addParseExceptionStackTrace(e);
593                        }
594                    }
595
596                    String md5raw = cmd5f.getMD5Raw();
597                    if(md5raw != null) {
598                        field.setText(md5raw);
599                    }
600
601                    field.setEntity(entityStack.peek());
602
603                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
604                        @Override
605                        public Object[] get() {
606                            String domPath = field.dumpPath();
607                            //System.out.println("UNSTRUCTURED FIELD");
608                            //System.out.println(domPath);
609                            return new Object[] { domPath };
610                        }
611                    });
612                }
613                //</editor-fold>
614
615
616                //<editor-fold defaultstate="collapsed" desc=" content location field ">
617                else if(f instanceof org.apache.james.mime4j.dom.field.ContentLocationField) {
618
619                    //**********************************************************
620                    //
621                    //  CONTENT LOCATION FIELD
622                    //
623                    //**********************************************************
624
625                    org.apache.james.mime4j.dom.field.ContentLocationField clf =
626                            (org.apache.james.mime4j.dom.field.ContentLocationField) f;
627
628                    final UnstructuredField field = new UnstructuredField();
629                    field.setName(fldName);
630
631                    field.setValid(clf.isValidField());
632                    if(!field.isValid()) {
633                        org.apache.james.mime4j.dom.field.ParseException e = clf.getParseException();
634                        if(e != null) {
635                            field.addParseExceptionStackTrace(e);
636                        }
637                    }
638
639                    String location = clf.getLocation();
640                    if(location != null) {
641                        field.setText(location);
642                    }
643
644                    field.setEntity(entityStack.peek());
645
646                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
647                        @Override
648                        public Object[] get() {
649                            String domPath = field.dumpPath();
650                            //System.out.println("UNSTRUCTURED FIELD");
651                            //System.out.println(domPath);
652                            return new Object[] { domPath };
653                        }
654                    });
655                }
656                //</editor-fold>
657
658
659                //<editor-fold defaultstate="collapsed" desc=" content length field ">
660                else if(f instanceof org.apache.james.mime4j.dom.field.ContentLengthField) {
661
662                    //**********************************************************
663                    //
664                    //  CONTENT LENGTH FIELD
665                    //
666                    //**********************************************************
667
668                    org.apache.james.mime4j.dom.field.ContentLengthField clf =
669                            (org.apache.james.mime4j.dom.field.ContentLengthField) f;
670
671                    final UnstructuredField field = new UnstructuredField();
672                    field.setName(fldName);
673
674                    field.setValid(clf.isValidField());
675                    if(!field.isValid()) {
676                        org.apache.james.mime4j.dom.field.ParseException e = clf.getParseException();
677                        if(e != null) {
678                            field.addParseExceptionStackTrace(e);
679                        }
680                    }
681
682                    String length = Long.toString(clf.getContentLength());
683                    field.setText(length);
684
685                    field.setEntity(entityStack.peek());
686
687                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
688                        @Override
689                        public Object[] get() {
690                            String domPath = field.dumpPath();
691                            //System.out.println("UNSTRUCTURED FIELD");
692                            //System.out.println(domPath);
693                            return new Object[] { domPath };
694                        }
695                    });
696                }
697                //</editor-fold>
698
699
700                //<editor-fold defaultstate="collapsed" desc=" content language field ">
701                else if(f instanceof org.apache.james.mime4j.dom.field.ContentLanguageField) {
702
703                    //**********************************************************
704                    //
705                    //  CONTENT LANGUAGE FIELD
706                    //
707                    //**********************************************************
708
709                    org.apache.james.mime4j.dom.field.ContentLanguageField clf =
710                            (org.apache.james.mime4j.dom.field.ContentLanguageField) f;
711
712                    final UnstructuredField field = new UnstructuredField();
713                    field.setName(fldName);
714
715                    field.setValid(clf.isValidField());
716                    if(!field.isValid()) {
717                        org.apache.james.mime4j.dom.field.ParseException e = clf.getParseException();
718                        if(e != null) {
719                            field.addParseExceptionStackTrace(e);
720                        }
721                    }
722
723                    String languages = null;
724                    for(String language : clf.getLanguages()) {
725                        if(languages == null) {
726                            languages = language;
727                        }
728                        else {
729                            languages += "|" + language;
730                        }
731                    }
732
733                    if(languages != null) {
734                        field.setText(languages);
735                    }
736
737                    field.setEntity(entityStack.peek());
738
739                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
740                        @Override
741                        public Object[] get() {
742                            String domPath = field.dumpPath();
743                            //System.out.println("UNSTRUCTURED FIELD");
744                            //System.out.println(domPath);
745                            return new Object[] { domPath };
746                        }
747                    });
748                }
749                //</editor-fold>
750
751
752                //<editor-fold defaultstate="collapsed" desc=" content id field ">
753                else if(f instanceof org.apache.james.mime4j.dom.field.ContentIdField) {
754
755                    //**********************************************************
756                    //
757                    //  CONTENT ID FIELD
758                    //
759                    //**********************************************************
760
761                    org.apache.james.mime4j.dom.field.ContentIdField cidf =
762                            (org.apache.james.mime4j.dom.field.ContentIdField) f;
763
764                    final UnstructuredField field = new UnstructuredField();
765                    field.setName(fldName);
766
767                    field.setValid(cidf.isValidField());
768                    if(!field.isValid()) {
769                        org.apache.james.mime4j.dom.field.ParseException e = cidf.getParseException();
770                        if(e != null) {
771                            field.addParseExceptionStackTrace(e);
772                        }
773                    }
774
775                    String cid = cidf.getId();
776                    if(cid != null) {
777                        Matcher m = Pattern.compile("<([^>]+)>").matcher(cid);
778                        if(m.find()) {
779                            field.setText(m.group(1));
780                        }
781                        else {
782                            log.error("%s field does not match content-id format: %s", fldName, cid);
783                            field.setText(cid);
784                        }
785                    }
786
787                    field.setEntity(entityStack.peek());
788
789                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
790                        @Override
791                        public Object[] get() {
792                            String domPath = field.dumpPath();
793                            //System.out.println("UNSTRUCTURED FIELD");
794                            //System.out.println(domPath);
795                            return new Object[] { domPath };
796                        }
797                    });
798                }
799                //</editor-fold>
800
801
802                //<editor-fold defaultstate="collapsed" desc=" content description field ">
803                else if(f instanceof org.apache.james.mime4j.dom.field.ContentDescriptionField) {
804
805                    //**********************************************************
806                    //
807                    //  CONTENT DESCRIPTION FIELD
808                    //
809                    //**********************************************************
810
811                    org.apache.james.mime4j.dom.field.ContentDescriptionField cdf =
812                            (org.apache.james.mime4j.dom.field.ContentDescriptionField) f;
813
814                    final UnstructuredField field = new UnstructuredField();
815                    field.setName(fldName);
816
817                    field.setValid(cdf.isValidField());
818                    if(!field.isValid()) {
819                        org.apache.james.mime4j.dom.field.ParseException e = cdf.getParseException();
820                        if(e != null) {
821                            field.addParseExceptionStackTrace(e);
822                        }
823                    }
824
825                    String description = cdf.getDescription();
826                    if(description != null) {
827                        description = decodeEncodedWords(description);
828                        field.setText(description);
829                    }
830
831                    field.setEntity(entityStack.peek());
832
833                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
834                        @Override
835                        public Object[] get() {
836                            String domPath = field.dumpPath();
837                            //System.out.println("UNSTRUCTURED FIELD");
838                            //System.out.println(domPath);
839                            return new Object[] { domPath };
840                        }
841                    });
842                }
843                //</editor-fold>
844
845
846                //<editor-fold defaultstate="collapsed" desc=" content transfer encoding field ">
847                else if(f instanceof org.apache.james.mime4j.dom.field.ContentTransferEncodingField) {
848
849                    //**********************************************************
850                    //
851                    //  CONTENT TRANSFER ENCODING FIELD
852                    //
853                    //**********************************************************
854
855                    org.apache.james.mime4j.dom.field.ContentTransferEncodingField ctef =
856                            (org.apache.james.mime4j.dom.field.ContentTransferEncodingField) f;
857
858                    final UnstructuredField field = new UnstructuredField();
859                    field.setName(fldName);
860
861                    field.setValid(ctef.isValidField());
862                    if(!field.isValid()) {
863                        org.apache.james.mime4j.dom.field.ParseException e = ctef.getParseException();
864                        if(e != null) {
865                            field.addParseExceptionStackTrace(e);
866                        }
867                    }
868
869                    String encoding = ctef.getEncoding();
870                    if(encoding != null) {
871                        field.setText(encoding);
872                    }
873
874                    field.setEntity(entityStack.peek());
875
876                    log.debug("Mime Parse Event: UNSTRUCTURED FIELD\n\n%s", new Supplier<Object[]>() {
877                        @Override
878                        public Object[] get() {
879                            String domPath = field.dumpPath();
880                            //System.out.println("UNSTRUCTURED FIELD");
881                            //System.out.println(domPath);
882                            return new Object[] { domPath };
883                        }
884                    });
885                }
886                //</editor-fold>
887
888
889                //<editor-fold defaultstate="collapsed" desc=" content type field ">
890                else if(f instanceof org.apache.james.mime4j.dom.field.ContentTypeField) {
891
892                    //**********************************************************
893                    //
894                    //  CONTENT TYPE FIELD
895                    //
896                    //**********************************************************
897
898                    org.apache.james.mime4j.dom.field.ContentTypeField ctf =
899                            (org.apache.james.mime4j.dom.field.ContentTypeField) f;
900
901                    final ContentTypeField field = new ContentTypeField();
902                    field.setName(fldName);
903
904                    field.setValid(ctf.isValidField());
905                    if(!field.isValid()) {
906                        org.apache.james.mime4j.dom.field.ParseException e = ctf.getParseException();
907                        if(e != null) {
908                            field.addParseExceptionStackTrace(e);
909                        }
910                    }
911
912                    String mimeType = ctf.getMimeType();
913                    if(mimeType != null) {
914                        String[] mimeTypeSplit = mimeType.split("/");
915                        field.setMediaType(mimeTypeSplit[0]);
916                        field.setSubType(mimeTypeSplit[1]);
917                    }
918
919                    for(Entry<String,String> entry : ctf.getParameters().entrySet()) {
920                        String key = entry.getKey();
921                        String value = entry.getValue();
922                        if((key != null) && (!key.isEmpty()) && (value != null) && (!value.isEmpty())) {
923                            value = decodeEncodedWords(value);
924                            field.addParameter(key, value);
925                        }
926                    }
927
928                    field.setEntity(entityStack.peek());
929
930                    log.debug("Mime Parse Event: CONTENT TYPE FIELD\n\n%s", new Supplier<Object[]>() {
931                        @Override
932                        public Object[] get() {
933                            String domPath = field.dumpPath();
934                            //System.out.println("CONTENT TYPE FIELD");
935                            //System.out.println(domPath);
936                            return new Object[] { domPath };
937                        }
938                    });
939                }
940                //</editor-fold>
941
942
943                //<editor-fold defaultstate="collapsed" desc=" content disposition field ">
944                else if(f instanceof org.apache.james.mime4j.dom.field.ContentDispositionField) {
945
946                    //**********************************************************
947                    //
948                    //  CONTENT DISPOSITION FIELD
949                    //
950                    //**********************************************************
951
952                    org.apache.james.mime4j.dom.field.ContentDispositionField cdf =
953                            (org.apache.james.mime4j.dom.field.ContentDispositionField) f;
954
955                    final ContentDispositionField field = new ContentDispositionField();
956                    field.setName(fldName);
957
958                    field.setValid(cdf.isValidField());
959                    if(!field.isValid()) {
960                        org.apache.james.mime4j.dom.field.ParseException e = cdf.getParseException();
961                        if(e != null) {
962                            field.addParseExceptionStackTrace(e);
963                        }
964                    }
965
966                    String dispositionType = cdf.getDispositionType();
967                    if(dispositionType != null) {
968                        field.setDispositionType(dispositionType);
969                    }
970
971                    for(Entry<String,String> entry : cdf.getParameters().entrySet()) {
972                        String key = entry.getKey();
973                        String value = entry.getValue();
974                        if((key != null) && (!key.isEmpty()) && (value != null) && (!value.isEmpty())) {
975                            value = decodeEncodedWords(value);
976                            field.addParameter(key, value);
977                        }
978                    }
979
980                    field.setEntity(entityStack.peek());
981
982                    log.debug("Mime Parse Event: CONTENT DISPOSITION FIELD\n\n%s", new Supplier<Object[]>() {
983                        @Override
984                        public Object[] get() {
985                            String domPath = field.dumpPath();
986                            //System.out.println("CONTENT DISPOSITION FIELD");
987                            //System.out.println(domPath);
988                            return new Object[] { domPath };
989                        }
990                    });
991                }
992                //</editor-fold>
993
994
995                //<editor-fold defaultstate="collapsed" desc=" date time field ">
996                else if(f instanceof org.apache.james.mime4j.dom.field.DateTimeField) {
997
998                    //**********************************************************
999                    //
1000                    //  DATE TIME FIELD
1001                    //
1002                    //  "Date", "Resent-Date"
1003                    //
1004                    //**********************************************************
1005
1006                    org.apache.james.mime4j.dom.field.DateTimeField dtf =
1007                            (org.apache.james.mime4j.dom.field.DateTimeField) f;
1008
1009                    final DateTimeField field = new DateTimeField();
1010                    field.setName(fldName);
1011
1012                    field.setValid(dtf.isValidField());
1013                    if(!field.isValid()) {
1014                        org.apache.james.mime4j.dom.field.ParseException e = dtf.getParseException();
1015                        if(e != null) {
1016                            field.addParseExceptionStackTrace(e);
1017                        }
1018                    }
1019
1020                    Date date = dtf.getDate();
1021                    if(date != null) {
1022                        field.setDate(date);
1023                    }
1024
1025                    field.setEntity(entityStack.peek());
1026
1027                    if(parsingRoot && (date != null)) {
1028                        if("date".equalsIgnoreCase(fldName)) {
1029                            addNotAnalyzedIndexField("date", DateTools.dateToString(date, Resolution.SECOND));
1030                        }
1031                    }
1032
1033                    log.debug("Mime Parse Event: DATE TIME FIELD\n\n%s", new Supplier<Object[]>() {
1034                        @Override
1035                        public Object[] get() {
1036                            String domPath = field.dumpPath();
1037                            //System.out.println("DATE TIME FIELD");
1038                            //System.out.println(domPath);
1039                            return new Object[] { domPath };
1040                        }
1041                    });
1042                }
1043                //</editor-fold>
1044
1045
1046                //<editor-fold defaultstate="collapsed" desc=" address list field ">
1047                else if(f instanceof org.apache.james.mime4j.dom.field.AddressListField) {
1048
1049                    //**********************************************************
1050                    //
1051                    //  ADDRESS LIST FIELD
1052                    //
1053                    //  "To", "Cc", "Bcc", "Reply-To",
1054                    //  "Resent-To", "Resent-Cc", "Resent-Bcc"
1055                    //
1056                    //**********************************************************
1057
1058                    org.apache.james.mime4j.dom.field.AddressListField alf =
1059                            (org.apache.james.mime4j.dom.field.AddressListField) f;
1060
1061                    final AddressListField field = new AddressListField();
1062                    field.setName(fldName);
1063
1064                    field.setValid(alf.isValidField());
1065                    if(!field.isValid()) {
1066                        org.apache.james.mime4j.dom.field.ParseException e = alf.getParseException();
1067                        if(e != null) {
1068                            field.addParseExceptionStackTrace(e);
1069                        }
1070                    }
1071
1072                    field.setEntity(entityStack.peek());
1073
1074                    log.debug("Mime Parse Event: ADDRESS LIST FIELD\n\n%s", new Supplier<Object[]>() {
1075                        @Override
1076                        public Object[] get() {
1077                            String domPath = field.dumpPath();
1078                            //System.out.println("ADDRESS LIST FIELD");
1079                            //System.out.println(domPath);
1080                            return new Object[] { domPath };
1081                        }
1082                    });
1083
1084                    for(org.apache.james.mime4j.dom.address.Address a : alf.getAddressList()) {
1085
1086                        if(a instanceof org.apache.james.mime4j.dom.address.Mailbox) {
1087
1088                            //**************************************************
1089                            //
1090                            //  address list field MAILBOX
1091                            //
1092                            //**************************************************
1093
1094                            org.apache.james.mime4j.dom.address.Mailbox m =
1095                                    (org.apache.james.mime4j.dom.address.Mailbox) a;
1096
1097                            final AddressListField_Mailbox mailbox = new AddressListField_Mailbox();
1098
1099                            String mname = m.getName();
1100                            if(mname != null) {
1101                                mname = decodeEncodedWords(mname);
1102                                mailbox.setName(mname);
1103                            }
1104
1105                            String localPart = m.getLocalPart();
1106                            if(localPart != null) {
1107                                mailbox.setLocalPart(localPart);
1108                            }
1109
1110                            String domain = m.getDomain();
1111                            if(domain != null) {
1112                                mailbox.setDomain(domain);
1113                            }
1114
1115                            org.apache.james.mime4j.dom.address.DomainList dl = m.getRoute();
1116                            if(dl.size() > 0) {
1117                                mailbox.setRoute(dl.toRouteString());
1118                            }
1119
1120                            mailbox.setField(field);
1121
1122                            if(parsingRoot && (mname != null)) {
1123                                if("to".equalsIgnoreCase(fldName)) {
1124                                    addAnalyzedIndexField("to", mname);
1125                                }
1126                                else if("cc".equalsIgnoreCase(fldName)) {
1127                                    addAnalyzedIndexField("cc", mname);
1128                                }
1129                                else if("bcc".equalsIgnoreCase(fldName)) {
1130                                    addAnalyzedIndexField("bcc", mname);
1131                                }
1132                            }
1133
1134                            if(parsingRoot && (localPart != null) && (domain != null)) {
1135                                String mbox = localPart + "@" + domain;
1136                                if("to".equalsIgnoreCase(fldName)) {
1137                                    addNotAnalyzedIndexField("to_mbox", mbox);
1138                                }
1139                                else if("cc".equalsIgnoreCase(fldName)) {
1140                                    addNotAnalyzedIndexField("cc_mbox", mbox);
1141                                }
1142                                else if("bcc".equalsIgnoreCase(fldName)) {
1143                                    addNotAnalyzedIndexField("bcc_mbox", mbox);
1144                                }
1145                            }
1146
1147                            log.debug("Mime Parse Event: ADDRESS LIST FIELD MAILBOX\n\n%s", new Supplier<Object[]>() {
1148                                @Override
1149                                public Object[] get() {
1150                                    String domPath = mailbox.dumpPath();
1151                                    //System.out.println("ADDRESS LIST FIELD MAILBOX");
1152                                    //System.out.println(domPath);
1153                                    return new Object[] { domPath };
1154                                }
1155                            });
1156                        }
1157                        else if(a instanceof org.apache.james.mime4j.dom.address.Group) {
1158
1159                            //**************************************************
1160                            //
1161                            //  address list field GROUP
1162                            //
1163                            //**************************************************
1164
1165                            org.apache.james.mime4j.dom.address.Group g =
1166                                    (org.apache.james.mime4j.dom.address.Group) a;
1167
1168                            final AddressListField_Group group = new AddressListField_Group();
1169
1170                            String gname = g.getName();
1171                            if(gname != null) {
1172                                gname = decodeEncodedWords(gname);
1173                                group.setName(gname);
1174                            }
1175
1176                            group.setField(field);
1177
1178                            if(parsingRoot && (gname != null)) {
1179                                if("to".equalsIgnoreCase(fldName)) {
1180                                    addAnalyzedIndexField("to", gname);
1181                                }
1182                                else if("cc".equalsIgnoreCase(fldName)) {
1183                                    addAnalyzedIndexField("cc", gname);
1184                                }
1185                                else if("bcc".equalsIgnoreCase(fldName)) {
1186                                    addAnalyzedIndexField("bcc", gname);
1187                                }
1188                            }
1189
1190                            log.debug("Mime Parse Event: GROUP\n\n%s", new Supplier<Object[]>() {
1191                                @Override
1192                                public Object[] get() {
1193                                    String domPath = group.dumpPath();
1194                                    //System.out.println("GROUP");
1195                                    //System.out.println(domPath);
1196                                    return new Object[] { domPath };
1197                                }
1198                            });
1199
1200                            for(org.apache.james.mime4j.dom.address.Mailbox m : g.getMailboxes()) {
1201
1202                                //**********************************************
1203                                //
1204                                //  address list field GROUP MAILBOX
1205                                //
1206                                //**********************************************
1207
1208                                final AddressListField_Group_Mailbox mailbox = new AddressListField_Group_Mailbox();
1209
1210                                String mname = m.getName();
1211                                if(mname != null) {
1212                                    mname = decodeEncodedWords(mname);
1213                                    mailbox.setName(mname);
1214                                }
1215
1216                                String localPart = m.getLocalPart();
1217                                if(localPart != null) {
1218                                    mailbox.setLocalPart(localPart);
1219                                }
1220
1221                                String domain = m.getDomain();
1222                                if(domain != null) {
1223                                    mailbox.setDomain(domain);
1224                                }
1225
1226                                org.apache.james.mime4j.dom.address.DomainList dl = m.getRoute();
1227                                if(dl.size() > 0) {
1228                                    mailbox.setRoute(dl.toRouteString());
1229                                }
1230
1231                                mailbox.setGroup(group);
1232
1233                                if(parsingRoot && (mname != null)) {
1234                                    if("to".equalsIgnoreCase(fldName)) {
1235                                        addAnalyzedIndexField("to", mname);
1236                                    }
1237                                    else if("cc".equalsIgnoreCase(fldName)) {
1238                                        addAnalyzedIndexField("cc", mname);
1239                                    }
1240                                    else if("bcc".equalsIgnoreCase(fldName)) {
1241                                        addAnalyzedIndexField("bcc", mname);
1242                                    }
1243                                }
1244
1245                                if(parsingRoot && (localPart != null) && (domain != null)) {
1246                                    String mbox = localPart + "@" + domain;
1247                                    if("to".equalsIgnoreCase(fldName)) {
1248                                        addNotAnalyzedIndexField("to_mbox", mbox);
1249                                    }
1250                                    else if("cc".equalsIgnoreCase(fldName)) {
1251                                        addNotAnalyzedIndexField("cc_mbox", mbox);
1252                                    }
1253                                    else if("bcc".equalsIgnoreCase(fldName)) {
1254                                        addNotAnalyzedIndexField("bcc_mbox", mbox);
1255                                    }
1256                                }
1257
1258                                log.debug("Mime Parse Event: GROUP MAILBOX\n\n%s", new Supplier<Object[]>() {
1259                                    @Override
1260                                    public Object[] get() {
1261                                        String domPath = mailbox.dumpPath();
1262                                        //System.out.println("GROUP MAILBOX");
1263                                        //System.out.println(domPath);
1264                                        return new Object[] { domPath };
1265                                    }
1266                                });
1267                            }
1268                        }
1269                    }
1270                }
1271                //</editor-fold>
1272
1273
1274                //<editor-fold defaultstate="collapsed" desc=" mailbox list field ">
1275                else if(f instanceof org.apache.james.mime4j.dom.field.MailboxListField) {
1276
1277                    //**********************************************************
1278                    //
1279                    //  MAILBOX LIST FIELD
1280                    //
1281                    //  "From", "Resent-From"
1282                    //
1283                    //**********************************************************
1284
1285                    org.apache.james.mime4j.dom.field.MailboxListField mlf =
1286                            (org.apache.james.mime4j.dom.field.MailboxListField) f;
1287
1288                    final MailboxListField field = new MailboxListField();
1289                    field.setName(fldName);
1290
1291                    field.setValid(mlf.isValidField());
1292                    if(!field.isValid()) {
1293                        org.apache.james.mime4j.dom.field.ParseException e = mlf.getParseException();
1294                        if(e != null) {
1295                            field.addParseExceptionStackTrace(e);
1296                        }
1297                    }
1298
1299                    field.setEntity(entityStack.peek());
1300
1301                    log.debug("Mime Parse Event: MAILBOX LIST FIELD\n\n%s", new Supplier<Object[]>() {
1302                        @Override
1303                        public Object[] get() {
1304                            String domPath = field.dumpPath();
1305                            //System.out.println("MAILBOX LIST FIELD");
1306                            //System.out.println(domPath);
1307                            return new Object[] { domPath };
1308                        }
1309                    });
1310
1311                    for(org.apache.james.mime4j.dom.address.Mailbox m : mlf.getMailboxList()) {
1312
1313                        //******************************************************
1314                        //
1315                        //  mailbox list field MAILBOX
1316                        //
1317                        //******************************************************
1318
1319                        final MailboxListField_Mailbox mailbox = new MailboxListField_Mailbox();
1320
1321                        String mname = m.getName();
1322                        if(mname != null) {
1323                            mname = decodeEncodedWords(mname);
1324                            mailbox.setName(mname);
1325                        }
1326
1327                        String localPart = m.getLocalPart();
1328                        if(localPart != null) {
1329                            mailbox.setLocalPart(localPart);
1330                        }
1331
1332                        String domain = m.getDomain();
1333                        if(domain != null) {
1334                            mailbox.setDomain(domain);
1335                        }
1336
1337                        org.apache.james.mime4j.dom.address.DomainList dl = m.getRoute();
1338                        if(dl.size() > 0) {
1339                            mailbox.setRoute(dl.toRouteString());
1340                        }
1341
1342                        mailbox.setField(field);
1343
1344                        if(parsingRoot && (mname != null)) {
1345                            if("from".equalsIgnoreCase(fldName)) {
1346                                addAnalyzedIndexField("from", mname);
1347                            }
1348                        }
1349
1350                        if(parsingRoot && (localPart != null) && (domain != null)) {
1351                            String mbox = localPart + "@" + domain;
1352                            if("from".equalsIgnoreCase(fldName)) {
1353                                addNotAnalyzedIndexField("from_mbox", mbox);
1354                            }
1355                        }
1356
1357                        log.debug("Mime Parse Event: MAILBOX LIST FIELD MAILBOX\n\n%s", new Supplier<Object[]>() {
1358                            @Override
1359                            public Object[] get() {
1360                                String domPath = mailbox.dumpPath();
1361                                //System.out.println("MAILBOX LIST FIELD MAILBOX");
1362                                //System.out.println(domPath);
1363                                return new Object[] { domPath };
1364                            }
1365                        });
1366                    }
1367                }
1368                //</editor-fold>
1369
1370
1371                //<editor-fold defaultstate="collapsed" desc=" mailbox field ">
1372                else if(f instanceof org.apache.james.mime4j.dom.field.MailboxField) {
1373
1374                    //**********************************************************
1375                    //
1376                    //  MAILBOX FIELD
1377                    //
1378                    //  "Sender", "Resent-Sender"
1379                    //
1380                    //**********************************************************
1381
1382                    org.apache.james.mime4j.dom.field.MailboxField mf =
1383                            (org.apache.james.mime4j.dom.field.MailboxField) f;
1384
1385                    final MailboxField field = new MailboxField();
1386                    field.setName(fldName);
1387
1388                    field.setValid(mf.isValidField());
1389                    if(!field.isValid()) {
1390                        org.apache.james.mime4j.dom.field.ParseException e = mf.getParseException();
1391                        if(e != null) {
1392                            field.addParseExceptionStackTrace(e);
1393                        }
1394                    }
1395
1396                    field.setEntity(entityStack.peek());
1397
1398                    log.debug("Mime Parse Event: MAILBOX FIELD\n\n%s", new Supplier<Object[]>() {
1399                        @Override
1400                        public Object[] get() {
1401                            String domPath = field.dumpPath();
1402                            //System.out.println("MAILBOX FIELD");
1403                            //System.out.println(domPath);
1404                            return new Object[] { domPath };
1405                        }
1406                    });
1407
1408                    //**********************************************************
1409                    //
1410                    //  mailbox field MAILBOX
1411                    //
1412                    //**********************************************************
1413
1414                    org.apache.james.mime4j.dom.address.Mailbox m = mf.getMailbox();
1415
1416                    final MailboxField_Mailbox mailbox = new MailboxField_Mailbox();
1417
1418                    String mname = m.getName();
1419                    if(mname != null) {
1420                        mname = decodeEncodedWords(mname);
1421                        mailbox.setName(mname);
1422                    }
1423
1424                    String localPart = m.getLocalPart();
1425                    if(localPart != null) {
1426                        mailbox.setLocalPart(localPart);
1427                    }
1428
1429                    String domain = m.getDomain();
1430                    if(domain != null) {
1431                        mailbox.setDomain(domain);
1432                    }
1433
1434                    org.apache.james.mime4j.dom.address.DomainList dl = m.getRoute();
1435                    if(dl.size() > 0) {
1436                        mailbox.setRoute(dl.toRouteString());
1437                    }
1438
1439                    mailbox.setField(field);
1440
1441                    if(parsingRoot && (mname != null)) {
1442                        if("sender".equalsIgnoreCase(fldName)) {
1443                            addAnalyzedIndexField("sender", mname);
1444                        }
1445                    }
1446
1447                    if(parsingRoot && (localPart != null) && (domain != null)) {
1448                        String mbox = localPart + "@" + domain;
1449                        if("sender".equalsIgnoreCase(fldName)) {
1450                            addNotAnalyzedIndexField("sender_mbox", mbox);
1451                        }
1452                    }
1453
1454                    log.debug("Mime Parse Event: MAILBOX FIELD MAILBOX\n\n%s", new Supplier<Object[]>() {
1455                        @Override
1456                        public Object[] get() {
1457                            String domPath = mailbox.dumpPath();
1458                            //System.out.println("MAILBOX FIELD MAILBOX");
1459                            //System.out.println(domPath);
1460                            return new Object[] { domPath };
1461                        }
1462                    });
1463                }
1464                //</editor-fold>
1465
1466            }
1467        }
1468
1469
1470        @Override
1471        public void body(BodyDescriptor bd, InputStream is) {
1472
1473            boolean isText = bd.getMediaType().equalsIgnoreCase("text");
1474
1475            final SingleBody singleBody = isText ? new TextBody() : new BinaryBody();
1476
1477            singleBody.setOid(UUID.randomUUID().toString());
1478
1479            singleBody.setEntity(entityStack.peek());
1480
1481            int size = 0;
1482            int capacity = 0x10000;
1483            byte[] textBuf = null;
1484
1485            if(isText) {
1486                textBuf = new byte[capacity];
1487            }
1488
1489            try {
1490                byte[] buf = new byte[0x1000];
1491                int n;
1492                while((n = is.read(buf)) >= 0) {
1493                    if(isText) {
1494                        if((size + n) >= capacity) {
1495                            capacity += 0x10000;
1496                            textBuf = Arrays.copyOf(textBuf, capacity);
1497                        }
1498                        System.arraycopy(buf, 0, textBuf, size, n);
1499                    }
1500                    size += n;
1501                }
1502            }
1503            catch(IOException ex) {
1504                log.error(ex);
1505            }
1506
1507            singleBody.setSize(size);
1508            singleBody.getEntity().incSize(size);
1509
1510            if(isText) {
1511                Charset cs = CharsetUtil.lookup(bd.getCharset());
1512                if(cs == null) {
1513                    cs = Charsets.Windows_1252;
1514                }
1515                String text = new String(textBuf, 0, size, cs);
1516
1517                //debug
1518                //System.out.println("--- text body ----");
1519                //System.out.println(text);
1520                //System.out.println("------------------");
1521
1522                String textExt;
1523
1524                if(bd.getSubType().equalsIgnoreCase("html")) {
1525                    Source html = new Source(text);
1526                    html.fullSequentialParse();
1527                    Element body = html.getFirstElement("body");
1528                    TextExtractor textExtractor = (body != null)
1529                            ? new TextExtractor(body)
1530                            : new TextExtractor(html);
1531                    textExt = textExtractor.toString();
1532                }
1533                else {
1534                    textExt = text.replaceAll("(" + CRLF + "|" + CR + "|" + LF + ")+", " ");
1535                }
1536
1537                String preview = textExt.substring(0, Math.min(textExt.length(), 300));
1538
1539                //debug
1540                //System.out.println("---- preview -----");
1541                //System.out.println(preview);
1542                //System.out.println("------------------");
1543
1544                ((TextBody)singleBody).setPreview(preview);
1545
1546                addAnalyzedIndexField("body", textExt);
1547            }
1548
1549            log.debug("Mime Parse Event: SINGLE BODY\n\n%s", new Supplier<Object[]>() {
1550                @Override
1551                public Object[] get() {
1552                    String domPath = singleBody.dumpPath();
1553                    //System.out.println("SINGLE BODY");
1554                    //System.out.println(domPath);
1555                    return new Object[] { domPath };
1556                }
1557            });
1558        }
1559
1560        @Override
1561        public void endBodyPart() {
1562
1563            final BodyPart bodyPart = (BodyPart) entityStack.pop();
1564
1565            log.debug("Mime Parse Event: END BODY PART\n\n%s", new Supplier<Object[]>() {
1566                @Override
1567                public Object[] get() {
1568                    String domPath = bodyPart.dumpPath();
1569                    //System.out.println("END BODY PART");
1570                    //System.out.println(domPath);
1571                    return new Object[] { domPath };
1572                }
1573            });
1574        }
1575
1576        @Override
1577        public void epilogue(InputStream is) {
1578
1579            Multipart multipart = multipartStack.peek();
1580            multipart.setEpilogueStream(is);
1581        }
1582
1583        @Override
1584        public void endMultipart() {
1585
1586            final Multipart multipart = multipartStack.pop();
1587
1588            log.debug("Mime Parse Event: END MULTIPART\n\n%s", new Supplier<Object[]>() {
1589                @Override
1590                public Object[] get() {
1591                    String domPath = multipart.dumpPath();
1592                    //System.out.println("END MULTIPART");
1593                    //System.out.println(domPath);
1594                    return new Object[] { domPath };
1595                }
1596            });
1597        }
1598
1599        @Override
1600        public void endMessage() {
1601
1602            final Entity entity = entityStack.pop();
1603
1604            if(entity instanceof EmbeddedMessage) {
1605                final EmbeddedMessage embeddedMessage = (EmbeddedMessage) entity;
1606
1607                log.debug("Mime Parse Event: END EMBEDDED MESSAGE\n\n%s", new Supplier<Object[]>() {
1608                    @Override
1609                    public Object[] get() {
1610                        String domPath = embeddedMessage.dumpPath();
1611                        //System.out.println("END EMBEDDED MESSAGE");
1612                        //System.out.println(domPath);
1613                        return new Object[] { domPath };
1614                    }
1615                });
1616            }
1617            else if(entity instanceof Message) {
1618                final Message message = (Message) entity;
1619
1620                log.debug("Mime Parse Event: END MESSAGE\n\n%s", new Supplier<Object[]>() {
1621                    @Override
1622                    public Object[] get() {
1623                        String domPath = message.dumpPath();
1624                        //System.out.println("END MESSAGE");
1625                        //System.out.println(domPath);
1626                        return new Object[] { domPath };
1627                    }
1628                });
1629            }
1630        }
1631    }
1632}
Note: See TracBrowser for help on using the repository browser.