Search in sources :

Example 1 with FTPClient

use of com.enterprisedt.net.ftp.FTPClient in project pentaho-kettle by pentaho.

the class JobEntryFTPDeleteDialog method connectToFTP.

private boolean connectToFTP() {
    boolean retval = false;
    String realServername = null;
    try {
        if (ftpclient == null || !ftpclient.connected()) {
            // Create ftp client to host:port ...
            ftpclient = new FTPClient();
            realServername = jobMeta.environmentSubstitute(wServerName.getText());
            int realPort = Const.toInt(jobMeta.environmentSubstitute(wPort.getText()), 21);
            ftpclient.setRemoteAddr(InetAddress.getByName(realServername));
            ftpclient.setRemotePort(realPort);
            if (!Utils.isEmpty(wProxyHost.getText())) {
                String realProxy_host = jobMeta.environmentSubstitute(wProxyHost.getText());
                ftpclient.setRemoteAddr(InetAddress.getByName(realProxy_host));
                int port = Const.toInt(jobMeta.environmentSubstitute(wProxyPort.getText()), 21);
                if (port != 0) {
                    ftpclient.setRemotePort(port);
                }
            }
            // login to ftp host ...
            ftpclient.connect();
            String realUsername = jobMeta.environmentSubstitute(wUserName.getText()) + (!Utils.isEmpty(wProxyHost.getText()) ? "@" + realServername : "") + (!Utils.isEmpty(wProxyUsername.getText()) ? " " + jobMeta.environmentSubstitute(wProxyUsername.getText()) : "");
            String realPassword = Utils.resolvePassword(jobMeta, wPassword.getText()) + (!Utils.isEmpty(wProxyPassword.getText()) ? " " + Utils.resolvePassword(jobMeta, wProxyPassword.getText()) : "");
            // login now ...
            ftpclient.login(realUsername, realPassword);
            pwdFolder = ftpclient.pwd();
        }
        retval = true;
    } catch (Exception e) {
        if (ftpclient != null) {
            try {
                ftpclient.quit();
            } catch (Exception ignored) {
            // We've tried quitting the FTP Client exception
            // nothing else to be done if the FTP Client was already disconnected
            }
            ftpclient = null;
        }
        MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
        mb.setMessage(BaseMessages.getString(PKG, "JobFTPDelete.ErrorConnect.NOK", realServername, e.getMessage()) + Const.CR);
        mb.setText(BaseMessages.getString(PKG, "JobFTPDelete.ErrorConnect.Title.Bad"));
        mb.open();
    }
    return retval;
}
Also used : FTPClient(com.enterprisedt.net.ftp.FTPClient) SFTPClient(org.pentaho.di.job.entries.sftp.SFTPClient) MessageBox(org.eclipse.swt.widgets.MessageBox)

Example 2 with FTPClient

use of com.enterprisedt.net.ftp.FTPClient in project pentaho-kettle by pentaho.

the class JobEntryFTPPUTDialog method connectToFTP.

private boolean connectToFTP(boolean checkfolder, String remoteFoldername) {
    boolean retval = false;
    String realServername = null;
    try {
        if (ftpclient == null || !ftpclient.connected()) {
            // Create ftp client to host:port ...
            ftpclient = new FTPClient();
            realServername = jobMeta.environmentSubstitute(wServerName.getText());
            int realPort = Const.toInt(jobMeta.environmentSubstitute(wServerPort.getText()), 21);
            ftpclient.setRemoteAddr(InetAddress.getByName(realServername));
            ftpclient.setRemotePort(realPort);
            if (!Utils.isEmpty(wProxyHost.getText())) {
                String realProxy_host = jobMeta.environmentSubstitute(wProxyHost.getText());
                ftpclient.setRemoteAddr(InetAddress.getByName(realProxy_host));
                int port = Const.toInt(jobMeta.environmentSubstitute(wProxyPort.getText()), 21);
                if (port != 0) {
                    ftpclient.setRemotePort(port);
                }
            }
            // login to ftp host ...
            ftpclient.connect();
            String realUsername = jobMeta.environmentSubstitute(wUserName.getText()) + (!Utils.isEmpty(wProxyHost.getText()) ? "@" + realServername : "") + (!Utils.isEmpty(wProxyUsername.getText()) ? " " + jobMeta.environmentSubstitute(wProxyUsername.getText()) : "");
            String realPassword = Utils.resolvePassword(jobMeta, wPassword.getText()) + (!Utils.isEmpty(wProxyPassword.getText()) ? " " + Utils.resolvePassword(jobMeta, wProxyPassword.getText()) : "");
            // login now ...
            ftpclient.login(realUsername, realPassword);
            pwdFolder = ftpclient.pwd();
        }
        if (checkfolder) {
            if (pwdFolder != null) {
                ftpclient.chdir(pwdFolder);
            }
            // move to spool dir ...
            if (!Utils.isEmpty(remoteFoldername)) {
                String realFtpDirectory = jobMeta.environmentSubstitute(remoteFoldername);
                ftpclient.chdir(realFtpDirectory);
            }
        }
        retval = true;
    } catch (Exception e) {
        if (ftpclient != null) {
            try {
                ftpclient.quit();
            } catch (Exception ignored) {
            // We've tried quitting the FTP Client exception
            // nothing else can be done if the FTP Client was already disconnected
            }
            ftpclient = null;
        }
        MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
        mb.setMessage(BaseMessages.getString(PKG, "JobFTPPUT.ErrorConnect.NOK", realServername, e.getMessage()) + Const.CR);
        mb.setText(BaseMessages.getString(PKG, "JobFTPPUT.ErrorConnect.Title.Bad"));
        mb.open();
    }
    return retval;
}
Also used : FTPClient(com.enterprisedt.net.ftp.FTPClient) MessageBox(org.eclipse.swt.widgets.MessageBox)

Example 3 with FTPClient

use of com.enterprisedt.net.ftp.FTPClient in project pentaho-kettle by pentaho.

the class JobEntryFTP method execute.

public Result execute(Result previousResult, int nr) {
    log.logBasic(BaseMessages.getString(PKG, "JobEntryFTP.Started", serverName));
    Result result = previousResult;
    result.setNrErrors(1);
    result.setResult(false);
    NrErrors = 0;
    NrfilesRetrieved = 0;
    successConditionBroken = false;
    boolean exitjobentry = false;
    limitFiles = Const.toInt(environmentSubstitute(getLimit()), 10);
    // Here let's put some controls before stating the job
    if (movefiles) {
        if (Utils.isEmpty(movetodirectory)) {
            logError(BaseMessages.getString(PKG, "JobEntryFTP.MoveToFolderEmpty"));
            return result;
        }
    }
    if (isDetailed()) {
        logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.Start"));
    }
    FTPClient ftpclient = null;
    String realMoveToFolder = null;
    try {
        // Create ftp client to host:port ...
        ftpclient = initFTPClient();
        String realServername = environmentSubstitute(serverName);
        String realServerPort = environmentSubstitute(port);
        ftpclient.setRemoteAddr(getInetAddress(realServername));
        if (!Utils.isEmpty(realServerPort)) {
            ftpclient.setRemotePort(Const.toInt(realServerPort, 21));
        }
        if (!Utils.isEmpty(proxyHost)) {
            String realProxy_host = environmentSubstitute(proxyHost);
            ftpclient.setRemoteAddr(InetAddress.getByName(realProxy_host));
            if (isDetailed()) {
                logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.OpenedProxyConnectionOn", realProxy_host));
            }
            // FIXME: Proper default port for proxy
            int port = Const.toInt(environmentSubstitute(proxyPort), 21);
            if (port != 0) {
                ftpclient.setRemotePort(port);
            }
        } else {
            ftpclient.setRemoteAddr(getInetAddress(realServername));
            if (isDetailed()) {
                logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.OpenedConnectionTo", realServername));
            }
        }
        // set activeConnection connectmode ...
        if (activeConnection) {
            ftpclient.setConnectMode(FTPConnectMode.ACTIVE);
            if (isDetailed()) {
                logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.SetActive"));
            }
        } else {
            ftpclient.setConnectMode(FTPConnectMode.PASV);
            if (isDetailed()) {
                logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.SetPassive"));
            }
        }
        // Set the timeout
        ftpclient.setTimeout(timeout);
        if (isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.SetTimeout", String.valueOf(timeout)));
        }
        ftpclient.setControlEncoding(controlEncoding);
        if (isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.SetEncoding", controlEncoding));
        }
        // If socks proxy server was provided
        if (!Utils.isEmpty(socksProxyHost)) {
            if (!Utils.isEmpty(socksProxyPort)) {
                FTPClient.initSOCKS(environmentSubstitute(socksProxyPort), environmentSubstitute(socksProxyHost));
            } else {
                throw new FTPException(BaseMessages.getString(PKG, "JobEntryFTP.SocksProxy.PortMissingException", environmentSubstitute(socksProxyHost), getName()));
            }
            // then if we have authentication information
            if (!Utils.isEmpty(socksProxyUsername) && !Utils.isEmpty(socksProxyPassword)) {
                FTPClient.initSOCKSAuthentication(environmentSubstitute(socksProxyUsername), Utils.resolvePassword(this, socksProxyPassword));
            } else if (!Utils.isEmpty(socksProxyUsername) && Utils.isEmpty(socksProxyPassword) || Utils.isEmpty(socksProxyUsername) && !Utils.isEmpty(socksProxyPassword)) {
                // we have a username without a password or vica versa
                throw new FTPException(BaseMessages.getString(PKG, "JobEntryFTP.SocksProxy.IncompleteCredentials", environmentSubstitute(socksProxyHost), getName()));
            }
        }
        // login to ftp host ...
        ftpclient.connect();
        String realUsername = environmentSubstitute(userName) + (!Utils.isEmpty(proxyHost) ? "@" + realServername : "") + (!Utils.isEmpty(proxyUsername) ? " " + environmentSubstitute(proxyUsername) : "");
        String realPassword = Utils.resolvePassword(this, password) + (!Utils.isEmpty(proxyPassword) ? " " + Utils.resolvePassword(this, proxyPassword) : "");
        ftpclient.login(realUsername, realPassword);
        // Remove password from logging, you don't know where it ends up.
        if (isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.LoggedIn", realUsername));
        }
        // Fix for PDI-2534 - add auxilliary FTP File List parsers to the ftpclient object.
        this.hookInOtherParsers(ftpclient);
        // move to spool dir ...
        if (!Utils.isEmpty(ftpDirectory)) {
            String realFtpDirectory = environmentSubstitute(ftpDirectory);
            realFtpDirectory = normalizePath(realFtpDirectory);
            ftpclient.chdir(realFtpDirectory);
            if (isDetailed()) {
                logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.ChangedDir", realFtpDirectory));
            }
        }
        // Create move to folder if necessary
        if (movefiles && !Utils.isEmpty(movetodirectory)) {
            realMoveToFolder = environmentSubstitute(movetodirectory);
            realMoveToFolder = normalizePath(realMoveToFolder);
            // Folder exists?
            boolean folderExist = true;
            if (isDetailed()) {
                logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.CheckMoveToFolder", realMoveToFolder));
            }
            String originalLocation = ftpclient.pwd();
            try {
                // does not work for folders, see PDI-2567: folderExist=ftpclient.exists(realMoveToFolder);
                // try switching to the 'move to' folder.
                ftpclient.chdir(realMoveToFolder);
                // Switch back to the previous location.
                if (isDetailed()) {
                    logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.CheckMoveToFolderSwitchBack", originalLocation));
                }
                ftpclient.chdir(originalLocation);
            } catch (Exception e) {
                folderExist = false;
            // Assume folder does not exist !!
            }
            if (!folderExist) {
                if (createmovefolder) {
                    ftpclient.mkdir(realMoveToFolder);
                    if (isDetailed()) {
                        logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.MoveToFolderCreated", realMoveToFolder));
                    }
                } else {
                    logError(BaseMessages.getString(PKG, "JobEntryFTP.MoveToFolderNotExist"));
                    exitjobentry = true;
                    NrErrors++;
                }
            }
        }
        if (!exitjobentry) {
            // Get all the files in the current directory...
            FTPFile[] ftpFiles = ftpclient.dirDetails(null);
            if (isDetailed()) {
                logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.FoundNFiles", String.valueOf(ftpFiles.length)));
            }
            // set transfertype ...
            if (binaryMode) {
                ftpclient.setType(FTPTransferType.BINARY);
                if (isDetailed()) {
                    logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.SetBinary"));
                }
            } else {
                ftpclient.setType(FTPTransferType.ASCII);
                if (isDetailed()) {
                    logDetailed(BaseMessages.getString(PKG, "JobEntryFTP.SetAscii"));
                }
            }
            if (ftpFiles.length == 1) {
                String translatedWildcard = environmentSubstitute(wildcard);
                if (!Utils.isEmpty(translatedWildcard)) {
                    if (ftpFiles[0].getName().startsWith(translatedWildcard)) {
                        throw new FTPException(ftpFiles[0].getName());
                    }
                }
            }
            Pattern pattern = null;
            if (!Utils.isEmpty(wildcard)) {
                String realWildcard = environmentSubstitute(wildcard);
                pattern = Pattern.compile(realWildcard);
            }
            if (!getSuccessCondition().equals(SUCCESS_IF_NO_ERRORS)) {
                limitFiles = Const.toInt(environmentSubstitute(getLimit()), 10);
            }
            // Get the files in the list...
            for (FTPFile ftpFile : ftpFiles) {
                if (parentJob.isStopped()) {
                    exitjobentry = true;
                    throw new Exception(BaseMessages.getString(PKG, "JobEntryFTP.JobStopped"));
                }
                if (successConditionBroken) {
                    throw new Exception(BaseMessages.getString(PKG, "JobEntryFTP.SuccesConditionBroken", "" + NrErrors));
                }
                boolean getIt = true;
                String filename = ftpFile.getName();
                if (isDebug()) {
                    logDebug(BaseMessages.getString(PKG, "JobEntryFTP.AnalysingFile", filename));
                }
                // We get only files
                if (ftpFile.isDir()) {
                    // not a file..so let's skip it!
                    getIt = false;
                    if (isDebug()) {
                        logDebug(BaseMessages.getString(PKG, "JobEntryFTP.SkippingNotAFile", filename));
                    }
                }
                if (getIt) {
                    try {
                        // See if the file matches the regular expression!
                        if (pattern != null) {
                            Matcher matcher = pattern.matcher(filename);
                            getIt = matcher.matches();
                        }
                        if (getIt) {
                            downloadFile(ftpclient, filename, realMoveToFolder, parentJob, result);
                        }
                    } catch (Exception e) {
                        // Update errors number
                        updateErrors();
                        logError(BaseMessages.getString(PKG, "JobFTP.UnexpectedError", e.toString()));
                    }
                }
            }
        // end for
        }
    } catch (Exception e) {
        if (!successConditionBroken && !exitjobentry) {
            updateErrors();
        }
        logError(BaseMessages.getString(PKG, "JobEntryFTP.ErrorGetting", e.getMessage()));
    } finally {
        if (ftpclient != null) {
            try {
                ftpclient.quit();
            } catch (Exception e) {
                logError(BaseMessages.getString(PKG, "JobEntryFTP.ErrorQuitting", e.getMessage()));
            }
        }
        FTPClient.clearSOCKS();
    }
    result.setNrErrors(NrErrors);
    result.setNrFilesRetrieved(NrfilesRetrieved);
    if (getSuccessStatus()) {
        result.setResult(true);
    }
    if (exitjobentry) {
        result.setResult(false);
    }
    displayResults();
    return result;
}
Also used : Pattern(java.util.regex.Pattern) Matcher(java.util.regex.Matcher) FTPFile(com.enterprisedt.net.ftp.FTPFile) FTPClient(com.enterprisedt.net.ftp.FTPClient) FTPException(com.enterprisedt.net.ftp.FTPException) FTPException(com.enterprisedt.net.ftp.FTPException) KettleException(org.pentaho.di.core.exception.KettleException) KettleDatabaseException(org.pentaho.di.core.exception.KettleDatabaseException) KettleXMLException(org.pentaho.di.core.exception.KettleXMLException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) Result(org.pentaho.di.core.Result)

Example 4 with FTPClient

use of com.enterprisedt.net.ftp.FTPClient in project pentaho-kettle by pentaho.

the class JobEntryFTPDelete method FTPConnect.

private void FTPConnect(String realServername, String realusername, String realpassword, int realport, String realFtpDirectory, String realProxyhost, String realproxyusername, String realproxypassword, int realproxyport, int realtimeout) throws Exception {
    // Create ftp client to host:port ...
    ftpclient = new FTPClient();
    ftpclient.setRemoteAddr(InetAddress.getByName(realServername));
    if (realport != 0) {
        ftpclient.setRemotePort(realport);
    }
    if (!Utils.isEmpty(realProxyhost)) {
        ftpclient.setRemoteAddr(InetAddress.getByName(realProxyhost));
        if (isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTPDelete.OpenedProxyConnectionOn", realProxyhost));
        }
        // FIXME: Proper default port for proxy
        if (realproxyport != 0) {
            ftpclient.setRemotePort(realproxyport);
        }
    } else {
        ftpclient.setRemoteAddr(InetAddress.getByName(realServername));
        if (isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTPDelete.OpenedConnectionTo", realServername));
        }
    }
    // set activeConnection connectmode ...
    if (activeConnection) {
        ftpclient.setConnectMode(FTPConnectMode.ACTIVE);
        if (isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTPDelete.SetActive"));
        }
    } else {
        ftpclient.setConnectMode(FTPConnectMode.PASV);
        if (isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTPDelete.SetPassive"));
        }
    }
    // Set the timeout
    ftpclient.setTimeout(realtimeout);
    if (isDetailed()) {
        logDetailed(BaseMessages.getString(PKG, "JobEntryFTPDelete.SetTimeout", String.valueOf(realtimeout)));
    }
    // login to ftp host ...
    ftpclient.connect();
    String realUsername = realusername + (!Utils.isEmpty(realProxyhost) ? "@" + realServername : "") + (!Utils.isEmpty(realproxyusername) ? " " + realproxyusername : "");
    String realPassword = realpassword + (!Utils.isEmpty(realproxypassword) ? " " + realproxypassword : "");
    ftpclient.login(realUsername, realPassword);
    // Remove password from logging, you don't know where it ends up.
    if (isDetailed()) {
        logDetailed(BaseMessages.getString(PKG, "JobEntryFTPDelete.LoggedIn", realUsername));
    }
    // move to spool dir ...
    if (!Utils.isEmpty(realFtpDirectory)) {
        ftpclient.chdir(realFtpDirectory);
        if (isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTPDelete.ChangedDir", realFtpDirectory));
        }
    }
}
Also used : FTPClient(com.enterprisedt.net.ftp.FTPClient) SFTPClient(org.pentaho.di.job.entries.sftp.SFTPClient)

Example 5 with FTPClient

use of com.enterprisedt.net.ftp.FTPClient in project pentaho-kettle by pentaho.

the class JobEntryFTPPUT method createAndSetUpFtpClient.

// package-local visibility for testing purposes
FTPClient createAndSetUpFtpClient() throws IOException, FTPException {
    String realServerName = environmentSubstitute(serverName);
    String realServerPort = environmentSubstitute(serverPort);
    FTPClient ftpClient = createFtpClient();
    ftpClient.setRemoteAddr(InetAddress.getByName(realServerName));
    if (!Utils.isEmpty(realServerPort)) {
        ftpClient.setRemotePort(Const.toInt(realServerPort, FTP_DEFAULT_PORT));
    }
    if (!Utils.isEmpty(proxyHost)) {
        String realProxyHost = environmentSubstitute(proxyHost);
        ftpClient.setRemoteAddr(InetAddress.getByName(realProxyHost));
        if (log.isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTPPUT.OpenedProxyConnectionOn", realProxyHost));
        }
        // FIXME: Proper default port for proxy
        int port = Const.toInt(environmentSubstitute(proxyPort), FTP_DEFAULT_PORT);
        if (port != 0) {
            ftpClient.setRemotePort(port);
        }
    } else {
        if (log.isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobEntryFTPPUT.OpenConnection", realServerName));
        }
    }
    // set activeConnection connectmode ...
    if (activeConnection) {
        ftpClient.setConnectMode(FTPConnectMode.ACTIVE);
        if (log.isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobFTPPUT.Log.SetActiveConnection"));
        }
    } else {
        ftpClient.setConnectMode(FTPConnectMode.PASV);
        if (log.isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobFTPPUT.Log.SetPassiveConnection"));
        }
    }
    // Set the timeout
    if (timeout > 0) {
        ftpClient.setTimeout(timeout);
        if (log.isDetailed()) {
            logDetailed(BaseMessages.getString(PKG, "JobFTPPUT.Log.SetTimeout", "" + timeout));
        }
    }
    ftpClient.setControlEncoding(controlEncoding);
    if (log.isDetailed()) {
        logDetailed(BaseMessages.getString(PKG, "JobFTPPUT.Log.SetEncoding", controlEncoding));
    }
    // If socks proxy server was provided
    if (!Utils.isEmpty(socksProxyHost)) {
        // if a port was provided
        if (!Utils.isEmpty(socksProxyPort)) {
            FTPClient.initSOCKS(environmentSubstitute(socksProxyPort), environmentSubstitute(socksProxyHost));
        } else {
            // looks like we have a host and no port
            throw new FTPException(BaseMessages.getString(PKG, "JobFTPPUT.SocksProxy.PortMissingException", environmentSubstitute(socksProxyHost)));
        }
        // now if we have authentication information
        if (!Utils.isEmpty(socksProxyUsername) && Utils.isEmpty(socksProxyPassword) || Utils.isEmpty(socksProxyUsername) && !Utils.isEmpty(socksProxyPassword)) {
            // we have a username without a password or vica versa
            throw new FTPException(BaseMessages.getString(PKG, "JobFTPPUT.SocksProxy.IncompleteCredentials", environmentSubstitute(socksProxyHost), getName()));
        }
    }
    return ftpClient;
}
Also used : FTPClient(com.enterprisedt.net.ftp.FTPClient) FTPException(com.enterprisedt.net.ftp.FTPException)

Aggregations

FTPClient (com.enterprisedt.net.ftp.FTPClient)7 FTPException (com.enterprisedt.net.ftp.FTPException)3 MessageBox (org.eclipse.swt.widgets.MessageBox)3 IOException (java.io.IOException)2 Matcher (java.util.regex.Matcher)2 Pattern (java.util.regex.Pattern)2 Result (org.pentaho.di.core.Result)2 KettleDatabaseException (org.pentaho.di.core.exception.KettleDatabaseException)2 KettleException (org.pentaho.di.core.exception.KettleException)2 KettleXMLException (org.pentaho.di.core.exception.KettleXMLException)2 SFTPClient (org.pentaho.di.job.entries.sftp.SFTPClient)2 FTPFile (com.enterprisedt.net.ftp.FTPFile)1 File (java.io.File)1 URI (java.net.URI)1 UnknownHostException (java.net.UnknownHostException)1