/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org 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 version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ package com.sun.star.wizards.web; import java.util.List; import java.util.Vector; import com.sun.star.awt.PushButtonType; import com.sun.star.awt.XButton; import com.sun.star.awt.XControl; import com.sun.star.awt.XFixedText; import com.sun.star.awt.XTextComponent; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.ucb.AuthenticationRequest; import com.sun.star.ucb.InteractiveAugmentedIOException; import com.sun.star.ucb.InteractiveNetworkConnectException; import com.sun.star.ucb.InteractiveNetworkResolveNameException; import com.sun.star.ucb.OpenCommandArgument2; import com.sun.star.ucb.OpenMode; import com.sun.star.wizards.common.Desktop; import com.sun.star.wizards.common.FileAccess; import com.sun.star.wizards.common.Helper; import com.sun.star.wizards.common.SystemDialog; import com.sun.star.wizards.common.UCB; import com.sun.star.wizards.ui.UIConsts; import com.sun.star.wizards.ui.UnoDialog; import com.sun.star.wizards.ui.UnoDialog2; import com.sun.star.wizards.ui.event.DataAware; import com.sun.star.wizards.ui.event.UnoDataAware; import com.sun.star.wizards.web.data.CGPublish; import com.sun.star.wizards.web.data.CGSettings; /** * This is the FTP Dialog.
* The Dialog enables the user: * (*) entering FTP server and user information. * (*) testing the connection. * (*) choosing a directory on the server. * If a connection was established succesfully, the user may * press OK, which will change * the CGPublish object propertiers according the user's input. * If no connection was established. the OK and Choose-Dir button are disabled. * See the method "disconnect()" which disables them. * * I use here the DataAware concept to automatically update * the members ip, username, and password (via the methods setXXX(...)) * for details see the ui.events.DataAware classes.
*/ public class FTPDialog extends UnoDialog2 implements UIConsts, WWHID { /** * A Constant used for the setLabel(int) method to change the * status-display. "unknown" is the status when the user first * opens the dialog, or changes the servername/username/password. */ private final static int STATUS_UNKONWN = 0; /** * A Constant used for the setLabel(int) method to change the * status-display. (connection established) */ private final static int STATUS_OK = 1; /** * A Constant used for the setLabel(int) method to change the * status-display. */ private final static int STATUS_USER_PWD_WRONG = 2; /** * A Constant used for the setLabel(int) method to change the * status-display. */ private final static int STATUS_SERVER_NOT_FOUND = 3; /** * A Constant used for the setLabel(int) method to change the * status-display. */ private final static int STATUS_NO_RIGHTS = 4; /** * A Constant used for the setLabel(int) method to change the * status-display. */ private final static int STATUS_HOST_UNREACHABLE = 5; /** * A Constant used for the setLabel(int) method to change the * status-display. */ private final static int STATUS_CONNECTING = 6; /** * The icon url for error */ private final static String ICON_ERROR = "ftperror.gif"; /** * The icon url for ok (connection ok) */ private final static String ICON_OK = "ftpconnected.gif"; /** * The icon url for unknown - this is the status when * the user first opens the dialog */ private final static String ICON_UNKNOWN = "ftpunknown.gif"; /** * The icon url for an icon representing the "connecting" state. */ private final static String ICON_CONNECTING = "ftpconnecting.gif"; //GUI Components as Class members. //Fixed Line private XControl ln1; private XFixedText lblFTPAddress; private XTextComponent txtHost; private XFixedText lblUsername; private XTextComponent txtUsername; private XFixedText lblPassword; private XTextComponent txtPassword; //Fixed Line private XControl ln2; private XButton btnTestConnection; private XControl imgStatus; private XFixedText lblStatus; //Fixed Line private XControl ln3; private XTextComponent txtDir; private XButton btnDir; private XButton btnOK; private XButton btnCancel; private XButton btnHelp; //Font Descriptors as Class members. //Resources Object private FTPDialogResources resources; private List dataAware = new Vector(); public String username = ""; public String password = ""; /** * The ftp host name */ public String host = ""; /** * The ftp directory. */ private String dir = ""; /** * the ftp publish object which contains the * data for this dialog. */ private CGPublish publish; private UCB ucb; /** * used for the status images url. */ private String imagesDirectory; /** * constructor. * constructs the UI. * @param xmsf * @param p the publishert object that contains the data * for this dialog * @throws Exception */ public FTPDialog(XMultiServiceFactory xmsf, CGPublish p) throws Exception { super(xmsf); publish = p; imagesDirectory = FileAccess.connectURLs(((CGSettings) (publish.root)).soTemplateDir, "../wizard/bitmap/"); //Load Resources resources = new FTPDialogResources(xmsf); ucb = new UCB(xmsf); //set dialog properties... Helper.setUnoPropertyValues(xDialogModel, new String[] { "Closeable", "Height", "HelpURL", "Moveable", "Name", "PositionX", "PositionY", "Title", "Width" }, new Object[] { Boolean.TRUE, new Integer(160), "HID:" + HID_FTP, Boolean.TRUE, "FTPDialog", new Integer(167), new Integer(82), resources.resFTPDialog_title, new Integer(222) }); //add controls to dialog build(); //make the hostname, username and password textfield data-aware. configure(); //make sure we display a disconnected status. disconnect(); } /** * Add controls to dialog. */ public void build() { final String[] PROPNAMES_LABEL = new String[] { "Height", "Label", "Name", "PositionX", "PositionY", "TabIndex", "Width" }; final String[] PROPNAMES_BUTTON = new String[] { "Height", "HelpURL", "Label", "Name", "PositionX", "PositionY", "TabIndex", "Width" }; final String[] PROPNAMES_BUTTON2 = new String[] { "Height", "HelpURL", "Label", "Name", "PositionX", "PositionY", "PushButtonType", "TabIndex", "Width" }; ln1 = insertFixedLine("ln1", PROPNAMES_LABEL, new Object[] { INTEGERS[8], resources.resln1_value, "ln1", INTEGERS[6], INTEGERS[6], new Short((short) 0), new Integer(210) }); lblFTPAddress = insertLabel("lblFTPAddress", PROPNAMES_LABEL, new Object[] { INTEGERS[8], resources.reslblFTPAddress_value, "lblFTPAddress", INTEGER_12, new Integer(20), new Short((short) 1), new Integer(95) }); txtHost = insertTextField("txtHost", "disconnect", new String[] { "Height", "HelpURL", "Name", "PositionX", "PositionY", "TabIndex", "Width" }, new Object[] { INTEGER_12, "HID:" + HID_FTP_SERVER, "txtIP", new Integer(110), new Integer(18), new Short((short) 2), new Integer(106) }); lblUsername = insertLabel("lblUsername", PROPNAMES_LABEL, new Object[] { INTEGERS[8], resources.reslblUsername_value, "lblUsername", INTEGER_12, new Integer(36), new Short((short) 3), new Integer(85) }); txtUsername = insertTextField("txtUsername", "disconnect", new String[] { "Height", "HelpURL", "Name", "PositionX", "PositionY", "TabIndex", "Width" }, new Object[] { INTEGER_12, "HID:" + HID_FTP_USERNAME, "txtUsername", new Integer(110), new Integer(34), new Short((short) 4), new Integer(106) }); lblPassword = insertLabel("lblPassword", PROPNAMES_LABEL, new Object[] { INTEGERS[8], resources.reslblPassword_value, "lblPassword", INTEGER_12, new Integer(52), new Short((short) 5), new Integer(85) }); txtPassword = insertTextField("txtPassword", "disconnect", new String[] { "EchoChar", "Height", "HelpURL", "Name", "PositionX", "PositionY", "TabIndex", "Width" }, new Object[] { new Short((short) 42), INTEGER_12, "HID:" + HID_FTP_PASS, "txtPassword", new Integer(110), new Integer(50), new Short((short) 6), new Integer(106) }); ln2 = insertFixedLine("ln2", PROPNAMES_LABEL, new Object[] { INTEGERS[8], resources.resln2_value, "ln2", INTEGERS[6], new Integer(68), new Short((short) 7), new Integer(210) }); btnTestConnection = insertButton("btnConnect", "connect", PROPNAMES_BUTTON, new Object[] { INTEGER_14, "HID:" + HID_FTP_TEST, resources.resbtnConnect_value, "btnConnect", INTEGER_12, new Integer(80), new Short((short) 8), INTEGER_50 }); imgStatus = insertImage("imgStatus", new String[] { "Border", "Height", "PositionX", "PositionY", "ScaleImage", "Tabstop", "Width" }, new Object[] { new Short((short) 0), INTEGER_14, new Integer(68), new Integer(80), Boolean.FALSE, Boolean.FALSE, INTEGER_14 }); lblStatus = insertLabel("lblStatus", PROPNAMES_LABEL, new Object[] { INTEGERS[8], resources.resFTPDisconnected, "lblStatus", new Integer(86), new Integer(82), new Short((short) 9), new Integer(99) }); ln3 = insertFixedLine("ln3", PROPNAMES_LABEL, new Object[] { INTEGERS[8], resources.resln3_value, "ln3", INTEGERS[6], new Integer(100), new Short((short) 10), new Integer(210) }); txtDir = insertTextField("txtDir", null, new String[] { "Enabled", "Height", "HelpURL", "Name", "PositionX", "PositionY", "TabIndex", "Text", "Width" }, new Object[] { new Boolean(false), INTEGER_12, "HID:" + HID_FTP_TXT_PATH, "txtDir", INTEGER_12, new Integer(113), new Short((short) 11), resources.restxtDir_value, new Integer(184) }); btnDir = insertButton("btnDir", "chooseDirectory", PROPNAMES_BUTTON, new Object[] { INTEGER_14, "HID:" + HID_FTP_BTN_PATH, resources.resbtnDir_value, "btnDir", new Integer(199), new Integer(112), new Short((short) 12), INTEGER_16 }); btnOK = insertButton("btnOK", null, PROPNAMES_BUTTON2, new Object[] { INTEGER_14, "HID:" + HID_FTP_OK, resources.resbtnOK_value, "btnOK", new Integer(165), new Integer(142), new Short((short) PushButtonType.OK_value), new Short((short) 13), INTEGER_50 }); btnCancel = insertButton("btnCancel", null, PROPNAMES_BUTTON2, new Object[] { INTEGER_14, "HID:" + HID_FTP_CANCEL, resources.resbtnCancel_value, "btnCancel", new Integer(113), new Integer(142), new Short((short) PushButtonType.CANCEL_value), new Short((short) 14), INTEGER_50 }); btnHelp = insertButton("btnHelp", null, PROPNAMES_BUTTON2, new Object[] { INTEGER_14, "", resources.resbtnHelp_value, "btnHelp", new Integer(57), new Integer(142), new Short((short) PushButtonType.HELP_value), new Short((short) 15), INTEGER_50 }); } /** * Make hostname, username and password text fields data aware. */ private void configure() { dataAware.add(UnoDataAware.attachEditControl(this, "host", txtHost, null, true)); dataAware.add(UnoDataAware.attachEditControl(this, "username", txtUsername, null, true)); dataAware.add(UnoDataAware.attachEditControl(this, "password", txtPassword, null, true)); } /** * Shows the dialog. * If the user clicks ok, changes the given CGPublish properties to the * user input. * @param parent a dialog to center this dialog to. * @return 0 for cancel, 1 for ok. * @throws Exception - well, if something goes wrong... */ public short execute(UnoDialog parent) throws Exception { host = extractHost(publish.cp_URL); username = publish.cp_Username == null ? "" : publish.cp_Username; password = publish.password == null ? "" : publish.password; dir = extractDir(publish.cp_URL); setLabel(STATUS_UNKONWN); enableTestButton(); updateUI(); short result = executeDialog(parent); //change the CGPublish properties if (result == 1) { publish.cp_URL = "ftp://" + host() + getDir(); publish.cp_Username = username; publish.password = password; } return result; } /** * updates the hostname, username, password and * directory text fields. * is called uppon initialization. */ private void updateUI() { DataAware.updateUI(dataAware); setDir(dir); } /** * extract the hostname out of the url used by the * publisher. This url does not include the username:password string. * @param ftpUrl * @return */ private String extractHost(String ftpUrl) { if (ftpUrl == null || ftpUrl.length() < 6) { return ""; } String url = ftpUrl.substring(6); int i = url.indexOf("/"); if (i == -1) { return url; } else { return url.substring(0, i); } } /** * used to get data from the CGPublish object. * @param ftpUrl * @return the directory portion of the ftp-url */ private String extractDir(String ftpUrl) { if (ftpUrl == null || ftpUrl.length() < 6) { return "/"; } String url = ftpUrl.substring(6); int i = url.indexOf("/"); if (i == -1) { return "/"; } else { return url.substring(i); } } /** * enables/disables the "test" button * according to the status of the hostname, username, password text fields. * If one of these fields is empty, the button is disabled. */ private void enableTestButton() { setEnabled(btnTestConnection, !(isEmpty(host) || isEmpty(username) || isEmpty(password))); } /** * @param s * @return true if the string is null or "". */ private final boolean isEmpty(String s) { return (s == null) || (s.equals("")); } /** * @return the ftp url with username and password, * but without the directory portion. */ public String getAcountUrl() { return "ftp://" + username + ":" + password + "@" + host(); } /** * return the host name without the "ftp://" * @return */ private String host() { return host(host); } private static String host(String s) { return (s.startsWith("ftp://") ? s.substring(6) : s); } /** * @return the full ftp url including username, password and directory portion. */ private String getFullUrl() { return getAcountUrl() + dir; } /** * First I try to connect to the full url, including directory. * If an InteractiveAugmentedIOException accures, I try again, * this time without the dir spec. If this works, I change the dir * to "/", if not I say to the user its his problem... * */ public void connect() { setEnabled(btnTestConnection, false); setLabel(STATUS_CONNECTING); boolean success = false; try { connect(getFullUrl()); success = true; } catch (InteractiveAugmentedIOException iaioex) { try { connect(getAcountUrl()); setDir("/"); success = true; } catch (Exception ex) { setLabel(STATUS_NO_RIGHTS); } } catch (InteractiveNetworkResolveNameException inrne) { setLabel(STATUS_SERVER_NOT_FOUND); } catch (AuthenticationRequest ar) { setLabel(STATUS_USER_PWD_WRONG); } catch (InteractiveNetworkConnectException incx) { setLabel(STATUS_HOST_UNREACHABLE); } catch (Exception ex) { setLabel(-1); ex.printStackTrace(); } if (success) { setLabel(STATUS_OK); setEnabled(btnDir, true); setEnabled(btnOK, true); } setEnabled(btnTestConnection, true); } /** * To try the conenction I do some actions that * seem logical to me:
* I get a ucb content. * I list the files in this content. * I call the ucb "open" command. * I get the "Title" property of this content. * @param acountUrl * @throws Exception */ private void connect(String acountUrl) throws Exception { Object content = ucb.getContent(acountUrl); //list files in the content. List l = ucb.listFiles(acountUrl, null); //open the content OpenCommandArgument2 aArg = new OpenCommandArgument2(); aArg.Mode = OpenMode.FOLDERS; // FOLDER, DOCUMENTS -> simple filter aArg.Priority = 32768; // Ignored by most implementations ucb.executeCommand(content, "open", aArg); //get the title property of the content. Object obj = ucb.getContentProperty(content, "Title", String.class); } /** * changes the ftp subdirectory, in both * the UI and the data. * @param s the directory. */ public void setDir(String s) { dir = s; Helper.setUnoPropertyValue(getModel(txtDir), "Text", dir); } /** * @return the ftp subdirecrtory. */ public String getDir() { return dir; } /** * changes the status label to disconnected status, and * disables the ok and choose-dir buttons. * This method is called also when the hostname, username * and passwordtext fields change. */ public void disconnect() { enableTestButton(); setEnabled(btnOK, false); setEnabled(btnDir, false); setLabel(STATUS_UNKONWN); } /** * used for debuging. * @param args */ public static void main(String args[]) { String ConnectStr = "uno:socket,host=localhost,port=8100;urp,negotiate=0,forcesynchronous=1;StarOffice.ServiceManager"; try { XMultiServiceFactory xLocMSF = Desktop.connect(ConnectStr); CGPublish p = new CGPublish(); p.cp_URL = "ftp://tv-1/Folder"; p.cp_Username = "ronftp"; p.password = "ronftp"; FTPDialog dialog = new FTPDialog(xLocMSF, p); dialog.execute(null); } catch (Exception exception) { exception.printStackTrace(); } } /** * changes the status label and icon, according to the * given status * @param status one opf the private status-constants. * if this param is not one of them, an "unknown error" status is displayed. */ private void setLabel(int status) { switch (status) { //not connected yet case STATUS_UNKONWN: setLabel(resources.resFTPDisconnected, ICON_UNKNOWN); break; //connected! case STATUS_OK: setLabel(resources.resFTPConnected, ICON_OK); break; case STATUS_USER_PWD_WRONG: setLabel(resources.resFTPUserPwdWrong, ICON_ERROR); break; //problem resolving server name case STATUS_SERVER_NOT_FOUND: setLabel(resources.resFTPServerNotFound, ICON_ERROR); break; //rights problem case STATUS_NO_RIGHTS: setLabel(resources.resFTPRights, ICON_ERROR); break; //host unreachable (firewall?) case STATUS_HOST_UNREACHABLE: setLabel(resources.resFTPHostUnreachable, ICON_ERROR); break; case STATUS_CONNECTING: setLabel(resources.resConnecting, ICON_CONNECTING); break; default: setLabel(resources.resFTPUnknownError, ICON_ERROR); } } /** * changes the text of the status label and * (TODO) the status image. * @param label * @param color */ private void setLabel(String label, String image) { Helper.setUnoPropertyValue(getModel(lblStatus), "Label", label); Helper.setUnoPropertyValue(getModel(imgStatus), "ImageURL", imageUrl(image)); } private String imageUrl(String s) { String t = imagesDirectory + s; //System.out.println(t); return t; } /** * called when the user clicks * the choose-dir button. ("...") * Opens the pickFolder dialog. * checks if the returned folder is an ftp folder. * sets the textbox and the data to the new selected dir. */ public void chooseDirectory() { SystemDialog sd = SystemDialog.createOfficeFolderDialog(xMSF); String newUrl = sd.callFolderDialog(resources.resFTPDirectory, "", getFullUrl()); if (newUrl != null) { /* if the user chose a local directory, * sI do not accept it. */ if (newUrl.startsWith("ftp://")) { setDir(extractDir(newUrl)); } else { AbstractErrorHandler.showMessage(xMSF, xControl.getPeer(), resources.resIllegalFolder, ErrorHandler.ERROR_PROCESS_FATAL); } } } /** * practical to have such a method... * @param p the publisher obejct that contains the ftp connection info. * @return the full ftp url with username password and everything one needs. */ public static final String getFullURL(CGPublish p) { return "ftp://" + p.cp_Username + ":" + p.password + "@" + host(p.cp_URL); } }