package com.hwlcn.ldap.ldap.protocol; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import com.hwlcn.ldap.asn1.ASN1Boolean; import com.hwlcn.ldap.asn1.ASN1Buffer; import com.hwlcn.ldap.asn1.ASN1BufferSequence; import com.hwlcn.ldap.asn1.ASN1Element; import com.hwlcn.ldap.asn1.ASN1Enumerated; import com.hwlcn.ldap.asn1.ASN1Integer; import com.hwlcn.ldap.asn1.ASN1OctetString; import com.hwlcn.ldap.asn1.ASN1Sequence; import com.hwlcn.ldap.asn1.ASN1StreamReader; import com.hwlcn.ldap.asn1.ASN1StreamReaderSequence; import com.hwlcn.ldap.ldap.sdk.Control; import com.hwlcn.ldap.ldap.sdk.DereferencePolicy; import com.hwlcn.ldap.ldap.sdk.Filter; import com.hwlcn.ldap.ldap.sdk.LDAPException; import com.hwlcn.ldap.ldap.sdk.ResultCode; import com.hwlcn.ldap.ldap.sdk.SearchRequest; import com.hwlcn.ldap.ldap.sdk.SearchScope; import com.hwlcn.core.annotation.NotMutable; import com.hwlcn.core.annotation.InternalUseOnly; import com.hwlcn.core.annotation.ThreadSafety; import com.hwlcn.ldap.util.ThreadSafetyLevel; import static com.hwlcn.ldap.ldap.protocol.ProtocolMessages.*; import static com.hwlcn.ldap.util.Debug.*; import static com.hwlcn.ldap.util.StaticUtils.*; @InternalUseOnly() @NotMutable() @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) public final class SearchRequestProtocolOp implements ProtocolOp { private static final long serialVersionUID = -8521750809606744181L; private final boolean typesOnly; private final DereferencePolicy derefPolicy; private final Filter filter; private final int sizeLimit; private final int timeLimit; private final List<String> attributes; private final SearchScope scope; private final String baseDN; public SearchRequestProtocolOp(final String baseDN, final SearchScope scope, final DereferencePolicy derefPolicy, final int sizeLimit, final int timeLimit, final boolean typesOnly, final Filter filter, final List<String> attributes) { this.scope = scope; this.derefPolicy = derefPolicy; this.typesOnly = typesOnly; this.filter = filter; if (baseDN == null) { this.baseDN = ""; } else { this.baseDN = baseDN; } if (sizeLimit > 0) { this.sizeLimit = sizeLimit; } else { this.sizeLimit = 0; } if (timeLimit > 0) { this.timeLimit = timeLimit; } else { this.timeLimit = 0; } if (attributes == null) { this.attributes = Collections.emptyList(); } else { this.attributes = Collections.unmodifiableList(attributes); } } public SearchRequestProtocolOp(final SearchRequest request) { baseDN = request.getBaseDN(); scope = request.getScope(); derefPolicy = request.getDereferencePolicy(); sizeLimit = request.getSizeLimit(); timeLimit = request.getTimeLimitSeconds(); typesOnly = request.typesOnly(); filter = request.getFilter(); attributes = request.getAttributeList(); } SearchRequestProtocolOp(final ASN1StreamReader reader) throws LDAPException { try { reader.beginSequence(); baseDN = reader.readString(); scope = SearchScope.valueOf(reader.readEnumerated()); derefPolicy = DereferencePolicy.valueOf(reader.readEnumerated()); sizeLimit = reader.readInteger(); timeLimit = reader.readInteger(); typesOnly = reader.readBoolean(); filter = Filter.readFrom(reader); final ArrayList<String> attrs = new ArrayList<String>(5); final ASN1StreamReaderSequence attrSequence = reader.beginSequence(); while (attrSequence.hasMoreElements()) { attrs.add(reader.readString()); } attributes = Collections.unmodifiableList(attrs); } catch (LDAPException le) { debugException(le); throw le; } catch (Exception e) { debugException(e); throw new LDAPException(ResultCode.DECODING_ERROR, ERR_SEARCH_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e); } } public String getBaseDN() { return baseDN; } public SearchScope getScope() { return scope; } public DereferencePolicy getDerefPolicy() { return derefPolicy; } public int getSizeLimit() { return sizeLimit; } public int getTimeLimit() { return timeLimit; } public boolean typesOnly() { return typesOnly; } public Filter getFilter() { return filter; } public List<String> getAttributes() { return attributes; } public byte getProtocolOpType() { return LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_REQUEST; } public ASN1Element encodeProtocolOp() { final ArrayList<ASN1Element> attrElements = new ArrayList<ASN1Element>(attributes.size()); for (final String attribute : attributes) { attrElements.add(new ASN1OctetString(attribute)); } return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_REQUEST, new ASN1OctetString(baseDN), new ASN1Enumerated(scope.intValue()), new ASN1Enumerated(derefPolicy.intValue()), new ASN1Integer(sizeLimit), new ASN1Integer(timeLimit), new ASN1Boolean(typesOnly), filter.encode(), new ASN1Sequence(attrElements)); } public static SearchRequestProtocolOp decodeProtocolOp( final ASN1Element element) throws LDAPException { try { final ASN1Element[] elements = ASN1Sequence.decodeAsSequence(element).elements(); final String baseDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); final SearchScope scope = SearchScope.valueOf( ASN1Enumerated.decodeAsEnumerated(elements[1]).intValue()); final DereferencePolicy derefPolicy = DereferencePolicy.valueOf( ASN1Enumerated.decodeAsEnumerated(elements[2]).intValue()); final int sizeLimit = ASN1Integer.decodeAsInteger(elements[3]).intValue(); final int timeLimit = ASN1Integer.decodeAsInteger(elements[4]).intValue(); final boolean typesOnly = ASN1Boolean.decodeAsBoolean(elements[5]).booleanValue(); final Filter filter = Filter.decode(elements[6]); final ASN1Element[] attrElements = ASN1Sequence.decodeAsSequence(elements[7]).elements(); final ArrayList<String> attributes = new ArrayList<String>(attrElements.length); for (final ASN1Element e : attrElements) { attributes.add(ASN1OctetString.decodeAsOctetString(e).stringValue()); } return new SearchRequestProtocolOp(baseDN, scope, derefPolicy, sizeLimit, timeLimit, typesOnly, filter, attributes); } catch (final Exception e) { debugException(e); throw new LDAPException(ResultCode.DECODING_ERROR, ERR_SEARCH_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e); } } public void writeTo(final ASN1Buffer buffer) { final ASN1BufferSequence opSequence = buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_REQUEST); buffer.addOctetString(baseDN); buffer.addEnumerated(scope.intValue()); buffer.addEnumerated(derefPolicy.intValue()); buffer.addInteger(sizeLimit); buffer.addInteger(timeLimit); buffer.addBoolean(typesOnly); filter.writeTo(buffer); final ASN1BufferSequence attrSequence = buffer.beginSequence(); for (final String s : attributes) { buffer.addOctetString(s); } attrSequence.end(); opSequence.end(); } public SearchRequest toSearchRequest(final Control... controls) { final String[] attrArray = new String[attributes.size()]; attributes.toArray(attrArray); return new SearchRequest(null, controls, baseDN, scope, derefPolicy, sizeLimit, timeLimit, typesOnly, filter, attrArray); } @Override() public String toString() { final StringBuilder buffer = new StringBuilder(); toString(buffer); return buffer.toString(); } public void toString(final StringBuilder buffer) { buffer.append("SearchRequestProtocolOp(baseDN='"); buffer.append(baseDN); buffer.append("', scope='"); buffer.append(scope.toString()); buffer.append("', derefPolicy='"); buffer.append(derefPolicy.toString()); buffer.append("', sizeLimit="); buffer.append(sizeLimit); buffer.append(", timeLimit="); buffer.append(timeLimit); buffer.append(", typesOnly="); buffer.append(typesOnly); buffer.append(", filter='"); filter.toString(buffer); buffer.append("', attributes={"); final Iterator<String> iterator = attributes.iterator(); while (iterator.hasNext()) { buffer.append(iterator.next()); if (iterator.hasNext()) { buffer.append(','); } } buffer.append("})"); } }