View Javadoc
1   package org.codehaus.plexus.util.xml;
2   
3   /*
4    * Copyright The Codehaus Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import org.codehaus.plexus.util.IOUtil;
20  import org.codehaus.plexus.util.xml.pull.MXParser;
21  import org.codehaus.plexus.util.xml.pull.XmlPullParser;
22  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
23  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.Reader;
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  /**
31   * @version $Id$
32   */
33  public class Xpp3DomBuilder
34  {
35      private static final boolean DEFAULT_TRIM = true;
36  
37      public static Xpp3Dom build( Reader reader )
38          throws XmlPullParserException, IOException
39      {
40          return build( reader, DEFAULT_TRIM );
41      }
42  
43      public static Xpp3Dom build( InputStream is, String encoding )
44          throws XmlPullParserException, IOException
45      {
46          return build( is, encoding, DEFAULT_TRIM );
47      }
48  
49      public static Xpp3Dom build( InputStream is, String encoding, boolean trim )
50          throws XmlPullParserException, IOException
51      {
52          try
53          {
54              final XmlPullParser parser = new MXParser();
55              parser.setInput( is, encoding );
56  
57              final Xpp3Dom xpp3Dom = build( parser, trim );
58              is.close();
59              is = null;
60  
61              return xpp3Dom;
62          }
63          finally
64          {
65              IOUtil.close( is );
66          }
67      }
68  
69      public static Xpp3Dom build( Reader reader, boolean trim )
70          throws XmlPullParserException, IOException
71      {
72          try
73          {
74              final XmlPullParser parser = new MXParser();
75              parser.setInput( reader );
76  
77              final Xpp3Dom xpp3Dom = build( parser, trim );
78              reader.close();
79              reader = null;
80  
81              return xpp3Dom;
82          }
83          finally
84          {
85              IOUtil.close( reader );
86          }
87      }
88  
89      public static Xpp3Dom build( XmlPullParser parser )
90          throws XmlPullParserException, IOException
91      {
92          return build( parser, DEFAULT_TRIM );
93      }
94  
95      public static Xpp3Dom build( XmlPullParser parser, boolean trim )
96          throws XmlPullParserException, IOException
97      {
98          List<Xpp3Dom> elements = new ArrayList<Xpp3Dom>();
99  
100         List<StringBuilder> values = new ArrayList<StringBuilder>();
101 
102         int eventType = parser.getEventType();
103 
104         boolean spacePreserve = false;
105 
106         while ( eventType != XmlPullParser.END_DOCUMENT )
107         {
108             if ( eventType == XmlPullParser.START_TAG )
109             {
110                 spacePreserve = false;
111 
112                 String rawName = parser.getName();
113 
114                 Xpp3Dom childConfiguration = new Xpp3Dom( rawName );
115 
116                 int depth = elements.size();
117 
118                 if ( depth > 0 )
119                 {
120                     Xpp3Dom parent = elements.get( depth - 1 );
121 
122                     parent.addChild( childConfiguration );
123                 }
124 
125                 elements.add( childConfiguration );
126 
127                 if ( parser.isEmptyElementTag() )
128                 {
129                     values.add( null );
130                 }
131                 else
132                 {
133                     values.add( new StringBuilder() );
134                 }
135 
136                 int attributesSize = parser.getAttributeCount();
137 
138                 for ( int i = 0; i < attributesSize; i++ )
139                 {
140                     String name = parser.getAttributeName( i );
141 
142                     String value = parser.getAttributeValue( i );
143 
144                     childConfiguration.setAttribute( name, value );
145 
146                     spacePreserve = spacePreserve || ( "xml:space".equals( name ) && "preserve".equals( value ) );
147                 }
148             }
149             else if ( eventType == XmlPullParser.TEXT )
150             {
151                 int depth = values.size() - 1;
152 
153                 @SuppressWarnings( "MismatchedQueryAndUpdateOfStringBuilder" )
154                 StringBuilder valueBuffer = values.get( depth );
155 
156                 String text = parser.getText();
157 
158                 if ( trim && !spacePreserve )
159                 {
160                     text = text.trim();
161                 }
162 
163                 valueBuffer.append( text );
164             }
165             else if ( eventType == XmlPullParser.END_TAG )
166             {
167                 int depth = elements.size() - 1;
168 
169                 Xpp3Dom finishedConfiguration = elements.remove( depth );
170 
171                 /* this Object could be null if it is a singleton tag */
172                 Object accumulatedValue = values.remove( depth );
173 
174                 if ( finishedConfiguration.getChildCount() == 0 )
175                 {
176                     if ( accumulatedValue == null )
177                     {
178                         finishedConfiguration.setValue( null );
179                     }
180                     else
181                     {
182                         finishedConfiguration.setValue( accumulatedValue.toString() );
183                     }
184                 }
185 
186                 if ( depth == 0 )
187                 {
188                     return finishedConfiguration;
189                 }
190             }
191 
192             eventType = parser.next();
193         }
194 
195         throw new IllegalStateException( "End of document found before returning to 0 depth" );
196     }
197 }