eclipse 源码泛读
eclipse的入口插件:
org.eclipse.platform ?
产品的定义,用到的图标,外观的定义都在这里,plugin.xml绑定一个application
这里没有代码,只是样式、图标。
org.eclipse.ui.ide.application
该插件是eclipse的真正入口,
主要的类有:
IDEApplication.java ? ?IDEWorkbenchAdvisor.java ??IDEWorkbenchWindowAdvisor.java?
ResourcePerspective.java ?
这几个类大家应该都很属性。
不过没有ActionBarAdvisor的定义,说明eclipse中所有的菜单、工具栏,在启动的时候是为空的。
里面的菜单都是其它插件扩展得到的。
?
接下来进入org.eclipse.core.runtime ?看看。
?
这里主要用到了 ?osgi ?equinox ? ?java.io ?java.net ?
?
Platform ?对该类进行了包装 ?InternalPlatform ? ? ?
InternalPlatform ? ?中使用了个单利模式。
eclipse 也大量运用了单利模式。
?
public IAdapterManager getAdapterManager() {
assertInitialized();
return AdapterManager.getDefault();
}
?
查看代码可知 ?如何名称相同的bundle 会返回第一个被加载的bundle。
?
public Bundle getBundle(String symbolicName) {
PackageAdmin packageAdmin = getBundleAdmin();
if (packageAdmin == null)
return null;
Bundle[] bundles = packageAdmin.getBundles(symbolicName, null);
if (bundles == null)
return null;
//Return the first bundle that is not installed or uninstalled
for (int i = 0; i < bundles.length; i++) {
if ((bundles[i].getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) {
return bundles[i];
}
}
return null;
}
?
?
该插件也相当于eclipse的 发动机了,服务的启动、停止、文件的加载等,都是在这里处理的。
?
?
下了看一下 ??org.eclipse.ui ?插件。
该插件有点出乎意料
只有两个类UIPlugin ??UIPreferenceInitializer
?
UIPlugin ? 中用到了 ?PrefUtil ?这个类是对preferences操作的一个工具类,用着还是很方便的。
PrefUtil .getInternalPreferenceStore(); 直接得到 系统?IPreferenceStore
?
UIPreferenceInitializer 为eclipse ?初始化一些参数,它是在这里定义的。
?
? ?<extension
? ? ? ? ?point="org.eclipse.core.runtime.preferences">
? ? ? <initializer
? ? ? ? ? ? src="/img/2012/06/25/111422766.bmp">
在看NewWizardAction 源码中看到了
LegacyResourceSupport类,这个类就是加载不同插件的class的。
这里也说明了不同插件(Bundle)是通过不同的类加载器加载的。
?
?
?IDialogSettings workbenchSettings = WorkbenchPlugin.getDefault()
? ? ? ? ? ? ? ? .getDialogSettings();
通过IDialogSettings ?可以对wizard的数据进行持久化到 xml,并进行状态保存。
?
?
?
?
An interface to a storage mechanism for making dialog settings persistent. The store manages a collection of key/value pairs. The keys must be strings and the values can be either, strings or array of strings. Convenience API to convert primitive types to strings is provided.
?
?
?
?
? ? NewWizard wizard = new NewWizard();
? ? ? ? wizard.setCategoryId(categoryId);
wizard.setWindowTitle(windowTitle);
?
? ? ? ? ISelection selection = workbenchWindow.getSelectionService()
? ? ? ? ? ? ? ? .getSelection();
? ? ? ? IStructuredSelection selectionToPass = StructuredSelection.EMPTY;
? ? ? ? if (selection instanceof IStructuredSelection) {
? ? ? ? ? ? selectionToPass = (IStructuredSelection) selection;
? ? ? ? } else {
? ? ? ? ? ? // @issue the following is resource-specific legacy code
? ? ? ? ? ? // Build the selection from the IFile of the editor
? ? ? ? ? ? Class resourceClass = LegacyResourceSupport.getResourceClass();
? ? ? ? ? ? if (resourceClass != null) {
? ? ? ? ? ? ? ? IWorkbenchPart part = workbenchWindow.getPartService()
? ? ? ? ? ? ? ? ? ? ? ? .getActivePart();
? ? ? ? ? ? ? ? if (part instanceof IEditorPart) {
? ? ? ? ? ? ? ? ? ? IEditorInput input = ((IEditorPart) part).getEditorInput();
? ? ? ? ? ? ? ? ? ? Object resource = Util.getAdapter(input, resourceClass);
? ? ? ? ? ? ? ? ? ? if (resource != null) {
? ? ? ? ? ? ? ? ? ? ? ? selectionToPass = new StructuredSelection(resource);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? wizard.init(workbenchWindow.getWorkbench(), selectionToPass);
?
? ? ? ? IDialogSettings workbenchSettings = WorkbenchPlugin.getDefault()
? ? ? ? ? ? ? ? .getDialogSettings();
? ? ? ? IDialogSettings wizardSettings = workbenchSettings
? ? ? ? ? ? ? ? .getSection("NewWizardAction"); //$NON-NLS-1$
? ? ? ? if (wizardSettings == null) {
wizardSettings = workbenchSettings.addNewSection("NewWizardAction"); //$NON-NLS-1$
}
? ? ? ? wizard.setDialogSettings(wizardSettings);
? ? ? ? wizard.setForcePreviousAndNextButtons(true);
?
? ? ? ? Shell parent = workbenchWindow.getShell();
? ? ? ? WizardDialog dialog = new WizardDialog(parent, wizard);
? ? ? ? dialog.create();
? ? ? ? dialog.getShell().setSize(
? ? ? ? ? ? ? ? Math.max(SIZING_WIZARD_WIDTH, dialog.getShell().getSize().x),
? ? ? ? ? ? ? ? SIZING_WIZARD_HEIGHT);
? ? ? ? PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(),
IWorkbenchHelpContextIds.NEW_WIZARD);
? ? ? ? dialog.open();
?
?
这是eclipse 打开一个创建对话框的代码,可以借鉴一下。
这个插件内的很多代码大家都可以在做插件开发中借鉴一下的。
?
所有的IHandler 都是通过
CommandAction ?来包装后执行的。
?
CommandAction ?这里的 源码,看看还是有些启发的。
?
public class CommandAction extends Action {
?
private IHandlerService handlerService = null;
?
private ParameterizedCommand parameterizedCommand = null;
?
private ICommandListener commandListener;
?
protected CommandAction() {
?
}
?
/**
* Creates the action backed by a command. For commands that don't take
* parameters.
*?
* @param serviceLocator
* ? ? ? ? ? ?The service locator that is closest in lifecycle to this
* ? ? ? ? ? ?action.
* @param commandIdIn
* ? ? ? ? ? ?the command id. Must not be <code>null</code>.
*/
public CommandAction(IServiceLocator serviceLocator, String commandIdIn) {
this(serviceLocator, commandIdIn, null);
}
?
/**
* Creates the action backed by a parameterized command. The parameterMap
* must contain only all required parameters, and may contain the optional
* parameters.
*?
* @param serviceLocator
* ? ? ? ? ? ?The service locator that is closest in lifecycle to this
* ? ? ? ? ? ?action.
* @param commandIdIn
* ? ? ? ? ? ?the command id. Must not be <code>null</code>.
* @param parameterMap
* ? ? ? ? ? ?the parameter map. May be <code>null</code>.
*/
public CommandAction(IServiceLocator serviceLocator, String commandIdIn,
Map parameterMap) {
if (commandIdIn == null) {
throw new NullPointerException("commandIdIn must not be null"); //$NON-NLS-1$
}
init(serviceLocator, commandIdIn, parameterMap);
}
?
protected ICommandListener getCommandListener() {
if (commandListener == null) {
commandListener = new ICommandListener() {
public void commandChanged(CommandEvent commandEvent) {
if (commandEvent.isHandledChanged()
|| commandEvent.isEnabledChanged()) {
if (commandEvent.getCommand().isDefined()) {
setEnabled(commandEvent.getCommand().isEnabled());
}
}
}
};
}
return commandListener;
}
?
/**
* Build a command from the executable extension information.
*?
* @param commandService
* ? ? ? ? ? ?to get the Command object
* @param commandId
* ? ? ? ? ? ?the command id for this action
* @param parameterMap
*/
private void createCommand(ICommandService commandService,
String commandId, Map parameterMap) {
Command cmd = commandService.getCommand(commandId);
if (!cmd.isDefined()) {
WorkbenchPlugin.log("Command " + commandId + " is undefined"); //$NON-NLS-1$//$NON-NLS-2$
return;
}
?
if (parameterMap == null) {
parameterizedCommand = new ParameterizedCommand(cmd, null);
return;
}
?
parameterizedCommand = ParameterizedCommand.generateCommand(cmd,
parameterMap);
}
?
public void dispose() {
// not important for command ID, maybe for command though.
handlerService = null;
if (commandListener != null) {
parameterizedCommand.getCommand().removeCommandListener(
commandListener);
commandListener = null;
}
parameterizedCommand = null;
}
?
/*
* (non-Javadoc)
*?
* @see org.eclipse.jface.action.Action#runWithEvent(org.eclipse.swt.widgets.Event)
*/
public void runWithEvent(Event event) {
if (handlerService == null) {
String commandId = (parameterizedCommand == null ? "unknownCommand" //$NON-NLS-1$
: parameterizedCommand.getId());
WorkbenchPlugin.log("Cannot run " + commandId //$NON-NLS-1$
+ " before command action has been initialized"); //$NON-NLS-1$
return;
}
try {
if (parameterizedCommand != null) {
handlerService.executeCommand(parameterizedCommand, event);
}
} catch (Exception e) {
WorkbenchPlugin.log(e);
}
}
?
/*
* (non-Javadoc)
*?
* @see org.eclipse.jface.action.Action#run()
*/
public void run() {
// hopefully this is never called
runWithEvent(null);
}
?
protected void init(IServiceLocator serviceLocator, String commandIdIn,
Map parameterMap) {
if (handlerService != null) {
// already initialized
return;
}
handlerService = (IHandlerService) serviceLocator
.getService(IHandlerService.class);
ICommandService commandService = (ICommandService) serviceLocator
.getService(ICommandService.class);
ICommandImageService commandImageService = (ICommandImageService) serviceLocator
.getService(ICommandImageService.class);
?
createCommand(commandService, commandIdIn, parameterMap);
if (parameterizedCommand != null) {
setId(parameterizedCommand.getId());
setActionDefinitionId(parameterizedCommand.getId());
try {
setText(parameterizedCommand.getName());
} catch (NotDefinedException e) {
// if we get this far it shouldn't be a problem
}
parameterizedCommand.getCommand().addCommandListener(
getCommandListener());
parameterizedCommand.getCommand().setEnabled(
handlerService.getCurrentState());
setEnabled(parameterizedCommand.getCommand().isEnabled());
setImageDescriptor(commandImageService.getImageDescriptor(
commandIdIn, ICommandImageService.TYPE_DEFAULT));
setDisabledImageDescriptor(commandImageService.getImageDescriptor(
commandIdIn, ICommandImageService.TYPE_DISABLED));
setHoverImageDescriptor(commandImageService.getImageDescriptor(
commandIdIn, ICommandImageService.TYPE_HOVER));
}
}
?
protected ParameterizedCommand getParameterizedCommand() {
return parameterizedCommand;
}
?
public String getActionDefinitionId() {
return super.getActionDefinitionId();
}
}
?
?
?还有org.eclipse.ui.internal.WorkbenchWindow ? ?
这个就是我们的rcp 窗口的实现类。
继承 jface?ApplicationWindow 。
?
?
接下来我们研究一下扩展定义的信息eclipse 是在哪里调用里面的信息,并动态的调用代码?
?
?
?
以action 为例?
?
可以在eclipse 作为菜单、工具栏、弹出菜单 有很几个扩展点都可以实现。
?
看eclipse ?是如何使用扩展的配置信息的。
入口肯定在
?
org.eclipse.ui.internal.WorkbenchWindow?
?
?
?
private final void initializeDefaultServices() {
serviceLocator.registerService(IWorkbenchLocationService.class,
new WorkbenchLocationService(IServiceScopes.WINDOW_SCOPE,
getWorkbench(), this, null, null, null, 1));
// added back for legacy reasons
serviceLocator.registerService(IWorkbenchWindow.class, this);
final ActionCommandMappingService mappingService = new ActionCommandMappingService();
serviceLocator.registerService(IActionCommandMappingService.class,
mappingService);
?
final LegacyActionPersistence actionPersistence = new LegacyActionPersistence(
this);
serviceLocator.registerService(LegacyActionPersistence.class,
actionPersistence);
actionPersistence.read(); ?//关键是这行代码。
?
}
这个是初始化方法。
?
?
方法的内容:
?
public final void read() {
clear();
LegacyActionPersistence.super.read();
?
// 创建 extension registry ?
final IExtensionRegistry registry = Platform.getExtensionRegistry();
int actionSetCount = 0;
int editorContributionCount = 0;
int objectContributionCount = 0;
int viewContributionCount = 0;
int viewerContributionCount = 0;
final IConfigurationElement[][] indexedConfigurationElements = new IConfigurationElement[5][];
?
// 1 ? ?actionSets??extension point.
final IConfigurationElement[] actionSetsExtensionPoint = registry
.getConfigurationElementsFor(EXTENSION_ACTION_SETS);
for (int i = 0; i < actionSetsExtensionPoint.length; i++) {
final IConfigurationElement element = actionSetsExtensionPoint[i];
final String name = element.getName();
if (TAG_ACTION_SET.equals(name)) {
addElementToIndexedArray(element, indexedConfigurationElements,
INDEX_ACTION_SETS, actionSetCount++);
}
}
?
// 2 ? ? editorActions extension point.
final IConfigurationElement[] editorActionsExtensionPoint = registry
.getConfigurationElementsFor(EXTENSION_EDITOR_ACTIONS);
for (int i = 0; i < editorActionsExtensionPoint.length; i++) {
final IConfigurationElement element = editorActionsExtensionPoint[i];
final String name = element.getName();
if (TAG_EDITOR_CONTRIBUTION.equals(name)) {
addElementToIndexedArray(element, indexedConfigurationElements,
INDEX_EDITOR_CONTRIBUTIONS, editorContributionCount++);
}
}
?
// ? ? popupMenus extension point.
final IConfigurationElement[] popupMenusExtensionPoint = registry
.getConfigurationElementsFor(EXTENSION_POPUP_MENUS);
for (int i = 0; i < popupMenusExtensionPoint.length; i++) {
final IConfigurationElement element = popupMenusExtensionPoint[i];
final String name = element.getName();
? ? ? ? ? ? ? ? ? ? ? ?//3 ?TAG_OBJECT_CONTRIBUTION
if (TAG_OBJECT_CONTRIBUTION.equals(name)) {
addElementToIndexedArray(element, indexedConfigurationElements,
INDEX_OBJECT_CONTRIBUTIONS, objectContributionCount++);
? ? ? ? ? ? ? ? ? ???//4 ?TAG_OBJECT_CONTRIBUTION
} else if (TAG_VIEWER_CONTRIBUTION.equals(name)) {
addElementToIndexedArray(element, indexedConfigurationElements,
INDEX_VIEWER_CONTRIBUTIONS, viewerContributionCount++);
}
}
?
// 4 ? viewActions extension point.
final IConfigurationElement[] viewActionsExtensionPoint = registry
.getConfigurationElementsFor(EXTENSION_VIEW_ACTIONS);
for (int i = 0; i < viewActionsExtensionPoint.length; i++) {
final IConfigurationElement element = viewActionsExtensionPoint[i];
final String name = element.getName();
if (TAG_VIEW_CONTRIBUTION.equals(name)) {
addElementToIndexedArray(element, indexedConfigurationElements,
INDEX_VIEW_CONTRIBUTIONS, viewContributionCount++);
}
}
?
readActionSets(indexedConfigurationElements[INDEX_ACTION_SETS],
actionSetCount);
readEditorContributions(
indexedConfigurationElements[INDEX_EDITOR_CONTRIBUTIONS],
editorContributionCount);
readObjectContributions(
indexedConfigurationElements[INDEX_OBJECT_CONTRIBUTIONS],
objectContributionCount);
readViewContributions(
indexedConfigurationElements[INDEX_VIEW_CONTRIBUTIONS],
viewContributionCount);
readViewerContributions(
indexedConfigurationElements[INDEX_VIEWER_CONTRIBUTIONS],
viewerContributionCount);
}
?
?
代码解释:
final IConfigurationElement[][] indexedConfigurationElements = new IConfigurationElement[5][];
这里一共有5中action的定义,所有这里的2维数组 ?的第一个参数为5了。
?
?
addElementToIndexedArray(element, indexedConfigurationElements,
INDEX_ACTION_SETS, actionSetCount++);
把读出来的?IConfigurationElement element ?添加到对应 ?indexedConfigurationElements 二维数组中。
?
然后分别调用
?
readActionSets(indexedConfigurationElements[INDEX_ACTION_SETS],
actionSetCount);
readEditorContributions(
indexedConfigurationElements[INDEX_EDITOR_CONTRIBUTIONS],
editorContributionCount);
readObjectContributions(
indexedConfigurationElements[INDEX_OBJECT_CONTRIBUTIONS],
objectContributionCount);
readViewContributions(
indexedConfigurationElements[INDEX_VIEW_CONTRIBUTIONS],
viewContributionCount);
readViewerContributions(
indexedConfigurationElements[INDEX_VIEWER_CONTRIBUTIONS],
viewerContributionCount);
?
对不同的action进行 初始化。
?
进入readActionSets中。
?
private final void readActionSets(
final IConfigurationElement[] configurationElements,
final int configurationElementCount) {
//?
// this was an even dumber fix than modifying the path
//?
// stupid navigate group
// SGroup nav = menuService.getGroup(STUPID_NAVIGATE);
// if (!nav.isDefined()) {
// nav.define(new SLocation(new SBar(SBar.TYPE_MENU, null)));
// }
// stupid navigate group
?
final List warningsToLog = new ArrayList(1);
?
for (int i = 0; i < configurationElementCount; i++) {
final IConfigurationElement element = configurationElements[i];
?
// Read the action set identifier.
final String id = readRequired(element, ATT_ID, warningsToLog,
"Action sets need an id"); //$NON-NLS-1$
if (id == null) {
continue;
}
?
// Read the label.
final String label = readRequired(element, ATT_LABEL,
warningsToLog, "Actions set need a label", //$NON-NLS-1$
id);
if (label == null) {
continue;
}
?
// Restrict the handler to when the action set is active.
final LegacyActionSetExpression expression = new LegacyActionSetExpression(
id, window);
?
?
// Read all of the child elements.
readActionsAndMenus(element, id,
warningsToLog, expression, null);
// Define the action set.
}
?
logWarnings(
warningsToLog,
"Warnings while parsing the action sets from the 'org.eclipse.ui.actionSets' extension point"); //$NON-NLS-1$
}
?
?
?
最后找到 ??WorkbenchMenuService ? 类中的populateContributionManager ?方法 具体把扩展点的信息?
添加到了 具体的 ?menu中。
藏的好深。。。。
?
?
MenuLocationURI ?这个类是对 menu?[scheme]:[path]?[query] ?的包装。
?
?
从定义扩展点 到 ?对扩展点的 调用 ?中间包装了很多层。 好多都是以service的形式提供的。
?
?