Package com.ibm.portal.resolver.data

Provides for the interfaces required to serve data via the POC resolution framework.

See:
          Description

Interface Summary
Addressable Interface that allows to retrieve the address of a piece of content.
ByteDataSink Implemented by comsumers of byte data streams.
ByteDataSource Implemented by providers of byte data streams.
CacheControlDataSource Interface that may optionally be implemented by a DataSource to fine tune how the content of the data source is cacheable.
CharDataSink Identifies a data sink that is able to handle text feeds.
CharDataSource Implemented by providers of character data streams.
ContentDispositionDataSource Captures information about the presentation of the data source
ContentLengthDataSource Optional interface implemented by a DataSource to advertize the size of the data.
ConvertibleDataSource Describes a DataSource that can be converted to another DataSource interface, typically used for type conversion of the content.
CreateDataSinkFactoryEx Tagging interface that is used to register a data sink factory explicitly for create operations (e.g.
DataSink Base interface implemented by all data sinks, independent on their actual stream type.
DataSinkFactoryEx Tagging interface for data sink factory.
DataSource Base interface implemented by all data sources, independent on their actual stream type.
DataSourceChecksum Provides the checksum for a data source.
DataSourceFactory Tagging interface for data source factory.
DataSourceFactoryEx Data source factory that allows to instantiate DataSource objects.
DataSourceFragment Represents a fragment of a complete data source.
DataSourceHandler Callback interface that indicates the existance of a DataSource.
DataSourceParser Abstraction of a parser that parses the content of the DataSource onto a handler.
DeleteDataSinkFactoryEx Tagging interface that is used to register a data sink factory explicitly for delete operations (e.g.
FormDataDataSink Data sink that accepts a multipart data request.
JsonDataSink Identifies a data sink that is able to handle json feeds.
JsonDataSource Implemented by providers of Json data streams.
MultipartDataSink Data sink that accepts a multipart data request.
MultipartDataSource Support for producing multipart responses.
ProjectContextDataSource Interface that may optionally be implemented by a DataSource to indicate if the content of the data source depends on the currently selected project.
RedirectDataSource Data source that allows to redirect to a different URL.
StatusCodeDataSource Optional interface implemented by a DataSource to specify a suggested status code.
UpdateDataSinkFactoryEx Tagging interface that is used to register a data sink factory explicitly for update operations (e.g.
URIParser Parses the content of the static page that is identified by the URI.
URIParserFactory Constructs URIParser instances
UserContextDataSource Interface that may optionally be implemented by a DataSource to indicate if the content of the data source depends on the current user context.
VaryDataSource Interface that may optionally be implemented by a DataSource to fine tune what context information a data source depends on.
VirtualPortalContextDataSource Interface that may optionally be implemented by a DataSource to indicate if the content of the data source depends on the currently selected virtual portal.
VoidDataSink Realization of a DataSink that does not require the input stream to generate output.
XmlDataSink Identifies a data sink that is able to handle XML feeds.
XmlDataSource Implemented by providers of XML data streams.
 

Class Summary
DataURI An URI class that represents data URIs as defined in http://tools.ietf.org/html/rfc2397
FileTypeMap Extension to the standard file type map that determines the mime type based on the content
 

Enum Summary
CacheControlDataSource.CACHE_POLICY Controls how the content is cached
CacheControlDataSource.CACHE_SCOPE Possible scope for the cache result
ContentDispositionDataSource.DISPOSITION Possible content dispositions,
 

Package com.ibm.portal.resolver.data Description

Provides for the interfaces required to serve data via the POC resolution framework.

POC DataSource

Using POC addressability it is possible to handle GET operations on a particular piece of content. For each POCURI handlers can be registered that will be invoked, if the resource is served via the content handler servlet. Handlers can plug into the content handler servlet to process GET requests. The content handler servlet deals with the details of the request processing such as security, virtual portal support and the initialization of the request to allow calls into the WebSphere Portal APIs. Handlers that plug into the content handler servlet then provide the request-specific processing logic. The responsiblity of a handler is to

DataSourceFactory

Data source factory that allows to instantiate DataSource objects. The data sources need to implement one of the strongly typed interfaces ByteDataSource, CharDataSource, XmlDataSource or MultipartDataSource. Clients of the DataSourceFactoryEx will determine the type of the returned data source via introspection.

A data source factory is registered in the plugin.xml of the providing extension as a serviceHandler

.
        <extension
                point="com.ibm.content.operations.registry.locationServiceHandler">
                <serviceHandler
                        class="YOUR_IMPLEMENTATION_CLASS"
                        locationTypeId="LOCATION_TYPE_ID"
                        id="com.ibm.portal.resolver.data.DataSourceFactoryEx" />
        </extension>
 

Example

In this example we show how a simple data source is developed and integrated. The data source in this example will serve a dynamically generated JPEG image. We develop the example bottom-up.

DataSource

The data source represents the actual data that is served as a response to a POC request for a POCURI. In this example the data source is a ByteDataSource because it represents a jpeg image:

package com.ibm.wps.test.resolver.data.binary;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.Collections;
import java.util.Date;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;

import com.ibm.portal.resolver.data.ByteDataSource;

/**
 * The representation of your actual data stream. Your implementation just needs
 * to be able to write the bytes dynamically out to the target stream.
 * 
 * @author cleue
 *
 */
public class DownloadSource implements ByteDataSource {
        
        /** copyright */
        public final static String COPYRIGHT = com.ibm.wps.Copyright.SHORT;
        
        /** mime type of the image we intend to produce **/
        public static final String mimeType = "image/jpeg";
        
        /**
         *      URI of this image
         */
        private URI pocURI;
        
        /** created timestamp **/
        private Date created;
        
        /**
         * pass the POC URI via reset to already prepare for object pooling
         * 
         * @param aPocURI
         */
        public void reset(final URI aPocURI) {
                pocURI = aPocURI;
                created = new Date();
        }
                
        /* (non-Javadoc)
         * @see com.ibm.portal.resolver.data.ByteDataSource#write(java.io.OutputStream)
         */
        public OutputStream write(final OutputStream out) throws IOException {
                // dimensions
                final int width = 128;
                final int height = 128;
                
                // construct the image
                final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                final Graphics2D graph = image.createGraphics();
                graph.clearRect(0, 0, width, height);
                // draw a circle
                graph.drawOval(0, 0, width, height);
                // draw the POC URI
                graph.drawString(pocURI.toString(), 0, height/2);
                // done with the graph
                graph.dispose();
                
                // write the image
                final ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByMIMEType(mimeType).next();
                final ImageOutputStream imgOut = ImageIO.createImageOutputStream(out);
                writer.setOutput(imgOut);
                writer.write(image);
                imgOut.close();
                // done with the  the writer
                writer.dispose();
                
                // done
                return out;
        }

        /* (non-Javadoc)
         * @see com.ibm.portal.resolver.data.DataSource#getContentType()
         */
        public String getContentType() {
                // return the mime type of the data
                return mimeType;
        }

        /*
         * Overriding method... does not require Javadoc.
         * @see com.ibm.portal.resolver.data.DataSource#getExpiration()
         */
        public Date getExpiration() {
                // some arbitrary expiration info
                return new Date(created.getTime() + 1000 * 10 * 10);
        }

        /*
         * Overriding method... does not require Javadoc.
         * @see com.ibm.portal.TimeStamped#getCreated()
         */
        public Date getCreated() {
                return created;
        }

        /*
         * Overriding method... does not require Javadoc.
         * @see com.ibm.portal.TimeStamped#getLastModified()
         */
        public Date getLastModified() {
                return created;
        }

        public void dispose() {
                // reset internal data
                pocURI = null;
                created = null;
                // if you do object pooling, return the object to the pool, here
        }

        /* (non-Javadoc)
         * @see com.ibm.portal.resolver.data.Addressable#getURI()
         */
        public URI getURI() {
                // the URI for this datasource
                return pocURI;
        }

        /* (non-Javadoc)
         * @see com.ibm.portal.resolver.data.Addressable#getParameters()
         */
        public Map getParameters() {
                // no parameters required
                return Collections.EMPTY_MAP;
        }

}

DataSourceFactoryEx

The data source is managed and instantiated by a DataSourceFactoryEx. This factory is called by the framework with the POCURI and the parameter map and constructs data sources based on these parameters. In this example we always serve the same image so the code is independent from the URI. In a real world example the selection of the matching data source would depend on the URI and probably on the parameter map.

package com.ibm.wps.test.resolver.data.binary;

import java.io.IOException;
import java.net.URI;
import java.util.Map;

import com.ibm.content.operations.registry.api.Context;
import com.ibm.portal.resolver.data.DataSource;
import com.ibm.portal.resolver.data.DataSourceFactoryEx;

/**
 * Simply data source factoy that creates the same DataSource (an image)
 * for all URIs. 
 */
public class ByteDownload implements DataSourceFactoryEx {

        /** copyright */
        public final static String COPYRIGHT = com.ibm.wps.Copyright.SHORT;

        /* (non-Javadoc)
         * @see com.ibm.portal.resolver.helper.AbstractByteDataSouceFactory#newSource(java.net.URI, java.util.Map, com.ibm.content.operations.registry.api.Context)
         */
        public DataSource newSource(final URI uri, final String verb,
                        final Map params, final Context ctx) throws IOException {
                // TODO somehow access your data
                // recommendation: for performance reasons use object pooling to get
                // ByteDataSource objects. You can return them in the dispose() call
                // on the source

                // in this example I just dynamically generate a JPEG image 
                final DownloadSource result = new DownloadSource();
                result.reset(uri);

                return result;
        }

}

COR artefacts

In order to register a DataSourceFactoryEx with the COR framework we need glue code that binds our implementation to the COR.

The ContentLocationFactory implementation:

package com.ibm.wps.test.resolver.cor;

import com.ibm.portal.resolver.helper.cor.SingleContentLocationFactory;
import com.ibm.wps.test.resolver.Constants;

/**
 * Code artifact that can be references via the <code>plugin.xml</code> to
 * perform a COR registration.
 */
public class SampleContentLocationFactory extends SingleContentLocationFactory implements Constants {

        public SampleContentLocationFactory() {
                super(SCHEME_TEST, new SampleContentLocation());
        }
}

The ContentLocation implementation referenced by the code above:

package com.ibm.wps.test.resolver.cor;

import com.ibm.portal.resolver.helper.cor.DefaultContentLocation;
import com.ibm.wps.test.resolver.Constants;

/**
 * 
 */
public class SampleContentLocation extends DefaultContentLocation implements Constants {

        public SampleContentLocation() {
                super(LOCATION_TYPE_ID, SCHEME_TEST);
        }
}

The LOCATION_TYPE_ID constant used in this code references the ID as registered in the plugin.xml (set to com.ibm.wps.test.resolver.locationTypeID). The SCHEME_TEST identifies the URI scheme that is used to access the content location (set to SampleScheme).

Registration

Our implementations must not be glued together via the plugin.xml. First the ContentLocationFactory is registered with its URI scheme:

  <extension
        point="com.ibm.content.operations.registry.locationTypeContribution">
        
       <!-- this is the location for the download URIs -->

      <contentLocationType
            class="com.ibm.wps.test.resolver.cor.SampleContentLocationFactory"
            id="com.ibm.wps.test.resolver.locationTypeID"
            match.uri.scheme="SampleScheme"
            title="Sample Content Location Factory"/>

 </extension>

Then the data source factory is registered as a service for this ContentLocationFactory (and therefore implicitly for the URI scheme). Note that the locationTypeId attribute in the serviceHandler matches the id attribute in the contentLocationType:

    <extension
                point="com.ibm.content.operations.registry.locationServiceHandler">

                <!-- this service handles the binary download of your data -->
                <serviceHandler
                        class="com.ibm.wps.test.resolver.data.binary.ByteDownload"
                        locationTypeId="com.ibm.wps.test.resolver.locationTypeID"

                        id="com.ibm.portal.resolver.data.DataSourceFactoryEx"/>

        </extension>