dev@jax-ws.java.net

Re: XMLStreamReader recycling <was> [Fwd: CVS update [mr-21]: /jax-ws-sources/jaxws-ri/rt/src/com/sun/xml/ws/message/stream/]

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 18 Jan 2007 11:34:59 +0100

Oleksiy Stashok wrote:
> Hi Paul,
>
> here I reimplemented XMLStreamReaderFactory, taking in account the ideas
> you had.
> I think code become more difficult. But may be less hacky.

I think it has become more unified. Instead of doing two different type
of things it is mostly doing one type of thing.

You can almost remove all references to the Zephyr XMLStreamReader in
the Zephyr class by reusing the register method in the Zephyr
constructor. The doCreate with no class uses the first one registered.

Unfortunately the reuse code is still Zephyr specific :-( We are running
up against XMLStreamReader iface limitations.

Ideally we should refactor the XMLStreamReaderFactory so that it can be
sensibly used by the FI codec rather than it using a partial impl of
XMLInputFactory. Then have a specialization of XMLStreamReaderFactory
that supports multiple implementations.

At least we should document something along those line to fix after HCF.

Paul.

> Any suggestions?
>
> Thank you.
>
> WBR,
> Alexey.
>
> Paul Sandoz wrote:
>> Oleksiy Stashok wrote:
>>> Hi.
>>>
>>> Can you pls. review XMLStreamReaderFactory I'm proposing. I made
>>> changes to reuse it for FastInfoset's XMLStreamReader.
>>> Actually for now I made Zephyr's factory implementation to be able to
>>> work as common pool for all possible implementation of
>>> XMLStreamReader. In this case seems name could be changed...
>>>
>>
>> Looks OK. I think you need some JavaDoc.
>>
>> Some notes:
>>
>> 1) I do not see the need for two pools; (i almost thought there is no
>> need for a Map since if the requested class is different it could
>> replace that which is already there, but that could lead to trouble!).
>>
>> 2) The doCreate method you created will likely fail for a Zephyr
>> instance but pass for an FI instance.
>>
>> 3) As you indicate the Zephyr class no longer fully reflects it's name
>> :-( it is tricky because there is a mix of stuff going on, but i
>> cannot think of something better.
>>
>>
>> I am wondering if we can resolve this better by using a special
>> XMLInputFactory implementation associated with the FI codec (note that
>> there is an impl with FI but this contains a whole bunch of other
>> stuff and is included with Mustang, for reasons of reducing the JRE
>> size). Then we can register that with the appropriate reader class to
>> the stream reader factory.
>>
>> That way we could have:
>>
>> doCreate(String systemId, InputStream in, boolean rejectDTDs, Class<?
>> extends XMLStreamReader> c)
>>
>> and
>>
>> doCreate(String systemId, InputStream in, boolean rejectDTDs)
>>
>> would default to something meaningful i.e. using Zephyr because it is
>> configured that way.
>>
>> Paul.
>>
>>> WBR,
>>> Alexey.
>>>
>>>
>>> Paul Sandoz wrote:
>>>> Kohsuke Kawaguchi wrote:
>>>>> Paul Sandoz wrote:
>>>>>> This recycling is related to the same issue for the FI StAX parsers.
>>>>>>
>>>>>> I have not looked deeply at the code but it looks like the right
>>>>>> place to support the recycling of XML *and* FI XMLStreamReader
>>>>>> instances.
>>>>>
>>>>> Yeah, we can do that. The easiet way is to have FI's
>>>>> XMLStreamReader implement RecycleAware. If needed we can move this
>>>>> interface on stax-ex
>>>>> to do this.
>>>>>
>>>>
>>>> A FI XMLStreamReader instance automatically resets itself when an
>>>> InputStream is set so it is not strictly necessary to implement this
>>>> interface.
>>>>
>>>>
>>>>>> I am wondering if it is possible to also recycle stream buffers
>>>>>> i.e. when the message is no longer used.
>>>>>
>>>>> I think we should first check if it's indeed costly.
>>>>
>>>> Agreed, profiling for cases where non-security header blocks are
>>>> present should tell is more.
>>>>
>>>> The reason i have a hunch is the fact that XML StAX parser creation
>>>> showed up in the profiler mainly because it created a whole bunch of
>>>> memory that could be reused. The same will happen with the
>>>> streambuffer for headers.
>>>>
>>>> Paul.
>>>>
>>>>> So far, it doesn't seem like this is a big enough problem. Pooling
>>>>> has its own overhead and problems, too.
>>>>>
>>>>> Finding out when a Message is no longer in use is harder than
>>>>> finding that out for XMLStreamReader, so doing this is more work.
>>>>> We need benefits that justify this work.
>>>>>
>>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> package com.sun.xml.ws.api.streaming;
>>>
>>> import com.sun.istack.NotNull;
>>> import com.sun.istack.Nullable;
>>> import com.sun.xml.ws.streaming.XMLReaderException;
>>> import java.util.HashMap;
>>> import java.util.Map;
>>> import org.xml.sax.InputSource;
>>>
>>> import javax.xml.stream.XMLInputFactory;
>>> import javax.xml.stream.XMLStreamException;
>>> import javax.xml.stream.XMLStreamReader;
>>> import java.io.IOException;
>>> import java.io.InputStream;
>>> import java.io.Reader;
>>> import java.io.StringReader;
>>> import java.lang.reflect.InvocationTargetException;
>>> import java.lang.reflect.Method;
>>> import java.net.URL;
>>>
>>> /**
>>> * Factory for {_at_link XMLStreamReader}.
>>> *
>>> * <p>
>>> * This wraps {_at_link XMLInputFactory} and allows us to reuse {_at_link
>>> XMLStreamReader} instances
>>> * when appropriate.
>>> *
>>> * @author Kohsuke Kawaguchi
>>> */
>>> public abstract class XMLStreamReaderFactory {
>>> /**
>>> * Singleton instance.
>>> */
>>> private static volatile @NotNull XMLStreamReaderFactory theInstance;
>>> static {
>>> XMLInputFactory xif = XMLInputFactory.newInstance();
>>> xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
>>> XMLStreamReaderFactory f=null;
>>> // this system property can be used to disable the
>>> pooling altogether,
>>> // in case someone hits an issue with pooling in the
>>> production system.
>>>
>>> if(!Boolean.getBoolean(XMLStreamReaderFactory.class.getName()+".noPool"))
>>>
>>> f = Zephyr.newInstance(xif);
>>> if(f==null)
>>> f = new Default(xif);
>>> theInstance = f;
>>> }
>>> /**
>>> * Overrides the singleton {_at_link XMLStreamReaderFactory}
>>> instance that
>>> * the JAX-WS RI uses.
>>> */
>>> public static void set(XMLStreamReaderFactory f) {
>>> if(f==null) throw new IllegalArgumentException();
>>> theInstance = f;
>>> }
>>> public static XMLStreamReaderFactory get() {
>>> return theInstance;
>>> }
>>> public static XMLStreamReader create(InputSource source,
>>> boolean rejectDTDs) {
>>> try {
>>> // Char stream available?
>>> if (source.getCharacterStream() != null) {
>>> return get().doCreate(source.getSystemId(),
>>> source.getCharacterStream(), rejectDTDs);
>>> }
>>> // Byte stream available?
>>> if (source.getByteStream() != null) {
>>> return get().doCreate(source.getSystemId(),
>>> source.getByteStream(), rejectDTDs);
>>> }
>>> // Otherwise, open URI
>>> return get().doCreate(source.getSystemId(), new
>>> URL(source.getSystemId()).openStream(),rejectDTDs);
>>> } catch (IOException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> }
>>> }
>>> public static XMLStreamReader create(@Nullable String
>>> systemId, InputStream in, boolean rejectDTDs) {
>>> return get().doCreate(systemId,in,rejectDTDs);
>>> }
>>> public static XMLStreamReader create(@Nullable String
>>> systemId, Reader reader, boolean rejectDTDs) {
>>> return get().doCreate(systemId,reader,rejectDTDs);
>>> }
>>> /**
>>> * Should be invoked when the code finished using an {_at_link
>>> XMLStreamReader}.
>>> *
>>> * <p>
>>> * If the recycled instance implements {_at_link RecycleAware},
>>> * {_at_link RecycleAware#onRecycled()} will be invoked to let the
>>> instance
>>> * know that it's being recycled.
>>> *
>>> * <p>
>>> * It is not a hard requirement to call this method on every
>>> {_at_link XMLStreamReader}
>>> * instance. Not doing so just reduces the performance by
>>> throwing away
>>> * possibly reusable instances. So the caller should always
>>> consider the effort
>>> * it takes to recycle vs the possible performance gain by doing so.
>>> *
>>> * <p>
>>> * This method may be invked by multiple threads concurrently.
>>> *
>>> * @param r
>>> * The {_at_link XMLStreamReader} instance that the caller
>>> finished using.
>>> * This could be any {_at_link XMLStreamReader} implementation,
>>> not just
>>> * the ones that were created from this factory. So the
>>> implementation
>>> * of this class needs to be aware of that.
>>> */
>>> public static void recycle(XMLStreamReader r) {
>>> get().doRecycle(r);
>>> }
>>> // implementations
>>> public abstract XMLStreamReader doCreate(String systemId,
>>> InputStream in, boolean rejectDTDs);
>>> public abstract XMLStreamReader doCreate(String systemId,
>>> Reader reader, boolean rejectDTDs);
>>> public abstract XMLStreamReader doCreate(Class<? extends
>>> XMLStreamReader> implClass);
>>> public abstract void doRecycle(XMLStreamReader r);
>>> /**
>>> * Interface that can be implemented by {_at_link XMLStreamReader} to
>>> * be notified when it's recycled.
>>> *
>>> * <p>
>>> * This provides a filtering {_at_link XMLStreamReader} an
>>> opportunity to
>>> * recycle its inner {_at_link XMLStreamReader}.
>>> */
>>> public interface RecycleAware {
>>> void onRecycled();
>>> }
>>> /**
>>> * {_at_link XMLStreamReaderFactory} implementation for SJSXP/JAXP RI.
>>> */
>>> public static final class Zephyr extends XMLStreamReaderFactory {
>>> private final XMLInputFactory xif;
>>> private final ThreadLocal<XMLStreamReader> pool = new
>>> ThreadLocal<XMLStreamReader>();
>>> private final ThreadLocal<Map<Class,
>>> XMLStreamReader>> customPool = new ThreadLocal<Map<Class,
>>> XMLStreamReader>>();
>>> /**
>>> * Sun StAX impl <code>XMLReaderImpl.setInputSource()</code>
>>> method via reflection.
>>> */
>>> private final Method setInputSourceMethod;
>>> /**
>>> * Sun StAX impl <code>XMLReaderImpl.reset()</code> method
>>> via reflection.
>>> */
>>> private final Method resetMethod;
>>> /**
>>> * The Sun StAX impl's {_at_link XMLStreamReader} implementation
>>> clas.
>>> */
>>> private final Class zephyrClass;
>>> /**
>>> * Creates {_at_link Zephyr} instance if the given {_at_link
>>> XMLInputFactory} is the one
>>> * from Zephyr.
>>> */
>>> public static @Nullable
>>> XMLStreamReaderFactory newInstance(XMLInputFactory
>>> xif) {
>>> // check if this is from Zephyr
>>> try {
>>> Class<?> clazz = xif.createXMLStreamReader(new
>>> StringReader("<foo/>")).getClass();
>>>
>>> if(!clazz.getName().startsWith("com.sun.xml.stream."))
>>> return null; // nope
>>> return new Zephyr(xif,clazz);
>>> } catch (NoSuchMethodException e) {
>>> return null; // this factory is not for zephyr
>>> } catch (XMLStreamException e) {
>>> return null; // impossible to fail to parse
>>> <foo/>, but anyway
>>> }
>>> }
>>> public Zephyr(XMLInputFactory xif, Class clazz)
>>> throws NoSuchMethodException {
>>> zephyrClass = clazz;
>>> setInputSourceMethod = clazz.getMethod("setInputSource",
>>> InputSource.class);
>>> resetMethod = clazz.getMethod("reset");
>>> try {
>>> // Turn OFF internal factory caching in Zephyr.
>>> // Santiago told me that this makes it thread-safe.
>>> xif.setProperty("reuse-instance", false);
>>> } catch (IllegalArgumentException e) {
>>> // falls through
>>> }
>>> this.xif = xif;
>>> }
>>> /**
>>> * Fetchs an instance from the pool if available, otherwise
>>> null.
>>> */
>>> private @Nullable XMLStreamReader fetch() {
>>> XMLStreamReader sr = pool.get();
>>> if(sr==null) return null;
>>> pool.set(null);
>>> return sr;
>>> }
>>> private @Nullable XMLStreamReader fetch(Class
>>> implClass) {
>>> if (zephyrClass.equals(implClass)) return fetch();
>>> Map<Class, XMLStreamReader> implMap =
>>> getCustomPoolImplMap();
>>> XMLStreamReader sr = implMap.get(implClass);
>>> if(sr==null) return null;
>>> implMap.put(implClass, null);
>>> return sr;
>>> }
>>> public void doRecycle(XMLStreamReader r) {
>>> if(zephyrClass.isInstance(r)) {
>>> pool.set(r);
>>> } else {
>>> offerToCustomPool(r);
>>> }
>>> if(r instanceof RecycleAware)
>>> ((RecycleAware)r).onRecycled();
>>> }
>>> public XMLStreamReader doCreate(String systemId,
>>> InputStream in, boolean rejectDTDs) {
>>> try {
>>> XMLStreamReader xsr = fetch();
>>> if(xsr==null)
>>> return xif.createXMLStreamReader(systemId,in);
>>> // try re-using this instance.
>>> InputSource is = new InputSource(systemId);
>>> is.setByteStream(in);
>>> reuse(xsr,is);
>>> return xsr;
>>> } catch (IllegalAccessException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> } catch (InvocationTargetException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> } catch (XMLStreamException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> }
>>> }
>>> public XMLStreamReader doCreate(String systemId,
>>> Reader in, boolean rejectDTDs) {
>>> try {
>>> XMLStreamReader xsr = fetch();
>>> if(xsr==null)
>>> return xif.createXMLStreamReader(systemId,in);
>>> // try re-using this instance.
>>> InputSource is = new InputSource(systemId);
>>> is.setCharacterStream(in);
>>> reuse(xsr,is);
>>> return xsr;
>>> } catch (IllegalAccessException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> } catch (InvocationTargetException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> } catch (XMLStreamException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> }
>>> }
>>> public XMLStreamReader doCreate(Class<? extends
>>> XMLStreamReader> implClass) {
>>> XMLStreamReader xsr = fetch(implClass);
>>> if(xsr != null) {
>>> return xsr;
>>> }
>>>
>>> try {
>>> return implClass.newInstance();
>>> } catch (IllegalAccessException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> } catch (InstantiationException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> }
>>> }
>>> private void offerToCustomPool(XMLStreamReader xsr) {
>>> Map<Class, XMLStreamReader> implMap =
>>> getCustomPoolImplMap();
>>> implMap.put(xsr.getClass(), xsr);
>>> }
>>> private Map<Class, XMLStreamReader>
>>> getCustomPoolImplMap() {
>>> Map<Class, XMLStreamReader> implMap = customPool.get();
>>> if (implMap == null) {
>>> implMap = new HashMap<Class, XMLStreamReader>(2);
>>> customPool.set(implMap);
>>> }
>>> return implMap;
>>> }
>>> private void reuse(XMLStreamReader xsr, InputSource
>>> in) throws IllegalAccessException, InvocationTargetException {
>>> resetMethod.invoke(xsr);
>>> setInputSourceMethod.invoke(xsr,in);
>>> }
>>> }
>>> /**
>>> * Default {_at_link XMLStreamReaderFactory} implementation
>>> * that can work with any {_at_link XMLInputFactory}.
>>> *
>>> * <p>
>>> * {_at_link XMLInputFactory} is not required to be thread-safe, so the
>>> * create method on this implementation is synchronized.
>>> */
>>> public static final class Default extends NoLock {
>>> public Default(XMLInputFactory xif) {
>>> super(xif);
>>> }
>>> public synchronized XMLStreamReader doCreate(String
>>> systemId, InputStream in, boolean rejectDTDs) {
>>> return super.doCreate(systemId, in, rejectDTDs);
>>> }
>>> public synchronized XMLStreamReader doCreate(String
>>> systemId, Reader in, boolean rejectDTDs) {
>>> return super.doCreate(systemId, in, rejectDTDs);
>>> }
>>> public synchronized XMLStreamReader doCreate(Class<?
>>> extends XMLStreamReader> implClass) {
>>> return super.doCreate(implClass);
>>> }
>>> }
>>> /**
>>> * Similar to {_at_link Default} but doesn't do any synchronization.
>>> *
>>> * <p>
>>> * This is useful when you know your {_at_link XMLInputFactory} is
>>> thread-safe by itself.
>>> */
>>> public static class NoLock extends XMLStreamReaderFactory {
>>> private final XMLInputFactory xif;
>>> public NoLock(XMLInputFactory xif) {
>>> this.xif = xif;
>>> }
>>> public XMLStreamReader doCreate(String systemId,
>>> InputStream in, boolean rejectDTDs) {
>>> try {
>>> return xif.createXMLStreamReader(systemId,in);
>>> } catch (XMLStreamException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> }
>>> }
>>> public XMLStreamReader doCreate(String systemId,
>>> Reader in, boolean rejectDTDs) {
>>> try {
>>> return xif.createXMLStreamReader(systemId,in);
>>> } catch (XMLStreamException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> }
>>> }
>>> public XMLStreamReader doCreate(Class<? extends
>>> XMLStreamReader> implClass) {
>>> try {
>>> return implClass.newInstance();
>>> } catch (IllegalAccessException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> } catch (InstantiationException e) {
>>> throw new XMLReaderException("stax.cantCreate",e);
>>> }
>>> }
>>> public void doRecycle(XMLStreamReader r) {
>>> // there's no way to recycle with the default StAX API.
>>> }
>>> }
>>> }
>>>
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe_at_jax-ws.dev.java.net
>>> For additional commands, e-mail: dev-help_at_jax-ws.dev.java.net
>>
>
> ------------------------------------------------------------------------
>
> package com.sun.xml.ws.api.streaming;
>
> import com.sun.istack.NotNull;
> import com.sun.istack.Nullable;
> import com.sun.xml.ws.streaming.XMLReaderException;
> import java.util.HashMap;
> import java.util.Map;
> import org.xml.sax.InputSource;
>
> import javax.xml.stream.XMLInputFactory;
> import javax.xml.stream.XMLStreamException;
> import javax.xml.stream.XMLStreamReader;
> import java.io.IOException;
> import java.io.InputStream;
> import java.io.Reader;
> import java.io.StringReader;
> import java.lang.reflect.InvocationTargetException;
> import java.lang.reflect.Method;
> import java.net.URL;
>
> /**
> * Factory for {_at_link XMLStreamReader}.
> *
> * <p>
> * This wraps {_at_link XMLInputFactory} and allows us to reuse {_at_link XMLStreamReader} instances
> * when appropriate.
> *
> * @author Kohsuke Kawaguchi
> */
> public abstract class XMLStreamReaderFactory {
>
> /**
> * Singleton instance.
> */
> private static volatile @NotNull XMLStreamReaderFactory theInstance;
>
> static {
> XMLInputFactory xif = XMLInputFactory.newInstance();
> xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
>
> XMLStreamReaderFactory f=null;
>
> // this system property can be used to disable the pooling altogether,
> // in case someone hits an issue with pooling in the production system.
> if(!Boolean.getBoolean(XMLStreamReaderFactory.class.getName()+".noPool"))
> f = Zephyr.newInstance(xif);
> if(f==null)
> f = Default.newInstance(xif);
>
> theInstance = f;
> }
>
> /**
> * Overrides the singleton {_at_link XMLStreamReaderFactory} instance that
> * the JAX-WS RI uses.
> */
> public static void set(XMLStreamReaderFactory f) {
> if(f==null) throw new IllegalArgumentException();
> theInstance = f;
> }
>
> public static XMLStreamReaderFactory get() {
> return theInstance;
> }
>
> public static XMLStreamReader create(InputSource source, boolean rejectDTDs) {
> try {
> // Char stream available?
> if (source.getCharacterStream() != null) {
> return get().doCreate(source.getSystemId(), source.getCharacterStream(), rejectDTDs);
> }
>
> // Byte stream available?
> if (source.getByteStream() != null) {
> return get().doCreate(source.getSystemId(), source.getByteStream(), rejectDTDs);
> }
>
> // Otherwise, open URI
> return get().doCreate(source.getSystemId(), new URL(source.getSystemId()).openStream(),rejectDTDs);
> } catch (IOException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> }
> }
>
> public static XMLStreamReader create(@Nullable String systemId, InputStream in, boolean rejectDTDs) {
> return get().doCreate(systemId,in,rejectDTDs);
> }
>
> public static XMLStreamReader create(@Nullable String systemId, Reader reader, boolean rejectDTDs) {
> return get().doCreate(systemId,reader,rejectDTDs);
> }
>
> /**
> * Should be invoked when the code finished using an {_at_link XMLStreamReader}.
> *
> * <p>
> * If the recycled instance implements {_at_link RecycleAware},
> * {_at_link RecycleAware#onRecycled()} will be invoked to let the instance
> * know that it's being recycled.
> *
> * <p>
> * It is not a hard requirement to call this method on every {_at_link XMLStreamReader}
> * instance. Not doing so just reduces the performance by throwing away
> * possibly reusable instances. So the caller should always consider the effort
> * it takes to recycle vs the possible performance gain by doing so.
> *
> * <p>
> * This method may be invked by multiple threads concurrently.
> *
> * @param r
> * The {_at_link XMLStreamReader} instance that the caller finished using.
> * This could be any {_at_link XMLStreamReader} implementation, not just
> * the ones that were created from this factory. So the implementation
> * of this class needs to be aware of that.
> */
> public static void recycle(XMLStreamReader r) {
> get().doRecycle(r);
> }
>
> // implementations
>
> public abstract void registerXMLInputFactory(Class<? extends XMLStreamReader> clazz, XMLInputFactory factory);
>
> public abstract XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs);
>
> public abstract XMLStreamReader doCreate(String systemId, Reader reader, boolean rejectDTDs);
>
> public abstract XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs, Class<? extends XMLStreamReader> clazz);
>
> public abstract void doRecycle(XMLStreamReader r);
>
> /**
> * Interface that can be implemented by {_at_link XMLStreamReader} to
> * be notified when it's recycled.
> *
> * <p>
> * This provides a filtering {_at_link XMLStreamReader} an opportunity to
> * recycle its inner {_at_link XMLStreamReader}.
> */
> public interface RecycleAware {
> void onRecycled();
> }
>
> /**
> * {_at_link XMLStreamReaderFactory} implementation for SJSXP/JAXP RI.
> */
> public static final class Zephyr extends XMLStreamReaderFactory {
> private final Map<Class<?>, XMLInputFactory> xifMap;
>
> private final ThreadLocal<Map<Class<?>, XMLStreamReader>> pool = new ThreadLocal<Map<Class<?>, XMLStreamReader>>();
>
> /**
> * Sun StAX impl <code>XMLReaderImpl.setInputSource()</code> method via reflection.
> */
> private final Method setInputSourceMethod;
>
> /**
> * Sun StAX impl <code>XMLReaderImpl.reset()</code> method via reflection.
> */
> private final Method resetMethod;
>
> /**
> * The Sun StAX impl's {_at_link XMLStreamReader} implementation clas.
> */
> private final Class zephyrClass;
>
> /**
> * Creates {_at_link Zephyr} instance if the given {_at_link XMLInputFactory} is the one
> * from Zephyr.
> */
> public static @Nullable
> XMLStreamReaderFactory newInstance(XMLInputFactory xif) {
> // check if this is from Zephyr
> try {
> Class<?> clazz = xif.createXMLStreamReader(new StringReader("<foo/>")).getClass();
>
> if(!clazz.getName().startsWith("com.sun.xml.stream."))
> return null; // nope
>
> return new Zephyr(xif,clazz);
> } catch (NoSuchMethodException e) {
> return null; // this factory is not for zephyr
> } catch (XMLStreamException e) {
> return null; // impossible to fail to parse <foo/>, but anyway
> }
> }
>
> public Zephyr(XMLInputFactory xif, Class clazz) throws NoSuchMethodException {
> zephyrClass = clazz;
> setInputSourceMethod = clazz.getMethod("setInputSource", InputSource.class);
> resetMethod = clazz.getMethod("reset");
>
> try {
> // Turn OFF internal factory caching in Zephyr.
> // Santiago told me that this makes it thread-safe.
> xif.setProperty("reuse-instance", false);
> } catch (IllegalArgumentException e) {
> // falls through
> }
>
> xifMap = new HashMap<Class<?>, XMLInputFactory>(4);
> xifMap.put(clazz, xif);
> }
>
>
> public void doRecycle(XMLStreamReader r) {
> offer(r);
>
> if(r instanceof RecycleAware)
> ((RecycleAware)r).onRecycled();
> }
>
> public void registerXMLInputFactory(Class<? extends XMLStreamReader> clazz, XMLInputFactory factory) {
> xifMap.put(clazz, factory);
> }
>
> /*
> * Method returns XMLStreamReader either from pool, if any available, or creates a new one.
> * If XMLStreamReader is taken from pool, than systemId and in arguments are not used
> */
> public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs, Class<? extends XMLStreamReader> clazz) {
> try {
> XMLStreamReader xsr = fetch(clazz);
> if(xsr==null)
> return xifMap.get(clazz).createXMLStreamReader(systemId,in);
>
> return xsr;
> } catch (XMLStreamException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> }
> }
>
> /*
> * Method returns Zephyr XMLStreamReader either from pool, if any available, or creates a new one.
> * If instance is taken from pool - its state will be reset with new systemId and in values
> */
> public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
> try {
> XMLStreamReader xsr = fetch(zephyrClass);
> if(xsr==null)
> return xifMap.get(zephyrClass).createXMLStreamReader(systemId,in);
>
> // try re-using this instance.
> InputSource is = new InputSource(systemId);
> is.setByteStream(in);
> reuse(xsr,is);
> return xsr;
> } catch (IllegalAccessException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> } catch (InvocationTargetException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> } catch (XMLStreamException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> }
> }
>
> public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
> try {
> XMLStreamReader xsr = fetch(zephyrClass);
> if(xsr==null)
> return xifMap.get(zephyrClass).createXMLStreamReader(systemId,in);
>
> // try re-using this instance.
> InputSource is = new InputSource(systemId);
> is.setCharacterStream(in);
> reuse(xsr,is);
> return xsr;
> } catch (IllegalAccessException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> } catch (InvocationTargetException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> } catch (XMLStreamException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> }
> }
>
> /**
> * Fetchs an instance from the pool if available, otherwise null.
> */
> private XMLStreamReader fetch(Class<? extends XMLStreamReader> clazz) {
> Map<Class<?>, XMLStreamReader> implMap = getPoolMap();
> return implMap.remove(clazz);
> }
>
> private void offer(XMLStreamReader reader) {
> Map<Class<?>, XMLStreamReader> implMap = getPoolMap();
> implMap.put(reader.getClass(), reader);
> }
>
> private Map<Class<?>, XMLStreamReader> getPoolMap() {
> Map<Class<?>, XMLStreamReader> implMap = pool.get();
> if (implMap == null) {
> implMap = new HashMap<Class<?>, XMLStreamReader>(4);
> pool.set(implMap);
> }
>
> return implMap;
> }
>
> private void reuse(XMLStreamReader xsr, InputSource in) throws IllegalAccessException, InvocationTargetException {
> resetMethod.invoke(xsr);
> setInputSourceMethod.invoke(xsr,in);
> }
>
> }
>
> /**
> * Default {_at_link XMLStreamReaderFactory} implementation
> * that can work with any {_at_link XMLInputFactory}.
> *
> * <p>
> * {_at_link XMLInputFactory} is not required to be thread-safe, so the
> * create method on this implementation is synchronized.
> */
> public static final class Default extends NoLock {
> /**
> * Creates Default instance
> */
> public static @Nullable
> XMLStreamReaderFactory newInstance(XMLInputFactory xif) {
> try {
> Class<?> clazz = xif.createXMLStreamReader(new StringReader("<foo/>")).getClass();
> return new Default(xif, clazz);
> } catch (XMLStreamException e) {
> e.printStackTrace();
> return null; // impossible to fail to parse <foo/>, but anyway
> }
> }
>
> public Default(XMLInputFactory xif, Class<?> clazz) {
> super(xif, clazz);
> }
>
> public synchronized XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
> return super.doCreate(systemId, in, rejectDTDs);
> }
>
> public synchronized XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
> return super.doCreate(systemId, in, rejectDTDs);
> }
>
> public synchronized XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs, Class<? extends XMLStreamReader> clazz) {
> return super.doCreate(systemId, in, rejectDTDs, clazz);
> }
> }
>
> /**
> * Similar to {_at_link Default} but doesn't do any synchronization.
> *
> * <p>
> * This is useful when you know your {_at_link XMLInputFactory} is thread-safe by itself.
> */
> public static class NoLock extends XMLStreamReaderFactory {
> private final Map<Class, XMLInputFactory> xifMap;
>
> /**
> * Default XMLStreamReader implementation class
> */
> private final Class defaultReaderClass;
>
> public NoLock(XMLInputFactory xif, Class<?> clazz) {
> defaultReaderClass = clazz;
> xifMap = new HashMap<Class, XMLInputFactory>(4);
> xifMap.put(defaultReaderClass, xif);
> }
>
> public void registerXMLInputFactory(Class<? extends XMLStreamReader> clazz, XMLInputFactory factory) {
> xifMap.put(clazz, factory);
> }
>
> public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
> return doCreate(systemId, in, rejectDTDs, defaultReaderClass);
> }
>
> public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs, Class<? extends XMLStreamReader> clazz) {
> try {
> return xifMap.get(clazz).createXMLStreamReader(systemId,in);
> } catch (XMLStreamException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> }
> }
>
> public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
> try {
> return xifMap.get(defaultReaderClass).createXMLStreamReader(systemId,in);
> } catch (XMLStreamException e) {
> throw new XMLReaderException("stax.cantCreate",e);
> }
> }
>
> public void doRecycle(XMLStreamReader r) {
> // there's no way to recycle with the default StAX API.
> }
> }
> }
>
>
> ------------------------------------------------------------------------
>
> /*
> * The contents of this file are subject to the terms
> * of the Common Development and Distribution License
> * (the License). You may not use this file except in
> * compliance with the License.
> *
> * You can obtain a copy of the license at
> * https://glassfish.dev.java.net/public/CDDLv1.0.html.
> * See the License for the specific language governing
> * permissions and limitations under the License.
> *
> * When distributing Covered Code, include this CDDL
> * Header Notice in each file and include the License file
> * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
> * If applicable, add the following below the CDDL Header,
> * with the fields enclosed by brackets [] replaced by
> * you own identifying information:
> * "Portions Copyrighted [year] [name of copyright owner]"
> *
> * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
> */
>
> package com.sun.xml.ws.encoding.fastinfoset;
>
> import java.io.InputStream;
> import java.io.Reader;
> import javax.xml.stream.EventFilter;
> import javax.xml.stream.StreamFilter;
> import javax.xml.stream.XMLEventReader;
> import javax.xml.stream.XMLInputFactory;
> import javax.xml.stream.XMLReporter;
> import javax.xml.stream.XMLResolver;
> import javax.xml.stream.XMLStreamException;
> import javax.xml.stream.XMLStreamReader;
> import javax.xml.stream.util.XMLEventAllocator;
> import javax.xml.transform.Source;
>
> /**
> * @author Alexey Stashok
> */
> public class FastInfosetXMLInputFactory extends XMLInputFactory {
> public boolean isPropertySupported(String string) {
> return false;
> }
>
> public XMLReporter getXMLReporter() {
> return null;
> }
>
> public void setXMLReporter(XMLReporter xMLReporter) {
> }
>
> public XMLResolver getXMLResolver() {
> return null;
> }
>
> public void setXMLResolver(XMLResolver xMLResolver) {
> }
>
> public XMLEventAllocator getEventAllocator() {
> return null;
> }
>
> public void setEventAllocator(XMLEventAllocator xMLEventAllocator) {
> }
>
> public Object getProperty(String string) throws IllegalArgumentException {
> return null;
> }
>
> public void setProperty(String string, Object object) throws IllegalArgumentException {
> }
>
> public XMLEventReader createXMLEventReader(InputStream inputStream) throws XMLStreamException {
> return null;
> }
>
> public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException {
> return null;
> }
>
> public XMLEventReader createXMLEventReader(XMLStreamReader xMLStreamReader) throws XMLStreamException {
> return null;
> }
>
> public XMLEventReader createXMLEventReader(Source source) throws XMLStreamException {
> return null;
> }
>
> public XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException {
> return null;
> }
>
> public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException {
> return null;
> }
>
> public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException {
> return null;
> }
>
> public XMLEventReader createXMLEventReader(String string, InputStream inputStream) throws XMLStreamException {
> return null;
> }
>
> public XMLEventReader createXMLEventReader(String string, Reader reader) throws XMLStreamException {
> return null;
> }
>
> public XMLEventReader createXMLEventReader(InputStream inputStream, String string) throws XMLStreamException {
> return null;
> }
>
> public XMLEventReader createFilteredReader(XMLEventReader xMLEventReader, EventFilter eventFilter) throws XMLStreamException {
> return null;
> }
>
> public XMLStreamReader createXMLStreamReader(String string, InputStream inputStream) throws XMLStreamException {
> return FastInfosetCodec.createNewStreamReader(inputStream, false);
> }
>
> public XMLStreamReader createXMLStreamReader(String string, Reader reader) throws XMLStreamException {
> return null;
> }
>
> public XMLStreamReader createXMLStreamReader(InputStream inputStream, String string) throws XMLStreamException {
> return null;
> }
>
> public XMLStreamReader createFilteredReader(XMLStreamReader xMLStreamReader, StreamFilter streamFilter) throws XMLStreamException {
> return null;
> }
> }
>
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_jax-ws.dev.java.net
> For additional commands, e-mail: dev-help_at_jax-ws.dev.java.net

-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109