/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portlet.tck.bridge;
import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.module.framework.ModuleServiceLifecycle;
import com.liferay.portal.kernel.servlet.ServletContextPool;
import com.liferay.portal.kernel.util.ThreadUtil;
import com.liferay.portal.kernel.util.Time;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.struts.StrutsActionRegistryUtil;
import com.liferay.portlet.tck.bridge.configuration.PortletTCKBridgeConfiguration;
import com.liferay.portlet.tck.bridge.struts.PortletTCKStrutsAction;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.charset.Charset;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import javax.servlet.ServletContext;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
/**
* @author Matthew Tambara
*/
@Component(
configurationPid = "com.liferay.portlet.tck.bridge.configuration.PortletTCKBridgeConfiguration"
)
public class PortletTCKBridge {
@Activate
@Modified
protected void activate(ComponentContext componentContext) {
deactivate();
StrutsActionRegistryUtil.register(_PATH, new PortletTCKStrutsAction());
FutureTask<Void> futureTask = new FutureTask<>(
new HandshakeServerCallable(
ConfigurableUtil.createConfigurable(
PortletTCKBridgeConfiguration.class,
componentContext.getProperties())));
_handshakeServerFuture = futureTask;
Thread handshakeServerThread = new Thread(
futureTask, "Handshake server thread");
handshakeServerThread.setDaemon(true);
handshakeServerThread.start();
}
@Deactivate
protected void deactivate() {
Future<Void> handshakeServerFuture = _handshakeServerFuture;
if (handshakeServerFuture != null) {
handshakeServerFuture.cancel(true);
}
StrutsActionRegistryUtil.unregister(_PATH);
}
@Reference(target = ModuleServiceLifecycle.PORTAL_INITIALIZED, unbind = "-")
protected void setModuleServiceLifecycle(
ModuleServiceLifecycle moduleServiceLifecycle) {
}
private static final String _PATH = "/portal/tck";
private static final Log _log = LogFactoryUtil.getLog(
PortletTCKBridge.class);
private volatile Future<Void> _handshakeServerFuture;
private static class HandshakeServerCallable implements Callable<Void> {
@Override
public Void call() throws IOException {
long startTime = System.currentTimeMillis();
for (String servletContextName :
_portletTCKBridgeConfiguration.servletContextNames()) {
_waitForDeployment(
servletContextName, startTime,
_portletTCKBridgeConfiguration.timeout() * Time.SECOND);
}
try (ServerSocket serverSocket = new ServerSocket(
_portletTCKBridgeConfiguration.handshakeServerPort())) {
serverSocket.setSoTimeout(100);
while (!Thread.interrupted()) {
try (Socket socket = serverSocket.accept();
OutputStream outputStream = socket.getOutputStream()) {
outputStream.write(
"Portlet TCK Bridge is ready".getBytes(
Charset.defaultCharset()));
}
catch (SocketTimeoutException ste) {
}
}
}
return null;
}
private HandshakeServerCallable(
PortletTCKBridgeConfiguration portletTCKBridgeConfiguration) {
_portletTCKBridgeConfiguration = portletTCKBridgeConfiguration;
}
private void _waitForDeployment(
String servletContextName, long startTime, long timeout) {
while ((System.currentTimeMillis() - startTime) < timeout) {
ServletContext serviceContext = ServletContextPool.get(
servletContextName);
if ((serviceContext == null) ||
(serviceContext.getAttribute(WebKeys.PLUGIN_PORTLETS) ==
null)) {
try {
Thread.sleep(100);
}
catch (InterruptedException ie) {
}
}
else {
return;
}
}
_log.error("Timeout on waiting " + servletContextName);
_log.error(ThreadUtil.threadDump());
}
private final PortletTCKBridgeConfiguration
_portletTCKBridgeConfiguration;
}
}