/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.ws.metadata.wsse;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URL;
import java.util.HashMap;
import org.jboss.logging.Logger;
import org.jboss.ws.core.utils.ResourceURL;
import org.jboss.xb.binding.JBossXBException;
import org.jboss.xb.binding.ObjectModelFactory;
import org.jboss.xb.binding.SimpleTypeBindings;
import org.jboss.xb.binding.Unmarshaller;
import org.jboss.xb.binding.UnmarshallerFactory;
import org.jboss.xb.binding.UnmarshallingContext;
import org.xml.sax.Attributes;
/**
* A JBossXB Object Model Factory that represets a JBoss WS-Security
* configuration. See the jboss-ws-security_1_0.xsd file for more info.
*
* @author <a href="mailto:jason.greene@jboss.com">Jason T. Greene</a>
* @version $Revision: 12505 $
*/
public class WSSecurityOMFactory implements ObjectModelFactory
{
public static String SERVER_RESOURCE_NAME = "jboss-wsse-server.xml";
public static String CLIENT_RESOURCE_NAME = "jboss-wsse-client.xml";
private static HashMap options = new HashMap(7);
static
{
options.put("key-store-file", "setKeyStoreFile");
options.put("key-store-type", "setKeyStoreType");
options.put("key-store-password", "setKeyStorePassword");
options.put("trust-store-file", "setTrustStoreFile");
options.put("trust-store-type", "setTrustStoreType");
options.put("trust-store-password", "setTrustStorePassword");
options.put("nonce-factory-class", "setNonceFactory");
}
// provide logging
private static final Logger log = Logger.getLogger(WSSecurityOMFactory.class);
// Hide constructor
private WSSecurityOMFactory()
{
}
/**
* Create a new instance of a jaxrpc-mapping factory
*/
public static WSSecurityOMFactory newInstance()
{
return new WSSecurityOMFactory();
}
public WSSecurityConfiguration parse(URL configURL) throws IOException
{
if (configURL == null)
throw new IllegalArgumentException("Security config URL cannot be null");
InputStream is = new ResourceURL(configURL).openStream();
try
{
Unmarshaller unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
WSSecurityConfiguration configuration = (WSSecurityConfiguration)unmarshaller.unmarshal(is, this, null);
return configuration;
}
catch (JBossXBException e)
{
IOException ioex = new IOException("Cannot parse: " + configURL);
Throwable cause = e.getCause();
if (cause != null)
ioex.initCause(cause);
throw ioex;
}
finally
{
is.close();
}
}
public WSSecurityConfiguration parse(String xmlString) throws JBossXBException
{
if (xmlString == null)
throw new IllegalArgumentException("Security config xml String cannot be null");
Unmarshaller unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
WSSecurityConfiguration configuration = (WSSecurityConfiguration)unmarshaller.unmarshal(xmlString, this, null);
return configuration;
}
public WSSecurityConfiguration parse(StringReader strReader) throws JBossXBException
{
if (strReader == null)
throw new IllegalArgumentException("Security InputStream cannot be null");
Unmarshaller unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
WSSecurityConfiguration configuration = (WSSecurityConfiguration)unmarshaller.unmarshal(strReader, this, null);
return configuration;
}
/**
* This method is called on the factory by the object model builder when the
* parsing starts.
*/
public Object newRoot(Object root, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
return new WSSecurityConfiguration();
}
public Object completeRoot(Object root, UnmarshallingContext ctx, String uri, String name)
{
return root;
}
public void setValue(WSSecurityConfiguration configuration, UnmarshallingContext navigator, String namespaceURI, String localName, String value)
{
log.trace("setValue: [obj=" + configuration + ",value=" + value + "]");
String method = (String)options.get(localName);
if (method == null)
return;
// Dispatch to proper initializer
try
{
WSSecurityConfiguration.class.getMethod(method, new Class[] { String.class }).invoke(configuration, new Object[] { value });
}
catch (Exception e)
{
log.error("Could not set option: " + method + " to: " + value, e);
}
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(WSSecurityConfiguration configuration, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("config".equals(localName))
{
return new Config();
}
if ("key-passwords".equals(localName))
{
HashMap pwds = new HashMap();
configuration.setKeyPasswords(pwds);
return pwds;
}
if ("port".equals(localName))
{
return new Port(attrs.getValue("", "name"));
}
if ("timestamp-verification".equals(localName))
{
//By default, the createdTolerance should be '0'
Long createdTolerance = new Long(0);
String createdToleranceAttr = attrs.getValue("", "createdTolerance");
if (createdToleranceAttr != null)
createdTolerance = (Long)SimpleTypeBindings.unmarshal(SimpleTypeBindings.XS_LONG_NAME, createdToleranceAttr, null);
//By default, we do log warnings if the tolerance is used.
Boolean warnCreated = new Boolean(true);
String warnCreatedAttr = attrs.getValue("", "warnCreated");
if (warnCreatedAttr != null)
warnCreated = (Boolean)SimpleTypeBindings.unmarshal(SimpleTypeBindings.XS_BOOLEAN_NAME, warnCreatedAttr, null);
//By default, the expiresTolerance should be '0'
Long expiresTolerance = new Long(0);
String expiresToleranceAttr = attrs.getValue("", "expiresTolerance");
if (expiresToleranceAttr != null)
expiresTolerance = (Long)SimpleTypeBindings.unmarshal(SimpleTypeBindings.XS_LONG_NAME, expiresToleranceAttr, null);
//By default, we do log warnings if the tolerance is used.
Boolean warnExpires = new Boolean(true);
String warnExpiresAttr = attrs.getValue("", "warnExpires");
if (warnExpiresAttr != null)
warnExpires = (Boolean)SimpleTypeBindings.unmarshal(SimpleTypeBindings.XS_BOOLEAN_NAME, warnExpiresAttr, null);
return new TimestampVerification(createdTolerance, warnCreated, expiresTolerance, warnExpires);
}
return null;
}
/**
* Called when parsing the contents of the <key-password> tag.
*/
public Object newChild(HashMap passwords, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("key-password".equals(localName))
{
String alias = attrs.getValue("", "alias");
String pwd = attrs.getValue("", "password");
passwords.put(alias, pwd);
}
return null;
}
/**
* Called when parsing character is complete.
*/
public void addChild(WSSecurityConfiguration configuration, Config defaultConfig, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + configuration + ",child=" + defaultConfig + "]");
configuration.setDefaultConfig(defaultConfig);
}
/**
* Called when parsing character is complete.
*/
public void addChild(WSSecurityConfiguration configuration, Port port, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + configuration + ",child=" + port + "]");
configuration.addPort(port);
}
/**
* Called when parsing TimestampVerification is complete.
*/
public void addChild(WSSecurityConfiguration configuration, TimestampVerification timestampVerification, UnmarshallingContext navigator, String namespaceURI,
String localName)
{
log.trace("addChild: [obj=" + configuration + ",child=" + timestampVerification + "]");
configuration.setTimestampVerification(timestampVerification);
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(Config config, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("sign".equals(localName))
{
// By default, we alwyas include a timestamp
Boolean include = new Boolean(true);
String timestamp = attrs.getValue("", "includeTimestamp");
if (timestamp != null)
include = (Boolean)SimpleTypeBindings.unmarshal(SimpleTypeBindings.XS_BOOLEAN_NAME, timestamp, null);
return new Sign(attrs.getValue("", "type"), attrs.getValue("", "alias"), include.booleanValue());
}
else if ("encrypt".equals(localName))
{
return new Encrypt(attrs.getValue("", "type"), attrs.getValue("", "alias"), attrs.getValue("", "algorithm"));
}
else if ("timestamp".equals(localName))
{
return new Timestamp(attrs.getValue("", "ttl"));
}
else if ("requires".equals(localName))
{
return new Requires();
}
else if ("username".equals(localName))
{
//By default, we do not use password digest
Boolean digestPassword = new Boolean(false);
String digestPasswordAttr = attrs.getValue("", "digestPassword");
if (digestPasswordAttr != null)
digestPassword = (Boolean)SimpleTypeBindings.unmarshal(SimpleTypeBindings.XS_BOOLEAN_NAME, digestPasswordAttr, null);
//if password digest is enabled, we use nonces by default
Boolean useNonce = new Boolean(true);
String useNonceAttr = attrs.getValue("", "useNonce");
if (useNonceAttr != null)
useNonce = (Boolean)SimpleTypeBindings.unmarshal(SimpleTypeBindings.XS_BOOLEAN_NAME, useNonceAttr, null);
//if password digest is enabled, we use the created element by default
Boolean useCreated = new Boolean(true);
String useCreatedAttr = attrs.getValue("", "useCreated");
if (useCreatedAttr != null)
useCreated = (Boolean)SimpleTypeBindings.unmarshal(SimpleTypeBindings.XS_BOOLEAN_NAME, useCreatedAttr, null);
return new Username(digestPassword, useNonce, useCreated);
}
else if ("authenticate".equals(localName))
{
return new Authenticate();
}
else if ("authorize".equals(localName))
{
return new Authorize();
}
return null;
}
/**
* Called when parsing character is complete.
*/
public void addChild(Config config, Encrypt encrypt, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + config + ",child=" + encrypt + "]");
config.setEncrypt(encrypt);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Config config, Sign sign, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + config + ",child=" + sign + "]");
config.setSign(sign);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Config config, Timestamp timestamp, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + config + ",child=" + timestamp + "]");
config.setTimestamp(timestamp);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Config config, Username username, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + config + ",child=" + username + "]");
config.setUsername(username);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Config config, Requires requires, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + config + ",child=" + requires + "]");
config.setRequires(requires);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Config config, Authenticate authenticate, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + config + ",child=" + authenticate + "]");
config.setAuthenticate(authenticate);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Authenticate authenticate, UsernameAuth usernameAuth, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + authenticate + ",child=" + usernameAuth + "]");
authenticate.setUsernameAuth(usernameAuth);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Authenticate authenticate, SignatureCertAuth signatureCertAuth, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + authenticate + ",child=" + signatureCertAuth + "]");
authenticate.setSignatureCertAuth(signatureCertAuth);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Config config, Authorize authorize, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + config + ",child=" + authorize + "]");
config.setAuthorize(authorize);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Authorize authorize, Unchecked unchecked, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + authorize + ",child=" + unchecked + "]");
authorize.setUnchecked(unchecked);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Authorize authorize, Role role, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + authorize + ",child=" + role + "]");
authorize.addRole(role);
}
private Object handleTargets(Object object, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("target".equals(localName))
{
Target target = new Target(attrs.getValue("", "type"));
if ("true".equals(attrs.getValue("", "contentOnly")))
target.setContentOnly(true);
return target;
}
return null;
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(Encrypt encrypt, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
return handleTargets(encrypt, navigator, namespaceURI, localName, attrs);
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(Sign sign, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
return handleTargets(sign, navigator, namespaceURI, localName, attrs);
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(Requires requires, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("signature".equals(localName))
{
return new RequireSignature();
}
else if ("encryption".equals(localName))
{
return new RequireEncryption();
}
else if ("timestamp".equals(localName))
{
return new RequireTimestamp(attrs.getValue("", "maxAge"));
}
return null;
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(Authenticate authenticate, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("usernameAuth".equals(localName))
{
return new UsernameAuth();
}
else if ("signatureCertAuth".equals(localName))
{
return new SignatureCertAuth(attrs.getValue("", "certificatePrincipal"));
}
return null;
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(Authorize authorize, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("unchecked".equals(localName))
{
return new Unchecked();
}
else if ("role".equals(localName))
{
return new Role();
}
return null;
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(RequireSignature requireSignature, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
return handleTargets(requireSignature, navigator, namespaceURI, localName, attrs);
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(RequireEncryption requireEncryption, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
return handleTargets(requireEncryption, navigator, namespaceURI, localName, attrs);
}
public void setValue(Target target, UnmarshallingContext navigator, String namespaceURI, String localName, String value)
{
log.trace("setValue: [obj=" + target + ",value=" + value + "]");
target.setValue(value);
}
public void setValue(Role role, UnmarshallingContext navigator, String namespaceURI, String localName, String value)
{
log.trace("setValue: [obj=" + role + ",value=" + value + "]");
role.setName(value);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Encrypt encrypt, Target target, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + encrypt + ",child=" + target + "]");
encrypt.addTarget(target);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Sign sign, Target target, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + sign + ",child=" + target + "]");
sign.addTarget(target);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Requires requires, RequireEncryption requireEncryption, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + requires + ",child=" + requireEncryption + "]");
requires.setRequireEncryption(requireEncryption);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Requires requires, RequireSignature requireSignature, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + requires + ",child=" + requireSignature + "]");
requires.setRequireSignature(requireSignature);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Requires requires, RequireTimestamp requireTimestamp, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + requires + ",child=" + requireTimestamp + "]");
requires.setRequireTimestamp(requireTimestamp);
}
/**
* Called when parsing character is complete.
*/
public void addChild(RequireEncryption requireEncryption, Target target, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + requireEncryption + ",child=" + target + "]");
requireEncryption.addTarget(target);
}
/**
* Called when parsing character is complete.
*/
public void addChild(RequireSignature requireSignature, Target target, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + requireSignature + ",child=" + target + "]");
requireSignature.addTarget(target);
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(Port port, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("operation".equals(localName))
{
return new Operation(attrs.getValue("", "name"));
}
else if ("config".equals(localName))
{
return new Config();
}
return null;
}
/**
* Called when parsing character is complete.
*/
public void addChild(Port port, Operation operation, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + port + ",child=" + operation + "]");
port.addOperation(operation);
}
/**
* Called when parsing character is complete.
*/
public void addChild(Port port, Config config, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + port + ",child=" + config + "]");
port.setDefaultConfig(config);
}
/**
* Called when parsing of a new element started.
*/
public Object newChild(Operation operation, UnmarshallingContext navigator, String namespaceURI, String localName, Attributes attrs)
{
log.trace("newChild: " + localName);
if ("config".equals(localName))
{
return new Config();
}
return null;
}
/**
* Called when parsing character is complete.
*/
public void addChild(Operation operation, Config config, UnmarshallingContext navigator, String namespaceURI, String localName)
{
log.trace("addChild: [obj=" + operation + ",child=" + config + "]");
operation.setConfig(config);
}
}