Personal tools
You are here: Home Documentation Tutorials Understanding and Using GenericSetup in Plone Under the Hood
Support

Get Help

Join our chat rooms or support forums if you have more specific questions.

Plone Training
Learn how to design, build, and deploy a website in Plone through one of the numerous Plone training sessions around the world.
Find Plone training…
 
Document Actions

Under the Hood

A programmer's overview of how GenericSetup profiles work, wherein we learn about exportimport packages and node adapters.

Rob Miller

A detailed look at GenericSetup, wherein we will learn what it is and how it can be used within Plone.
Page 6 of 10.

Okay, enough of the overview stuff.  How does it REALLY work?  What glues it all together?  How would I create my own, completely custom, import steps, in order to configure this really cool thingamajobby that I will be installing in every Plone site I ever touch from this day forward?

The import process is initiated when you tell the setup tool to run some set of import steps.  At this point, GenericSetup will iterate through each of the steps, extracting the "handler" attribute (specified in the step's XML tag in the import_steps.xml file from which it was loaded).  This handler is a callable, usually a function, that accepts a single argument "context", which is some flavor of what GenericSetup calls an "import context".  (The basic set of import and export contexts can be found in the GenericSetup/context.py file.)  By convention, this handler function, and all of the associated adapters and other related import and export code, should live in either a module or a package called "exportimport" in your Product's package.  For example, all of the Plone-specific import / export code lives in the Products.CMFPlone.exportimport package.

So what is this import handler supposed to do, then?  Well, it's supposed to know which XML files in the profile it cares about, and it should read these in.  Then it should query for a multiadapter.  This multiadapter should adapt from some interface that marks the object that is being configured, and from GenericSetup's ISetupEnviron, which is implemented by the import context object.  It should adapt to GenericSetup's IBody interface.  For example, the ZCML that defines this adapter for the Plone properties tool (which can be found in CMFPlone/exportimport/configure.zcml) looks like this:

  <adapter
     factory=".propertiestool.PlonePropertiesToolXMLAdapter"
     provides="Products.GenericSetup.interfaces.IBody"
     for="Products.CMFPlone.interfaces.IPropertiesTool
          Products.GenericSetup.interfaces.ISetupEnviron"
     />
The code that performs the adapter lookup in the importPloneProperties handler looks like this:
importer = queryMultiAdapter((ptool, context), IBody)

'importer', then, will be an instance of the PlonePropertiesToolXMLAdapter class, which implements GenericSetup's IBody interface; I'll leave it as an exercise to the reader to look up that interface, but I'll tell you that it defines a Zope 3 schema which includes a 'body' Text field.  This is implemented (in the XMLAdapterBase that the properties tool's adapter extends) as a property, such that when you set the 'importer.body' to be the XML read in from the configuration file, this XML is parsed (using minidom) and the configuration is applied.

So, if you want have some fancy new frobnozz tool that you want your product to install, and you want to be able to manage the configuration of that tool using XML files in a GenericSetup profile, what would you do?  Here are the steps:

  1. Add a toolset.xml to your extension profile that lists your tool's class, so it will be created during the toolset import step.
  2. Add a handler function in an appropriate place within your product's exportimport package.  This function should accept a 'context' argument, it should read in any XML file(s), and (in most cases) it should set the body attribute to be the content of the XML file.
  3. Create and register an adapter that adapts from an IFrobNozz interface and ISetupEnviron to IBody.  If you're subclassing from XMLAdapterBase, all you'll need to do is implement an _importNode method that accepts the minidom node that is the root of the XML tree in the configuration file.  This should iterate through the tree and perform all necessary configuration.
  4. Add your new import step to your extension profile's import_steps.xml file.
  5. Add your new frobnozz.xml file to the extension profile.

That should do it!

Note that we've been looking at an XMLAdapterBase-based example.  XMLAdapterBase is a good starting point for situations where you have a tool and a single XML file that contains the tool's configuration.  Not all import steps are like this, though, and there are other utility classes that GenericSetup provides in its utils module.  It is beyond the scope of this tutorial to cover them all in detail, but I will list a couple that you should know about:

ObjectManagerHelpers
 When you need to import (or export) folderish objects that contain other objects, you will probably find this useful.
PropertyManagerHelpers
 This provides some assistance when the configuration you need to perform relates to Zope's PropertyManager API.

Note also that, while we have been focusing on the import process, the export process works very similarly.  Usually the same adapter is used for exporting as for importing.  In the XMLAdapterBase situation, you would define an export handler that looked up the adapter, read the 'body' attribute (which would actually trigger introspection of the site state and creation of the DOM nodes and XML that represent that state), and then write this out to the appropriate filename.

 
by Rob Miller last modified June 15, 2006 - 16:18 All content is copyright Plone Foundation and the individual contributors.

For any issues with the web site functionality, please file a ticket.

Please consult the policy on plone.org content if you want your content published on this site.

Servers and hosting by