/******************************************************************************* * Copyright (c) 2013, 2016 GoPivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * GoPivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.core.cli; import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.osgi.service.prefs.BackingStoreException; import org.springframework.ide.eclipse.boot.core.BootActivator; import org.springframework.ide.eclipse.boot.core.cli.install.GenericBootInstall; import org.springframework.ide.eclipse.boot.core.cli.install.IBootInstall; import org.springframework.ide.eclipse.boot.core.cli.install.ZippedBootInstall; import org.springframework.ide.eclipse.boot.util.Log; import org.springsource.ide.eclipse.commons.core.preferences.StsProperties; import org.springsource.ide.eclipse.commons.frameworks.core.downloadmanager.DownloadManager; import org.springsource.ide.eclipse.commons.frameworks.core.util.ArrayEncoder; import org.springsource.ide.eclipse.commons.livexp.util.ExceptionUtil; /** * Manages the boot installations that are configured in this workspace. * * @author Kris De Volder */ public class BootInstallManager implements IBootInstallFactory { public interface BootInstallListener { public void defaultInstallChanged(); } private static final String BOOT_INSTALLS = "installs"; //Key used to store info in the prefs. private static final String DEFAULT_BOOT_INSTALL = "default.install"; //TODO: should use preferences to store boot installation and // we should provide UI for the user to configure different installs etc. //For now a trivial install manager only knows about one Spring boot instal // and its location is injected via 'STSProperties'. private static BootInstallManager instance; private static File determineCacheDir() { IPath stateLocation = BootActivator.getDefault().getStateLocation(); return stateLocation.append("installs").toFile(); } public static synchronized BootInstallManager getInstance() throws Exception { if (instance==null) { instance = new BootInstallManager(); } return instance; } private DownloadManager downloader; private List<IBootInstall> installs = null; private IBootInstall defaultInstall; private ListenerList installListeners = new ListenerList(); private BootInstallManager() throws Exception { downloader = new DownloadManager(null, determineCacheDir()); installs = new ArrayList<>(); read(); if (installs.isEmpty()) { setDefaultInstall(newInstall(StsProperties.getInstance().get("spring.boot.install.url"), null)); } } /** * Initializes the manager by reading Eclipse preferences. */ private void read() { IEclipsePreferences prefs = getPrefs(); String defaultName = prefs.get(DEFAULT_BOOT_INSTALL, ""); String encoded = prefs.get(BOOT_INSTALLS, null); if (encoded!=null) { String[] encodedInstalls = ArrayEncoder.decode(encoded); for (String encodedInstall : encodedInstalls) { try { String[] parts = ArrayEncoder.decode(encodedInstall); IBootInstall install = newInstall(parts[0], parts[1]); installs.add(install); if (defaultName.equals(install.getName())) { setDefaultInstall(install); } } catch (Exception e) { Log.log(e); } } } } protected IEclipsePreferences getPrefs() { return InstanceScope.INSTANCE.getNode(BootActivator.PLUGIN_ID); } /** * Saves current installs by writing them into the Eclipse preferences. * This is not done automatically when values in the manager are set. * The client is repsonsible for calling this method. */ public void save() { List<IBootInstall> local = installs; String[] encodedInstalls = new String[local.size()]; for (int i = 0; i < encodedInstalls.length; i++) { encodedInstalls[i] = encodeInstall(local.get(i)); } String encoded = ArrayEncoder.encode(encodedInstalls); IEclipsePreferences prefs = getPrefs(); prefs.put(BOOT_INSTALLS, encoded); IBootInstall di = null; try { di = getDefaultInstall(); } catch (Exception e) { Log.log(e); } if (di==null) { prefs.remove(DEFAULT_BOOT_INSTALL); } else { prefs.put(DEFAULT_BOOT_INSTALL, di.getName()); } try { prefs.flush(); } catch (BackingStoreException e) { Log.log(e); } } private String encodeInstall(IBootInstall install) { return ArrayEncoder.encode(new String[] { install.getUrl(), install.getName() }); } public IBootInstall newInstall(String url, String name) { try { URI uri = new URI(url); if ("file".equals(uri.getScheme())) { File file = new File(uri); if (file.isDirectory()) { return new LocalBootInstall(file, name); } else { return new ZippedBootInstall(downloader, url, name); } } else { String path = uri.getPath(); if (path.toLowerCase().endsWith(".zip")) { return new ZippedBootInstall(downloader, url, name); } else { return new GenericBootInstall(url, null, "Not a zip url: "+url); } } } catch (Exception e) { Log.log(e); return new GenericBootInstall(url, name, ExceptionUtil.getMessage(e)); } } public synchronized IBootInstall getDefaultInstall() throws Exception { return defaultInstall; } public void setDefaultInstall(IBootInstall defaultInstall) { if (!installs.contains(defaultInstall)) { installs.add(defaultInstall); } if ((this.defaultInstall != defaultInstall) || (this.defaultInstall != null && !this.defaultInstall.equals(defaultInstall))) { this.defaultInstall = defaultInstall; for (Object listener : installListeners.getListeners()) { ((BootInstallListener)listener).defaultInstallChanged(); } } } public void setInstalls(Collection<IBootInstall> newInstalls) { this.installs = new ArrayList<>(newInstalls); } public Collection<IBootInstall> getInstalls() { return new ArrayList<>(installs); } public DownloadManager getDownloader() { return downloader; } public void addBootInstallListener(BootInstallListener listener) { installListeners.add(listener); } public void removeBootInstallListener(BootInstallListener listener) { installListeners.remove(listener); } }