/*
* 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.server.impl;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.activemq.artemis.api.core.BaseInterceptor;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.core.config.ConnectorServiceConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle;
import org.apache.activemq.artemis.core.server.ConnectorServiceFactory;
import org.apache.activemq.artemis.core.server.ServiceRegistry;
import org.apache.activemq.artemis.core.server.cluster.Transformer;
import org.apache.activemq.artemis.spi.core.remoting.AcceptorFactory;
import org.apache.activemq.artemis.utils.ClassloadingUtil;
public class ServiceRegistryImpl implements ServiceRegistry {
private ExecutorService executorService;
private ExecutorService ioExecutorService;
private ScheduledExecutorService scheduledExecutorService;
/* We are using a List rather than HashMap here as ActiveMQ Artemis allows multiple instances of the same class to be added
* to the interceptor list
*/
private List<BaseInterceptor> incomingInterceptors;
private List<BaseInterceptor> outgoingInterceptors;
private Map<String, Transformer> divertTransformers;
private Map<String, Transformer> bridgeTransformers;
private Map<String, AcceptorFactory> acceptorFactories;
private Map<String, Pair<ConnectorServiceFactory, ConnectorServiceConfiguration>> connectorServices;
public ServiceRegistryImpl() {
this.incomingInterceptors = Collections.synchronizedList(new ArrayList<BaseInterceptor>());
this.outgoingInterceptors = Collections.synchronizedList(new ArrayList<BaseInterceptor>());
this.connectorServices = new ConcurrentHashMap<>();
this.divertTransformers = new ConcurrentHashMap<>();
this.bridgeTransformers = new ConcurrentHashMap<>();
this.acceptorFactories = new ConcurrentHashMap<>();
}
@Override
public ExecutorService getExecutorService() {
return executorService;
}
@Override
public void setExecutorService(ExecutorService executorService) {
this.executorService = executorService;
}
@Override
public ScheduledExecutorService getScheduledExecutorService() {
return scheduledExecutorService;
}
@Override
public void setScheduledExecutorService(ScheduledExecutorService scheduledExecutorService) {
this.scheduledExecutorService = scheduledExecutorService;
}
@Override
public void addConnectorService(ConnectorServiceFactory connectorServiceFactory,
ConnectorServiceConfiguration configuration) {
connectorServices.put(configuration.getConnectorName(), new Pair<>(connectorServiceFactory, configuration));
}
@Override
public void removeConnectorService(ConnectorServiceConfiguration configuration) {
connectorServices.remove(configuration.getConnectorName());
}
@Override
public Collection<Pair<ConnectorServiceFactory, ConnectorServiceConfiguration>> getConnectorServices(List<ConnectorServiceConfiguration> configs) {
if (configs != null) {
for (final ConnectorServiceConfiguration config : configs) {
if (connectorServices.get(config.getConnectorName()) == null) {
ConnectorServiceFactory factory = loadClass(config.getFactoryClassName());
addConnectorService(factory, config);
}
}
}
return connectorServices.values();
}
@Override
public ConnectorServiceFactory getConnectorService(ConnectorServiceConfiguration configuration) {
return loadClass(configuration.getFactoryClassName());
}
@Override
public void addIncomingInterceptor(BaseInterceptor interceptor) {
incomingInterceptors.add(interceptor);
}
@Override
public List<BaseInterceptor> getIncomingInterceptors(List<String> classNames) {
List<BaseInterceptor> interceptors = new ArrayList<>(incomingInterceptors);
instantiateInterceptors(classNames, interceptors);
return interceptors;
}
@Override
public void addOutgoingInterceptor(BaseInterceptor interceptor) {
outgoingInterceptors.add(interceptor);
}
@Override
public List<BaseInterceptor> getOutgoingInterceptors(List<String> classNames) {
List<BaseInterceptor> interceptors = new ArrayList<>(outgoingInterceptors);
instantiateInterceptors(classNames, interceptors);
return interceptors;
}
@Override
public void addDivertTransformer(String name, Transformer transformer) {
divertTransformers.put(name, transformer);
}
@Override
public Transformer getDivertTransformer(String name, String className) {
Transformer transformer = divertTransformers.get(name);
if (transformer == null && className != null) {
transformer = instantiateTransformer(className);
addDivertTransformer(name, transformer);
}
return transformer;
}
@Override
public ExecutorService getIOExecutorService() {
return ioExecutorService;
}
@Override
public void setIOExecutorService(ExecutorService ioExecutorService) {
this.ioExecutorService = ioExecutorService;
}
@Override
public void addBridgeTransformer(String name, Transformer transformer) {
bridgeTransformers.put(name, transformer);
}
@Override
public Transformer getBridgeTransformer(String name, String className) {
Transformer transformer = bridgeTransformers.get(name);
if (transformer == null && className != null) {
transformer = instantiateTransformer(className);
addBridgeTransformer(name, transformer);
}
return transformer;
}
@Override
public AcceptorFactory getAcceptorFactory(String name, final String className) {
AcceptorFactory factory = acceptorFactories.get(name);
if (factory == null && className != null) {
factory = loadClass(className);
addAcceptorFactory(name, factory);
}
return factory;
}
@Override
public void addAcceptorFactory(String name, AcceptorFactory acceptorFactory) {
acceptorFactories.put(name, acceptorFactory);
}
@SuppressWarnings("TypeParameterUnusedInFormals")
public <T> T loadClass(final String className) {
return AccessController.doPrivileged(new PrivilegedAction<T>() {
@Override
public T run() {
return (T) ClassloadingUtil.newInstanceFromClassLoader(className);
}
});
}
private Transformer instantiateTransformer(final String className) {
Transformer transformer = null;
if (className != null) {
try {
transformer = loadClass(className);
} catch (Exception e) {
throw ActiveMQMessageBundle.BUNDLE.errorCreatingTransformerClass(e, className);
}
}
return transformer;
}
private void instantiateInterceptors(List<String> classNames, List<BaseInterceptor> interceptors) {
if (classNames != null) {
for (final String className : classNames) {
BaseInterceptor interceptor = loadClass(className);
interceptors.add(interceptor);
}
}
}
}