Fetching Objects
Implement resource loaders that handle both DOM and JDOM objects
by Claude Duguay
Editors Note: This is the concluding installment of a two-part article on developing a simple resource manager interface that accommodates XML and other object groups stored in arbitrary containers. Follow the link to read the first installment, "Cluster Resources in Containers" (August 13, 2003).
The addResourceLoader() method lets you add ResourceLoader instances. We use a Map object—a HashMap instance—to associate the Class type associated with a loader to the loader instance. Because of the way a HashMap works, this association means that registering a ResourceLoader instance repeatedly or registering one with an already registered type will have no ill effect other than replacing the previous entry in the table. The getResourceLoader() method is used to fetch a ResouceLoader by name. If no entry exists in the table, this method returns a null value.
The loadResource() method is key to the infrastructure and actually uses the ResourceLoader to fetch an object. The container reference is used to fetch the necessary input stream by name. We catch exceptions generically and throw a ResourceException if anything goes wrong. Note that we also make sure the input stream is closed before returning the object.
The getResource() method is vital to using the ResourceManager to get objects from a resource container. It can return any object and handles caching when appropriate. We first fetch the resource loader by type and then check the cache and return the object if it's already been saved; otherwise, we load the resource and cache it if the loader specifies caching is permitted.
The rest of the methods are there for convenience and make assumptions about the resource loaders available. If you want to handle additional types, the process primarily involves adding ResourceLoader instances. If desired, you can optionally extend the ResourceManager to add convenience methods like this.
In the DOMResourceLoader class we use the Java API for XML Processing (JAXP) interface that's now a standard part of Java 1.4 (see Listing 2). For older versions, you'll need to get the JAXP JAR file from Sun and a suitable XML parser such as Xerces. If you use Java 1.4 the code requires no additional libraries.
The DOMResourceLoader creates a reference to a DocumentBuilder object by working with the DocumentBuilderFactory. We'll use this reference in the load() method. The type() method returns a Document object. Fully qualified, this object is the org.w3c.xml.Document type because we include the package discussed previously. You'll see that the Document type in the JDOMResourceLoader looks the same but references a different class. The cache() method returns false to avoid caching DOM objects. It's up to you to change this if you disagree with the policy.
The load() method does most of the work by using the builder reference created in the constructor to retrieve a DOM instance from an input stream. We don't close the input stream here because the ResourceManager handles that for us. All we need to do is handle potential problems, in this case by catching exceptions and returning them with an explanation. Notice that this pattern of catching exceptions and cascading the stack trace information into a more informative exception instance is what chained exceptions were designed for, thus helping programmers report problems at suitable abstraction levels.
The JDOMResourceLoader is similar, but it uses the JDOM library instead of a standard DOM, primarily for convenience (see Listing 3). JDOM specifies a DOMBuilder to build Document instances, so we create an instance in the constructor and reference it in the load() method. Otherwise, the rest of the code is virtually identical to the DOMResourceLoader, though it uses a different Document class.
Collect Away
Accessing XML documents from different sources is already possible using existing infrastructures, but the notion of collecting resources of different types in container files is also a common requirement. Given how easy it is to work with ZIP files in Java, this discussion is meant to demonstrate both a simple solution that accommodates XML, as well as other objects, and represents a good use of interfaces to maximize design flexibility. I hope these ideas serve you well.
About the Author
Claude Duguay has developed software for more than 20 years. He is passionate about Java, reads about it incessantly, and writes about it as often as possible. Reach Claude at .
Back to top
|