001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.resiliency.spi.remote;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.nio.intraband.RegistrationReference;
020    import com.liferay.portal.kernel.process.TerminationProcessException;
021    import com.liferay.portal.kernel.resiliency.PortalResiliencyException;
022    import com.liferay.portal.kernel.resiliency.mpi.MPI;
023    import com.liferay.portal.kernel.resiliency.mpi.MPIHelperUtil;
024    import com.liferay.portal.kernel.resiliency.spi.SPI;
025    import com.liferay.portal.kernel.resiliency.spi.SPIConfiguration;
026    import com.liferay.portal.kernel.resiliency.spi.agent.SPIAgent;
027    import com.liferay.portal.kernel.resiliency.spi.agent.SPIAgentFactoryUtil;
028    import com.liferay.portal.kernel.util.StringPool;
029    
030    import java.rmi.RemoteException;
031    
032    import java.util.concurrent.ExecutionException;
033    import java.util.concurrent.Future;
034    import java.util.concurrent.TimeUnit;
035    
036    /**
037     * @author Shuyang Zhou
038     */
039    public class RemoteSPIProxy implements SPI {
040    
041            public static final int SIGINT = 130;
042    
043            public RemoteSPIProxy(
044                    SPI spi, SPIConfiguration spiConfiguration, String spiProviderName,
045                    Future<SPI> cancelHandlerFuture,
046                    RegistrationReference registrationReference) {
047    
048                    _spi = spi;
049                    _spiConfiguration = spiConfiguration;
050                    _spiProviderName = spiProviderName;
051                    _cancelHandlerFuture = cancelHandlerFuture;
052                    _registrationReference = registrationReference;
053    
054                    _mpi = MPIHelperUtil.getMPI();
055                    _spiAgent = SPIAgentFactoryUtil.createSPIAgent(
056                            spiConfiguration, registrationReference);
057            }
058    
059            @Override
060            public void addServlet(
061                            String contextPath, String docBasePath, String mappingPattern,
062                            String servletClassName)
063                    throws RemoteException {
064    
065                    _spi.addServlet(
066                            contextPath, docBasePath, mappingPattern, servletClassName);
067            }
068    
069            @Override
070            public void addWebapp(String contextPath, String docBasePath)
071                    throws RemoteException {
072    
073                    _spi.addWebapp(contextPath, docBasePath);
074            }
075    
076            @Override
077            public void destroy() {
078                    try {
079                            _spi.destroy();
080    
081                            _cancelHandlerFuture.get(
082                                    _spiConfiguration.getShutdownTimeout(), TimeUnit.MILLISECONDS);
083                    }
084                    catch (Exception e) {
085                            boolean forceDestroy = true;
086    
087                            if (e instanceof ExecutionException) {
088                                    Throwable throwable = e.getCause();
089    
090                                    if (throwable instanceof TerminationProcessException) {
091                                            TerminationProcessException terminationProcessException =
092                                                    (TerminationProcessException)throwable;
093    
094                                            if (terminationProcessException.getExitCode() == SIGINT) {
095                                                    forceDestroy = false;
096                                            }
097                                    }
098                            }
099    
100                            if (forceDestroy) {
101                                    _cancelHandlerFuture.cancel(true);
102    
103                                    if (_log.isWarnEnabled()) {
104                                            _log.warn("Forcibly destroyed SPI " + _spiConfiguration, e);
105                                    }
106                            }
107                    }
108                    finally {
109                            MPIHelperUtil.unregisterSPI(this);
110                    }
111    
112                    _spiAgent.destroy();
113            }
114    
115            @Override
116            public MPI getMPI() {
117                    return _mpi;
118            }
119    
120            @Override
121            public RegistrationReference getRegistrationReference() {
122                    return _registrationReference;
123            }
124    
125            @Override
126            public SPIAgent getSPIAgent() {
127                    return _spiAgent;
128            }
129    
130            @Override
131            public SPIConfiguration getSPIConfiguration() {
132                    return _spiConfiguration;
133            }
134    
135            @Override
136            public String getSPIProviderName() {
137                    return _spiProviderName;
138            }
139    
140            @Override
141            public void init() throws RemoteException {
142                    _spi.init();
143    
144                    try {
145                            _spiAgent.init(this);
146                    }
147                    catch (PortalResiliencyException pre) {
148                            throw new RemoteException("Unable to initialize SPI agent", pre);
149                    }
150            }
151    
152            @Override
153            public boolean isAlive() throws RemoteException {
154                    try {
155                            return _spi.isAlive();
156                    }
157                    catch (RemoteException re) {
158                            try {
159                                    _cancelHandlerFuture.get();
160                            }
161                            catch (Exception e) {
162                                    throw new RemoteException(
163                                            "SPI " + toString() + " died unexpectedly", e);
164                            }
165    
166                            return false;
167                    }
168            }
169    
170            @Override
171            public void start() throws RemoteException {
172                    _spi.start();
173            }
174    
175            @Override
176            public void stop() throws RemoteException {
177                    _spi.stop();
178            }
179    
180            @Override
181            public String toString() {
182                    return _spiProviderName.concat(StringPool.POUND).concat(
183                            _spiConfiguration.toString());
184            }
185    
186            private static final Log _log = LogFactoryUtil.getLog(RemoteSPIProxy.class);
187    
188            private final Future<SPI> _cancelHandlerFuture;
189            private final MPI _mpi;
190            private final RegistrationReference _registrationReference;
191            private final SPI _spi;
192            private final SPIAgent _spiAgent;
193            private final SPIConfiguration _spiConfiguration;
194            private final String _spiProviderName;
195    
196    }