1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /** 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 */ 23 package com.sun.org.apache.xml.internal.security.encryption; 24 25 import java.io.ByteArrayOutputStream; 26 import java.io.IOException; 27 import java.io.OutputStreamWriter; 28 import java.io.UnsupportedEncodingException; 29 import java.util.HashMap; 30 import java.util.Map; 31 32 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; 33 import org.w3c.dom.Element; 34 import org.w3c.dom.NamedNodeMap; 35 import org.w3c.dom.Node; 36 import org.w3c.dom.NodeList; 37 38 /** 39 * Converts <code>String</code>s into <code>Node</code>s and visa versa. 40 * 41 * An abstract class for common Serializer functionality 42 */ 43 public abstract class AbstractSerializer implements Serializer { 44 45 protected Canonicalizer canon; 46 47 public void setCanonicalizer(Canonicalizer canon) { 48 this.canon = canon; 49 } 50 51 /** 52 * Returns a <code>String</code> representation of the specified 53 * <code>Element</code>. 54 * <p/> 55 * Refer also to comments about setup of format. 56 * 57 * @param element the <code>Element</code> to serialize. 58 * @return the <code>String</code> representation of the serilaized 59 * <code>Element</code>. 60 * @throws Exception 61 */ 62 public String serialize(Element element) throws Exception { 63 return canonSerialize(element); 64 } 65 66 /** 67 * Returns a <code>byte[]</code> representation of the specified 68 * <code>Element</code>. 69 * 70 * @param element the <code>Element</code> to serialize. 71 * @return the <code>byte[]</code> representation of the serilaized 72 * <code>Element</code>. 73 * @throws Exception 74 */ 75 public byte[] serializeToByteArray(Element element) throws Exception { 76 return canonSerializeToByteArray(element); 77 } 78 79 /** 80 * Returns a <code>String</code> representation of the specified 81 * <code>NodeList</code>. 82 * <p/> 83 * This is a special case because the NodeList may represent a 84 * <code>DocumentFragment</code>. A document fragment may be a 85 * non-valid XML document (refer to appropriate description of 86 * W3C) because it my start with a non-element node, e.g. a text 87 * node. 88 * <p/> 89 * The methods first converts the node list into a document fragment. 90 * Special care is taken to not destroy the current document, thus 91 * the method clones the nodes (deep cloning) before it appends 92 * them to the document fragment. 93 * <p/> 94 * Refer also to comments about setup of format. 95 * 96 * @param content the <code>NodeList</code> to serialize. 97 * @return the <code>String</code> representation of the serialized 98 * <code>NodeList</code>. 99 * @throws Exception 100 */ 101 public String serialize(NodeList content) throws Exception { 102 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 103 canon.setWriter(baos); 104 canon.notReset(); 105 for (int i = 0; i < content.getLength(); i++) { 106 canon.canonicalizeSubtree(content.item(i)); 107 } 108 String ret = baos.toString("UTF-8"); 109 baos.reset(); 110 return ret; 111 } 112 113 /** 114 * Returns a <code>byte[]</code> representation of the specified 115 * <code>NodeList</code>. 116 * 117 * @param content the <code>NodeList</code> to serialize. 118 * @return the <code>byte[]</code> representation of the serialized 119 * <code>NodeList</code>. 120 * @throws Exception 121 */ 122 public byte[] serializeToByteArray(NodeList content) throws Exception { 123 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 124 canon.setWriter(baos); 125 canon.notReset(); 126 for (int i = 0; i < content.getLength(); i++) { 127 canon.canonicalizeSubtree(content.item(i)); 128 } 129 return baos.toByteArray(); 130 } 131 132 /** 133 * Use the Canonicalizer to serialize the node 134 * @param node 135 * @return the canonicalization of the node 136 * @throws Exception 137 */ 138 public String canonSerialize(Node node) throws Exception { 139 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 140 canon.setWriter(baos); 141 canon.notReset(); 142 canon.canonicalizeSubtree(node); 143 String ret = baos.toString("UTF-8"); 144 baos.reset(); 145 return ret; 146 } 147 148 /** 149 * Use the Canonicalizer to serialize the node 150 * @param node 151 * @return the (byte[]) canonicalization of the node 152 * @throws Exception 153 */ 154 public byte[] canonSerializeToByteArray(Node node) throws Exception { 155 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 156 canon.setWriter(baos); 157 canon.notReset(); 158 canon.canonicalizeSubtree(node); 159 return baos.toByteArray(); 160 } 161 162 /** 163 * @param source 164 * @param ctx 165 * @return the Node resulting from the parse of the source 166 * @throws XMLEncryptionException 167 */ 168 public abstract Node deserialize(String source, Node ctx) throws XMLEncryptionException; 169 170 /** 171 * @param source 172 * @param ctx 173 * @return the Node resulting from the parse of the source 174 * @throws XMLEncryptionException 175 */ 176 public abstract Node deserialize(byte[] source, Node ctx) throws XMLEncryptionException; 177 178 protected static byte[] createContext(byte[] source, Node ctx) throws XMLEncryptionException { 179 // Create the context to parse the document against 180 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 181 try { 182 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(byteArrayOutputStream, "UTF-8"); 183 outputStreamWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?><dummy"); 184 185 // Run through each node up to the document node and find any xmlns: nodes 186 Map<String, String> storedNamespaces = new HashMap<String, String>(); 187 Node wk = ctx; 188 while (wk != null) { 189 NamedNodeMap atts = wk.getAttributes(); 190 if (atts != null) { 191 for (int i = 0; i < atts.getLength(); ++i) { 192 Node att = atts.item(i); 193 String nodeName = att.getNodeName(); 194 if ((nodeName.equals("xmlns") || nodeName.startsWith("xmlns:")) 195 && !storedNamespaces.containsKey(att.getNodeName())) { 196 outputStreamWriter.write(" "); 197 outputStreamWriter.write(nodeName); 198 outputStreamWriter.write("=\""); 199 outputStreamWriter.write(att.getNodeValue()); 200 outputStreamWriter.write("\""); 201 storedNamespaces.put(nodeName, att.getNodeValue()); 202 } 203 } 204 } 205 wk = wk.getParentNode(); 206 } 207 outputStreamWriter.write(">"); 208 outputStreamWriter.flush(); 209 byteArrayOutputStream.write(source); 210 211 outputStreamWriter.write("</dummy>"); 212 outputStreamWriter.close(); 213 214 return byteArrayOutputStream.toByteArray(); 215 } catch (UnsupportedEncodingException e) { 216 throw new XMLEncryptionException("empty", e); 217 } catch (IOException e) { 218 throw new XMLEncryptionException("empty", e); 219 } 220 } 221 222 protected static String createContext(String source, Node ctx) { 223 // Create the context to parse the document against 224 StringBuilder sb = new StringBuilder(); 225 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><dummy"); 226 227 // Run through each node up to the document node and find any xmlns: nodes 228 Map<String, String> storedNamespaces = new HashMap<String, String>(); 229 Node wk = ctx; 230 while (wk != null) { 231 NamedNodeMap atts = wk.getAttributes(); 232 if (atts != null) { 233 for (int i = 0; i < atts.getLength(); ++i) { 234 Node att = atts.item(i); 235 String nodeName = att.getNodeName(); 236 if ((nodeName.equals("xmlns") || nodeName.startsWith("xmlns:")) 237 && !storedNamespaces.containsKey(att.getNodeName())) { 238 sb.append(' ').append(nodeName).append("=\"") 239 .append(att.getNodeValue()).append('"'); 240 storedNamespaces.put(nodeName, att.getNodeValue()); 241 } 242 } 243 } 244 wk = wk.getParentNode(); 245 } 246 sb.append('>').append(source).append("</dummy>"); 247 return sb.toString(); 248 } 249 250 }