View Javadoc
1   package org.apache.maven.internal.xml;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.Reader;
25  import java.util.ArrayList;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.maven.api.xml.Dom;
31  import org.codehaus.plexus.util.IOUtil;
32  import org.codehaus.plexus.util.xml.pull.MXParser;
33  import org.codehaus.plexus.util.xml.pull.XmlPullParser;
34  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
35  
36  /**
37   *
38   */
39  public class Xpp3DomBuilder
40  {
41      private static final boolean DEFAULT_TRIM = true;
42  
43      public static Xpp3Dom build( Reader reader )
44          throws XmlPullParserException, IOException
45      {
46          return build( reader, null );
47      }
48  
49      /**
50       * @param reader the reader
51       * @param locationBuilder the builder
52       * @since 3.2.0
53       * @return DOM
54       * @throws XmlPullParserException xml exception
55       * @throws IOException io
56       */
57      public static Xpp3Dom build( Reader reader, InputLocationBuilder locationBuilder )
58          throws XmlPullParserException, IOException
59      {
60          return build( reader, DEFAULT_TRIM, locationBuilder );
61      }
62  
63      public static Xpp3Dom build( InputStream is, String encoding )
64          throws XmlPullParserException, IOException
65      {
66          return build( is, encoding, DEFAULT_TRIM );
67      }
68  
69      public static Xpp3Dom build( InputStream is, String encoding, boolean trim )
70          throws XmlPullParserException, IOException
71      {
72          try
73          {
74              final XmlPullParser parser = new MXParser();
75              parser.setInput( is, encoding );
76  
77              final Xpp3Dom xpp3Dom = build( parser, trim );
78              is.close();
79              is = null;
80  
81              return xpp3Dom;
82          }
83          finally
84          {
85              IOUtil.close( is );
86          }
87      }
88  
89      public static Xpp3Dom build( Reader reader, boolean trim )
90          throws XmlPullParserException, IOException
91      {
92          return build( reader, trim, null );
93      }
94  
95      /**
96       * @param reader the reader
97       * @param trim to trim
98       * @param locationBuilder the builder
99       * @since 3.2.0
100      * @return DOM
101      * @throws XmlPullParserException xml exception
102      * @throws IOException io
103      */
104     public static Xpp3Dom build( Reader reader, boolean trim, InputLocationBuilder locationBuilder )
105         throws XmlPullParserException, IOException
106     {
107         try
108         {
109             final XmlPullParser parser = new MXParser();
110             parser.setInput( reader );
111 
112             final Xpp3Dom xpp3Dom = build( parser, trim, locationBuilder );
113             reader.close();
114             reader = null;
115 
116             return xpp3Dom;
117         }
118         finally
119         {
120             IOUtil.close( reader );
121         }
122     }
123 
124     public static Xpp3Dom build( XmlPullParser parser )
125         throws XmlPullParserException, IOException
126     {
127         return build( parser, DEFAULT_TRIM );
128     }
129 
130     public static Xpp3Dom build( XmlPullParser parser, boolean trim )
131         throws XmlPullParserException, IOException
132     {
133         return build( parser, trim, null );
134     }
135 
136     /**
137      * @since 3.2.0
138      * @param locationBuilder builder
139      * @param parser the parser
140      * @param trim do trim
141      * @return DOM
142      * @throws XmlPullParserException xml exception
143      * @throws IOException io
144      */
145     public static Xpp3Dom build( XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder )
146         throws XmlPullParserException, IOException
147     {
148         boolean spacePreserve = false;
149         String name = null;
150         String value = null;
151         Object location = null;
152         Map<String, String> attrs = null;
153         List<Dom> children = null;
154         int eventType = parser.getEventType();
155         while ( eventType != XmlPullParser.END_DOCUMENT )
156         {
157             if ( eventType == XmlPullParser.START_TAG )
158             {
159                 if ( name == null )
160                 {
161                     name = parser.getName();
162                     location = locationBuilder != null ? locationBuilder.toInputLocation( parser ) : null;
163                     int attributesSize = parser.getAttributeCount();
164                     if ( attributesSize > 0 )
165                     {
166                         attrs = new HashMap<>();
167                         for ( int i = 0; i < attributesSize; i++ )
168                         {
169                             String aname = parser.getAttributeName( i );
170                             String avalue = parser.getAttributeValue( i );
171                             attrs.put( aname, avalue );
172                             spacePreserve =
173                                     spacePreserve || ( "xml:space".equals( aname ) && "preserve".equals( avalue ) );
174                         }
175                     }
176                 }
177                 else
178                 {
179                     if ( children == null )
180                     {
181                         children = new ArrayList<>();
182                     }
183                     Dom child = build( parser, trim, locationBuilder );
184                     children.add( child );
185                 }
186             }
187             else if ( eventType == XmlPullParser.TEXT )
188             {
189                 String text = parser.getText();
190                 if ( trim && !spacePreserve )
191                 {
192                     text = text.trim();
193                 }
194                 value = value != null ? value + text : text;
195             }
196             else if ( eventType == XmlPullParser.END_TAG )
197             {
198                 return new Xpp3Dom( name, children == null ? value : null,
199                         attrs, children, location );
200             }
201             eventType = parser.next();
202         }
203         throw new IllegalStateException( "End of document found before returning to 0 depth" );
204     }
205 
206     /**
207      * Input location builder interface, to be implemented to choose how to store data.
208      *
209      * @since 3.2.0
210      */
211     public interface InputLocationBuilder
212     {
213         Object toInputLocation( XmlPullParser parser );
214     }
215 }