001/*
002 *  Copyright 2016 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.core.util;
017
018import java.io.IOException;
019import java.io.InputStream;
020
021import org.apache.avalon.framework.component.Component;
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.avalon.framework.service.Serviceable;
025import org.apache.excalibur.xml.sax.SAXParser;
026import org.slf4j.Logger;
027import org.xml.sax.Attributes;
028import org.xml.sax.ContentHandler;
029import org.xml.sax.InputSource;
030import org.xml.sax.SAXException;
031import org.xml.sax.helpers.DefaultHandler;
032
033import org.ametys.runtime.i18n.I18nizable;
034import org.ametys.runtime.plugin.component.LogEnabled;
035
036/**
037 * Component with XML utils methods
038 */
039public class XMLUtils extends org.apache.cocoon.xml.XMLUtils implements Component, Serviceable, LogEnabled
040{
041    /** The avalon role */
042    public static final String ROLE = XMLUtils.class.getName();
043
044    /** Avalon service manager */
045    protected ServiceManager _manager;
046    
047    private Logger _logger;
048    
049    public void service(ServiceManager manager) throws ServiceException
050    {
051        _manager = manager;
052    }
053    
054    /**
055     * Returns the {@link Logger}.
056     * @return the {@link Logger}.
057     */
058    protected Logger getLogger()
059    {
060        return _logger;
061    }
062
063    public void setLogger(Logger logger)
064    {
065        _logger = logger;
066    }
067    
068    /**
069     * Create a start and endElement with a empty Namespace and without Attributes with the given {@link I18nizable}
070     * If the {@link I18nizable} is <code>null</code>, the element is not created
071     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
072     * @param localName The local name (without prefix)
073     * @param i18n the {@link I18nizable} to SAX
074     * @throws SAXException if an error occurs during the SAX events generation
075     */
076    public static void createI18nElementIfNotNull(ContentHandler contentHandler, String localName, I18nizable i18n) throws SAXException
077    {
078        if (i18n != null)
079        {
080            i18n.toSAX(contentHandler, localName);
081        }
082    }
083    
084    /**
085     * Create a start and endElement with a empty Namespace and without Attributes
086     * If the string value is <code>null</code>, the element is not created
087     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
088     * @param localName The local name (without prefix)
089     * @param stringValue The content of the Element
090     * @throws SAXException if an error occurs during the SAX events generation
091     */
092    public static void createElementIfNotNull(ContentHandler contentHandler, String localName, String stringValue) throws SAXException
093    {
094        if (stringValue != null)
095        {
096            createElement(contentHandler, localName, stringValue);
097        }
098    }
099    
100    /**
101     * Create a start and endElement with a empty Namespace and without Attributes
102     * If the string value is <code>null</code>, the element is not created
103     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
104     * @param localName The local name (without prefix)
105     * @param stringValue The content of the Element
106     * @param attributes The attributes attached to the element.  If there are no attributes, it shall be an empty Attributes object.
107     * @throws SAXException if an error occurs during the SAX events generation
108     */
109    public static void createElementIfNotNull(ContentHandler contentHandler, String localName, String stringValue, Attributes attributes) throws SAXException
110    {
111        if (stringValue != null)
112        {
113            createElement(contentHandler, localName, attributes, stringValue);
114        }
115    }
116
117    /**
118     * Get a XML as a string and extract the text only
119     * @param is The inputstream of XML
120     * @return The text or null if the XML is not well formed
121     */
122    public String toString(InputStream is)
123    {
124        SAXParser saxParser = null;
125        try
126        {
127            TxtHandler txtHandler = new TxtHandler();
128            saxParser = (SAXParser) _manager.lookup(SAXParser.ROLE);
129            saxParser.parse(new InputSource(is), txtHandler);
130            return txtHandler.getValue();
131        }
132        catch (ServiceException e)
133        {
134            getLogger().error("Unable to get a SAX parser", e);
135            return null;
136        }
137        catch (IOException | SAXException e)
138        {
139            getLogger().error("Cannot parse inputstream", e);
140            return null;
141        }
142        finally
143        {
144            _manager.release(saxParser);
145        }
146    }
147    
148    final class TxtHandler extends DefaultHandler
149    {
150        private StringBuilder _internal = new StringBuilder();
151        
152        @Override
153        public void characters(char[] ch, int start, int length) throws SAXException
154        {
155            _internal.append(new String(ch, start, length));
156        }
157        
158        public String getValue()
159        {
160            return _internal.toString();
161        }
162    }
163}