/*******************************************************************************
* Copyright (c) 2005 RadRails.org and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.radrails.rails.ui;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.progress.UIJob;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import org.radrails.rails.core.IRailsConstants;
import org.radrails.rails.internal.core.RailsPlugin;
import org.radrails.rails.internal.ui.RailsProjectListener;
import org.radrails.rails.internal.ui.RailsShellOpenJob;
import org.radrails.rails.internal.ui.autotest.AutotestManager;
import org.radrails.rails.internal.ui.tail.TailConsoleManager;
import org.rubypeople.rdt.core.ILoadpathEntry;
import org.rubypeople.rdt.core.IRubyProject;
import org.rubypeople.rdt.core.ISourceFolder;
import org.rubypeople.rdt.core.ISourceFolderRoot;
import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.ui.RubyExplorerTracker;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.ui.PreferenceConstants;
import com.aptana.ide.core.db.EventInfo;
import com.aptana.ide.core.db.EventLogger;
import com.aptana.rdt.AptanaRDTPlugin;
import com.aptana.rdt.core.gems.Gem;
import com.aptana.rdt.core.gems.IGemManager;
/**
* Plugin class for the rails.ui plugin.
*
* @author mkent
*/
public class RailsUIPlugin extends AbstractUIPlugin
{
/**
* Whether or not to show jobs in progress view/bar. If false, jobs will be set to "System" so they won't get shown.
*/
private static final boolean DISPLAY_JOBS = true;
private static RailsUIPlugin instance;
private static final String PLUGIN_ID = "org.radrails.rails.ui";
private static Hashtable<String, Image> images = new Hashtable<String, Image>();
private AutotestManager fAutotestManager;
private RailsProjectListener fRailsListener;
// TODO When/if the RailsDBConnector is working properly then uncomment this.
// private RailsDBConnector connector;
private ServiceTracker gemManagerTracker;
/**
* Default constructor.
*/
public RailsUIPlugin()
{
super();
instance = this;
}
/**
* getImage
*
* @param path
* @return Image
*/
public static Image getImage(String path)
{
if (images.get(path) == null)
{
ImageDescriptor id = getImageDescriptor(path);
if (id == null)
{
return null;
}
Image i = id.createImage();
images.put(path, i);
return i;
}
else
{
return (Image) images.get(path);
}
}
/**
* Returns the singleton instance of the plugin.
*
* @return - the plugin
*/
public static RailsUIPlugin getInstance()
{
return instance;
}
/**
* Returns an image descriptor for the image file at the given plug-in relative path.
*
* @param path
* the path
* @return the image descriptor
*/
public static ImageDescriptor getImageDescriptor(String path)
{
return AbstractUIPlugin.imageDescriptorFromPlugin(PLUGIN_ID, path);
}
/**
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*/
public void start(final BundleContext context) throws Exception
{
super.start(context);
gemManagerTracker = new ServiceTracker(context, IGemManager.class.getName(), null);
gemManagerTracker.open();
// TODO Only register AutoTestManager as resource listener if it's being used
fAutotestManager = new AutotestManager();
ResourcesPlugin.getWorkspace().addResourceChangeListener(fAutotestManager, IResourceChangeEvent.POST_CHANGE);
getPreferenceStore().addPropertyChangeListener(fAutotestManager);
// Listen for imported projects and if they look like rails projects, add the rails nature
fRailsListener = new RailsProjectListener();
ResourcesPlugin.getWorkspace().addResourceChangeListener(fRailsListener,
IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.POST_CHANGE);
// Simplification of RadRails perspective. Do not show the Rails Shell initially.
// Job job = new RailsShellOpenJob(context);
// job.setSystem(!DISPLAY_JOBS);
// job.schedule(1000);
Job job = new Job("Start DB Core plugin")
{
@Override
protected IStatus run(IProgressMonitor monitor)
{
// Force the DB plugin to load so that derby will start up
try
{
Platform.getBundle("org.radrails.db.core").loadClass("org.radrails.db.core.DatabasePlugin"); // force
// DB
// plugin
// to
// load
}
catch (Exception e)
{
// ignore
}
return Status.OK_STATUS;
}
};
job.setSystem(!DISPLAY_JOBS);
job.schedule(1000);
// TODO When/if the RailsDBConnector is working properly then uncomment this.
// connector = new RailsDBConnector();
job = new Job("Record number of rails projects")
{
@Override
protected IStatus run(IProgressMonitor monitor)
{
int count = RailsPlugin.getRailsProjects().size();
EventLogger.getInstance().logEvent("rails.project.count", Integer.toString(count));
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
/**
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception
{
try
{
gemManagerTracker.close();
ResourcesPlugin.getWorkspace().removeResourceChangeListener(fAutotestManager);
getPreferenceStore().removePropertyChangeListener(fAutotestManager);
// save pref store - for autotest
IPersistentPreferenceStore ppStore = (IPersistentPreferenceStore) getPreferenceStore();
ppStore.save();
ResourcesPlugin.getWorkspace().removeResourceChangeListener(fRailsListener);
TailConsoleManager.getInstance().stopAll();
// TODO When/if the RailsDBConnector is working properly then uncomment this.
// connector.stop();
}
finally
{
super.stop(context);
}
}
/**
* getGemManager
*
* @return - gem manager
*/
public IGemManager getGemManager()
{
return (IGemManager) gemManagerTracker.getService();
}
/**
* getAutotestManager
*
* @return - autotest manager
*/
public AutotestManager getAutotestManager()
{
return fAutotestManager;
}
/**
* Get plugin identifier
*
* @return - plugin id
*/
public static String getPluginIdentifier()
{
return PLUGIN_ID;
}
/**
* getFileContents
*
* @param path
* @return - string file contents
*/
public String getFileContents(String path)
{
BufferedReader reader = null;
try
{
reader = new BufferedReader(new InputStreamReader(FileLocator
.openStream(getBundle(), new Path(path), false)));
StringBuffer buffer = new StringBuffer();
String line = null;
while ((line = reader.readLine()) != null)
{
buffer.append(line);
buffer.append("\n");
}
return buffer.toString();
}
catch (IOException e)
{
RailsUILog.log(e);
}
finally
{
try
{
if (reader != null)
reader.close();
}
catch (IOException e)
{
// ignore
}
}
return "";
}
/**
* Gets selected rails project
*
* @return - selected project
*/
public IProject getSelectedRailsProject()
{
return getProjectTracker().getSelectedByNatureID(IRailsConstants.RAILS_PROJECT_NATURE);
}
private RubyExplorerTracker getProjectTracker()
{
return RubyPlugin.getDefault().getProjectTracker();
}
/**
* Gets selected rails or ruby project
*
* @return - rails or ruby selected project
*/
public IProject getSelectedRailsOrRubyProject()
{
IProject retVal = getSelectedRailsProject();
if (retVal != null)
return retVal;
return getProjectTracker().getSelectedRubyProject();
}
/**
* getSelectedOrOnlyRailsProject
*
* @return - project
*/
public static IProject getSelectedOrOnlyRailsProject()
{
IProject project = RailsUIPlugin.getInstance().getSelectedRailsOrRubyProject();
if (project != null)
return project;
Set<IProject> projects = RailsPlugin.getRailsProjects();
if (projects != null && projects.size() == 1)
{
return projects.iterator().next();
}
return null;
}
/**
* Adds the default rails loadpaths
*
* @param rubyProject
* @param monitor
* @throws RubyModelException
*/
public static void addDefaultRailsLoadpaths(IRubyProject rubyProject, IProgressMonitor monitor)
throws RubyModelException
{
List<ILoadpathEntry> list = new ArrayList<ILoadpathEntry>();
IProject project = rubyProject.getProject();
list.add(RubyCore.newSourceEntry(project.getFullPath())); // Entry for project as src folder root
ILoadpathEntry[] jreEntries = PreferenceConstants.getDefaultRubyVMLibrary(); // Default Ruby libraries
for (int i = 0; i < jreEntries.length; i++)
{
list.add(jreEntries[i]);
}
rubyProject.setRawLoadpath(list.toArray(new ILoadpathEntry[list.size()]), monitor);
// ROR-292 Grab the version of rails that is stated in config/environment.rb! And then figure out what versions
// of the other gems that needs!
String version = RailsPlugin.getRailsVersion(project);
if (version != null)
{
Gem railsGem = new Gem("rails", version, "n/a");// tack the version onto the end of rails, but then we need
// to check dependencies....
AptanaRDTPlugin.addGemLoadPath(rubyProject, railsGem, monitor);
}
else
{
AptanaRDTPlugin.log("Unable to get the version number for rails for project: "
+ rubyProject.getElementName());
}
}
/**
* Has rails frozen in vendor
*
* @param rubyProject
* @return - true if has rails frozen in vendor
*/
public static boolean hasRailsFrozenInVendor(IRubyProject rubyProject)
{
ISourceFolderRoot root = rubyProject.getSourceFolderRoot(rubyProject.getProject());
ISourceFolder folder = root.getSourceFolder(new String[] { "vendor", "rails" });
if (folder == null)
return false;
return folder.exists();
}
public static void overrideDocumentRoot(IProject project) throws CoreException
{
project.setPersistentProperty(
new QualifiedName("", "com.aptana.ide.editor.html.preview.HTML_PREVIEW_OVERRIDE"), "true"); // HTMLPreviewConstants.HTML_PREVIEW_OVERRIDE
project.setPersistentProperty(new QualifiedName("", "com.aptana.ide.editor.html.preview.CONTEXT_ROOT"),
"/public"); // HTMLPreviewConstants.CONTEXT_ROOT
}
}