/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and 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: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.model.project; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; import org.eclipse.core.resources.ICommand; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IProjectNature; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.PlatformObject; import org.jboss.tools.common.model.ServiceDialog; import org.jboss.tools.common.model.XModel; import org.jboss.tools.common.model.XModelConstants; import org.jboss.tools.common.model.XModelFactory; import org.jboss.tools.common.model.XModelObjectConstants; import org.jboss.tools.common.model.plugin.ModelPlugin; import org.jboss.tools.common.model.util.ModelFeatureFactory; public abstract class ModelNature extends PlatformObject implements IProjectNature, IModelNature { public static final String NATURE_ID = ModelPlugin.PLUGIN_ID + ".modelnature"; //$NON-NLS-1$ static Map<IProject,XModel> models = new HashMap<IProject,XModel>(); static IResourceChangeListener listener = null; protected String workspaceHome = null; protected IProject project = null; protected XModel model = null; public ModelNature() {} public void configure() throws CoreException { } public void deconfigure() throws CoreException { ModelPlugin p = ModelPlugin.getDefault(); if(model != null) { p.getSaveParticipant().removeModel(model); model = null; } } public IProject getProject() { return project; } public void setProject(IProject project) { if(this.project == project) return; this.project = project; createProject(); } public Object getAdapter(Class adapter) { return super.getAdapter(adapter); } public XModel getModel() { return model; } private void updateListener() { if(listener != null) return; listener = new Listener(); ModelPlugin.getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_CLOSE); } static class Listener implements IResourceChangeListener { public void resourceChanged(IResourceChangeEvent event) { if(event.getType() == IResourceChangeEvent.PRE_DELETE //TODO It will be good to clean cache on close project, //but it will need extensive testing, so let's do it later //when having more time before another release. // || event.getType() == IResourceChangeEvent.PRE_CLOSE ) { IProject p = event.getResource().getProject(); if(p != null && models.containsKey(p)) { models.remove(p); } } } } private void createProject() { Properties p = new Properties(); p.putAll(System.getProperties()); String home = getWorkspaceHome(); if(home != null && home.length() > 0) { p.setProperty(XModelConstants.WORKSPACE, home); p.setProperty(XModelConstants.WORKSPACE_OLD, home); } else { IAutoLoad auto = createAutoLoad(); boolean result = auto != null && ProjectHome.getLocation(project, p); if(result) { p.put(XModelConstants.AUTOLOAD, auto); } else { p.setProperty(XModelConstants.WORKSPACE, ""); //$NON-NLS-1$ p.setProperty(XModelConstants.WORKSPACE_OLD, ""); //$NON-NLS-1$ } } p.setProperty(ECLIPSE_PROJECT, project.getLocation().toString()); p.setProperty(ECLIPSE_PROJECT_OLD, project.getLocation().toString()); p.put(XModelObjectConstants.PROJECT, project); p.setProperty("nature", getID()); //$NON-NLS-1$ model = (XModel)models.get(project); if(model != null) { home = p.getProperty(XModelConstants.WORKSPACE); String h = XModelConstants.getWorkspace(model); if(home == null || !home.equals(h)) { ModelPlugin.getPluginLog().logInfo("WARNING:" + " workspace home changed from " + h + " to " + home); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ model.getProperties().setProperty(XModelConstants.WORKSPACE, home); model.getProperties().setProperty(XModelConstants.WORKSPACE_OLD, home); model.getProperties().setProperty("nature", getID()); //$NON-NLS-1$ model.load(); } return; } model = XModelFactory.getModel(p); if(model.getService() == null) { model.setService(createServiceDialog()); } models.put(project, model); ModelPlugin.getDefault().getSaveParticipant().addModel(model); updateProjectVersion(); updateListener(); } protected IAutoLoad createAutoLoad() { return null; } protected void addToBuildSpec(String builderID) throws CoreException { IProjectDescription description = getProject().getDescription(); ICommand command = null; ICommand commands[] = description.getBuildSpec(); for (int i = 0; i < commands.length && command == null; ++i) { if (commands[i].getBuilderName().equals(builderID)) command = commands[i]; } if (command == null) { command = description.newCommand(); command.setBuilderName(builderID); ICommand[] oldCommands = description.getBuildSpec(); ICommand[] newCommands = new ICommand[oldCommands.length + 1]; System.arraycopy(oldCommands, 0, newCommands, 0, oldCommands.length); newCommands[oldCommands.length] = command; description.setBuildSpec(newCommands); getProject().setDescription(description, null); } } static String EXTERNAL_TOOL_BUILDER = "org.eclipse.ui.externaltools.ExternalToolBuilder"; //$NON-NLS-1$ static final String LAUNCH_CONFIG_HANDLE = "LaunchConfigHandle"; //$NON-NLS-1$ protected void removeFromBuildSpec(String builderID) throws CoreException { IProjectDescription description = getProject().getDescription(); ICommand[] commands = description.getBuildSpec(); for (int i = 0; i < commands.length; ++i) { String builderName = commands[i].getBuilderName(); if (!builderName.equals(builderID)) { if(!builderName.equals(EXTERNAL_TOOL_BUILDER)) continue; Object handle = commands[i].getArguments().get(LAUNCH_CONFIG_HANDLE); if(handle == null || handle.toString().indexOf(builderID) < 0) continue; } ICommand[] newCommands = new ICommand[commands.length - 1]; System.arraycopy(commands, 0, newCommands, 0, i); System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1); description.setBuildSpec(newCommands); getProject().setDescription(description, null); return; } } protected void updateProjectVersion() { } private String getWorkspaceHome() { return new ProjectHome().getLocation(project); } private ServiceDialog createServiceDialog() { try { return (ServiceDialog)ModelFeatureFactory.getInstance().createFeatureInstance("org.jboss.tools.common.model.ui.wizards.one.ServiceDialogImpl"); //$NON-NLS-1$ } catch (ClassCastException e) { ModelPlugin.getPluginLog().logError("Cannot create service dialog."); //$NON-NLS-1$ } return null; } /** * These hack methods are used to prevent loading model nature * when its project data is not stored in xmodel settings and should * be loaded from WTP, but project is not synchronized yet so that * loading will fail and xmodel will be corrupted. * @param project * @return */ public static boolean checkModelNature(IProject project) { if(project == null || !project.isOpen()) return false; String nature = null; ModelNatureExtension[] es = ModelNatureExtension.getInstances(); try { for (ModelNatureExtension ext: es) { if(project.hasNature(ext.getName())) { nature = ext.getName(); break; } } } catch (CoreException e) { ModelPlugin.getPluginLog().logError(e); return false; } return checkModelNature(project, nature); } static Map<IProject, Set<String>> checked = new HashMap<IProject, Set<String>>(); public static boolean checkModelNature(IProject project, String nature) { if(project == null || !project.isOpen() || !project.isSynchronized(IResource.DEPTH_ONE)) { if(project != null && checked.containsKey(project)) { checked.remove(project); } return false; } if(nature == null) return false; Set<String> ns = checked.get(project); if(ns == null) { ns = new HashSet<String>(); checked.put(project, ns); } else if(ns.contains(nature)) { return true; } String home = new ProjectHome().getLocation(project); if(home != null && home.length() > 0) { ns.add(nature); return true; } // ns.add(nature); return true; } }