001
014
015 package com.liferay.portal.kernel.resiliency.spi.provider;
016
017 import com.liferay.portal.kernel.nio.intraband.RegistrationReference;
018 import com.liferay.portal.kernel.nio.intraband.welder.Welder;
019 import com.liferay.portal.kernel.process.ProcessExecutor;
020 import com.liferay.portal.kernel.resiliency.PortalResiliencyException;
021 import com.liferay.portal.kernel.resiliency.mpi.MPIHelperUtil;
022 import com.liferay.portal.kernel.resiliency.spi.SPI;
023 import com.liferay.portal.kernel.resiliency.spi.SPIConfiguration;
024 import com.liferay.portal.kernel.resiliency.spi.remote.RemoteSPI;
025 import com.liferay.portal.kernel.resiliency.spi.remote.RemoteSPIProxy;
026 import com.liferay.portal.kernel.util.StringBundler;
027
028 import java.util.concurrent.Callable;
029 import java.util.concurrent.Future;
030 import java.util.concurrent.FutureTask;
031 import java.util.concurrent.SynchronousQueue;
032 import java.util.concurrent.TimeUnit;
033
034
037 public abstract class BaseSPIProvider implements SPIProvider {
038
039 public abstract RemoteSPI createRemoteSPI(SPIConfiguration spiConfiguration)
040 throws PortalResiliencyException;
041
042 @Override
043 public SPI createSPI(SPIConfiguration spiConfiguration)
044 throws PortalResiliencyException {
045
046 String classPath = getClassPath();
047
048 RemoteSPI remoteSPI = createRemoteSPI(spiConfiguration);
049
050 String spiUUID = remoteSPI.getUUID();
051
052 SynchronousQueue<SPI> synchronousQueue =
053 SPISynchronousQueueUtil.createSynchronousQueue(spiUUID);
054
055 FutureTask<RegistrationReference> weldServerFutureTask =
056 new FutureTask<RegistrationReference>(
057 new WeldServerCallable(remoteSPI.getWelder()));
058
059 Thread weldServerThread = new Thread(
060 weldServerFutureTask,
061 "Weld Server Thread for " + spiConfiguration.getSPIId());
062
063 weldServerThread.setDaemon(true);
064
065 weldServerThread.start();
066
067 try {
068 Future<SPI> cancelHandlerFuture = ProcessExecutor.execute(
069 spiConfiguration.getJavaExecutable(), classPath,
070 spiConfiguration.getJVMArguments(), remoteSPI);
071
072 SPI spi = synchronousQueue.poll(
073 spiConfiguration.getRegisterTimeout(), TimeUnit.MILLISECONDS);
074
075 if (spi != null) {
076 RegistrationReference registrationReference =
077 weldServerFutureTask.get(
078 spiConfiguration.getRegisterTimeout(),
079 TimeUnit.MILLISECONDS);
080
081 RemoteSPIProxy remoteSPIProxy = new RemoteSPIProxy(
082 spi, spiConfiguration, getName(), cancelHandlerFuture,
083 registrationReference);
084
085 if (!MPIHelperUtil.registerSPI(remoteSPIProxy)) {
086 cancelHandlerFuture.cancel(true);
087
088 throw new PortalResiliencyException(
089 "Unable to register SPI " + remoteSPIProxy +
090 ". Forcibly cancelled SPI process launch.");
091 }
092
093 return remoteSPIProxy;
094 }
095 else {
096 cancelHandlerFuture.cancel(true);
097
098 throw new PortalResiliencyException(
099 "SPI synchronous queue waiting timeout. Forcibly " +
100 "cancelled SPI process launch.");
101 }
102 }
103 catch (InterruptedException ie) {
104 throw new PortalResiliencyException(
105 "Interrupted on waiting SPI process, registering back RMI stub",
106 ie);
107 }
108 catch (PortalResiliencyException pre) {
109 throw pre;
110 }
111 catch (Exception e) {
112 throw new PortalResiliencyException(
113 "Unable to launch SPI process", e);
114 }
115 finally {
116 weldServerFutureTask.cancel(true);
117
118 SPISynchronousQueueUtil.destroySynchronousQueue(spiUUID);
119 }
120 }
121
122 public abstract String getClassPath();
123
124 @Override
125 public String toString() {
126 StringBundler sb = new StringBundler(5);
127
128 sb.append("{name=");
129 sb.append(getName());
130 sb.append(", classPath=");
131 sb.append(getClassPath());
132 sb.append("}");
133
134 return sb.toString();
135 }
136
137 protected static class WeldServerCallable
138 implements Callable<RegistrationReference> {
139
140 public WeldServerCallable(Welder welder) {
141 _welder = welder;
142 }
143
144 @Override
145 public RegistrationReference call() throws Exception {
146 return _welder.weld(MPIHelperUtil.getIntraband());
147 }
148
149 private final Welder _welder;
150
151 }
152
153 }