PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/vt-ldap/branches/vt-ldap-3/src/main/java/edu/vt/middleware/ldap/ldif/Ldif.java

http://vt-middleware.googlecode.com/
Java | 398 lines | 241 code | 39 blank | 118 comment | 81 complexity | 7a7c086d093c3a777e10477c2d054352 MD5 | raw file
Possible License(s): GPL-3.0, Apache-2.0, LGPL-3.0, LGPL-2.1
  1. /*
  2. $Id: Ldif.java 1330 2010-05-23 22:10:53Z dfisher $
  3. Copyright (C) 2003-2010 Virginia Tech.
  4. All rights reserved.
  5. SEE LICENSE FOR MORE INFORMATION
  6. Author: Middleware Services
  7. Email: middleware@vt.edu
  8. Version: $Revision: 1330 $
  9. Updated: $Date: 2010-05-24 00:10:53 +0200 (Mon, 24 May 2010) $
  10. */
  11. package edu.vt.middleware.ldap.ldif;
  12. import java.io.BufferedReader;
  13. import java.io.IOException;
  14. import java.io.Reader;
  15. import java.io.Serializable;
  16. import java.io.Writer;
  17. import java.net.URL;
  18. import java.util.Iterator;
  19. import javax.naming.NamingException;
  20. import javax.naming.directory.SearchResult;
  21. import edu.vt.middleware.ldap.LdapUtil;
  22. import edu.vt.middleware.ldap.bean.LdapAttribute;
  23. import edu.vt.middleware.ldap.bean.LdapBeanFactory;
  24. import edu.vt.middleware.ldap.bean.LdapBeanProvider;
  25. import edu.vt.middleware.ldap.bean.LdapEntry;
  26. import edu.vt.middleware.ldap.bean.LdapResult;
  27. import org.apache.commons.logging.Log;
  28. import org.apache.commons.logging.LogFactory;
  29. /**
  30. * <code>Ldif</code> contains functions for converting LDAP search result sets
  31. * into LDIF.
  32. *
  33. * @author Middleware Services
  34. * @version $Revision: 1330 $ $Date: 2010-05-24 00:10:53 +0200 (Mon, 24 May 2010) $
  35. */
  36. public class Ldif implements Serializable
  37. {
  38. /** ASCII decimal value of nul. */
  39. public static final int NUL_CHAR = 0;
  40. /** ASCII decimal value of line feed. */
  41. public static final int LF_CHAR = 10;
  42. /** ASCII decimal value of carriage return. */
  43. public static final int CR_CHAR = 13;
  44. /** ASCII decimal value of space. */
  45. public static final int SP_CHAR = 32;
  46. /** ASCII decimal value of colon. */
  47. public static final int COLON_CHAR = 58;
  48. /** ASCII decimal value of left arrow. */
  49. public static final int LA_CHAR = 60;
  50. /** ASCII decimal value of highest character. */
  51. public static final int MAX_ASCII_CHAR = 127;
  52. /** serial version uid. */
  53. private static final long serialVersionUID = -3763879179455001975L;
  54. /** Line separator. */
  55. private static final String LINE_SEPARATOR = System.getProperty(
  56. "line.separator");
  57. /** Log for this class. */
  58. protected final Log logger = LogFactory.getLog(this.getClass());
  59. /** Ldap bean factory. */
  60. protected LdapBeanFactory beanFactory = LdapBeanProvider.getLdapBeanFactory();
  61. /**
  62. * Returns the factory for creating ldap beans.
  63. *
  64. * @return <code>LdapBeanFactory</code>
  65. */
  66. public LdapBeanFactory getLdapBeanFactory()
  67. {
  68. return this.beanFactory;
  69. }
  70. /**
  71. * Sets the factory for creating ldap beans.
  72. *
  73. * @param lbf <code>LdapBeanFactory</code>
  74. */
  75. public void setLdapBeanFactory(final LdapBeanFactory lbf)
  76. {
  77. if (lbf != null) {
  78. this.beanFactory = lbf;
  79. }
  80. }
  81. /**
  82. * This will take the results of a prior LDAP query and convert it to LDIF.
  83. *
  84. * @param results <code>Iterator</code> of LDAP search results
  85. *
  86. * @return <code>String</code>
  87. */
  88. public String createLdif(final Iterator<SearchResult> results)
  89. {
  90. String ldif = "";
  91. try {
  92. final LdapResult lr = this.beanFactory.newLdapResult();
  93. lr.addEntries(results);
  94. ldif = this.createLdif(lr);
  95. } catch (NamingException e) {
  96. if (this.logger.isErrorEnabled()) {
  97. this.logger.error("Error creating String from SearchResults", e);
  98. }
  99. }
  100. return ldif;
  101. }
  102. /**
  103. * This will take the results of a prior LDAP query and convert it to LDIF.
  104. *
  105. * @param result <code>LdapResult</code>
  106. *
  107. * @return <code>String</code>
  108. */
  109. public String createLdif(final LdapResult result)
  110. {
  111. // build string from results
  112. final StringBuffer ldif = new StringBuffer();
  113. if (result != null) {
  114. for (LdapEntry le : result.getEntries()) {
  115. ldif.append(createLdifEntry(le));
  116. }
  117. }
  118. return ldif.toString();
  119. }
  120. /**
  121. * This will take an LDAP entry and convert it to LDIF.
  122. *
  123. * @param ldapEntry <code>LdapEntry</code> to convert
  124. *
  125. * @return <code>String</code>
  126. */
  127. protected String createLdifEntry(final LdapEntry ldapEntry)
  128. {
  129. final StringBuffer entry = new StringBuffer();
  130. if (ldapEntry != null) {
  131. final String dn = ldapEntry.getDn();
  132. if (dn != null) {
  133. if (encodeData(dn)) {
  134. final String encodedDn = LdapUtil.base64Encode(dn);
  135. if (encodedDn != null) {
  136. entry.append("dn:: ").append(dn).append(LINE_SEPARATOR);
  137. }
  138. } else {
  139. entry.append("dn: ").append(dn).append(LINE_SEPARATOR);
  140. }
  141. }
  142. for (LdapAttribute attr : ldapEntry.getLdapAttributes().getAttributes()) {
  143. final String attrName = attr.getName();
  144. for (Object attrValue : attr.getValues()) {
  145. if (encodeData(attrValue)) {
  146. String encodedAttrValue = null;
  147. if (attrValue instanceof String) {
  148. encodedAttrValue = LdapUtil.base64Encode((String) attrValue);
  149. } else if (attrValue instanceof byte[]) {
  150. encodedAttrValue = LdapUtil.base64Encode((byte[]) attrValue);
  151. } else {
  152. if (this.logger.isWarnEnabled()) {
  153. this.logger.warn(
  154. "Could not cast attribute value as a byte[]" +
  155. " or a String");
  156. }
  157. }
  158. if (encodedAttrValue != null) {
  159. entry.append(attrName).append(":: ").append(encodedAttrValue)
  160. .append(LINE_SEPARATOR);
  161. }
  162. } else {
  163. entry.append(attrName).append(": ").append(attrValue).append(
  164. LINE_SEPARATOR);
  165. }
  166. }
  167. }
  168. }
  169. if (entry.length() > 0) {
  170. entry.append(LINE_SEPARATOR);
  171. }
  172. return entry.toString();
  173. }
  174. /**
  175. * This determines whether the supplied data should be base64 encoded. See
  176. * http://www.faqs.org/rfcs/rfc2849.html for more details.
  177. *
  178. * @param data <code>Object</code> to inspect
  179. *
  180. * @return <code>boolean</code>
  181. */
  182. private boolean encodeData(final Object data)
  183. {
  184. boolean encode = false;
  185. if (data instanceof String) {
  186. final String stringData = (String) data;
  187. final char[] dataCharArray = stringData.toCharArray();
  188. for (int i = 0; i < dataCharArray.length; i++) {
  189. final int charInt = (int) dataCharArray[i];
  190. // check for NUL
  191. if (charInt == NUL_CHAR) {
  192. encode = true;
  193. // check for LF
  194. } else if (charInt == LF_CHAR) {
  195. encode = true;
  196. // check for CR
  197. } else if (charInt == CR_CHAR) {
  198. encode = true;
  199. // check for SP at beginning or end of string
  200. } else if (
  201. charInt == SP_CHAR &&
  202. (i == 0 || i == dataCharArray.length - 1)) {
  203. encode = true;
  204. // check for colon(:) at beginning of string
  205. } else if (charInt == COLON_CHAR && i == 0) {
  206. encode = true;
  207. // check for left arrow(<) at beginning of string
  208. } else if (charInt == LA_CHAR && i == 0) {
  209. encode = true;
  210. // check for any character above 127
  211. } else if (charInt > MAX_ASCII_CHAR) {
  212. encode = true;
  213. }
  214. }
  215. } else {
  216. encode = true;
  217. }
  218. return encode;
  219. }
  220. /**
  221. * This will write the supplied LDAP search results to the supplied writer in
  222. * LDIF form.
  223. *
  224. * @param results <code>Iterator</code> of LDAP search results
  225. * @param writer <code>Writer</code> to write to
  226. *
  227. * @throws IOException if an error occurs while writing to the output stream
  228. */
  229. public void outputLdif(
  230. final Iterator<SearchResult> results,
  231. final Writer writer)
  232. throws IOException
  233. {
  234. writer.write(createLdif(results));
  235. writer.flush();
  236. }
  237. /**
  238. * This will write the supplied LDAP search results to the supplied writer in
  239. * LDIF form.
  240. *
  241. * @param result <code>LdapResult</code>
  242. * @param writer <code>Writer</code> to write to
  243. *
  244. * @throws IOException if an error occurs while writing to the output stream
  245. */
  246. public void outputLdif(final LdapResult result, final Writer writer)
  247. throws IOException
  248. {
  249. writer.write(createLdif(result));
  250. writer.flush();
  251. }
  252. /**
  253. * This will take a Reader containing an LDIF and convert it to an Iterator of
  254. * LDAP search results. Provides a loose implementation of RFC 2849. Should
  255. * not be used to validate LDIF format as it does not enforce strictness.
  256. *
  257. * @param reader <code>Reader</code> containing LDIF content
  258. *
  259. * @return <code>Iterator</code> - of LDAP search results
  260. *
  261. * @throws IOException if an I/O error occurs
  262. */
  263. public Iterator<SearchResult> importLdif(final Reader reader)
  264. throws IOException
  265. {
  266. return this.importLdifToLdapResult(reader).toSearchResults().iterator();
  267. }
  268. /**
  269. * This will take a Reader containing an LDIF and convert it to an <code>
  270. * LdapResult</code>. Provides a loose implementation of RFC 2849. Should not
  271. * be used to validate LDIF format as it does not enforce strictness.
  272. *
  273. * @param reader <code>Reader</code> containing LDIF content
  274. *
  275. * @return <code>LdapResult</code> - LDAP search results
  276. *
  277. * @throws IOException if an I/O error occurs
  278. */
  279. public LdapResult importLdifToLdapResult(final Reader reader)
  280. throws IOException
  281. {
  282. final LdapResult ldapResult = this.beanFactory.newLdapResult();
  283. final BufferedReader br = new BufferedReader(reader);
  284. String line = null;
  285. int lineCount = 0;
  286. LdapEntry ldapEntry = null;
  287. StringBuffer lineValue = new StringBuffer();
  288. while ((line = br.readLine()) != null) {
  289. lineCount++;
  290. if (line.startsWith("dn:")) {
  291. lineValue.append(line);
  292. ldapEntry = this.beanFactory.newLdapEntry();
  293. break;
  294. }
  295. }
  296. boolean read = true;
  297. while (read) {
  298. line = br.readLine();
  299. if (line == null) {
  300. read = false;
  301. line = "";
  302. }
  303. if (!line.startsWith("#")) {
  304. if (line.startsWith("dn:")) {
  305. ldapResult.addEntry(ldapEntry);
  306. ldapEntry = this.beanFactory.newLdapEntry();
  307. }
  308. if (line.startsWith(" ")) {
  309. lineValue.append(line.substring(1));
  310. } else {
  311. final String s = lineValue.toString();
  312. if (s.indexOf(":") != -1) {
  313. boolean isBinary = false;
  314. boolean isUrl = false;
  315. final String[] parts = s.split(":", 2);
  316. final String attrName = parts[0];
  317. String attrValue = parts[1];
  318. if (attrValue.startsWith(":")) {
  319. isBinary = true;
  320. attrValue = attrValue.substring(1);
  321. } else if (attrValue.startsWith("<")) {
  322. isUrl = true;
  323. attrValue = attrValue.substring(1);
  324. }
  325. if (attrValue.startsWith(" ")) {
  326. attrValue = attrValue.substring(1);
  327. }
  328. if ("dn".equals(attrName)) {
  329. ldapEntry.setDn(attrValue);
  330. } else {
  331. LdapAttribute ldapAttr = ldapEntry.getLdapAttributes()
  332. .getAttribute(attrName);
  333. if (ldapAttr == null) {
  334. ldapAttr = this.beanFactory.newLdapAttribute();
  335. ldapAttr.setName(attrName);
  336. ldapEntry.getLdapAttributes().addAttribute(ldapAttr);
  337. }
  338. if (isBinary) {
  339. ldapAttr.getValues().add(LdapUtil.base64Decode(attrValue));
  340. } else if (isUrl) {
  341. ldapAttr.getValues().add(LdapUtil.readURL(new URL(attrValue)));
  342. } else {
  343. ldapAttr.getValues().add(attrValue);
  344. }
  345. }
  346. }
  347. lineValue = new StringBuffer(line);
  348. }
  349. }
  350. }
  351. if (ldapEntry != null) {
  352. ldapResult.addEntry(ldapEntry);
  353. }
  354. return ldapResult;
  355. }
  356. }