001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.plugin.java; 018 019import java.util.Arrays; 020import java.util.Set; 021 022import org.apache.activemq.broker.Broker; 023import org.apache.activemq.broker.region.policy.PolicyEntry; 024import org.apache.activemq.broker.region.policy.PolicyMap; 025import org.apache.activemq.broker.region.virtual.VirtualDestination; 026import org.apache.activemq.command.ActiveMQDestination; 027import org.apache.activemq.network.DiscoveryNetworkConnector; 028import org.apache.activemq.plugin.AbstractRuntimeConfigurationBroker; 029import org.apache.activemq.plugin.UpdateVirtualDestinationsTask; 030import org.apache.activemq.plugin.util.PolicyEntryUtil; 031import org.apache.activemq.security.AuthorizationBroker; 032import org.apache.activemq.security.AuthorizationMap; 033import org.apache.activemq.security.SimpleAuthenticationBroker; 034import org.apache.activemq.security.SimpleAuthenticationPlugin; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038public class JavaRuntimeConfigurationBroker extends AbstractRuntimeConfigurationBroker { 039 040 /** 041 * @param next 042 */ 043 public JavaRuntimeConfigurationBroker(Broker next) { 044 super(next); 045 } 046 047 public static final Logger LOG = LoggerFactory.getLogger(JavaRuntimeConfigurationBroker.class); 048 049 050 //Virtual Destinations 051 public void setVirtualDestinations(final VirtualDestination[] virtualDestinations) { 052 this.addDestinationWork.add(new UpdateVirtualDestinationsTask(this) { 053 @Override 054 protected VirtualDestination[] getVirtualDestinations() { 055 return virtualDestinations; 056 } 057 }); 058 } 059 060 /** 061 * Set the virtual destinations and apply immediately, instead of waiting for a new 062 * destination or connection to trigger the work. 063 * 064 * @param virtualDestinations 065 * @param applyImmediately 066 * @throws Exception 067 */ 068 public void setVirtualDestinations(final VirtualDestination[] virtualDestinations, boolean applyImmediately) throws Exception { 069 setVirtualDestinations(virtualDestinations); 070 if (applyImmediately) { 071 this.applyDestinationWork(); 072 } 073 } 074 075 //New Destinations 076 public void setDestinations(final ActiveMQDestination[] destinations) { 077 for (ActiveMQDestination destination : destinations) { 078 try { 079 if (!containsDestination(destination)) { 080 this.addDestination(this.getBrokerService().getAdminConnectionContext(), destination, true); 081 this.info("Added destination " + destination); 082 } 083 } catch (Exception e) { 084 this.info("Failed to add a new destination for: " + destination, e); 085 } 086 } 087 } 088 089 protected boolean containsDestination(ActiveMQDestination destination) throws Exception { 090 return Arrays.asList(this.getBrokerService().getRegionBroker().getDestinations()).contains(destination); 091 } 092 093 public void addNewDestination(ActiveMQDestination destination) { 094 try { 095 this.addDestination(this.getBrokerService().getAdminConnectionContext(), destination, true); 096 this.info("Added destination " + destination); 097 } catch (Exception e) { 098 this.info("Failed to add a new destination for: " + destination, e); 099 } 100 } 101 102 //Network Connectors 103 public void addNetworkConnector(final DiscoveryNetworkConnector nc) { 104 try { 105 if (!getBrokerService().getNetworkConnectors().contains(nc)) { 106 getBrokerService().addNetworkConnector(nc); 107 getBrokerService().startNetworkConnector(nc, null); 108 info("started new network connector: " + nc); 109 } else { 110 info("skipping network connector add, already exists: " + nc); 111 } 112 } catch (Exception e) { 113 info("Failed to add new networkConnector " + nc, e); 114 } 115 } 116 117 public void updateNetworkConnector(final DiscoveryNetworkConnector nc) { 118 removeNetworkConnector(nc); 119 addNetworkConnector(nc); 120 } 121 122 public void removeNetworkConnector(final DiscoveryNetworkConnector existingCandidate) { 123 if (getBrokerService().removeNetworkConnector(existingCandidate)) { 124 try { 125 existingCandidate.stop(); 126 info("stopped and removed networkConnector: " + existingCandidate); 127 } catch (Exception e) { 128 info("Failed to stop removed network connector: " + existingCandidate); 129 } 130 } 131 } 132 133 //Policy entries 134 public void addNewPolicyEntry(PolicyEntry addition) { 135 PolicyMap existingMap = getBrokerService().getDestinationPolicy(); 136 existingMap.put(addition.getDestination(), addition); 137 PolicyEntryUtil.applyRetrospectively(this, addition, null); 138 info("added policy for: " + addition.getDestination()); 139 } 140 141 142 /** 143 * This method will modify an existing policy entry that matches the destination 144 * set on the PolicyEntry passed in. 145 * 146 * The PolicyEntry reference must already be in the PolicyMap or it won't be updated. 147 * To modify the entry the best way is to look up the existing PolicyEntry from the 148 * PolicyMap, make changes to it, and pass it to this method to apply. 149 * 150 * To create or replace an existing entry (if the destination matches), see 151 * {@link #modifyPolicyEntry(PolicyEntry, boolean) 152 * 153 * 154 * @param existing 155 */ 156 public void modifyPolicyEntry(PolicyEntry existing) { 157 modifyPolicyEntry(existing, false); 158 } 159 160 public void modifyPolicyEntry(PolicyEntry existing, boolean createOrReplace) { 161 modifyPolicyEntry(existing, createOrReplace, null); 162 } 163 164 /** 165 * This method will modify an existing policy entry that matches the destination 166 * set on the PolicyEntry passed in. If createOrReplace is true, a new policy 167 * will be created if it doesn't exist and a policy will be replaced in the PolicyMap, 168 * versus modified, if it is a different reference but the destinations for the Policy match. 169 * 170 * If createOrReplace is false, the policy update will only be applied if 171 * the PolicyEntry reference already exists in the PolicyMap. 172 * 173 * includedProperties is a list of properties that will be applied retrospectively. If 174 * the list is null, then all properties on the policy will be reapplied to the destination. 175 * This allows the ability to limit which properties are applied to existing destinations. 176 * 177 * @param existing 178 * @param createIfAbsent 179 * @param includedProperties - optional list of properties to apply retrospectively 180 */ 181 public void modifyPolicyEntry(PolicyEntry existing, boolean createOrReplace, 182 Set<String> includedProperties) { 183 PolicyMap existingMap = this.getBrokerService().getDestinationPolicy(); 184 185 //First just look up by the destination type to see if anything matches 186 PolicyEntry existingEntry = PolicyEntryUtil.findEntryByDestination(this, existing); 187 188 //handle createOrReplace 189 if (createOrReplace) { 190 //if not found at all, go ahead and insert the policy entry 191 if (existingEntry == null) { 192 existingMap.put(existing.getDestination(), existing); 193 existingEntry = existing; 194 //If found but the objects are different, remove the old policy entry 195 //and replace it with the new one 196 } else if (!existing.equals(existingEntry)) { 197 synchronized(existingMap) { 198 existingMap.remove(existingEntry.getDestination(), existingEntry); 199 existingMap.put(existing.getDestination(), existing); 200 } 201 existingEntry = existing; 202 } 203 } 204 205 //Make sure that at this point the passed in object and the entry in 206 //the map are the same 207 if (existingEntry != null && existingEntry.equals(existing)) { 208 PolicyEntryUtil.applyRetrospectively(this, existingEntry, includedProperties); 209 this.info("updated policy for: " + existingEntry.getDestination()); 210 } else { 211 throw new IllegalArgumentException("The policy can not be updated because it either does not exist or the PolicyEntry" 212 + " reference does not match an existing PolicyEntry in the PolicyMap. To replace an" 213 + " entry (versus modifying) or add, set createOrReplace to true. " 214 + existing + ", destination:" + existing.getDestination()); 215 } 216 } 217 218 //authentication plugin 219 public void updateSimpleAuthenticationPlugin(final SimpleAuthenticationPlugin updatedPlugin) { 220 try { 221 final SimpleAuthenticationBroker authenticationBroker = 222 (SimpleAuthenticationBroker) getBrokerService().getBroker().getAdaptor(SimpleAuthenticationBroker.class); 223 addConnectionWork.add(new Runnable() { 224 @Override 225 public void run() { 226 authenticationBroker.setUserGroups(updatedPlugin.getUserGroups()); 227 authenticationBroker.setUserPasswords(updatedPlugin.getUserPasswords()); 228 authenticationBroker.setAnonymousAccessAllowed(updatedPlugin.isAnonymousAccessAllowed()); 229 authenticationBroker.setAnonymousUser(updatedPlugin.getAnonymousUser()); 230 authenticationBroker.setAnonymousGroup(updatedPlugin.getAnonymousGroup()); 231 } 232 }); 233 } catch (Exception e) { 234 info("failed to apply SimpleAuthenticationPlugin modifications to SimpleAuthenticationBroker", e); 235 } 236 } 237 238 //authorization map 239 public void updateAuthorizationMap(final AuthorizationMap authorizationMap) { 240 try { 241 // replace authorization map - need exclusive write lock to total broker 242 AuthorizationBroker authorizationBroker = 243 (AuthorizationBroker) getBrokerService().getBroker().getAdaptor(AuthorizationBroker.class); 244 245 authorizationBroker.setAuthorizationMap(authorizationMap); 246 } catch (Exception e) { 247 info("failed to apply modified AuthorizationMap to AuthorizationBroker", e); 248 } 249 } 250}