/* * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.groovy.eclipse.refactoring.actions; import org.codehaus.groovy.eclipse.core.GroovyCore; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.groovy.core.util.ContentTypeUtils; import org.eclipse.jdt.groovy.core.util.ReflectionUtils; import org.eclipse.jdt.internal.corext.fix.CleanUpPostSaveListener; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.javaeditor.saveparticipant.IPostSaveListener; import org.eclipse.jdt.internal.ui.javaeditor.saveparticipant.SaveParticipantDescriptor; import org.eclipse.jdt.internal.ui.javaeditor.saveparticipant.SaveParticipantRegistry; import org.eclipse.jface.text.IRegion; /** * @author Andrew Eisenberg * @created Aug 25, 2009 * * This class Delegates to either the {@link org.eclipse.jdt.internal.corext.fix.CleanUpPostSaveListener} or * to {@link GroovyCleanupPostSaveListener} depending on the content type of the file being saved. * <p> * This class ensures that when groovy compilation units are encountered, Post save actions are * properly executed */ public class DelegatingCleanUpPostSaveListener extends CleanUpPostSaveListener { private final IPostSaveListener jdtCleanUp; private final IPostSaveListener groovyCleanUp; public DelegatingCleanUpPostSaveListener(CleanUpPostSaveListener jdtCleanUp, GroovyCleanupPostSaveListener groovyCleanUp) { this.jdtCleanUp = jdtCleanUp; this.groovyCleanUp = groovyCleanUp; } /** * Installs a delegating cleanup by replacing the existing jdt cleanup */ public static void installCleanUp() { try { SaveParticipantRegistry registry = JavaPlugin.getDefault().getSaveParticipantRegistry(); // synchronized because we don't want registry being used in the middle of this. synchronized (registry) { SaveParticipantDescriptor descriptor = registry.getSaveParticipantDescriptor(org.eclipse.jdt.internal.corext.fix.CleanUpPostSaveListener.POSTSAVELISTENER_ID); // descriptor shouldn't be null, but if it is, NPE is thrown and we register the exception in the log. // also exception will be thrown if the delegating cleanup was already installed org.eclipse.jdt.internal.corext.fix.CleanUpPostSaveListener jdtCleanUp = (org.eclipse.jdt.internal.corext.fix.CleanUpPostSaveListener) descriptor.getPostSaveListener(); GroovyCleanupPostSaveListener groovyCleanUp = new GroovyCleanupPostSaveListener(); IPostSaveListener delegatingCleanUp = new DelegatingCleanUpPostSaveListener(jdtCleanUp, groovyCleanUp); ReflectionUtils.setPrivateField(SaveParticipantDescriptor.class, "fPostSaveListener", descriptor, delegatingCleanUp); } } catch (Exception e) { // a ClassCastException can be thrown when changing compilers, so ignore it if (e instanceof ClassCastException) { if (e.getStackTrace()[0].getLineNumber() == 55) { return; } } // if an exception is thrown, then the groovy post save listener will not be used. GroovyCore.logException("Exception thrown while trying to install GroovyCleanUpPostSaveListener", e); } } /** * Uninstalls the delegating cleanup and replaces it with the original jdt cleanup */ public static void uninstallCleanUp() { try { SaveParticipantRegistry registry = JavaPlugin.getDefault().getSaveParticipantRegistry(); // synchronized because we don't want registry being used in the middle of this. synchronized (registry) { SaveParticipantDescriptor descriptor = registry.getSaveParticipantDescriptor(org.eclipse.jdt.internal.corext.fix.CleanUpPostSaveListener.POSTSAVELISTENER_ID); DelegatingCleanUpPostSaveListener delegatingCleanUp = (DelegatingCleanUpPostSaveListener) descriptor.getPostSaveListener(); ReflectionUtils.setPrivateField(SaveParticipantDescriptor.class, "fPostSaveListener", descriptor, delegatingCleanUp.jdtCleanUp); } } catch (Exception e) { // if an exception is thrown, then the groovy post save listener will not be used. GroovyCore.logException("Exception thrown while trying to install GroovyCleanUpPostSaveListener", e); } } public String getId() { return jdtCleanUp.getId(); } public String getName() { return jdtCleanUp.getName(); } public boolean needsChangedRegions(ICompilationUnit compilationUnit) throws CoreException { if (ContentTypeUtils.isGroovyLikeFileName(compilationUnit.getElementName())) { return groovyCleanUp.needsChangedRegions(compilationUnit); } else { return jdtCleanUp.needsChangedRegions(compilationUnit); } } public void saved(ICompilationUnit compilationUnit, IRegion[] changedRegions, IProgressMonitor monitor) throws CoreException { if (ContentTypeUtils.isGroovyLikeFileName(compilationUnit.getElementName())) { groovyCleanUp.saved(compilationUnit, changedRegions, monitor); } else { jdtCleanUp.saved(compilationUnit, changedRegions, monitor); } } }