001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.search.extractors; 029 030import org.opencms.xml.CmsXmlEntityResolver; 031import org.opencms.xml.CmsXmlGenericWrapper; 032 033import java.io.InputStream; 034import java.util.Iterator; 035import java.util.List; 036import java.util.zip.ZipEntry; 037import java.util.zip.ZipInputStream; 038 039import org.dom4j.Document; 040import org.dom4j.Node; 041import org.dom4j.io.SAXReader; 042 043/** 044 * Extracts the text from OpenOffice documents (.ods, .odf).<p> 045 * 046 * @since 7.0.4 047 */ 048public final class CmsExtractorOpenOffice extends A_CmsTextExtractor { 049 050 /** Static member instance of the extractor. */ 051 private static final CmsExtractorOpenOffice INSTANCE = new CmsExtractorOpenOffice(); 052 053 /** 054 * Hide the public constructor.<p> 055 */ 056 private CmsExtractorOpenOffice() { 057 058 // noop 059 } 060 061 /** 062 * Returns an instance of this text extractor.<p> 063 * 064 * @return an instance of this text extractor 065 */ 066 public static I_CmsTextExtractor getExtractor() { 067 068 return INSTANCE; 069 } 070 071 /** 072 * @see org.opencms.search.extractors.A_CmsTextExtractor#extractText(java.io.InputStream, java.lang.String) 073 */ 074 @Override 075 public I_CmsExtractionResult extractText(InputStream in, String encoding) throws Exception { 076 077 try (ZipInputStream zin = new ZipInputStream(in)) { 078 ZipEntry ze; 079 boolean FOUND_CONTENT = false; 080 String result = ""; 081 while (!FOUND_CONTENT) { 082 ze = zin.getNextEntry(); 083 FOUND_CONTENT = ze.getName().equalsIgnoreCase("content.xml"); 084 if (FOUND_CONTENT) { 085 result = readContent(zin); 086 } 087 } 088 result = removeControlChars(result); 089 return new CmsExtractionResult(result); 090 } 091 } 092 093 /** 094 * Internal routine that parses the specific content.xml part of 095 * an odf document.<p> 096 * 097 * @param in the input stream spooled to the start of the content.xml part 098 * 099 * @return the extracted content 100 * 101 * @throws Exception if sth goes wrong 102 */ 103 private String readContent(java.io.InputStream in) throws Exception { 104 105 StringBuffer resultBuffer = new StringBuffer(); 106 SAXReader reader = new SAXReader(); 107 reader.setEntityResolver(new CmsXmlEntityResolver(null)); 108 Document doc = reader.read(in); 109 List<Node> textlist = CmsXmlGenericWrapper.selectNodes(doc, "//text:p[@*] | //text:span[@*]"); 110 Iterator<Node> li = textlist.iterator(); 111 while (li.hasNext()) { 112 Node textNode = li.next(); 113 String text = textNode.getText(); 114 if (text.length() > 1) { 115 text = " " + text + " "; 116 resultBuffer.append(text); 117 } 118 } 119 return resultBuffer.toString(); 120 } 121 122}