/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/jdomobjects/SAXParserPool.java,v 1.3 2004/07/30 06:52:00 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:00 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed 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.slide.store.tamino.jdomobjects;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.xml.parsers.SAXParserFactory;
import org.apache.slide.util.XException;
import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Pools SAXParsers for reusage. Parsers retrieved from this pool use a
 * dummy entity resolver (entities are not resolved), an error handler that
 * ignores parse errors and validating is switched off.
 *
 * ATTENTION! if a user changes any state of the parser (except default handler),
 * he is responsible to clean up again, else the next user of this parser may have
 * funny results.
 *
 * @author martin.wallmer@softwareag.com
 *
 * @version $Revision: 1.3 $
 */
public class SAXParserPool
{
    
    private static List pool = Collections.synchronizedList (new ArrayList());
    
    private static int getParser;
    private static int createParser;
    
    private static SAXParserFactory factory = SAXParserFactory.newInstance();
    private static Object monitor = new Object();
    
    /**
     * retrieves a non validating parser with a non resolving entity resolver.
     * If a parser is in pool, takes one of the pool, else a new one is created.
     *
     * @param    handler             a  DefaultHandler
     *
     * @return   a SAXParser
     *
     * @throws   XException
     *
     */
    public static SAXParser getParser(DefaultHandler handler) throws XException {
        
        try {
            SAXParser parser;
            getParser++;
            if (pool.size() > 0) {
                parser = (SAXParser) pool.remove(0);
            }
            else {
                createParser++;
                parser = createParser();
            }
            parser.setContentHandler (handler);
            
            return parser;
        }
        catch (SAXException e) {
            throw new XException (e);
        }
    }
    
    /**
     * gives parser back to pool.
     *
     * @param    parser              a  SAXParser
     *
     */
    public static void returnParser (SAXParser parser) {
        pool.add (parser);
    }
    
    /**
     * Method createParser
     *
     * @return   a SAXParser
     *
     * @throws   SAXException
     *
     */
    private static SAXParser createParser () throws SAXException {
        
        SAXParser parser;
        
        synchronized (monitor) {
            
            parser = new SAXParser();
            parser.setEntityResolver (new MyResolver());
            parser.setErrorHandler (new DummyErrorHandler());
            parser.setFeature("http://xml.org/sax/features/validation", false);
        }
        return parser;
        
    }
}

/**
 * dummy resolver
 */
class MyResolver implements EntityResolver {
    public InputSource resolveEntity (String publicId, String systemId) {
        return new InputSource(new StringReader (""));
    }
}

class DummyErrorHandler implements ErrorHandler {
    
    
    /**
     * Receive notification of a warning.
     *
     * <p>SAX parsers will use this method to report conditions that
     * are not errors or fatal errors as defined by the XML 1.0
     * recommendation.  The default behaviour is to take no action.</p>
     *
     * <p>The SAX parser must continue to provide normal parsing events
     * after invoking this method: it should still be possible for the
     * application to process the document through to the end.</p>
     *
     * <p>Filters may use this method to report other, non-XML warnings
     * as well.</p>
     *
     * @param exception The warning information encapsulated in a
     *                  SAX parse exception.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see org.xml.sax.SAXParseException
     */
    public void warning(SAXParseException exception) throws SAXException
    {
        // System.out.println("warning: " + exception.getMessage());
    }
    
    /**
     * Receive notification of a recoverable error.
     *
     * <p>This corresponds to the definition of "error" in section 1.2
     * of the W3C XML 1.0 Recommendation.  For example, a validating
     * parser would use this callback to report the violation of a
     * validity constraint.  The default behaviour is to take no
     * action.</p>
     *
     * <p>The SAX parser must continue to provide normal parsing events
     * after invoking this method: it should still be possible for the
     * application to process the document through to the end.  If the
     * application cannot do so, then the parser should report a fatal
     * error even if the XML 1.0 recommendation does not require it to
     * do so.</p>
     *
     * <p>Filters may use this method to report other, non-XML errors
     * as well.</p>
     *
     * @param exception The error information encapsulated in a
     *                  SAX parse exception.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see org.xml.sax.SAXParseException
     */
    public void error(SAXParseException exception) throws SAXException
    {
        // System.out.println("error: " + exception.getMessage());
    }
    
    /**
     * Receive notification of a non-recoverable error.
     *
     * <p>This corresponds to the definition of "fatal error" in
     * section 1.2 of the W3C XML 1.0 Recommendation.  For example, a
     * parser would use this callback to report the violation of a
     * well-formedness constraint.</p>
     *
     * <p>The application must assume that the document is unusable
     * after the parser has invoked this method, and should continue
     * (if at all) only for the sake of collecting addition error
     * messages: in fact, SAX parsers are free to stop reporting any
     * other events once this method has been invoked.</p>
     *
     * @param exception The error information encapsulated in a
     *                  SAX parse exception.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see org.xml.sax.SAXParseException
     */
    public void fatalError(SAXParseException exception) throws SAXException
    {
         // System.out.println("fatal: " + exception.getMessage());
    }
    
}



