| /* |
| * 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.axis2.engine; |
| |
| import org.apache.axis2.AxisFault; |
| import org.apache.axis2.addressing.EndpointReference; |
| import org.apache.axis2.context.ConfigurationContext; |
| import org.apache.axis2.description.AxisService; |
| import org.apache.axis2.description.TransportInDescription; |
| import org.apache.axis2.description.TransportOutDescription; |
| import org.apache.axis2.i18n.Messages; |
| import org.apache.axis2.transport.TransportListener; |
| import org.apache.axis2.transport.TransportSender; |
| import org.apache.axis2.util.OnDemandLogger; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| public class ListenerManager { |
| |
| private static final OnDemandLogger log = new OnDemandLogger(ListenerManager.class); |
| |
| protected ListenerManagerShutdownThread shutdownHookThread = null; |
| |
| private ConfigurationContext configctx; |
| private HashMap<String, TransportListener> startedTransports = |
| new HashMap<String, TransportListener>(); |
| |
| /** |
| * We're stopped at first. This is the flag to check whether the listener manager is |
| * started or not |
| */ |
| private boolean stopped = true; |
| |
| /** |
| * need to preserve the default behavior of requiring a shutdown hook, at the same time |
| * providing the flexibility to not to add the shutdown hook |
| */ |
| private boolean shutdownHookRequired = true; |
| |
| /** |
| * Initializes the listener manager and the defined transports in the |
| * <code>AxisConfiguration</code> |
| * |
| * @param configCtx used for the initialization |
| */ |
| public void init(ConfigurationContext configCtx) { |
| |
| if (this.configctx != null) { |
| log.warn("ConfigurationContext provided for the ListenerManager " + |
| "initialization is null. ListenerManager will not be initialized"); |
| return; |
| } |
| |
| configCtx.setTransportManager(this); |
| this.configctx = configCtx; |
| |
| // initialize all the transport listeners |
| for (TransportInDescription transportIn : |
| configctx.getAxisConfiguration().getTransportsIn().values()) { |
| |
| try { |
| TransportListener listener = transportIn.getReceiver(); |
| if (listener != null && startedTransports.get(transportIn.getName()) == null) { |
| listener.init(configctx, transportIn); |
| } |
| } catch (Exception e) { |
| log.error("Couldn't initialize the " |
| + transportIn.getName() + "transport listener", e); |
| } |
| } |
| } |
| |
| /** |
| * Returns the ConfigurationContext used for the initalization of the listener manager. It |
| * should be the current ConfigurationContext in use in most of the time. |
| * |
| * @return the ConfigurationContext used for the ListenerManager initialization |
| */ |
| public ConfigurationContext getConfigctx() { |
| return configctx; |
| } |
| |
| /** |
| * To get an EPR for a given service |
| * |
| * @param serviceName the name of the service |
| * @param opName the operation name |
| * @param transportName the name of the transport, or null. |
| * @return String |
| */ |
| public synchronized EndpointReference getEPRforService(String serviceName, String opName, |
| String transportName) throws AxisFault { |
| if (transportName == null || "".equals(transportName)) { |
| AxisService service = configctx.getAxisConfiguration().getService(serviceName); |
| if (service == null) { |
| throw new AxisFault(Messages.getMessage("servicenotfoundinthesystem", serviceName)); |
| } |
| if (service.isEnableAllTransports()) { |
| Iterator<TransportListener> itr_st = startedTransports.values().iterator(); |
| while (itr_st.hasNext()) { |
| TransportListener transportListener = itr_st.next(); |
| EndpointReference[] epRsForService = |
| transportListener.getEPRsForService(serviceName, null); |
| if (epRsForService != null) { |
| return epRsForService[0]; |
| } |
| } |
| |
| // if nothing can be found return null |
| return null; |
| |
| } else { |
| List<String> exposeTransport = service.getExposedTransports(); |
| TransportListener listener = startedTransports.get(exposeTransport.get(0)); |
| |
| EndpointReference[] eprsForService; |
| eprsForService = listener.getEPRsForService(serviceName, null); |
| return eprsForService != null ? eprsForService[0] : null; |
| } |
| |
| } else { |
| TransportInDescription trsIN = configctx.getAxisConfiguration() |
| .getTransportIn(transportName); |
| TransportListener listener = trsIN.getReceiver(); |
| EndpointReference[] eprsForService; |
| eprsForService = listener.getEPRsForService(serviceName, null); |
| return eprsForService != null ? eprsForService[0] : null; |
| } |
| } |
| |
| /** To start all the transports */ |
| public synchronized void start() { |
| if (!stopped) { |
| log.error("Couldn't start ListenerManager, it seems to be already started!"); |
| return; |
| } |
| |
| if (configctx == null) { |
| log.error("Can't start uninitialized ListenerManager!"); |
| return; |
| } |
| |
| for (Object o : configctx.getAxisConfiguration().getTransportsIn().values()) { |
| try { |
| TransportInDescription transportIn = (TransportInDescription)o; |
| TransportListener listener = transportIn.getReceiver(); |
| if (listener != null && startedTransports.get(transportIn.getName()) == null) { |
| listener.start(); |
| startedTransports.put(transportIn.getName(), listener); |
| } |
| } catch (Exception e) { |
| log.info(e.getMessage(), e); |
| } |
| } |
| |
| if (shutdownHookThread == null && isShutdownHookRequired()) { |
| shutdownHookThread = new ListenerManagerShutdownThread(this); |
| Runtime.getRuntime().addShutdownHook(shutdownHookThread); |
| } |
| |
| stopped = false; |
| } |
| |
| public synchronized void startSystem(ConfigurationContext configurationContext) { |
| init(configurationContext); |
| start(); |
| } |
| |
| /** Stop all the transports and notify modules of shutdown. */ |
| public synchronized void stop() throws AxisFault { |
| if (stopped) { |
| return; |
| } |
| |
| // Remove the shutdown hook |
| if (shutdownHookThread != null && shutdownHookThread.getState() != Thread.State.RUNNABLE) { |
| Runtime.getRuntime().removeShutdownHook(shutdownHookThread); |
| shutdownHookThread = null; |
| } |
| |
| for (Object o : startedTransports.values()) { |
| TransportListener transportListener = (TransportListener)o; |
| transportListener.stop(); |
| } |
| |
| // Stop the transport senders |
| if(log.isDebugEnabled()){ |
| log.debug("Start invoke transport sender shutdown."); |
| } |
| HashMap<String, TransportOutDescription> outTransports = |
| configctx.getAxisConfiguration().getTransportsOut(); |
| if (outTransports.size() > 0) { |
| Iterator<TransportOutDescription> trsItr = outTransports.values().iterator(); |
| while (trsItr.hasNext()) { |
| TransportOutDescription outDescription = trsItr.next(); |
| TransportSender sender = outDescription.getSender(); |
| if (sender != null) { |
| sender.stop(); |
| } |
| } |
| } |
| if(log.isDebugEnabled()){ |
| log.debug("End Invoke transport sender shutdown."); |
| } |
| /*Shutdown modules and Services */ |
| if(log.isDebugEnabled()){ |
| log.debug("Start Invoke modules and services shutdown."); |
| } |
| configctx.shutdownModulesAndServices(); |
| if(log.isDebugEnabled()){ |
| log.debug("End Invoke modules and services shutdown."); |
| } |
| stopped = true; |
| } |
| |
| /** |
| * Adds the listener described in the provided <code>TransportInDescription</code>. Further |
| * if the listener represented by the TransportInDescription has already been initialized and |
| * started the boolean <code>started</code> input parameter has to be provided as |
| * <code>true</code>.</p> |
| * |
| * <p>It is not possible to add a listener which is already initialized but not started to the |
| * listener manager, even though the above is a condition that has to be satisfied there is no |
| * means of enforcing that, becuase the {@link org.apache.axis2.transport.TransportListener} |
| * API doesn't provide a mechanism to test whether it is initialized or started.</p> |
| * |
| * <p>If the caller is using an already intialized listener, then it is the responsability of |
| * the caller to start the listener before adding it to the listener manager and pass the |
| * <code>started</code> parameter value as <code>true</code>. |
| * |
| * @param trsIn Transport in description (which contains Transport Listener) to be added |
| * @param started whether the transport Listener that is being added is already started or not |
| * @throws AxisFault will throw AxisFault if something goes wrong |
| */ |
| public synchronized void addListener(TransportInDescription trsIn, |
| boolean started) throws AxisFault { |
| configctx.getAxisConfiguration().addTransportIn(trsIn); |
| TransportListener transportListener = trsIn.getReceiver(); |
| if (transportListener != null) { |
| if (!started) { |
| transportListener.init(configctx, trsIn); |
| transportListener.start(); |
| if (shutdownHookThread == null && isShutdownHookRequired()) { |
| shutdownHookThread = new ListenerManagerShutdownThread(this); |
| Runtime.getRuntime().addShutdownHook(shutdownHookThread); |
| } |
| stopped = false; |
| } |
| startedTransports.put(trsIn.getName(), transportListener); |
| } |
| } |
| |
| public synchronized boolean isListenerRunning(String transportName) { |
| return startedTransports.get(transportName) != null; |
| } |
| |
| public boolean isStopped() { |
| return stopped; |
| } |
| |
| public void destroy() throws AxisFault { |
| stop(); |
| this.configctx.setTransportManager(null); |
| // need to destory all the transports not only the started ones |
| // most of the transports create the worker pool at the init method. |
| TransportInDescription transportInDescription; |
| for (Object o : configctx.getAxisConfiguration().getAxisConfiguration().getTransportsIn().values()) { |
| transportInDescription = (TransportInDescription) o; |
| TransportListener transportListener = transportInDescription.getReceiver(); |
| transportListener.destroy(); |
| } |
| |
| this.startedTransports.clear(); |
| this.configctx = null; |
| } |
| |
| public boolean isShutdownHookRequired() { |
| return shutdownHookRequired; |
| } |
| |
| public void setShutdownHookRequired(boolean shutdownHookRequired) { |
| this.shutdownHookRequired = shutdownHookRequired; |
| } |
| |
| static class ListenerManagerShutdownThread extends Thread { |
| ListenerManager listenerManager; |
| |
| public ListenerManagerShutdownThread(ListenerManager listenerManager) { |
| super(); |
| this.listenerManager = listenerManager; |
| } |
| |
| public void run() { |
| try { |
| if (!listenerManager.stopped) { |
| listenerManager.stop(); |
| } |
| } catch (AxisFault axisFault) { |
| log.error(axisFault.getMessage(), axisFault); |
| } |
| } |
| } |
| } |