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.util.Iterator;
047    import java.util.Properties;
048    import javax.xml.namespace.NamespaceContext;
049    import javax.xml.namespace.QName;
050    import javax.xml.stream.events.Attribute;
051    import javax.xml.stream.events.Characters;
052    import javax.xml.stream.events.Comment;
053    import javax.xml.stream.events.DTD;
054    import javax.xml.stream.events.EndDocument;
055    import javax.xml.stream.events.EndElement;
056    import javax.xml.stream.events.EntityDeclaration;
057    import javax.xml.stream.events.EntityReference;
058    import javax.xml.stream.events.Namespace;
059    import javax.xml.stream.events.ProcessingInstruction;
060    import javax.xml.stream.events.StartDocument;
061    import javax.xml.stream.events.StartElement;
062    
063    /**
064     * Factory for XML events.
065     */
066    public abstract class XMLEventFactory
067    {
068    
069      protected XMLEventFactory()
070      {
071      }
072    
073      /**
074       * Create a new factory instance.
075       * @see #newInstance(String,ClassLoader)
076       */
077      public static XMLEventFactory newInstance()
078        throws FactoryConfigurationError
079      {
080        return newInstance(null, null);
081      }
082    
083      /**
084       * Create a new factory instance.
085       * The implementation class to load is the first found in the following
086       * locations:
087       * <ol>
088       * <li>the <code>javax.xml.stream.XMLEventFactory</code> system
089       * property</li>
090       * <li>the above named property value in the
091       * <code><i>$JAVA_HOME</i>/lib/stax.properties</code> file</li>
092       * <li>the class name specified in the
093       * <code>META-INF/services/javax.xml.stream.XMLEventFactory</code>
094       * system resource</li>
095       * <li>the default factory class</li>
096       * </ol>
097       */
098      static XMLEventFactory newInstance(String factoryId, ClassLoader classLoader)
099        throws FactoryConfigurationError
100      {
101        ClassLoader loader = classLoader;
102        if (loader == null)
103          {
104            loader = Thread.currentThread().getContextClassLoader();
105          }
106        if (loader == null)
107          {
108            loader = XMLEventFactory.class.getClassLoader();
109          }
110        String className = null;
111        int count = 0;
112        do
113          {
114            className = getFactoryClassName(loader, count++);
115            if (className != null)
116              {
117                try
118                  {
119                    Class<?> t = (loader != null) ? loader.loadClass(className) :
120                      Class.forName(className);
121                    return (XMLEventFactory) t.newInstance();
122                  }
123                catch (ClassNotFoundException e)
124                  {
125                    className = null;
126                  }
127                catch (Exception e)
128                  {
129                    throw new FactoryConfigurationError(e,
130                         "error instantiating class " + className);
131                  }
132              }
133          }
134        while (className == null && count < 3);
135        return new gnu.xml.stream.XMLEventFactoryImpl();
136      }
137    
138      private static String getFactoryClassName(ClassLoader loader, int attempt)
139      {
140        final String propertyName = "javax.xml.stream.XMLEventFactory";
141        switch (attempt)
142          {
143            case 0:
144              return System.getProperty(propertyName);
145            case 1:
146              try
147                {
148                  File file = new File(System.getProperty("java.home"));
149                  file = new File(file, "lib");
150                  file = new File(file, "stax.properties");
151                  InputStream in = new FileInputStream(file);
152                  Properties props = new Properties();
153                  props.load(in);
154                  in.close();
155                  return props.getProperty(propertyName);
156                }
157              catch (IOException e)
158                {
159                  return null;
160                }
161            case 2:
162              try
163                {
164                  String serviceKey = "/META-INF/services/" + propertyName;
165                  InputStream in = (loader != null) ?
166                     loader.getResourceAsStream(serviceKey) :
167                    XMLEventFactory.class.getResourceAsStream(serviceKey);
168                  if (in != null)
169                    {
170                      BufferedReader r =
171                         new BufferedReader(new InputStreamReader(in));
172                      String ret = r.readLine();
173                      r.close();
174                      return ret;
175                    }
176                }
177              catch (IOException e)
178                {
179                }
180              return null;
181            default:
182              return null;
183          }
184      }
185    
186      /**
187       * Sets the location for each event created by this factory.
188       */
189      public abstract void setLocation(Location location);
190    
191      /**
192       * Create an attribute event.
193       */
194      public abstract Attribute createAttribute(String prefix, String namespaceURI,
195                                                String localName, String value);
196      
197      /**
198       * Create an attribute event.
199       */
200      public abstract Attribute createAttribute(String localName, String value);
201    
202      /**
203       * Create an attribute event.
204       */
205      public abstract Attribute createAttribute(QName name, String value);
206    
207      /**
208       * Create a namespace declaration event.
209       */
210      public abstract Namespace createNamespace(String namespaceURI);
211    
212      /**
213       * Create a namespace declaration event.
214       */
215      public abstract Namespace createNamespace(String prefix, String namespaceUri);
216    
217      /**
218       * Create a start-element event.
219       */
220      @SuppressWarnings("unchecked")
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      @SuppressWarnings("unchecked")
236      public abstract StartElement createStartElement(String prefix,
237                                                      String namespaceUri,
238                                                      String localName,
239                                                      Iterator attributes,
240                                                      Iterator namespaces);
241    
242      /**
243       * Create a start-element event.
244       */
245      @SuppressWarnings("unchecked")
246      public abstract StartElement createStartElement(String prefix,
247                                                      String namespaceUri,
248                                                      String localName,
249                                                      Iterator attributes,
250                                                      Iterator namespaces,
251                                                      NamespaceContext context);
252      
253      /**
254       * Create an end-element event.
255       */
256      @SuppressWarnings("unchecked")
257      public abstract EndElement createEndElement(QName name,
258                                                  Iterator namespaces);
259    
260      /**
261       * Create an end-element event.
262       */
263      public abstract EndElement createEndElement(String prefix,
264                                                  String namespaceUri,
265                                                  String localName);
266    
267      /**
268       * Create an end-element event.
269       */
270      @SuppressWarnings("unchecked")
271      public abstract EndElement createEndElement(String prefix,
272                                                  String namespaceUri,
273                                                  String localName,
274                                                  Iterator namespaces);
275    
276      /**
277       * Create a text event.
278       */
279      public abstract Characters createCharacters(String content);
280    
281      /**
282       * Create a text event of type CDATA section.
283       */
284      public abstract Characters createCData(String content);
285    
286      /**
287       * Create a text event of type whitespace.
288       */
289      public abstract Characters createSpace(String content);
290    
291      /**
292       * Create a text event of type ignorable whitespace.
293       */
294      public abstract Characters createIgnorableSpace(String content);
295    
296      /**
297       * Create a start-document event.
298       */
299      public abstract StartDocument createStartDocument();
300    
301      /**
302       * Create a start-document event.
303       */
304      public abstract StartDocument createStartDocument(String encoding,
305                                                        String version,
306                                                        boolean standalone);
307    
308      /**
309       * Create a start-document event.
310       */
311      public abstract StartDocument createStartDocument(String encoding,
312                                                        String version);
313    
314      /**
315       * Create a start-document event.
316       */
317      public abstract StartDocument createStartDocument(String encoding);
318    
319      /**
320       * Create an end-document event.
321       */
322      public abstract EndDocument createEndDocument();
323    
324      /**
325       * Create an entity reference event.
326       */
327      public abstract EntityReference createEntityReference(String name,
328                                                            EntityDeclaration declaration);
329    
330      /**
331       * Create a comment event.
332       */
333      public abstract Comment createComment(String text);
334    
335      /**
336       * Create a processing instruction event.
337       */
338      public abstract ProcessingInstruction createProcessingInstruction(String target,
339                                                                        String data);
340    
341      /**
342       * Create a DOCTYPE declaration event.
343       */
344      public abstract DTD createDTD(String dtd);
345      
346    }
347