View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.ws.security;
21  
22  import java.lang.reflect.Field;
23  import java.security.AccessController;
24  import java.security.PrivilegedAction;
25  import java.security.PrivilegedExceptionAction;
26  import java.security.Provider;
27  import java.security.Security;
28  import java.util.HashMap;
29  import java.util.Map;
30  
31  import javax.xml.namespace.QName;
32  
33  import org.apache.ws.security.action.Action;
34  import org.apache.ws.security.processor.Processor;
35  import org.apache.ws.security.util.Loader;
36  import org.apache.ws.security.util.UUIDGenerator;
37  import org.apache.ws.security.validate.Validator;
38  import org.apache.xml.security.utils.XMLUtils;
39  
40  /**
41   * WSSConfig <p/> Carries configuration data so the WSS4J spec compliance can be
42   * modified in runtime. Configure an instance of this object only if you need
43   * WSS4J to emulate certain industry clients or previous OASIS specifications
44   * for WS-Security interoperability testing purposes. <p/> The default settings
45   * follow the latest OASIS and changing anything might violate the OASIS specs.
46   * <p/> <b>WARNING: changing the default settings will break the compliance with
47   * the latest specs. Do this only if you know what you are doing.</b> <p/>
48   * 
49   * @author Rami Jaamour (rjaamour@parasoft.com)
50   * @author Werner Dittmann (werner@apache.org)
51   */
52  public class WSSConfig {
53      
54      private static final org.apache.commons.logging.Log LOG = 
55          org.apache.commons.logging.LogFactory.getLog(WSSConfig.class);
56  
57      /**
58       * The default collection of actions supported by the toolkit.
59       */
60      private static final Map<Integer, Class<?>> DEFAULT_ACTIONS;
61      static {
62          final Map<Integer, Class<?>> tmp = new HashMap<Integer, Class<?>>();
63          try {
64              tmp.put(
65                  Integer.valueOf(WSConstants.UT),
66                  org.apache.ws.security.action.UsernameTokenAction.class
67              );
68              tmp.put(
69                  Integer.valueOf(WSConstants.ENCR),
70                  org.apache.ws.security.action.EncryptionAction.class
71              );
72              tmp.put(
73                  Integer.valueOf(WSConstants.SIGN),
74                  org.apache.ws.security.action.SignatureAction.class
75              );
76              tmp.put(
77                  Integer.valueOf(WSConstants.ST_SIGNED),
78                  org.apache.ws.security.action.SAMLTokenSignedAction.class
79              );
80              tmp.put(
81                  Integer.valueOf(WSConstants.ST_UNSIGNED),
82                  org.apache.ws.security.action.SAMLTokenUnsignedAction.class
83              );
84              tmp.put(
85                  Integer.valueOf(WSConstants.TS),
86                  org.apache.ws.security.action.TimestampAction.class
87              );
88              tmp.put(
89                  Integer.valueOf(WSConstants.UT_SIGN),
90                  org.apache.ws.security.action.UsernameTokenSignedAction.class
91              );
92              tmp.put(
93                  Integer.valueOf(WSConstants.SC),
94                  org.apache.ws.security.action.SignatureConfirmationAction.class
95              );
96          } catch (final Exception ex) {
97              if (LOG.isDebugEnabled()) {
98                  LOG.debug(ex.getMessage(), ex);
99              }
100         }
101         DEFAULT_ACTIONS = java.util.Collections.unmodifiableMap(tmp);
102     }
103 
104     /**
105      * The default collection of processors supported by the toolkit
106      */
107     private static final Map<QName, Class<?>> DEFAULT_PROCESSORS;
108     static {
109         final Map<QName, Class<?>> tmp = new HashMap<QName, Class<?>>();
110         try {
111             tmp.put(
112                 WSSecurityEngine.SAML_TOKEN,
113                 org.apache.ws.security.processor.SAMLTokenProcessor.class
114             );
115             tmp.put(
116                 WSSecurityEngine.SAML2_TOKEN,
117                 org.apache.ws.security.processor.SAMLTokenProcessor.class
118             );
119             tmp.put(
120                 WSSecurityEngine.ENCRYPTED_KEY,
121                 org.apache.ws.security.processor.EncryptedKeyProcessor.class
122             );
123             tmp.put(
124                 WSSecurityEngine.SIGNATURE,
125                 org.apache.ws.security.processor.SignatureProcessor.class
126             );
127             tmp.put(
128                 WSSecurityEngine.TIMESTAMP,
129                 org.apache.ws.security.processor.TimestampProcessor.class
130             );
131             tmp.put(
132                 WSSecurityEngine.USERNAME_TOKEN,
133                 org.apache.ws.security.processor.UsernameTokenProcessor.class
134             );
135             tmp.put(
136                 WSSecurityEngine.REFERENCE_LIST,
137                 org.apache.ws.security.processor.ReferenceListProcessor.class
138             );
139             tmp.put(
140                 WSSecurityEngine.SIGNATURE_CONFIRMATION,
141                 org.apache.ws.security.processor.SignatureConfirmationProcessor.class
142             );
143             tmp.put(
144                 WSSecurityEngine.DERIVED_KEY_TOKEN_05_02,
145                 org.apache.ws.security.processor.DerivedKeyTokenProcessor.class
146             );
147             tmp.put(
148                 WSSecurityEngine.DERIVED_KEY_TOKEN_05_12,
149                 tmp.get(WSSecurityEngine.DERIVED_KEY_TOKEN_05_02)
150             );
151             tmp.put(
152                 WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_02,
153                 org.apache.ws.security.processor.SecurityContextTokenProcessor.class
154             );
155             tmp.put(
156                 WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_12,
157                 tmp.get(WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_02)
158             );
159             tmp.put(
160                 WSSecurityEngine.BINARY_TOKEN,
161                 org.apache.ws.security.processor.BinarySecurityTokenProcessor.class
162             );
163             tmp.put(
164                 WSSecurityEngine.ENCRYPTED_DATA,
165                 org.apache.ws.security.processor.EncryptedDataProcessor.class
166             );
167         } catch (final Exception ex) {
168             if (LOG.isDebugEnabled()) {
169                 LOG.debug(ex.getMessage(), ex);
170             }
171         }
172         DEFAULT_PROCESSORS = java.util.Collections.unmodifiableMap(tmp);
173     }
174     
175     /**
176      * The default collection of validators supported by the toolkit
177      */
178     private static final Map<QName, Class<?>> DEFAULT_VALIDATORS;
179     static {
180         final Map<QName, Class<?>> tmp = new HashMap<QName, Class<?>>();
181         try {
182             tmp.put(
183                 WSSecurityEngine.SAML_TOKEN,
184                 org.apache.ws.security.validate.SamlAssertionValidator.class
185             );
186             tmp.put(
187                 WSSecurityEngine.SAML2_TOKEN,
188                 org.apache.ws.security.validate.SamlAssertionValidator.class
189             );
190             tmp.put(
191                 WSSecurityEngine.SIGNATURE,
192                 org.apache.ws.security.validate.SignatureTrustValidator.class
193             );
194             tmp.put(
195                 WSSecurityEngine.TIMESTAMP,
196                 org.apache.ws.security.validate.TimestampValidator.class
197             );
198             tmp.put(
199                 WSSecurityEngine.USERNAME_TOKEN,
200                 org.apache.ws.security.validate.UsernameTokenValidator.class
201             );
202         } catch (final Exception ex) {
203             if (LOG.isDebugEnabled()) {
204                 LOG.debug(ex.getMessage(), ex);
205             }
206         }
207         DEFAULT_VALIDATORS = java.util.Collections.unmodifiableMap(tmp);
208     }
209 
210     protected boolean wsiBSPCompliant = true;
211 
212     /**
213      * Set the timestamp precision mode. If set to <code>true</code> then use
214      * timestamps with milliseconds, otherwise omit the milliseconds. As per XML
215      * Date/Time specification the default is to include the milliseconds.
216      */
217     protected boolean precisionInMilliSeconds = true;
218 
219     protected boolean enableSignatureConfirmation = false;
220 
221     /**
222      * If set to true then the timestamp handling will throw an exception if the
223      * timestamp contains an expires element and the semantics are expired.
224      * 
225      * If set to false, no exception will be thrown, even if the semantics are
226      * expired.
227      */
228     protected boolean timeStampStrict = true;
229     
230     /**
231      * If this value is not null, then username token handling will throw an 
232      * exception if the password type of the Username Token does not match this value
233      */
234     protected String requiredPasswordType = null;
235     
236     /**
237      * This variable controls whether a UsernameToken with no password element is allowed. 
238      * The default value is "false". Set it to "true" to allow deriving keys from UsernameTokens 
239      * or to support UsernameTokens for purposes other than authentication.
240      */
241     protected boolean allowUsernameTokenNoPassword = false;
242     
243     /**
244      * The time in seconds between creation and expiry for a Timestamp. The default
245      * is 300 seconds (5 minutes).
246      */
247     protected int timeStampTTL = 300;
248     
249     /**
250      * The time in seconds in the future within which the Created time of an incoming 
251      * Timestamp is valid. The default is 60 seconds.
252      */
253     protected int timeStampFutureTTL = 60;
254     
255     /**
256      * The time in seconds between creation and expiry for a UsernameToken Created
257      * element. The default is 300 seconds (5 minutes).
258      */
259     protected int utTTL = 300;
260     
261     /**
262      * The time in seconds in the future within which the Created time of an incoming 
263      * UsernameToken is valid. The default is 60 seconds.
264      */
265     protected int utFutureTTL = 60;
266     
267     /**
268      * This variable controls whether types other than PasswordDigest or PasswordText
269      * are allowed when processing UsernameTokens. 
270      * 
271      * By default this is set to false so that the user doesn't have to explicitly
272      * reject custom token types in the callback handler.
273      */
274     protected boolean handleCustomPasswordTypes = false;
275     
276     /**
277      * This variable controls whether (wsse) namespace qualified password types are
278      * accepted when processing UsernameTokens.
279      * 
280      * By default this is set to false.
281      */
282     protected boolean allowNamespaceQualifiedPasswordTypes = false;
283     
284     /**
285      * The secret key length to be used for UT_SIGN.
286      */
287     protected int secretKeyLength = WSConstants.WSE_DERIVED_KEY_LEN;
288 
289     /**
290      * Whether the password should be treated as a binary value.  This
291      * is needed to properly handle password equivalence for UsernameToken
292      * passwords.  Binary passwords are Base64 encoded so they can be
293      * treated as strings in most places, but when the password digest
294      * is calculated or a key is derived from the password, the password
295      * will be Base64 decoded before being used. This is most useful for
296      * hashed passwords as password equivalents.
297      *
298      * See https://issues.apache.org/jira/browse/WSS-239
299      */
300     protected boolean passwordsAreEncoded = false;
301     
302     /**
303      * The default wsu:Id allocator is a simple "start at 1 and increment up"
304      * thing that is very fast.
305      */
306     public static final WsuIdAllocator DEFAULT_ID_ALLOCATOR = new WsuIdAllocator() {
307         int i;
308         private synchronized String next() {
309             return Integer.toString(++i);
310         }
311         public String createId(String prefix, Object o) {
312             if (prefix == null) {
313                 return "_" + next();
314             }
315             return prefix + next();
316         }
317 
318         public String createSecureId(String prefix, Object o) {
319             if (prefix == null) {
320                 return UUIDGenerator.getUUID();
321             }
322             return prefix + UUIDGenerator.getUUID();
323         }
324     };
325     protected WsuIdAllocator idAllocator = DEFAULT_ID_ALLOCATOR;
326     
327     /**
328      * The known actions. This map is of the form <Integer, Class<?>> or 
329      * <Integer, Action>. 
330      * The known actions are initialized from a set of defaults,
331      * but the list may be modified via the setAction operations.
332      */
333     private final Map<Integer, Object> actionMap = 
334         new HashMap<Integer, Object>(DEFAULT_ACTIONS);
335 
336     /**
337      * The known processors. This map is of the form <QName, Class<?>> or
338      * <QName, Processor>.
339      * The known processors are initialized from a set of defaults,
340      * but the list may be modified via the setProcessor operations.
341      */
342     private final Map<QName, Object> processorMap = 
343         new HashMap<QName, Object>(DEFAULT_PROCESSORS);
344     
345     /**
346      * The known validators. This map is of the form <QName, Class<?>> or
347      * <QName, Validator>.
348      * The known validators are initialized from a set of defaults,
349      * but the list may be modified via the setValidator operations.
350      */
351     private final Map<QName, Object> validatorMap = 
352         new HashMap<QName, Object>(DEFAULT_VALIDATORS);
353     
354     /**
355      * a static boolean flag that determines whether default JCE providers
356      * should be added at the time of construction.
357      *
358      * These providers, and the order in which they are added, can interfere
359      * with some JVMs (such as IBMs).
360      */
361     private static boolean addJceProviders = true;
362     
363     /**
364      * a boolean flag to record whether we have already been statically
365      * initialized.  This flag prevents repeated and unnecessary calls
366      * to static initialization code at construction time.
367      */
368     private static boolean staticallyInitialized = false;
369     
370     /**
371      * Set the value of the internal addJceProviders flag.  This flag
372      * turns on (or off) automatic registration of known JCE providers
373      * that provide necessary cryptographic algorithms for use with WSS4J.
374      * By default, this flag is true.  You may wish (or need) to initialize 
375      * the JCE manually, e.g., in some JVMs.
376      */
377     public static void setAddJceProviders(boolean value) {
378         addJceProviders = value;
379     }
380     
381     private static void setXmlSecIgnoreLineBreak() {
382         //really need to make sure ignoreLineBreaks is set to
383         boolean wasSet = false;
384         try {
385             // Don't override if it was set explicitly
386             wasSet = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
387                 public Boolean run() {
388                     String lineBreakPropName = "org.apache.xml.security.ignoreLineBreaks";
389                     if (System.getProperty(lineBreakPropName) == null) {
390                         System.setProperty(lineBreakPropName, "true");
391                         return false;
392                     }
393                     return true; 
394                 }
395             });
396         } catch (Throwable t) { //NOPMD
397             //ignore
398         }
399         org.apache.xml.security.Init.init();
400         if (!wasSet) {
401             try {
402                 AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
403                     public Boolean run() throws Exception {
404                         Field f = XMLUtils.class.getDeclaredField("ignoreLineBreaks");
405                         f.setAccessible(true);
406                         f.set(null, Boolean.TRUE);
407                         return false;
408                     }
409                 });
410             } catch (Throwable t) { //NOPMD
411                 //ignore
412             }
413         }
414     }
415     
416     public static synchronized void init() {
417         if (!staticallyInitialized) {
418             if (addJceProviders) {
419                 setXmlSecIgnoreLineBreak();
420                 AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
421                     public Boolean run() {
422                         addXMLDSigRI();
423                         addJceProvider("BC", "org.bouncycastle.jce.provider.BouncyCastleProvider");
424                         Security.removeProvider("STRTransform");
425                         appendJceProvider(
426                             "STRTransform", new org.apache.ws.security.transform.STRTransformProvider()
427                         );
428                         
429                         return true;
430                     }
431                 });
432             }
433             staticallyInitialized = true;
434         }
435     }
436     
437     private static void addXMLDSigRI() {
438         try {
439             addXMLDSigRIInternal();
440         } catch (Throwable t) {
441             //ignore - may be a NoClassDefFound if XMLDSigRI isn't avail
442             return;
443         }
444     }
445     
446     public static void addXMLDSigRIInternal() {
447         addJceProvider("ApacheXMLDSig", SantuarioUtil.getSantuarioProvider());
448     }
449 
450     /**
451      * @return a new WSSConfig instance configured with the default values
452      */
453     public static WSSConfig getNewInstance() {
454         init();
455         return new WSSConfig();
456     }
457 
458     /**
459      * Checks if we are in WS-I Basic Security Profile compliance mode
460      * 
461      * @return whether we are in WS-I Basic Security Profile compliance mode
462      */
463     public boolean isWsiBSPCompliant() {
464         return wsiBSPCompliant;
465     }
466 
467     /**
468      * Set the WS-I Basic Security Profile compliance mode. The default is true.
469      * 
470      * @param wsiBSPCompliant
471      */
472     public void setWsiBSPCompliant(boolean wsiBSPCompliant) {
473         this.wsiBSPCompliant = wsiBSPCompliant;
474     }
475 
476     /**
477      * Checks if we need to use milliseconds in timestamps
478      * 
479      * @return whether to use precision in milliseconds for timestamps
480      */
481     public boolean isPrecisionInMilliSeconds() {
482         return precisionInMilliSeconds;
483     }
484 
485     /**
486      * Set the precision in milliseconds for timestamps
487      * 
488      * @param precisionInMilliSeconds whether to use precision in milliseconds for timestamps
489      */
490     public void setPrecisionInMilliSeconds(boolean precisionInMilliSeconds) {
491         this.precisionInMilliSeconds = precisionInMilliSeconds;
492     }
493 
494     /**
495      * @return Returns the enableSignatureConfirmation.
496      */
497     public boolean isEnableSignatureConfirmation() {
498         return enableSignatureConfirmation;
499     }
500 
501     /**
502      * @param enableSignatureConfirmation
503      *            The enableSignatureConfirmation to set.
504      */
505     public void setEnableSignatureConfirmation(boolean enableSignatureConfirmation) {
506         this.enableSignatureConfirmation = enableSignatureConfirmation;
507     }
508     
509     /**
510      * @param handleCustomTypes 
511      * whether to handle custom UsernameToken password types or not
512      */
513     public void setHandleCustomPasswordTypes(boolean handleCustomTypes) {
514         this.handleCustomPasswordTypes = handleCustomTypes;
515     }
516     
517     /**
518      * @return whether custom UsernameToken password types are allowed or not
519      */
520     public boolean getHandleCustomPasswordTypes() {
521         return handleCustomPasswordTypes;
522     }
523     
524     /**
525      * @param allowNamespaceQualifiedTypes
526      * whether (wsse) namespace qualified password types are accepted or not
527      */
528     public void setAllowNamespaceQualifiedPasswordTypes(boolean allowNamespaceQualifiedTypes) {
529         allowNamespaceQualifiedPasswordTypes = allowNamespaceQualifiedTypes;
530     }
531     
532     /**
533      * @return whether (wsse) namespace qualified password types are accepted or not
534      */
535     public boolean getAllowNamespaceQualifiedPasswordTypes() {
536         return allowNamespaceQualifiedPasswordTypes;
537     }
538     
539     /**
540      * @return Returns if we shall throw an exception on expired request
541      *         semantic
542      */
543     public boolean isTimeStampStrict() {
544         return timeStampStrict;
545     }
546 
547     /**
548      * @param timeStampStrict
549      *            If true throw an exception on expired request semantic
550      */
551     public void setTimeStampStrict(boolean timeStampStrict) {
552         this.timeStampStrict = timeStampStrict;
553     }
554     
555     /**
556      * @return the required password type when processing a UsernameToken
557      */
558     public String getRequiredPasswordType() {
559         return requiredPasswordType;
560     }
561 
562     /**
563      * @param requiredPasswordType The required password type when processing
564      * a Username Token.
565      */
566     public void setRequiredPasswordType(String requiredPasswordType) {
567         this.requiredPasswordType = requiredPasswordType;
568     }
569     
570     /**
571      * @return Returns the TTL of a Timestamp in seconds
572      */
573     public int getTimeStampTTL() {
574         return timeStampTTL;
575     }
576 
577     /**
578      * @param timeStampTTL The new value for timeStampTTL
579      */
580     public void setTimeStampTTL(int timeStampTTL) {
581         this.timeStampTTL = timeStampTTL;
582     }
583     
584     /**
585      * @return Returns the Future TTL of a Timestamp in seconds
586      */
587     public int getTimeStampFutureTTL() {
588         return timeStampFutureTTL;
589     }
590 
591     /**
592      * @param timeStampFutureTTL the new value for timeStampFutureTTL
593      */
594     public void setTimeStampFutureTTL(int timeStampFutureTTL) {
595         this.timeStampFutureTTL = timeStampFutureTTL;
596     }
597     
598     /**
599      * Set the secret key length to be used for UT_SIGN.
600      */
601     public void setSecretKeyLength(int length) {
602         secretKeyLength = length;
603     }
604     
605     /**
606      * Get the secret key length to be used for UT_SIGN.
607      */
608     public int getSecretKeyLength() {
609         return secretKeyLength;
610     }
611     
612     /**
613      * @param passwordsAreEncoded
614      * whether passwords are encoded
615      */
616     public void setPasswordsAreEncoded(boolean passwordsAreEncoded) {
617         this.passwordsAreEncoded = passwordsAreEncoded;
618     }
619     
620     /**
621      * @return whether passwords are encoded
622      */
623     public boolean getPasswordsAreEncoded() {
624         return passwordsAreEncoded;
625     }
626     
627     /**
628      * @return Returns the WsuIdAllocator used to generate wsu:Id attributes
629      */
630     public WsuIdAllocator getIdAllocator() {
631         return idAllocator;
632     }
633 
634     public void setIdAllocator(WsuIdAllocator idAllocator) {
635         this.idAllocator = idAllocator;
636     }
637     
638     /**
639      * Associate an action instance with a specific action code.
640      *
641      * This operation allows applications to supply their own
642      * actions for well-known operations.
643      * 
644      * Please note that the Action object does NOT get class-loaded per invocation, and so
645      * it is up to the implementing class to ensure that it is thread-safe.
646      */
647     public Class<?> setAction(int code, Action action) {
648         Object result = actionMap.put(Integer.valueOf(code), action);
649         if (result instanceof Class<?>) {
650             return (Class<?>)result;
651         } else if (result instanceof Action) {
652             return result.getClass();
653         }
654         return null;
655     }
656     
657     /**
658      * Associate an action instance with a specific action code.
659      *
660      * This operation allows applications to supply their own
661      * actions for well-known operations.
662      */
663     public Class<?> setAction(int code, Class<?> clazz) {
664         Object result = actionMap.put(Integer.valueOf(code), clazz);
665         if (result instanceof Class<?>) {
666             return (Class<?>)result;
667         } else if (result instanceof Action) {
668             return result.getClass();
669         }
670         return null;
671     }
672 
673     /**
674      * Lookup action
675      * 
676      * @param action
677      * @return An action class to create a security token
678      * @throws WSSecurityException
679      */
680     public Action getAction(int action) throws WSSecurityException {
681         final Object actionObject = actionMap.get(Integer.valueOf(action));
682         
683         if (actionObject instanceof Class<?>) {
684             try {
685                 return (Action)((Class<?>)actionObject).newInstance();
686             } catch (Throwable t) {
687                 if (LOG.isDebugEnabled()) {
688                     LOG.debug(t.getMessage(), t);
689                 }
690                 throw new WSSecurityException(WSSecurityException.FAILURE,
691                         "unableToLoadClass", new Object[] { ((Class<?>)actionObject).getName() }, t);
692             }
693         } else if (actionObject instanceof Action) {
694             return (Action)actionObject;
695         }
696         return null;
697     }
698     
699     /**
700      * Associate a SOAP processor name with a specified SOAP Security header
701      * element QName.  Processors registered under this QName will be
702      * called when processing header elements with the specified type.
703      * 
704      * Please note that the Processor object does NOT get class-loaded per invocation, and so
705      * it is up to the implementing class to ensure that it is thread-safe.
706      */
707     public Class<?> setProcessor(QName el, Processor processor) {
708         Object result = processorMap.put(el, processor);
709         if (result instanceof Class<?>) {
710             return (Class<?>)result;
711         } else if (result instanceof Processor) {
712             return result.getClass();
713         }
714         return null;
715     }
716     
717     /**
718      * Associate a SOAP processor name with a specified SOAP Security header
719      * element QName.  Processors registered under this QName will be
720      * called when processing header elements with the specified type.
721      */
722     public Class<?> setProcessor(QName el, Class<?> clazz) {
723         Object result = processorMap.put(el, clazz);
724         if (result instanceof Class<?>) {
725             return (Class<?>)result;
726         } else if (result instanceof Processor) {
727             return result.getClass();
728         }
729         return null;
730     }
731     
732     /**
733      * Associate a SOAP validator name with a specified SOAP Security header
734      * element QName.  Validators registered under this QName will be
735      * called when processing header elements with the specified type.
736      * 
737      * Please note that the Validator object does NOT get class-loaded per invocation, and so
738      * it is up to the implementing class to ensure that it is thread-safe.
739      */
740     public Class<?> setValidator(QName el, Validator validator) {
741         Object result = validatorMap.put(el, validator);
742         if (result instanceof Class<?>) {
743             return (Class<?>)result;
744         } else if (result instanceof Validator) {
745             return result.getClass();
746         }
747         return null;
748     }
749     
750     /**
751      * Associate a SOAP validator name with a specified SOAP Security header
752      * element QName.  validator registered under this QName will be
753      * called when processing header elements with the specified type.
754      */
755     public Class<?> setValidator(QName el, Class<?> clazz) {
756         Object result = validatorMap.put(el, clazz);
757         if (result instanceof Class<?>) {
758             return (Class<?>)result;
759         } else if (result instanceof Validator) {
760             return result.getClass();
761         }
762         return null;
763     }
764     
765     /**
766      * @return      the SOAP Validator associated with the specified
767      *              QName.  The QName is intended to refer to an element
768      *              in a SOAP security header.  This operation returns
769      *              null if there is no Validator associated with the 
770      *              specified QName.
771      */
772     public Validator getValidator(QName el) throws WSSecurityException {
773         final Object validatorObject = validatorMap.get(el);
774         
775         if (validatorObject instanceof Class<?>) {
776             try {
777                 return (Validator)((Class<?>)validatorObject).newInstance();
778             } catch (Throwable t) {
779                 if (LOG.isDebugEnabled()) {
780                     LOG.debug(t.getMessage(), t);
781                 }
782                 throw new WSSecurityException(WSSecurityException.FAILURE,
783                     "unableToLoadClass", new Object[] { ((Class<?>)validatorObject).getName() }, t);
784             }
785         } else if (validatorObject instanceof Validator) {
786             return (Validator)validatorObject;
787         }
788         return null;
789     }
790     
791     /**
792      * @return      the SOAP processor associated with the specified
793      *              QName.  The QName is intended to refer to an element
794      *              in a SOAP security header.  This operation returns
795      *              null if there is no processor associated with the 
796      *              specified QName.
797      */
798     public Processor getProcessor(QName el) throws WSSecurityException {
799         final Object processorObject = processorMap.get(el);
800         
801         if (processorObject instanceof Class<?>) {
802             try {
803                 return (Processor)((Class<?>)processorObject).newInstance();
804             } catch (Throwable t) {
805                 if (LOG.isDebugEnabled()) {
806                     LOG.debug(t.getMessage(), t);
807                 }
808                 throw new WSSecurityException(WSSecurityException.FAILURE,
809                         "unableToLoadClass", new Object[] { ((Class<?>)processorObject).getName() }, t);
810             }
811         } else if (processorObject instanceof Processor) {
812             return (Processor)processorObject;
813         }
814         return null;
815     }
816 
817     /**
818      * Add a new JCE security provider to use for WSS4J, of the specified name and class. Return
819      * either the name of the previously loaded provider, the name of the new loaded provider, or
820      * null if there's an exception in loading the provider. Add the provider either after the SUN
821      * provider (see WSS-99), or the IBMJCE provider. Otherwise fall back to the old behaviour of
822      * inserting the provider in position 2.
823      * 
824      * @param name
825      *            The name string of the provider (this may not be the real name of the provider)
826      * @param className
827      *            Name of the class the implements the provider. This class must
828      *            be a subclass of <code>java.security.Provider</code>
829      * 
830      * @return Returns the actual name of the provider that was loaded
831      */
832     public static String addJceProvider(String name, String className) {
833         Provider currentProvider = Security.getProvider(name);
834         if (currentProvider == null) {
835             try {
836                 Class<? extends Provider> clazz = Loader.loadClass(className, false, Provider.class);
837                 Provider provider = clazz.newInstance();
838                 return addJceProvider(name, provider);
839             } catch (Throwable t) {
840                 if (LOG.isDebugEnabled()) {
841                     LOG.debug("The provider " + name + " could not be added: " + t.getMessage(), t);
842                 }
843                 return null;
844             }
845         }
846         return currentProvider.getName();
847     }
848     
849     /**
850      * Add a new JCE security provider to use for WSS4J, of the specified name and class. Return
851      * either the name of the previously loaded provider, the name of the new loaded provider, or
852      * null if there's an exception in loading the provider. Add the provider either after the SUN
853      * provider (see WSS-99), or the IBMJCE provider. Otherwise fall back to the old behaviour of
854      * inserting the provider in position 2.
855      * 
856      * @param name
857      *            The name string of the provider (this may not be the real name of the provider)
858      * @param provider
859      *            A subclass of <code>java.security.Provider</code>
860      * 
861      * @return Returns the actual name of the provider that was loaded
862      */
863     public static String addJceProvider(String name, Provider provider) {
864         Provider currentProvider = Security.getProvider(name);
865         if (currentProvider == null) {
866             try {
867                 //
868                 // Install the provider after the SUN provider (see WSS-99)
869                 // Otherwise fall back to the old behaviour of inserting
870                 // the provider in position 2. For AIX, install it after
871                 // the IBMJCE provider.
872                 //
873                 int ret = 0;
874                 Provider[] provs = Security.getProviders();
875                 for (int i = 0; i < provs.length; i++) {
876                     if ("SUN".equals(provs[i].getName())
877                         || "IBMJCE".equals(provs[i].getName())) {
878                         ret = Security.insertProviderAt(provider, i + 2);
879                         break;
880                     }
881                 }
882                 if (ret == 0) {
883                     ret = Security.insertProviderAt(provider, 2);
884                 }
885                 if (LOG.isDebugEnabled()) {
886                     LOG.debug(
887                         "The provider " + provider.getName() + " - "
888                          + provider.getVersion() + " was added at position: " + ret
889                     );
890                 }
891                 return provider.getName();
892             } catch (Throwable t) {
893                 if (LOG.isDebugEnabled()) {
894                     LOG.debug("The provider " + name + " could not be added: " + t.getMessage(), t);
895                 }
896                 return null;
897             }
898         }
899         return currentProvider.getName();
900     }
901     
902     
903     /**
904      * Add a new JCE security provider to use for WSS4J, of the specified name and class. Return
905      * either the name of the previously loaded provider, the name of the new loaded provider, or
906      * null if there's an exception in loading the provider. Append the provider to the provider
907      * list.
908      * 
909      * @param name
910      *            The name string of the provider (this may not be the real name of the provider)
911      * @param className
912      *            Name of the class the implements the provider. This class must
913      *            be a subclass of <code>java.security.Provider</code>
914      * 
915      * @return Returns the actual name of the provider that was loaded
916      */
917     public static String appendJceProvider(String name, String className) {
918         Provider currentProvider = Security.getProvider(name);
919         if (currentProvider == null) {
920             try {
921                 Class<? extends Provider> clazz = Loader.loadClass(className, false, Provider.class);
922                 Provider provider = clazz.newInstance();
923                 
924                 int ret = Security.addProvider(provider);
925                 if (LOG.isDebugEnabled()) {
926                     LOG.debug(
927                         "The provider " + provider.getName() 
928                         + " was added at position: " + ret
929                     );
930                 }
931                 return provider.getName();
932             } catch (Throwable t) {
933                 if (LOG.isDebugEnabled()) {
934                     LOG.debug("The provider " + name + " could not be added: " + t.getMessage(), t);
935                 }
936                 return null;
937             }
938         }
939         return currentProvider.getName();
940     }
941     
942     /**
943      * Add a new JCE security provider to use for WSS4J, of the specified name and class. Return
944      * either the name of the previously loaded provider, the name of the new loaded provider, or
945      * null if there's an exception in loading the provider. Append the provider to the provider
946      * list.
947      * 
948      * @param name
949      *            The name string of the provider (this may not be the real name of the provider)
950      * @param provider
951      *            A subclass of <code>java.security.Provider</code>
952      * 
953      * @return Returns the actual name of the provider that was loaded
954      */
955     public static String appendJceProvider(String name, Provider provider) {
956         Provider currentProvider = Security.getProvider(name);
957         if (currentProvider == null) {
958             try {
959                 int ret = Security.addProvider(provider);
960                 if (LOG.isDebugEnabled()) {
961                     LOG.debug(
962                         "The provider " + provider.getName() 
963                         + " was added at position: " + ret
964                     );
965                 }
966                 return provider.getName();
967             } catch (Throwable t) {
968                 if (LOG.isDebugEnabled()) {
969                     LOG.debug("The provider " + name + " could not be added: " + t.getMessage(), t);
970                 }
971                 return null;
972             }
973         }
974         return currentProvider.getName();
975     }
976 
977     public boolean isAllowUsernameTokenNoPassword() {
978         return allowUsernameTokenNoPassword;
979     }
980 
981     public void setAllowUsernameTokenNoPassword(boolean allowUsernameTokenNoPassword) {
982         this.allowUsernameTokenNoPassword = allowUsernameTokenNoPassword;
983     }
984 
985     public int getUtTTL() {
986         return utTTL;
987     }
988 
989     public void setUtTTL(int utTTL) {
990         this.utTTL = utTTL;
991     }
992 
993     public int getUtFutureTTL() {
994         return utFutureTTL;
995     }
996 
997     public void setUtFutureTTL(int utFutureTTL) {
998         this.utFutureTTL = utFutureTTL;
999     }
1000     
1001 }