Some random notes on OSD ======================== Version: 11th December 2001 Original: November 2001 Hugh Pyle Cabezal Limited hpyle@cabezal.com http://www.cabezal.com/ Distribute this document if you want to, but please keep the attribution. I've seen some *really bad* OSD recently. I've also painted myself into several corners with my own *really stupid* OSD. The worst of those is the need to always, forever keep every installable version of my code on my main web server, ad infinitum. That was becoming a pain, but mostly unnecessary (you really only need to maintain every major version of your code). Hence this. If you find it useful, tell me. If you want me to fix your OSD, just ask (although it will cost you a small amount of money). The Component Resource URL ========================== Your components are all refered to by a "component resource URL" which is http://host/path/something.osd?Package=some.package.name&Version=1,2,3,4&Factory=Open in other words, there are usually four parts to this URL - the URL of an OSD file - a package name - a version number - a factory (which tells Groove how to turn that package into a COM object). In the OSD, your SOFTPKG entries have Before we look at the package naming and version numbering, the path to your OSD file should be considered... Server naming ============= These URLs first of all tell Groove how to locate your OSD file. This OSD might be on a different server from your actual code (TPL, GSL files and so on), but usually you'll want to put them all together, on a Web server somewhere. That web server will eventually (you hope) have a large amount of traffic as more and more users install your software. If you have millions of users downloading code from you, you'll need to run a number of servers with the same DNS name. You could use Akamai or something (as Groove do), or you could simply use round-robin DNS to effectively put multiple webservers in parallel. Because of this, you should start with a different name from your regular webserver. And, above all, don't hardcode the IP address. So, this is not good: http://192.168.0.25/root.osd?Package=.... (because it's a fixed IP address, but also because it's not an Internet-visible IP address so nobody outside your LAN would be able to install your tools!) and this is not too great either http://www.mycompany.com/root.osd?Package=.... because you really want to name a different server as soon as possible, like this: http://components.mycompany.com/root.osd?Package=.... and set up DNS to point at the right machine (often your main web server, of course, but this way you can at least change it later). OSD Path ======== Groove have a single OSD file ("Root.osd") which redirects to the various other OSD files used to decsribe their tools. That's a good thing. But it takes a lot of coordination to release tools with this method (you basically need to sign the whole of Root.osd and all its dependents every time you release a tool), and it also means that anyone can browse your root OSD file to discover tools you'd rather not tell people about. For these reasons I take the lazy route: a separate OSD file for each tool. I also put these OSD files under a subdirectory structure, not in the Web server's root directory. The root of that directory structure in my case is "/Cabezal/" because I might want to host tools from other companies, and they would each get their own subdirectory structures "/ThatCo/" and so on. So a typical URL would then start http://components.mycompany.com/MyCompany/Tools/ThisTool/ThisTool.osd?Package=.... Package naming ============== It's usual to name packages according to the Java convention of "reverse domain names", so packages from cabezal.com are named "com.cabezal.package1", packages from Agora are named "uk.co.agora.package1" and so on. If you don't do this, OSD has no way to distinguish between the two "package1" packages. It's convenient also to subdivide your packages even more. For example com.cabezal.skins.fun.xxxx com.cabezal.tools.games.bridge com.cabezal.tools.general.autosurf com.cabezal.tools.business.billing com.cabezal.tools.business.procurement so that you can scale to as many tools, skins etc as you create over time, without needing to rearrange your whole package-name hierarchy. Version numbering ================= The four version numbers are: - major version - minor version - major internal build - minor internal build Always ignore the last two; Groove's component manager does. Start at version 0,0 for development. Move to major version 1 when you release to the public. Increment the major version whenever you change to an incompatible file format (ie. when your recordset schema changes, or when you add roles&permissions for the first time, etc). Major versions need to be able to live side-by-side with each other in the same machine, so you should use different filenames. Increment the minor version whenever you release a new injectable version of the tool. Minor versions must be backward-compatible (same data structures, etc). Minor versions overwrite each other. Injectable ========== (the GRV file) The injectable's TemplateDescriptorURL should include the major and minor version numbers. When a user clicks the injectable it will inject that specific version of the tool. Alternatively you can create an injectable which only includes the major version number, but in the case where the user already has a version with that major version number, they will not inject the later version. Descriptor ========== The descriptor's "ResourceURL" should only contain the major version number. (Caveat: For some enterprise acceptance you may want the descriptor to specify the minor version too: for example, if a company has a lengthy acceptance cycle and wants to guarantee that exactly the right version is installed, you'll need to specify the minor version). When you add a tool into a space, this actually stamps a copy of the tool's descriptor into the telespace (it doesn't put any of the tool's code in there). So, when other users see that this tool has been added to the space (or when new users are invited), the space says: "you need tool xxx version y". If they already have the tool (same major version, any minor version) it just works. If they do not already have the tool, they will automatically install the *latest* tool with that major version. Generally, this is exactly the behaviour you want. If, instead, your descriptor included the major and minor version numbers: - user Alfred injects version 1.7 - user Alfred adds this tool to a space. The space now includes a descriptor for version 1.7 - tool author Tony creates an update, version 1.8 - Alfred injects version 1.8; fine. No effect. This still works in his space. - Alfred invites another user Brian who did not have the tool. - Brian sees the descriptor: "you need version 1.7". Attempts to download version 1.7 - Brian obtains an obsolete version of the tool. - Tony must maintain all obsolete versions of the tool on his web site. OSD === g:ComponentURLProvider will become obsolete sometime. Just remove all these lines from your OSD. If you had used g:ComponentURLProvider to create "implicit" dependencies (for example, on a script library) without specifying those dependencies in your OSD, you should instead make them explicit in the OSD. Structure dependencies in a way which makes sense. The simplest way is - everything depends on the descriptor - if there are script libraries or images etc used by a tool template, make them depend on the tool template so you end up with an OSD structure such as Localhost ========= When you inject a tool, Groove looks in the localhost directory (under groove/data) before looking at the web server specified in the component resource URL. So if you have a localhost directory with development versions of your tool, they'll be found before (or instead of) the published versions. To avoid confusion it helps to keep your localhost directory as empty as possible!