2012-08-22 4 views
1

mbox 형식 전자 메일 메시지를 구문 분석하려고합니다.Tika에서 TNEFParser를 사용하지 못하도록

2012-08-21 17:44:42,139 FATAL org.apache.hadoop.mapred.Child: Error running child : java.lang.OutOfMemoryError: Java heap space 
    at org.apache.poi.hmef.attribute.TNEFAttribute.<init>(TNEFAttribute.java:50) 
    at org.apache.poi.hmef.attribute.TNEFAttribute.create(TNEFAttribute.java:76) 
    at org.apache.poi.hmef.HMEFMessage.process(HMEFMessage.java:74) 
    at org.apache.poi.hmef.HMEFMessage.process(HMEFMessage.java:98) 
    at org.apache.poi.hmef.HMEFMessage.process(HMEFMessage.java:98) 
    at org.apache.poi.hmef.HMEFMessage.<init>(HMEFMessage.java:63) 
    at org.apache.tika.parser.microsoft.TNEFParser.parse(TNEFParser.java:80) 
    at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242) 
    at org.apache.tika.parser.mail.MailContentHandler.body(MailContentHandler.java:102) 
    at org.apache.james.mime4j.parser.MimeStreamParser.parse(MimeStreamParser.java:133) 
    at org.apache.tika.parser.mail.RFC822Parser.parse(RFC822Parser.java:76) 
    at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242) 
    at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242) 
    at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:120) 
    at org.lab41.asf.etl.mapred.MailboxToTextMapper.parse(MailboxToTextMapper.java:124) 
    at org.lab41.asf.etl.mapred.MailboxToTextMapper.map(MailboxToTextMapper.java:88) 
    at org.lab41.asf.etl.mapred.MailboxToTextMapper.map(MailboxToTextMapper.java:45) 
    at org.apache.avro.mapred.HadoopMapper.map(HadoopMapper.java:81) 
    at org.apache.avro.mapred.HadoopMapper.map(HadoopMapper.java:34) 
    at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50) 
    at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:391) 
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:325) 
    at org.apache.hadoop.mapred.Child$4.run(Child.java:266) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Subject.java:396) 
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1278) 
    at org.apache.hadoop.mapred.Child.main(Child.java:260) 

는 TNEFParser를 사용 티카를 방지 할 수있다 : 그러나 티카 오류의 결과로 이러한 메시지에 TNEFParser를 사용하려고 계속? 어떤 제안이 도움이 될 것입니다.

답변

2

장기적으로 수정하려면 Apache Tika의 버그로보고하고 문제가있는 파일을 버그 보고서에 첨부 한 다음 프로젝트 작업을 통해 버그를 수정해야합니다.

단기간에 Tika-Parsers jar 파일의 압축을 풀고 META-INF/services/org.apache.tika.parser.Parser 파일을 편집하고 목록에서 TNEF 파서를 제거하십시오. AutoDetectParser에 의해 자동 로딩되고 사용되는 것을 막을 것입니다.

Tika Parsers jar 파일을 변경하지 않고 조금 까다 롭습니다. 사용할 수있는 두 가지 옵션이 있습니다. 하나는 기본 인스턴스를 사용하는 대신 TikaConfig 인스턴스를 직접 생성하고 제한된 파서 목록 만 제공하는 것입니다. 화이트리스트 또는 블랙리스트에 추가 할 것인지 여부에 따라 쉽지 않을 수도 있습니다. 또는 mimetype에 대해 마지막으로 등록 된 파서가 승리한다는 사실을 사용할 수도 있습니다. 따라서 서비스 파일과 자신의 더미 파서를 사용하여 자신 만의 jar 파일을 생성하십시오. 이 구문 분석기가 TNEF MIME 형식을 처리하지만 아무것도 수행하지 않는다고 선언하도록합니다. 클래스 패스에 항아리를 추가하면 더미 파서가 대신 사용됩니다.

+0

항아리 포장을 풀었습니다. –

2

@ Gagravarr에 의해 제안 된 프로그래밍 방식의 버전입니다. 등록 된 불필요한 파서를 EmptyParser으로 바꿉니다.

private Tika createTika(final Parser... unnecessaryParsers) 
     throws TikaException, IOException { 
    final TikaConfig config = new TikaConfig(); 
    final AutoDetectParser autoDetectParser = new AutoDetectParser(config); 

    final Set<MediaType> unnecessaryMimeTypes = 
     getUnnecessaryMediaTypes(unnecessaryParsers); 
    disableParsing(autoDetectParser, unnecessaryMimeTypes); 

    final Detector detector = config.getDetector(); 
    final Tika tika = new Tika(detector, autoDetectParser); 
    return tika; 
} 

private Set<MediaType> getUnnecessaryMediaTypes(
     final Parser... unnecessaryParsers) { 
    final Set<MediaType> unnecessaryTypes = new HashSet<MediaType>(); 
    for (final Parser unnecessaryParser: unnecessaryParsers) { 
     final Set<MediaType> supportedTypes = 
      unnecessaryParser.getSupportedTypes(null); 
     unnecessaryTypes.addAll(supportedTypes); 
    } 
    return unnecessaryTypes; 
} 

private void disableParsing(final CompositeParser mainParser, 
     final Set<MediaType> unnecessaryMediaTypes) { 
    final EmptyParser emptyParser = new EmptyParser(); 

    final Map<MediaType, Parser> parsers = mainParser.getParsers(); 
    for (final MediaType unnecessaryType: unnecessaryMediaTypes) { 
     parsers.put(unnecessaryType, emptyParser); 
    } 

    mainParser.setParsers(parsers); 
} 

사용법 :

final Parser unnecessaryParser = new MP4Parser(); 
final Tika tika = createTika(unnecessaryParser); 

또한 TIKA-1040: Could not delete temporary file를 방지하는 데 사용할 수 있습니다.

3

다음은 @Gagravarr에서 제안한 구성 버전입니다. (그것은 당신의 클래스 패스 어딘가에 가정)이 구성에서 TikaConfig을 만들 지금

<properties> 
    <parsers> 

    <!-- use the default parser in most cases, it is a composite of all 
     the parsers listed in META-INF/services/org.apache.tika.parser.Parser --> 
    <parser class="org.apache.tika.parser.DefaultParser"/> 

    <!-- Disable tnef extraction-->  
    <parser class="org.apache.tika.parser.EmptyParser"> 
     <mime>application/vnd.ms-tnef</mime> 
     <mime>application/x-tnef</mime> 
    </parser> 

    </parsers> 
</properties> 

:

Firsly가하는 티카-config.xml 파일을 만들

ClassLoader loader = Thread.currentThread().getContextClassLoader(); 
TikaConfig config = new TikaConfig(loader.getResource("tika-config.xml"), loader); 

을 때 당신은 creata 새 파서 또는 티카 파사드를 사용하여 구성을 전달하십시오.

AutoDetectParser parser = new AutoDetectParser(config); 
ParseContext context = new ParseContext(); 
context.set(Parser.class, parser); 
parser.parse(input, handler, metadata, context); 

TNEF는 내용을 반환하지 않고 실제로 아무것도 구문 분석하지 않는 EmptyParser를 사용합니다.

허용 목록이 필요하면 XML에서 DefaultParser를 제거하고 각 파서와 메타 데이터를 수동으로 구성해야합니다.

관련 문제