Shared flag added to TrashResource concerning Issue 69.
[pithos] / src / gr / ebs / gss / server / webdav / DOMWriter.java
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package gr.ebs.gss.server.webdav;
19
20 import java.io.OutputStreamWriter;
21 import java.io.PrintWriter;
22 import java.io.UnsupportedEncodingException;
23 import java.io.Writer;
24
25 import org.w3c.dom.Attr;
26 import org.w3c.dom.Document;
27 import org.w3c.dom.NamedNodeMap;
28 import org.w3c.dom.Node;
29 import org.w3c.dom.NodeList;
30
31 /**
32  * A sample DOM writer. This sample program illustrates how to
33  * traverse a DOM tree in order to print a document that is parsed.
34  */
35 public class DOMWriter {
36
37         //
38         // Data
39         //
40
41         /** Default Encoding */
42         private static  String
43         PRINTWRITER_ENCODING = "UTF8";
44
45         /**
46          *
47          */
48         private static String MIME2JAVA_ENCODINGS[] =
49         { "Default", "UTF-8", "US-ASCII", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4",
50                 "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-2022-JP",
51                 "SHIFT_JIS", "EUC-JP","GB2312", "BIG5", "EUC-KR", "ISO-2022-KR", "KOI8-R", "EBCDIC-CP-US",
52                 "EBCDIC-CP-CA", "EBCDIC-CP-NL", "EBCDIC-CP-DK", "EBCDIC-CP-NO", "EBCDIC-CP-FI", "EBCDIC-CP-SE",
53                 "EBCDIC-CP-IT", "EBCDIC-CP-ES", "EBCDIC-CP-GB", "EBCDIC-CP-FR", "EBCDIC-CP-AR1",
54                 "EBCDIC-CP-HE", "EBCDIC-CP-CH", "EBCDIC-CP-ROECE","EBCDIC-CP-YU",
55                 "EBCDIC-CP-IS", "EBCDIC-CP-AR2", "UTF-16"
56         };
57
58         /** Output qualified names */
59         private boolean qualifiedNames = true;
60
61         /** Print writer. */
62         protected PrintWriter out;
63
64         /** Canonical output. */
65         protected boolean canonical;
66
67
68         /**
69          * @param encoding
70          * @param _canonical
71          * @throws UnsupportedEncodingException
72          */
73         public DOMWriter(String encoding, boolean _canonical)
74         throws UnsupportedEncodingException {
75                 out = new PrintWriter(new OutputStreamWriter(System.out, encoding));
76                 canonical = _canonical;
77         } // <init>(String,boolean)
78
79         //
80         // Constructors
81         //
82
83         /** Default constructor.
84          * @param _canonical
85          * @throws UnsupportedEncodingException
86          */
87         public DOMWriter(boolean _canonical) throws UnsupportedEncodingException {
88                 this( getWriterEncoding(), _canonical);
89         }
90
91         /**
92          * @param writer
93          * @param _canonical
94          */
95         public DOMWriter(Writer writer, boolean _canonical) {
96                 out = new PrintWriter(writer);
97                 canonical = _canonical;
98         }
99
100         /**
101          * @return the qualifiedNames
102          */
103         public boolean getQualifiedNames() {
104                 return qualifiedNames;
105         }
106
107         /**
108          * @param _qualifiedNames
109          */
110         public void setQualifiedNames(boolean _qualifiedNames) {
111                 qualifiedNames = _qualifiedNames;
112         }
113
114         /**
115          * @return the PrintWriter encoding
116          */
117         public static String getWriterEncoding( ) {
118                 return PRINTWRITER_ENCODING;
119         }// getWriterEncoding
120
121         /**
122          * @param encoding
123          */
124         public static void  setWriterEncoding( String encoding ) {
125                 if( encoding.equalsIgnoreCase( "DEFAULT" ) )
126                         PRINTWRITER_ENCODING  = "UTF8";
127                 else if( encoding.equalsIgnoreCase( "UTF-16" ) )
128                         PRINTWRITER_ENCODING  = "Unicode";
129                 else
130                         PRINTWRITER_ENCODING = MIME2Java.convert( encoding );
131         }// setWriterEncoding
132
133
134         /**
135          * @param encoding
136          * @return true if the encoding is valid
137          */
138         public static boolean isValidJavaEncoding( String encoding ) {
139                 for ( int i = 0; i < MIME2JAVA_ENCODINGS.length; i++ )
140                         if ( encoding.equals( MIME2JAVA_ENCODINGS[i] ) )
141                                 return true;
142
143                 return false;
144         }// isValidJavaEncoding
145
146
147         /** Prints the specified node, recursively.
148          * @param node
149          */
150         public void print(Node node) {
151
152                 // is there anything to do?
153                 if ( node == null )
154                         return;
155
156                 int type = node.getNodeType();
157                 switch ( type ) {
158                         // print document
159                         case Node.DOCUMENT_NODE: {
160                                 if ( !canonical ) {
161                                         String  Encoding = getWriterEncoding();
162                                         if( Encoding.equalsIgnoreCase( "DEFAULT" ) )
163                                                 Encoding = "UTF-8";
164                                         else if( Encoding.equalsIgnoreCase( "Unicode" ) )
165                                                 Encoding = "UTF-16";
166                                         else
167                                                 Encoding = MIME2Java.reverse( Encoding );
168
169                                         out.println("<?xml version=\"1.0\" encoding=\""+
170                                                                 Encoding + "\"?>");
171                                 }
172                                 print(((Document)node).getDocumentElement());
173                                 out.flush();
174                                 break;
175                         }
176
177                         // print element with attributes
178                         case Node.ELEMENT_NODE: {
179                                 out.print('<');
180                                 if (qualifiedNames)
181                                         out.print(node.getNodeName());
182                                 else
183                                         out.print(node.getLocalName());
184                                 Attr attrs[] = sortAttributes(node.getAttributes());
185                                 for ( int i = 0; i < attrs.length; i++ ) {
186                                         Attr attr = attrs[i];
187                                         out.print(' ');
188                                         if (qualifiedNames)
189                                                 out.print(attr.getNodeName());
190                                         else
191                                                 out.print(attr.getLocalName());
192
193                                         out.print("=\"");
194                                         out.print(normalize(attr.getNodeValue()));
195                                         out.print('"');
196                                 }
197                                 out.print('>');
198                                 NodeList children = node.getChildNodes();
199                                 if ( children != null ) {
200                                         int len = children.getLength();
201                                         for ( int i = 0; i < len; i++ )
202                                                 print(children.item(i));
203                                 }
204                                 break;
205                         }
206
207                         // handle entity reference nodes
208                         case Node.ENTITY_REFERENCE_NODE: {
209                                 if ( canonical ) {
210                                         NodeList children = node.getChildNodes();
211                                         if ( children != null ) {
212                                                 int len = children.getLength();
213                                                 for ( int i = 0; i < len; i++ )
214                                                         print(children.item(i));
215                                         }
216                                 } else {
217                                         out.print('&');
218                                         if (qualifiedNames)
219                                                 out.print(node.getNodeName());
220                                         else
221                                                 out.print(node.getLocalName());
222                                         out.print(';');
223                                 }
224                                 break;
225                         }
226
227                         // print cdata sections
228                         case Node.CDATA_SECTION_NODE: {
229                                 if ( canonical )
230                                         out.print(normalize(node.getNodeValue()));
231                                 else {
232                                         out.print("<![CDATA[");
233                                         out.print(node.getNodeValue());
234                                         out.print("]]>");
235                                 }
236                                 break;
237                         }
238
239                         // print text
240                         case Node.TEXT_NODE: {
241                                 out.print(normalize(node.getNodeValue()));
242                                 break;
243                         }
244
245                         // print processing instruction
246                         case Node.PROCESSING_INSTRUCTION_NODE: {
247                                 out.print("<?");
248                                 if (qualifiedNames)
249                                         out.print(node.getNodeName());
250                                 else
251                                         out.print(node.getLocalName());
252
253                                 String data = node.getNodeValue();
254                                 if ( data != null && data.length() > 0 ) {
255                                         out.print(' ');
256                                         out.print(data);
257                                 }
258                                 out.print("?>");
259                                 break;
260                         }
261                 }
262
263                 if ( type == Node.ELEMENT_NODE ) {
264                         out.print("</");
265                         if (qualifiedNames)
266                                 out.print(node.getNodeName());
267                         else
268                                 out.print(node.getLocalName());
269                         out.print('>');
270                 }
271
272                 out.flush();
273
274         } // print(Node)
275
276         /** Returns a sorted list of attributes.
277          * @param attrs
278          * @return
279          */
280         @SuppressWarnings("null")
281         protected Attr[] sortAttributes(NamedNodeMap attrs) {
282
283                 int len = attrs != null ? attrs.getLength() : 0;
284                 Attr array[] = new Attr[len];
285                 for ( int i = 0; i < len; i++ )
286                         array[i] = (Attr)attrs.item(i);
287                 for ( int i = 0; i < len - 1; i++ ) {
288                         String name = null;
289                         if (qualifiedNames)
290                                 name  = array[i].getNodeName();
291                         else
292                                 name  = array[i].getLocalName();
293                         int    index = i;
294                         for ( int j = i + 1; j < len; j++ ) {
295                                 String curName = null;
296                                 if (qualifiedNames)
297                                         curName = array[j].getNodeName();
298                                 else
299                                         curName = array[j].getLocalName();
300                                 if ( curName.compareTo(name) < 0 ) {
301                                         name  = curName;
302                                         index = j;
303                                 }
304                         }
305                         if ( index != i ) {
306                                 Attr temp    = array[i];
307                                 array[i]     = array[index];
308                                 array[index] = temp;
309                         }
310                 }
311
312                 return array;
313
314         } // sortAttributes(NamedNodeMap):Attr[]
315
316
317         /** Normalizes the given string.
318          * @param s
319          * @return
320          */
321         @SuppressWarnings({"fallthrough", "null"})
322         protected String normalize(String s) {
323                 StringBuffer str = new StringBuffer();
324
325                 int len = s != null ? s.length() : 0;
326                 for ( int i = 0; i < len; i++ ) {
327                         char ch = s.charAt(i);
328                         switch ( ch ) {
329                                 case '<': {
330                                         str.append("&lt;");
331                                         break;
332                                 }
333                                 case '>': {
334                                         str.append("&gt;");
335                                         break;
336                                 }
337                                 case '&': {
338                                         str.append("&amp;");
339                                         break;
340                                 }
341                                 case '"': {
342                                         str.append("&quot;");
343                                         break;
344                                 }
345                                 case '\r':
346                                 case '\n': {
347                                         if ( canonical ) {
348                                                 str.append("&#");
349                                                 str.append(Integer.toString(ch));
350                                                 str.append(';');
351                                                 break;
352                                         }
353                                         // else, default append char
354                                 }
355                                 default: {
356                                         str.append(ch);
357                                 }
358                         }
359                 }
360
361                 return str.toString();
362
363         } // normalize(String):String
364
365         /**
366          *
367          */
368         @SuppressWarnings("unused")
369         private static void printValidJavaEncoding() {
370                 System.err.println( "    ENCODINGS:" );
371                 System.err.print( "   " );
372                 for( int i = 0;
373                 i < MIME2JAVA_ENCODINGS.length; i++) {
374                         System.err.print( MIME2JAVA_ENCODINGS[i] + " " );
375                         if( i % 7 == 0 ){
376                                 System.err.println();
377                                 System.err.print( "   " );
378                         }
379                 }
380
381         } // printJavaEncoding()
382
383 }