??xml version="1.0" encoding="utf-8" standalone="yes"?>
本文用eclipse的自动重构功能对一个程序实例进行重构,目的是探索Eclipse自动重构可以在多大程度上辅助重构q个q程。程序实例用《RefactoringQImproving the Design of Existing Code》一书中的例子?BR>
Eclipse的自动重构功能能够很好地支持各种E序元素的重命名Qƈ自动更新相关的引用。Eclipse能够支持Ҏ(gu)、字D在cM间移动,q自动更新引用。Eclipse较好地支持内联字Dc(din)函数的更新替换。Eclipse较好地支持抽取方法、变量等E序元素?BR>
重构的过E是一个不断尝试和探烦(ch)的过E。Eclipse的重构支持撤销和重做,q且能够预览重构l果Q这些是很实用的功能?BR>
Eclipse的重命名、抽取方法、移动、内联功能、更Ҏ(gu)法特征符{代码结构别的重构Ҏ(gu)Q是比较成熟同时也值得使用的功能。至于设计结构上的重构,eclipseq(sh)能很好地支持。但是作者相信,自动重构的理念应该是"工具辅助下的重构工作"Qh仍然承担大部分重构工作?BR>
一、预备工?/B>
本文使用《RefactoringQImproving the Design of Existing Code》一书第一章的例子。重构前的代码及(qing)每一步重构后的代码见附g。读者最好配合《RefactoringQImproving the Design of Existing Code》一书阅L文?BR>
Eclipse使用如下版本Q?BR>
同时安装?jin)中文语a包?BR>
二、重构第一步:(x)分解qlstatement()
目的Q?BR>
1?把statement()函数中的swich语句提炼到独立的函数amountFor()中?BR>
2?修改amountFor()参数命名
重构Ҏ(gu)Q?BR>
Extract Method
Rename Method
Ҏ(gu)Q?BR>
1、选中swich语句的代码块Q在右键菜单中选择"重构/抽取Ҏ(gu)"Q出现参数对话框。Eclipse自动分析代码块中的局部变量,扑ֈ?jin)两个局部变量:(x)each和thisAmount。其中,each只是在代码块中被dQ但thisAmount?x)在代码块中被修攏V按照重构Extract Methodȝ出来的规则,应该把each当作抽取函数的参数、thisAmount当作抽取函数的返回倹{然而Eclipseq不做区分,直接把这两个变量当作抽取新方法的参数Q如图?BR>
我们的目的是把在抽取函数中不?x)被修改的each作ؓ(f)参数Q会(x)被修改的thisAmount作ؓ(f)q回倹{解决的办法是,?double thisAmount = 0; q行代码Udswitch语句的上面,变成q样Q?BR>
double thisAmount = 0;
switch(each.getMovie().getPriceCode()){
case Movie.REGULAR:
thisAmount += 2;
if(each.getDaysRented()>2)
thisAmount += (each.getDaysRented()-2)*1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented()*3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if(each.getDaysRented()>3)
thisAmount += (each.getDaysRented()-3)*1.5;
break;
}
选中q段代码Q在右键菜单中选择"重构/抽取Ҏ(gu)"Qeclipseq次变得聪明点了(jin)Q如图?BR>
选择"预览"按钮预先查看重构后的l果Q符合我们最初的目的?BR>
选择"定"按钮Q重构后的代码片断如下:(x)
public String statement() {
double totalAmount = 0;
int frequentRenterPoints = 0;
Enumeration rentals = _rentals.elements();
String result = "Rental Record for " + getName() + "\n";
while(rentals.hasMoreElements()){
Rental each = (Rental)rentals.nextElement();
double thisAmount = amountFor(each);
frequentRenterPoints ++;
if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE &&each.getDaysRented()>1)
frequentRenterPoints ++;
result += "\t" + each.getMovie().getTitle() + "\t" +String.valueOf(thisAmount) + "\n";
totalAmount += thisAmount;
}
result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";
return result;
}
/**
* @param each
* @return
*/
private double amountFor(Rental each) {
double thisAmount = 0;
switch(each.getMovie().getPriceCode()){
case Movie.REGULAR:
thisAmount += 2;
if(each.getDaysRented()>2)
thisAmount += (each.getDaysRented()-2)*1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented()*3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if(each.getDaysRented()>3)
thisAmount += (each.getDaysRented()-3)*1.5;
break;
}
return thisAmount;
}
2、选中amountFor()的参数eachQ在右键菜单中选择"重构/重命?Q在对话框中输入新的名称QaRentalQ选择定QamountFor()中所有each的引用全部被替换成新的名U。用同样的办法修改amountFor()中的局部变量thisAmount为result。重构后的amountFor()代码如下Q?BR>
/**
* @param aRental
* @return
*/
private double amountFor(Rental aRental) {
double result = 0;
switch(aRental.getMovie().getPriceCode()){
case Movie.REGULAR:
result += 2;
if(aRental.getDaysRented()>2)
result += (aRental.getDaysRented()-2)*1.5;
break;
case Movie.NEW_RELEASE:
result += aRental.getDaysRented()*3;
break;
case Movie.CHILDRENS:
result += 1.5;
if(aRental.getDaysRented()>3)
result += (aRental.getDaysRented()-3)*1.5;
break;
}
return result;
}
三、重构第二步Q搬U?金额计算"代码
目的Q?BR>
1?函数amountFor()转移到RentalcMQƈ更名为getCharge()?BR>
2?更新q替换所有对amountFor()的引用?BR>
重构Ҏ(gu)Q?BR>
Move Method
Change Method signatrue
Inline Method
Inline Temp
Ҏ(gu)Q?BR>
1、选中函数amountFor()的定义,在右键菜单中选择"重构/Ud"Q显C参数设|对话框。把新方法名Ҏ(gu)getCharge。按?定"按钮QCustomer Class中的amountFor()函数被移动到Rental Class中,q更名ؓ(f)QgetCharge()?BR>
同时eclipse自动在Customer的amountFor()函数中添加一行对新函数的"委托"代码Q?BR>
private double amountFor(Rental aRental) {
return aRental.getCharge();
}
q行代码?x)生编译错误,原因是amountFor()的private型被传递到?jin)新的方法中Q?BR>
/**
* @param this
* @return
*/
private double getCharge() {
…?BR> }
2、l重构!选中getCharge()Ҏ(gu)Q在右键菜单中选择"重构/更改Ҏ(gu)特征W?Q弹出参数选择对话框,把访问修饰符从privateҎ(gu)public。Eclipse的编译错误提C动消失?BR>
3、回到Customerc,把所有对amountFor()引用的地Ҏ(gu)换成直接对getCharge()的引用。选中Customercȝ函数amountFor(Rental aRental)Q在右键菜单中选择"重构/内联"Q出现参数选择对话框?BR>
选择"认"按钮Q引用amountFor()的地方被替换成对getCharge()的引用?BR>
public String statement() {
…?BR> double thisAmount = each.getCharge();
…?BR> }
4、除M(f)时变量thisAmount?BR>
选中变量thisAmountQ在右键菜单中选择"重构/内联"Q重构预览窗口如下,可见辑ֈ?jin)重构的目的。按?认"按钮重构代码?BR>
statement()代码Q?BR>
public String statement() {
double totalAmount = 0; // L贚w?BR> int frequentRenterPoints = 0; // 常客U点
Enumeration rentals = _rentals.elements();
String result = "Rental Record for " + getName() + "\n";
while(rentals.hasMoreElements()){
Rental each = (Rental)rentals.nextElement(); //取得一W租借记?BR>
// add frequent renter points(累加 常客U点)
frequentRenterPoints ++;
// add bouns for a two day new release rental
if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE && each.getDaysRented()>1)
frequentRenterPoints ++;
// show figures for this rental(昄此笔U借数?
result += "\t" + each.getMovie().getTitle() + "\t" +
String.valueOf(each.getCharge()) + "\n";
totalAmount += each.getCharge();
}
// add footer linesQ结打华ͼ(j)
result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";
return result;
}
四、重构第三步Q提?常客U点计算"代码
目的Q提?常客U点计算"代码q放在RentalcMQ?常客U点计算"代码如下?BR>
public String statement() {
…?BR> // add frequent renter points
frequentRenterPoints ++;
// add bouns for a two day new release rental
if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE && each.getDaysRented()>1)
frequentRenterPoints ++;
…?BR> }
重构后的代码如下Q?BR>
frequentRenterPoints += each.getFrequentRenterPoints();
重构Ҏ(gu)Q?BR>
Extract Method
Move Method
Change Method signatrue
Inline Method
Ҏ(gu)Q?BR>
1?首先Q抽取代码到独立的函C?BR>
?抽取Ҏ(gu)"重构代码Q函数名QgetFrequentRenterPoints。很遗憾Qeclipse的不能生成诸如:(x)frequentRenterPoints += getFrequentRenterPoints(Rental aRental); 的代码。原因是执行自增操作的局部变量frequentRenterPoints要出现在{式双Q因此抽取函数getFrequentRenterPoints()一定要把frequentRenterPoints作ؓ(f)参数。手工修改函数和对函数的引用Q重构后的代码如下:(x)
public String statement() {
…?BR> while(rentals.hasMoreElements()){
…?BR> frequentRenterPoints += getFrequentRenterPoints(each);
…?BR> }
…?BR> }
/**
* @param each
* @return
*/
private int getFrequentRenterPoints(Rental each) {
if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE && each.getDaysRented()>1)
return 2;
else
return 1;
}
2?把getFrequentRenterPointsQ)(j)Ud到RentalcM?BR>
3?对getFrequentRenterPointsQ)(j)"更改Ҏ(gu)特征W?为public?BR>
4?对Customer的函数getFrequentRenterPoints()执行内联操作Q重构目标完成?BR>
五、重构第四步Q去除(f)时变量(totalAmount和frequentRenterPointsQ?/B>
目的Q去除(f)时变量(totalAmount和frequentRenterPointsQ?BR>
Ҏ(gu)Q?BR>
1?分析totalAmount和frequentRenterPoints的定义和引用l构如下Q?BR>
// 声明和定?BR> double totalAmount = 0;
int frequentRenterPoints = 0;
…?BR> // 在@环中修改
while(rentals.hasMoreElements()){
…?BR> frequentRenterPoints += each.getFrequentRenterPoints();
…?BR> totalAmount += each.getCharge();
…?BR> }
…?BR> // 在@环外使用
result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";
…?BR>
上述两个变量在@环体外面定义和用,在@环中被修改,q用Replace Temp with QueryҎ(gu)去除q两个(f)时变量是一稍微复杂的重构。很遗憾Qeclipse目前不支持这L(fng)重构?BR>
2、手工修改代码?BR>
六、重构第五步Q运用多态取代与h相关的条仉辑
目的Q?BR>
1?把RentalcM的函数getCharge()Ud到MoviecM?BR>
2?把RentalcM的函数getFrequentRenterPoints()Ud到MoviecM?BR>
重构Ҏ(gu)Q?BR>
Move Method
Inline Method
Ҏ(gu)Q?BR>
1?选中RentalcM的函数getCharge()Q右键菜单选中"重构/Ud"Qeclipse提示找不到接收者,不能Ud。原因在于这行语句:(x)
switch(getMovie().getPriceCode()){//取得q出租h
选中getMovie()Q右键菜单选中"重构/内联"Q确定后代码成ؓ(f)Q?BR>
switch(_movie.getPriceCode()){ //取得q出租h
选中getCharge()Q执?重构/Ud"后,函数被移动到MoviecM。然而这只是部分达成?jin)重构目的,我们发现Q移动后的代码把Rental作ؓ(f)参数传给?jin)getCharge()Q手工修改一下,代码变成Q?BR>
class Movie …?BR> /**
* @param this
* @return
*/
public double getCharge(int _daysRented) {
double result = 0;
switch(getPriceCode()){ //取得q出租h
case Movie.REGULAR: // 普通片
result += 2;
if(_daysRented>2)
result += (_daysRented-2)*1.5;
break;
case Movie.NEW_RELEASE: // 新片
result += _daysRented*3;
break;
case Movie.CHILDRENS: // 儿童?BR> result += 1.5;
if(_daysRented>3)
result += (_daysRented-3)*1.5;
break;
}
return result;
}
class Rental…?BR> /**
* @param this
* @return
*/
public double getCharge() {
return _movie.getCharge(_daysRented);
}
2、用同样的步骤处理getFrequentRenterPoints()Q重构后的代码:(x)
class Movie …?BR> /**
* @param frequentRenterPoints
* @param this
* @return
*/
public int getFrequentRenterPoints(int daysRented) {
if((getPriceCode())==Movie.NEW_RELEASE && daysRented>1)
return 2;
else
return 1;
}
class Rental…?BR> /**
* @param frequentRenterPoints
* @param this
* @return
*/
public int getFrequentRenterPoints(int daysRented) {
if((getPriceCode())==Movie.NEW_RELEASE && daysRented>1)
return 2;
else
return 1;
}
七、重构第六步Q终于……我们来到?/B>
目的Q对switch语句引入state模式?BR>
Ҏ(gu)Q?BR>
很遗憾,不得不在q里提前l束eclipse的自动重构之旅。Eclipse几乎不能做结构上的重构。也许Martin Fowler在书中呼唤的自动重构工具止于"工具辅助下的重构工作"q一理念。艺术是人类的专利,~程艺术的梦惛_持箋(hu)下去?BR>
感兴的读者可以查看手工重构的最后一步代码。将重构q行到底Q?BR>
附录Qeclipse支持的重构方法(摘自eclipse中文帮助Q?BR>
![]() |
![]() |
QactionSet label="Sample Action Set" visible="true" id="myplugin.actionSet"Q?BR>Qmenu label="我的I间" id="sampleMenu"Q?BR>Qseparator name="sampleGroup"Q?BR>Q?separatorQ?BR>Q?menuQ?BR>Qaction label="天气预报" icon="icons/sample.gif" class="myplugin.actions.SampleAction" tooltip="Hello, Eclipse world" menubarPath="sampleMenu/sampleGroup" toolbarPath="sampleGroup" id="myplugin.actions.SampleAction"Q?BR>Q?actionQ?BR> |
![]() |
![]() |
![]() |
public void run(IAction action) { MessageDialog.openInformation( window.getShell(),"Myplugin Plug-in", "Hello, Eclipse world"); } |
public void run(IAction action) { WeatherDialog wd=new WeatherDialog(); wd.setSize(400, 335); wd.show(); } |
![]() |
![]() |
/* * Created on 2004-9-23 * */ package myplugin; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import javax.swing.JDialog; import javax.swing.JEditorPane; /** * QpQTitle: WatherDialogQ?pQ?BR>* QpQDescription: q个是对话框c,用于昄指定城市(jng)的当天的天气预报Q?pQ?BR>* QpQCopyright: Copyright (c) 2004Q?pQ?BR>* QpQCompany:UF SOFTQ?pQ?BR>* @author 赵勇 * @version 1.0 */ public class WatherDialog extends JDialog { String city="北京"; private JEditorPane jEditorPane = null; /** * This method initializes * / public WatherDialog(String city) { super(); this.city=city; initialize(); } /** * This method initializes this * @return void */ private void initialize() { this.setContentPane(getJEditorPane()); try { //构徏URL对象 URL url =new URL("http://weather.news.sina.com.cn//cgi-bin/figureWeather/simpleSearch.cgi?city="+city); String temp=""; BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); //使用openStream得到一输入ƈ由此构造一个BufferedReader对象 String inputLine; //从输入流不断的读数据Q直到读完ؓ(f)?BR>while ((inputLine = in.readLine()) != null) temp=temp+inputLine+"\n"; //关闭输入?BR>in.close(); String weather =temp.substring ( temp.indexOf( "Qbody"), temp.lastIndexOf( "bodyQ?)+5); this.jEditorPane .setText(weather); } catch (Exception e) { e.printStackTrace(); } this.setTitle("天气预报"); this.setSize(400, 166); } /** * This method initializes jEditorPane * * @return javax.swing.JEditorPane */ private JEditorPane getJEditorPane() { if (jEditorPane == null) { jEditorPane = new JEditorPane(); jEditorPane.setContentType( "text/html"); } return jEditorPane; } } // @jve:decl-index=0:visual-constraint="70,19" |
public void run(IAction action) { WeatherDialog wd=new WeatherDialog("北京"); wd.setSize(400, 335); wd.show(); } |
![]() |
如果你在上v或者其他城?jng),试着修改city参数?上v"Q再ơ运行,你将发现Q你仍然能够得到该城?jng)的天气预报Q这里我们从|站上提取的信息Q有Ҏ(gu)机取巧了(jin)Q。值得注意的是QXmethod|站提供?jin)一个天气预报的WebServiceQ可惜只有美国的城市(jng)Q不然我们可以用Web Service调用获取天气预报Q将?x)更酗?BR>
现在q行是工作台已经具备?jin)天气预报的功能Q还需要更q一步,改插g导出发布Q拷贝到Eclipse根目录的plugins目录中,重新启动Q具体参见Eclipse帮助Q。现在你自己的EclipseQ就具备?jin)天气预报的功能Q只要你点击鼠标Q就可以在编E之余轻杄获取天气信息?除非你的老板认ؓ(f)你在工作旉随时?jin)解天气情况不是一个好LQ我认ؓ(f)你完全可以将q个插gU_个h收藏的插件之列。你也可以在此基上扩展,增加一些配|文件和属性设|,定制出满p求的插g。如果能够增加信息的自动qo(h)和筛选,那将是一ơ很愉快的体验,如果你有旉和兴,不妨一试?/P>
3.邮g快速监控插?/B>
现在你的工作因ؓ(f)Eclipse而更加惬意,更具创造力Q那么你q有什么不满?你是否厌倦了(jin)各种邮g客户端随旉地的?d)扰你呢Q你希望你在高兴的时候适时的了(jin)解一下邮件的概况Q好?jin),既然惛_?jin)?f)什么犹豫呢Q因Z是程序员Q你是要用Eclipse享受完全DIY的乐?BR>
3.1生成插g
本部分我们将在以上myplugin插g的基上增加一个邮件过滤显C的对话框,cM的我们通过VisualEditer创徏一个名为MailDialog的对话框Qƈ增加一个JEditPane用来昄邮箱中我们关注的信息?BR>
修改plugin.xmlQ增加一?我的邮g"菜单
Qaction
label="邮g信息"
icon="icons/sample.gif"
class="myplugin.actions.MailAction"
tooltip="邮g信息"
menubarPath="sampleMenu/sampleGroup"
toolbarPath="sampleGroup"
id="myplugin.actions.MailAction"Q?BR>Q?actionQ?/TD>
现在Q你知道要创Z个MailAction的Actionc,q在在Run中增加如下代?BR>
MailConfig mail=new MailConfig();
String popServer="server";
String popUser="zhaoyong";
String popPassword="1234";
//讄需要过滤的关键字:(x)发g人和邮g主题
String [] strFrom=new String[] {"zhaoyong"};
String [] strSubject=new String[] {"试"};
MailConfig[] mc =new MailConfig [] { mail };
MailDialog md=new MailDialog(mc);
System.err.println("run run run ") ;
md.setSize(400, 335);
md.show();
以上的代码编译不?x)通过Q但是别着急,慢慢来,很快?jin)?BR>
3.2构徏邮g监控对话?
当然你需要徏立一个MailConfigcȝ来表CZ个邮q具体讄已及(qing)相关信息Q这里就不在累述说明Q详情参见参考资料中的代码。需要说明的式MailConfig除了(jin)要记录一个邮q地址Q用户名和密码外Q还提供2个关键字数组Q如果ؓ(f)I,不加qo(h)Q如果关键字有|pȝ?x)根据发件h和邮件标题(sh)是否包含关键字来q行昄邮g信息Q已保证你的l对自由?BR>
首先我们需要实C个MailConfigc,表示邮g配置Q每个MailConfig的对象代表一个邮件帐P我们的系l将能显C多个邮q配置Q每个MailConfig中用一个数l来保存需要过滤的收g人和邮g地址?BR>
MailConfigcȝ中的变量如下Q?
String popServer;
String popUser;
String popPassword;
//讄需要过滤的关键字:(x)发g人和邮g主题
String [] strFrom;
String [] strSubject;
//是否昄邮g内容
boolean isViewContent=false;
同样Q我们将使用一个对话框来显C邮件信息,MailDialog需要引用javaMail.jar,和activation.jarq两个类包,保已经有这两个cdq加入到目的类路径中。最后的MailDialog代码如下Q?BR>
package myplugin;
import java.io.IOException;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JTextPane;
/**
* @author zhaoyong
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class MailDialog extends JDialog
{
private JEditorPane jEditorPane = null;
private JTextPane jTextPane = null;
//可以昄多个邮g配置
MailConfig[] mc= null;
/**
* This method initializes
* 构造函?BR>* @param mc : 需要显C的多个邮箱配置对象?BR>*/
public MailDialog(MailConfig[] mc)
{
super();
if(mc!=null)
this.mc = mc;
else
System.err.println("邮g配置错误Q?) ;
initialize();
}
/**
* This method initializes this
* 初始?BR>* @return void
*/
private void initialize()
{
try
{
//讑֮昄内容的面?BR>this.setContentPane(getJTextPane());
//取得所有的新邮件信?BR>String s= getAllMailInfo();
//信息显C在对话框中
this.jTextPane .setText(s);
this.setTitle("邮g信息");
this.setSize(251, 100);
}
catch (Exception e)
{
//发生错误昄错误信息
this.jTextPane .setText(e.toString());
e.printStackTrace();
}
}
/**取得所有的邮箱的需要监控的邮g信息
*
* @return String
*/
private String getAllMailInfo()
{
String allMailInfo="";
if (mc.length Q?)
allMailInfo="没有配置邮箱Q?;
else
{
for(int i=0;iQmc.length;i++)
{
//循环获取每个邮箱的邮件信?
allMailInfo=allMailInfo+getMailInfo(mc[i]);
}
}
//q没有收到相关的邮g
if (allMailInfo.trim().length() ==0)
allMailInfo="未检到相关新邮Ӟ";
return allMailInfo;
}
/*
*得到一个邮׃满条g的所有新邮g的字W串形式
**/
private String getMailInfo(MailConfig mc)
{
//最l输出的邮g信息
String mailInfo="";
//每个邮箱服务器上的Store和Folder对象
Store store=null;
Folder folder=null;
try
{
Properties props = System.getProperties();
//与邮件服务器生成一个Session
Session session = Session.getDefaultInstance( props,null);
//l出服务器,用户名,密码q接服务?BR>store = session.getStore("pop3");
store.connect(mc.getPopServer(), mc.getPopUser(),mc.getPopPassword());
//取得默认的邮件Folder
folder = store.getDefaultFolder();
if (folder == null)
throw new Exception("No default folder");
//取得收g?BR>folder = folder.getFolder("INBOX");
if (folder == null)
throw new Exception("No POP3 INBOX");
//以只L式打开收g?BR>folder.open(Folder.READ_ONLY);
//获取所有新邮gq处?BR>Message[] msgs = folder.getMessages();
for (int i = 0; i Q?msgs.length; i++)
{
Message message= msgs[i];
//取得每封邮g的信息,需要引用MailConfig对象q行关键字过?BR>mailInfo = mailInfo+ getMessageInfo( message,mc);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
//安全的关闭邮件服务器资源
try
{
if (folder!=null) folder.close(true);
if (store!=null) store.close();
}
catch (Exception ex2) {ex2.printStackTrace();}
}
return mailInfo;
}
/**
* 得到一邮件的信息Q需要根据MailConfigqo(h)
* @param mailInfo
* @param message
* @return 邮g信息
* @throws MessagingException
* @throws IOException
*/
private String getMessageInfo( final Message message ,final MailConfig mc)
throws MessagingException, IOException
{
//q回的改邮g信息
String mailInfo="";
String from=((InternetAddress)message.getFrom()[0]).getPersonal();
if (from==null)
from=((InternetAddress)message.getFrom()[0]).getAddress();
String subject=message.getSubject();
//如果满qo(h)信息则显C,否则q回I?BR>if(isElementinString(from,mc.getStrFrom())
||isElementinString(subject,mc.getStrSubject()) )
{
mailInfo=mailInfo+"发g?: "+from+"\n";
mailInfo=mailInfo+"邮g主题 : "+subject+"\n";
mailInfo=mailInfo+"发送时?: "+message.getSentDate() +"\n";
//如果昄内容Q则打印内容
if(mc.isViewContent)
mailInfo=mailInfo+message.getContent() +"\n";
mailInfo=mailInfo+"------------------------------------\n";
}
return mailInfo;
}
private JTextPane getJTextPane()
{
if (jTextPane == null)
{
jTextPane = new JTextPane();
}
return jTextPane;
}
/**
* 判断目标关键字数l中是否有指定的字符?q行qo(h)
* @param targetStr Q?BR>* @param keys Q?BR>* @return 如果有,q回trueQ?否则q回false
*/
private boolean isElementinString(String targetStr,String [] keys)
{
//没指定过滤条Ӟ昄所?BR>if (keys==null)
return true;
//指定字符串ؓ(f)I,直接q回false
if (targetStr==null)
return false;
for(int i=0;iQkeys.length ;i++)
{
if (targetStr.indexOf(keys[i])Q?1)
return true;
}
return false;
}
}
// @jve:decl-index=0:visual-constraint="10,10"Q-说明Q这是Visual Editord的控制信?/TD>
以上代码的注释已l保证你能够看清楚,q里׃加篏qͼ有兴的可以自己试试Q体验一切尽在掌握的快感。当然这个例子做的实在简单,因此也ؓ(f)你的q一步开发留有够的余地?BR>
3.3 打包和发?BR>
到此Q在mypulgin中增加了(jin)邮g信息菜单和对话框Q系l的plugin.xml如下Q?BR>
Q?xml version="1.0" encoding="UTF-8"?Q?BR>Q?eclipse version="3.0"?Q?BR>Qplugin
id="myplugin"
name="Myplugin Plug-in"
version="1.0.0"
provider-name=""
class="myplugin.MypluginPlugin"Q?BR>
QruntimeQ?BR>Qlibrary name="myplugin.jar"Q?BR>Qexport name="*"/Q?BR>Q?libraryQ?BR>Qlibrary name="lib/javaMail.jar"Q?BR>Qexport name="*"/Q?BR>Q?libraryQ?BR>Qlibrary name="lib/activation.jar"Q?BR>Qexport name="*"/Q?BR>Q?libraryQ?BR>Q?runtimeQ?BR>
QrequiresQ?BR>Qimport plugin="org.eclipse.ui"/Q?BR>Qimport plugin="org.eclipse.core.runtime"/Q?BR>Q?requiresQ?BR>
Qextension
point="org.eclipse.ui.actionSets"Q?BR>QactionSet
label="Sample Action Set"
visible="true"
id="myplugin.actionSet"Q?BR>Qmenu
label="我的I间"
id="sampleMenu"Q?BR>Qseparator
name="sampleGroup"Q?BR>Q?separatorQ?BR>Q?menuQ?BR>Qaction
label="天气预报"
icon="icons/sample.gif"
class="myplugin.actions.SampleAction"
tooltip="Hello, Eclipse world"
menubarPath="sampleMenu/sampleGroup"
toolbarPath="sampleGroup"
id="myplugin.actions.SampleAction"Q?BR>Q?actionQ?BR>Qaction
label="邮g信息"
icon="icons/sample.gif"
class="myplugin.actions.MailAction"
tooltip="邮g信息"
menubarPath="sampleMenu/sampleGroup"
toolbarPath="sampleGroup"
id="myplugin.actions.MailAction"Q?BR>Q?actionQ?BR>Q?actionSetQ?BR>Q?extensionQ?BR>Q?pluginQ?/TD>
实际上,我们在一个插件中加入?个功能,因此实C(jin)我们的开发环境的自我扩展和定制。同P参考Eclipse的帮助,你可以轻杄再次插件打包导出,q将其加入自qEclipse 的plugins目录Q可能需要解压羃Q,或通过help菜单的Update选项q行安装Q注意导出时需要选定相关的类包。重新启动,你将发现自己的IDE已经多了(jin)自己的菜单,开发环境已l随着自己的意愿在改变?sh)(jin),E序员天生的满感a(b)然而生?
现在Q你可以在需要的时候点击菜单,?jin)解你希望监控的邮g情况或者最q的天气情况Q一切轻杄在掌握QEclipse的插Ӟ是q样全能?BR>
4.ȝ
那么Q聪明的你有没有发现什么问题,对,上面的东西太_糙Q太单了(jin)Q你可以做进一步的优化设计和功能加强,比如Q自己增加邮仉|文件而不是写在代码里面,动态监控弹出邮仉警(通过事先讑֮的紧急状态)(j)Q你也许q(sh)(x)惌v来很多的新的LQ比如我Z么不能有个能看电(sh)q插gQ或是Eclipse中飘出动听的音乐Q别急,q些不一定需要你亲手dQhttp://sourceforge.net/projects/rocexwang/ 有一个播攑֙插gQ但是现在仅能播N乐,国外已经有h用Eclipse开发游戏,也有人用Eclipse来做MISpȝ的。http://www.matrix.org.cn/forum_view.asp?forum_id=25&view_id=10510 有一个国人开发的俄罗斯方块游戏,虽然单了(jin)一炏V当?dng)通过|址http://eclipse-plugins.2y.net/eclipse/index.jsp和http://www.eclipseplugincentral.com/你可以找到很多的插gQ如果你知道什么更好的插gQ请告诉我?BR>
Eclipse提供?jin)一个纯的框架和插gl构Q得开发Q何功能的插g都能成ؓ(f)现实。本文介l了(jin)2个有的Eclipse插g的开发,可以使我们的工作环境增加?jin)两个可q功能,同时也得你具备?jin)基的插件开发能力,借助Eclipse的强大功能,从此你可以把你的Mx(chng)变(sh)ؓ(f)现实。同时请保持与别人的交流Q我?x)很乐意了(jin)解你的新奇的插Ӟq收藏和学习(fn)M好的插gQ打造一个完全属于自q个性化的开发环境。Eclipse在不久的将来成Z个全能的PlatformQ这一点在全世界数以万计的开发h员的手中Q正一点一点变?sh)现实?/P>
虽然目前Eclipse目q没有最后完成,但从已有的版本中已经能领略到Eclipse设计d思想和主要功能特炏V现在就?jin)解Eclipse不但能q大E序员对q款业界期望很高的IDE能一睹ؓ(f)快,更ؓ(f)重要的是如果能参加到Eclipse目的开发中或是阅读它的开放源代码Q这对广大程序员来说无疑是一个千载难逢的提高~程水^的好Z(x)。Eclipse计划提供多个q_的版本,象WindowsQLinuxQSolarisQHP-UX和AIXQ以下只介绍Windows版本。本文第一部分先介lEclipse的基本用方法。第二部分介l如何进行Eclipse的插件开发?/P>
Eclipse是开放源代码的项目,你可以到 www.eclipse.orgd费下载Eclipse的最新版本,一般Eclipse提供几个下蝲版本QReleaseQStable BuildQIntegration Build和Nightly BuildQ徏议下载Release或Stable版本Q笔者用的是Build20020125QStable版本Q。Eclipse本n是用Java语言~写Q但下蝲的压~包中ƈ不包含Javaq行环境Q需要用戯己另行安装JREQƈ且要在操作系l的环境变量中指明JRE中bin的\径。安装Eclipse的步骤非常简单:(x)只需下载的压羃包按原\径直接解压既可。需注意如果有了(jin)更新的版本,要先删除老的版本重新安装Q不能直接解压到原来的\径覆盖老版本。在解压~之后可以到相应的安装\径去找Eclipse.exeq行。如果下载的是Release或Stable版本Qƈ且JRE环境安装正确无误Q一般来说不?x)有什么问题,在闪C个很L(fng)月蚀囄后,Eclipse?x)显C它的缺省界面:(x)
图一
乍一看v来,Eclipse的界面有点象JBilderQ但实际操作q程中会(x)发现它更象IVJQ毕竟开发Eclipse的主导用量是开发IVJ的原班h马(可参考www.oti.comQ。另外还值得一提的是Eclipse目的参预者除?jin)IBM以外Q还有象BorlandQRational SoftwareQRedHatQMerant{一大批业界的姣姣者,q也为Eclipse的未来奠定了(jin)良好的基?/P>
下面分别对Eclipse的各U特性作单介l,包括Q文件存放,开发环境,~译与运行,版本理Q用插件?/P>
大多IVJ的初学者都Ҏ(gu)不到Java源代码感到非怸适应Q因为IVJ把所有的源代码都存储C个reponsitory库文件中Q想要得到文本格式的源代码必ȝExport功能从reponsitory中导出源代码。用了(jin)reponsitory的IVJҎ(gu)代码的管理功能几乎达到极_(d)正是q一点得许多程序员对IVJ钟爱有加。而Eclipse源代码以文本方式保存,却实C(jin)IVJҎ(gu)代码理的几乎全部功能,q且q增加了(jin)一些新的功能,能达到这一点,不能不惊叹于Eclipse开发者的高超技巧?/P>
安装Eclipse之后Q在安装路径的下一层\径中?x)有一个workspace文g夏V每当在Eclipse中新生成一个项目,~省情况下都?x)在workspace中生和目同名的文件夹以存放该目所用到的全部文件。你可以用Windows资源理器直接访问或l护q些文g?/P>
已有的文g加入C个项目中目前有三U方式:(x)W一U是象在IVJ中的一P用IDE?File"菜单中的"Import"功能文件导入到目中。这也是推荐的方式。第二种是从Windows的资源管理器中直接拖动文件到目中。第三种是直接文件拷贝到目文g夹中Q然后在Eclipse的资源浏览窗口中选择目或文件夹q执行从本地h功能QRefresh from locateQ。需要说明的一Ҏ(gu)Q项目文件夹可以攑֜计算机的M位置Qƈ且可以在Eclipse中用新徏目的方法将目路径指定到已l存在的目文g夹,然后在Eclipse中刷新即可。但要注意的是,M目文g夹徏立或指定Q目前都只能在Eclipse中用新徏目的方法来实现Q即使是在缺省存储项目文件夹的workspace路径下新建立一个文件夹Q在Eclipse环境中也是无法将它变成一个项目,也就是说Q这个文件夹对Eclipse是不可视的?/P>
和IVJ一PEclipse开发环境被UCؓ(f)WorkbenchQ它主要׃个部分组成:(x)视图QPerspectiveQ,~辑H口QEditorQ和观察H口QViewQ。在下面的介l中Q希望读者能知道Java视图QJava包浏览窗口,资源视图Q资源浏览窗口等区别Q其实最主要的也是要区别视囑֒H口Q,以免在进一步的阅读中生淆。图二是它们之间的关pȝ构略图:(x)
图二
在图二中Q可以看出Workbench包含多个视图Q而每个视囑֏包含不同的窗口。由于每个编辑窗口有很大的共性,而且~省情况它们都在同一区域中显C,因此我们只在每个视图中标Z个编辑窗口,以绿色表C。观察窗口则各不相同Q这里以U色表示?/P>
下面首先介绍~辑H口。所有文件的昄和编辑都包含在编辑窗口里。缺省情况下打开的多个文件是以标{(TagTableQ方式在同一个窗口中排列Q可以用拖动方式这些文件排列成各种布局。方法是拖动某一个文件的标签QtagQ到~辑H口的边框,当光标有相应的变化时再释放?/P>
当文件被加入到项目中后,在资源浏览或Java包浏览窗口双?yn)LӞEclipse?x)试图打开q个文gQ其中Eclipse内嵌的编辑器能缺省打开一些文Ӟ?.javaQ?.txtQ?.class{等。如果是其它cd的文ӞEclipse?x)调用操作系l相应的~省~辑器打开Q如word文档QPDF文g{。同时Eclipse也可以象IVJ一L(fng)指定的编辑器打开相应的文件。例如在Eclipse目中双击HTML文gӞ可能希望是用Notepad打开Q而不是用pȝ~省的IE览器打开。实现的Ҏ(gu)是打开菜单栏中的WorkBenchàPreferences对话框,之后在对话框中选择WorkBenchàFile EditorsQ然后添加文件类型,?.htmlQ再为其指定~辑器即可?/P>
在编辑窗口,q值得注意的是Q习(fn)惯了(jin)IVJ的程序员在编辑JavaE序的时候,更愿意以Ҏ(gu)为独立的~辑单位Q即在编辑窗口中只显C单个的Ҏ(gu)Q而不是程序全部的源代码)(j)Q这U方式也的确是非常合理的开发方式,不仅代码的显C更加简Pq能辅助E序员编出封装性更好的cR在Eclipse在工h上提供了(jin)一个切换按钮,可以?昄全部代码"?只显C所选单?Q这里的单元指的是单个方法、变量、导入的包等Q之间切换(可参考下面的图三Q。徏议没有用过IVJ的程序员?sh)尝试一下在"只显C所选单?状态下q行代码开发?/P>
其次要介l的是观察窗口,它配合编辑窗口ƈ提供?jin)多U的相关信息和浏览方式。常用的观察H口有资源浏览窗口(NavigatorQ,Java包浏览窗?Packages)Q控制台QConsoleQ,d栏(TaskQ等{?/P>
览H口和Java览H口是观察窗口核?j)部分。前者和W(xu)indows的浏览器差不多,能浏览项目文件夹中的所有文Ӟ后者用来浏览项目中的Java包,包中的类Q类中的变量和方法等信息。在Java览H口中可以通过用鼠标右键的菜单中的Open Type Hierarchy打开层次览H口QHierarchyQ,q个H口非常实用Q它能非常清晰的查看cȝ层次l构。类中的~译出错信息可以在Q务窗口中查到Q同时它也可以成为名W其实的dH口Q向其中d新的d描述信息Q来跟踪目的进度。控制台则主要用来显C程序的输出信息。在调试E序的时候,?x)有更丰富的观察H口来帮助程序员q行调试Q如变量值察看窗口,断点H口{等?/P>
观察H口是Q何IDE开发环境的核心(j)Q用好观察窗口是也就是用好IDE开发环境。Eclipse提供?jin)丰富的观察H口Q能真正用好q些H口恐怕要得经q一D|间的练?/P>
最后介l视图。一个视囑括一个或多个~辑H口和观察窗口。在开发环境的最左侧的快h中的上部分显C的是当前所打开的视囑֛标。视图是Eclipse的最灉|的部分,可以自定义每个视图中包含的观察窗口种c,也可以自定义一个新视图。这些功能都被包括在"Perspective" 菜单中。在Eclipse的Java开发环境中提供?jin)几U缺省视图,如资源视图(Resource PerspectiveQ它也是W一ơ启动Eclipse时的~省视图Q,Java视图QJava PerspectiveQ,调试视图QDebug PerspectiveQ,团队视图(Team Perspective){等。每一U视N对应不同U类的观察窗口。可以从菜单栏中的PerspectiveàShow View看到该视囑֯应的观察H口。当?dng)每个视图的观察窗口都是可配置的,可以在菜单栏中的PerspectiveàCustomizeq行配置。多样化的视图不但可以帮助程序员?sh)不同角度观察代码,也可以满不同的~程?fn)惯?/P>
在IVJ中调试功能非常强大,多种跟踪方式Q断点设|,变量值察看窗口等{。这些在Eclipse中都也有提供。在本文下面介绍插g的时候,?x)结合例子更加详l的介绍如何使用配置目环境Q如何运行和调试E序?/P>
在Java视图中,工具栏中有两个按钮,分别用来q行调试和运行。ƈ且可能由于安装的插g不同Eclipse?x)存在多U运?调试E序的方式,Z(jin)定当前目用那一U方式运行,需要在目的属性选项中的讄LauncheràRun/Debug选项。通常我们需要用的是"Java Applicantion"方式。在q种方式下,如果当前位置是包含main()Ҏ(gu)的JavaE序Q点击调?q行按钮׃(x)立即开始执行调?q行功能。如果当前位|是在包或项目上QEclipse?x)搜索出当前位置所包含的所有可执行E序Q然后由E序员自己选择q行那一个?/P>
在目前的Eclipse的Release和Stable版本中缺省安装了(jin)插g开发环境(Plug-in Development EnvironmentQ即PDEQ它本n也是一个插Ӟ(j)Q此时系l除?Java Applicantion" q行方式Q可能还有另外两U方式:(x)"Run-time WorkBench"?Run-time WorkBench with Tracing"Q当用PDE开发插件的时候会(x)用到q两U运行方式,在下面我们也有提到?/P>
可以把Eclipse的版本管理分Z人(或称为本圎ͼ(j)和团队两U?/P>
Eclipse提供?jin)强大的个h版本理机制Q每一ơ被保存的更攚w可以得到恢复。而且可以_到每一个方法的版本恢复。操作也十分方便Q在M一个能看到所要操作文件的观察H口中,例如资源览H口Q选中该文Ӟ点击右鼠标键Q选择Compare with或Replace withQ如果是恢复已经被删除的Ҏ(gu)则可以选择Add from local historyQ之后相应的本地历史记录׃(x)昄出来Q按照你的需求找到相应的版本可以了(jin)。强大的个h版本理功能为程序员提供?jin)更多的信?j)Q只编下去QQ何不心(j)的错误都可以恢复Q在Eclipse下开发,是有"后?zhn)?的!
Eclipse~省为版本管理工具CVS提供?jin)接口,可以非常方便的连接到CVS服务器上。通过CVS版本理QEclipse为团队开发提供良好的环境。要q接CVS服务器需要先打开团队视图QTeam PerspectiveQ,然后在Reponsitories观察H口中点击鼠标右键ƈ选择新徏QNewQ,在打开的对话框中可以填入要q接的CVS库所需要的信息Q如CVS服务器类型,目前Eclipse支持三种方式Qpserver、extssh和extQ还要填入用户名Q主机名Q密码,reponsitory地址{信息?/P>
在Eclipse中用CVS需要注意的是一些术语和功能的变化,CVS中的Branchq里被称为StreamQ取消了(jin)CVS中check out、import和commit{功能,l统用鼠标右键菜单中的Team->Synchronized with Stream来替代。这些功能都通过囑Ş界面完成Q在每次操作中都?x)有当前文g和以前各个版本的比较H口Q操作非常直观,易于掌握Q因此这里也׃再做q一步介l了(jin)?/P>
使用插g可以丰富Eclipse的功能。下面将介绍如何应用插g来嵌入Tomcat服务器。这个插件ƈ不是Eclipse目l开发的Q而是一家叫sysdeo的公司开发,非常yQ只?7.8K。你可以?http://www.sysdeo.com/eclipse/tomcatPlugin.htmld费下载。另外,q个插g只支持Tomat4.0以上的版本,可以?www.apache.org得到Tomcat的最新版本?
要安装插件只需下载的zip文g按原路径解压?你的Eclipse的安装\径\plugins"下面Q然后重新启动Eclipse。启动后在菜单栏上选择PerspectiveàCustomizeQ在打开的对话框中选中OtheràTomcat。之后马上会(x)发现Eclipse有了(jin)两处变化Q菜单栏中多?jin)一个Tomcat选项Q工h中多?jin)两个按钮,上面是大家可能非常熟?zhn)的Tomcat猫Q如下图三。除此之外,在菜单栏中选择QWorkbenchàPreferencesQ打开对话框后?x)发现这也多了(jin)一个Tomcat选项Q在q里要求指定你的Tomcat安装根\径。之后还要检查一下在Preferences对话框中的JavaàI(yng)nstalled JRE所指定的JRE和启动Tomcat的JRE是否为同一个JREQ如果不是,可能?x)导致Tomat不能正常启动。如果以上检查没有问题,可以用工具栏上?猫"直接起动Tomcat?jin)。要注意的是Q启动过E很慢,要耐心(j){到以下信息出现Q?/P>
Starting service Tomcat-Standalone
Apache Tomcat/4.0.1
Starting service Tomcat-Apache
Apache Tomcat/4.0.1
之后可以在外部览器(如IEQ中输入 http://localhost:8080来测试Tomcat是否正常?
图三
如果启动正常Q可以进一步尝试在Eclipse中调试Servlet或JSPE序。下面我们将用Tomcat自带的Servlet例程HelloWorldExample.java来示范一下如何在Eclipse中调试SevletE序?/P>
首先要在Java视图中新Z个Java目Qؓ(f)?jin)方便,可以直接项目\径指定到HelloWorldExmapleE序所在\径,如图四:(x)
囑֛
之后?Next"Q进入Java Settings对话框,选择Libraries标签Qƈ用Add External JARs按钮来指定Servlet.jar包的位置。这里直接用?jin)Tomcat中的Servlet.jar包。如图五Q?/P>
图五
最后,点击"Finish"完成目的生成。在新生成项目中的default package可以扑ֈHelloWorldExample.javaQ双?yn)L开文gQƈ可尝试给HelloWorldExample加上一个断点(双击~辑H口左侧边界Q。之后在外部览器中输入 http://localhost:8080/examples/servlet/HelloWorldExampleQ再回过来看Eclipse发生?jin)什么变化,是一个调试窗口呀Q在Eclipse中进行的调试操作和绝大多数的IDE大同异Q如讄断点Q单步跟t,变量值察看等{,在这里也׃用再详述?jin)?
二.开发Eclipse插gQPlug-insQ?/SPAN>
Eclipse最有魅力的地方是它的插g体系l构。在q个体系中重要的概念是扩展点Qextension pointsQ,也就是ؓ(f)插g提供的接口。每一个插仉是在现有的扩展点上开发,q可能还留有自己的扩展点Q以便在q个插g上l开发?/P>
׃有了(jin)插gQEclipsepȝ的核?j)部分在启动的时候要完成的工作十分简单:(x)启动q_的基部分和查扄l的插g。在Eclipse中实现的l大部分功能是由相应的插件完成的Q比如WrokBench UI插g完成界面的外观显C,Resource Management插g完成l护或生成项目或文g{资源管理工作(在下面的W二个例子就?x)用到这个插Ӟ?j)Q而Version and Configuration Management (VCM)插g则负责完成版本控制功能,{等。虽然以上提到的每一个功能都是绝大多数IDE环境所必备的功能,Eclipse却也把它们都做成?jin)插件模式,甚至用来开发JavaE序的开发环境(Java development toolingQJDTQ也只不q是Eclipsepȝ中的一个普通插件而已。整个Eclipse体系l构p一个大拼图Q可以不断的向上加插Ӟ同时Q现有插件上q可以再加插件。下面的插g开发示例就是在WorkBench UI插g中的观察H口扩展点上开发的?/P>
本文W一部分介绍qEclipse的开发界面其中之一是观察H口Q它通常配合~辑H口昄一些有用的信息Q在q里我们只简单生成一个显C欢q信息的观察H口Q假设新插g的名子叫Welcome?/P>
W一步,先用向导新徏一个Java目。我们可以在菜单栏选择FileàNewQ或用工h的向导按键,或是在资源窗口用鼠标右键菜单中的NewQ打开向导对话框,然后用缺省方式创建项目。ƈ在项目中建立一个Welcome.java文gQ代码如下:(x)
|
Zɘq个E序能正常编译,要配|它的编译环境,x(chng)定所需的CLASSPATH。在Eclipse中可以用几种Ҏ(gu)Q常用的是两U:(x)W一是在资源H口或Java包窗口选中该项目,点击鼠标右键Q在打开的菜单中选择属性(PropertiesQ,之后在属性对话框中选择Java Build PathàLibrariesQ用Add External JARs功能d三个包,它们都是Eclipse的现有插件的cdQ可以在"你的Eclipse安装路径\plugins"下面的相应\径中扑ֈ。分别是org.eclipse.core.runtime插g中的runtime.jarQorg.eclipse.swt中的swt.jar和org.eclipse.ui中的workbench.jar。第二种指定CLASSPATH的方法是先将以上提到的三个包直接导入到Eclipse中的某下一个项目中。如果导入到和W(xu)elcome.java相同的项目中Q则无需q一步指定CLASSPATHQ否则需要在目的属性菜单中选择Java Build PathàProjectsQ然后选中q三个包所在的目?/P>
在我们的目中还要生成一个XML文gQ它的名字必plugin.xml。代码如下:(x)
|
在plugin.xml中一共有四个主要的标{:(x)pluginQrequiresQruntimeQextension。其中plugin标签的属性提供的是我们要开发的Welcome插g的基本信息,除了(jin)nameQversionQprovider-name{,最重要的是idQ它要求不能和现有的Eclipse插gid有冲H,因此我们用包名作为插件的id。requires标签中所列出的是需要的插gQ这里我们要用到Eclipse Workbench和SWT APIQ因此导入了(jin)org.eclipse.ui插g。runtime标签指明的是我们开发的插g所在JAR包的文g名。extension标签是插件扩展点的信息。org.eclipse.ui.views是Eclipsepȝ提供的观察窗口扩展点Q我们的例子是一个观察窗口(ViewQ,q表明我们是要在 org.eclipse.ui.views扩展点上q一步开发。extension中还包括category和view两个标签Q在后箋(hu)的启动Welcome插g步骤中,我们׃(x)知道q两个标{含义。要注意的是category和view标签的id的唯一性,q且在view的属性中声明?jin)Welcome插g的类名?/P>
在Eclipse中ؓ(f)plugin.xml提供?jin)缺省可视化的编辑器Q在~写plugin.xmlq程中可以借助q个~辑器完成一些工作。如果你直接录入?jin)plugin.xml文g源代码,q可以用q个~辑器校验你的代码:(x)如果~辑器不能正读入,p明你的plugin.xml有一些问题?/P>
在确认Weclome.java和plugin.xml都正无误之后,可以用Eclipse菜单栏中的Export命o(h)Weclome.java导出为JAR文gQ它的名子应该和plugin.xml中runtime声明的JAR怸致。同时导出plugin.xml。安装Welcome插g的方法和本文W一部分介绍的安装Tomcat插gҎ(gu)是一L(fng)Q首先在"Eclipse的安装\径\plugins"路径下面建立一个com.nidapeng.eclipse.plugin路径Q然后将Weclome.jar和plugin.xml拷到q个路径下。之后必需重新启动EclipseQ在Eclipse启动的时候,它会(x)搜烦(ch)所有在插g路径下的插gq注册它们(仅仅是注册,只有在需要某个插件的时候,Eclipse才会(x)启动它)(j)。在重新启动的Eclipse的菜单栏中选择PerspectiveàShow ViewàOthersQ在打开的对话框中我们会(x)扑ֈ在plugin.xml中extension的category标签中声明的name属性:(x)Welcome。在Welcome的支l点中包含了(jin)view标签name属性:(x)Welcome to Eclipse。选中它ƈ认QW(xu)elcomeH口׃(x)昄在Eclipse Workbench上的某个位置 。如果在执行?jin)以上操作,但没有显C新H口Q可以再ơ打开Show View菜单Q此时在菜单中应该有C剙择QWelcome to EclipseQ然后选中它?/P>
上面我们完成?jin)一个观察窗口的插gQ但q个操作q程对开发稍微复杂一些的插g显得不太方便了(jin)Q每ơ测试都要将代码打包Q发布,再重新启动EclipsepȝQؓ(f)此Eclipse提供?jin)一个专门ؓ(f)开发插件而做插gQ有点绕_(d)(j)QPlug-in Development EnvironmentQPDEQ。本文前面曾提到Q目前Eclipse的Release或Stable版本~省提供?jin)这个插Ӟ因此如果安装的Eclipse是这两个版本中的一个就可以直接q行下面的步骤。下面我们再用PDE环境开发一个稍微复杂一些的插g?/P>
W一步仍然要新徏一个项目,只是在向g不是用Java目Q而是Plug-in Development中的Plug-in Project。在应用向导生成新项目的时候,要注意两点:(x)W一是PDE的项目名U就是plugin的idQ因此要保证它的唯一性,q里我们的项目名是com.nidapeng.eclipse.plugin.pde。其ơؓ(f)?jin)进一步说明Eclipse插g的结构,在Plug-in Code Generators中,选择用向导模板生成一个缺省的插gQ如囑օQ?/P>
囑օ
q个用缺省方式生成的插gcd于我们将要的代码q不是必需的,也可以用生成I插件的方式建立我们的项目,q样做只是ؓ(f)q一步说明Eclipse的插件结构?/P>
目生成之后Q在我们的项目中?x)包含一个PdePlugin.java文gQ它?yu)是以缺省方式生成的插gcR注意到它承了(jin)AbstractUIPluginc,而AbstractUIPlugincdC(jin)org.eclipse.ui.plugin接口。事实上Q所有的Eclipse插g都会(x)有一个相应的实现plugin接口的类Q这个类是新插件的ȝQ类g有main()函数的Javac)(j)Q它负责理插g的生存期。在我们的AbstractUIPluginl承子类中,可以用singleton模式来保存在Eclipse中的生成的该插g的第一个也是唯一实例Q一般来_(d)在该l承子类中也要实C个getDefault()Ҏ(gu)以返回当前插件的实例。而且Q当Eclipse首次使用该插件的时候,q个ȝ是W一个被调用的类Q因此我们也可以在它的代码中执行一些初始化的工作。而且如果插g需要用PreferencesQDialogs或Images资源Q也可以通过q个cM的相应方法来得到它们的实例,如用其中的getDialogSettings()QgetPreferenceStore()QgetImageRegistry()Ҏ(gu)?/P>
但是象前面提到的QPdePlugin.java对下面的例子q不是必需的,我们不用对它q行M修改。在我们W一个例子中的Weclome插gQ根本就没有生成AbstractUIPlugin的承子c,此时pȝ?x)自动?f)Weclome插g生成一个缺省的ȝQ类gJavacL造函敎ͼ如果没有声明Q系l会(x)指定一个默认的构造函敎ͼ(j)?/P>
下面的代码是才真正实C(jin)我们新插件的功能Q假设这个插件名子是NoticeViewQ?/P>
|
象上面的W一个Welcome插gQ这个新插g同样l承?jin)ViewPartQ不同的是实C(jin)三个接口QRunnable,IResourceChangeListener ,IResourceDeltaVisitor。其中的Runnable大家应该很熟(zhn):(x)多线E的接口。而IResourceChangeListener和IResourceDeltaVisitor是Eclipsepȝ中的资源接口Q这里的资源是指Eclipse中的目或文件等。在下面q行NoticeView插g的过E中你可以通过d、打开、删除项目或文g来触发这两个接口中的事gQƈ在我们的观察H口中显C相关信息?/P>
在程序中比较奇怪部分的是在resourceChanged()函数里面Qƈ没有象大家想象的那样直接调用label.setText()Ҏ(gu)来显CZ息,而是调用?jin)disp.syncExec(this)Q其中的disp是Displaycd的对象。这是因为resourceChanged()Ҏ(gu)q行的线E和lable所在插件运行的EclipseȝEƈ不是同一个线E,如果直接调用label.setText()Ҏ(gu)Q会(x)抛出一个异常?/P>
下面q需要对目中的plugin.xmlq行一些改动,主要是加上扩展点声明:(x)
|
q个xml文g和W(xu)elcome插g的plugin.xml非常接近Q这里就不做q多的说明了(jin)?/P>
要运行这个插Ӟ可以直接用Eclipse中的q行按钮Q因个项目是一个Plug-in ProjectQ此旉目会(x)自动以Run-time Workbench方式q行。运行后Q会(x)生成一个和当前Eclipse完全一致的q_Q在q个q_上可以直接运行NoticeView插gQ查看这个插件到底会(x)执行什么功能,也可以用直接Run-time Workbench方式调试插g。这里省M(jin)安装插gQ重启动Eclipse{过E,可以看到用PDE开发插件的q程比直接用Java开发环境简z了(jin)很多Q?/P>
Eclipse的开发不仅仅限于插g的开发,它还可以取代Java中的标准SwingQ进行基于Java的独立应用程序GUI开发。它带来的好处是显而易见的Q高速,资源占用低,跨^収ͼ代码开放,有大公司的支持等{?/P>
׃Eclipse目前q在开发阶D,W者在用它调试E序时发现有些性能q(sh)是十分的E_Q一些地方会(x)遇到奇怪的问题Q要求用者能想一些办法解冟뀂不q,以现在Eclipse的开发速度Q相信过不了(jin)多久Q它的各U功能会(x)逐步完善。目前Eclipse虽然有种U不I但瑕不掩玉,W者对Eclipse的M印象q是非常不错的,q行速度Q资源占用都要好于IVJQ操作v来也大多手Q而且即在现阶段也很有意外退出等重大的Bug发生Q希望未来的Eclipse能真正达到IVJ的功能,VisualCafe的速度Q成为广大程序员开发Y件的一大利器!
Q?xml version="1.0" encoding="UTF-8"?Q?BR>Q?eclipse version="3.0"?Q?BR> QpluginQ?BR> Qextension point="org.eclipse.ui.views"Q?BR> Qcategory id="com.developer.superview.category1" name="Developer.com"/Q?BR> Qview category="com.developer.superview.category1" class="com.developer.superview.Superview" id="com.developer.superview.view1" name="Superview"/Q?BR> Q?extensionQ?BR> Q?pluginQ?/TD> |
![]() |
package com.developer.superview; import org.eclipse.jface.viewers.ArrayContentProvider; public class SuperView extends ViewPart { (tng)public void createPartControl(Composite parent) { (tng)public void setFocus() { } |
![]() |
package com.developer.superview; import org.eclipse.swt.graphics.Image; import org.eclipse.jface.resource.ImageDescriptor; public class SuperView extends ViewPart { (tng)public void createPartControl(Composite parent) { (tng)public void setFocus() { |
![]() |
Z插g的体pȝ?/SPAN>
Eclipse q_?IBM 向开发源码社区捐赠的开发框Ӟ它之所以出名ƈ不是因ؓ(f) IBM 宣称投入开发的资金L ?4 千万元 ?而是因ؓ(f)如此巨大的投入所带来的成果:(x)一个成熟的、精?j)设计的以?qing)可扩展的体系l构。Eclipse 的h(hun)值是它ؓ(f)创徏可扩展的集成开发环境提供了(jin)一个开放源码^台。这个^台允怓Q何h构徏与环境和其它工具无缝集成的工兗?/P>
工具?Eclipse 无缝集成的关键是 插g。除?jin)小型的q行时内怹外,Eclipse 中的所有东襉K是插件。从q个角度来讲Q所有功能部仉是以同等的方式创建的。从q个角度来讲Q所有功能部仉是以同等的方式创建的?
但是Q某些插件比其它插g更重要些。Workbench ?Workspace ?Eclipse q_的两个必备的插g ?它们提供?jin)大多数插g使用的扩展点Q如?1 所C。插仉要扩展点才可以插入,q样它才能运行?/P>
?1. Eclipse Workbench ?WorkspaceQ必备的插g支持
Workbench lg包含?jin)一些扩展点Q例如,允许(zhn)的插g扩展 Eclipse 用户界面Qɘq些用户界面带有菜单选择和工h按钮Q请求不同类型事件的通知Q以?qing)创建新视图。Workspace lg包含?jin)可以让?zhn)与资源Q包括项目和文gQ交互的扩展炏V?/P>
当然Q其它插件可以扩展的 Eclipse lgq只有 Workbench ?Workspace。此外,q有一?Debug lg可以让?zhn)的插件启动程序、与正在q行的程序交互,以及(qing)处理错误 ?q是构徏调试器所必需的。虽?Debug lg对于某些cd的应用程序是必需的,但大多数应用E序q不需要它?/P>
q有一?Team lg允许 Eclipse 资源与版本控制系l(VCSQ交互,但除非?zhn)正在构?VCS ?Eclipse 客户机,否则 Team lgQ就?Debug lg一P不会(x)扩展或增强它的功能?/P>
最后,q有一?Help lg可以让?zhn)提供应用E序的联机文档和与上下文敏感的帮助。没有h?x)否认帮助文档是专业应用E序必备的部分,但它q不是插件功能的必要部分?/P>
上述每个lg提供的扩展点都记录在 Eclipse Platform Help 中,该帮助在 Platform Plug-in Developer 指南的参考部分中。乍一看,其?API 参考大全的 Workbench 部分Q一开始会(x)令h望而却步。我们不?x)深入?jin)解众多可用扩展点的详l信息,而只是粗略地看一个简单插件及(qing)其组件?/P>
插g?/SPAN>
创徏插g最单的Ҏ(gu)是?Plug-in Development EnvironmentQPDEQ。PDE ?Java Development ToolingQJDTQIDE ?Eclipse 的标准扩展。PDE 提供?jin)一些向g帮助创徏插gQ包括我们将在这里研I的“Hello, world”示例?/P>
?Eclipse 菜单Q选择 File=>New=>OtherQ或?Ctrl-NQ,然后选择 Select 对话框左边的 Plug-in Development 向导。在 Select 对话框的双Q选择 Plug-in Project。按 Next。在下一屏上Q输入项目名Uͼ我用了(jin) com.example.hello
。再ơ按 Next。在下一屏上Q请注意Q插件标识就与项目名U相同。用项目名UC为插件标识可以将该插件与另一个插件的名称发生冲突的机?x)减到最。再按一?Next。下一屏让(zhn)选择是手工创建初始插件代码,q是q行代码生成向导。保留代码生成向导的~省选项Q选择“Hello, World”,然后?NextQ如?2 所C?
下一屏要求一些附加信息。请注意q一屏上的信息:(x)它包含了(jin)插g名称、版本号、提供者名U和cd。这些是关于插g的重要信息,我们在E后研究。可以接受向导提供的~省倹{按 Next。在下一屏幕上,接受包名、类名和消息文本的缺省倹{选择“Add the action set to the resource perspective”复选框。按 Finish?/P>
如果接到通知Q向导需要启用某些其它插件才能完成,那么?OK?/P>
q一?x)儿Q向导将完成Q而在(zhn)的工作Z会(x)有一个新的项目,名ؓ(f) com.example.hello
Q如?3 所C?
?3. PDE 透视图:(x)Welcome to Hello Plug-in
?Package Explorer 中,工作台的左边是向导创建的一些东西的概述。大多数w不引人关注:(x)包括目c\径中的许?.jar
文gQ这些包括插件和 Java q行时所需?Eclipse c)(j)、一个图标文件夹Q包含了(jin)工具栏按钮的囑ŞQ,以及(qing) build.properties
文gQ包含自动构本所使用的变量)(j)?
q里最有意思的东西?src 文g夹,它包含了(jin)插g?plugin.xml 文g的源代码 ?plug-in.xml 是插件的清单文g。我们将先查?plugin.xml?/P>
插g清单文g
插g清单文g plugin.xml 包含?Eclipse 插仉成到框架所使用的描qC息。缺省情况下Q当W一ơ创建插件时Q会(x)在清单编辑器区域中打开 plugin.xml。编辑器底部的选项卡让(zhn)可以选择关于插g的不同信息集合。Welcome 选项卡显CZ(jin)消息“Welcome to Hello Plug-In”,q且要讨Z(jin)所使用的模板和关于使用 Eclipse 实现插g的提C。选择“Source”选项卡可以让(zhn)查?plugin.xml 文g的完整源代码?/P>
让我们看看插件清单文件的各个部分。首先是关于插g的常规信息,包括它的名称、版本号、实现它的类文g的名U和 .jar
文g名?
|
接着Q列Z(jin)我们的插件所需的插Ӟ(x)
清单 2. 插g清单文g ?必需的插?/B>
|
列出的第一个插?org.eclipse.core.resources
是工作区插gQ但实际上我们的插gq不需要它。第二个插g org.eclipse.ui
是工作台。我们需要工作台插gQ因为我们将扩展它的两个扩展点,正如后面?extension 标记所指出的?
W一?extension 标记拥有点属?org.eclipse.ui.actionSets
。操作集合是插gd到工作台用户界面的一l?基?/I>?卻I菜单、菜单项和工h。操作集合分l了(jin)基|q样用户可以更方便地理它们。例如,我们?Hello 插g的菜单和工具栏项出现在 Resource 透视图中Q因为当在运行代码生成向导时Q我们做?jin)这L(fng)选择。如果用戯更改它,可以使用 Window=>Customize Perspective菜单选项从要?Resource 透视图中昄的项中除厠ZSample Action Set”?
操作集合包含?jin)两个标讎ͼ?x) menu 标记Q描q菜单项应该出现在工作台菜单的什么位|,以及(qing)如何出现Q和 action 标记Q描q它应该做什么)(j)?其?action 标记标识?jin)执行操作的cR注Q这个类不是上面列出的插件类?
清单 3. 操作集合
|
许多菜单和操作属性的目的相当明显 ?例如Q提供工hC文本和标识工具栏项的图形。但q要注意 action 标记中的 menubarPath
Q这个属性标识了(jin) menu 标记中定义的哪个菜单调?action 标记中定义的操作。有兌个和其它工作台扩展点的详l信息,请参?Platform Plug-in Developer GuideQ尤其是“Plugging into the workbench”章节(可以?Eclipse 的帮助菜单中获取该指南)(j)?
׃我们选择?jin)将插gd?Resource 透视图,于是生成?jin)第二?extension 标记。这个标C(x)D?Eclipse W一ơ启动ƈ装入我们的插件时Q将插gd?Resource 透视图?/P>清单 4. extension 标记
|
如果忽略q最后一?extensionQ用户就需要?Window=>Customize Perspective插件添加到 ResourceQ或其它Q透视图?
插g源代?/SPAN>
代码生成向导生成?jin)两?Java 源文Ӟ打开 PDE Package Explorer 中的 src 文g夹就可以看到它们。第一个文?HelloPlugin.java
是插件类Q它l承?AbstractUIPlugin
抽象cR?HelloPlugin
负责理插g的生命周期,在更为扩展的应用E序中,它负责维护诸如对话框讄和用户首选项{内宏V?HelloPlugin
要做的事p么多Q?
|
W二个源文g SampleAction.java
包含的类执行在清单文g的操作集合中指定的操作?SampleAction
实现?IWorkbenchWindowActionDelegate
接口Q它允许 Eclipse 使用插g的代理,q样不是在万不得已的情况下,Eclipse 无需装入插gQ这优化工作在装入插件时发生内存和性能斚w的问题降到最低)(j)?IWorkbenchWindowActionDelegate
接口Ҏ(gu)使插件可以与代理q行交互Q?
|
q行和调试插?/SPAN>
当开?Eclipse 的插件时Q必d?Eclipse q用新的插g重新启动它以便进行测试和调试Q这很笨拙。幸好,Eclipse PDE 提供?jin)一个自托管Qself-hostedQ的开发环境,它让(zhn)无需插件安装在工作台的单独实例中即可运行?/P>
要运?Hello 插gQ选择 Run=>Run As=>Run-time Workbench来启动另一?Workbench 实例Q而该实例d?jin)插件的菜单选项和工hQ如?5 所C?
我们可以通过单击工具栏按钮或从“Sample Menu”菜单激zL件。Q何一U方法都?x)生成一个框Q其标题是“Hello Plug-in”,内容是“Hello, Eclipse world”,以及(qing)一?OK 按钮Q按该按钮可以关闭这个框?/P>
通过选择 Run=>Debug As=>Run-time WorkbenchQ按cM的方法调试插件。这ơ,当插件在W二个工作台实例中运行时Q我们可以在最初的工作C单步执行源代码,以及(qing)(g)查变量等?
一旦插件经q测试ƈ准备发布Q我们就需要将它适当打包Q以便在 Eclipse 中安装?/P>
打包插g
Eclipse 在启动时?x)查看其插g目录来确定要装入哪些插g。要安装插gQ我们需要在插g目录中创Z个子目录Qƈ程序文件和清单文g复制到那里。徏议目录名U能表示插g的标识,q且后面跟下划线和版本号Q但是这U做法不是必需的。假?Eclipse 安装?C:\eclipse 中;我们要创Z个目录:(x)
C:\eclipse\plugins\com.example.hello_1.0.0.
按照 Java E序的标准,我们的程序文仉要归档到 .jar
文g??我们的插件清单文Ӟ(zhn)也许记得它包含q个:(x)
|
要创?hello.jar
文gQ我们可以通过H出昄目名称Qƈ?Eclipse 菜单选择 File=>ExportQ以导出插g文g。选择 JAR 文g作ؓ(f)导出方式Q按 NextQ然后浏览到我们为它创徏的目录。下一步,我们q需要将 plugin.xml 文g复制到这个目录。也可以使用 File=>Export菜单选项Q但误C选择 File System 作ؓ(f)导出目的圎ͼ(j)?
q就是安装插件所需的全部操作,但?zhn)需要停止ƈ重新启动 EclipseQ以便能识别q个新的插g。从帮助菜单中选择“About Eclipse Platform”,可以扑ֈ关于已安装插件的信息Q包括版本号。在出现的屏q上有一个按钮是 Plug-in DetailsQ向下滚动列表来L Hello 插g?qing)其版本受?/P>
更新插g版本
在目录名UC包含版本L(fng)目的是允许在同一台机器上共存某个插g的多个版本(每次只装入一个版本)(j)。我们可以通过创徏一?Hello 插g的已更新版本来看看这是如何工作的Q例如,?plugin.xml 文g中的版本hҎ(gu)?.0.1”,然后?SampleAction.java
中的文本更改成“New and improved Hello, Eclipse world”。从 Eclipse 菜单中选择 Project=> Rebuild All。下一步,项目文件以 JAR 形式导出到新的插件目录,例如Q?com.example.hello_1.0.1
。将修订q的 plugin.xml 文g复制到同一个目录中。当停止q新启?Eclipse Ӟ只会(x)装入已更新的插g?
插g片段和功能部?/SPAN>
Eclipse 由插件组成,但在开?Eclipse 的插件时Q还要慎重考虑另外两个U别的组??插g片段和功能部件?/P>
插g 片段Q如名称所暗示的)(j)是完整插件的l成部分 ?目标插g。片D|供的功能与目标插件的功能合ƈ。片D可以用于将插g本地化成各种语言Q在无需形成一个全新发行版的情况下Q以增量形式功能部件添加到现有插gQ或者提供特定于q_的功能。在许多斚wQ片D与插g一栗主要的区别是片段没有插gc??片段的生命周期由其目标插件管理。此外,片段的清单文件叫?fragment.xmlQ它列出?jin)目标插件的标识和版本号Q以?qing)片D늚标识和版本号?
另一斚wQ插?功能部gҎ(gu)不包含编码。在 Eclipse 体系l构术语中,功能部g是将一l相x(chng)件打包到完整的品中。例如,JDT 是包含了(jin)?Java ~辑器、调试器和控制台q样的插件的功能部g。名?feature.xml 的清单文件描qC(jin)一个功能部件归档文件。在其中Q该清单文g包含?jin)对该功能部件所包含的插件和其它资源的引用、关于如何更新该功能部g的信息、版权信息和许可证信息?
?Eclipse 中, d能部?/I>讄?Eclipse q_的外观。主功能部g旨在定诸如l予 Eclipse 其n份的闪屏和其它特征之cȝ东西。Eclipse 只允怸个主功能部g。用q种方式Q通过创徏一l插Ӟ它们打包到功能部g中,q且使这个功能部件成Z功能部gQ就可以重新创徏 Eclipse 的品牌,q将它用于创建全C不同的品。如果从 Eclipse.org 下蝲Q缺省主功能部g?eclipse.org.platform
?
后箋(hu)步骤
在插件的介绍里我们只是稍微了(jin)解一些插件的必要用法。学?fn)插件的更多知识的最?jng)_考资料是 Plug-in Developer's GuideQ可以从 Eclipse 中的帮助菜单中获得该指南。该文档包含?jin)编E指南、Eclipse API 和插件扩展点的参考大全、Eclipse.org 上可用的~程CZ的指南,以及(qing)常见问题列表。另一个优U参考资料是 Eclipse 本n的源代码。根据?zhn)的兴,?zhn)也许想要查找一些示例,以了(jin)解不同工作台功能部gQ如视图和编辑器Q是如何扩展的,或者如何?SWTQEclipse 囑Ş APIQ。此外,下面?参考资?/A>可以帮助(zhn)学到更多知识?
public class InvokatronDocument
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)extends Properties
{
(tng) (tng) (tng) (tng)public static final String PACKAGE = "package";
(tng) (tng) (tng) (tng)public static final String SUPERCLASS = "superclass";
(tng) (tng) (tng) (tng)public static final String INTERFACES = "interfaces";
}
String package =
(tng) (tng) (tng) (tng)document.getProperty(InvokatronDocument.PACKAGE);
public class InvokatronWizard extends Wizard
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)implements INewWizard {
(tng) (tng) (tng) (tng)private InvokatronWizardPage page;
(tng) (tng) (tng) (tng)private InvokatronWizardPage2 page2;
(tng) (tng) (tng) (tng)private ISelection selection;
(tng) (tng) (tng) (tng)public InvokatronWizard() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)super();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setNeedsProgressMonitor(true);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)mageDescriptor image =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)AbstractUIPlugin.
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)imageDescriptorFromPlugin("Invokatron",
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) "icons/InvokatronIcon32.GIF");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setDefaultPageImageDescriptor(image);
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)public void init(IWorkbench workbench,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)StructuredSelection selection) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)this.selection = selection;
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)public void addPages() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page=new InvokatronWizardPage(selection);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)addPage(page);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page2 = new InvokatronWizardPage2(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)selection);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)addPage(page2);
(tng) (tng) (tng) (tng)}
public boolean performFinish() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//First save all the page data as variables.
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final String containerName =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page.getContainerName();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final String fileName =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page.getFileName();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final InvokatronDocument properties =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new InvokatronDocument();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties.setProperty(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nvokatronDocument.PACKAGE,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page2.getPackage());
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties.setProperty(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nvokatronDocument.SUPERCLASS,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page2.getSuperclass());
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties.setProperty(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nvokatronDocument.INTERFACES,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page2.getInterfaces());
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//Now invoke the finish method.
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)RunnableWithProgress op =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new IRunnableWithProgress() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void run(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)ProgressMonitor monitor)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throws InvocationTargetException {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)doFinish(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)containerName,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)fileName,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (CoreException e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throw new InvocationTargetException(e);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} finally {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.done();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)};
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getContainer().run(true, false, op);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (InterruptedException e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return false;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (InvocationTargetException e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Throwable realException =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)e.getTargetException();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)MessageDialog.openError(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getShell(),
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Error",
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)realException.getMessage());
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return false;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return true;
(tng) (tng) (tng) (tng)}
private void doFinish(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String containerName,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String fileName,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Properties properties,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)ProgressMonitor monitor)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throws CoreException {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// create a sample file
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.beginTask("Creating " + fileName, 2);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)WorkspaceRoot root = ResourcesPlugin.
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getWorkspace().getRoot();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Resource resource = root.findMember(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Path(containerName));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (!resource.exists() ||
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)!(resource instanceof IContainer)) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throwCoreException("Container \"" +
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)containerName +
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"\" does not exist.");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Container container =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)(IContainer)resource;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final IFile iFile = container.getFile(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Path(fileName));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final File file =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)iFile.getLocation().toFile();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)OutputStream os =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new FileOutputStream(file, false);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties.store(os, null);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)os.close();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (IOException e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)e.printStackTrace();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throwCoreException(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Error writing to file " +
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)file.toString());
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//Make sure the project is refreshed
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//as the file was created outside the
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//Eclipse API.
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)container.refreshLocal(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Resource.DEPTH_INFINITE, monitor);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.worked(1);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.setTaskName(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Opening file for editing...");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getShell().getDisplay().asyncExec(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Runnable() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void run() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)WorkbenchPage page =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)PlatformUI.getWorkbench().
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getActiveWorkbenchWindow().
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getActivePage();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)DE.openEditor(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)iFile,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)true);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (PartInitException e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)});
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.worked(1);
(tng) (tng) (tng) (tng)}
private void throwCoreException(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String message) throws CoreException {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Status status =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Status(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Status.ERROR,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Invokatron",
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Status.OK,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)message,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)null);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throw new CoreException(status);
(tng) (tng) (tng) (tng)}
}
public class InvokatronWizardPage2 extends WizardPage {
(tng) (tng) (tng) (tng)private Text packageText;
(tng) (tng) (tng) (tng)private Text superclassText;
(tng) (tng) (tng) (tng)private Text interfacesText;
(tng) (tng) (tng) (tng)private ISelection selection;
(tng) (tng) (tng) (tng)public InvokatronWizardPage2(ISelection selection) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)super("wizardPage2");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setTitle("Invokatron Wizard");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setDescription("This wizard creates a new"+
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)" file with *.invokatron extension.");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)this.selection = selection;
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)private void updateStatus(String message) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setErrorMessage(message);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setPageComplete(message == null);
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)public String getPackage() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return packageText.getText();
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)public String getSuperclass() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return superclassText.getText();
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)public String getInterfaces() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return interfacesText.getText();
(tng) (tng) (tng) (tng)}
public void createControl(Composite parent) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Composite controls =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Composite(parent, SWT.NULL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridLayout layout = new GridLayout();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)controls.setLayout(layout);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)layout.numColumns = 3;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)layout.verticalSpacing = 9;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Label label =
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Label(controls, SWT.NULL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("&Package:");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)packageText = new Text(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)controls,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)SWT.BORDER | SWT.SINGLE);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridData gd = new GridData(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridData.FILL_HORIZONTAL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)packageText.setLayoutData(gd);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)packageText.addModifyListener(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new ModifyListener() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void modifyText(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ModifyEvent e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dialogChanged();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)});
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("Blank = default package");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("&Superclass:");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)superclassText = new Text(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)controls,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)SWT.BORDER | SWT.SINGLE);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)gd = new GridData(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridData.FILL_HORIZONTAL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)superclassText.setLayoutData(gd);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)superclassText.addModifyListener(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new ModifyListener() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void modifyText(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ModifyEvent e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dialogChanged();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)});
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("Blank = Object");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("&Interfaces:");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)interfacesText = new Text(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)controls,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)SWT.BORDER | SWT.SINGLE);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)gd = new GridData(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridData.FILL_HORIZONTAL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)interfacesText.setLayoutData(gd);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)interfacesText.addModifyListener(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new ModifyListener() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void modifyText(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ModifyEvent e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dialogChanged();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)});
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("Separated by ','");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dialogChanged();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setControl(controls);
(tng) (tng) (tng) (tng)}
private void dialogChanged() {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String aPackage = getPackage();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String aSuperclass = getSuperclass();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String interfaces = getInterfaces();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String status = new PackageValidator().isValid(aPackage);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(status != null) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)updateStatus(status);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)status = new SuperclassValidator().isValid(aSuperclass);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(status != null) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)updateStatus(status);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)status = new InterfacesValidator().isValid(interfaces);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(status != null) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)updateStatus(status);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)updateStatus(null);
(tng) (tng) (tng) (tng)}
}
public class InterfacesValidator implements ICellEditorValidator
{
(tng) (tng) (tng) (tng)public String isValid(Object value)
(tng) (tng) (tng) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if( !( value instanceof String) )
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return null;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String interfaces = ((String)value).trim();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if( interfaces.equals(""))
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return null;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String[] interfaceArray = interfaces.split(",");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)for (int i = 0; i < interfaceArray.length; i++)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Status status = JavaConventions
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng).validateJavaTypeName(interfaceArray[i]);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (status.getCode() != IStatus.OK)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return "Validation of interface " + interfaceArray[i]
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)+ ": " + status.getMessage();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return null;
(tng) (tng) (tng) (tng)}
}