/******************************************************************************* * Copyright (c) 2007, 2008 Spring IDE Developers * 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: * Spring IDE Developers - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.aop.core.internal.model; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.ui.IElementFactory; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPersistableElement; import org.eclipse.ui.XMLMemento; import org.springframework.ide.eclipse.aop.core.Activator; import org.springframework.ide.eclipse.aop.core.model.IAopProject; import org.springframework.ide.eclipse.aop.core.model.IAopReference; import org.springframework.ide.eclipse.aop.core.model.IAopReferenceModel; import org.springframework.ide.eclipse.aop.core.model.IAspectDefinition; import org.springframework.ide.eclipse.aop.core.util.AopReferenceModelMarkerUtils; /** * @author Christian Dupuis * @since 2.0 */ public class AopReferenceModelPeristence { private static final Map<String, IElementFactory> ELEMENT_FACTORIES; static { ELEMENT_FACTORIES = new HashMap<String, IElementFactory>(); ELEMENT_FACTORIES.put(AnnotationAspectDefinitionElementFactory.FACTORY_ID, new AnnotationAspectDefinitionElementFactory()); ELEMENT_FACTORIES.put(AnnotationIntroductionDefinitionElementFactory.FACTORY_ID, new AnnotationIntroductionDefinitionElementFactory()); ELEMENT_FACTORIES.put(BeanAspectDefinitionElementFactory.FACTORY_ID, new BeanAspectDefinitionElementFactory()); ELEMENT_FACTORIES.put(BeanIntroductionDefinitionElementFactory.FACTORY_ID, new BeanIntroductionDefinitionElementFactory()); ELEMENT_FACTORIES.put(JavaAdvisorDefinitionElementFactory.FACTORY_ID, new JavaAdvisorDefinitionElementFactory()); ELEMENT_FACTORIES.put(AopReferenceElementFactory.FACTORY_ID, new AopReferenceElementFactory()); } private static final String AOP_PROJECT_ELEMENT = "aop-project"; private static final String AOP_REFERENCE_ELEMENT = "aop-reference"; private static final String AOP_REFERENCE_MODEL_ELEMENT = "aop-reference-model"; private static final String ASPECT_DEFINITION_ELEMENT = "aspect-definition"; private static final String FACTORY_ID = "factory-id"; private static final String NAME_ATTRIBUTE = "name"; private IPath defaultFile = null; public AopReferenceModelPeristence() { this.defaultFile = Activator.getDefault().getStateLocation().append(".state"); } private IMemento appendNewChild(IMemento memento, String type) { memento.createChild(type); IMemento[] ms = memento.getChildren(type); if (ms != null && ms.length > 0) { return ms[ms.length - 1]; } return memento; } private void createAopProjects(IAopReferenceModel model, XMLMemento memento) { IMemento[] projects = memento.getChildren(AOP_PROJECT_ELEMENT); if (projects != null && projects.length > 0) { for (IMemento project : projects) { String projectName = project.getString(NAME_ATTRIBUTE); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IResource member = root.findMember(projectName); if (member instanceof IProject) { IJavaProject javaProject = JavaCore.create((IProject) member); IAopProject aopProject = model.getProject(javaProject); createAspectDefinitions(projects, project, aopProject); // recreate the marker Set<IAopReference> references = aopProject.getAllReferences(); for (IAopReference reference : references) { AopReferenceModelMarkerUtils.createMarker(reference, reference .getResource()); } } } } } private void createAopReferences(IAopProject aopProject, IMemento aspectDefinitionM, IAspectDefinition aspectDefinition) { String factoryId; IMemento[] aopReferences = aspectDefinitionM.getChildren(AOP_REFERENCE_ELEMENT); if (aopReferences != null && aopReferences.length > 0) { for (IMemento aopReferenceM : aopReferences) { factoryId = aopReferenceM.getString(FACTORY_ID); IAopReference aopReference = (IAopReference) ELEMENT_FACTORIES.get(factoryId) .createElement(aopReferenceM); // The aopReference can be null if the resource has been deleted or is an external if (aopReference != null) { aopReference.setDefinition(aspectDefinition); aopProject.addAopReference(aopReference); } } } } private void createAspectDefinitions(IMemento[] projects, IMemento project, IAopProject aopProject) { IMemento[] aspectDefinitions = project.getChildren(ASPECT_DEFINITION_ELEMENT); if (projects != null && projects.length > 0) { for (IMemento aspectDefinitionM : aspectDefinitions) { String factoryId = aspectDefinitionM.getString(FACTORY_ID); IAspectDefinition aspectDefinition = (IAspectDefinition) ELEMENT_FACTORIES.get( factoryId).createElement(aspectDefinitionM); createAopReferences(aopProject, aspectDefinitionM, aspectDefinition); } } } protected boolean isPersisted() { return defaultFile.toFile().exists(); } protected synchronized void loadReferenceModel() { if (!shouldModelByPersisted() || !isPersisted()) { return; } IAopReferenceModel model = Activator.getModel(); Reader reader = null; try { reader = new FileReader(defaultFile.toFile()); XMLMemento memento = XMLMemento.createReadRoot(reader); createAopProjects(model, memento); } catch (Exception e) { Activator.log("Cannot load .state model file", e); // re-init aop reference model Activator.getModel().clearProjects(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { } } } } private boolean shouldModelByPersisted() { IScopeContext context = new InstanceScope(); IEclipsePreferences node = context.getNode(Activator.PLUGIN_ID); return node.getBoolean(Activator.PERSIST_AOP_MODEL_PREFERENCE, true); } protected synchronized void saveReferenceModel() { if (!shouldModelByPersisted()) { if (isPersisted()) { defaultFile.toFile().delete(); } return; } XMLMemento memento = XMLMemento.createWriteRoot(AOP_REFERENCE_MODEL_ELEMENT); Collection<IAopProject> projects = Activator.getModel().getProjects(); for (IAopProject project : projects) { IMemento projectM = appendNewChild(memento, AOP_PROJECT_ELEMENT); projectM.putString(NAME_ATTRIBUTE, project.getProject().getElementName()); Set<IAopReference> refs = project.getAllReferences(); Map<IAspectDefinition, List<IAopReference>> maps = new HashMap<IAspectDefinition, List<IAopReference>>(); for (IAopReference ref : refs) { if (maps.containsKey(ref.getDefinition())) { maps.get(ref.getDefinition()).add(ref); } else { List<IAopReference> r = new ArrayList<IAopReference>(); r.add(ref); maps.put(ref.getDefinition(), r); } } for (Map.Entry<IAspectDefinition, List<IAopReference>> entry : maps.entrySet()) { IMemento definitionM = appendNewChild(projectM, ASPECT_DEFINITION_ELEMENT); if (entry.getKey() instanceof IAdaptable) { IPersistableElement pers = (IPersistableElement) ((IAdaptable) entry.getKey()) .getAdapter(IPersistableElement.class); if (pers != null) { pers.saveState(definitionM); definitionM.putString(FACTORY_ID, pers.getFactoryId()); } for (IAopReference ref : entry.getValue()) { if (ref instanceof IAdaptable) { IPersistableElement pers2 = (IPersistableElement) ((IAdaptable) ref) .getAdapter(IPersistableElement.class); if (pers2 != null) { IMemento refM = appendNewChild(definitionM, AOP_REFERENCE_ELEMENT); pers2.saveState(refM); refM.putString(FACTORY_ID, pers2.getFactoryId()); } } } } } } // save memento to default map file Writer writer = null; try { writer = new FileWriter(defaultFile.toFile()); memento.save(writer); } catch (IOException e) { } finally { if (writer != null) { try { writer.flush(); writer.close(); } catch (IOException e) { } } } } }