帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

614 lines
25 KiB

/*
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
*/
package com.fr.design.data.datapane.connect;
import com.fr.data.driver.util.JarFileParseUtil;
import com.fr.data.impl.Connection;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.data.security.ssl.impl.NormalSsl;
import com.fr.data.solution.ExceptionSolutionSelector;
import com.fr.data.solution.entity.DriverPage;
import com.fr.data.solution.processor.ClassNotFoundExceptionSolutionProcessor;
import com.fr.data.solution.processor.SolutionProcessor;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.file.ConnectionService;
import com.fr.log.FineLoggerFactory;
import com.fr.rpc.ExceptionHandler;
import com.fr.rpc.RPCInvokerExceptionInfo;
import com.fr.stable.ArrayUtils;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.net.URI;
import java.util.concurrent.ExecutionException;
/**
* Database Connection pane.
*/
public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connection> extends BasicBeanPane<com.fr.data.impl.Connection> {
private static int MAX_MAIN_PANEL_HEIGHT = 410;
private static int MAX_MAIN_PANEL_WIDTH = 675;
private UILabel message;
private UIButton okButton;
private UIButton cancelButton;
private JDialog dialog;
private UILabel uiLabel;
private UILabel directUiLabel;
private UILabel detailLabel;
private JPanel midPane;
private JPanel hiddenPanel;
// 编码转换.
private UIComboBox charSetComboBox;
private String originalCharSet = null;
private JPanel mainPanel;
// Database pane
public DatabaseConnectionPane() {
this.initComponents();
}
ActionListener testConnectionActionListener = new ActionListener() {
private boolean firstCreate = true;
@Override
public void actionPerformed(ActionEvent evt) {
// Try the java connection.
final SwingWorker<Void, Void> connectionThread = new TestConnectionWorker();
midPane.setVisible(false);
hiddenPanel.setVisible(false);
initDialogPane();
connectionThread.execute();
// 老bug,initDialogPane 中的 dialog每次都是new的,所以可以重新添加 listener,但是其他的对象不行,会多次添加listener
if (firstCreate) {
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
hiddenPanel.removeAll();
dialog.dispose();
}
});
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
hiddenPanel.removeAll();
dialog.dispose();
connectionThread.cancel(true);
}
});
detailLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (hiddenPanel.isVisible()) {
hiddenPanel.setVisible(false);
dialog.setSize(new Dimension(380, 142));
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Look_Detail"));
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.right"));
} else {
dialog.setSize(new Dimension(380, 270));
hiddenPanel.setVisible(true);
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Hide_Detail"));
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.down"));
}
}
@Override
public void mouseEntered(MouseEvent e) {
detailLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
detailLabel.setCursor(Cursor.getDefaultCursor());
}
});
firstCreate = false;
}
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
connectionThread.cancel(true);
}
});
dialog.setVisible(true);
hiddenPanel.removeAll();
dialog.dispose();
}
};
protected abstract JPanel mainPanel();
protected abstract boolean isFineBI();
@Override
public void populateBean(com.fr.data.impl.Connection ob) {
populateSubDatabaseConnectionBean((E) ob);
if (mainPanel instanceof JDBCDefPane) {
return;
}
this.originalCharSet = ob.getOriginalCharsetName();
if (StringUtils.isBlank(originalCharSet)) {
this.charSetComboBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Encode_Auto"));
} else {
this.charSetComboBox.setSelectedItem(ob.getOriginalCharsetName());
}
}
protected abstract void populateSubDatabaseConnectionBean(E ob);
@Override
public com.fr.data.impl.Connection updateBean() {
E ob = updateSubDatabaseConnectionBean();
if (mainPanel instanceof JDBCDefPane) {
return ob;
}
ob.setOriginalCharsetName(this.originalCharSet);
if (this.charSetComboBox.getSelectedIndex() == 0) {
ob.setNewCharsetName(null);
ob.setOriginalCharsetName(null);
} else {
ob.setNewCharsetName(EncodeConstants.ENCODING_GBK);
ob.setOriginalCharsetName(((String) this.charSetComboBox.getSelectedItem()));
}
return ob;
}
protected abstract E updateSubDatabaseConnectionBean();
protected JPanel getAdvancePane() {
throw new UnsupportedOperationException();
}
protected SslPane getSslPane() {
throw new UnsupportedOperationException();
}
protected SshPane getSshPane() {
throw new UnsupportedOperationException();
}
protected void initComponents() {
message = new UILabel();
uiLabel = new UILabel();
detailLabel = new UILabel();
directUiLabel = new UILabel();
hiddenPanel = new JPanel();
midPane = new JPanel();
midPane.add(directUiLabel);
midPane.add(detailLabel);
okButton = new UIButton(Toolkit.i18nText("Fine-Design_Report_OK"));
cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel northPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
UIScrollPane uiScrollPane = new UIScrollPane(northPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
this.add(uiScrollPane, BorderLayout.CENTER);
// 按钮.
JPanel testPane = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane();
northPane.add(testPane, BorderLayout.NORTH);
UIButton testButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Datasource_Test_Connection"));
testPane.add(testButton);
testButton.addActionListener(testConnectionActionListener);
testPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 3, 4));
// Center
mainPanel = mainPanel();
JPanel advancedPanel = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_Advanced"));
if (mainPanel instanceof JDBCDefPane) {
northPane.add(mainPanel, BorderLayout.CENTER);
ActionLabel actionLabel = new ActionLabel(Toolkit.i18nText("Fine-Design_Advanced_More_Settings"));
actionLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
JDialog wDialog = createJDialog();
if (wDialog != null) {
wDialog.setVisible(true);
}
}
});
JPanel actionLabelPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
actionLabelPanel.setBorder(BorderFactory.createEmptyBorder(2, 4, 4, 20));
actionLabelPanel.add(actionLabel, BorderLayout.WEST);
JPanel advancePane = getAdvancePane();
if (advancePane != null) {
advancedPanel.add(advancePane);
}
advancedPanel.add(actionLabelPanel);
northPane.add(getSshPane());
northPane.add(getSslPane());
} else {
//非jdbc配置布局保持不变
advancedPanel.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, 60));
if (mainPanel.getPreferredSize().height > MAX_MAIN_PANEL_HEIGHT || mainPanel.getPreferredSize().width > MAX_MAIN_PANEL_WIDTH) {
UIScrollPane jp = new
UIScrollPane(mainPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jp.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, MAX_MAIN_PANEL_HEIGHT));
northPane.add(jp, BorderLayout.CENTER);
} else {
mainPanel.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, MAX_MAIN_PANEL_HEIGHT));
northPane.add(mainPanel, BorderLayout.CENTER);
}
// ChartSet
String[] defaultEncode = new String[]{Toolkit.i18nText("Fine-Design_Encode_Auto")};
charSetComboBox = new UIComboBox(ArrayUtils.addAll(defaultEncode, EncodeConstants.ENCODING_ARRAY));
JPanel chartSetPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(2);
chartSetPane.add(GUICoreUtils.createNamedPane(charSetComboBox, Toolkit.i18nText("Fine-Design_Basic_Datasource_Charset") + ":"));
advancedPanel.add(chartSetPane);
}
northPane.add(advancedPanel);
}
private JDialog createJDialog() {
return JDBC.getAdvancedAttrPane() != null ? JDBC.getAdvancedAttrPane().showWindow(SwingUtilities.getWindowAncestor(mainPanel)) : null;
}
private void initDialogPane() {
message.setText(Toolkit.i18nText("Fine-Design_Basic_Datasource_Test_Connection") + "...");
message.setBorder(BorderFactory.createEmptyBorder(8, 5, 0, 0));
okButton.setEnabled(false);
dialog = new JDialog((Dialog) SwingUtilities.getWindowAncestor(DatabaseConnectionPane.this), Toolkit.i18nText("Fine-Design_Basic_Datasource_Test_Connection"), true);
dialog.setSize(new Dimension(380, 125));
okButton.setEnabled(false);
JPanel jp = new JPanel();
JPanel upPane = new JPanel();
JPanel downPane = new JPanel();
uiLabel = new UILabel(UIManager.getIcon("OptionPane.informationIcon"));
upPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
upPane.add(uiLabel);
upPane.add(message);
midPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0));
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.right"));
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Look_Detail"));
detailLabel.setForeground(Color.BLUE);
hiddenPanel.setLayout(new BorderLayout(2, 0));
hiddenPanel.add(new JPanel(), BorderLayout.WEST);
hiddenPanel.add(new JPanel(), BorderLayout.EAST);
downPane.setLayout(new FlowLayout(FlowLayout.RIGHT, 15, 9));
downPane.add(okButton);
downPane.add(cancelButton);
jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS));
jp.add(upPane);
jp.add(midPane);
jp.add(hiddenPanel);
jp.add(downPane);
dialog.add(jp);
dialog.setResizable(false);
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(DatabaseConnectionPane.this));
}
public static class JDBC extends DatabaseConnectionPane<JDBCDatabaseConnection> {
private static JDBCDefPane jdbcDefPane = new JDBCDefPane();
private static DBCPAttrPane dbcpAttrPane = new DBCPAttrPane();
private static AdvancePane advancePane = new AdvancePane();
private static SslPane sslPane = new SslPane();
private static SshPane sshPane = new SshPane();
static {
jdbcDefPane.addLinkPane(sslPane);
}
@Override
protected JPanel mainPanel() {
return jdbcDefPane;
}
@Override
protected boolean isFineBI() {
return false;
}
protected static DBCPAttrPane getAdvancedAttrPane() {
return dbcpAttrPane;
}
@Override
protected void populateSubDatabaseConnectionBean(JDBCDatabaseConnection ob) {
jdbcDefPane.populate(ob);
dbcpAttrPane.populate(jdbcDefPane.getJDBCDatabase());
advancePane.populate(jdbcDefPane.getJDBCDatabase());
sshPane.populate(jdbcDefPane.getJDBCDatabase());
sslPane.populate(jdbcDefPane.getJDBCDatabase());
}
@Override
protected JDBCDatabaseConnection updateSubDatabaseConnectionBean() {
JDBCDatabaseConnection jdbcDatabaseConnection = jdbcDefPane.update();
dbcpAttrPane.update(jdbcDatabaseConnection);
advancePane.update(jdbcDatabaseConnection);
sshPane.update(jdbcDatabaseConnection);
if (sslPane.isVisible()) {
sslPane.update(jdbcDatabaseConnection);
} else {
jdbcDatabaseConnection.setSsl(new NormalSsl());
}
return jdbcDatabaseConnection;
}
@Override
protected JPanel getAdvancePane() {
return advancePane;
}
@Override
protected SslPane getSslPane() {
return sslPane;
}
@Override
protected SshPane getSshPane() {
return sshPane;
}
@Override
protected String title4PopupWindow() {
return "JDBC";
}
}
public static class JNDI extends DatabaseConnectionPane<JNDIDatabaseConnection> {
private static JNDIDefPane jndiDefPane = new JNDIDefPane();
@Override
protected JPanel mainPanel() {
return jndiDefPane;
}
@Override
protected boolean isFineBI() {
return false;
}
@Override
protected void populateSubDatabaseConnectionBean(JNDIDatabaseConnection ob) {
jndiDefPane.populate(ob);
}
@Override
protected JNDIDatabaseConnection updateSubDatabaseConnectionBean() {
return jndiDefPane.update();
}
@Override
protected String title4PopupWindow() {
return "JNDI";
}
}
private class TestConnectionWorker extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {
Connection database = DatabaseConnectionPane.this.updateBean();
// 返回连接结果
DriverPage.updateCache();
final Exception[] exception = new Exception[1];
WorkContext.getCurrent().get(ConnectionService.class, new ExceptionHandler() {
@Override
public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) {
// 正常调用发生的异常也会被捕获,因此需要对异常类型进行判断,如果是NoSuchMethodException 就要去调用 testConnection
// 如果不是 NoSuchMethodException 保存下异常上下文
// 两种情况下异常都需要抛出
if (exceptionInfo.getException() instanceof NoSuchMethodException) {
if (!WorkContext.getCurrent().get(ConnectionService.class).test(database)) {
exception[0] = new Exception(Toolkit.i18nText("Fine-Design_Description_Of_Test_Connection"));
}
} else {
exception[0] = exceptionInfo.getException();
}
return null;
}
}).test(database);
if (exception[0] != null) {
throw exception[0];
}
return null;
}
@Override
protected void done() {
try {
get();
dialog.setSize(new Dimension(380, 125));
okButton.setEnabled(true);
uiLabel.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
message.setText(Toolkit.i18nText("Fine-Design_Basic_Datasource_Connection_Successfully"));
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
dealWithException(e);
}
}
private void dealWithException(ExecutionException e) {
dialog.setSize(new Dimension(380, 142));
midPane.setVisible(true);
hiddenPanel.setVisible(false);
okButton.setEnabled(true);
uiLabel.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
message.setText(Toolkit.i18nText("Fine-Design_Basic_Connection_Failed"));
Connection database = DatabaseConnectionPane.this.updateBean();
SolutionProcessor select = ExceptionSolutionSelector.get().select(e, database);
String detail = select.getResultException().getDetailMessage();
String solution = select.getResultException().getSolution();
if (select instanceof ClassNotFoundExceptionSolutionProcessor) {
showClassNotFoundUI(select.getResultException().getDetailMessage(), select.getResultException().getSolution());
} else {
showExceptionMessageUI(detail, solution);
}
okButton.setEnabled(true);
}
private void showClassNotFoundUI(String detailMessage, String solution) {
JPanel gridJpanel = new JPanel();
gridJpanel.setLayout(new GridLayout(5, 1, 0, 5));
UILabel driverTips = new UILabel();
driverTips.setText(Toolkit.i18nText("Fine_Designer_Not_Found_Driver"));
gridJpanel.add(driverTips);
UILabel deatail = new UILabel();
String content = Toolkit.i18nText("Fine_Designer_Not_Found") + " " + detailMessage+ " " + Toolkit.i18nText("Fine_Designer_Driver");
deatail.setText(content);
deatail.setToolTipText(content);
gridJpanel.add(deatail);
UILabel redirect = new UILabel();
if (solution != null) {
redirect.setText(Toolkit.i18nText("Fine_Designer_Download_Driver"));
redirect.setForeground(Color.BLUE);
redirect.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
try {
Desktop.getDesktop().browse(new URI(solution));
} catch (Exception clickException) {
FineLoggerFactory.getLogger().warn("can not open browser with {}", solution);
}
}
@Override
public void mouseEntered(MouseEvent e) {
redirect.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
redirect.setCursor(Cursor.getDefaultCursor());
}
});
} else {
redirect.setText(Toolkit.i18nText("Fine_Designer_Not_Found_Driver_No_Solution"));
}
gridJpanel.add(redirect);
hiddenPanel.add(gridJpanel);
gridJpanel.setBackground(Color.WHITE);
}
private void showExceptionMessageUI(String detail, String solution) {
JPanel borderPanel = new JPanel();
borderPanel.setLayout(new BorderLayout());
JTextArea jta = new JTextArea();
JScrollPane jsp = new JScrollPane(jta);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
Connection con = DatabaseConnectionPane.this.updateBean();
if(con instanceof JDBCDatabaseConnection && WorkContext.getCurrent().isLocal()) {
String driverPath = JarFileParseUtil.getDriverClassPath((JDBCDatabaseConnection) con);
jta.append(Toolkit.i18nText("Fine_Designer_Current_Driver_Path") + ":" + driverPath + "\n");
JPanel testDriverPanel = generateTestDriverPanel((JDBCDatabaseConnection) con, driverPath);
borderPanel.add(testDriverPanel, BorderLayout.NORTH);
}
jta.append(detail + "\n");
jta.append(solution);
jta.setCaretPosition(0);
jta.setEditable(false);
jta.getCaret().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
jta.getCaret().setVisible(true);
}
});
borderPanel.add(jsp, BorderLayout.CENTER);
hiddenPanel.add(borderPanel);
}
private JPanel generateTestDriverPanel(JDBCDatabaseConnection con, String driverPath) {
JPanel xBorderPanel = new JPanel();
xBorderPanel.setLayout(new BorderLayout());
UILabel driverTestTip = new UILabel();
JLabel testResult = new JLabel();
driverTestTip.setForeground(Color.BLUE);
driverTestTip.setVisible(true);
testResult.setVisible(false);
testResult.setHorizontalAlignment(SwingConstants.CENTER);
driverTestTip.setText(Toolkit.i18nText("Fine_Designer_Driver_Path_Test"));
xBorderPanel.add(driverTestTip, BorderLayout.WEST);
xBorderPanel.add(testResult, BorderLayout.CENTER);
driverTestTip.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
driverTestTip.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
driverTestTip.setCursor(Cursor.getDefaultCursor());
}
@Override
public void mouseClicked(MouseEvent e) {
try {
String path;
if(driverPath.endsWith(JarFileParseUtil.JAR_MARKER)) {
path = new File(driverPath).getParent();
} else {
path = driverPath;
}
if(hasDuplicateDriver(con.getDriver(), path)) {
testResult.setForeground(Color.RED);
testResult.setText(Toolkit.i18nText("Fine_Designer_Driver_Conflict"));
} else {
testResult.setForeground(Color.BLACK);
testResult.setText(Toolkit.i18nText("Fine_Designer_Driver_No_Conflict"));
}
testResult.setVisible(true);
} catch (Exception clickException) {
FineLoggerFactory.getLogger().warn(clickException, "can not test driver conflict");
}
}
});
return xBorderPanel;
}
private boolean hasDuplicateDriver(String driver, String folder) {
return JarFileParseUtil.hasDuplicateDriver(driver, folder);
}
}
}