{"id":380,"date":"2007-10-21T00:00:00","date_gmt":"2007-10-21T00:00:00","guid":{"rendered":"http:\/\/www.strongd.net\/?p=380"},"modified":"2007-10-21T00:00:00","modified_gmt":"2007-10-21T00:00:00","slug":"Download Extensions","status":"publish","type":"post","link":"https:\/\/www.strongd.net\/?p=380","title":{"rendered":"Download Extensions"},"content":{"rendered":"<p><DIV><br \/>\n<DIV id=PageTitle>Download Extensions<\/DIV><br \/>\n<BLOCKQUOTE>Download extensions are sets of classes (and related resources) in JAR files. A JAR file&#8217;s manifest can contain headers that refer to one or more download extensions. The extensions can be referenced in one of two ways:<br \/>\n<UL><br \/>\n<LI>by a <TT>Class-Path<\/TT> header<\/LI><br \/>\n<LI>by an <TT>Extension-List<\/TT> header<\/LI><\/UL>Note that at most one of each is allowed in a manifest. Download extensions indicated by a <TT>Class-Path<\/TT> header are downloaded only for the lifetime of the application that downloads them, such as a web browser. Their advantage is that nothing is installed on the client; their disadvantage is that they are downloaded each time they are needed. Download extensions that are downloaded by an <TT>Extension-List<\/TT> header are installed into the <TT>\/lib\/ext<\/TT> directory of the JRE that downloads them. Their advantage is that they are downloaded the first time they&#8217;re needed; subsequently they can be used without downloading. But as shown later in this tutorial, they are more complex to deploy.<br \/>\n<P>Since download extensions that use the <TT>Class-Path<\/TT> headers are simpler, lets consider them first. Assume for example that <TT>a.jar<\/TT> and <TT>b.jar<\/TT> are two JAR files in the same directory, and that the manifest of <TT>a.jar<\/TT> contains this header: <\/P><br \/>\n<BLOCKQUOTE><PRE>Class-Path: b.jar<br \/>\n<\/PRE><\/BLOCKQUOTE>Then the classes in <TT>b.jar<\/TT> serve as extension classes for purposes of the classes in <TT>a.jar<\/TT>. The classes in <TT>a.jar<\/TT> can invoke classes in <TT>b.jar<\/TT> without <TT>b.jar<\/TT>&#8216;s classes having to be named on the class path. <TT>a.jar<\/TT> may or may not itself be an extension. If <TT>b.jar<\/TT> weren&#8217;t in the same directory as <TT>a.jar<\/TT>, then the value of the <TT>Class-Path<\/TT> header should be set to the relative pathname of <TT>b.jar<\/TT>.<br \/>\n<P>There&#8217;s nothing special about the classes that are playing the role of a download extension. They are treated as extensions solely because they&#8217;re referenced by the manifest of some other JAR file. <\/P><br \/>\n<P>To get a better understanding of how download extensions work, let&#8217;s create one and put it to use. <\/P><\/BLOCKQUOTE><br \/>\n<H3>An Example<\/H3><br \/>\n<BLOCKQUOTE>Suppose you want to create an applet that makes use of the <CODE>RectangleArea<\/CODE> class of the previous section:<br \/>\n<BLOCKQUOTE><PRE>public final class RectangleArea {<br \/>\n    public static int area(java.awt.Rectangle r) {<br \/>\n        return r.width * r.height;<br \/>\n    }<br \/>\n}<br \/>\n<\/PRE><\/BLOCKQUOTE>In the previous section, you made the <TT>RectangleArea<\/TT> class into an installed extension by placing the JAR file containing it into the <TT>lib\/ext<\/TT> directory of the JRE. By making it an installed extension, you enabled any application to use the <TT>RectangleArea<\/TT> class as if it were part of the Java platform.<br \/>\n<P>If you want to be able to use the <TT>RectangleArea<\/TT> class from an applet, the situation is a little different. Suppose, for example, that you have an applet, <CODE>AreaApplet<\/CODE>, that makes use of class <TT>RectangleArea<\/TT>: <\/P><br \/>\n<BLOCKQUOTE><PRE>import java.applet.Applet;<br \/>\nimport java.awt.*;<\/p>\n<p>public class AreaApplet extends Applet {<br \/>\n    Rectangle r;<\/p>\n<p>    public void init() {<br \/>\n        int width = 10;<br \/>\n        int height = 5;<\/p>\n<p>        r = new Rectangle(width, height);<br \/>\n    }<\/p>\n<p>    public void paint(Graphics g) {<br \/>\n        g.drawString(&#8220;The rectangle&#8217;s area is &#8221;<br \/>\n                      + RectangleArea.area(r), 10, 10);<br \/>\n    }<br \/>\n}<br \/>\n<\/PRE><\/BLOCKQUOTE>This applet instantiates a 10 <VAR>x<\/VAR> 5 rectangle and then displays the rectangle&#8217;s area by using the <TT>RectangleArea.area<\/TT> method.<br \/>\n<P>However, you can&#8217;t assume that everyone who downloads and uses your applet is going to have the <TT>RectangleArea<\/TT> class available on their system, as an installed extension or otherwise. One way around that problem is to make the <TT>RectangleArea<\/TT> class available from the server side, and you can do that by using it as a download extension. <\/P><br \/>\n<P>To see how that&#8217;s done, let&#8217;s assume that you&#8217;ve bundled <CODE>AreaApplet<\/CODE> in a JAR file called <TT>AreaApplet.jar<\/TT> and that the class <TT>RectangleArea<\/TT> is bundled in <TT>RectangleArea.jar<\/TT>. In order for <TT>RectangleArea.jar<\/TT> to be treated as a download extension, <TT>RectangleArea.jar<\/TT> must be listed in the <TT>Class-Path<\/TT> header in <TT>AreaApplet.jar<\/TT>&#8216;s manifest. <TT>AreaApplet.jar<\/TT>&#8216;s manifest might look like this, for example: <\/P><br \/>\n<BLOCKQUOTE><PRE>Manifest-Version: 1.0<br \/>\nClass-Path: RectangleArea.jar<br \/>\n<\/PRE><\/BLOCKQUOTE>The value of the <TT>Class-Path<\/TT> header in this manifest is <TT>RectangleArea.jar<\/TT> with no path specified, indicating that <TT>RectangleArea.jar<\/TT> is located in the same directory as the applet&#8217;s JAR file. <\/BLOCKQUOTE><br \/>\n<H3>More about the Class-Path Header<\/H3><br \/>\n<BLOCKQUOTE>If an applet or application uses more than one extension, you can list multiple URLs in a manifest. For example, the following is a valid header:<br \/>\n<BLOCKQUOTE><PRE>Class-Path: area.jar servlet.jar images\/<br \/>\n<\/PRE><\/BLOCKQUOTE>In the <TT>Class-Path<\/TT> header any URLs listed that don&#8217;t end with &#8216;<TT>\/<\/TT>&#8216; are assumed to be JAR files. URLs ending in &#8216;<TT>\/<\/TT>&#8216; indicate directories. In the preceding example, <TT>images\/<\/TT> might be a directory containing resources needed by the applet or the application.<br \/>\n<P>Note that only one <TT>Class-Path<\/TT> header is allowed in a manifest file, and that each line in a manifest must be no more than 72 characters long. If you need to specify more class path entries than will fit on one line, you can extend them onto subsequent continuation lines. Begin each continuation line with two spaces. For example: <\/P><br \/>\n<BLOCKQUOTE><PRE>Class-Path: area.jar servlet.jar monitor.jar datasource.jar<br \/>\n  provider.jar gui.jar<br \/>\n<\/PRE><\/BLOCKQUOTE>A future release may remove the limitation of having only one instance of each header, and of limiting lines to only 72 characters.<br \/>\n<P>Download extensions can be &#8220;daisy chained&#8221;, meaning that the manifest of one download extension can have a <TT>Class-Path<\/TT> header that refers to a second extension, which can refer to a third extension, and so on. <\/P><\/BLOCKQUOTE><br \/>\n<H3>Installing Download Extensions<\/H3><br \/>\n<BLOCKQUOTE>In the above example, the extension downloaded by the applet is available only while the browser which loaded the applet is still running. However, applets can trigger installation of extensions, if additional information is included in the manifests of both the applet and the extension.<br \/>\n<P>Since this mechanism extends the platform&#8217;s core API, its use should be judiciously applied. It is rarely appropriate for interfaces used by a single, or small set of applications. All visible symbols should follow reverse domain name and class hierarchy conventions. <\/P><br \/>\n<P>The basic requirements are that both the applet and the extensions it uses provide version information in their manifests, and that they be signed. The version information allows Java Plug-in to ensure that the extension code has the version expected by the applet. For example, the <TT>AreaApplet<\/TT> could specify an <TT>areatest<\/TT> extension in its manifest: <\/P><br \/>\n<BLOCKQUOTE><PRE>Manifest-Version: 1.0<br \/>\nExtension-List: areatest<br \/>\nareatest-Extension-Name: area<br \/>\nareatest-Specification-Version: 1.1<br \/>\nareatest-Implementation-Version: 1.1.2<br \/>\nareatest-Implementation-Vendor-Id: com.sun<br \/>\nareatest-Implementation-URL: http:\/\/www.sun.com\/test\/area.jar<br \/>\n<\/PRE><\/BLOCKQUOTE>(Please note that there is no <TT>area.jar<\/TT> file at the above URL; this is just an example!) The manifest in <TT>area.jar<\/TT> would provide corresponding information:<br \/>\n<BLOCKQUOTE><PRE>Manifest-Version: 1.0<br \/>\nExtension-Name: area<br \/>\nSpecification-Vendor: Sun Microsystems, Inc<br \/>\nSpecification-Version: 1.1<br \/>\nImplementation-Vendor-Id: com.sun<br \/>\nImplementation-Vendor: Sun Microsystems, Inc<br \/>\nImplementation-Version: 1.1.2<br \/>\n<\/PRE><\/BLOCKQUOTE>Both the applet and the extension must be signed, by the same signer. Signing the jar files will modify them in-place, providing more information in their manifest files. Signing helps ensure that only trusted code gets installed. A simple way to sign jar files is to first create a keystore, and then use that to hold certificates for the applet and extension. For example:<br \/>\n<BLOCKQUOTE><PRE>keytool -genkey -dname &#8220;cn=Fred&#8221; -alias test -keypass mykeypass -storepass mystorepass -validity 180<br \/>\n<\/PRE><\/BLOCKQUOTE>Then the jar files can be signed:<br \/>\n<BLOCKQUOTE><PRE>jarsigner -storepass mystorepass -keypass mykeypass AreaApplet.jar test<br \/>\njarsigner -storepass mystorepass -keypass mykeypass area.jar test<br \/>\n<\/PRE><\/BLOCKQUOTE>More information on <TT>keytool<\/TT>, <TT>jarsigner<\/TT>, and other security tools is at the <A class=OutsideLink href=\"http:\/\/java.sun.com\/javase\/6\/docs\/technotes\/guides\/security\/SecurityToolsSummary.html\" target=_blank>Summary of Tools for the Java 2 Platform Security<\/A>.<br \/>\n<P>Here is <TT>AreaDemo.html<\/TT>, which loads the applet and causes the extension code to be downloaded and installed: <\/P><br \/>\n<BLOCKQUOTE><PRE>&lt;html&gt;<br \/>\n&lt;body&gt;<br \/>\n  &lt;applet code=&#8221;AreaApplet.class&#8221; archive=&#8221;AreaApplet.jar&#8221;\/&gt;<br \/>\n&lt;\/body&gt;<br \/>\n&lt;\/html&gt;<br \/>\n<\/PRE><\/BLOCKQUOTE>When the page is loaded for the first time, the user is told that the applet requires installation of the extension. A subsequent dialog informs the user about the signed applet. Accepting both installs the extension in the <TT>lib\/ext<\/TT> folder of the JRE and runs the applet.<br \/>\n<P>After restarting the web browser and load the same web page, only the dialog about the applet&#8217;s signer is presented, because <TT>area.jar<\/TT> is already installed. This is also true if <TT>AreaDemo.html<\/TT> is opened in a different web browser (assuming both browsers use the same JRE). <\/P><\/BLOCKQUOTE><\/DIV><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Download Extensions Download extensions are sets of classes (and related resources) in JAR files. A JAR file&#8217;s manifest can contain headers that refer to one or more download extensions. The extensions can be referenced in one of two ways: by a Class-Path header by an Extension-List headerNote that at most one of each is allowed &hellip; <a href=\"https:\/\/www.strongd.net\/?p=380\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Download Extensions<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-380","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/380","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=380"}],"version-history":[{"count":0,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/380\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=380"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=380"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}