blob: f9477406944a226c24122b4ca1eaa4589c23ad08 [file] [log] [blame]
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rahas;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Reader;
import java.io.StringReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Properties;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMMetaFactory;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.om.OMXMLStreamReaderConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.util.XmlSchemaDateFormat;
/**
* This represents a security token which can have either one of 4 states. <ul> <li>ISSUED</li> <li>EXPIRED</li>
* <li>CACELLED</li> <li>RENEWED</li> </ul> Also this holds the <code>OMElement</code>s representing the token in its
* present state and the previous state.
* <p/>
* These tokens are stored using the storage mechanism provided via the <code>TokenStorage</code> interface.
*
* @see org.apache.rahas.TokenStorage
*/
public class Token implements Externalizable {
private static Log log = LogFactory.getLog(Token.class);
public final static int ISSUED = 1;
public final static int EXPIRED = 2;
public final static int CANCELLED = 3;
public final static int RENEWED = 4;
/**
* Token identifier
*/
private String id;
/**
* Current state of the token
*/
private int state = -1;
/**
* The actual token in its current state
*/
private OMElement token;
/**
* The token in its previous state
*/
private OMElement previousToken;
/**
* The RequestedAttachedReference element NOTE : The oasis-200401-wss-soap-message-security-1.0 spec allows an
* extensibility mechanism for wsse:SecurityTokenReference and wsse:Reference. Hence we cannot limit to the
* wsse:SecurityTokenReference\wsse:Reference case and only hold the URI and the ValueType values.
*/
private OMElement attachedReference;
/**
* The RequestedUnattachedReference element NOTE : The oasis-200401-wss-soap-message-security-1.0 spec allows an
* extensibility mechanism for wsse:SecurityTokenRefence and wsse:Reference. Hence we cannot limit to the
* wsse:SecurityTokenReference\wsse:Reference case and only hold the URI and the ValueType values.
*/
private OMElement unattachedReference;
/**
* A bag to hold any other properties
*/
private Properties properties;
/**
* A flag to assist the TokenStorage
*/
private boolean changed;
/**
* The secret associated with the Token
*/
private byte[] secret;
/**
* Created time
*/
private Date created;
/**
* Expiration time
*/
private Date expires;
/**
* Issuer end point address
*/
private String issuerAddress;
private String encrKeySha1Value;
public Token() {
}
public Token(String id, Date created, Date expires) {
this.id = id;
this.created = created;
this.expires = expires;
}
public Token(String id, OMElement tokenElem, Date created, Date expires)
throws TrustException {
this.id = id;
OMMetaFactory metaFactory = OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM);
OMXMLStreamReaderConfiguration configuration = new OMXMLStreamReaderConfiguration();
configuration.setNamespaceURIInterning(true);
this.token = OMXMLBuilderFactory.createStAXOMBuilder(metaFactory.getOMFactory(),
tokenElem.getXMLStreamReader(true, configuration)).getDocumentElement();
this.created = created;
this.expires = expires;
}
public Token(String id, OMElement tokenElem, OMElement lifetimeElem)
throws TrustException {
this.id = id;
OMMetaFactory metaFactory = OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM);
OMXMLStreamReaderConfiguration configuration = new OMXMLStreamReaderConfiguration();
configuration.setNamespaceURIInterning(true);
this.token = OMXMLBuilderFactory.createStAXOMBuilder(metaFactory.getOMFactory(),
tokenElem.getXMLStreamReader(true, configuration)).getDocumentElement();
this.processLifeTime(lifetimeElem);
}
/**
* @param lifetimeElem
* @throws TrustException
*/
private void processLifeTime(OMElement lifetimeElem)
throws TrustException {
try {
DateFormat zulu = new XmlSchemaDateFormat();
OMElement createdElem =
lifetimeElem.getFirstChildWithName(new QName(WSConstants.WSU_NS, WSConstants.CREATED_LN));
this.created = zulu.parse(createdElem.getText());
OMElement expiresElem =
lifetimeElem.getFirstChildWithName(new QName(WSConstants.WSU_NS, WSConstants.EXPIRES_LN));
this.expires = zulu.parse(expiresElem.getText());
} catch (OMException e) {
throw new TrustException("lifeTimeProcessingError", new String[]{lifetimeElem.toString()}, e);
} catch (ParseException e) {
throw new TrustException("lifeTimeProcessingError", new String[]{lifetimeElem.toString()}, e);
}
}
/**
* @return Returns the changed.
*/
public boolean isChanged() {
return changed;
}
/**
* @param chnaged The changed to set.
*/
public void setChanged(boolean chnaged) {
this.changed = chnaged;
}
/**
* @return Returns the properties.
*/
public Properties getProperties() {
return properties;
}
/**
* @param properties The properties to set.
*/
public void setProperties(Properties properties) {
this.properties = properties;
}
/**
* @return Returns the state.
*/
public int getState() {
return state;
}
/**
* @param state The state to set.
*/
public void setState(int state) {
this.state = state;
}
/**
* @return Returns the token.
*/
public OMElement getToken() {
return token;
}
/**
* @param token The token to set.
*/
public void setToken(OMElement token) {
this.token = token;
}
/**
* @return Returns the id.
*/
public String getId() {
return id;
}
/**
* @return Returns the presivousToken.
*/
public OMElement getPreviousToken() {
return previousToken;
}
/**
* @param presivousToken The presivousToken to set.
*/
public void setPreviousToken(OMElement presivousToken) {
OMMetaFactory metaFactory = OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM);
this.previousToken = OMXMLBuilderFactory.createStAXOMBuilder(metaFactory.getOMFactory(),
presivousToken.getXMLStreamReader()).getDocumentElement();
}
/**
* @return Returns the secret.
*/
public byte[] getSecret() {
return secret;
}
/**
* @param secret The secret to set.
*/
public void setSecret(byte[] secret) {
this.secret = secret;
}
/**
* @return Returns the attachedReference.
*/
public OMElement getAttachedReference() {
return attachedReference;
}
/**
* @param attachedReference The attachedReference to set.
*/
public void setAttachedReference(OMElement attachedReference) {
if (attachedReference != null) {
OMMetaFactory metaFactory = OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM);
this.attachedReference =
OMXMLBuilderFactory.createStAXOMBuilder(metaFactory.getOMFactory(),
attachedReference.getXMLStreamReader()).getDocumentElement();
}
}
/**
* @return Returns the unattachedReference.
*/
public OMElement getUnattachedReference() {
return unattachedReference;
}
/**
* @param unattachedReference The unattachedReference to set.
*/
public void setUnattachedReference(OMElement unattachedReference) {
if (unattachedReference != null) {
OMMetaFactory metaFactory = OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM);
this.unattachedReference =
OMXMLBuilderFactory.createStAXOMBuilder(metaFactory.getOMFactory(),
unattachedReference.getXMLStreamReader()).getDocumentElement();
}
}
/**
* @return Returns the created.
*/
public Date getCreated() {
return created;
}
/**
* @return Returns the expires.
*/
public Date getExpires() {
return expires;
}
/**
* @param expires The expires to set.
*/
public void setExpires(Date expires) {
this.expires = expires;
}
public String getIssuerAddress() {
return issuerAddress;
}
public void setIssuerAddress(String issuerAddress) {
this.issuerAddress = issuerAddress;
}
/**
* Implementing serialize logic according to our own protocol. We had to follow this, because
* OMElement class is not serializable. Making OMElement serializable will have an huge impact
* on other components. Therefore implementing serialization logic according to a manual
* protocol.
* @param out Stream which writes serialized bytes.
* @throws IOException If unable to serialize particular member.
*/
public void writeExternal(ObjectOutput out)
throws IOException {
out.writeObject(this.id);
out.writeInt(this.state);
String stringElement = convertOMElementToString(this.token);
out.writeObject(stringElement);
stringElement = convertOMElementToString(this.previousToken);
out.writeObject(stringElement);
stringElement = convertOMElementToString(this.attachedReference);
out.writeObject(stringElement);
stringElement = convertOMElementToString(this.unattachedReference);
out.writeObject(stringElement);
out.writeObject(this.properties);
out.writeBoolean(this.changed);
int secretLength = 0;
if (null != this.secret) {
secretLength = this.secret.length;
}
// First write the length of secret
out.writeInt(secretLength);
if (0 != secretLength) {
out.write(this.secret);
}
out.writeObject(this.created);
out.writeObject(this.expires);
out.writeObject(this.issuerAddress);
out.writeObject(this.encrKeySha1Value);
}
/**
* Implementing de-serialization logic in accordance with the serialization logic.
* @param in Stream which used to read data.
* @throws IOException If unable to de-serialize particular data member.
* @throws ClassNotFoundException
*/
public void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException {
this.id = (String)in.readObject();
this.state = in.readInt();
String stringElement = (String)in.readObject();
this.token = convertStringToOMElement(stringElement);
stringElement = (String)in.readObject();
this.previousToken = convertStringToOMElement(stringElement);
stringElement = (String)in.readObject();
this.attachedReference = convertStringToOMElement(stringElement);
stringElement = (String)in.readObject();
this.unattachedReference = convertStringToOMElement(stringElement);
this.properties = (Properties)in.readObject();
this.changed = in.readBoolean();
// Read the length of the secret
int secretLength = in.readInt();
if (0 != secretLength) {
byte[] buffer = new byte[secretLength];
if (secretLength != in.read(buffer)) {
throw new IllegalStateException("Bytes read from the secret key is not equal to serialized length");
}
this.secret = buffer;
}else{
this.secret = null;
}
this.created = (Date)in.readObject();
this.expires = (Date)in.readObject();
this.issuerAddress = (String)in.readObject();
this.encrKeySha1Value = (String)in.readObject();
}
private String convertOMElementToString(OMElement element)
throws IOException {
String serializedToken = "";
if (null == element) {
return serializedToken;
}
try {
serializedToken = element.toStringWithConsume();
} catch (XMLStreamException e) {
throw new IOException("Could not serialize token OM element");
}
return serializedToken;
}
private OMElement convertStringToOMElement(String stringElement)
throws IOException {
if (null == stringElement || stringElement.trim().equals("")) {
return null;
}
try {
Reader in = new StringReader(stringElement);
XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(in);
OMXMLParserWrapper builder = OMXMLBuilderFactory.createStAXOMBuilder(parser);
OMElement documentElement = builder.getDocumentElement();
XMLStreamReader llomReader = documentElement.getXMLStreamReader();
OMMetaFactory metaFactory = OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM);
OMFactory doomFactory = metaFactory.getOMFactory();
OMXMLParserWrapper doomBuilder = OMXMLBuilderFactory.createStAXOMBuilder(doomFactory, llomReader);
return doomBuilder.getDocumentElement();
} catch (XMLStreamException e) {
log.error("Cannot convert de-serialized string to OMElement. Could not create XML stream.", e);
// IOException only has a constructor supporting exception chaining starting with Java 1.6
IOException ex = new IOException("Cannot convert de-serialized string to OMElement. Could not create XML stream.");
ex.initCause(e);
throw ex;
}
}
}