跳到导航
BEA Dev2Dev Oracle and BEA
首页 资源中心 dev2dev学堂 在线技术论坛 User Group CodeShare
dev2dev 首页 > 资源中心 > 技术文章
Workshop控件和扩展:第一部分——编写扩展

时间:2005-05-08
作者:Emmanuel ProulxKunal MittalLucian Agapie
浏览次数:
本文关键字:Workshop扩展
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章
  BEA WebLogic Workshop 8.1(™)为知道如何扩展它的程序员提供了很多的机会。本文给出了一个如何通过添加菜单选项、工具栏按钮和框架来扩展Workshop的实例。本文是研究Workshop控件和扩展系列文章的第一篇。随后的文章将涉及帮助系统、向导、分发和其他主题。

  我们正处在一个聚合的年代。当技术合并的时候,就会发生聚合。BEA在向我们推出WebLogic Workshop 8.1的时候,合并了J2EE、Web服务和WebLogic Platform技术的最佳特性。同时,BEA为将定制技术合并到Workshop中打开了大门。它是通过使用控件 和扩展 实现的。
  Workshop包含了一种高度可定制的用户界面,该界面包含了开发环境、类、运行时环境等。在该系列中,我们将研究这些特性中的一部分。我们将通过开发一套其他IDE厂商称为“插件”的控件和扩展来开展研究。在该系列文章结束之后,您就可以非常轻松地构建WebLogic Workshop环境的任意扩展。

案例分析
  在我们开始编写控件和扩展之前,首先需要研究一个案例。有时,我们需要和远程开发人员协同工作。让我们假定这些开发人员不具有源控件存储库的访问权限。发送代码给这些开发人员的一个好办法就是通过电子邮件。但是打开电子邮件客户端、添加Java文件附件、然后发送邮件的过程需要几分钟的时间。如果您可以从Workshop内部直接发送文档,那又会是什么情况呢?
  在本文中,我们将创建一个简单的电子邮件客户端,该客户端可以通过按钮激活,或者通过菜单项激活。
  通过完成该项目,您可以掌握如何:
  • 创建、管理、构建和部署扩展项目。
  • 在Workshop中创建菜单项、工具栏按钮和视图
  • 有计划的调用扩展

扩展点
  扩展点是一种可以确定Workshop主程序和扩展之间的界面的机制。它包含一套预定义的位置,这些位置允许在主用户界面上插入任意的新项目,如菜单、工具栏、按钮和视图。
  Workshop核心具有一套扩展点。定制扩展可以使用这些扩展点来添加它们自己的特性。这些定制扩展所添加的它们自己的扩展点,又可以为其他扩展所用。该操作创建了一种分层结构的扩展点。
  扩展点可以通过名称(文本值)来进行检索。他们可以保留各种类型的对象,取决于扩展点的类型。这说明必须将所有的扩展点记录下来才可以使用。Workshop帮助系统中提供了一份基本扩展点的列表。如需要察看该列表,请转到菜单Help | Help Topics,然后导航到该类别:
  Extension Development Kit -> Extending the WebLogic Workshop IDE -> Extension XML Reference
  如果一个扩展希望将自身添加到Workshop中,则它必须执行以下两种方式中的一种:
1. 以声明的方式列出通过部署描述符extension.xml添加到扩展点中的对象
2. 以编程的方式添加这些对象;这必须以某种方式触发,因此通常将初始化对象添加到extension.xml中
  随后,extension.xml文件会发生更多聚合。

扩展项目的结构
  通常,扩展就是具有如图1所示结构的Workshop项目。我们的项目将与此图具有相同的外形。


图1.项目结构

  下表描述了这些文件夹和文件。

项目 描述 文件夹
controls_extension 承载一个或者多个扩展和控件的应用程序 /controls_extensions
my_email 承载单个扩展或者控件的项目 /controls_extensions/my_email
META-INF 存档元信息文件夹 /controls_extensions/my_email/META-INF
extension.xml 部署描述符,包含扩展点/对象映射 /controls_extensions/my_email/META-INF/extension.xml
MANIFEST.MF 存档的证明文件。包含运行时扩展所需的类路径 /controls_extensions/my_email/META-INF/MANIFEST.MF
src 适用于所有项目代码文件的基础文件夹 /controls_extensions/my_email/src
dev2dev/
controls_extensions
源文件包 /controls_extensions/my_email/src/
dev2dev/controls_extensions
images 一些扩展对象(工具栏按钮、菜单)可能包含图形;该文件夹承载这些图形。 /controls_extensions/my_email/src/images
email.gif 电子邮件菜单项和工具栏按钮使用的图像。 /controls_extensions/my_email/src/images/email.gif
build.xml Ant构建脚本;创建扩展归档文件 /controls_extensions/my_email/build.xml
Libraries 包含支持库列表,该列表不在Workshop的类路径中,但是在编译和运行时需要使用。 /controls_extensions/APP-INF/lib

  其他的文件夹与我们无关。注意,最后一个项目并不像它所代表的文件夹那样命名。
图2说明了编译和存档了扩展之后产生的JAR文件。


图2.Java归档结构

  在JAR文件中,当已编译的文件出现在项目之中时,您可以在它们的文件包和其他支持文件中找到它们。

扩展Workshop
  以下部分提供了创建电子邮件项目的分步向导。本文结尾处还附加了全部的源代码,供下载使用。
  我们将通过研究开发的几个阶段来描述如何添加扩展:创建项目结构、创建构建支持文件、创建扩展文件、构建扩展文件、创建支持文件,以及最后,实现扩展。

设置项目
  在这个阶段,我们将说明您如何为扩展创建Workshop项目,以及设置类路径和集成的调式程序。

1. 首先,我们将创建一个新的应用程序。从主菜单中选择File | New | Application。在New Application对话框中,从All类别中选择Empty Application。在Directory字段中输入“dev2dev”,在Name字段输入“controls_extensions”。退出示例Workshop服务器,该服务器作为缺省值出现在Server中,然后点击Create按钮。
此时会创建名称为controls_extensions的目录和名称为Modules、Libraries和Security Roles的子目录,并出现在Application窗格中。这就是将承载扩展的应用程序。单个应用程序可以包含多个项目,例如扩展和控件。

2. 为扩展添加新项目。右键点击Application窗格中名称为controls_extensions的文件夹,然后选择File | New | Project。在名称为New Project的对话框中选择Business Logic类别中的Java Project。在Project Name字段中输入“my_email”,然后按Create按钮。一个名称为my_email的新文件夹将出现在controls_extensions下的Application窗格中。
该项目代表单个扩展。它将被构建到可部署的扩展JAR文件中。

3. 为源文件创建储存库。右键点击my_email,选择New|Folder,在Create New Folder对话框中输入“src”,然后点击OK。这就是所有的Java文件保存在各自文件包中的位置。仅有该文件夹被编译。其他文件夹包含支持文件。

4. 设置项目的属性。在Application窗格中右键点击项目my_email,然后从菜单中选择Properties。项目属性对话框就会出现。我们可以在该对话框中进行很多设置。
注意:如果没有设置这些属性,则所提供的源代码可能不编译。

a)选择Paths类别。

  • 类路径:Workshop扩展需要特殊的资料库,以便于编译和执行。这是wlw-ide.jar资料库,它包含了所有的扩展类和接口。当Workshop启动的时候它在类路径中,但是在编译扩展的时候它不在类路径中。我们需要添加它。点击位于窗口右侧的Classpath列表旁边的Add Jar按钮,然后浏览以查找:BEA_HOME\weblogic81\workshop\wlw-ide.jar,BEA_HOME是安装BEA WebLogic的文件夹。这就确保提供了编译应用程序所需的类。
  • 类路径:我们不需要编译项目中的所有内容。仅有src文件夹包含Java代码。我们可以在此指定。点击窗口右侧的Source Path列表旁边的Add Path按钮。浏览以查找C:\bea\user_projects\applications\controls_extensions\src文件夹,然后点击Select Directory。

    b)为了编译扩展,我们可以依靠默认的Workshop构建机制。但是该机制不允许我们自动部署扩展。执行该操作的唯一方法是使用Ant构建脚本。Workshop可以创建一份可定制的默认脚本。选择窗口左侧的Build按钮。
    在Build Type下方的右部,点击“Use IDE build”下的“Export to ant file”,然后点击对话框中的OK按钮。此操作将在my_email文件夹中创建一个名称为exported_build.xml 的新文件。我们将在随后定制该文件。

    c) Workshop是适用于扩展开发的一种优秀工具,因为它具有集成的调试程序。但是在我们可以调试应用程序之前,必须配置Workshop。在窗口的左侧选择Debugger。
      在窗口右侧的Debugging Options中,选择“Build before debugging”,而不选择“Pause all threads after stepping”,然后选择“Create new process”单选按钮。在Main Class字段中输入“workshop.core.Workshop”,并启用“Smart debugging”。此时,扩展已准备好进行调试了。在代码中简单地设置一个断点,然后运行调试程序。一个Workshop的新实例将被生成,而您可以逐步进入扩展的代码之中!
      有关调试选项的更多信息,请参见Setting Up Extension Debugging Properties。

    创建构建支持
      在这个阶段,我们将说明您如何定制Ant构建文件。

5. 构建文件定制:由于“exported_build.xml”不是一个常见名称或者标准,所以让我们来重新命名它。在Application窗格中,右键点击my_email项目文件夹中的文件exported_build.xml,然后从弹出菜单中选择Rename。将其重命名为“build.xml”,以便于Ant识别。
  双击build.xml,在编辑器窗口中将其打开。我们将在构建任务的结尾处添加以下语句:

  这些语句将在扩展部署文件夹中创建新的JAR文件,并且可以在下一次Workshop启动的时候立即执行。
  在这之下添加以下语句:

  该命令可以把第三方mail.jar资料库复制到部署文件夹中。
  定制的最后一步是使Workshop使用新的Ant脚本,而不是默认脚本。此外,打开项目属性,然后在Build类别中点击Use Ant Build单选按钮。保留缺省值。

创建extension.xml
  此时,我们已经完成了准备工作。让我们深入到编码部分。
6. Workshop期待在名称为META-INF的文件夹中查找到控件和扩展部署描述符。让我们来创建它。右键点击my_email项目文件夹,然后从弹出菜单中选择New | Folder。在Dialog框中输入“META-INF”,然后点击OK。
在这个阶段,我们将说明您如何创建一份扩展点文件,以及如何按照需求来定制该文件。创建新扩展点的机制已经超出了本文研究的范围。

7. 添加文件extension.xml。这样可以按照前面所解释的那样来定义扩展对象。右键点击META-INF文件夹,然后从弹出菜单中选择New | Other File Types。在出现的New File对话框中,从Common类别中选择“XML file”,并将其命名为“extension.xml”。然后点击Create按钮。警告:如果文件名称或者其内容有录入错误,则扩展可以进行编译,但是不会起作用。也不会出现任何的错误消息。
  让我们编写extension.xml的内容。该文件以根标记<extension-definition>开头。其中包含了一份<extension-xml>标记列表。每一个标记描述一种扩展点。我们需要创建一个工具栏按钮和一个菜单项。这些扩展都将被添加到类型为“action”的扩展点中。因此,以下语句用于指定action扩展:

<extension-xml id="urn:com-bea-ide:actions">

  属性“id”包含令我们感兴趣的那种扩展点的唯一标示符。<extension-xml>标记内部的语法在文档中指定。它对每一种扩展点来说都是很特殊的。对“actions”来说,语法是两个标记。<action-ui>和<action-set>。第一个标记指定要创建的可视元素(菜单、弹出菜单、工具栏按钮)并将其关联到操作。第二个标记列举了这些操作和类型IAction的Java类。

以下是完整的列表:

<extension-definition>
    <extension-xml id="urn:com-bea-ide:actions">

        <action-ui>
            <menu id="email" path="menu/main" priority="100" label="E&amp;mail">
                <action-group id="messagesgroup" priority="10"/>
            </menu>

            <toolbar id="my_email" path="toolbar/main" priority="2" label="Email">
                <action-group id="default" priority="10"/>
            </toolbar>
        </action-ui>

        <action-set>
            <action class="dev2dev.controls_extensions.EmailApplication" 
            label="E&amp;mail" icon="images/email.gif" show-always="true">
                <location priority="10" path="menu/email/messagesgroup"/>
            </action>

            <action class="dev2dev.controls_extensions.EmailApplication" 
            label="Email" icon="images/email.gif" show-always="true">
                <location priority="10" path="toolbar/my_email/default" />
            </action>
        </action-set>

    </extension-xml>
</extension-definition>
  该文件的一些注意事项:
  • 菜单项和工具栏按钮的相对位置通过整数“priority”属性指定。
  • path属性可以作为已经存在的菜单或者工具栏的参考。它包含一个父菜单/工具栏ID的列表,由左斜杠(“/”)分开。您如何知道使用哪一些ID呢?不幸的是,这里没有详细记录。我们必须通过在文件extension.xml中仔细研究Shell扩展(C:\bea\weblogic81\workshop\extensions\shell.jar)才能知道。此处就是创建基本菜单和工具栏的位置。
  • 键盘快捷键以“&”字符表示(如果在XML中编码,则其为“&amp;”)。
  • 图片通过classloader进行加载。因此,必须作为到src文件夹根目录的相对路径来指定他们。
  • 这里有两种UI元素(工具栏按钮和菜单项),但是只有一种操作。两种UI元素执行相同的操作。

创建支持文件
  在这个阶段中,我们将说明您如何创建项目的支持文件。

8. 在META-INF文件夹中创建文件MANIFEST.MF。这可以告诉Workshop在何处查找任意的第三方资料库。在我们这种情况中,我们需要JavaMail API资料库文件。这是MANIFEST.MF的内容:

Class-Path:../lib/mail.jar

  扩展JAR文件的目标文件夹是C:\bea\weblogic81\workshop\extensions。因此将一个文件转到上一层并且进入到lib文件夹,这意味着文件mail.jar位于文件夹C:\bea\weblogic81\workshop\lib中。

9. 正如我们刚才讨论的那样,图形文件被放在src中的images子文件夹中。工具栏按钮和菜单项的图形是16x16的GIF文件,其背景设置为透明。我们已经创建了文件email.gif,因此您不必绘制自己的文件;只需要将此图标保存到计算机中:

实现扩展:
在前面的部分中,我们定义了需要为<action>元素的class属性中的操作而执行的类。现在,我们将实现这个类。

10. 让我们来为操作类进行编码。创建文件:/dev2dev/controls_extensions/EmailApplication.java。该类必须实现Iaction接口。执行该操作的一种简便方法是细分DefaultAction。使用该方法时仅实现actionPerformed()方法即可。这种方法在执行该操作的时候由Workshop调用。在我们这种情况中,这种方法会为输入电子邮件信息打开一个新的框架。我们将在以后创建该框架。目前,请仅输入以下列表:

package dev2dev.controls_extensions;

import com.bea.ide.actions.DefaultAction;
import com.bea.ide.ui.frame.FrameSvc;
import java.awt.event.ActionEvent;
import javax.swing.JOptionPane;
import net.sourceforge.jiu.util.Statistics;

public class EmailApplication extends DefaultAction {
    public void actionPerformed(ActionEvent e) {
        FrameSvc.LayoutConstraints layout = new FrameSvc.LayoutConstraints();
        layout.askAvailable = false;
        layout.exact = false;
        layout.focus = true;
        layout.hasAction = false;
        layout.hasMenu = false;
        layout.icon = null;
        layout.insert = true;
        layout.label = "eMail";
        layout.open = true;
        layout.orientation = FrameSvc.NORTH;
        layout.proportion = 0.20;
        layout.scope = null;
        layout.viewClassDest = null;
        layout.viewIdDest = "main";
        layout.visible = true;

        FrameSvc.get().addView("dev2dev.controls_extensions.EmailFrame", layout);
    }
}
  这段代码是如何有计划的例示扩展的一个示例。读者还可以通过在extension.xml中添加框架扩展来显示这个相同的窗格。
  Workshop包含了很多类,这些类允许操作其窗口操作系统和内部状态。FrameSvc是一种帮助程序类,可以在Workshop GUI中创建新的窗格。在此,我们根据名称调用了EmailFrame类,并且我们使用LayoutConstraints对象指定了其位置。请参考Workshop中有关这些类的帮助文档。可通过选择菜单Help | Help topics,然后在类别WebLogic Workshop Reference、Workshop API Javadoc Reference、Extension API Reference中获得帮助。您可以从对很多类的浏览中体验到很多乐趣。

11. 类EmailFrame仍不存在,因此addView()将不会出现在前面的列表中。让我们来添加遗失的类。创建文件:/dev2dev/controls_extensions/ EmailFrame.java.
Frame是一个实现IFrameView接口的类。这个接口有两种方法,它们是:
  • isAvailable():指出(真或者假)Workshop是否处于一种允许显示框架的状态。如果需要,我们可以在某些特定情况中禁止显示框架。
  • getView():返回一个作为框架显示的直观的Component。通常,它是JPanel。
package dev2dev.controls_extensions;

import java.awt.Component;
import java.awt.FlowLayout;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import com.bea.ide.Application;
import com.bea.ide.document.IDocument;
import com.bea.ide.ui.frame.IFrameView;

import com.bea.ide.util.IOUtil;

public class EmailFrame extends JPanel implements IFrameView {
    JTextField toField;
    JTextField subjectField;
    JButton sendBtn;
    Session mailSession;

    public EmailFrame() {
        this.initComponents();
    }

    public Component getView(String arg0) {
        return this;
    }

    public boolean isAvailable() {
        return true;
    }

    private void initComponents() {
        this.setLayout(new FlowLayout());
        sendBtn = new javax.swing.JButton();
        sendBtn.setText("Send");
        sendBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent event) {
                Session session = getMailSession();
                MimeMessage msg = new MimeMessage(session);

                try {

                String messageText;

                IDocument doc = Application.getActiveDocument();
                messageText = IOUtil.read(doc.getURI());
                msg.setText(messageText);

                Address fromAddr = new InternetAddress(
                    "sender@exemaple.com",
                    "Joe Doe");

                msg.setFrom(fromAddr);
                Address toAddr = new InternetAddress(toField.getText(), null);
                msg.addRecipient(Message.RecipientType.TO, toAddr);

                msg.setSubject(subjectField.getText());

                Transport.send(msg);

                } catch (Throwable e) {

                    JOptionPane.showMessageDialog(null, e.toString(),
                        "Error while sending mail!",
                        JOptionPane.ERROR_MESSAGE);
                 }

            }
        });
        JLabel toLabel = new JLabel("To:");
        toField = new JTextField(40);
        JLabel subjectLabel = new JLabel("Subject:");
        subjectField = new JTextField(40);
        add(toLabel);


        add(toField);
        add(subjectLabel);
        add(subjectField);
        add(sendBtn);
    }

    protected Session getMailSession()
    {
        if (mailSession == null) {
            Properties p = new Properties();
            p.put("mail.host", "mailServerAddress");
            p.put("mail.user", "userName");
            p.put("mail.password", "passwod");

            mailSession = Session.getDefaultInstance(p,  null);
        }
        return mailSession;
    }
}
  

简而言之,我们在此创建了包含To(目标地址)字段的 JPanel、Subject字段和Send按钮。在Send按钮中,我们使用JavaMail API来发送其文档在编辑器中已经打开的电子邮件。
  这里使用了三种有趣的类。一种是Application,用于检索活动(打开)的文档。第二种是IDocument,一种代表文档的接口。它具有一种可以返回文件位置的getURI()方法。最后一种是非常酷的IOUtil,可以用于将文件复制到String中。如上所述,这些全部都记录在Extension API Reference中。

结果
  在项目构建完成之后,从主菜单中选择Debug | Start。注意工具栏左侧的电子邮件图标和主菜单中名称为Email的新项。如果您点击图标,在顶部就会出现一个新的框架,该框架包含To和Subject字段,以及Send按钮,如图3所示。


图3.项目结果

结束语
  利用Workshop强大的、易于使用的扩展机制,聚合就不再是可望而不可及的事了。无论您在企业中使用了什么技术,您都可以轻松地将其作为扩展或者控件集成到Workshop中。正如您可以看到的,在Workshop中有很多工具需要研究,因此有数不清的应用程序等待人们去开发。
  在下一篇文章中,我们将探讨Workshop帮助系统,同时补充一种具有适合正式验证的文档的控件(可以将经过验证的控件和扩展添加到 Premier Component Gallery中)。

参考资料

下载
  本文中描述的扩展的源代码可以通过点击以下链接得到。它是压缩格式的Workshop应用程序。如果想启动该应用程序,请首先解压缩ZIP文件,然后双击.work文件。系统将提示您选择运行时环境,此时选择默认值(示例)即可。

controls_extensions.zip (318 KB)

  Emmanuel Proulx是J2EE和Enterprise JavaBeans方面的专家。他是一位获取证书的WebLogic Server 7.0工程师。Emmanuel的工作涉及到电信和Web开发领域。Emmanuel开发了电话(SIP)应用程序、IDE插件、电子商务系统、各种Web应用程序,他还出版了很多著作和文章。他是Laura(2)和Simon(4)引以为自豪的父亲。
  Lucian Agapie是一位高级电气工程师和IEEE成员,他喜欢使用Java、C++和TCL/TK 编写软件应用程序。他在电信行业工作,非常热衷于在家庭自动化方面应用人工智能。现在,他正从事开发新的IDE插件。

原文出处
http://dev2dev.bea.com/products/wlworkshop81/articles/wlwseries_extensions.jsp

 作者简介
Emmanuel Proulx 是一位J2EE和Enterprise JavaBeans方面的专家,也是一位获得认证的WebLogic Server 7.0工程师。
Kunal Mittal是Web services的实现和战略,以及面向服务的架构方面的顾问。他与人合著或参与编撰了几本Java、WebLogic和Web services方面的书籍。
dot dot dot

dot
  作者其它文章
您对本文的评价
您对这篇文章的看法如何?
太棒了!5分 不错啊 4分 一般般 3分 有待提高 2分 不好 1分