001: /*
002: * Copyright 2007 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: */
013: package com.pentaho.security.ldap.transform;
014:
015: import java.util.HashSet;
016: import java.util.Set;
017:
018: import javax.naming.NamingEnumeration;
019: import javax.naming.NamingException;
020: import javax.naming.directory.Attribute;
021: import javax.naming.directory.SearchResult;
022:
023: import org.apache.commons.collections.Transformer;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.springframework.beans.factory.InitializingBean;
027: import org.springframework.util.Assert;
028: import org.springframework.util.StringUtils;
029:
030: import org.pentaho.messages.Messages;
031:
032: /**
033: * Extracts the value of the token <code>tokenName</code> from the attribute
034: * <code>attributeName</code>. Ignores attribute value if value is not of
035: * type <code>String</code>. Returns the entire attribute value if
036: * <code>tokenName</code> is not specified.
037: * <p>
038: * <strong>Note: This transformer can produce more than one output (in the form
039: * of a collection) per single input. Any client of this class should merge the
040: * results (e.g. <code>collection.addAll(collection)</code>) into an existing
041: * collection.</strong>
042: * </p>
043: *
044: * <p>
045: * Transformer input: <code>SearchResult</code> instance
046: * </p>
047: * <p>
048: * Transformer output: <code>Collection</code> of <code>String</code>
049: * instances
050: * </p>
051: * TODO refactor into searchresulttoattributelist,
052: * attributelisttosingleattribute, attributestringtoattributesubstring
053: *
054: * @author mlowery
055: */
056: public class SearchResultToAttrValueList implements Transformer,
057: InitializingBean {
058:
059: // ~ Static fields/initializers ============================================
060: private static final Log logger = LogFactory
061: .getLog(SearchResultToAttrValueList.class);
062:
063: // ~ Instance fields =======================================================
064:
065: private String attributeName;
066:
067: private String tokenName;
068:
069: // ~ Constructors ==========================================================
070:
071: public SearchResultToAttrValueList(final String attributeName) {
072: this (attributeName, null);
073: }
074:
075: public SearchResultToAttrValueList(final String attributeName,
076: final String tokenName) {
077: super ();
078: this .attributeName = attributeName;
079: this .tokenName = tokenName;
080: }
081:
082: // ~ Methods ===============================================================
083:
084: /**
085: * Assumes that <code>src</code> consists of name-value pairs linked via
086: * <code>'='</code> and each pair separated by <code>','</code>.
087: *
088: * @param src
089: * the source string
090: * @param inTokenName
091: * the name part of the name-value pair whose value will be
092: * returned
093: * @return the value part of the name-value pair whose name part is
094: * <code>tokenName</code>
095: */
096: protected String extract(final String src, final String inTokenName) {
097: if (logger.isDebugEnabled()) {
098: logger
099: .debug(Messages
100: .getString(
101: "SearchResultToAttrValueList.DEBUG_LOOKING_FOR_SUBSTRING", inTokenName, src)); //$NON-NLS-1$
102: }
103: String[] tokens = src.split(","); //$NON-NLS-1$
104: for (int i = 0; i < tokens.length; i++) {
105: String rdnString = tokens[i];
106: String[] rdnTokens = rdnString.split("="); //$NON-NLS-1$
107: if (rdnTokens[0].trim().equals(inTokenName)) {
108: if (logger.isDebugEnabled()) {
109: logger
110: .debug(Messages
111: .getString(
112: "SearchResultToAttrValueList.DEBUG_EXTRACTED_TOKEN", rdnTokens[1].trim())); //$NON-NLS-1$
113: }
114: return rdnTokens[1].trim();
115: }
116: }
117: if (logger.isDebugEnabled()) {
118: logger
119: .debug(Messages
120: .getString(
121: "SearchResultToAttrValueList.DEBUG_TOKEN_NOT_FOUND", inTokenName, src)); //$NON-NLS-1$
122: }
123: return null;
124: }
125:
126: public void afterPropertiesSet() throws Exception {
127: Assert.hasLength(attributeName);
128: }
129:
130: public Object transform(final Object obj) {
131: Object transformed = obj;
132: if (obj instanceof SearchResult) {
133: transformed = new HashSet();
134: Set valueSet = (Set) transformed;
135: SearchResult res = (SearchResult) obj;
136: if (logger.isDebugEnabled()) {
137: logger
138: .debug(Messages
139: .getString(
140: "SearchResultToAttrValueList.DEBUG_ATTRIBUTES_FROM_SEARCHRESULT", (null != res.getAttributes()) ? res.getAttributes().toString() : "null")); //$NON-NLS-1$ //$NON-NLS-2$
141: }
142: Attribute attr = res.getAttributes().get(attributeName);
143: if (logger.isDebugEnabled()) {
144: logger
145: .debug(Messages
146: .getString(
147: "SearchResultToAttrValueList.DEBUG_ATTRIBUTE_VALUE", attributeName, (null != attr) ? attr.toString() : "null")); //$NON-NLS-1$ //$NON-NLS-2$
148: }
149: try {
150: NamingEnumeration values = attr.getAll();
151: while (values.hasMore()) {
152: // if tokenName was specified, extract from value; otherwise
153: // store value unchanged
154: Object value = values.next();
155: if (StringUtils.hasLength(tokenName)) {
156: if (null != value && value instanceof String) {
157: String tokenValue = extract((String) value,
158: tokenName);
159: if (null != tokenValue) {
160: valueSet.add(tokenValue);
161: }
162: } else {
163: if (logger.isWarnEnabled()) {
164: logger
165: .warn(Messages
166: .getString("SearchResultToAttrValueList.WARN_ATTRIBUTE_NOT_A_STRING")); //$NON-NLS-1$
167: }
168: }
169: } else {
170: if (null != value) {
171: valueSet.add(value.toString());
172: }
173: }
174: }
175: } catch (NamingException e) {
176: if (logger.isErrorEnabled()) {
177: logger
178: .error(
179: Messages
180: .getErrorString("SearchResultToAttrValueList.ERROR_0001_NAMING_EXCEPTION"), e); //$NON-NLS-1$
181: }
182: }
183: return transformed;
184:
185: }
186: return transformed;
187:
188: }
189: }
|