001    /* XMLEventFactory.java -- 
002       Copyright (C) 2005,2006  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package javax.xml.stream;
039    
040    import java.io.BufferedReader;
041    import java.io.File;
042    import java.io.FileInputStream;
043    import java.io.InputStream;
044    import java.io.InputStreamReader;
045    import java.io.IOException;
046    import java.io.Reader;
047    import java.util.Iterator;
048    import java.util.Properties;
049    import javax.xml.namespace.NamespaceContext;
050    import javax.xml.namespace.QName;
051    import javax.xml.stream.events.Attribute;
052    import javax.xml.stream.events.Characters;
053    import javax.xml.stream.events.Comment;
054    import javax.xml.stream.events.DTD;
055    import javax.xml.stream.events.EndDocument;
056    import javax.xml.stream.events.EndElement;
057    import javax.xml.stream.events.EntityDeclaration;
058    import javax.xml.stream.events.EntityReference;
059    import javax.xml.stream.events.Namespace;
060    import javax.xml.stream.events.ProcessingInstruction;
061    import javax.xml.stream.events.StartDocument;
062    import javax.xml.stream.events.StartElement;
063    
064    /**
065     * Factory for XML events.
066     */
067    public abstract class XMLEventFactory
068    {
069    
070      protected XMLEventFactory()
071      {
072      }
073    
074      /**
075       * Create a new factory instance.
076       * @see #newInstance(String,ClassLoader)
077       */
078      public static XMLEventFactory newInstance()
079        throws FactoryConfigurationError
080      {
081        return newInstance(null, null);
082      }
083    
084      /**
085       * Create a new factory instance.
086       * The implementation class to load is the first found in the following
087       * locations:
088       * <ol>
089       * <li>the <code>javax.xml.stream.XMLEventFactory</code> system
090       * property</li>
091       * <li>the above named property value in the
092       * <code><i>$JAVA_HOME</i>/lib/stax.properties</code> file</li>
093       * <li>the class name specified in the
094       * <code>META-INF/services/javax.xml.stream.XMLEventFactory</code>
095       * system resource</li>
096       * <li>the default factory class</li>
097       * </ol>
098       */
099      static XMLEventFactory newInstance(String factoryId, ClassLoader classLoader)
100        throws FactoryConfigurationError
101      {
102        ClassLoader loader = classLoader;
103        if (loader == null)
104          {
105            loader = Thread.currentThread().getContextClassLoader();
106          }
107        if (loader == null)
108          {
109            loader = XMLEventFactory.class.getClassLoader();
110          }
111        String className = null;
112        int count = 0;
113        do
114          {
115            className = getFactoryClassName(loader, count++);
116            if (className != null)
117              {
118                try
119                  {
120                    Class t = (loader != null) ? loader.loadClass(className) :
121                      Class.forName(className);
122                    return (XMLEventFactory) t.newInstance();
123                  }
124                catch (ClassNotFoundException e)
125                  {
126                    className = null;
127                  }
128                catch (Exception e)
129                  {
130                    throw new FactoryConfigurationError(e,
131                         "error instantiating class " + className);
132                  }
133              }
134          }
135        while (className == null && count < 3);
136        return new gnu.xml.stream.XMLEventFactoryImpl();
137      }
138    
139      private static String getFactoryClassName(ClassLoader loader, int attempt)
140      {
141        final String propertyName = "javax.xml.stream.XMLEventFactory";
142        switch (attempt)
143          {
144            case 0:
145              return System.getProperty(propertyName);
146            case 1:
147              try
148                {
149                  File file = new File(System.getProperty("java.home"));
150                  file = new File(file, "lib");
151                  file = new File(file, "stax.properties");
152                  InputStream in = new FileInputStream(file);
153                  Properties props = new Properties();
154                  props.load(in);
155                  in.close();
156                  return props.getProperty(propertyName);
157                }
158              catch (IOException e)
159                {
160                  return null;
161                }
162            case 2:
163              try
164                {
165                  String serviceKey = "/META-INF/services/" + propertyName;
166                  InputStream in = (loader != null) ?
167                     loader.getResourceAsStream(serviceKey) :
168                    XMLEventFactory.class.getResourceAsStream(serviceKey);
169                  if (in != null)
170                    {
171                      BufferedReader r =
172                         new BufferedReader(new InputStreamReader(in));
173                      String ret = r.readLine();
174                      r.close();
175                      return ret;
176                    }
177                }
178              catch (IOException e)
179                {
180                }
181              return null;
182            default:
183              return null;
184          }
185      }
186    
187      /**
188       * Sets the location for each event created by this factory.
189       */
190      public abstract void setLocation(Location location);
191    
192      /**
193       * Create an attribute event.
194       */
195      public abstract Attribute createAttribute(String prefix, String namespaceURI,
196                                                String localName, String value);
197      
198      /**
199       * Create an attribute event.
200       */
201      public abstract Attribute createAttribute(String localName, String value);
202    
203      /**
204       * Create an attribute event.
205       */
206      public abstract Attribute createAttribute(QName name, String value);
207    
208      /**
209       * Create a namespace declaration event.
210       */
211      public abstract Namespace createNamespace(String namespaceURI);
212    
213      /**
214       * Create a namespace declaration event.
215       */
216      public abstract Namespace createNamespace(String prefix, String namespaceUri);
217    
218      /**
219       * Create a start-element event.
220       */
221      public abstract StartElement createStartElement(QName name,
222                                                      Iterator attributes,
223                                                      Iterator namespaces);
224    
225      /**
226       * Create a start-element event.
227       */
228      public abstract StartElement createStartElement(String prefix,
229                                                      String namespaceUri,
230                                                      String localName);
231    
232      /**
233       * Create a start-element event.
234       */
235      public abstract StartElement createStartElement(String prefix,
236                                                      String namespaceUri,
237                                                      String localName,
238                                                      Iterator attributes,
239                                                      Iterator namespaces);
240    
241      /**
242       * Create a start-element event.
243       */
244      public abstract StartElement createStartElement(String prefix,
245                                                      String namespaceUri,
246                                                      String localName,
247                                                      Iterator attributes,
248                                                      Iterator namespaces,
249                                                      NamespaceContext context);
250      
251      /**
252       * Create an end-element event.
253       */
254      public abstract EndElement createEndElement(QName name,
255                                                  Iterator namespaces);
256    
257      /**
258       * Create an end-element event.
259       */
260      public abstract EndElement createEndElement(String prefix,
261                                                  String namespaceUri,
262                                                  String localName);
263    
264      /**
265       * Create an end-element event.
266       */
267      public abstract EndElement createEndElement(String prefix,
268                                                  String namespaceUri,
269                                                  String localName,
270                                                  Iterator namespaces);
271    
272      /**
273       * Create a text event.
274       */
275      public abstract Characters createCharacters(String content);
276    
277      /**
278       * Create a text event of type CDATA section.
279       */
280      public abstract Characters createCData(String content);
281    
282      /**
283       * Create a text event of type whitespace.
284       */
285      public abstract Characters createSpace(String content);
286    
287      /**
288       * Create a text event of type ignorable whitespace.
289       */
290      public abstract Characters createIgnorableSpace(String content);
291    
292      /**
293       * Create a start-document event.
294       */
295      public abstract StartDocument createStartDocument();
296    
297      /**
298       * Create a start-document event.
299       */
300      public abstract StartDocument createStartDocument(String encoding,
301                                                        String version,
302                                                        boolean standalone);
303    
304      /**
305       * Create a start-document event.
306       */
307      public abstract StartDocument createStartDocument(String encoding,
308                                                        String version);
309    
310      /**
311       * Create a start-document event.
312       */
313      public abstract StartDocument createStartDocument(String encoding);
314    
315      /**
316       * Create an end-document event.
317       */
318      public abstract EndDocument createEndDocument();
319    
320      /**
321       * Create an entity reference event.
322       */
323      public abstract EntityReference createEntityReference(String name,
324                                                            EntityDeclaration declaration);
325    
326      /**
327       * Create a comment event.
328       */
329      public abstract Comment createComment(String text);
330    
331      /**
332       * Create a processing instruction event.
333       */
334      public abstract ProcessingInstruction createProcessingInstruction(String target,
335                                                                        String data);
336    
337      /**
338       * Create a DOCTYPE declaration event.
339       */
340      public abstract DTD createDTD(String dtd);
341      
342    }
343