SecurityHeader.java :  » 6.0-JDK-Modules-com.sun » xws-security » com » sun » xml » ws » security » opt » impl » outgoing » Java Open Source

Java Open Source » 6.0 JDK Modules com.sun » xws security 
xws security » com » sun » xml » ws » security » opt » impl » outgoing » SecurityHeader.java
 /*
  * The contents of this file are subject to the terms
  * of the Common Development and Distribution License
  * (the License).  You may not use this file except in
  * compliance with the License.
  *
  * You can obtain a copy of the license at
  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
  * See the License for the specific language governing
  * permissions and limitations under the License.
  *
  * When distributing Covered Code, include this CDDL
  * Header Notice in each file and include the License file
  * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
  * If applicable, add the following below the CDDL Header,
  * with the fields enclosed by brackets [] replaced by
  * you own identifying information:
  * "Portions Copyrighted [year] [name of copyright owner]"
  *
  * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
  */

package com.sun.xml.ws.security.opt.impl.outgoing;

import com.sun.istack.NotNull;
import com.sun.istack.Nullable;
import com.sun.xml.ws.security.opt.api.SecurityElementWriter;
import com.sun.xml.ws.security.opt.api.SecurityHeaderElement;
import com.sun.xml.ws.security.opt.impl.enc.JAXBEncryptedData;
import com.sun.xml.ws.security.opt.impl.enc.JAXBEncryptedKey;
import com.sun.xml.ws.security.opt.impl.message.GSHeaderElement;
import com.sun.xml.ws.security.opt.impl.tokens.Timestamp;
import com.sun.xml.wss.impl.MessageConstants;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;

/**
 *
 * @author K.Venugopal@sun.com
 */
public class SecurityHeader {
    public static final int LAYOUT_LAX = 0;
    public static final int LAYOUT_STRICT = 1;
    public static final int LAYOUT_LAX_TS_FIRST = 2;
    public static final int LAYOUT_LAX_TS_LAST = 3;
    
    protected ArrayList<SecurityHeaderElement> secHeaderContent = new ArrayList<SecurityHeaderElement>();
    protected int headerLayout = LAYOUT_STRICT;
    protected String soapVersion = MessageConstants.SOAP_1_1_NS;
    private boolean debug = false;
    /**
     * Default constructor
     * uses Lax Message Layout and SOAP 1.1 version
     */
    public SecurityHeader(){
        
    }
    
    public SecurityHeader(int layout, String soapVersion){
        this.headerLayout = layout;
        this.soapVersion = soapVersion;
    }
    
    public int getHeaderLayout(){
        return this.headerLayout;
    }
    
    public void setHeaderLayout(int headerLayout){
        this.headerLayout = headerLayout;
    }
    
    public String getSOAPVersion(){
        return this.soapVersion;
    }
    
    public void setSOAPVersion(String soapVersion){
        this.soapVersion = soapVersion;
    }
    
    public SecurityHeaderElement getChildElement(String localName,String uri){
        for(SecurityHeaderElement she : secHeaderContent){
            if(localName.equals(she.getLocalPart()) && uri.equals(she.getNamespaceURI())){
                return she;
            }
        }
        return null;
    }
    
    public Iterator getHeaders(final String localName,final String uri){
        return new Iterator() {
            int idx = 0;
            Object next;
            public boolean hasNext() {
                if(next==null)
                    fetch();
                return next!=null;
            }
            
            public Object next() {
                if(next==null) {
                    fetch();
                    if(next==null){
                        throw new NoSuchElementException();
                    }
                }
                
                Object r = next;
                next = null;
                return r;
            }
            
            private void fetch() {
                while(idx<secHeaderContent.size()) {
                    SecurityHeaderElement she = secHeaderContent.get(idx++);
                    if((uri == null && localName.equals(she.getLocalPart())) ||
                            (localName.equals(she.getLocalPart() )&& uri.equals(she.getNamespaceURI()))){
                        next = she;
                        break;
                    }
                }
            }
            
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
    
    
    public SecurityHeaderElement getChildElement(String id){
        for(SecurityHeaderElement she: secHeaderContent){
            if(id.equals(she.getId()))
                return she;
        }
        return null;
    }
    
    public void add(SecurityHeaderElement header){
        prepend(header);
    }
    
    public boolean replace(SecurityHeaderElement replaceThis, SecurityHeaderElement withThis){
        int index = secHeaderContent.indexOf(replaceThis);
        if(index != -1){
            secHeaderContent.set(index,withThis);
            return true;
        }
        return false;
    }
    
    public void prepend(SecurityHeaderElement element){
        secHeaderContent.add(0,element);
    }
    
    public void append(SecurityHeaderElement element){
        secHeaderContent.add(element);
    }
    
    /**
     * Gets the namespace URI of this header element.
     *
     * @return
     *      this string must be interned.
     */
    public @NotNull String getNamespaceURI(){
        return MessageConstants.WSSE_NS;
    }
    
    /**
     * Gets the local name of this header element.
     *
     * @return
     *      this string must be interned.
     */
    public @NotNull String getLocalPart(){
        return "Security";
    }
    
    /**
     * Gets the attribute value on the header element.
     *
     * @param nsUri
     *      The namespace URI of the attribute. Can be empty.
     * @param localName
     *      The local name of the attribute.
     *
     * @return
     *      if the attribute is found, return the whitespace normalized value.
     *      (meaning no leading/trailing space, no consequtive whitespaces in-between.)
     *      Otherwise null. Note that the XML parsers are responsible for
     *      whitespace-normalizing attributes, so {@link Header} implementation
     *      doesn't have to do anything.
     */
    public @Nullable String getAttribute(@NotNull String nsUri, @NotNull String localName){
        throw new UnsupportedOperationException();
    }
    
    /**
     * Gets the attribute value on the header element.
     *
     * <p>
     * This is a convenience method that calls into {@link #getAttribute(String, String)}
     *
     * @param name
     *      Never null.
     *
     * @see #getAttribute(String, String)
     */
    public @Nullable String getAttribute(@NotNull QName name){
        throw new UnsupportedOperationException();
    }
    
    
    /**
     * Writes out the header.
     *
     * @throws XMLStreamException
     *      if the operation fails for some reason. This leaves the
     *      writer to an undefined state.
     */
    public void writeTo(XMLStreamWriter streamWriter) throws XMLStreamException{
        orderHeaders();
        if(secHeaderContent.size() >0){
            streamWriter.writeStartElement(MessageConstants.WSSE_PREFIX,"Security",MessageConstants.WSSE_NS);
            writeMustunderstand(streamWriter);
            for( SecurityHeaderElement el : secHeaderContent){
                ((SecurityElementWriter)el).writeTo(streamWriter);
            }
            
            streamWriter.writeEndElement();
        }
    }
    
    /**
     * Writes out the header to the given SOAPMessage.
     *
     * <p>
     * Sometimes a {@link Message} needs to produce itself
     * as {@link SOAPMessage}, in which case each header needs
     * to turn itself into a header.
     *
     * @throws SOAPException
     *      if the operation fails for some reason. This leaves the
     *      writer to an undefined state.
     */
    public void writeTo(SOAPMessage saaj) throws SOAPException{
        throw new UnsupportedOperationException();
    }
    
    /**
     * Writes out the header as SAX events.
     *
     * <p>
     * Sometimes a {@link Message} needs to produce SAX events,
     * and this method is necessary for headers to participate to it.
     *
     * <p>
     * A header is responsible for producing the SAX events for its part,
     * including <tt>startPrefixMapping</tt> and <tt>endPrefixMapping</tt>,
     * but not startDocument/endDocument.
     *
     * <p>
     * Note that SAX contract requires that any error that does NOT originate
     * from {@link ContentHandler} (meaning any parsing error and etc) must
     * be first reported to {@link ErrorHandler}. If the SAX event production
     * cannot be continued and the processing needs to abort, the code may
     * then throw the same {@link SAXParseException} reported to {@link ErrorHandler}.
     *
     * @param contentHandler
     *      The {@link ContentHandler} that receives SAX events.
     *
     * @param errorHandler
     *      The {@link ErrorHandler} that receives parsing errors.
     */
    public void writeTo(ContentHandler contentHandler, ErrorHandler errorHandler) throws SAXException{
        throw new UnsupportedOperationException();
    }
    
    private void writeMustunderstand(XMLStreamWriter writer) throws XMLStreamException{
        if(soapVersion == MessageConstants.SOAP_1_1_NS){
            writer.writeAttribute("S",MessageConstants.SOAP_1_1_NS,MessageConstants.MUST_UNDERSTAND,"1");
        }else if(soapVersion == MessageConstants.SOAP_1_2_NS){
            writer.writeAttribute("S",MessageConstants.SOAP_1_2_NS,MessageConstants.MUST_UNDERSTAND,"true");
        }
    }
    
    private void orderHeaders(){
        if(headerLayout == LAYOUT_LAX_TS_LAST){
            laxTimestampLast();
        }else if(headerLayout == LAYOUT_LAX_TS_FIRST){
            laxTimestampFirst();
        }else if(headerLayout ==LAYOUT_STRICT){
            strict();
        }else{
            strict();
        }
    }
    
    private void laxTimestampLast(){
        strict();
        SecurityHeaderElement timestamp = this.secHeaderContent.get(0);
        if(timestamp != null && (timestamp instanceof Timestamp )){
            this.secHeaderContent.remove(0);
            this.secHeaderContent.add(timestamp);
        }
    }
    
    
    private void laxTimestampFirst(){
        strict();
    }
    
    private void print(ArrayList<SecurityHeaderElement> list){
        if(!debug){
            return;
        }
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++");
        for(int j=0;j<list.size();j++){
            System.out.println(list.get(j));
        }
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++");
    }
    
    private void strict(){
        ArrayList<SecurityHeaderElement> primaryElementList  = new ArrayList<SecurityHeaderElement> ();
        ArrayList<SecurityHeaderElement> topElementList  = new ArrayList<SecurityHeaderElement> ();
        int len = secHeaderContent.size();
        print(secHeaderContent);
        
        SecurityHeaderElement timeStamp = null;
        for(int i=0;i<len;i++){
            SecurityHeaderElement she = secHeaderContent.get(i);
            if(she.getLocalPart() == MessageConstants.TIMESTAMP_LNAME){
                timeStamp = she;
                continue;
            }
            if(isTopLevelElement(she)){
                topElementList.add(she);
            }else{
                primaryElementList.add(0,she);
            }
        }
        
        print(topElementList);
        topElementList = orderList(topElementList);
        
        print(primaryElementList);
        primaryElementList = orderList(primaryElementList);
        
        ArrayList<SecurityHeaderElement> tmpList =   new ArrayList<SecurityHeaderElement> ();
        for(int i=0;i<primaryElementList.size();i++){
            SecurityHeaderElement she = primaryElementList.get(i);
            if(she.getLocalPart() == MessageConstants.XENC_REFERENCE_LIST_LNAME ||
                    she.getLocalPart() == MessageConstants.ENCRYPTEDKEY_LNAME){
                int tLen = topElementList.size();
                for(int j=tLen-1;j>=0;j--){
                    SecurityHeaderElement tk = topElementList.get(j);
                    if(she.refersToSecHdrWithId(tk.getId())){
                        topElementList.add(j+1,she);
                        //topElementList.add(j,she);
                        tmpList.add(she);
                        break;
                    }
                }
            }
        }
        primaryElementList.removeAll(tmpList);
        
        secHeaderContent.clear();
        for(int i=topElementList.size()-1;i>=0;i--){
            secHeaderContent.add(topElementList.get(i));
        }
        
        for(int i=primaryElementList.size()-1;i>=0;i--){
            secHeaderContent.add(primaryElementList.get(i));
        }
        
        if(timeStamp != null){
            secHeaderContent.add(0,timeStamp);
        }
    }
    
    private ArrayList<SecurityHeaderElement> orderList(ArrayList<SecurityHeaderElement> list){
        ArrayList<SecurityHeaderElement> tmp = new ArrayList<SecurityHeaderElement>();
        for(int i=0;i<list.size();i++){
            SecurityHeaderElement securityElementOne = list.get(i);
            
            int wLen = tmp.size();
            int index = 0;
            if(wLen == 0){
                tmp.add(securityElementOne);
                continue;
            }
            
            int setIndex = -1;
            for(int j=0;j<wLen;j++){
                SecurityHeaderElement securityElementTwo = tmp.get(j);
                if(securityElementOne.refersToSecHdrWithId(securityElementTwo.getId())){
                    if(securityElementTwo instanceof JAXBEncryptedData){
                        if(securityElementOne instanceof JAXBEncryptedKey || securityElementOne.getLocalPart() == MessageConstants.XENC_REFERENCE_LIST_LNAME){
                            setIndex = j+1;
                        }else{
                            setIndex = j;
                        }
                    } else{
                        setIndex = j;
                    }
                }else if(securityElementTwo instanceof JAXBEncryptedData  && refersToEncryptedElement(securityElementOne,securityElementTwo)){
                    setIndex = j;
                }else if(securityElementTwo.refersToSecHdrWithId(securityElementOne.getId())){
                    if(securityElementTwo instanceof JAXBEncryptedKey && securityElementOne instanceof JAXBEncryptedData){
                        setIndex = j;
                    }else{
                        setIndex = j+1;
                    }
                    
                }
            }
            if(tmp.contains(securityElementOne)){
                continue;
            }
            if(setIndex == -1){
                tmp.add(securityElementOne);
            }else{
                tmp.add(setIndex,securityElementOne);
            }
            print(tmp);
        }
        return tmp;
    }
    
    private boolean refersToEncryptedElement(SecurityHeaderElement securityElementOne,SecurityHeaderElement securityElementTwo){
        if(securityElementOne.refersToSecHdrWithId(((JAXBEncryptedData)securityElementTwo).getEncryptedId())){
            return true;
        }
        return false;
    }
    private void movePrevHeader(SecurityHeaderElement toBeMoved, int index){
        int prevIndex = secHeaderContent.indexOf(toBeMoved);
        SecurityHeaderElement prev = (SecurityHeaderElement)secHeaderContent.get(prevIndex-1);
        String prevId = prev.getId();
        secHeaderContent.remove(toBeMoved);
        secHeaderContent.add(index, toBeMoved);
        if(toBeMoved.refersToSecHdrWithId(prevId)){
            movePrevHeader(prev, index);
        }
    }
    //move tokens to top.
    private boolean isTopLevelElement(SecurityHeaderElement she) {
        String localPart = she.getLocalPart();
        //String uri = she.getNamespaceURI();
        if(localPart.equals(MessageConstants.ENCRYPTED_DATA_LNAME)){
            if(she instanceof GSHeaderElement){
                return true;//Issued token encrypted.
            }
            localPart = ((JAXBEncryptedData)she).getEncryptedLocalName();
            
        }
        if(localPart == MessageConstants.WSSE_BINARY_SECURITY_TOKEN_LNAME){
            return true;
        }
        if(localPart == MessageConstants.SECURITY_CONTEXT_TOKEN_LNAME){
            return true;
        }
        if(localPart == MessageConstants.ENCRYPTEDKEY_LNAME){
            if (((JAXBEncryptedKey)she).hasReferenceList()) {
                return false;
            }
            return true;
        }
        if(localPart == MessageConstants.DERIVEDKEY_TOKEN_LNAME ){
            return true;
        }
        if(localPart == MessageConstants.SIGNATURE_CONFIRMATION_LNAME){
            return true;
        }
        
        if(localPart == MessageConstants.TIMESTAMP_LNAME){
            return true;
        }
        if(localPart.equals( MessageConstants.SAML_ASSERTION_LNAME)){
            return true;
        }
        if(localPart == MessageConstants.USERNAME_TOKEN_LNAME){
            return true;
        }
        return false;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.