/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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.
*
* Copyright (c) 2002-2016 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.platform.plugin.output;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.platform.api.engine.IApplicationContext;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.util.StringUtil;
import org.pentaho.reporting.platform.plugin.cache.IReportContent;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class PaginationControlWrapper {
private PaginationControlWrapper() {
}
private static Log logger = LogFactory.getLog( PaginationControlWrapper.class );
private static final String TEMPLATE_PATH = "system/reporting/reportviewer/paginationTemplate.html";
private static final String STAGING_PATH = "system/tmp/";
private static final Pattern CSS = Pattern.compile( "(.*link.*\\/getImage\\?image=)(.*)(\".*)" );
private static final Pattern IMG = Pattern.compile( "(.*img.*src=\")(http.+)(\\/getImage\\?image=)(.*)(\".*)" );
private static String pageableHtml;
public static void write( final OutputStream stream, final IReportContent content ) throws IOException {
final StringBuilder builder = new StringBuilder();
synchronized ( TEMPLATE_PATH ) {
if ( StringUtil.isEmpty( pageableHtml ) ) {
pageableHtml = getSolutionDirFileContent( TEMPLATE_PATH );
}
}
final String pages = getPageArray( content, builder );
final StrSubstitutor substitutor = new StrSubstitutor( Collections.singletonMap( "pages", pages ) );
final String filledTemplate = substitutor.replace( pageableHtml );
stream.write( filledTemplate.getBytes() );
stream.flush();
}
private static String getPageArray( final IReportContent content, final StringBuilder builder ) throws IOException {
builder.append( "var pages = [ " );
int index = 0;
byte[] page = content.getPageData( index );
while ( page != null ) {
String pageContent = new String( page, "UTF-8" );
try {
pageContent = embedCss( pageContent );
pageContent = replaceImgSrc( pageContent );
} catch ( final IOException e ) {
//Can't embed, let's not fail and at least make it usable inside the platform
logger.error( "Can't embed styles and images into scheduled HTML file: ", e );
}
builder.append( '\'' )
.append( Base64.encodeBase64String( StringEscapeUtils.escapeHtml( pageContent ).getBytes( "UTF-8" ) ) )
.append( '\'' )
.append( ", \n" );
index++;
page = content.getPageData( index );
}
//don't need comma in the end
builder.setLength( builder.length() - 3 );
builder.append( " ];\n" );
return builder.toString();
}
private static String embedCss( String pageContent ) throws IOException {
Matcher cssLinkMatcher = CSS.matcher( pageContent );
while ( cssLinkMatcher.find() && cssLinkMatcher.groupCount() > 1 ) {
final String cssContent = getSolutionDirFileContent( STAGING_PATH + cssLinkMatcher.group( 2 ) );
pageContent = cssLinkMatcher.replaceFirst( "<style>\n" + cssContent + "\n</style>" );
cssLinkMatcher = CSS.matcher( pageContent );
}
return pageContent;
}
private static String replaceImgSrc( String pageContent ) throws IOException {
String fullyQualifiedServerUrl = PentahoSystem.getApplicationContext().getFullyQualifiedServerURL();
URL url = new URL( fullyQualifiedServerUrl );
String garbage = url.getProtocol() + "://" + url.getHost() + ":" + url.getPort();
String prefix = fullyQualifiedServerUrl.substring( garbage.length(), fullyQualifiedServerUrl.length() - 1 );
Matcher imgLinkMatcher = IMG.matcher( pageContent );
while ( imgLinkMatcher.find() && imgLinkMatcher.groupCount() > 1 ) {
String imgContent = imgLinkMatcher.group( 0 );
imgContent = imgContent.replace( imgLinkMatcher.group( 2 ), prefix );
pageContent = imgLinkMatcher.replaceFirst( imgContent );
imgLinkMatcher = IMG.matcher( pageContent );
}
return pageContent;
}
private static String getSolutionDirFileContent( final String path ) throws IOException {
final IApplicationContext context = PentahoSystem.getApplicationContext();
final String templateFile =
context == null ? null : context.getSolutionPath( path );
if ( !StringUtil.isEmpty( templateFile ) ) {
try ( FileInputStream fis = new FileInputStream( templateFile ) ) {
return IOUtils.toString( fis );
}
} else {
throw new FileNotFoundException( "Can't find file in solution directory: " + TEMPLATE_PATH );
}
}
}