| |||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
See:
Description
Interface Summary | |
---|---|
Addressable | Interface that allows to retrieve the address of a piece of content. |
ByteDataSource | Implemented by providers of byte data streams. |
CharDataSource | Implemented by providers of character data streams. |
DataSink | Base interface implemented by all data sinks, independent on their actual stream type. |
DataSource | Base interface implemented by all data sources, independent on their actual stream type. |
DataSourceFactory | Tagging interface for data source factory. |
DataSourceFactoryEx | Data source factory that allows to instantiate DataSource objects. |
MultipartDataSink | Data sink that accepts a multipart data request. |
XmlDataSource | Implemented by providers of XML data streams. |
Provides for the interfaces required to serve data via the POC resolution framework.
Data source factory that allows to instantiate {@link com.ibm.portal.resolver.data.DataSource} objects. The data sources need to implement one of the strongly typed interfaces {@link com.ibm.portal.resolver.data.ByteDataSource}, {@link com.ibm.portal.resolver.data.CharDataSource}, {@link com.ibm.portal.resolver.data.XmlDataSource} or {@link com.ibm.portal.resolver.data.MultipartDataSource}. Clients of the {@link 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>
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.
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; } }
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 {@link 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; } }
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
).
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>
| |||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |