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.credential;
18
19 import java.util.List;
20
21 import org.opensaml.xml.Configuration;
22 import org.opensaml.xml.XMLObject;
23 import org.opensaml.xml.security.SecurityException;
24 import org.opensaml.xml.security.keyinfo.KeyInfoGenerator;
25 import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
26 import org.opensaml.xml.security.keyinfo.KeyInfoHelper;
27 import org.opensaml.xml.signature.KeyInfo;
28 import org.opensaml.xml.signature.impl.KeyInfoBuilder;
29 import org.opensaml.xml.util.DatatypeHelper;
30
31
32 /**
33 * A factory implementation which produces instances of {@link KeyInfoGenerator} capable of
34 * handling the information contained within a {@link Credential}.
35 *
36 * All boolean options default to false.
37 */
38 public class BasicKeyInfoGeneratorFactory implements KeyInfoGeneratorFactory {
39
40 /** The set of options configured for the factory. */
41 private BasicOptions options;
42
43 /**
44 * Constructor.
45 *
46 * All boolean options are initialzed as false;
47 */
48 public BasicKeyInfoGeneratorFactory() {
49 options = newOptions();
50 }
51
52 /** {@inheritDoc} */
53 public Class<? extends Credential> getCredentialType() {
54 return Credential.class;
55 }
56
57 /** {@inheritDoc} */
58 public boolean handles(Credential credential) {
59 // This top-level class can handle any Credential type, with output limited to basic Credential information
60 return true;
61 }
62
63 /** {@inheritDoc} */
64 public KeyInfoGenerator newInstance() {
65 //TODO lock options during cloning ?
66 BasicOptions newOptions = options.clone();
67 return new BasicKeyInfoGenerator(newOptions);
68 }
69
70 /**
71 * Get the option to emit the entity ID value in a Credential as a KeyName element.
72 *
73 * @return return the option value
74 */
75 public boolean emitEntityIDAsKeyName() {
76 return options.emitEntityIDAsKeyName;
77 }
78
79 /**
80 * Set the option to emit the entity ID value in a Credential as a KeyName element.
81 *
82 * @param newValue the new option value to set
83 */
84 public void setEmitEntityIDAsKeyName(boolean newValue) {
85 options.emitEntityIDAsKeyName = newValue;
86 }
87
88 /**
89 * Get the option to emit key names found in a Credential as KeyName elements.
90 *
91 * @return the option value
92 */
93 public boolean emitKeyNames() {
94 return options.emitKeyNames;
95 }
96
97 /**
98 * Set the option to emit key names found in a Credential as KeyName elements.
99 *
100 * @param newValue the new option value to set
101 */
102 public void setEmitKeyNames(boolean newValue) {
103 options.emitKeyNames = newValue;
104 }
105
106 /**
107 * Get the option to emit the value of {@link Credential#getPublicKey()} as a KeyValue element.
108 *
109 * @return the option value
110 */
111 public boolean emitPublicKeyValue() {
112 return options.emitPublicKeyValue;
113 }
114
115 /**
116 * Set the option to emit the value of {@link Credential#getPublicKey()} as a KeyValue element.
117 *
118 * @param newValue the new option value to set
119 */
120 public void setEmitPublicKeyValue(boolean newValue) {
121 options.emitPublicKeyValue = newValue;
122
123 }
124
125 /**
126 * Get a new instance to hold options. Used by the top-level superclass constructor.
127 * Subclasses <strong>MUST</strong> override to produce an instance of the appropriate
128 * subclass of {@link BasicOptions}.
129 *
130 * @return a new instance of factory/generator options
131 */
132 protected BasicOptions newOptions() {
133 return new BasicOptions();
134 }
135
136 /**
137 * Get the options of this instance. Used by subclass constructors to get the options built by
138 * the top-level class constructor with {@link #newOptions()}.
139 *
140 * @return the options instance
141 */
142 protected BasicOptions getOptions() {
143 return options;
144 }
145
146 /**
147 * An implementation of {@link KeyInfoGenerator} capable of handling the information
148 * contained within a {@link Credential}.
149 */
150 public class BasicKeyInfoGenerator implements KeyInfoGenerator {
151
152 /** The set of options to be used by the generator.*/
153 private BasicOptions options;
154
155 /** Builder for KeyInfo objects. */
156 private KeyInfoBuilder keyInfoBuilder;
157
158 /**
159 * Constructor.
160 *
161 * @param newOptions the options to be used by the generator
162 */
163 protected BasicKeyInfoGenerator(BasicOptions newOptions) {
164 options = newOptions;
165 keyInfoBuilder =
166 (KeyInfoBuilder) Configuration.getBuilderFactory().getBuilder(KeyInfo.DEFAULT_ELEMENT_NAME);
167 }
168
169 /** {@inheritDoc} */
170 public KeyInfo generate(Credential credential) throws SecurityException {
171 KeyInfo keyInfo = keyInfoBuilder.buildObject();
172
173 processKeyNames(keyInfo, credential);
174 processEntityID(keyInfo, credential);
175 processPublicKey(keyInfo, credential);
176
177 List<XMLObject> children = keyInfo.getOrderedChildren();
178 if (children != null && children.size() > 0) {
179 return keyInfo;
180 } else {
181 return null;
182 }
183 }
184
185 /** Process the values of {@link Credential#getKeyNames()}.
186 *
187 * @param keyInfo the KeyInfo that is being built
188 * @param credential the Credential that is geing processed
189 */
190 protected void processKeyNames(KeyInfo keyInfo, Credential credential) {
191 if (options.emitKeyNames) {
192 for (String keyNameValue : credential.getKeyNames()) {
193 if ( ! DatatypeHelper.isEmpty(keyNameValue)) {
194 KeyInfoHelper.addKeyName(keyInfo, keyNameValue);
195 }
196 }
197 }
198 }
199
200 /** Process the value of {@link Credential#getEntityId()}.
201 *
202 * @param keyInfo the KeyInfo that is being built
203 * @param credential the Credential that is geing processed
204 */
205 protected void processEntityID(KeyInfo keyInfo, Credential credential) {
206 if (options.emitEntityIDAsKeyName) {
207 String keyNameValue = credential.getEntityId();
208 if ( ! DatatypeHelper.isEmpty(keyNameValue)) {
209 KeyInfoHelper.addKeyName(keyInfo, keyNameValue);
210 }
211 }
212 }
213
214 /** Process the value of {@link Credential#getPublicKey()}.
215 *
216 * @param keyInfo the KeyInfo that is being built
217 * @param credential the Credential that is geing processed
218 */
219 protected void processPublicKey(KeyInfo keyInfo, Credential credential) {
220 if (options.emitPublicKeyValue) {
221 if (credential.getPublicKey() != null) {
222 KeyInfoHelper.addPublicKey(keyInfo, credential.getPublicKey());
223 }
224 }
225 }
226 }
227
228 /**
229 * Options to be used in the production of a {@link KeyInfo} from a {@link Credential}.
230 */
231 protected class BasicOptions implements Cloneable {
232
233 /** Emit key names found in a Credential as KeyName elements. */
234 private boolean emitKeyNames;
235
236 /** Emit the entity ID value in a Credential as a KeyName element. */
237 private boolean emitEntityIDAsKeyName;
238
239 /** Emit the value of {@link Credential#getPublicKey()} as a KeyValue element. */
240 private boolean emitPublicKeyValue;
241
242 /** {@inheritDoc} */
243 protected BasicOptions clone() {
244 try {
245 return (BasicOptions) super.clone();
246 } catch (CloneNotSupportedException e) {
247 // we know we're cloneable, so this will never happen
248 return null;
249 }
250 }
251
252 }
253
254 }