WireHose gives WebObjects developers the power
to create fast, personalizable web portals that categorize, index and
deliver any media type, like video clips, stock quotes or legacy
data. It features a simple, flexible API for adding new own
portal components and resource types, making it perfect for creating
enterprise portals in addition to high-traffic internet sites.
WireHose also has special support for creating and deploying large
numbers of re-branded portals sharing some common resources, as for
example in an application service provider environment, community
publishing, or higher education.
WireHose provides a powerful, flexible foundation for building content management systems in WebObjects, based on the concept of tagging and indexing content.
- WHTag objects represent metadata which can be arranged in an arbitrary hierarchy and assigned to taggable objects. Tags can be arranged into any hierarchy required. A tag can be uniquely identified by its tagpath, which is a slash-delimited string indicating its position in the hierarchy such as "Animals/Cats/Black cats/Budu". You use static methods in WHTag create and retrieve tags, and assign them to taggable objects. You can subclass WHTag to implement access control, workflow or other special applications. The com.wirehose.base.engage package defines several WHTag subclasses which implement access control for taggable objects. WHRevision is a WHTag subclass which provides support for versioning taggable objects.
- Taggable objects
- WHTaggable defines an interface for objects which can be categorized and fetched by tags. A taggable object can have any number of tags. You can add taggable support to your existing enterprise object entities by adding a few relationships and implementing the WHTaggable interface, which provides a default implementation as a static inner class. WireHose also includes templates to create new taggable objects from scratch.
- Indexable objects
- WHIndexable defines an interface for objects which can be indexed and fetched by keywords. You can add indexable support to your existing enterprise object entities by implementing the WHIndexable interface and adding a few relationships. WireHose also includes templates to create new indexable objects from scratch. Indexable objects are indexed through the WHTextIndexer utility class.
- Fetching taggable and indexable objects
- WHTagDataSource is an EODataSource, suitable for use with display groups, which fetches taggable and indexable objects by tags and keywords. WHTagDataSource is optimized for performance, and includes fine-tunable caching and entity pruning so expensive fetches are minimized. You can filter fetched objects by entity or interfaces implemented, and control its SQL generation through several Java properties.
WireHose provides everything you need to create high-performance, scalable personalized applications. It models users, guest users, channels, global channels, and channel factories, and includes optimized implementations which handle caching and propagation of default settings to individual sessions.
- WHUser is the parent entity for all WireHose users. It includes many methods for fetching, sorting and filtering a user's channels. Subclasses can override the
allUserChannels method to include channels which are not modeled as part of the base "channels" relationship. Users can be automatically logged in via cookies, and you can override the default authentication and guest user creation behavior by implementing WHApplicationHelper's delegate methods.
- WHChannel defines an interface for things which can be personalized for individual users. WireHose includes templates which use WHConcreteChannel as a default implementation, or you can create your own channel objects by implementing the WHChannel interface. WireHose also provides support for global channels, which belong to all users.
- Channel factories
- WHChannelFactory defines an interface for objects which create channels for individual users and global channels. Channel factories also may provide default settings which can be overridden on a per-instance basis by individual channels. In a typical deployment scenario, channel factories are shared between all sessions in an application, and thus are often used to cache the results of expensive fetches. It includes a static inner class which provides a default implementation of the interface. WireHose includes templates so new channel factories can be rapidly built.
- WHFetcher defines an interface for objects which cache and filter the results of expensive fetches. WHConcreteFetcher provides an abstract implementation of this interface as a channel. For maximum performance, fetcher channels will attempt to use their factories' fetch results rather than perform their own whenever possible. WHTagFetcher is a fetcher which uses a WHTagDataSource to fetch taggable and indexable objects. WHQualifierFetcher uses a WHQualifierDataSource to retrieve enterprise objects by arbitrary qualifiers, making it well-suited for creating enterprise information channels that personalize queries into non-WireHose databases.
WireHose defines a delegate interface which can use to customize how users are authenticated, how guest users get created, and whether or not users can view, edit or delete objects. The WireHoseEngageSupport framework provides an implementation which uses WHTag subclasses to model roles-based access control, with users, groups, operations and inheritable permissions.
- WHApplicationHelper will automatically authenticate users based on username and password or unique login cookies or request headers. If a user can't be found, a guest user will be used. You can customize this behavior by implementing delegate methods which allow you to inspect whatever formvalues, cookies or headers you find in an incoming request to determine the user for a session.
- Access control
The WHApplicationHelper.Delegate interface also defines methods such as userCanViewObject and userCanEditObject, which you can implement to control what users are allowed to do.
The com.wirehose.base.engage package uses tags to implement roles-based access control, with users, groups, operations and inheritable permissions for taggable objects. WHEngageTag is a WHTag subclass which is taggable and indexable, so you can control access to tags. WHEngageUser represents users which can belong to multiple groups. WHGroup is a WHTag subclass which represents groups that can be arranged in an arbitrary hierarchy.
Permissions, represented by the WHPermission class, are tags which are assigned to taggable objects to indicate an association between a group and a WHOperation object. Permissions can be marked as inheritable, which means you can assign a permission to a tag, and any resources tagged with that tag will inherit the assigned permission.
Dynamic layout support
WireHose applications can have multiple user interface appearances. This can be used to support multiple branded affiliates from a single codebase, as in an application service provider environment, or to allow the user to personalize the look of their page in addition to personalizing its content. You can also use this ability to support multiple output formats, such as XML, HDML, SMIL, RSS, RDF, etc.
- Layout dictionary
- Each separate look in a WireHose application is called a layout. Layouts are defined in a file called a layout dictionary. You can provide a layout dictionary programmatically, or specify the location of a layout dictionary file on the command line. WHSessionHelper is the primary object used for accessing the layout dictionary.
By default, WireHose will use the value of the user's currentLayout property to determine which layout to use. It can also automatically determine which layout to use by sniffing HTTP request headers, which is useful for temporarily overriding the user's layout preference if they are using a handheld device or other non-HTML client.
- Pages, wrappers and areas
- Like all WebObjects applications, a WireHose application consists of pages and components. You can substitute pages and components for a given layout; the session helper uses the layout dictionary to determine which components to use. Each layout has an associated WHWrapper, which defines the look for that layout. Wrappers and pages also may define multiple areas on the page using WHArea components. For example, a three-column layout may define three areas, "left", "middle" and "right", while another layout may include only a "main" area. Channels are mapped to a particular area through their areaName property; you can map areas from one layout to another through entries in the layout dictionary.
- Dynamic binding resolution
- Components that inherit from WHComponent can optionally resolve their bindings through the layout dictionary rather than being set directly by a parent component. A component's color binding can resolve to "blue" in one area, and "green" in another, depending on the current area, page and layout.
- WHSessionHelper provides methods which return localized strings depending on the session's languages array, and will look in several places to resolve the value. You can define strings for a particular component on a particular page, or for a particular component, or for a particular page. You can also provide default localizations for components which are in a framework, and those localizations can be overridden in a particular application. You can also define non-localized strings in the layout dictionary. WHPropertyBinder objects are used to get localized labels and values for binding to popup menus.
- Cookies, URL rewriting and bookmarkable pages
- WHDirectAction provides a mechanism for automatically detecting whether cookies are enabled in a client's browser, and controlling whether session IDs are visible in URLs accordingly. WHHyperlink is a dynamic element which includes support for URL-rewriting similar to Apache's mod_rewrite, but which is applied to URLs generated by your application. Together these two classes enable your applications to have clean, bookmarkable URLs such as "/WireHoseDemo/MyHomePage" and still provide personalized sessions.
The WireHose frameworks are designed to help you build content management and portal applications faster. You can use them to build new applications from scratch, or you can add WireHose functionality to an existing codebase, usually without subclassing WireHose objects.
- WireHose provides templates for creating new WireHose applications and frameworks. It also includes templates for rapidly building new channels, channel factories, taggable and indexable entities, as well as components for rendering and editing channels and resources.
- Using interfaces instead of subclassing
- WireHose defines several Java interfaces which you can implement, enabling you to add WireHose support to your existing enterprise object classes. WHEnterpriseObject provides methods for automatically discovering entities which implement an interface, and performing fetches against all entities which support a given interface. WHFetcher defines an interface for fetching, caching and retrieving objects based on an entity name or interface, and WHCachingDataSource provides a default implementation, which also doubles as an EODataSource so you can use it to drive display groups. Most interfaces provide a default implementation, so the amount of code you need to write to support a particular interface is minimal.
- Creating entities at runtime
- WireHose makes extensive use of entity inheritance, taking advantage of the fact if an entity is not visible at runtime, any database rows described that entity are simply unavailable to the application. This is a simple but effective way to partition objects between separate application instances which share identical codebases and differ only in configuration files or launch arguments. For example, if you are deploying multiple news portals, users connecting to the Seattle portal should only see Seattle-area traffic cams, and Portland users should only see Portland-area traffic cams, but both should have access to national newsfeeds.
WHEnterpriseObject provides several methods for dynamically creating subentities at runtime, so you don't have to manually model many common types of inheritance in EOModeler. These methods are especially convenient for horizontal and single-table inheritance.
WHEnterpriseObject also includes special support for "affiliate-based inheritance", which is used by many WireHose entities. In this approach, you define an attribute on your base entity called "affiliate". This attribute is used with a restricting qualifier to identify subentities. WHApplicationHelper and WHTag use a "default affiliate" to determine which subentity should be used. WHApplicationHelper also lets an application access multiple affiliates simultaneously, and WHEnterpriseObject can automatically create subentities for all available affiliates.
- Database indepdendence
- WHEnterpriseObject makes it simple to switch between databases when an application is launched. EOModel connection dictionaries can be replaced on the fly through command-line arguments, so you can use a different database during development versus deployment, or deploy multiple instances of the same application against multiple database backends. WireHose also makes extensive use of attribute prototypes so models don't have to be modified even when switching between different database vendors. In addition, since databases vary in how boolean values are supported, WHEnterpriseObject provides utility methods which transparently set and retrieve booleans, whether the columns are defined as INT, BOOLEAN or CHAR.