/*******************************************************************************
* Copyright (c) 2007 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.seam.core.project.facet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.jboss.tools.seam.core.ISeamProject;
import org.jboss.tools.seam.core.SeamCorePlugin;
import org.jboss.tools.seam.core.SeamUtil;
import org.jboss.tools.seam.internal.core.SeamProject;
import org.jboss.tools.seam.internal.core.project.facet.ISeamFacetDataModelProperties;
import org.jboss.tools.seam.internal.core.project.facet.SeamFacetPreferenceInitializer;
import org.osgi.service.prefs.BackingStoreException;
/**
* This class is responsible for managing available SeamRuntime list.
*
* @author eskimo
*/
public class SeamRuntimeManager {
private static SeamRuntimeListConverter converter = new SeamRuntimeListConverter();
private Map<String, SeamRuntime> runtimes = new HashMap<String, SeamRuntime>();
/**
* Private constructor
*/
private SeamRuntimeManager() {
String configVersion = SeamProjectPreferences
.getStringPreference(SeamProjectPreferences.RUNTIME_CONFIG_FORMAT_VERSION);
String runtimeListString = SeamProjectPreferences
.getStringPreference(SeamProjectPreferences.RUNTIME_LIST);
runtimes = converter.getMap(runtimeListString);
SeamCorePlugin.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
String property = event.getProperty();
if (SeamProjectPreferences.RUNTIME_LIST.equals(property)) {
String runtimeListString = SeamProjectPreferences
.getStringPreference(SeamProjectPreferences.RUNTIME_LIST);
Map<String, SeamRuntime> newRuntimes = converter.getMap(runtimeListString);
for (SeamRuntime seamRuntime : newRuntimes.values()) {
String name = seamRuntime.getName();
if (name == null) {
continue;
}
SeamRuntime runtime = runtimes.get(name);
if (runtime == null) {
addRuntime(seamRuntime);
}
}
}
}
});
}
/**
* This class make Java Runtime responsible for solving synchronization
* problems during initialization if there is any
*
* @author eskimo
*/
static class SeamRuntimeManagerHolder {
private static final SeamRuntimeManager INSTANCE = new SeamRuntimeManager();
}
/**
* Return SeamRuntimeManaher instance
*
* @return
* SeamRuntimeManager instance
*/
public static SeamRuntimeManager getInstance() {
return SeamRuntimeManagerHolder.INSTANCE;
}
/**
* Return Array of configured SeamRuntimes
*
* @return
* SeamRuntime[]
*/
public SeamRuntime[] getRuntimes() {
Collection<SeamRuntime> c = runtimes.values();
return c.toArray(new SeamRuntime[runtimes.size()]);
}
/**
* @return the latest version of installed Seam runtimes. If there are a few runtimes with the same version
* then the default one will be returned.
*/
public SeamRuntime getLatestSeamRuntime() {
SeamVersion latestVersion = runtimes.isEmpty()?SeamVersion.getLatestDefaultVersion():SeamVersion.SEAM_1_2;
for (SeamRuntime runtime : runtimes.values()) {
if(runtime.getVersion().compareTo(latestVersion)>=0) {
latestVersion = runtime.getVersion();
}
}
SeamRuntime runtime = getDefaultRuntime(latestVersion);
if(runtime==null) {
SeamRuntime[] runtimes = getRuntimes(latestVersion);
if(runtimes.length>0) {
runtime = runtimes[0];
}
}
return runtime;
}
/**
* Return array of SeamRuntimes that is compatible with given version
*
* @param version
* SeamVersion
* @return
* SeamRuntime[]
*/
public SeamRuntime[] getRuntimes(SeamVersion version) {
Collection<SeamRuntime> c = runtimes.values();
List<SeamRuntime> rts = new ArrayList<SeamRuntime>();
for (SeamRuntime seamRuntime : c) {
if (seamRuntime.getVersion() == version) {
rts.add(seamRuntime);
}
}
return rts.toArray(new SeamRuntime[rts.size()]);
}
/**
* Add new SeamRuntime
*
* @param runtime
* SeamRuntime
*/
public void addRuntime(SeamRuntime runtime) {
SeamRuntime oldDefaultRuntime = getDefaultRuntime(runtime.getVersion());
if (oldDefaultRuntime != null) {
if(runtime.isDefault()) {
oldDefaultRuntime.setDefault(false);
}
} else {
runtime.setDefault(true);
}
runtimes.put(runtime.getName(), runtime);
updateProjectsForRuntime(runtime);
save();
}
/**
* Add new SeamRuntime with given parameters
*
* @param name
* String - runtime name
* @param path
* String - runtime home folder
* @param version
* String - string representation of version number
* @param defaultRt
* boolean - default flag
*/
public SeamRuntime addRuntime(String name, String path, SeamVersion version,
boolean defaultRt) {
SeamRuntime seamRt = new SeamRuntime();
seamRt.setVersion(version);
seamRt.setHomeDir(path);
seamRt.setName(name);
seamRt.setDefault(defaultRt);
addRuntime(seamRt);
return seamRt;
}
/**
* Return SeamRuntime by given name
*
* @param name
* String - SeamRuntime name
* @return
* SeamRuntime - found SeamRuntime instance or null
*/
public SeamRuntime findRuntimeByName(String name) {
for (SeamRuntime seamRuntime : runtimes.values()) {
if (seamRuntime.getName().equals(name)) {
return seamRuntime;
}
}
return null;
}
/**
* Remove given SeamRuntime from manager
* @param rt
* SeamRuntime
*/
public void removeRuntime(SeamRuntime rt) {
runtimes.remove(rt.getName());
updateProjectsForRuntime(rt);
}
private void updateProjectsForRuntime(SeamRuntime rt) {
IProject[] ps = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (int i = 0; i < ps.length; i++) {
ISeamProject sp = SeamCorePlugin.getSeamProject(ps[i], false);
if (sp != null ) {
String tmpName = null;
try {
tmpName = sp.getRuntimeName();
} catch (IllegalStateException ex) {
// JBIDE-13811 fix to avoid IllegalStateExceptions
SeamCorePlugin.getDefault().logWarning(ex);
}
if(rt.getName().equals(tmpName)) {
IEclipsePreferences prefs = ((SeamProject)sp).getSeamPreferences();
prefs.remove(ISeamProject.RUNTIME_NAME);
prefs.put(ISeamProject.RUNTIME_NAME, rt.getName());
try {
prefs.flush();
} catch (BackingStoreException e) {
SeamCorePlugin.getPluginLog().logError(e);
}
}
}
}
}
/**
* Return SeamRuntime instance for given project
*
* @param project
* IProject
* @return
* SeamRuntime - instance of available SeamRuntime or null
*/
public SeamRuntime getRuntimeForProject(IProject project) {
ISeamProject seamProject = SeamCorePlugin
.getSeamProject(project, false);
return (seamProject == null) ? null : seamProject.getRuntime();
}
/**
* Save preference value and force save changes to disk
*/
public void save() {
SeamCorePlugin.getDefault().getPluginPreferences().setValue(
SeamProjectPreferences.RUNTIME_LIST,
converter.getString(runtimes));
IPreferenceStore store = SeamCorePlugin.getDefault()
.getPreferenceStore();
if (store instanceof IPersistentPreferenceStore) {
try {
((IPersistentPreferenceStore) store).save();
} catch (IOException e) {
SeamCorePlugin.getPluginLog().logError(
"Seam Runtime List was not saved", e);
}
}
}
/**
* Marks this runtime as default. Marks other runtimes with the same version as not default.
* @param runtime
*/
public void setDefaultRuntime(SeamRuntime runtime) {
SeamRuntime[] runtimes = getRuntimes(runtime.getVersion());
for (int i = 0; i < runtimes.length; i++) {
runtimes[i].setDefault(false);
}
runtime.setDefault(true);
}
/**
* Return first default SeamRuntime
*
* @return
* SeamRuntime
*/
public SeamRuntime getDefaultRuntime() {
for (SeamRuntime rt : runtimes.values()) {
if (rt.isDefault()) {
return rt;
}
}
return null;
}
/**
* If project has seam facet then this method returns default seam runtime for proper version of facet.
* Otherwise return first default runtime.
* @param project
* @return
*/
public static SeamRuntime getDefaultRuntimeForProject(IProject project) {
if(project==null) {
throw new IllegalArgumentException("Project must not be null.");
}
try {
IProjectFacet facet = ProjectFacetsManager.getProjectFacet(ISeamFacetDataModelProperties.SEAM_FACET_ID);
IFacetedProject facetedProject = ProjectFacetsManager.create(project);
if(facetedProject!=null) {
IProjectFacetVersion facetVersion = facetedProject.getInstalledVersion(facet);
if(facetVersion==null) return null;
SeamVersion seamVersion = SeamVersion.parseFromString(facetVersion.getVersionString());
return getInstance().getDefaultRuntime(seamVersion);
}
} catch (CoreException e) {
SeamCorePlugin.getPluginLog().logError(e);
} catch (IllegalArgumentException e) {
SeamCorePlugin.getPluginLog().logError(e);
}
return getInstance().getDefaultRuntime();
}
/**
* Return default runtime for given SeamVersion
*
* @param version
* given SeamVersion
* @return
* Default SeamRuntime for given version
*/
public SeamRuntime getDefaultRuntime(SeamVersion version) {
for (SeamRuntime rt : runtimes.values()) {
if (rt.isDefault() && rt.getVersion() == version) {
return rt;
}
}
return null;
}
/**
* Return version of configuration
*
* @return
* String - string representation of version
*/
public String getConfigurationVersion() {
return SeamFacetPreferenceInitializer.RUNTIME_CONFIG_FORMAT_VERSION;
}
/**
* Return a list of all runtime names
*
* @return
* List of all runtime names
*/
public List<String> getAllRuntimeNames() {
SeamRuntime[] rts = getRuntimes();
List<String> result = new ArrayList<String>();
for (SeamRuntime seamRuntime : rts) {
result.add(seamRuntime.getName());
}
return result;
}
/**
* TBD
*
* @param oldName
* old runtime name
* @param newName
* new runtime name
*/
public void changeRuntimeName(String oldName, String newName) {
SeamRuntime o = findRuntimeByName(oldName);
if (o == null) {
return;
}
o.setName(newName);
runtimes.remove(oldName);
runtimes.put(newName, o);
onRuntimeNameChanged(oldName, newName);
}
private void onRuntimeNameChanged(String oldName, String newName) {
IProject[] ps = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (int i = 0; i < ps.length; i++) {
ISeamProject sp = SeamCorePlugin.getSeamProject(ps[i], false);
if (sp != null && oldName.equals(sp.getRuntimeName())) {
sp.setRuntimeName(newName);
}
}
}
}