Jigsaw 2.0 Internal design

# Jigsaw
Resource tutorial

Jigsaw Home / Documentation Overview / Tutorials

This tutorial explains you how to write a new resource, by walking through a complete example. It is assumed that you are familiar with Jigsaw architecture, and that you have understand the configuration tutorial.

The resource we will write here will be the PassDirectory. The tutorial will go through the following steps:

1. writing the resource class,
2. installing and configuring it.

# Writing the resource class

Before actually writing a new resource, some decisions must be made about:

1. What will be its super class
2. In what package should it go
3. What attribute should it define
4. What method should it redefine

## Picking a super class

Deciding for the super class of your resource is a pretty simple process right now. Here are the rule of thumbs:

- If your resource is supposed to wrap a file, then you have to choose FileResource as your super class.
- If your resource is to wrap a directory, then you have to choose org.w3c.tools.resource.DirectoryResource (or org.w3c.jigsaw.resources.DirectoryResource if you need content negotiation)
- If you need to manage children then you probably want to sub-class the ContainerResource.
- In any other case, you need to pick FramedResource as your super class.

Given these short rules, it should be obvious that for our sample resource, what we want to do is subclass the DirectoryResource. So right now, we can start writing the following piece of code (we will keep in bold the additional code we add as we walk through the example):
Note that we don't know yet were to put this file until we have selected an appropriate package for our resource.

    import java.util.*;
    import java.io.*;
    import org.w3c.tools.resources.*;

    public class PassDirectory extends org.w3c.jigsaw.resources.DirectoryResource {

    }

## Selecting a package

There is no particular problem with regard to the package your resource belong to: Jigsaw impose no constraint on this. The only thing you should be aware of is your CLASSPATH environment variable. This variable setting is particularly crucial in Jigsaw since it may impact its security: you don't want anyone to be able to plug new resource classes in the server !

For our sample resource, we don't need to create a new package, let's use `org.w3c.jigsaw.resources`. We can write in it the following PassDirectory.java file:

    package org.w3c.jigsaw.resources ;

    import java.util.*;
    import java.io.*;
    import org.w3c.tools.resources.*;

    public class PassDirectory extends org.w3c.jigsaw.resources.DirectoryResource {

    }

## Defining the attributes

The next thing we have to figure out, is the list of attributes for our new frame. The DirectoryResource already defines a number of attributes (see the reference manual). Defining the set of attributes of a resource also defines the way the resource will be configured (since a resource is configured by editing its attribute values). Here, we want to be able to configure the target directory that will be wrapped by the resource.

The directory wrapped by the resource can be described as an editable FileAttribute, which has no defaults value.

Now that we now the attribute our resource is to have, we should declare it to the AttributeRegistry. This Registry keeps track of all the attributes of all resource classes. For each class it knows of, it maintains an ordered list of the attribute it defines. The fact that this list is ordered is important, since it allows for fast attribute value access (through a simple indirection in the attribute value array of each resource instance). Attribute declaration should be done at class initialization time, so we introduce a static statement in the class, whose purpose is to declare our attribute:

    package org.w3c.jigsaw.resources ;

    import java.util.*;
    import java.io.*;
    import org.w3c.tools.resources.*;

    public class PassDirectory extends org.w3c.jigsaw.resources.DirectoryResource {

        /**
         * Attribute index - The target physical directory of this resource.
         */
        protected static int ATTR_PASSTARGET = -1 ;

        static {
            Attribute a   = null ;
            Class     cls = null ;

            // Get a pointer to our class.
            try {
                cls = Class.forName("org.w3c.jigsaw.resources.PassDirectory") ;
            } catch (Exception ex) {
                ex.printStackTrace() ;
                System.exit(1) ;
            }
            // The directory attribute.
            a = new FileAttribute("pass-target"
                                  , null
                                  , Attribute.EDITABLE);
            ATTR_PASSTARGET = AttributeRegistry.registerAttribute(cls, a) ;
        }
    }

## Redefining some methods

At this point, we have declared the set of attributes that our resource defines, the attribute Registry knows about it, we can now focus on the actual behavior of the resource. The only difference between PassDirectory and DirectoryResource is that PassDirectory wraps an external directory instead of the inherited one.
In this case, we have to redefine the followings method of DirectoryResource:

- `public void setValue(int idx, Object value)`
- `public File getDirectory()`
- `public void initialize(Object values[])`

The actual implementation of these methods is the following:

    package org.w3c.jigsaw.resources ;

    import java.util.*;
    import java.io.*;
    import org.w3c.tools.resources.*;

    public class PassDirectory extends org.w3c.jigsaw.resources.DirectoryResource {

        /**
         * Attribute index - The target physical directory of this resource.
         */
        protected static int ATTR_PASSTARGET = -1 ;

        static {
            Attribute a   = null ;
            Class     cls = null ;

            // Get a pointer to our class.
            try {
                cls = Class.forName("org.w3c.jigsaw.resources.PassDirectory") ;
            } catch (Exception ex) {
                ex.printStackTrace() ;
                System.exit(1) ;
            }
            // The directory attribute.
            a = new FileAttribute("pass-target"
                                  , null
                                  , Attribute.EDITABLE);
            ATTR_PASSTARGET = AttributeRegistry.registerAttribute(cls, a) ;
        }

        /**
         * Catch side-effects on pass-target, to absolutize it.
         * @param idx The attribute to set.
         * @param value The new value.
         */

        public void setValue(int idx, Object value) {
            super.setValue(idx, value);
            if ( idx == ATTR_PASSTARGET ) {
                File file = (File) value;
                if ( ! file.isAbsolute() ) {
                    // Make it absolute, relative to the server space.
                    File abs = new File(getServer().getRootDirectory()
                                        , file.toString());
                    values[ATTR_PASSTARGET] = abs;
                    values[ATTR_DIRECTORY]  = abs;
                }
            }
        }

        /**
         * The getDirectory method now returns the pass-directory.
         * @return The pass target location.
         */

        public File getDirectory() {
            return (File) getValue(ATTR_PASSTARGET, null) ;
        }

        /**
         * Make the directory attribute default to the target location.
         * This is required for classes that rely on the directory attribute to
         * compute their own attributes.
         * @param values The values we should initialized from.
         */

        public void initialize(Object values[]) {
            super.initialize(values);
            File target = getDirectory();
            if ( target != null )
                setValue(ATTR_DIRECTORY, target);
        }
    }

# Installing the resource

After reading the Resource configuration tutorial you will be able to install the PassDirectory.

The example we have been walking through is probably one of the simplest one, however, by now, you shouldn't have to write a new resource class but a new frame class, see the internal design of Jigsaw.

Enjoy !