001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2015 ForgeRock AS. 016 */ 017 018package org.opends.guitools.controlpanel.util; 019 020import java.util.HashSet; 021import java.util.Set; 022 023import javax.naming.NamingEnumeration; 024import javax.naming.directory.SearchControls; 025import javax.naming.directory.SearchResult; 026import javax.naming.ldap.InitialLdapContext; 027 028import org.opends.guitools.controlpanel.datamodel.CustomSearchResult; 029import org.opends.guitools.controlpanel.event.EntryReadErrorEvent; 030import org.opends.guitools.controlpanel.event.EntryReadEvent; 031import org.opends.guitools.controlpanel.event.EntryReadListener; 032 033/** 034 * A class that reads an entry on the background. This is used in the LDAP 035 * entries browser. When the entry is read it notifies to the EntryReadListener 036 * objects that have been registered. 037 * 038 */ 039public class LDAPEntryReader extends BackgroundTask<CustomSearchResult> 040{ 041 private final String dn; 042 private final InitialLdapContext ctx; 043 private final Set<EntryReadListener> listeners = new HashSet<>(); 044 private boolean isOver; 045 private boolean notifyListeners; 046 047 /** 048 * Constructor of the entry reader. 049 * @param dn the DN of the entry. 050 * @param ctx the connection to the server. 051 */ 052 public LDAPEntryReader(String dn, InitialLdapContext ctx) 053 { 054 this.dn = dn; 055 this.ctx = ctx; 056 this.notifyListeners = true; 057 } 058 059 /** {@inheritDoc} */ 060 @Override 061 public CustomSearchResult processBackgroundTask() throws Throwable 062 { 063 isOver = false; 064 NamingEnumeration<SearchResult> en = null; 065 try 066 { 067 SearchControls controls = new SearchControls(); 068 069 String[] attrs = {"*", "+"}; 070 controls.setReturningAttributes(attrs); 071 controls.setSearchScope(SearchControls.OBJECT_SCOPE); 072 final String filter = "(|(objectclass=*)(objectclass=ldapsubentry))"; 073 074 en = ctx.search(Utilities.getJNDIName(dn), filter, controls); 075 076 SearchResult sr = null; 077 while (en.hasMore()) 078 { 079 sr = en.next(); 080 } 081 082 return new CustomSearchResult(sr, dn); 083 } 084 finally 085 { 086 if (isInterrupted()) 087 { 088 isOver = true; 089 } 090 if (en != null) 091 { 092 en.close(); 093 } 094 } 095 } 096 097 /** {@inheritDoc} */ 098 @Override 099 public void backgroundTaskCompleted(CustomSearchResult sr, 100 Throwable throwable) 101 { 102 if (!isInterrupted() && isNotifyListeners()) 103 { 104 if (throwable == null) 105 { 106 notifyListeners(sr); 107 } 108 else 109 { 110 notifyListeners(throwable); 111 } 112 } 113 isOver = true; 114 } 115 116 /** 117 * Returns whether this entry reader will notify the listeners once it is 118 * over. 119 * @return whether this entry reader will notify the listeners once it is 120 * over. 121 */ 122 public boolean isNotifyListeners() 123 { 124 return notifyListeners; 125 } 126 127 /** 128 * Sets whether this entry reader will notify the listeners once it is 129 * over. 130 * @param notifyListeners whether this entry reader will notify the listeners 131 * once it is over. 132 */ 133 public void setNotifyListeners(boolean notifyListeners) 134 { 135 this.notifyListeners = notifyListeners; 136 } 137 138 /** 139 * Returns <CODE>true</CODE> if the read process is over and 140 * <CODE>false</CODE> otherwise. 141 * @return <CODE>true</CODE> if the read process is over and 142 * <CODE>false</CODE> otherwise. 143 */ 144 public boolean isOver() 145 { 146 return isOver; 147 } 148 149 /** 150 * Notifies listeners that a new entry was read. 151 * @param sr the new entry in form of CustomSearchResult. 152 */ 153 private void notifyListeners(CustomSearchResult sr) 154 { 155 EntryReadEvent ev = new EntryReadEvent(this, sr); 156 for (EntryReadListener listener : listeners) 157 { 158 listener.entryRead(ev); 159 } 160 } 161 162 /** 163 * Notifies the listeners that an error occurred reading an entry. 164 * @param t the error that occurred reading an entry. 165 */ 166 private void notifyListeners(Throwable t) 167 { 168 EntryReadErrorEvent ev = new EntryReadErrorEvent(this, dn, t); 169 for (EntryReadListener listener : listeners) 170 { 171 listener.entryReadError(ev); 172 } 173 } 174 175 /** 176 * Adds an EntryReadListener. 177 * @param listener the listener. 178 */ 179 public void addEntryReadListener(EntryReadListener listener) 180 { 181 listeners.add(listener); 182 } 183 184 /** 185 * Removes an EntryReadListener. 186 * @param listener the listener. 187 */ 188 public void removeEntryReadListener(EntryReadListener listener) 189 { 190 listeners.remove(listener); 191 } 192}