/* * Author: Markus Barchfeld * * Copyright (c) 2004 RubyPeople. * * This file is part of the Ruby Development Tools (RDT) plugin for eclipse. RDT * is subject to the "Common Public License (CPL) v 1.0". You may not use RDT * except in compliance with the License. For further information see * org.rubypeople.rdt/rdt.license. */ package org.rubypeople.rdt.internal.ui; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.util.ListenerList; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.IFileEditorMapping; import org.eclipse.ui.IPropertyListener; import org.eclipse.ui.internal.WorkbenchPlugin; import org.rubypeople.rdt.ui.RubyUI; /** * RubyViewerFilter uses the Editor mappings for recognising and filtering files * Both Editor mappings from plugin.xml and creating using the preferences page * are considered */ public class RubyFileMatcher { private static final String RUBY = "ruby"; private static final String SHEBANG = "#!"; public static final int PROP_MATCH_CRITERIA = 1; private String[] rubyFileExtensions; private String[] rubyFileNames; private ListenerList propChangeListeners; private IPropertyListener propertyListener = new IPropertyListener() { public void propertyChanged(Object source, int property) { if (property == IEditorRegistry.PROP_CONTENTS && source instanceof IEditorRegistry) { createFileExtensions(); firePropertyChange(PROP_MATCH_CRITERIA); } } }; /** * The set of files that are generally associated with Ruby, but aren't * editable by the RubyEditor (they're not ruby code) */ private static Set RUBY_NON_EDITABLE_EXTENSIONS = new HashSet(); static { RUBY_NON_EDITABLE_EXTENSIONS.add("yaml"); RUBY_NON_EDITABLE_EXTENSIONS.add("yml"); RUBY_NON_EDITABLE_EXTENSIONS.add("rhtml"); RUBY_NON_EDITABLE_EXTENSIONS.add("gem"); RUBY_NON_EDITABLE_EXTENSIONS.add("gemspec"); } public RubyFileMatcher() { propChangeListeners = new ListenerList(); this.createFileExtensions(); WorkbenchPlugin.getDefault().getEditorRegistry().addPropertyListener( propertyListener); } public void addPropertyChangeListener(IPropertyListener propListener) { propChangeListeners.add(propListener); } private void firePropertyChange(final int type) { Object[] array = propChangeListeners.getListeners(); for (int nX = 0; nX < array.length; nX++) { final IPropertyListener l = (IPropertyListener) array[nX]; Platform.run(new SafeRunnable() { public void run() { l.propertyChanged(this, type); } }); } } public void createFileExtensions() { List extensions = new ArrayList(); extensions.addAll(createDefaultExtensions()); List filenames = new ArrayList(); filenames.addAll(createDefaultFilenames()); IFileEditorMapping[] mappings = WorkbenchPlugin.getDefault() .getEditorRegistry().getFileEditorMappings(); for (int i = 0; i < mappings.length; i++) { IFileEditorMapping mapping = mappings[i]; IEditorDescriptor[] editors = mapping.getEditors(); for (int j = 0; j < editors.length; j++) { IEditorDescriptor descriptor = editors[j]; if (descriptor.getId().equals(RubyUI.ID_RUBY_EDITOR)) { // a mapping can also use a filename instead of a suffix if (mapping.getExtension() != null && mapping.getExtension().length() != 0) { extensions.add(mapping.getExtension()); break; } if (mapping.getName() != null && mapping.getName().length() != 0) { filenames.add(mapping.getName()); break; } } } } this.rubyFileExtensions = (String[]) extensions .toArray(new String[extensions.size()]); this.rubyFileNames = (String[]) filenames.toArray(new String[filenames .size()]); } /** * The default list of full filenames for ruby related files. * * @return a Collection of filenames associated with ruby projects. */ private Collection createDefaultFilenames() { Set set = new HashSet(); set.add("Rakefile"); return set; } /** * The default list of file extensions for ruby related files. * * @return a Collection of file extensions associated with ruby files. */ private Collection createDefaultExtensions() { return RUBY_NON_EDITABLE_EXTENSIONS; } public boolean hasRubyEditorAssociation(IFile file) { String fileExtension = file.getFileExtension(); for (int i = 0; i < rubyFileExtensions.length; i++) { if (rubyFileExtensions[i].equalsIgnoreCase(fileExtension)) { return true; } } String fileName = file.getName(); for (int i = 0; i < rubyFileNames.length; i++) { if (rubyFileNames[i].equalsIgnoreCase(fileName)) { return true; } } return containsRubyShebang(file); } /** * Read the first line and check for '#!' and 'ruby' If we find them, assume * this is a ruby file. * * @param file * The file to check * @return */ private boolean containsRubyShebang(IFile file) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(file .getContents())); String firstLine = reader.readLine(); if (firstLine == null) return false; if (firstLine.indexOf(SHEBANG) > -1 && firstLine.indexOf(RUBY) > -1) return true; } catch (CoreException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (reader != null) reader.close(); } catch (IOException e) { e.printStackTrace(); } } return false; } }