修改帆软报表toimage函数,支持https和无效ssl证书

2020-03-04  

帆软报表 8.0,使用自带的 toimage 函数,无法加载 https 协议和 ssl 证书无效的的图片,对其进行修改,代码如下:

package com.fr.function;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;

import com.fr.base.BaseUtils;
import com.fr.base.FRContext;
import com.fr.base.GraphHelper;
import com.fr.base.Utils;
import com.fr.performance.PerformanceManager;
import com.fr.script.AbstractFunction;
import com.fr.stable.ColumnRow;
import com.fr.stable.CoreGraphHelper;
import com.fr.stable.Primitive;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;

/**
 * 修改帆软toimage函数,支持https协议图片,支持无效证书
 * @author ConstXiong
 */
@SuppressWarnings("deprecation")
public class TOIMGS extends AbstractFunction {

	private static final long serialVersionUID = 1L;

	public Object run(Object[] paramArrayOfObject) {
		if (paramArrayOfObject.length < 1) {
			return Primitive.ERROR_NAME;
		}
		Object localObject1 = paramArrayOfObject[0];
		boolean bool = true;
		if (paramArrayOfObject.length > 1) {
			bool = Boolean.valueOf(Utils.objectToString(paramArrayOfObject[1])).booleanValue();
		}
		if ((localObject1 instanceof String))
			try {
				Image localImage = readImageFromPath(localObject1, bool);
				Object localObject2 = localImage;
				if (paramArrayOfObject.length > 3) {
					localObject2 = drawExtendImage(paramArrayOfObject, localImage);
				}
				return localObject2;
			} catch (Exception localException) {
				FRContext.getLogger().error(localException.getMessage(), localException);
			}
		return Primitive.ERROR_NAME;
	}

	private void record(BufferedImage paramBufferedImage, boolean paramBoolean) {
		if (paramBufferedImage == null) {
			return;
		}
		long l = PerformanceManager.getMemoryEstimation().estimateImageMemory( paramBufferedImage);
		String str = getMark();
		PerformanceManager.getRecorder().recordToImageFun(str, l, paramBoolean);
	}

	private String getMark() {
		ColumnRow localColumnRow = getCalculator().getCurrentColumnRow();
		String str;
		if (localColumnRow != null) {
			str = localColumnRow.toString();
		} else {
			str = "TOIMGS";
		}
		return str;
	}

	private Image readImageFromPath(Object paramObject, boolean paramBoolean) {
		String str1 = (String) paramObject;
		if ((str1.endsWith("/")) || (str1.endsWith("\\"))) {
			paramObject = str1.substring(0, ((String) paramObject).length() - 1);
		}
		String str2 = ((String) paramObject).trim();
		BufferedImage localBufferedImage = getBufferedImage(paramBoolean, str2);
		if ((localBufferedImage == null) && (FRContext.getCurrentEnv() != null)
				&& (StringUtils.isNotBlank((String) paramObject))) {
			String str3 = StableUtils.pathJoin(new String[] {
					new File(FRContext.getCurrentEnv().getPath()).getParent(),
					Utils.objectToString(paramObject) });
			localBufferedImage = getBufferedImage(paramBoolean, str3);
		}
		return localBufferedImage;
	}

	private BufferedImage getBufferedImage(boolean paramBoolean,
			String paramString) {
		BufferedImage localBufferedImage = null;
		if (paramBoolean) {
			localBufferedImage = BaseUtils.readCacheImage(paramString);
			if (localBufferedImage != null) {
				record(localBufferedImage, true);
				return localBufferedImage;
			}
			localBufferedImage = readImage(paramString);
			record(localBufferedImage, false);
			return localBufferedImage;
		}
		localBufferedImage = readImage(paramString);
		record(localBufferedImage, false);
		return localBufferedImage;
	}

	private BufferedImage readImage(String imageUrl) {
		try {
			return requestImg(imageUrl);
		} catch (Exception e) {
			FRContext.getLogger().error(e.getMessage(), e);
		}
		return null;
	}

	private Object drawExtendImage(Object[] paramArrayOfObject, Image paramImage) {
		int i = 0;
		int j = 0;
		if (paramImage == null)
			return Primitive.NULL;
		j = getRealSize(paramArrayOfObject[2], paramImage.getWidth(null));
		i = getRealSize(paramArrayOfObject[3], paramImage.getHeight(null));
		if ((i != 0) && (j != 0)) {
			BufferedImage localBufferedImage = CoreGraphHelper
					.createBufferedImage(j, i, 2);
			Graphics2D localGraphics2D = localBufferedImage.createGraphics();
			localGraphics2D.setPaint(Color.white);
			GraphHelper.paintImage(localGraphics2D, j, i, paramImage, 2, -1, 0,
					-1, -1);
			return localBufferedImage;
		}
		return paramImage;
	}

	private int getRealSize(Object paramObject, int paramInt) {
		String str = paramObject.toString();
		int i = 0;
		if (str.indexOf("%") != -1) {
			str = str.substring(0, str.length() - 1);
			i = (int) (paramInt * (Double.parseDouble(str) / 100.0D));
		} else {
			i = Integer.parseInt(str);
		}
		return i;
	}

	public Type getType() {
		return OTHER;
	}

	public String getCN() {
		return "TOIMGS(path):显示指定路径下的图片。此处默认开启了图片缓存功能以加速报表的生成.\n如不需要缓存,请在参数后面追加值FALSE,例如:TOIMGS(\"D:/fr.png\",false).\n如需要指定图片大小,拉伸显示, 则需要添加参数,TOIMGS(patch, true, width, height).\n示例:=TOIMGS(\"d:/1.jpg\", true, \"50%\", 300), 第三个参数为指定宽度, 第四个参数为指定高度.\n如果参数为整数, 则直接写数字, 如果为百分比, 则需要加上引号, 如\"300%\"";
	}

	public String getEN() {
		return "TOIMGS (path): display images under the specified path. Here enabled by default image cache to speed up report generation capabilities.\nIf no cache, appending the value of the parameter FALSE, for example:TOIMGS(\"D:/fr.png\",false).\nIf you need to specify the image size, stretch, you need to add parameters: TOIMGS(patch, true, width, height).\neg, =TOIMGS(\"d:/1.jpg\", true, \"50\", 300), The third parameter to specify the width, the fourth parameter is the height specified.\nIf the parameter is an integer, write directly to digital, as a percentage, you need the quotation marks, such as \"300%\"";
	}
	
	public static BufferedImage requestImg(String url) {
		HttpClient httpclient = httpsTrustClient();
		HttpPost httpRequest = new HttpPost(url);
		List<NameValuePair> map = new ArrayList<NameValuePair>();
		try {
			httpRequest.setEntity(new UrlEncodedFormEntity(map, HTTP.UTF_8));
			HttpResponse response = httpclient.execute(httpRequest);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				return ImageIO.read(entity.getContent());
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			httpRequest.abort();
		}

		return null;
	}

	private static HttpParams httpParams;

	private static ClientConnectionManager connectionManager;

	/**
	 * 最大连接数
	 */
	public final static int MAX_TOTAL_CONNECTIONS = 10;

	/**
	 * 获取连接的最大等待时间
	 */
	public final static int WAIT_TIMEOUT = 300000;

	/**
	 * 每个路由最大连接数
	 */
	public final static int MAX_ROUTE_CONNECTIONS = 400;

	/**
	 * 连接超时时间
	 */
	public final static int CONNECT_TIMEOUT = 10000;

	/**
	 * 读取超时时间
	 */
	public final static int READ_TIMEOUT = 30000;

	static {
		httpParams = new BasicHttpParams();
		// 设置最大连接数
		ConnManagerParams.setMaxTotalConnections(httpParams,
				MAX_TOTAL_CONNECTIONS);
		// 设置获取连接的最大等待时间
		ConnManagerParams.setTimeout(httpParams, WAIT_TIMEOUT);
		// 设置每个路由最大连接数
		ConnPerRouteBean connPerRoute = new ConnPerRouteBean(
				MAX_ROUTE_CONNECTIONS);
		ConnManagerParams.setMaxConnectionsPerRoute(httpParams, connPerRoute);
		// 设置连接超时时间
		HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);
		// 设置读取超时时间
		HttpConnectionParams.setSoTimeout(httpParams, READ_TIMEOUT);

		SchemeRegistry registry = new SchemeRegistry();
		registry.register(new Scheme("http", PlainSocketFactory
				.getSocketFactory(), 80));
		registry.register(new Scheme("https", SSLSocketFactory
				.getSocketFactory(), 443));

		connectionManager = new ThreadSafeClientConnManager(httpParams,
				registry);
	}

	public static HttpClient getHttpClient() {
		return new DefaultHttpClient(connectionManager, httpParams);
	}

	public static HttpClient httpsTrustClient() {
		HttpClient base = getHttpClient();
		try {
			SSLContext ctx = SSLContext.getInstance("TLS");
			X509TrustManager tm = new X509TrustManager() {
				public void checkClientTrusted(X509Certificate[] chain,
						String authType) throws CertificateException {
				}

				public void checkServerTrusted(X509Certificate[] chain,
						String authType) throws CertificateException {
				}

				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}

			};
			ctx.init(null, new TrustManager[] { tm }, null);
			SSLSocketFactory ssf = new SSLSocketFactory(ctx);
			ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
			ClientConnectionManager ccm = base.getConnectionManager();
			SchemeRegistry sr = ccm.getSchemeRegistry();
			// 设置要使用的端口,默认是443
			sr.register(new Scheme("https", ssf, 443));
			return new DefaultHttpClient(ccm, base.getParams());
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}
}

 

ConstXiong 备案号:苏ICP备16009629号-3