Skip to content

Instantly share code, notes, and snippets.

@digulla
Created April 10, 2012 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save digulla/2351505 to your computer and use it in GitHub Desktop.
Save digulla/2351505 to your computer and use it in GitHub Desktop.
Refactored org.cloudsmith.geppetto.pp.dsl.ui.preferences.AbstractRebuildingPreferencePage
/**
* Copyright (c) 2011 Cloudsmith Inc. and other contributors, as listed below.
* 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:
* Cloudsmith
* Aaron Digulla
*/
package com.pany.dsl.ui.preferences;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.xtext.ui.editor.preferences.AbstractPreferencePage;
/**
* Adds behavior to the abstract preference page that checks if a single preference id has
* changed, and if so, triggers a clean build of the project.
*
*/
public abstract class AbstractRebuildingPreferencePage extends AbstractPreferencePage {
private IPropertyChangeListener rebuildListener;
private IPreferenceStore usedPreferenceStore;
@Override
public void dispose() {
if(isPropertyPage()) {
if(rebuildListener != null)
usedPreferenceStore.removePropertyChangeListener(rebuildListener);
}
super.dispose();
}
/** Return true if the project must be rebuilt when the specified property changes */
protected abstract boolean rebuildForChangeOf( String propertyName );
@Override
protected void updateFieldEditors(boolean enabled) {
super.updateFieldEditors(enabled);
if(isPropertyPage()) {
if(rebuildListener == null) {
rebuildListener = new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if(rebuildForChangeOf(event.getProperty())) {
Job job = createBuildJob();
job.schedule();
}
}
};
}
// protect against getting different store instances (happens at least when debugging).
IPreferenceStore store = getPreferenceStore();
if(store != usedPreferenceStore) {
if(usedPreferenceStore != null)
usedPreferenceStore.removePropertyChangeListener(rebuildListener);
usedPreferenceStore = store;
store.addPropertyChangeListener(rebuildListener);
}
}
}
/** Create a job to rebuild the project */
protected abstract Job createBuildJob();
public IProject getProject() {
return (IProject) getElement();
}
}
/**
* Copyright (c) 2011 Cloudsmith Inc. and other contributors, as listed below.
* 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:
* Cloudsmith
* Aaron Digulla
*/
package com.pany.dsl.ui.preferences;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.TextProcessor;
import com.pany.dsl.DslException;
public class DslBuildJob extends Job {
private final IProject project;
private DslResourceLocator locator;
public DslBuildJob(String name, IProject project, DslResourceLocator locator) {
super(name);
this.project = project;
this.locator = locator;
}
public boolean isCoveredBy(DslBuildJob other) {
if (other.project == null) {
return true;
}
return project != null && project.equals(other.project);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
synchronized (getClass()) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
cancelExistingJobs();
}
try {
if (project != null) {
buildSingleProject( monitor );
} else {
buildAllProjects( monitor );
}
} catch (CoreException e) {
return e.getStatus();
} catch (OperationCanceledException e) {
return Status.CANCEL_STATUS;
} finally {
monitor.done();
}
return Status.OK_STATUS;
}
private void buildAllProjects( IProgressMonitor monitor ) throws CoreException {
monitor.beginTask(Messages.DslBuildJob_Build_All, 2);
IWorkspace workspace = ResourcesPlugin.getWorkspace();
touchAllDslResource( workspace, new SubProgressMonitor( monitor, 1 ) );
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD,
new SubProgressMonitor(monitor, 1));
}
private void buildSingleProject( IProgressMonitor monitor ) throws CoreException {
monitor.beginTask( getName(), 3 );
touchAllDslResources( project, new SubProgressMonitor( monitor, 1 ) );
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD,
new SubProgressMonitor(monitor, 1));
project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, new SubProgressMonitor(monitor, 1));
}
private void cancelExistingJobs() {
Job[] buildJobs = Job.getJobManager().find(ResourcesPlugin.FAMILY_MANUAL_BUILD);
for (int i = 0; i < buildJobs.length; i++) {
if (buildJobs[i] != this && buildJobs[i] instanceof DslBuildJob) {
DslBuildJob job = (DslBuildJob) buildJobs[i];
if (job.isCoveredBy(this)) {
buildJobs[i].cancel();
}
}
}
}
private void touchAllDslResource( IWorkspace workspace, IProgressMonitor monitor ) {
IProject[] projects = workspace.getRoot().getProjects();
IProgressMonitor perProjectMonitor = new SubProgressMonitor( monitor, projects.length );
for( IProject project : projects ) {
if( ! project.isOpen() ) {
continue;
}
touchAllDslResources( project, new SubProgressMonitor( perProjectMonitor, 1 ) );
}
}
private void touchAllDslResources( IProject project, IProgressMonitor monitor ) {
final List<IFile> files = locator.findDslResources( project );
IFile file = null;
try {
monitor.beginTask( String.format(
Messages.DslBuildJob_Touching_resources,
TextProcessor.process(project.getName(), ":.")), //$NON-NLS-1$
files.size());
for( int i=0; i<files.size(); i++ ) {
file = files.get( i );
file.touch( new SubProgressMonitor( monitor, 1 ) );
}
} catch( CoreException e ) {
throw new DslException( "Error touching " + file, e ); //$NON-NLS-1$
} finally {
monitor.done();
}
}
@Override
public boolean belongsTo(Object family) {
return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
}
}
/**
* Copyright (c) 2011 Cloudsmith Inc. and other contributors, as listed below.
* 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:
* Cloudsmith
* Aaron Digulla
*/
package com.pany.dsl.ui.preferences;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import com.pany.dsl.DslException;
import com.google.common.collect.Lists;
public class DslResourceLocator {
private static Logger log = Logger.getLogger( DslResourceLocator.class );
public List<IFile> findDslResources( IContainer parent ) {
final List<IFile> files = Lists.newArrayList();
if( null == parent ) {
return files;
}
final IPath out = getOutputLocation( parent );
// System.out.println( "out=" + out );
IResourceVisitor visitor = new IResourceVisitor() {
@Override
public boolean visit( IResource resource ) throws CoreException {
if( resource.getType() == IResource.FILE ) {
IFile file = (IFile) resource;
if( includeFile( file ) ) {
files.add( file );
}
} else if (resource.getType() == IResource.FOLDER ) {
IPath path = resource.getProjectRelativePath();
// System.out.println( "path=" + path );
if( out != null && out.isPrefixOf( path ) ) {
return false;
}
}
return true;
}
};
try {
parent.accept( visitor );
} catch( CoreException e ) {
throw new DslException( "Error getting list of files from " + parent.getFullPath(), e ); //$NON-NLS-1$
}
return files;
}
protected boolean includeFile( IFile file ) {
return file.getName().endsWith( ".i18n" ); //$NON-NLS-1$
}
private IPath getOutputLocation( IContainer parent ) {
IPath result = null;
if( parent instanceof IProject ) {
IProject project = (IProject) parent;
if( hasJavaNature( project ) ) {
IJavaProject javaProject = JavaCore.create( project );
try {
result = javaProject.getOutputLocation();
result = result.makeRelativeTo( javaProject.getPath() );
} catch( JavaModelException e ) {
// Should not happen
log.error( "Unable to determine output location of Java project " + project.getProject().getName(), e ); //$NON-NLS-1$
}
}
}
return result;
}
// TODO I couldn't find a public API to do this check
@SuppressWarnings( "restriction" )
protected boolean hasJavaNature( IProject project ) {
return org.eclipse.jdt.internal.core.JavaProject.hasJavaNature( project );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment