PageRenderTime 27ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/xml-security-1_4_5/src/org/apache/xml/security/transforms/Transform.java

#
Java | 362 lines | 177 code | 43 blank | 142 comment | 21 complexity | e4612b5cb5eb3d9d9ae3322c278637b5 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Copyright 1999-2009 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.xml.security.transforms;
  18. import java.io.IOException;
  19. import java.io.OutputStream;
  20. import java.util.HashMap;
  21. import javax.xml.parsers.ParserConfigurationException;
  22. import org.apache.xml.security.c14n.CanonicalizationException;
  23. import org.apache.xml.security.c14n.InvalidCanonicalizerException;
  24. import org.apache.xml.security.exceptions.AlgorithmAlreadyRegisteredException;
  25. import org.apache.xml.security.exceptions.XMLSecurityException;
  26. import org.apache.xml.security.signature.XMLSignatureInput;
  27. import org.apache.xml.security.utils.ClassLoaderUtils;
  28. import org.apache.xml.security.utils.Constants;
  29. import org.apache.xml.security.utils.HelperNodeList;
  30. import org.apache.xml.security.utils.SignatureElementProxy;
  31. import org.apache.xml.security.utils.XMLUtils;
  32. import org.w3c.dom.Document;
  33. import org.w3c.dom.Element;
  34. import org.w3c.dom.NodeList;
  35. import org.xml.sax.SAXException;
  36. /**
  37. * Implements the behaviour of the <code>ds:Transform</code> element.
  38. *
  39. * This <code>Transform</code>(Factory) class acts as the Factory and Proxy of
  40. * the implementing class that supports the functionality of <a
  41. * href=http://www.w3.org/TR/xmldsig-core/#sec-TransformAlg>a Transform
  42. * algorithm</a>.
  43. * Implements the Factory and Proxy pattern for ds:Transform algorithms.
  44. *
  45. * @author Christian Geuer-Pollmann
  46. * @see Transforms
  47. * @see TransformSpi
  48. */
  49. public final class Transform extends SignatureElementProxy {
  50. /** {@link org.apache.commons.logging} logging facility */
  51. private static org.apache.commons.logging.Log log =
  52. org.apache.commons.logging.LogFactory.getLog(Transform.class.getName());
  53. /** Field _alreadyInitialized */
  54. private static boolean alreadyInitialized = false;
  55. /** All available Transform classes are registered here */
  56. private static HashMap transformClassHash = null;
  57. private static HashMap transformSpiHash = new HashMap();
  58. private TransformSpi transformSpi = null;
  59. /**
  60. * Constructs {@link Transform}
  61. *
  62. * @param doc the {@link Document} in which <code>Transform</code> will be
  63. * placed
  64. * @param algorithmURI URI representation of
  65. * <code>Transform algorithm</code> which will be specified as parameter of
  66. * {@link #getInstance(Document, String)}, when generated. </br>
  67. * @param contextNodes the child node list of <code>Transform</code> element
  68. * @throws InvalidTransformException
  69. */
  70. public Transform(Document doc, String algorithmURI, NodeList contextNodes)
  71. throws InvalidTransformException {
  72. super(doc);
  73. this._constructionElement.setAttributeNS
  74. (null, Constants._ATT_ALGORITHM, algorithmURI);
  75. transformSpi = getTransformSpi(algorithmURI);
  76. if (transformSpi == null) {
  77. Object exArgs[] = { algorithmURI };
  78. throw new InvalidTransformException(
  79. "signature.Transform.UnknownTransform", exArgs);
  80. }
  81. if (log.isDebugEnabled()) {
  82. log.debug("Create URI \"" + algorithmURI + "\" class \""
  83. + transformSpi.getClass() + "\"");
  84. log.debug("The NodeList is " + contextNodes);
  85. }
  86. // give it to the current document
  87. if (contextNodes != null) {
  88. for (int i = 0; i < contextNodes.getLength(); i++) {
  89. this._constructionElement.appendChild
  90. (contextNodes.item(i).cloneNode(true));
  91. }
  92. }
  93. }
  94. /**
  95. * This constructor can only be called from the {@link Transforms} object,
  96. * so it's protected.
  97. *
  98. * @param element <code>ds:Transform</code> element
  99. * @param BaseURI the URI of the resource where the XML instance was stored
  100. * @throws InvalidTransformException
  101. * @throws TransformationException
  102. * @throws XMLSecurityException
  103. */
  104. public Transform(Element element, String BaseURI)
  105. throws InvalidTransformException, TransformationException,
  106. XMLSecurityException {
  107. super(element, BaseURI);
  108. // retrieve Algorithm Attribute from ds:Transform
  109. String algorithmURI = element.getAttributeNS(null, Constants._ATT_ALGORITHM);
  110. if (algorithmURI == null || algorithmURI.length() == 0) {
  111. Object exArgs[] = { Constants._ATT_ALGORITHM,
  112. Constants._TAG_TRANSFORM };
  113. throw new TransformationException("xml.WrongContent", exArgs);
  114. }
  115. transformSpi = getTransformSpi(algorithmURI);
  116. if (transformSpi == null) {
  117. Object exArgs[] = { algorithmURI };
  118. throw new InvalidTransformException(
  119. "signature.Transform.UnknownTransform", exArgs);
  120. }
  121. }
  122. /**
  123. * Generates a Transform object that implements the specified
  124. * <code>Transform algorithm</code> URI.
  125. *
  126. * @param algorithmURI <code>Transform algorithm</code> URI representation,
  127. * such as specified in
  128. * <a href=http://www.w3.org/TR/xmldsig-core/#sec-TransformAlg>Transform algorithm </a>
  129. * @param doc the proxy {@link Document}
  130. * @return <code>{@link Transform}</code> object
  131. * @throws InvalidTransformException
  132. */
  133. public static Transform getInstance(
  134. Document doc, String algorithmURI) throws InvalidTransformException {
  135. return getInstance(doc, algorithmURI, (NodeList) null);
  136. }
  137. /**
  138. * Generates a Transform object that implements the specified
  139. * <code>Transform algorithm</code> URI.
  140. *
  141. * @param algorithmURI <code>Transform algorithm</code> URI representation,
  142. * such as specified in
  143. * <a href=http://www.w3.org/TR/xmldsig-core/#sec-TransformAlg>Transform algorithm </a>
  144. * @param contextChild the child element of <code>Transform</code> element
  145. * @param doc the proxy {@link Document}
  146. * @return <code>{@link Transform}</code> object
  147. * @throws InvalidTransformException
  148. */
  149. public static Transform getInstance(
  150. Document doc, String algorithmURI, Element contextChild)
  151. throws InvalidTransformException {
  152. HelperNodeList contextNodes = null;
  153. if (contextChild != null) {
  154. contextNodes = new HelperNodeList();
  155. XMLUtils.addReturnToElement(doc, contextNodes);
  156. contextNodes.appendChild(contextChild);
  157. XMLUtils.addReturnToElement(doc, contextNodes);
  158. }
  159. return getInstance(doc, algorithmURI, contextNodes);
  160. }
  161. /**
  162. * Generates a Transform object that implements the specified
  163. * <code>Transform algorithm</code> URI.
  164. *
  165. * @param algorithmURI <code>Transform algorithm</code> URI form, such as
  166. * specified in <a href=http://www.w3.org/TR/xmldsig-core/#sec-TransformAlg>
  167. * Transform algorithm </a>
  168. * @param contextNodes the child node list of <code>Transform</code> element
  169. * @param doc the proxy {@link Document}
  170. * @return <code>{@link Transform}</code> object
  171. * @throws InvalidTransformException
  172. */
  173. public static Transform getInstance(
  174. Document doc, String algorithmURI, NodeList contextNodes)
  175. throws InvalidTransformException {
  176. return new Transform(doc, algorithmURI, contextNodes);
  177. }
  178. /**
  179. * Initalizes for this {@link Transform}.
  180. */
  181. public static void init() {
  182. if (!alreadyInitialized) {
  183. transformClassHash = new HashMap(10);
  184. alreadyInitialized = true;
  185. }
  186. }
  187. /**
  188. * Registers implementing class of the Transform algorithm with algorithmURI
  189. *
  190. * @param algorithmURI algorithmURI URI representation of
  191. * <code>Transform algorithm</code> will be specified as parameter of
  192. * {@link #getInstance(Document, String)}, when generate. </br>
  193. * @param implementingClass <code>implementingClass</code> the implementing
  194. * class of {@link TransformSpi}
  195. * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI
  196. * is already registered
  197. */
  198. public static void register(String algorithmURI, String implementingClass)
  199. throws AlgorithmAlreadyRegisteredException {
  200. // are we already registered?
  201. Class registeredClass = getImplementingClass(algorithmURI);
  202. if ((registeredClass != null) ) {
  203. Object exArgs[] = { algorithmURI, registeredClass };
  204. throw new AlgorithmAlreadyRegisteredException(
  205. "algorithm.alreadyRegistered", exArgs);
  206. }
  207. try {
  208. transformClassHash.put
  209. (algorithmURI, ClassLoaderUtils.loadClass(implementingClass, Transform.class));
  210. } catch (ClassNotFoundException e) {
  211. throw new RuntimeException(e);
  212. }
  213. }
  214. /**
  215. * Returns the URI representation of Transformation algorithm
  216. *
  217. * @return the URI representation of Transformation algorithm
  218. */
  219. public String getURI() {
  220. return this._constructionElement.getAttributeNS
  221. (null, Constants._ATT_ALGORITHM);
  222. }
  223. /**
  224. * Transforms the input, and generates {@link XMLSignatureInput} as output.
  225. *
  226. * @param input input {@link XMLSignatureInput} which can supplied Octet
  227. * Stream and NodeSet as Input of Transformation
  228. * @return the {@link XMLSignatureInput} class as the result of
  229. * transformation
  230. * @throws CanonicalizationException
  231. * @throws IOException
  232. * @throws InvalidCanonicalizerException
  233. * @throws TransformationException
  234. */
  235. public XMLSignatureInput performTransform(XMLSignatureInput input)
  236. throws IOException, CanonicalizationException,
  237. InvalidCanonicalizerException, TransformationException {
  238. XMLSignatureInput result = null;
  239. try {
  240. result = transformSpi.enginePerformTransform(input, this);
  241. } catch (ParserConfigurationException ex) {
  242. Object exArgs[] = { this.getURI(), "ParserConfigurationException" };
  243. throw new CanonicalizationException(
  244. "signature.Transform.ErrorDuringTransform", exArgs, ex);
  245. } catch (SAXException ex) {
  246. Object exArgs[] = { this.getURI(), "SAXException" };
  247. throw new CanonicalizationException(
  248. "signature.Transform.ErrorDuringTransform", exArgs, ex);
  249. }
  250. return result;
  251. }
  252. /**
  253. * Transforms the input, and generates {@link XMLSignatureInput} as output.
  254. *
  255. * @param input input {@link XMLSignatureInput} which can supplied Octect
  256. * Stream and NodeSet as Input of Transformation
  257. * @param os where to output the result of the last transformation
  258. * @return the {@link XMLSignatureInput} class as the result of
  259. * transformation
  260. * @throws CanonicalizationException
  261. * @throws IOException
  262. * @throws InvalidCanonicalizerException
  263. * @throws TransformationException
  264. */
  265. public XMLSignatureInput performTransform(XMLSignatureInput input,
  266. OutputStream os) throws IOException, CanonicalizationException,
  267. InvalidCanonicalizerException, TransformationException {
  268. XMLSignatureInput result = null;
  269. try {
  270. result = transformSpi.enginePerformTransform(input, os, this);
  271. } catch (ParserConfigurationException ex) {
  272. Object exArgs[] = { this.getURI(), "ParserConfigurationException" };
  273. throw new CanonicalizationException(
  274. "signature.Transform.ErrorDuringTransform", exArgs, ex);
  275. } catch (SAXException ex) {
  276. Object exArgs[] = { this.getURI(), "SAXException" };
  277. throw new CanonicalizationException(
  278. "signature.Transform.ErrorDuringTransform", exArgs, ex);
  279. }
  280. return result;
  281. }
  282. /**
  283. * Method getImplementingClass
  284. *
  285. * @param URI
  286. * @return The name of the class implementing the URI.
  287. */
  288. private static Class getImplementingClass(String URI) {
  289. return (Class) transformClassHash.get(URI);
  290. }
  291. private static TransformSpi getTransformSpi(String URI)
  292. throws InvalidTransformException {
  293. try {
  294. Object value = transformSpiHash.get(URI);
  295. if (value != null) {
  296. return (TransformSpi) value;
  297. }
  298. Class cl = (Class) transformClassHash.get(URI);
  299. if (cl != null) {
  300. TransformSpi tr = (TransformSpi) cl.newInstance();
  301. transformSpiHash.put(URI, tr);
  302. return tr;
  303. }
  304. } catch (InstantiationException ex) {
  305. Object exArgs[] = { URI };
  306. throw new InvalidTransformException(
  307. "signature.Transform.UnknownTransform", exArgs, ex);
  308. } catch (IllegalAccessException ex) {
  309. Object exArgs[] = { URI };
  310. throw new InvalidTransformException(
  311. "signature.Transform.UnknownTransform", exArgs, ex);
  312. }
  313. return null;
  314. }
  315. /** @inheritDoc */
  316. public String getBaseLocalName() {
  317. return Constants._TAG_TRANSFORM;
  318. }
  319. }