001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2012-2015 ForgeRock AS 026 */ 027package org.opends.server.extensions; 028 029import java.util.List; 030 031import org.forgerock.i18n.LocalizableMessage; 032import org.forgerock.i18n.slf4j.LocalizedLogger; 033import org.forgerock.opendj.ldap.ByteString; 034import org.forgerock.opendj.ldap.ConditionResult; 035import org.forgerock.opendj.ldap.ResultCode; 036import org.opends.server.admin.std.server.HasSubordinatesVirtualAttributeCfg; 037import org.opends.server.api.Backend; 038import org.forgerock.opendj.ldap.schema.MatchingRule; 039import org.opends.server.api.VirtualAttributeProvider; 040import org.opends.server.core.DirectoryServer; 041import org.opends.server.core.SearchOperation; 042import org.opends.server.types.*; 043 044import static org.opends.messages.ExtensionMessages.*; 045 046/** 047 * This class implements a virtual attribute provider that is meant to serve the 048 * hasSubordinates operational attribute as described in X.501. 049 */ 050public class HasSubordinatesVirtualAttributeProvider 051 extends VirtualAttributeProvider<HasSubordinatesVirtualAttributeCfg> 052{ 053 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 054 055 /** 056 * Creates a new instance of this HasSubordinates virtual attribute provider. 057 */ 058 public HasSubordinatesVirtualAttributeProvider() 059 { 060 super(); 061 062 // All initialization should be performed in the 063 // initializeVirtualAttributeProvider method. 064 } 065 066 /** {@inheritDoc} */ 067 @Override 068 public boolean isMultiValued() 069 { 070 return false; 071 } 072 073 /** {@inheritDoc} */ 074 @Override 075 public Attribute getValues(Entry entry, VirtualAttributeRule rule) 076 { 077 Backend backend = DirectoryServer.getBackend(entry.getName()); 078 079 try 080 { 081 ConditionResult ret = backend.hasSubordinates(entry.getName()); 082 if(ret != null && ret != ConditionResult.UNDEFINED) 083 { 084 return Attributes.create(rule.getAttributeType(), ret.toString()); 085 } 086 } 087 catch(DirectoryException de) 088 { 089 logger.traceException(de); 090 } 091 092 return Attributes.empty(rule.getAttributeType()); 093 } 094 095 /** {@inheritDoc} */ 096 @Override 097 public boolean hasValue(Entry entry, VirtualAttributeRule rule) 098 { 099 Backend backend = DirectoryServer.getBackend(entry.getName()); 100 101 try 102 { 103 ConditionResult ret = backend.hasSubordinates(entry.getName()); 104 return ret != null && ret != ConditionResult.UNDEFINED; 105 } 106 catch(DirectoryException de) 107 { 108 logger.traceException(de); 109 110 return false; 111 } 112 } 113 114 /** {@inheritDoc} */ 115 @Override 116 public boolean hasValue(Entry entry, VirtualAttributeRule rule, ByteString value) 117 { 118 Backend backend = DirectoryServer.getBackend(entry.getName()); 119 MatchingRule matchingRule = 120 rule.getAttributeType().getEqualityMatchingRule(); 121 122 try 123 { 124 ByteString normValue = matchingRule.normalizeAttributeValue(value); 125 ConditionResult ret = backend.hasSubordinates(entry.getName()); 126 return ret != null 127 && ret != ConditionResult.UNDEFINED 128 && ConditionResult.valueOf(normValue.toString()).equals(ret); 129 } 130 catch (Exception de) 131 { 132 logger.traceException(de); 133 return false; 134 } 135 } 136 137 /** {@inheritDoc} */ 138 @Override 139 public ConditionResult matchesSubstring(Entry entry, 140 VirtualAttributeRule rule, 141 ByteString subInitial, 142 List<ByteString> subAny, 143 ByteString subFinal) 144 { 145 // This virtual attribute does not support substring matching. 146 return ConditionResult.UNDEFINED; 147 } 148 149 /** {@inheritDoc} */ 150 @Override 151 public ConditionResult greaterThanOrEqualTo(Entry entry, 152 VirtualAttributeRule rule, 153 ByteString value) 154 { 155 // This virtual attribute does not support ordering matching. 156 return ConditionResult.UNDEFINED; 157 } 158 159 /** {@inheritDoc} */ 160 @Override 161 public ConditionResult lessThanOrEqualTo(Entry entry, 162 VirtualAttributeRule rule, 163 ByteString value) 164 { 165 // This virtual attribute does not support ordering matching. 166 return ConditionResult.UNDEFINED; 167 } 168 169 /** {@inheritDoc} */ 170 @Override 171 public ConditionResult approximatelyEqualTo(Entry entry, 172 VirtualAttributeRule rule, 173 ByteString value) 174 { 175 // This virtual attribute does not support approximate matching. 176 return ConditionResult.UNDEFINED; 177 } 178 179 /** {@inheritDoc} */ 180 @Override 181 public boolean isSearchable(VirtualAttributeRule rule, 182 SearchOperation searchOperation, 183 boolean isPreIndexed) 184 { 185 return false; 186 } 187 188 /** {@inheritDoc} */ 189 @Override 190 public void processSearch(VirtualAttributeRule rule, 191 SearchOperation searchOperation) 192 { 193 searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); 194 195 LocalizableMessage message = ERR_HASSUBORDINATES_VATTR_NOT_SEARCHABLE.get( 196 rule.getAttributeType().getNameOrOID()); 197 searchOperation.appendErrorMessage(message); 198 } 199} 200