/** * Download the remote content and store it the temp directory. * * @param URLs * @param progressMonitor */ public IStatus download(String[] URLs, IProgressMonitor progressMonitor) { if (URLs.length == 0) { String err = Messages.InstallerConfigurationProcessor_missingDownloadTargets; applyErrorAttributes(err); IdeLog.logError( PortalUIPlugin.getDefault(), "We expected an array of URLs, but got an empty array.", new Exception(err)); // $NON-NLS-1$ return new Status(IStatus.ERROR, PortalUIPlugin.PLUGIN_ID, err); } downloadedPaths = null; DownloadManager downloadManager = new DownloadManager(); List<URI> urlsList = new ArrayList<URI>(URLs.length); for (int i = 0; i < URLs.length; i++) { try { urlsList.add(new URI(urls[i])); } catch (URISyntaxException mue) { IdeLog.logError(PortalUIPlugin.getDefault(), mue); } } try { downloadManager.addURIs(urlsList); IStatus status = downloadManager.start(progressMonitor); if (status.isOK()) { downloadedPaths = downloadManager.getContentsLocations(); } return status; } catch (Exception e) { IdeLog.logError(PortalUIPlugin.getDefault(), e); } return Status.CANCEL_STATUS; }
/** * Cache the installed application location and version in the preferences. * * @param installDir - The directory the application was installed to. * @param versionedFileLocation - Can be the URL that we grabbed the installer from, or any other * string that contains a version information in a form of x.y.z. * @param appName - The application name (e.g. xampp) */ @SuppressWarnings("unchecked") public void cacheVersion(String installDir, String versionedFileLocation, String appName) { IPreferenceStore preferenceStore = PortalUIPlugin.getDefault().getPreferenceStore(); String versions = preferenceStore.getString(IPortalPreferences.CACHED_VERSIONS_PROPERTY_NAME); Map<String, Map<String, String>> versionsMap = null; if (versions == null || versions.equals(StringUtil.EMPTY)) { versionsMap = new HashMap<String, Map<String, String>>(); } else { versionsMap = (Map<String, Map<String, String>>) JSON.parse(versions); } Map<String, String> appVersionMap = new HashMap<String, String>(); Version version = VersionUtil.parseVersion(versionedFileLocation); if (!VersionUtil.isEmpty(version)) { appVersionMap.put(IPortalPreferences.CACHED_VERSION_PROPERTY, version.toString()); appVersionMap.put(IPortalPreferences.CACHED_LOCATION_PROPERTY, installDir); versionsMap.put(appName.toLowerCase(), appVersionMap); preferenceStore.setValue( IPortalPreferences.CACHED_VERSIONS_PROPERTY_NAME, JSON.toString(versionsMap)); } else { IdeLog.logError( PortalUIPlugin.getDefault(), MessageFormat.format( "Could not cache the location and version for {0}. Install dir: {1}, versionedFileLocation: {2}", //$NON-NLS-1$ appName, installDir, versionedFileLocation), new Exception()); } }
/** * Opens an internal browser with the URL that is given in the attributes. * * @param attributes We expect for an array that contains a single string URL. * @return {@link IBrowserNotificationConstants#JSON_OK} or a {@link * IBrowserNotificationConstants#JSON_ERROR} */ @ControllerAction public Object internalOpen(Object attributes) { URL url = getURL(attributes); if (url == null) { return IBrowserNotificationConstants.JSON_ERROR; } try { IWebBrowser browser = PortalUIPlugin.getDefault() .getWorkbench() .getBrowserSupport() .createBrowser( IWorkbenchBrowserSupport.AS_EDITOR | IWorkbenchBrowserSupport.LOCATION_BAR | IWorkbenchBrowserSupport.STATUS | IWorkbenchBrowserSupport.NAVIGATION_BAR, url.toString(), null, null); browser.openURL(url); } catch (PartInitException e) { PortalUIPlugin.logError(e); return IBrowserNotificationConstants.JSON_ERROR; } return IBrowserNotificationConstants.JSON_OK; }
/** * Returns the URL from the attributes. Null, if an error occured. * * @param attributes * @return A URL, or null if an error occurs. */ private URL getURL(Object attributes) { if (attributes instanceof Object[]) { Object[] arr = (Object[]) attributes; if (arr.length == 1) { try { return new URL(arr[0].toString()); } catch (MalformedURLException e) { PortalUIPlugin.logError("Invalid URL: " + arr[0], e); // $NON-NLS-1$ } } else { PortalUIPlugin.logError( new Exception( "Wrong argument count passed to BrowserActionController::getURL. Expected 1 and got " + arr.length)); //$NON-NLS-1$ } } else { PortalUIPlugin.logError( new Exception( "Wrong argument type passed to BrowserActionController::getURL. Expected Object[] and got " //$NON-NLS-1$ + ((attributes == null) ? "null" : attributes.getClass().getName()))); // $NON-NLS-1$s } return null; }
/** * Opens a Studio view.<br> * * @param attributes We expect for an array that contains a single string Id for the view. */ @ControllerAction public Object openView(Object attributes) { String viewId = getViewId(attributes); if (viewId == null) { return IBrowserNotificationConstants.JSON_ERROR; } try { PortalUIPlugin.getDefault() .getWorkbench() .getActiveWorkbenchWindow() .getActivePage() .showView(viewId); } catch (Exception e) { PortalUIPlugin.logError(e); return IBrowserNotificationConstants.JSON_ERROR; } return IBrowserNotificationConstants.JSON_OK; }
/** * Returns the view-Id from the attributes. Null, if an error occurred. * * @param attributes * @return A view Id, or null if an error occurs. */ private String getViewId(Object attributes) { if (attributes instanceof Object[]) { Object[] arr = (Object[]) attributes; if (arr.length == 1 && arr[0] != null) { return arr[0].toString(); } else { PortalUIPlugin.logError( new Exception( "Wrong argument count passed to ViewActionController::openView. Expected 1 and got " + arr.length)); //$NON-NLS-1$ } } else { PortalUIPlugin.logError( new Exception( "Wrong argument type passed to ViewActionController::openView. Expected Object[] and got " //$NON-NLS-1$ + ((attributes == null) ? "null" : attributes.getClass().getName()))); // $NON-NLS-1$s } return null; }
/** * Finalize the installation by placing a .aptana file in the installed directory, specifying some * properties. * * @param installDir */ protected void finalizeInstallation(String installDir) { super.finalizeInstallation(installDir); File propertiesFile = new File(installDir, APTANA_PROPERTIES_FILE_NAME); Properties properties = new Properties(); properties.put("PYTHON_install", urls[0]); // $NON-NLS-1$ FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(propertiesFile); properties.store( fileOutputStream, NLS.bind(Messages.InstallProcessor_aptanaInstallationComment, PYTHON)); } catch (IOException e) { IdeLog.logError(PortalUIPlugin.getDefault(), e); } finally { if (fileOutputStream != null) { try { fileOutputStream.flush(); fileOutputStream.close(); } catch (IOException e) { } } } }
/** * Extract the given zip file into the target folder on a Windows machine. * * @param sfxZip Self extracting 7zip file. * @param targetFolder * @return The status of that extraction result. */ public static IStatus extractWin(IPath sfxZip, IPath targetFolder) { IStatus errorStatus = new Status( IStatus.ERROR, PortalUIPlugin.PLUGIN_ID, Messages.InstallerConfigurationProcessor_unableToExtractZip); if (!Platform.OS_WIN32.equals(Platform.getOS())) { IdeLog.logError( PortalUIPlugin.getDefault(), "Unable to extract the Zip file. A Windows OS extractor was called for a non-Windows platform.", new Exception()); //$NON-NLS-1$ return errorStatus; } if (sfxZip == null || targetFolder == null) { IdeLog.logError( PortalUIPlugin.getDefault(), "Undefined zip file or target folder", new Exception()); //$NON-NLS-1$ return errorStatus; } File destinationFolder = targetFolder.toFile(); if (!destinationFolder.exists() && !destinationFolder.mkdirs()) { IdeLog.logError( PortalUIPlugin.getDefault(), "Failed to create destination directory " + destinationFolder, new Exception()); //$NON-NLS-1$ return errorStatus; } // TODO Use ProcessUtil! ProcessBuilder processBuilder = new ProcessBuilder( sfxZip.toOSString(), "-o" + targetFolder.toOSString(), // $NON-NLS-1$ "-y", //$NON-NLS-1$ sfxZip.toOSString()); processBuilder.directory(destinationFolder); processBuilder.redirectErrorStream(true); String output = null; try { Process process = processBuilder.start(); InputStreamGobbler errorGobbler = new InputStreamGobbler(process.getErrorStream(), "\n", null); // $NON-NLS-1$ InputStreamGobbler outputGobbler = new InputStreamGobbler(process.getInputStream(), "\n", null); // $NON-NLS-1$ outputGobbler.start(); errorGobbler.start(); process.waitFor(); outputGobbler.interrupt(); errorGobbler.interrupt(); outputGobbler.join(); errorGobbler.join(); output = outputGobbler.getResult(); String errors = errorGobbler.getResult(); int exitVal = process.exitValue(); if (exitVal == 0) { return Status.OK_STATUS; } IdeLog.logError( PortalUIPlugin.getDefault(), "Zip extraction failed. The process returned " + exitVal, new Exception("Process output:\n" + errors)); // $NON-NLS-1$ //$NON-NLS-2$ return errorStatus; } catch (Exception e) { IdeLog.logError(PortalUIPlugin.getDefault(), e); return errorStatus; } finally { if (output != null) { IdeLog.logInfo(PortalUIPlugin.getDefault(), output); } } }
/** * Install Python on the machine.<br> * The configuration will grab the installer from the given attributes.<br> * We expect an array of attributes with the same structure described at {@link * #loadAttributes(Object)}. * * @param attributes First - A string array of size 1, which contains the URL for the Python * installer (.exe). Second - (optional) map of additional attributes. * @see * com.aptana.configurations.processor.AbstractConfigurationProcessor#configure(org.eclipse.core.runtime.IProgressMonitor, * java.lang.Object) * @see #loadAttributes(Object) */ @Override public ConfigurationStatus configure(IProgressMonitor progressMonitor, Object attributes) { // Get a Class lock to avoid multiple installations at the same time even with multiple // instances of this // processor synchronized (this.getClass()) { if (installationInProgress) { return configurationStatus; } installationInProgress = true; } if (!Platform.OS_WIN32.equals(Platform.getOS())) { String err = "The Python installer processor is designed to work on Windows."; // $NON-NLS-1$ IdeLog.logError(PortalUIPlugin.getDefault(), new Exception(err)); applyErrorAttributes(err); installationInProgress = false; return configurationStatus; } try { configurationStatus.removeAttribute(CONFIG_ATTR); clearErrorAttributes(); // Load the installer's attributes IStatus loadingStatus = loadAttributes(attributes); if (!loadingStatus.isOK()) { String message = loadingStatus.getMessage(); applyErrorAttributes(message); IdeLog.logError(PortalUIPlugin.getDefault(), new Exception(message)); return configurationStatus; } // Check that we got the expected single install URL if (urls.length != 1) { // structure error String err = NLS.bind( Messages.InstallProcessor_wrongNumberOfInstallLinks, new Object[] {PYTHON, 1, urls.length}); applyErrorAttributes(err); IdeLog.logError(PortalUIPlugin.getDefault(), new Exception(err)); return configurationStatus; } // Try to get the default install directory from the optional attributes installDir = attributesMap.get(INSTALL_DIR_ATTRIBUTE); if (installDir == null) { installDir = PYTHON_DEFAULT_INSTALL_DIR; } // Start the installation... configurationStatus.setStatus(ConfigurationStatus.PROCESSING); IStatus status = download(urls, progressMonitor); if (status.isOK()) { status = install(progressMonitor); } switch (status.getSeverity()) { case IStatus.OK: case IStatus.INFO: case IStatus.WARNING: displayMessageInUIThread( MessageDialog.INFORMATION, NLS.bind(Messages.InstallProcessor_installerTitle, PYTHON), NLS.bind(Messages.InstallProcessor_installationSuccessful, PYTHON)); configurationStatus.setStatus(ConfigurationStatus.OK); break; case IStatus.ERROR: configurationStatus.setStatus(ConfigurationStatus.ERROR); break; case IStatus.CANCEL: configurationStatus.setStatus(ConfigurationStatus.INCOMPLETE); break; default: configurationStatus.setStatus(ConfigurationStatus.UNKNOWN); } return configurationStatus; } finally { synchronized (this.getClass()) { installationInProgress = false; } } }
public PythonInstallerOptionsDialog() { super(Display.getDefault().getActiveShell(), PYTHON); setTitleImage( PortalUIPlugin.getDefault().getImageRegistry().get(PortalUIPlugin.PYTHON_IMAGE)); }
/** * Run the PYTHON installer and install XMAPP into the given directory. * * @param installationAttributes - Attributes map that contains the installation directory and a * specification whether to run the PYTHON auto-install script. * @return The status of this installation */ protected IStatus installPYTHON(final Map<String, Object> installationAttributes) { Job job = new Job( NLS.bind( Messages.InstallProcessor_installerJobName, PYTHON + ' ' + Messages.InstallProcessor_installerGroupTitle)) { @Override protected IStatus run(IProgressMonitor monitor) { try { // extract the values from the attributes: String installDir = (String) installationAttributes.get(InstallerOptionsDialog.INSTALL_DIR_ATTR); // This installer requires Windows path slashes style (backslashes) installDir = installDir.replaceAll("/", "\\\\"); // $NON-NLS-1$ //$NON-NLS-2$ SubMonitor subMonitor = SubMonitor.convert(monitor, IProgressMonitor.UNKNOWN); subMonitor.beginTask( NLS.bind(Messages.InstallProcessor_installingTaskName, PYTHON), IProgressMonitor.UNKNOWN); IdeLog.logInfo( PortalUIPlugin.getDefault(), "Installing Python into " + installDir); // $NON-NLS-1$ // Try to get a file lock first, before running the process. This file was just // downloaded, so there // is a chance it's still being held by the OS or by the downloader. IStatus fileLockStatus = LockUtils.waitForLockRelease(downloadedPaths.get(0).toOSString(), 10000L); if (!fileLockStatus.isOK()) { return new Status( IStatus.ERROR, PortalUIPlugin.PLUGIN_ID, NLS.bind(Messages.InstallProcessor_failedToInstallSeeLog, PYTHON)); } // Run the Python installer, as specified in this link: // http://www.python.org/download/releases/2.5/msi/ List<String> command = new ArrayList<String>(4); command.add("msiexec"); // $NON-NLS-1$ command.add("/i"); // $NON-NLS-1$ command.add(downloadedPaths.get(0).toOSString()); command.add("/qr"); // $NON-NLS-1$ command.add("TARGETDIR=\"" + installDir + '\"'); // $NON-NLS-1$ if (Boolean.FALSE.toString().equals(attributesMap.get(INSTALL_FOR_ALL_USERS_ATTR))) { command.add("ALLUSERS=0"); // $NON-NLS-1$ } else { command.add("ALLUSERS=1"); // $NON-NLS-1$ } ProcessBuilder processBuilder = new ProcessBuilder(command); Process process = processBuilder.start(); int res = process.waitFor(); if (res == PYTHON_INSTALLER_PROCESS_CANCEL_CODE) { IdeLog.logInfo( PortalUIPlugin.getDefault(), "Python installation cancelled"); // $NON-NLS-1$ return Status.CANCEL_STATUS; } if (res != 0) { // We had an error while installing IdeLog.logError( PortalUIPlugin.getDefault(), "Failed to install Python. The PYTHON installer process returned a termination code of " + res); //$NON-NLS-1$ return new Status( IStatus.ERROR, PortalUIPlugin.PLUGIN_ID, res, NLS.bind(Messages.InstallProcessor_installationErrorMessage, PYTHON, PYTHON), null); } else if (!new File(installDir).exists()) { // Just to be sure that we got everything in place IdeLog.logError( PortalUIPlugin.getDefault(), "Failed to install Python. The " + installDir + " directory was not created", (Throwable) null); // $NON-NLS-1$ //$NON-NLS-2$ return new Status( IStatus.ERROR, PortalUIPlugin.PLUGIN_ID, res, NLS.bind(Messages.InstallProcessor_installationError_installDirMissing, PYTHON), null); } finalizeInstallation(installDir); return Status.OK_STATUS; } catch (Exception e) { IdeLog.logError(PortalUIPlugin.getDefault(), e.getMessage(), e); return new Status( IStatus.ERROR, PortalUIPlugin.PLUGIN_ID, NLS.bind(Messages.InstallProcessor_failedToInstallSeeLog, PYTHON), e); } finally { monitor.done(); } } }; // Give it a little delay, just in case the downloader still holds on to the installer file. job.schedule(1000); try { job.join(); } catch (InterruptedException e) { IdeLog.logError(PortalUIPlugin.getDefault(), e.getMessage(), e); return Status.CANCEL_STATUS; } return job.getResult(); }
/** * Do the PYTHON installation. * * @param progressMonitor * @return A status indication of the process success or failure. */ protected IStatus install(IProgressMonitor progressMonitor) { if (CollectionsUtil.isEmpty(downloadedPaths)) { String failureMessge = Messages.InstallProcessor_couldNotLocateInstaller; String err = NLS.bind(Messages.InstallProcessor_failedToInstall, PYTHON); displayMessageInUIThread( MessageDialog.ERROR, Messages.InstallProcessor_installationErrorTitle, err + ' ' + failureMessge); return new Status(IStatus.ERROR, PortalUIPlugin.PLUGIN_ID, err + ' ' + failureMessge); } SubMonitor subMonitor = SubMonitor.convert( progressMonitor, Messages.InstallProcessor_installerProgressInfo, IProgressMonitor.UNKNOWN); final Map<String, Object> installationAttributes = new HashMap<String, Object>(); try { subMonitor.beginTask( NLS.bind(Messages.InstallProcessor_installingTaskName, PYTHON), IProgressMonitor.UNKNOWN); final String[] installDir = new String[1]; Job installPythonDialog = new UIJob("Python installer options") // $NON-NLS-1$ { @Override public IStatus runInUIThread(IProgressMonitor monitor) { PythonInstallerOptionsDialog dialog = new PythonInstallerOptionsDialog(); if (dialog.open() == Window.OK) { installationAttributes.putAll(dialog.getAttributes()); return Status.OK_STATUS; } return Status.CANCEL_STATUS; } }; installPythonDialog.schedule(); try { installPythonDialog.join(); } catch (InterruptedException e) { } IStatus result = installPythonDialog.getResult(); if (!result.isOK()) { return result; } IStatus status = installPYTHON(installationAttributes); if (!status.isOK()) { return status; } IdeLog.logInfo( PortalUIPlugin.getDefault(), MessageFormat.format( "Successfully installed PYTHON into {0}. PYTHON installation completed.", installDir[0])); // $NON-NLS-1$ // note that we called the finalizeInstallation from the installPYTHON Job. return Status.OK_STATUS; } catch (Exception e) { IdeLog.logError( PortalUIPlugin.getDefault(), "Error while installing PYTHON", e); // $NON-NLS-1$ return new Status( IStatus.ERROR, PortalUIPlugin.PLUGIN_ID, NLS.bind(Messages.InstallProcessor_errorWhileInstalling, PYTHON)); } finally { subMonitor.done(); } }