opends/src/quicksetup/org/opends/quicksetup/Application.java
@@ -169,7 +169,7 @@ * Sets the application's installation. * @param installation describing the application's OpenDS installation */ protected void setInstallation(Installation installation) { public void setInstallation(Installation installation) { this.installation = installation; } opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java
@@ -102,11 +102,27 @@ ENABLING_WINDOWS_SERVICE, /** * User is waiting for current task to finish * so that the operation can be canceled. */ WAITING_TO_CANCEL, /** * Canceling install. */ CANCELING, /** * Installation finished successfully. */ FINISHED_SUCCESSFULLY, /** * User canceled installation. */ FINISHED_CANCELED, /** * Installation finished with an error. */ FINISHED_WITH_ERROR; @@ -116,6 +132,7 @@ */ public boolean isLast() { return this == FINISHED_SUCCESSFULLY || this == FINISHED_CANCELED || this == FINISHED_WITH_ERROR; } opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -100,9 +100,12 @@ public abstract class Installer extends GuiApplication { private TopologyCache lastLoadedCache; /* Indicates that we've detected that there is something installed */ /** Indicates that we've detected that there is something installed. */ boolean forceToDisplaySetup = false; /** When true indicates that the user has canceled this operation. */ protected boolean canceled = false; // Constants used to do checks private static final int MIN_DIRECTORY_MANAGER_PWD = 1; @@ -122,6 +125,10 @@ private static final int MAX_NUMBER_ENTRIES = 10000; /** Set of progress steps that have been completed. */ protected Set<InstallProgressStep> completedProgress = new HashSet<InstallProgressStep>(); private List<WizardStep> lstSteps = new ArrayList<WizardStep>(); private final HashSet<WizardStep> SUBSTEPS = new HashSet<WizardStep>(); @@ -137,12 +144,17 @@ private HashMap<WizardStep, WizardStep> hmPreviousSteps = new HashMap<WizardStep, WizardStep>(); private char[] selfSignedCertPw = null; /** * An static String that contains the class name of ConfigFileHandler. */ protected static final String CONFIG_CLASS_NAME = "org.opends.server.extensions.ConfigFileHandler"; /** Alias of a self-signed certificate. */ protected static final String SELF_SIGNED_CERT_ALIAS = "server-cert"; /** * Creates a default instance. */ @@ -175,7 +187,7 @@ * {@inheritDoc} */ public boolean isCancellable() { return false; // TODO: have installer delete installed files upon cancel return true; } /** @@ -338,6 +350,7 @@ public boolean isFinished() { return getCurrentProgressStep() == InstallProgressStep.FINISHED_SUCCESSFULLY || getCurrentProgressStep() == InstallProgressStep.FINISHED_CANCELED || getCurrentProgressStep() == InstallProgressStep.FINISHED_WITH_ERROR; } @@ -345,7 +358,9 @@ * {@inheritDoc} */ public void cancel() { // do nothing; not cancellable setStatus(InstallProgressStep.WAITING_TO_CANCEL); notifyListeners(null); this.canceled = true; } /** @@ -644,6 +659,26 @@ } /** * Uninstalls installed services. This is to be used when the user * has elected to cancel an installation. */ protected void uninstallServices() { if (completedProgress.contains( InstallProgressStep.ENABLING_WINDOWS_SERVICE)) { try { new InstallerHelper().disableWindowsService(); } catch (ApplicationException ae) { LOG.log(Level.INFO, "Error disabling Windows service", ae); } } if (completedProgress.contains( InstallProgressStep.CONFIGURING_REPLICATION)) { // TODO: undo replication } } /** * Creates a template file based in the contents of the UserData object. * This template file is used to generate automatically data. To generate * the template file the code will basically take into account the value of @@ -815,17 +850,17 @@ getSelfSignedKeystorePath(), CertificateManager.KEY_STORE_TYPE_JKS, pwd); certManager.generateSelfSignedCertificate("server-cert", certManager.generateSelfSignedCertificate(SELF_SIGNED_CERT_ALIAS, getSelfSignedCertificateSubjectDN(), getSelfSignedCertificateValidity()); exportCertificate(certManager, "server-cert", exportCertificate(certManager, SELF_SIGNED_CERT_ALIAS, getTemporaryCertificatePath()); trustManager = new CertificateManager( getTrustManagerPath(), CertificateManager.KEY_STORE_TYPE_JKS, pwd); trustManager.addCertificate("server-cert", trustManager.addCertificate(SELF_SIGNED_CERT_ALIAS, new File(getTemporaryCertificatePath())); Utils.createFile(getKeystorePinPath(), pwd); f = new File(getTemporaryCertificatePath()); @@ -1034,16 +1069,18 @@ if (result != 0) { String[] msgArgs = { Utils.stringArrayToString(args, " ") }; throw new ApplicationException( ApplicationException.Type.CONFIGURATION_ERROR, getMsg("error-import-automatically-generated", msgArgs), null); getMsg("error-import-ldif-tool-return-code", Integer.toString(result)), null); } } catch (Throwable t) { throw new ApplicationException( ApplicationException.Type.CONFIGURATION_ERROR, getThrowableMsg("error-import-automatically-generated", null, t), t); getThrowableMsg("error-import-automatically-generated", new String[] { Utils.listToString(argList, " "), t.getLocalizedMessage()}, t), t); } } @@ -1278,6 +1315,10 @@ getFormattedSummary(getMsg("summary-initialize-replicated-suffixes"))); hmSummary.put(InstallProgressStep.ENABLING_WINDOWS_SERVICE, getFormattedSummary(getMsg("summary-enabling-windows-service"))); hmSummary.put(InstallProgressStep.WAITING_TO_CANCEL, getFormattedSummary(getMsg("summary-waiting-to-cancel"))); hmSummary.put(InstallProgressStep.CANCELING, getFormattedSummary(getMsg("summary-canceling"))); Installation installation = getInstallation(); String cmd = Utils.getPath(installation.getStatusPanelCommandFile()); @@ -1286,11 +1327,32 @@ hmSummary.put(InstallProgressStep.FINISHED_SUCCESSFULLY, getFormattedSuccess( getMsg("summary-install-finished-successfully", args))); hmSummary.put(InstallProgressStep.FINISHED_CANCELED, getFormattedSuccess( getMsg("summary-install-finished-canceled", args))); hmSummary.put(InstallProgressStep.FINISHED_WITH_ERROR, getFormattedError(getMsg("summary-install-finished-with-error", args))); } /** * Checks the value of <code>canceled</code> field and throws an * ApplicationException if true. This indicates that the user has * canceled this operation and the process of aborting should begin * as soon as possible. * * @throws ApplicationException thrown if <code>canceled</code> */ protected void checkAbort() throws ApplicationException { if (canceled) { setStatus(InstallProgressStep.CANCELING); notifyListeners(null); throw new ApplicationException( ApplicationException.Type.CANCEL, getMsg("upgrade-canceled"), null); } } /** * Writes the java home that we are using for the setup in a file. * This way we can use this java home even if the user has not set JAVA_HOME * when running the different scripts. @@ -1365,6 +1427,9 @@ */ protected void setStatus(InstallProgressStep status) { if (status != null) { this.completedProgress.add(status); } this.status = status; } @@ -3339,7 +3404,7 @@ * @return the keystore path to be used for generating a self-signed * certificate. */ private String getSelfSignedKeystorePath() protected String getSelfSignedKeystorePath() { String parentFile = Utils.getPath(getInstallationPath(), Installation.CONFIG_PATH_RELATIVE); @@ -3405,13 +3470,26 @@ } /** * Returns the self-signed certificate password used for this session. This * method calls <code>createSelfSignedCertificatePwd()</code> the first time * this method is called. * @return the self-signed certificate password used for this session. */ protected String getSelfSignedCertificatePwd() { if (selfSignedCertPw == null) { selfSignedCertPw = createSelfSignedCertificatePwd(); } return new String(selfSignedCertPw); } /** * Returns a randomly generated password for the self-signed certificate * keystore. * @return a randomly generated password for the self-signed certificate * keystore. */ private String getSelfSignedCertificatePwd() { private char[] createSelfSignedCertificatePwd() { int pwdLength = 50; char[] pwd = new char[pwdLength]; Random random = new Random(); @@ -3420,9 +3498,7 @@ char nextChar = getRandomChar(random,type); pwd[pos] = nextChar; } String pwdString = new String(pwd); return pwdString; return pwd; } private void exportCertificate(CertificateManager certManager, String alias, opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
@@ -145,6 +145,19 @@ } } /** * This method disables this server as a Windows service. * @throws ApplicationException if something goes worong. */ public void disableWindowsService() throws ApplicationException { int code = ConfigureWindowsService.disableService(System.out, System.err); if (code == ConfigureWindowsService.SERVICE_DISABLE_ERROR) { throw new ApplicationException( ApplicationException.Type.WINDOWS_SERVICE_ERROR, getMsg("error-disabling-windows-service"), null); } } private String getThrowableMsg(String key, Throwable t) { opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
@@ -28,17 +28,23 @@ package org.opends.quicksetup.installer.offline; import java.io.PrintStream; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import java.security.KeyStoreException; import org.opends.quicksetup.ApplicationException; import org.opends.quicksetup.ProgressStep; import org.opends.quicksetup.Installation; import org.opends.quicksetup.SecurityOptions; import org.opends.quicksetup.installer.Installer; import org.opends.quicksetup.installer.InstallProgressStep; import org.opends.quicksetup.util.Utils; import org.opends.quicksetup.util.ServerController; import org.opends.quicksetup.util.FileManager; import org.opends.server.util.CertificateManager; /** * This is an implementation of the Installer class that is used to install @@ -83,11 +89,17 @@ System.setErr(err); System.setOut(out); checkAbort(); setStatus(InstallProgressStep.CONFIGURING_SERVER); configureServer(); checkAbort(); createData(); checkAbort(); writeJavaHome(); if (Utils.isWindows() && getUserData().getEnableWindowsService()) @@ -95,6 +107,7 @@ notifyListeners(getTaskSeparator()); setStatus(InstallProgressStep.ENABLING_WINDOWS_SERVICE); enableWindowsService(); checkAbort(); } if (mustStart()) @@ -102,6 +115,7 @@ notifyListeners(getTaskSeparator()); setStatus(InstallProgressStep.STARTING_SERVER); new ServerController(this).startServer(); checkAbort(); } if (mustConfigureReplication()) @@ -110,6 +124,7 @@ notifyListeners(getTaskSeparator()); configureReplication(); checkAbort(); } if (mustInitializeSuffixes()) @@ -117,6 +132,7 @@ notifyListeners(getTaskSeparator()); setStatus(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); initializeSuffixes(); checkAbort(); } if (mustCreateAds()) @@ -124,6 +140,7 @@ notifyListeners(getTaskSeparator()); setStatus(InstallProgressStep.CONFIGURING_ADS); updateADS(); checkAbort(); } if (mustStop()) @@ -133,17 +150,24 @@ new ServerController(this).stopServer(); } checkAbort(); setStatus(InstallProgressStep.FINISHED_SUCCESSFULLY); notifyListeners(null); } catch (ApplicationException ex) { notifyListeners(getLineBreak()); notifyListenersOfLog(); setStatus(InstallProgressStep.FINISHED_WITH_ERROR); String html = getFormattedError(ex, true); notifyListeners(html); LOG.log(Level.SEVERE, "Error installing.", ex); if (ApplicationException.Type.CANCEL.equals(ex.getType())) { uninstall(); setStatus(InstallProgressStep.FINISHED_CANCELED); notifyListeners(null); } else { notifyListeners(getLineBreak()); notifyListenersOfLog(); setStatus(InstallProgressStep.FINISHED_WITH_ERROR); String html = getFormattedError(ex, true); notifyListeners(html); LOG.log(Level.SEVERE, "Error installing.", ex); } } catch (Throwable t) { @@ -177,6 +201,92 @@ } /** * Called when the user elects to cancel this operation. */ protected void uninstall() { Installation installation = getInstallation(); FileManager fm = new FileManager(this); // Stop the server if necessary if (installation.getStatus().isServerRunning()) { try { new ServerController(installation).stopServer(true); } catch (ApplicationException e) { LOG.log(Level.INFO, "error stopping server", e); } } uninstallServices(); // Revert to the base configuration try { File newConfig = fm.copy(installation.getBaseConfigurationFile(), installation.getConfigurationDirectory(), /*overwrite=*/true); fm.rename(newConfig, installation.getCurrentConfigurationFile()); } catch (ApplicationException ae) { LOG.log(Level.INFO, "failed to restore base configuration", ae); } // Cleanup SSL if necessary SecurityOptions sec = getUserData().getSecurityOptions(); if (sec.getEnableSSL() || sec.getEnableStartTLS()) { if (SecurityOptions.CertificateType.SELF_SIGNED_CERTIFICATE.equals( sec.getCertificateType())) { CertificateManager cm = new CertificateManager( getSelfSignedKeystorePath(), CertificateManager.KEY_STORE_TYPE_JKS, getSelfSignedCertificatePwd()); try { cm.removeCertificate(SELF_SIGNED_CERT_ALIAS); } catch (KeyStoreException e) { LOG.log(Level.INFO, "Error deleting self signed certification", e); } } File keystore = new File(installation.getConfigurationDirectory(), "keystore"); if (keystore.exists()) { try { fm.delete(keystore); } catch (ApplicationException e) { LOG.log(Level.INFO, "Failed to delete keystore", e); } } File keystorePin = new File(installation.getConfigurationDirectory(), "keystore.pin"); if (keystorePin.exists()) { try { fm.delete(keystorePin); } catch (ApplicationException e) { LOG.log(Level.INFO, "Failed to delete keystore.pin", e); } } File truststore = new File(installation.getConfigurationDirectory(), "truststore"); if (truststore.exists()) { try { fm.delete(truststore); } catch (ApplicationException e) { LOG.log(Level.INFO, "Failed to delete truststore", e); } } } // Remove the databases try { fm.deleteChildren(installation.getDatabasesDirectory()); } catch (ApplicationException e) { LOG.log(Level.INFO, "Error deleting databases", e); } } /** * Initialize the different map used in this class. * */ @@ -277,6 +387,7 @@ } hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100); hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100); hmRatio.put(InstallProgressStep.FINISHED_CANCELED, 100); } /** opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
@@ -45,6 +45,7 @@ import org.opends.quicksetup.util.Utils; import org.opends.quicksetup.util.ZipExtractor; import org.opends.quicksetup.util.ServerController; import org.opends.quicksetup.util.FileManager; /** * This is an implementation of the Installer class that is used to install @@ -109,12 +110,16 @@ setStatus(InstallProgressStep.DOWNLOADING); checkAbort(); InputStream in = getZipInputStream(getRatio(InstallProgressStep.EXTRACTING)); setStatus(InstallProgressStep.EXTRACTING); notifyListeners(getTaskSeparator()); checkAbort(); createParentDirectoryIfRequired(); extractZipFiles(in, getRatio(InstallProgressStep.EXTRACTING), getRatio(InstallProgressStep.CONFIGURING_SERVER)); @@ -127,6 +132,9 @@ { LOG.log(Level.INFO, "Error closing zip input stream: "+t, t); } checkAbort(); setStatus(InstallProgressStep.CONFIGURING_SERVER); notifyListeners(getTaskSeparator()); @@ -135,15 +143,24 @@ writeJavaHome(); setInstallation(new Installation(getUserData().getServerLocation())); checkAbort(); setStatus(InstallProgressStep.CONFIGURING_SERVER); configureServer(); checkAbort(); createData(); checkAbort(); if (Utils.isWindows() && getUserData().getEnableWindowsService()) { notifyListeners(getTaskSeparator()); setStatus(InstallProgressStep.ENABLING_WINDOWS_SERVICE); enableWindowsService(); checkAbort(); } if (mustStart()) @@ -151,6 +168,8 @@ notifyListeners(getTaskSeparator()); setStatus(InstallProgressStep.STARTING_SERVER); new ServerController(this).startServer(); checkAbort(); } if (mustConfigureReplication()) @@ -159,6 +178,8 @@ notifyListeners(getTaskSeparator()); configureReplication(); checkAbort(); } if (mustInitializeSuffixes()) @@ -166,6 +187,8 @@ notifyListeners(getTaskSeparator()); setStatus(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); initializeSuffixes(); checkAbort(); } if (mustCreateAds()) @@ -173,6 +196,8 @@ notifyListeners(getTaskSeparator()); setStatus(InstallProgressStep.CONFIGURING_ADS); updateADS(); checkAbort(); } if (mustStop()) @@ -182,17 +207,24 @@ new ServerController(this).stopServer(); } checkAbort(); setStatus(InstallProgressStep.FINISHED_SUCCESSFULLY); notifyListeners(null); } catch (ApplicationException ex) { notifyListeners(getLineBreak()); notifyListenersOfLog(); setStatus(InstallProgressStep.FINISHED_WITH_ERROR); String html = getFormattedError(ex, true); notifyListeners(html); LOG.log(Level.SEVERE, "Error installing.", ex); if (ApplicationException.Type.CANCEL.equals(ex.getType())) { uninstall(); setStatus(InstallProgressStep.FINISHED_CANCELED); notifyListeners(null); } else { notifyListeners(getLineBreak()); notifyListenersOfLog(); setStatus(InstallProgressStep.FINISHED_WITH_ERROR); String html = getFormattedError(ex, true); notifyListeners(html); LOG.log(Level.SEVERE, "Error installing.", ex); } } catch (Throwable t) { @@ -338,6 +370,7 @@ } hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100); hmRatio.put(InstallProgressStep.FINISHED_CANCELED, 100); hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100); } @@ -462,6 +495,32 @@ } /** * Uninstall what has already been installed. */ private void uninstall() { Installation installation = getInstallation(); FileManager fm = new FileManager(this); // Stop the server if necessary if (installation.getStatus().isServerRunning()) { try { new ServerController(installation).stopServer(true); } catch (ApplicationException e) { LOG.log(Level.INFO, "error stopping server", e); } } uninstallServices(); try { fm.deleteRecursively(installation.getRootDirectory(), null, FileManager.DeletionPolicy.DELETE_ON_EXIT_IF_UNSUCCESSFUL); } catch (ApplicationException e) { LOG.log(Level.INFO, "error deleting files", e); } } /** * {@inheritDoc} */ protected String getInstallationPath() opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -918,6 +918,8 @@ summary-configuring-replication=Configuring Replication... summary-starting=Starting Directory Server... summary-enabling-windows-service=Enabling Windows Service... summary-waiting-to-cancel=Waiting to Cancel... summary-canceling=Canceling... summary-configuring-ads=Creating Registration Configuration... summary-initialize-replicated-suffixes=Initializing Contents of Replicated \ Suffixes... @@ -928,6 +930,9 @@ configuration.<br>To see basic server configuration status and to start/stop \ the server, click Launch Status Panel. Note that you can launch this tool \ later using {1}.<br><INPUT type="submit" value="Launch Status Panel"></INPUT> summary-install-finished-canceled=<b>OpenDS QuickSetup Canceled.</b> \ <br>The upgrade operation was canceled and any files installed to your system \ during this operation have been removed. summary-install-finished-with-error=An error occurred. Check 'Details' text \ area for more information.<br>To see basic server configuration status, click \ Launch Status Panel. Note that you can launch this tool \ @@ -1022,6 +1027,7 @@ progress-creating-base-entry=Creating Base Entry {0} progress-importing-ldif=Importing LDIF file {0}: progress-configuring-replication=Configuring Replication progress-cancel=Waiting to cancel operation. progress-configuring-replication-remote=Configuring Replication on {0} progress-import-automatically-generated=Importing Automatically-Generated Data \ @@ -1037,7 +1043,7 @@ progress-deleting-installation-files=Deleting Files under the Installation Path: progress-deleting-file=Deleting file {0} progress-deleting-directory=Deleting directory {0} progress-deleting-file-does-not-exist=Ignoring file {0} since it does not exist. progress-deleting-file-does-not-exist=Ignoring file {0} since it does not exist. progress-copying-file=Copying file {0} to {1} progress-server-already-stopped=The Directory Server is already stopped. @@ -1080,8 +1086,8 @@ {0}\\bat\\windows-service.bat -d command-line to disable the service manually. error-creating-base-entry=Error Creating Base Entry. error-importing-ldif=Error Importing LDIF File. error-import-automatically-generated=Error Importing Automatically- Generated \ Data when invoked with arguments: {0}. error-import-automatically-generated=Error Importing Automatically-Generated \ Data when invoked with arguments {0}: {1}. error-starting-server-with-no-connection-handlers=Error Starting Server with \ no connection handlers: {0}. error-starting-server=Error Starting Directory Server. @@ -1098,6 +1104,7 @@ exception-root-cause=Root Cause: error-deleting-file=Error deleting file {0}. Check that you have the rights \ to delete this file and that there is no other application using it. error-renaming-file=Error renaming file {0} to {1}. error-deleting-directory=Error deleting directory {0}. Check that you have \ the rights to delete this directory and that there is no other application \ using it. @@ -1155,6 +1162,7 @@ error-determining-server-state=Failed to determine the server's state. error-backup-db-tool-return-code=The backup tool returned error code {0}. error-ldif-diff-tool-return-code=The LDIF diff tool returned error code {0}. error-import-ldif-tool-return-code=The import LDIF tool returned error code {0}. error-apply-ldif-modify=Error processing modification operation of {0}: {1} error-apply-ldif-add=Error processing add operation of {0}: {1} error-apply-ldif-delete=Error processing delete operation of {0}: {1} opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
@@ -202,8 +202,8 @@ } progressBarLabel.setText(summaryText); int v = descriptor.getProgressBarRatio(); if (v > 0) Integer v = descriptor.getProgressBarRatio(); if (v != null && v > 0) { progressBar.setIndeterminate(false); progressBar.setValue(v); opends/src/quicksetup/org/opends/quicksetup/util/FileManager.java
@@ -112,6 +112,44 @@ } /** * Renames the source file to the target file. If the target file exists * it is first deleted. The rename and delete operation return values * are checked for success and if unsuccessful, this method throws an * exception. * * @param fileToRename The file to rename. * @param target The file to which <code>fileToRename</code> will be * moved. * @throws ApplicationException If a problem occurs while attempting to rename * the file. On the Windows platform, this typically * indicates that the file is in use by this or another * application. */ public void rename(File fileToRename, File target) throws ApplicationException { if (fileToRename != null && target != null) { synchronized (target) { if (target.exists()) { if (!target.delete()) { throw new ApplicationException( ApplicationException.Type.FILE_SYSTEM_ERROR, getMsg("error-deleting-file", Utils.getPath(target)), null); } } } if (!fileToRename.renameTo(target)) { throw new ApplicationException( ApplicationException.Type.FILE_SYSTEM_ERROR, getMsg("error-renaming-file", Utils.getPath(fileToRename), Utils.getPath(target)), null); } } } /** * Move a file. * @param object File to move * @param newParent File representing new parent directory @@ -167,6 +205,23 @@ } /** * Deletes the children of a directory. * * @param parentDir the directory whose children is deleted * @throws ApplicationException if there is a problem deleting children */ public void deleteChildren(File parentDir) throws ApplicationException { if (parentDir != null && parentDir.exists() && parentDir.isDirectory()) { File[] children = parentDir.listFiles(); if (children != null) { for (File child : children) { delete(child); } } } } /** * Deletes everything below the specified file. * * @param file the path to be deleted. @@ -198,12 +253,15 @@ * * @param objectFile the file to be copied. * @param destDir the directory to copy the file to * @return File representing the destination * @throws ApplicationException if something goes wrong. */ public void copy(File objectFile, File destDir) public File copy(File objectFile, File destDir) throws ApplicationException { new CopyOperation(objectFile, destDir, false).apply(); CopyOperation co = new CopyOperation(objectFile, destDir, false); co.apply(); return co.getDestination(); } /** @@ -211,13 +269,16 @@ * * @param objectFile the file to be copied. * @param destDir the directory to copy the file to * @return File representing the destination * @param overwrite overwrite destination files. * @throws ApplicationException if something goes wrong. */ public void copy(File objectFile, File destDir, boolean overwrite) public File copy(File objectFile, File destDir, boolean overwrite) throws ApplicationException { new CopyOperation(objectFile, destDir, overwrite).apply(); CopyOperation co = new CopyOperation(objectFile, destDir, overwrite); co.apply(); return co.getDestination(); } /** @@ -372,6 +433,15 @@ } /** * Returns the destination file that is the result of copying * <code>objectFile</code> to <code>destDir</code>. * @return */ public File getDestination() { return this.destination; } /** * {@inheritDoc} */ public void apply() throws ApplicationException {