View Javadoc

1   /*
2    * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
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.opensaml.xml.security.keyinfo;
18  
19  import org.opensaml.xml.Configuration;
20  import org.opensaml.xml.io.Marshaller;
21  import org.opensaml.xml.io.MarshallingException;
22  import org.opensaml.xml.io.Unmarshaller;
23  import org.opensaml.xml.io.UnmarshallingException;
24  import org.opensaml.xml.security.SecurityException;
25  import org.opensaml.xml.security.credential.Credential;
26  import org.opensaml.xml.signature.KeyInfo;
27  import org.w3c.dom.Element;
28  
29  /**
30   * Implementation of {@link KeyInfoGenerator} which always returns static {@link KeyInfo} data.
31   * 
32   * Note that the argument to {@link #generate(Credential)} is not used in generating the new KeyInfo,
33   * and so may be null.
34   * 
35   * If the original KeyInfo that was passed to this instance is already the child of some other
36   * XMLObject at the time {@link #generate(Credential)} is called, then a newly constructed KeyInfo
37   * object will be returned that contains the same data as the original. Otherwise, the original
38   * KeyInfo instance is returned directly.
39   * 
40   */
41  public class StaticKeyInfoGenerator implements KeyInfoGenerator {
42      
43      /** The KeyInfo object held by this generator instance. */
44      private KeyInfo keyInfo;
45      
46      /** Unmarshaller used in cloning operation. */
47      private Unmarshaller keyInfoUnmarshaller;
48      
49      /** Marshaller used in cloning operation. */
50      private Marshaller keyInfoMarshaller;
51      
52      /**
53       * Constructor.
54       *
55       * @param newKeyInfo the KeyInfo used as the basis to return new KeyInfo objects from this generator
56       */
57      public StaticKeyInfoGenerator(KeyInfo newKeyInfo) {
58          setKeyInfo(newKeyInfo);
59      }
60  
61      /** {@inheritDoc} */
62      public KeyInfo generate(Credential credential) throws SecurityException {
63          if (keyInfo.getParent() == null) {
64              return keyInfo;
65          } else {
66              return clone(keyInfo);
67          }
68      }
69      
70      /**
71       * Get the static KeyInfo object held by this generator.
72       * 
73       * @return the currently held KeyInfo object
74       */
75      public KeyInfo getKeyInfo() {
76          return keyInfo;
77      }
78      
79      /**
80       * Set the static KeyInfo object held by this generator.
81       * 
82       * @param newKeyInfo the new KeyInfo object
83       */
84      public void setKeyInfo(KeyInfo newKeyInfo) {
85          if (newKeyInfo == null) {
86              throw new IllegalArgumentException("KeyInfo may not be null");
87          }
88          keyInfo = newKeyInfo;
89      }
90      
91      /**
92       * Clone a KeyInfo and return the new object.
93       * 
94       * @param origKeyInfo the KeyInfo object to clone
95       * @return a new KeyInfo object cloned from the original
96       * @throws SecurityException thrown in there are marshalling or unmarshalling errors during cloning
97       */
98      private KeyInfo clone(KeyInfo origKeyInfo) throws SecurityException {
99          // A brute force approach to cloning:
100         //   1) marshall the original (if necessary)
101         //   2) unmarshall a new object around the cached or newly marshalled DOM.
102         //   3) ensure only one of them caches the DOM (original or marshalled)
103         Element origDOM = origKeyInfo.getDOM();
104         if (origDOM == null) {
105             try {
106                 getMarshaller().marshall(origKeyInfo);
107             } catch (MarshallingException e) {
108                 throw new SecurityException("Error marshalling the original KeyInfo during cloning", e);
109             }
110         }
111         
112         KeyInfo newKeyInfo = null;
113         try {
114             newKeyInfo = (KeyInfo) getUnmarshaller().unmarshall(origKeyInfo.getDOM());
115         } catch (UnmarshallingException e) {
116             throw new SecurityException("Error unmarshalling the new KeyInfo during cloning", e);
117         }
118         
119         // If the original had no cached DOM, go ahead and drop so this operation doesn't have any side effects.
120         // If it did have, then drop it on the new one, so isn't cached by two objects.
121         if (origDOM == null) {
122             origKeyInfo.releaseChildrenDOM(true);
123             origKeyInfo.releaseDOM();
124         } else {
125             newKeyInfo.releaseChildrenDOM(true);
126             newKeyInfo.releaseDOM();
127         }
128         
129         return newKeyInfo;
130     }
131     
132     /**
133      * Get a KeyInfo marshaller.
134      * 
135      * @return a KeyInfo marshaller
136      * @throws SecurityException thrown if there is an error obtaining the marshaller from the configuration
137      */
138     private Marshaller getMarshaller() throws SecurityException {
139         if (keyInfoMarshaller != null) {
140             return keyInfoMarshaller;
141         }
142         keyInfoMarshaller = Configuration.getMarshallerFactory().getMarshaller(KeyInfo.DEFAULT_ELEMENT_NAME);
143         if (keyInfoMarshaller == null) {
144             throw new SecurityException("Could not obtain KeyInfo marshaller from the configuration");
145         }
146         return keyInfoMarshaller;
147     }
148 
149     /**
150      * Get a KeyInfo unmarshaller.
151      * 
152      * @return a KeyInfo unmarshaller
153      * @throws SecurityException thrown if there is an error obtaining the unmarshaller from the configuration
154      */
155     private Unmarshaller getUnmarshaller() throws SecurityException {
156         if (keyInfoUnmarshaller != null) {
157             return keyInfoUnmarshaller;
158         }
159         keyInfoUnmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(KeyInfo.DEFAULT_ELEMENT_NAME);
160         if (keyInfoUnmarshaller == null) {
161             throw new SecurityException("Could not obtain KeyInfo unmarshaller from the configuration");
162         }
163         return keyInfoUnmarshaller;
164     }
165     
166 }