001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: Transform.java,v 1.2 2008/06/25 05:47:08 qcheng Exp $
026 *
027 */
028
029
030package com.sun.identity.liberty.ws.authnsvc.protocol;
031
032import java.util.ArrayList;
033import java.util.HashMap;
034import java.util.Iterator;
035import java.util.List;
036import java.util.Map;
037import java.util.StringTokenizer;
038
039import org.w3c.dom.Document;
040import org.w3c.dom.Element;
041import org.w3c.dom.Node;
042import org.w3c.dom.NodeList;
043
044import com.sun.identity.shared.xml.XMLUtils;
045import com.sun.identity.shared.configuration.SystemPropertiesManager;
046import com.sun.identity.liberty.ws.authnsvc.AuthnSvcConstants;
047import com.sun.identity.liberty.ws.authnsvc.AuthnSvcException;
048import com.sun.identity.liberty.ws.authnsvc.AuthnSvcUtils;
049
050/**
051 * The <code>Transform</code> class represents 'Transform' element in
052 * 'PasswordTransforms' element defined in Authentication Service schema.
053 *
054 * @supported.all.api
055 */
056public abstract class Transform {
057
058    /**
059     * Truncation Transform name.
060     */
061    public static final String TRUNCATION_URI = "urn:liberty:sa:pw:truncate";
062
063    /**
064     * Lowercase Transform name.
065     */
066    public static final String LOWERCASE_URI = "urn:liberty:sa:pw:lowercase";
067
068    /**
069     * Uppercase Transform name.
070     */
071    public static final String UPPERCASE_URI = "urn:liberty:sa:pw:uppercase";
072
073    /**
074     * Select Transform name.
075     */
076    public static final String SELECT_URI = "urn:liberty:sa:pw:select";
077
078    private static final String TRANSFORM_CLASSES =
079                      "com.sun.identity.liberty.ws.authnsvc.transformClasses";
080
081    private static Map transformClasses = new HashMap();
082
083    protected String name = null;
084    protected String id = null;
085    protected List parameters = null;
086
087    static {
088        String tmpstr = SystemPropertiesManager.get(TRANSFORM_CLASSES);
089        if (tmpstr != null && tmpstr.length() > 0) {
090            StringTokenizer stz = new StringTokenizer(tmpstr, ",");
091            while(stz.hasMoreTokens()) {
092                String token = stz.nextToken().trim();
093                int index = token.indexOf('|');
094                if (index != -1 && index != 0 && index != token.length() - 1) {
095                    String name = token.substring(0, index);
096                    String className = token.substring(index + 1);
097                    if (AuthnSvcUtils.debug.messageEnabled()) {
098                        AuthnSvcUtils.debug.message(
099                                      "Transform.static: add " + token);
100                    }
101                    transformClasses.put(name, className);
102                } else {
103                    if (AuthnSvcUtils.debug.warningEnabled()) {
104                        AuthnSvcUtils.debug.warning(
105                                      "Transform.static: Invalid syntax " +
106                                      "for Transform Classes List: " +
107                                      token);
108                    }
109                }
110            }          
111        }
112
113    }
114
115    static Transform getTransform(Element element) throws AuthnSvcException {
116
117        String name = XMLUtils.getNodeAttributeValue(element,
118                                                  AuthnSvcConstants.ATTR_NAME);
119        if (name == null || name.length() == 0) {
120            throw new AuthnSvcException("missingNameTF");
121        }
122
123        Transform tf = null;
124        String className = (String)transformClasses.get(name);
125        if (className != null) {
126            try {
127                tf = (Transform)Class.forName(className).newInstance();
128            } catch (Throwable t) {
129                if (AuthnSvcUtils.debug.warningEnabled()) {
130                    AuthnSvcUtils.debug.warning(
131                            "Transform.getTransform class = " + className, t);
132                }
133
134                transformClasses.remove(name);
135            }
136        }
137
138        if (tf == null) {
139            if (name.equals(TRUNCATION_URI)) {
140
141                tf = new TruncationTransform();
142            } else if (name.equals(LOWERCASE_URI)) {
143
144                tf = new LowercaseTransform();
145            } else if (name.equals(UPPERCASE_URI)) {
146
147                tf = new UppercaseTransform();
148            } else if (name.equals(SELECT_URI)) {
149
150                tf = new SelectTransform();
151            } else {
152
153                tf = new GenericTransform(name);
154            }
155        }
156
157        String id =  XMLUtils.getNodeAttributeValue(element,
158                                                    AuthnSvcConstants.ATTR_id);
159        tf.setId(id);
160
161        NodeList nl = element.getChildNodes();
162        int length = nl.getLength();
163
164        List parameters = null;
165        for(int i = 0; i < length; i++) {
166            Node child = nl.item(i);
167            if (child.getNodeType() == Node.ELEMENT_NODE) {
168                Element childElement = (Element)child;
169                String localName = childElement.getLocalName();
170                String namespaceURI = childElement.getNamespaceURI();
171
172                if (AuthnSvcConstants.NS_AUTHN_SVC.equals(namespaceURI) &&
173                    AuthnSvcConstants.TAG_PARAMETER.equals(localName)) {
174
175                    Parameter parameter = new Parameter(childElement);
176                    if (parameters == null) {
177                        parameters = new ArrayList();
178                    }
179                    parameters.add(parameter);
180                } else {
181                    throw new AuthnSvcException("invalidChildTF");
182                }
183            }
184        }
185
186        tf.setParameters(parameters);
187
188        return tf;
189    }
190
191
192    /**
193     * Transforms password.
194     * @param password original password
195     * @return transformed password
196     */
197    public abstract String transform(String password);
198
199    /**
200     * Returns value of 'name' attribute.
201     * @return value of 'name' attribute
202     */
203    public String getName()
204    {
205        return name;
206    }
207
208    /**
209     * Returns value of 'id' attribute.
210     * @return value of 'id' attribute
211     * @see #setId(String)
212     */
213    public String getId()
214    {
215        return id;
216    }
217
218    /**
219     * Returns a list of 'Parameter' child element.
220     * @return a list of 'Parameter' child element
221     * @see #setParameters(List)
222     */
223    public List getParameters()
224    {
225        return parameters;
226    }
227
228    /**
229     * Sets value of 'id' attribute.
230     * @param id value of 'id' attribute
231     * @see #getId()
232     */
233    public void setId(String id)
234    {
235        this.id = id;
236    }
237
238    /**
239     * Sets a list of 'Parameter' child element.
240     * @param parameters a list of 'Parameter' child element
241     * @see #getParameters()
242     */
243    public void setParameters(List parameters)
244    {
245        this.parameters = parameters;
246    }
247
248    /**
249     * Converts this to <code>org.w3c.dom.Element</code> and add to
250     * parent PasswordTransforms Element.
251     * @param ptE parent PasswordTransforms Element
252     * @exception AuthnSvcException if there is 'name' attribute is empty
253     */
254    void addToParent(Element ptE) throws AuthnSvcException
255    {
256        if (name == null || name.length() == 0) {
257            throw new AuthnSvcException("missingNameTF");
258        }
259
260        Document doc = ptE.getOwnerDocument();
261        Element tfE = doc.createElementNS(
262                            AuthnSvcConstants.NS_AUTHN_SVC,
263                            AuthnSvcConstants.PTAG_TRANSFORM);
264        ptE.appendChild(tfE);
265
266        tfE.setAttributeNS(null, AuthnSvcConstants.ATTR_NAME, name);
267
268        if (id != null) {
269            tfE.setAttributeNS(null, AuthnSvcConstants.ATTR_id, id);
270        }
271
272        if (parameters != null && !parameters.isEmpty()) {
273            for(Iterator iter = parameters.iterator(); iter.hasNext(); ) {
274                Parameter parameter = (Parameter)iter.next();
275                parameter.addToParent(tfE);
276            }
277        }
278
279    }
280}