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-2016 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 */ 038public class LDAPEntryReader extends BackgroundTask<CustomSearchResult> 039{ 040 private final String dn; 041 private final InitialLdapContext ctx; 042 private final Set<EntryReadListener> listeners = new HashSet<>(); 043 private boolean isOver; 044 private boolean notifyListeners; 045 046 /** 047 * Constructor of the entry reader. 048 * @param dn the DN of the entry. 049 * @param ctx the connection to the server. 050 */ 051 public LDAPEntryReader(String dn, InitialLdapContext ctx) 052 { 053 this.dn = dn; 054 this.ctx = ctx; 055 this.notifyListeners = true; 056 } 057 058 @Override 059 public CustomSearchResult processBackgroundTask() throws Throwable 060 { 061 isOver = false; 062 NamingEnumeration<SearchResult> en = null; 063 try 064 { 065 SearchControls controls = new SearchControls(); 066 067 String[] attrs = {"*", "+"}; 068 controls.setReturningAttributes(attrs); 069 controls.setSearchScope(SearchControls.OBJECT_SCOPE); 070 final String filter = "(|(objectclass=*)(objectclass=ldapsubentry))"; 071 072 en = ctx.search(Utilities.getJNDIName(dn), filter, controls); 073 074 SearchResult sr = null; 075 while (en.hasMore()) 076 { 077 sr = en.next(); 078 } 079 080 return new CustomSearchResult(sr, dn); 081 } 082 finally 083 { 084 if (isInterrupted()) 085 { 086 isOver = true; 087 } 088 if (en != null) 089 { 090 en.close(); 091 } 092 } 093 } 094 095 @Override 096 public void backgroundTaskCompleted(CustomSearchResult sr, 097 Throwable throwable) 098 { 099 if (!isInterrupted() && isNotifyListeners()) 100 { 101 if (throwable == null) 102 { 103 notifyListeners(sr); 104 } 105 else 106 { 107 notifyListeners(throwable); 108 } 109 } 110 isOver = true; 111 } 112 113 /** 114 * Returns whether this entry reader will notify the listeners once it is 115 * over. 116 * @return whether this entry reader will notify the listeners once it is 117 * over. 118 */ 119 public boolean isNotifyListeners() 120 { 121 return notifyListeners; 122 } 123 124 /** 125 * Sets whether this entry reader will notify the listeners once it is 126 * over. 127 * @param notifyListeners whether this entry reader will notify the listeners 128 * once it is over. 129 */ 130 public void setNotifyListeners(boolean notifyListeners) 131 { 132 this.notifyListeners = notifyListeners; 133 } 134 135 /** 136 * Returns <CODE>true</CODE> if the read process is over and 137 * <CODE>false</CODE> otherwise. 138 * @return <CODE>true</CODE> if the read process is over and 139 * <CODE>false</CODE> otherwise. 140 */ 141 public boolean isOver() 142 { 143 return isOver; 144 } 145 146 /** 147 * Notifies listeners that a new entry was read. 148 * @param sr the new entry in form of CustomSearchResult. 149 */ 150 private void notifyListeners(CustomSearchResult sr) 151 { 152 EntryReadEvent ev = new EntryReadEvent(this, sr); 153 for (EntryReadListener listener : listeners) 154 { 155 listener.entryRead(ev); 156 } 157 } 158 159 /** 160 * Notifies the listeners that an error occurred reading an entry. 161 * @param t the error that occurred reading an entry. 162 */ 163 private void notifyListeners(Throwable t) 164 { 165 EntryReadErrorEvent ev = new EntryReadErrorEvent(this, dn, t); 166 for (EntryReadListener listener : listeners) 167 { 168 listener.entryReadError(ev); 169 } 170 } 171 172 /** 173 * Adds an EntryReadListener. 174 * @param listener the listener. 175 */ 176 public void addEntryReadListener(EntryReadListener listener) 177 { 178 listeners.add(listener); 179 } 180 181 /** 182 * Removes an EntryReadListener. 183 * @param listener the listener. 184 */ 185 public void removeEntryReadListener(EntryReadListener listener) 186 { 187 listeners.remove(listener); 188 } 189}