/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.kafka.common.requests; import org.apache.kafka.clients.admin.AccessControlEntry; import org.apache.kafka.clients.admin.AclBinding; import org.apache.kafka.clients.admin.Resource; import org.apache.kafka.common.protocol.ApiKeys; import org.apache.kafka.common.protocol.Errors; import org.apache.kafka.common.protocol.types.Struct; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class DescribeAclsResponse extends AbstractResponse { private final static String THROTTLE_TIME_MS = "throttle_time_ms"; private final static String ERROR_CODE = "error_code"; private final static String ERROR_MESSAGE = "error_message"; private final static String RESOURCES = "resources"; private final static String ACLS = "acls"; private final int throttleTimeMs; private final Throwable throwable; private final Collection<AclBinding> acls; public DescribeAclsResponse(int throttleTimeMs, Throwable throwable, Collection<AclBinding> acls) { this.throttleTimeMs = throttleTimeMs; this.throwable = throwable; this.acls = acls; } public DescribeAclsResponse(Struct struct) { this.throttleTimeMs = struct.getInt(THROTTLE_TIME_MS); Errors error = Errors.forCode(struct.getShort(ERROR_CODE)); if (error != Errors.NONE) { this.throwable = error.exception(struct.getString(ERROR_MESSAGE)); this.acls = Collections.emptySet(); } else { this.throwable = null; this.acls = new ArrayList<>(); for (Object resourceStructObj : struct.getArray(RESOURCES)) { Struct resourceStruct = (Struct) resourceStructObj; Resource resource = RequestUtils.resourceFromStructFields(resourceStruct); for (Object aclDataStructObj : resourceStruct.getArray(ACLS)) { Struct aclDataStruct = (Struct) aclDataStructObj; AccessControlEntry entry = RequestUtils.aceFromStructFields(aclDataStruct); this.acls.add(new AclBinding(resource, entry)); } } } } @Override protected Struct toStruct(short version) { Struct struct = new Struct(ApiKeys.DESCRIBE_ACLS.responseSchema(version)); struct.set(THROTTLE_TIME_MS, throttleTimeMs); if (throwable != null) { Errors errors = Errors.forException(throwable); struct.set(ERROR_CODE, errors.code()); struct.set(ERROR_MESSAGE, throwable.getMessage()); struct.set(RESOURCES, new Struct[0]); return struct; } struct.set(ERROR_CODE, (short) 0); struct.set(ERROR_MESSAGE, null); Map<Resource, List<AccessControlEntry>> resourceToData = new HashMap<>(); for (AclBinding acl : acls) { List<AccessControlEntry> entry = resourceToData.get(acl.resource()); if (entry == null) { entry = new ArrayList<>(); resourceToData.put(acl.resource(), entry); } entry.add(acl.entry()); } List<Struct> resourceStructs = new ArrayList<>(); for (Map.Entry<Resource, List<AccessControlEntry>> tuple : resourceToData.entrySet()) { Resource resource = tuple.getKey(); Struct resourceStruct = struct.instance(RESOURCES); RequestUtils.resourceSetStructFields(resource, resourceStruct); List<Struct> dataStructs = new ArrayList<>(); for (AccessControlEntry entry : tuple.getValue()) { Struct dataStruct = resourceStruct.instance(ACLS); RequestUtils.aceSetStructFields(entry, dataStruct); dataStructs.add(dataStruct); } resourceStruct.set(ACLS, dataStructs.toArray()); resourceStructs.add(resourceStruct); } struct.set(RESOURCES, resourceStructs.toArray()); return struct; } public int throttleTimeMs() { return throttleTimeMs; } public Throwable throwable() { return throwable; } public Collection<AclBinding> acls() { return acls; } public static DescribeAclsResponse parse(ByteBuffer buffer, short version) { return new DescribeAclsResponse(ApiKeys.DESCRIBE_ACLS.responseSchema(version).read(buffer)); } }