1 package org.codehaus.plexus.util.xml;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.OutputStream;
8 import java.io.OutputStreamWriter;
9 import java.io.StringWriter;
10 import java.io.Writer;
11 import java.util.regex.Matcher;
12 import java.util.regex.Pattern;
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class XmlStreamWriter
42 extends Writer
43 {
44 private static final int BUFFER_SIZE = 4096;
45
46 private StringWriter xmlPrologWriter = new StringWriter( BUFFER_SIZE );
47
48 private OutputStream out;
49
50 private Writer writer;
51
52 private String encoding;
53
54 public XmlStreamWriter( OutputStream out )
55 {
56 this.out = out;
57 }
58
59 public XmlStreamWriter( File file )
60 throws FileNotFoundException
61 {
62 this( new FileOutputStream( file ) );
63 }
64
65 public String getEncoding()
66 {
67 return encoding;
68 }
69
70 public void close()
71 throws IOException
72 {
73 if ( writer == null )
74 {
75 encoding = "UTF-8";
76 writer = new OutputStreamWriter( out, encoding );
77 writer.write( xmlPrologWriter.toString() );
78 }
79 writer.close();
80 }
81
82 public void flush()
83 throws IOException
84 {
85 if ( writer != null )
86 {
87 writer.flush();
88 }
89 }
90
91 private void detectEncoding( char[] cbuf, int off, int len )
92 throws IOException
93 {
94 int size = len;
95 StringBuffer xmlProlog = xmlPrologWriter.getBuffer();
96 if ( xmlProlog.length() + len > BUFFER_SIZE )
97 {
98 size = BUFFER_SIZE - xmlProlog.length();
99 }
100 xmlPrologWriter.write( cbuf, off, size );
101
102
103 if ( xmlProlog.length() >= 5 )
104 {
105 if ( xmlProlog.substring( 0, 5 ).equals( "<?xml" ) )
106 {
107
108 int xmlPrologEnd = xmlProlog.indexOf( "?>" );
109 if ( xmlPrologEnd > 0 )
110 {
111
112 Matcher m = ENCODING_PATTERN.matcher( xmlProlog.substring( 0, xmlPrologEnd ) );
113 if ( m.find() )
114 {
115 encoding = m.group( 1 ).toUpperCase();
116 encoding = encoding.substring( 1, encoding.length() - 1 );
117 }
118 else
119 {
120
121 encoding = "UTF-8";
122 }
123 }
124 else
125 {
126 if ( xmlProlog.length() >= BUFFER_SIZE )
127 {
128
129 encoding = "UTF-8";
130 }
131 }
132 }
133 else
134 {
135
136 encoding = "UTF-8";
137 }
138 if ( encoding != null )
139 {
140
141 xmlPrologWriter = null;
142 writer = new OutputStreamWriter( out, encoding );
143 writer.write( xmlProlog.toString() );
144 if ( len > size )
145 {
146 writer.write( cbuf, off + size, len - size );
147 }
148 }
149 }
150 }
151
152 public void write( char[] cbuf, int off, int len )
153 throws IOException
154 {
155 if ( xmlPrologWriter != null )
156 {
157 detectEncoding( cbuf, off, len );
158 }
159 else
160 {
161 writer.write( cbuf, off, len );
162 }
163 }
164
165 static final Pattern ENCODING_PATTERN = XmlReader.ENCODING_PATTERN;
166 }