001    /**
002     * Copyright (c) 2000-2013 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.nio.intraband.welder.Welder;
021    import com.liferay.portal.kernel.nio.intraband.welder.WelderFactoryUtil;
022    import com.liferay.portal.kernel.process.ProcessCallable;
023    import com.liferay.portal.kernel.process.ProcessException;
024    import com.liferay.portal.kernel.process.ProcessExecutor;
025    import com.liferay.portal.kernel.process.log.ProcessOutputStream;
026    import com.liferay.portal.kernel.resiliency.mpi.MPI;
027    import com.liferay.portal.kernel.resiliency.mpi.MPIHelperUtil;
028    import com.liferay.portal.kernel.resiliency.spi.SPI;
029    import com.liferay.portal.kernel.resiliency.spi.SPIConfiguration;
030    import com.liferay.portal.kernel.resiliency.spi.agent.SPIAgent;
031    import com.liferay.portal.kernel.resiliency.spi.agent.SPIAgentFactoryUtil;
032    import com.liferay.portal.kernel.resiliency.spi.provider.SPISynchronousQueueUtil;
033    import com.liferay.portal.kernel.util.PropsKeys;
034    
035    import java.io.IOException;
036    import java.io.ObjectInputStream;
037    import java.io.ObjectOutputStream;
038    
039    import java.rmi.Remote;
040    import java.rmi.RemoteException;
041    import java.rmi.server.UnicastRemoteObject;
042    
043    import java.util.UUID;
044    import java.util.concurrent.ConcurrentMap;
045    
046    /**
047     * @author Shuyang Zhou
048     */
049    public abstract class RemoteSPI implements ProcessCallable<SPI>, Remote, SPI {
050    
051            public RemoteSPI(SPIConfiguration spiConfiguration) {
052                    this.spiConfiguration = spiConfiguration;
053    
054                    mpi = MPIHelperUtil.getMPI();
055    
056                    UUID uuidObject = UUID.randomUUID();
057    
058                    uuid = uuidObject.toString();
059    
060                    welder = WelderFactoryUtil.createWelder();
061            }
062    
063            @Override
064            public SPI call() throws ProcessException {
065                    try {
066                            ProcessExecutor.ProcessContext.attach(
067                                    spiConfiguration.getSPIId(), spiConfiguration.getPingInterval(),
068                                    new SPIShutdownHook());
069    
070                            SPI spi = (SPI)UnicastRemoteObject.exportObject(this, 0);
071    
072                            RegisterCallback registerCallback = new RegisterCallback(uuid, spi);
073    
074                            ProcessOutputStream processOutputStream =
075                                    ProcessExecutor.ProcessContext.getProcessOutputStream();
076    
077                            processOutputStream.writeProcessCallable(registerCallback);
078    
079                            registrationReference = welder.weld(MPIHelperUtil.getIntraband());
080    
081                            ConcurrentMap<String, Object> attributes =
082                                    ProcessExecutor.ProcessContext.getAttributes();
083    
084                            attributes.put(SPI.SPI_INSTANCE_PUBLICATION_KEY, this);
085    
086                            return spi;
087                    }
088                    catch (RemoteException re) {
089                            throw new ProcessException("Failed to export SPI as RMI stub.", re);
090                    }
091                    catch (IOException ioe) {
092                            throw new ProcessException(ioe);
093                    }
094            }
095    
096            @Override
097            public MPI getMPI() {
098                    return mpi;
099            }
100    
101            @Override
102            public RegistrationReference getRegistrationReference() {
103                    return registrationReference;
104            }
105    
106            @Override
107            public SPIAgent getSPIAgent() {
108                    if (spiAgent == null) {
109                            spiAgent = SPIAgentFactoryUtil.createSPIAgent(
110                                    spiConfiguration, registrationReference);
111                    }
112    
113                    return spiAgent;
114            }
115    
116            @Override
117            public SPIConfiguration getSPIConfiguration() {
118                    return spiConfiguration;
119            }
120    
121            public String getUUID() {
122                    return uuid;
123            }
124    
125            public Welder getWelder() {
126                    return welder;
127            }
128    
129            @Override
130            public boolean isAlive() {
131                    return true;
132            }
133    
134            protected final MPI mpi;
135            protected RegistrationReference registrationReference;
136            protected transient volatile SPIAgent spiAgent;
137            protected final SPIConfiguration spiConfiguration;
138            protected final String uuid;
139            protected final Welder welder;
140    
141            protected static class RegisterCallback implements ProcessCallable<SPI> {
142    
143                    public RegisterCallback(String spiUUID, SPI spi) {
144                            _spiUUID = spiUUID;
145                            _spi = spi;
146                    }
147    
148                    @Override
149                    public SPI call() throws ProcessException {
150                            try {
151                                    SPISynchronousQueueUtil.notifySynchronousQueue(_spiUUID, _spi);
152                            }
153                            catch (InterruptedException ie) {
154                                    throw new ProcessException(ie);
155                            }
156    
157                            return _spi;
158                    }
159    
160                    private static final long serialVersionUID = 1L;
161    
162                    private final SPI _spi;
163                    private final String _spiUUID;
164    
165            }
166    
167            protected class SPIShutdownHook implements ProcessExecutor.ShutdownHook {
168    
169                    @Override
170                    public boolean shutdown(int shutdownCode, Throwable shutdownThrowable) {
171                            try {
172                                    RemoteSPI.this.stop();
173                            }
174                            catch (RemoteException re) {
175                                    _log.error("Unable to stop SPI", re);
176                            }
177    
178                            try {
179                                    RemoteSPI.this.destroy();
180                            }
181                            catch (RemoteException re) {
182                                    _log.error("Unable to destroy SPI", re);
183                            }
184    
185                            return true;
186                    }
187    
188            }
189    
190            private void readObject(ObjectInputStream objectInputStream)
191                    throws ClassNotFoundException, IOException {
192    
193                    objectInputStream.defaultReadObject();
194    
195                    System.setProperty(
196                            PropsKeys.INTRABAND_IMPL, objectInputStream.readUTF());
197                    System.setProperty(
198                            PropsKeys.INTRABAND_TIMEOUT_DEFAULT, objectInputStream.readUTF());
199                    System.setProperty(
200                            PropsKeys.INTRABAND_WELDER_IMPL, objectInputStream.readUTF());
201                    System.setProperty(
202                            "portal:" + PropsKeys.LIFERAY_HOME, objectInputStream.readUTF());
203    
204                    // Disable auto deploy
205    
206                    System.setProperty("portal:" + PropsKeys.AUTO_DEPLOY_ENABLED, "false");
207    
208                    // Disable cluster link
209    
210                    System.setProperty("portal:" + PropsKeys.CLUSTER_LINK_ENABLED, "false");
211    
212                    // Disable dependency management
213    
214                    System.setProperty(
215                            "portal:" + PropsKeys.HOT_DEPLOY_DEPENDENCY_MANAGEMENT_ENABLED,
216                            "false");
217    
218                    // Log4j log file postfix
219    
220                    System.setProperty("spi.id", "-" + spiConfiguration.getSPIId());
221            }
222    
223            private void writeObject(ObjectOutputStream objectOutputStream)
224                    throws IOException {
225    
226                    objectOutputStream.defaultWriteObject();
227    
228                    objectOutputStream.writeUTF(
229                            System.getProperty(PropsKeys.INTRABAND_IMPL));
230                    objectOutputStream.writeUTF(
231                            System.getProperty(PropsKeys.INTRABAND_TIMEOUT_DEFAULT));
232                    objectOutputStream.writeUTF(
233                            System.getProperty(PropsKeys.INTRABAND_WELDER_IMPL));
234                    objectOutputStream.writeUTF(System.getProperty(PropsKeys.LIFERAY_HOME));
235            }
236    
237            private static Log _log = LogFactoryUtil.getLog(RemoteSPI.class);
238    
239    }