![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.jasperreports.chrome.BrowserService Maven / Gradle / Ivy
The newest version!
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports 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 3 of the License, or
* (at your option) any later version.
*
* JasperReports 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.chrome;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.kklisura.cdt.protocol.commands.Emulation;
import com.github.kklisura.cdt.protocol.commands.Page;
import com.github.kklisura.cdt.protocol.commands.Runtime;
import com.github.kklisura.cdt.protocol.events.log.EntryAdded;
import com.github.kklisura.cdt.protocol.events.runtime.ConsoleAPICalled;
import com.github.kklisura.cdt.protocol.events.runtime.ExceptionThrown;
import com.github.kklisura.cdt.protocol.types.log.LogEntry;
import com.github.kklisura.cdt.protocol.types.page.Navigate;
import com.github.kklisura.cdt.protocol.types.runtime.ExceptionDetails;
import com.github.kklisura.cdt.protocol.types.runtime.RemoteObject;
import com.github.kklisura.cdt.services.ChromeDevToolsService;
import net.sf.jasperreports.annotations.properties.Property;
import net.sf.jasperreports.annotations.properties.PropertyScope;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.properties.PropertyConstants;
/**
* @author Lucian Chirita ([email protected])
*/
public class BrowserService
{
private static final Log log = LogFactory.getLog(BrowserService.class);
@Property(
category = PropertyConstants.CATEGORY_CHROME,
scopes = {PropertyScope.CONTEXT},
sinceVersion = PropertyConstants.VERSION_6_11_0,
valueType = Long.class,
defaultValue = "60000"
)
public static final String PROPERTY_PAGE_TIMEOUT = Chrome.PROPERTY_PREFIX + "page.timeout";
@Property(
category = PropertyConstants.CATEGORY_CHROME,
scopes = {PropertyScope.CONTEXT},
sinceVersion = PropertyConstants.VERSION_6_12_0,
valueType = Boolean.class,
defaultValue = "false"
)
public static final String PROPERTY_PAGE_ISOLATE = Chrome.PROPERTY_PREFIX + "page.isolate";
private JRPropertiesUtil propertiesUtil;
private ChromeServiceHandle chromeServiceHandle;
public BrowserService(JasperReportsContext jasperReportsContext, ChromeServiceHandle chromeServiceHandle)
{
this.propertiesUtil = JRPropertiesUtil.getInstance(jasperReportsContext);
this.chromeServiceHandle = chromeServiceHandle;
}
public T evaluateInPage(String pageURL, PageOptions options, ChromePageEvaluation evaluation)
{
if (log.isDebugEnabled())
{
log.debug("page evaluation at " + pageURL);
}
PageCreator pageCreator = isolate(options) ? IsolatedPageCreator.instance() : StandardPageCreator.instance();
ChromeInstanceHandle chromeInstance = chromeServiceHandle.getChromeInstance();
T result = pageCreator.runInPage(chromeInstance, devToolsService ->
{
try
{
com.github.kklisura.cdt.protocol.commands.Log pageLog = devToolsService.getLog();
pageLog.onEntryAdded(this::pageLogEvent);
pageLog.enable();
Runtime runtime = devToolsService.getRuntime();
runtime.onConsoleAPICalled(this::consoleEvent);
runtime.onExceptionThrown(this::pageExceptionEvent);
runtime.enable();
setScreenDimensions(options, devToolsService);
CompletableFuture resultFuture = new CompletableFuture<>();
ChromePage chromePage = new ChromePage(devToolsService);
Page page = devToolsService.getPage();
page.onLoadEventFired(event ->
{
try
{
T evaluationResult = evaluation.runInPage(chromePage);
resultFuture.complete(evaluationResult);
}
catch (Exception e)
{
resultFuture.completeExceptionally(e);
}
});
page.enable();
Navigate navigate = page.navigate(pageURL);
if (navigate.getErrorText() != null)
{
throw new JRRuntimeException("Page failed to load: " + navigate.getErrorText());
}
Long timeout = pageTimeout(options);
if (log.isDebugEnabled())
{
log.debug("waiting for result, timeout " + timeout);
}
T promiseResult = timeout == null || timeout <= 0
? resultFuture.get()
: resultFuture.get(timeout, TimeUnit.MILLISECONDS);
return promiseResult;
}
catch (InterruptedException | ExecutionException | TimeoutException e)
{
throw new JRRuntimeException(e);
}
});
if (log.isDebugEnabled())
{
log.debug("page evaluation done");
}
return result;
}
protected boolean isolate(PageOptions options)
{
Boolean isolate = options == null ? null : options.getIsolate();
return isolate == null ? propertiesUtil.getBooleanProperty(PROPERTY_PAGE_ISOLATE, false)
: isolate;
}
protected void setScreenDimensions(PageOptions options, ChromeDevToolsService devToolsService)
{
if (options != null && (options.getScreenWidth() != null || options.getScreenHeight() != null))
{
Emulation emulation = devToolsService.getEmulation();
if (emulation.canEmulate())
{
if (log.isDebugEnabled())
{
log.debug("setting screen dimensions " + options.getScreenWidth() + ", " + options.getScreenHeight());
}
emulation.setDeviceMetricsOverride(
options.getScreenWidth() != null && options.getScreenWidth() > 0 ? options.getScreenWidth() : 0,
options.getScreenHeight() != null && options.getScreenHeight() > 0 ? options.getScreenHeight() : 0,
0d, false);
}
else
{
log.warn("Chrome device emulation is not supported, cannot set page width and height");
}
}
}
protected Long pageTimeout(PageOptions options)
{
Long timeout = options == null ? null : options.getTimeout();
if (timeout == null)
{
String timeoutProp = propertiesUtil.getProperty(PROPERTY_PAGE_TIMEOUT);
if (timeoutProp != null && !timeoutProp.trim().isEmpty())
{
timeout = JRPropertiesUtil.asLong(timeoutProp);
}
}
return timeout;
}
protected void pageLogEvent(EntryAdded event)
{
LogEntry entry = event.getEntry();
switch (entry.getLevel())
{
case ERROR:
log.error("Page error: " + entry.getText());
break;
case WARNING:
log.warn("Page warning: " + entry.getText());
break;
case INFO:
log.info("Page info: " + entry.getText());
break;
default:
if (log.isDebugEnabled())
{
log.info("Page message: " + entry.getText());
}
break;
}
}
protected void consoleEvent(ConsoleAPICalled event)
{
if (log.isDebugEnabled())
{
StringBuilder eventString = new StringBuilder();
eventString.append("Page console ");
eventString.append(event.getType());
eventString.append(": ");
List args = event.getArgs();
if (args != null)
{
for (RemoteObject argObject : args)
{
eventString.append(argObject.getValue() == null
? argObject.getUnserializableValue()
: argObject.getValue());
eventString.append(", ");
}
}
log.debug(eventString.substring(0, eventString.length() - 2));
}
}
protected void pageExceptionEvent(ExceptionThrown event)
{
if (log.isWarnEnabled())
{
ExceptionDetails exceptionDetails = event.getExceptionDetails();
log.warn("Script exception: " + exceptionDetails.getText());
if (log.isDebugEnabled())
{
//TODO stacktrace?
RemoteObject exception = exceptionDetails.getException();
String exceptionString = null;
if (exception != null)
{
if (exception.getDescription() != null)
{
exceptionString = exception.getDescription();
}
else if (exception.getValue() != null)
{
exceptionString = exception.getValue().toString();
}
}
if (exceptionString != null)
{
log.debug("Exception description: " + exceptionString);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy