/* * 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.activemq.artemis.core.management.impl; import javax.json.JsonArrayBuilder; import javax.management.MBeanAttributeInfo; import javax.management.MBeanOperationInfo; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.activemq.artemis.api.core.ActiveMQException; import org.apache.activemq.artemis.api.core.Message; import org.apache.activemq.artemis.api.core.RoutingType; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.api.core.management.AddressControl; import org.apache.activemq.artemis.api.core.management.QueueControl; import org.apache.activemq.artemis.api.core.management.ResourceNames; import org.apache.activemq.artemis.core.message.impl.CoreMessage; import org.apache.activemq.artemis.core.paging.PagingManager; import org.apache.activemq.artemis.core.paging.PagingStore; import org.apache.activemq.artemis.core.persistence.StorageManager; import org.apache.activemq.artemis.core.postoffice.Binding; import org.apache.activemq.artemis.core.postoffice.Bindings; import org.apache.activemq.artemis.core.postoffice.PostOffice; import org.apache.activemq.artemis.core.postoffice.QueueBinding; import org.apache.activemq.artemis.core.security.CheckType; import org.apache.activemq.artemis.core.security.Role; import org.apache.activemq.artemis.core.security.SecurityAuth; import org.apache.activemq.artemis.core.security.SecurityStore; import org.apache.activemq.artemis.core.server.impl.AddressInfo; import org.apache.activemq.artemis.core.server.management.ManagementService; import org.apache.activemq.artemis.core.settings.HierarchicalRepository; import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; import org.apache.activemq.artemis.utils.Base64; import org.apache.activemq.artemis.utils.JsonLoader; public class AddressControlImpl extends AbstractControl implements AddressControl { // Constants ----------------------------------------------------- // Attributes ---------------------------------------------------- private AddressInfo addressInfo; private final PostOffice postOffice; private final PagingManager pagingManager; private final HierarchicalRepository<Set<Role>> securityRepository; private final SecurityStore securityStore; private final ManagementService managementService; // Static -------------------------------------------------------- // Constructors -------------------------------------------------- public AddressControlImpl(AddressInfo addressInfo, final PostOffice postOffice, final PagingManager pagingManager, final StorageManager storageManager, final HierarchicalRepository<Set<Role>> securityRepository, final SecurityStore securityStore, final ManagementService managementService)throws Exception { super(AddressControl.class, storageManager); this.addressInfo = addressInfo; this.postOffice = postOffice; this.pagingManager = pagingManager; this.securityRepository = securityRepository; this.securityStore = securityStore; this.managementService = managementService; } // Public -------------------------------------------------------- // AddressControlMBean implementation ---------------------------- @Override public String getAddress() { return addressInfo.getName().toString(); } @Override public String[] getRoutingTypes() { Set<RoutingType> routingTypes = addressInfo.getRoutingTypes(); String[] result = new String[routingTypes.size()]; int i = 0; for (RoutingType routingType : routingTypes) { result[i++] = routingType.toString(); } return result; } @Override public String getRoutingTypesAsJSON() throws Exception { clearIO(); try { JsonArrayBuilder json = JsonLoader.createArrayBuilder(); String[] routingTypes = getRoutingTypes(); for (String routingType : routingTypes) { json.add(routingType); } return json.build().toString(); } finally { blockOnIO(); } } @Override public String[] getQueueNames() throws Exception { clearIO(); try { Bindings bindings = postOffice.getBindingsForAddress(addressInfo.getName()); List<String> queueNames = new ArrayList<>(); for (Binding binding : bindings.getBindings()) { if (binding instanceof QueueBinding) { queueNames.add(binding.getUniqueName().toString()); } } return queueNames.toArray(new String[queueNames.size()]); } catch (Throwable t) { throw new IllegalStateException(t.getMessage()); } finally { blockOnIO(); } } @Override public String[] getBindingNames() throws Exception { clearIO(); try { Bindings bindings = postOffice.getBindingsForAddress(addressInfo.getName()); String[] bindingNames = new String[bindings.getBindings().size()]; int i = 0; for (Binding binding : bindings.getBindings()) { bindingNames[i++] = binding.getUniqueName().toString(); } return bindingNames; } catch (Throwable t) { throw new IllegalStateException(t.getMessage()); } finally { blockOnIO(); } } @Override public Object[] getRoles() throws Exception { clearIO(); try { Set<Role> roles = securityRepository.getMatch(addressInfo.getName().toString()); Object[] objRoles = new Object[roles.size()]; int i = 0; for (Role role : roles) { objRoles[i++] = new Object[]{role.getName(), CheckType.SEND.hasRole(role), CheckType.CONSUME.hasRole(role), CheckType.CREATE_DURABLE_QUEUE.hasRole(role), CheckType.DELETE_DURABLE_QUEUE.hasRole(role), CheckType.CREATE_NON_DURABLE_QUEUE.hasRole(role), CheckType.DELETE_NON_DURABLE_QUEUE.hasRole(role), CheckType.MANAGE.hasRole(role)}; } return objRoles; } finally { blockOnIO(); } } @Override public String getRolesAsJSON() throws Exception { clearIO(); try { JsonArrayBuilder json = JsonLoader.createArrayBuilder(); Set<Role> roles = securityRepository.getMatch(addressInfo.getName().toString()); for (Role role : roles) { json.add(role.toJson()); } return json.build().toString(); } finally { blockOnIO(); } } @Override public long getNumberOfBytesPerPage() throws Exception { clearIO(); try { return pagingManager.getPageStore(addressInfo.getName()).getPageSizeBytes(); } finally { blockOnIO(); } } @Override public long getAddressSize() throws Exception { clearIO(); try { return pagingManager.getPageStore(addressInfo.getName()).getAddressSize(); } finally { blockOnIO(); } } @Override public long getNumberOfMessages() throws Exception { clearIO(); long totalMsgs = 0; try { Bindings bindings = postOffice.getBindingsForAddress(addressInfo.getName()); for (Binding binding : bindings.getBindings()) { if (binding instanceof QueueBinding) { totalMsgs += ((QueueBinding) binding).getQueue().getMessageCount(); } } return totalMsgs; } catch (Throwable t) { throw new IllegalStateException(t.getMessage()); } finally { blockOnIO(); } } @Override public boolean isPaging() throws Exception { clearIO(); try { return pagingManager.getPageStore(addressInfo.getName()).isPaging(); } finally { blockOnIO(); } } @Override public int getNumberOfPages() throws Exception { clearIO(); try { PagingStore pageStore = pagingManager.getPageStore(addressInfo.getName()); if (!pageStore.isPaging()) { return 0; } else { return pagingManager.getPageStore(addressInfo.getName()).getNumberOfPages(); } } finally { blockOnIO(); } } @Override public long getMessageCount() { return getMessageCount(DurabilityType.ALL); } @Override public String sendMessage(final Map<String, String> headers, final int type, final String body, boolean durable, final String user, final String password) throws Exception { try { securityStore.check(addressInfo.getName(), CheckType.SEND, new SecurityAuth() { @Override public String getUsername() { return user; } @Override public String getPassword() { return password; } @Override public RemotingConnection getRemotingConnection() { return null; } }); CoreMessage message = new CoreMessage(storageManager.generateID(), 50); if (headers != null) { for (String header : headers.keySet()) { message.putStringProperty(new SimpleString(header), new SimpleString(headers.get(header))); } } message.setType((byte) type); message.setDurable(durable); message.setTimestamp(System.currentTimeMillis()); if (body != null) { if (type == Message.TEXT_TYPE) { message.getBodyBuffer().writeNullableSimpleString(new SimpleString(body)); } else { message.getBodyBuffer().writeBytes(Base64.decode(body)); } } message.setAddress(addressInfo.getName()); postOffice.route(message, true); return "" + message.getMessageID(); } catch (ActiveMQException e) { throw new IllegalStateException(e.getMessage()); } } @Override protected MBeanOperationInfo[] fillMBeanOperationInfo() { return MBeanInfoHelper.getMBeanOperationsInfo(AddressControl.class); } @Override protected MBeanAttributeInfo[] fillMBeanAttributeInfo() { return MBeanInfoHelper.getMBeanAttributesInfo(AddressControl.class); } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- // Private ------------------------------------------------------- private long getMessageCount(final DurabilityType durability) { List<QueueControl> queues = getQueues(durability); long count = 0; for (QueueControl queue : queues) { count += queue.getMessageCount(); } return count; } private List<QueueControl> getQueues(final DurabilityType durability) { try { List<QueueControl> matchingQueues = new ArrayList<>(); String[] queues = getQueueNames(); for (String queue : queues) { QueueControl coreQueueControl = (QueueControl) managementService.getResource(ResourceNames.QUEUE + queue); // Ignore the "special" subscription if (coreQueueControl != null) { if (durability == DurabilityType.ALL || durability == DurabilityType.DURABLE && coreQueueControl.isDurable() || durability == DurabilityType.NON_DURABLE && !coreQueueControl.isDurable()) { matchingQueues.add(coreQueueControl); } } } return matchingQueues; } catch (Exception e) { return Collections.emptyList(); } } // Inner classes ------------------------------------------------- private enum DurabilityType { ALL, DURABLE, NON_DURABLE } }