/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source 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, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Alex Rojkov
*/
package com.caucho.netbeans;
import java.awt.event.FocusEvent;
import org.openide.WizardDescriptor;
import org.openide.WizardValidationException;
import org.openide.util.ChangeSupport;
import org.openide.util.HelpCtx;
import javax.swing.*;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.FocusListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AddResinServerPanel extends JPanel {
private final static Logger log = Logger.getLogger(AddResinServerPanel.class.getName());
//
private JComboBox _versionsBox;
private JButton _downloadButton;
private JProgressBar _progressBar;
private JTextField _home;
private JCheckBox _useHomeAsRootChk;
private JLabel _rootLbl;
private JTextField _root;
private JButton _rootBtn;
private JTextField _hostName;
private JTextField _address;
private JTextField _port;
private JTextField _webapps;
private JTextField _user;
private JTextField _password;
private JCheckBox _useDefaultConf;
private JLabel _pluginConf;
private JLabel _confLbl;
private JTextField _conf;
private JButton _confSelect;
private java.util.List<String> _versions;
private ChangeSupport _support;
private WizardDescriptor.ValidatingPanel _panel;
private WizardDescriptor _wd;
private String _pluginConfName;
AddResinServerPanel() {
init();
}
public void init() {
_support = new ChangeSupport(this);
//
setLayout(new GridBagLayout());
//download: button, choose resin combobox, go button
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.WEST;
constraints.gridx = 0;
constraints.gridy = 0;
/*
add(new JToggleButton(new DownloadVersionsAction()), constraints);
_versionsBox = new JComboBox();
_versionsBox.setEnabled(false);
constraints.gridx++;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1.0;
add(_versionsBox, constraints);
_goBtn = new JButton(new DownloadResinAction());
_goBtn.setEnabled(false);
constraints.gridx++;
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
add(_goBtn, constraints);
*/
//-------
//resin-home: label, resin home dir,
constraints.gridx = 0;
constraints.gridy++;
constraints.insets.left = constraints.insets.right = 0;
constraints.insets.top = constraints.insets.bottom = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0;
constraints.anchor = GridBagConstraints.WEST;
add(new JLabel("Resin Home"), constraints);
_home = new JTextField();
constraints.gridx = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_home, constraints);
_home.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent fe) {
}
@Override
public void focusLost(FocusEvent fe) {
if (_root.getText() == null || _root.getText().trim().isEmpty()) {
_root.setText(_home.getText().trim());
}
}
});
JButton button = new JButton(new SelectResinHomeAction());
constraints.gridx = 2;
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0;
add(button, constraints);
//-------
//download progress bar
_progressBar = new JProgressBar(JProgressBar.HORIZONTAL);
_progressBar.setPreferredSize(new Dimension(0, 10));
constraints.gridx = 1;
constraints.gridy++;
constraints.insets.left = constraints.insets.right = 5;
constraints.insets.top = 5;
constraints.insets.bottom = 10;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_progressBar, constraints);
//-------
// download button
_downloadButton = new JButton(new DownloadResinAction());
constraints.gridx = 1;
constraints.gridy++;
constraints.weightx = 0;
constraints.anchor = GridBagConstraints.EAST;
add(_downloadButton, constraints);
//-------
//resin-root: label, editbox, button
_rootLbl = new JLabel("Resin root");
constraints.gridx = 0;
constraints.gridy++;
constraints.insets.left = 0;
constraints.gridwidth = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0;
constraints.anchor = GridBagConstraints.WEST;
add(_rootLbl, constraints);
_root = new JTextField();
constraints.gridx = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_root, constraints);
_rootBtn = new JButton("Browse...");
constraints.gridx = 2;
constraints.insets.left = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0;
add(_rootBtn, constraints);
//-------
//host name: label, editbox
constraints.gridx = 0;
constraints.gridy++;
add(new JLabel("Resin's host name"), constraints);
_hostName = new JTextField("localhost");
constraints.gridx = 1;
constraints.insets.right = 20;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_hostName, constraints);
//-------
//address/ip: label, editbox
constraints.gridx = 0;
constraints.gridy++;
constraints.insets.right = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0;
add(new JLabel("Address"), constraints);
_address = new JTextField("127.0.0.1");
constraints.gridx = 1;
constraints.insets.right = 20;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_address, constraints);
//-------
//http-port: label,editbox
constraints.gridx = 0;
constraints.gridy++;
constraints.insets.right = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 0;
add(new JLabel("Port"), constraints);
_port = new JTextField("8080");
constraints.gridx = 1;
constraints.insets.right = 20;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_port, constraints);
//-------
//http-port: label,editbox
constraints.gridx = 0;
constraints.gridy++;
constraints.insets.right = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 0;
add(new JLabel("Deploy Directory"), constraints);
_webapps = new JTextField("webapps");
constraints.gridx = 1;
constraints.insets.right = 20;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_webapps, constraints);
button = new JButton("Browse...");
constraints.gridx = 2;
constraints.insets.left = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0;
add(button, constraints);
//-------
//user: label,editbox
/*
constraints.gridx = 0;
constraints.gridy++;
constraints.insets.right = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 0;
add(new JLabel("User"), constraints);
_user = new JTextField("admin");
constraints.gridx = 1;
constraints.insets.right = 20;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_user, constraints);
//password: label,editbox
constraints.gridx = 0;
constraints.gridy++;
constraints.insets.right = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 0;
add(new JLabel("Password"), constraints);
_password = new JTextField("password");
constraints.gridx = 1;
constraints.insets.right = 20;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
add(_password, constraints);
*
*/
//-------
//label: "Select which resin configuration you want to use with this server
/*
JLabel label = new JLabel(
"Select configuration you want to use with this server");
constraints.gridx = 0;
constraints.gridy++;
constraints.insets.right = 0;
constraints.insets.top = 10;
constraints.gridwidth = 3;
constraints.weightx = 1;
add(label, constraints);
//-------
//radio: copy default configuration into the project
_useDefaultConf = new JCheckBox();
_useDefaultConf.setSelected(true);
constraints.gridy++;
constraints.insets.right = 0;
constraints.insets.top = 5;
constraints.gridwidth = 3;
constraints.weightx = 1;
add(_useDefaultConf, constraints);
_pluginConf = new JLabel(" ");
constraints.gridy++;
add(_pluginConf, constraints);
//-------
//configuration: resin.xml
_confLbl = new JLabel("Configuration");
_confLbl.setEnabled(false);
constraints.gridy++;
constraints.gridwidth = 1;
constraints.insets.top = 0;
constraints.weightx = 0;
add(_confLbl, constraints);
_conf = new JTextField();
_conf.setEnabled(false);
constraints.gridx = 1;
constraints.weightx = 1;
add(_conf, constraints);
_confSelect = new JButton(new AbstractAction("Select") {
@Override
public void actionPerformed(ActionEvent ae) {
selectConfiguration();
}
});
_confSelect.setEnabled(false);
constraints.gridx = 2;
constraints.weightx = 0;
add(_confSelect, constraints);
//
_useDefaultConf.setAction(new AbstractAction(
"Copy plugin supplied configuration file into Resin Home") {
@Override
public void actionPerformed(ActionEvent ae) {
copyPluginSuppliedConfigrationFile();
}
});
*
*/
JComponent push = new JPanel();
constraints.gridx = 1;
constraints.gridy++;
constraints.weighty = 1.0;
constraints.fill = GridBagConstraints.BOTH;
add(push, constraints);
//
}
public void copyPluginSuppliedConfigrationFile() {
if (_useDefaultConf.isSelected()) {
_confLbl.setEnabled(false);
_conf.setEnabled(false);
_confSelect.setEnabled(false);
initPluginConfFileName();
} else {
_confLbl.setEnabled(true);
_conf.setEnabled(true);
_confSelect.setEnabled(true);
_pluginConf.setText("Please select configuration file below");
}
}
public void selectConfiguration() {
String home = _home.getText();
String confDir = null;
if (ResinInstance.isResinHome(home)) {
confDir = home + "/conf";
}
JFileChooser chooser;
if (confDir == null) {
chooser = new JFileChooser();
} else {
chooser = new JFileChooser(confDir);
}
chooser.setFileFilter(new FileFilter() {
@Override
public String getDescription() {
return "Accepts files ending with .xml and .conf extensions";
}
@Override
public boolean accept(File file) {
String path = file.getPath();
if (path.endsWith(".xml") || path.endsWith(".conf")) {
return true;
} else {
return false;
}
}
});
chooser.setDialogType(JFileChooser.OPEN_DIALOG);
chooser.setDialogTitle("Select directory where Resin will be installed");
chooser.setMultiSelectionEnabled(false);
chooser.showOpenDialog(this);
final File dest = chooser.getSelectedFile();
if (dest != null) {
_conf.setText(dest.getPath());
}
}
public void initPluginConfFileName() {
String displayName = _wd.getProperty("ServInstWizard_displayName").toString();
String confName = ResinInstance.makeConfName(displayName);
_pluginConfName = confName;
_pluginConf.setText("Configuration is set to $RESIN_HOME/conf/" + confName);
}
public void setWizardDescriptor(WizardDescriptor wd) {
_wd = wd;
}
public void checkInput()
throws WizardValidationException {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE, null);
if (_home.getText() == null || _home.getText().isEmpty()) {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE,
"Supply Resin Home");
throw new WizardValidationException(_home, "", "");
}
if (!ResinInstance.isResinHome(_home.getText())) {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE,
"Invalid Resin Home");
throw new WizardValidationException(_home, "", "");
}
if (_root.getText() == null || _root.getText().isEmpty()) {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE,
"Invalid Resin Root");
throw new WizardValidationException(_root, "", "");
}
String address = _address.getText();
if (address == null || address.isEmpty()) {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE, "Supply Address");
throw new WizardValidationException(_address, "", "");
}
address = address.trim();
if (address.trim() != "*" && !isValidAddress(address)) {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE, "Invalid Address");
throw new WizardValidationException(_address, "", "");
}
String port = _port.getText();
try {
Integer.parseInt(port);
} catch (Exception e) {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE, "Invalid Port");
throw new WizardValidationException(_port, "", "");
}
}
private boolean isValidAddress(String address) {
try {
InetAddress inetAddress = InetAddress.getByName(address);
if (inetAddress.isLoopbackAddress()) {
return true;
}
if (inetAddress.isSiteLocalAddress()) {
return true;
}
if (inetAddress.isAnyLocalAddress()) {
return true;
}
if (inetAddress.isLinkLocalAddress()) {
return true;
}
} catch (UnknownHostException ex) {
log.severe(ex.getMessage());
}
return false;
}
public String getHome() {
return _home.getText().trim();
}
public String getRoot() {
return _root.getText().trim();
}
public String getHost() {
return _hostName.getText().trim();
}
public String getAddress() {
return _address.getText().trim();
}
public int getPort() {
return Integer.parseInt(_port.getText().trim());
}
public String getUser() {
return _user.getText().trim();
}
public String getPassword() {
return _password.getText().trim();
}
public String getConf() {
if (_useDefaultConf.isSelected()) {
return getHome() + "/conf/" + _pluginConfName;
} else {
return _conf.getText().trim();
}
}
public String getWebapps() {
return _webapps.getText();
}
public boolean isUsingPluginConfiguration() {
return _useDefaultConf.isSelected();
}
public void readSettings(Object data) {
}
public void storeSettings(Object data) {
}
public WizardDescriptor.ValidatingPanel getWizardDescriptorPanel() {
if (_panel == null) {
_panel = new WizardDescriptor.ValidatingPanel() {
@Override
public void validate()
throws WizardValidationException {
checkInput();
}
@Override
public void addChangeListener(ChangeListener cl) {
_support.addChangeListener(cl);
}
@Override
public Component getComponent() {
return AddResinServerPanel.this;
}
@Override
public HelpCtx getHelp() {
return HelpCtx.DEFAULT_HELP;
}
@Override
public boolean isValid() {
return true;
}
@Override
public void readSettings(Object data) {
AddResinServerPanel.this.readSettings(data);
}
@Override
public void removeChangeListener(ChangeListener cl) {
_support.removeChangeListener(cl);
}
@Override
public void storeSettings(Object data) {
AddResinServerPanel.this.storeSettings(data);
}
};
}
return _panel;
}
private String getLatestVersion() throws IOException {
try {
URL url = new URL("http://www.caucho.com/download/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "UTF-8"));
int c;
_versions = new ArrayList<String>();
StringBuilder href = new StringBuilder();
while ((c = reader.read()) > 0) {
if ('\"' == c) {
if (href.length() > 9 && href.charAt(0) == 'r'
&& href.charAt(1) == 'e' && href.charAt(2) == 's'
&& href.charAt(3) == 'i' && href.charAt(4) == 'n'
&& href.charAt(5) == '-'
&& href.lastIndexOf(".zip") == href.length() - 4
&& href.charAt(href.length() - 5) != 'c') {
return href.toString();
} else {
href = new StringBuilder();
}
} else if (' ' == c || '<' == c || '=' == c || '>' == c || '\n' == c
|| '\r' == c || '\t' == c) {
href = new StringBuilder();
} else {
href.append((char) c);
}
}
throw new RuntimeException("can't retrieve versions");
} catch (IOException e) {
log.log(Level.WARNING, e.getMessage(), e);
throw e;
}
}
private void downloadResin() {
_downloadButton.setEnabled(false);
_progressBar.setValue(0);
_progressBar.setMinimum(0);
final File file = new File(_home.getText());
if (!file.isAbsolute()) {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE,
"Resin Home must be absolute path");
return;
}
if (!file.exists() && !file.mkdirs()) {
_wd.putProperty(WizardDescriptor.PROP_WARNING_MESSAGE,
"Can't create directory `" + file + "'");
return;
}
SwingWorker download = new SwingWorker() {
@Override
protected Object doInBackground()
throws Exception {
asyncDownloadResin(file);
return null;
}
};
download.execute();
}
private void asyncDownloadResin(File dest) {
InputStream in = null;
OutputStream out = null;
JarFile jar = null;
boolean success = false;
File resinHome = null;
try {
String version = getLatestVersion();
URL url = new URL("http://www.caucho.com/download/" + version);
String temp = System.getProperty("java.io.tmpdir");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
final int len = connection.getHeaderFieldInt("Content-Length", 20000000);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
_progressBar.setMaximum(len * 2);
}
});
in = connection.getInputStream();
String jarFile = temp + File.separatorChar + version;
out = new FileOutputStream(jarFile);
byte[] buffer = new byte[65536];
int bytesRead;
final int[] x = new int[1];
Runnable uiTask = new Runnable() {
public void run() {
_progressBar.setValue(_progressBar.getValue() + x[0]);
}
};
while ((bytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, bytesRead);
out.flush();
x[
0] = bytesRead;
SwingUtilities.invokeLater(uiTask);
}
out.close();
in.close();
jar = new JarFile(jarFile);
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
name = name.substring(name.indexOf('/') + 1);
if (entry.isDirectory()) {
final File file = new File(dest + File.separator + name);
file.mkdirs();
} else {
final File file = new File(dest + File.separator + name);
file.getParentFile().mkdirs();
in = jar.getInputStream(entry);
out = new FileOutputStream(file);
while ((bytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, bytesRead);
out.flush();
}
out.close();
in.close();
}
x[0] = (int) entry.getCompressedSize();
SwingUtilities.invokeLater(uiTask);
}
success = true;
} catch (Exception e) {
log.log(Level.WARNING, e.getMessage(), e);
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
}
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
}
try {
if (jar != null) {
jar.close();
}
} catch (IOException e) {
log.log(Level.WARNING, e.getMessage(), e);
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
_progressBar.setValue(_progressBar.getMaximum());
_downloadButton.setEnabled(true);
}
});
}
}
private class SelectResinHomeAction extends AbstractAction {
public SelectResinHomeAction() {
super("Browse...");
}
@Override
public void actionPerformed(ActionEvent ae) {
String home = _home.getText();
if (home == null) {
home = System.getProperty("user.home");
}
JFileChooser chooser = new JFileChooser(home);
chooser.setDialogType(JFileChooser.OPEN_DIALOG);
chooser.setDialogTitle("Select directory where Resin will be installed");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setMultiSelectionEnabled(false);
chooser.showOpenDialog(AddResinServerPanel.this);
final File dest = chooser.getSelectedFile();
if (dest == null) {
return;
}
home = dest.getPath();
_home.setText(home);
_root.setText(home);
}
}
private class UseResinHomeAsRootAction extends AbstractAction {
public UseResinHomeAsRootAction() {
super("Use Resin home as Resin root");
}
@Override
public void actionPerformed(ActionEvent ae) {
if (_useHomeAsRootChk.isSelected()) {
_rootLbl.setEnabled(false);
_root.setText(_home.getText());
_root.setEnabled(false);
_rootBtn.setEnabled(false);
} else {
_rootLbl.setEnabled(true);
_root.setEnabled(true);
_rootBtn.setEnabled(true);
}
}
}
private class DownloadVersionsAction extends AbstractAction {
public DownloadVersionsAction() {
super("Download");
}
@Override
public void actionPerformed(ActionEvent ae) {
}
}
private class DownloadResinAction extends AbstractAction {
public DownloadResinAction() {
super("Download");
}
@Override
public void actionPerformed(ActionEvent ae) {
downloadResin();
}
}
private class SelectWebappsDirectoryAction extends AbstractAction {
public SelectWebappsDirectoryAction() {
super("Browse...");
}
@Override
public void actionPerformed(ActionEvent ae) {
File root = new File(_root.getText());
File webapps = new File(_webapps.getText());
File dir = null;
if (webapps.isAbsolute()) {
dir = webapps;
} else {
dir = root;
}
if (!dir.exists()) {
dir = new File(System.getProperty("user.home"));
}
JFileChooser chooser = new JFileChooser(dir);
chooser.setDialogType(JFileChooser.OPEN_DIALOG);
chooser.setDialogTitle("Select directory where Resin will deploy webapps");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setMultiSelectionEnabled(false);
chooser.showOpenDialog(AddResinServerPanel.this);
final File dest = chooser.getSelectedFile();
if (dest == null) {
return;
}
String deployDir = dest.getPath();
_webapps.setText(deployDir);
}
}
}