Skip to content

Latest commit

 

History

History
251 lines (209 loc) · 6.84 KB

README.asciidoc

File metadata and controls

251 lines (209 loc) · 6.84 KB

resources

This addon exports services for use in other addons. The Resources addon provides APIs and services for interacting with real and virtual resources, typically for the purpose of reading and manipulating files or other data-structures. The resources API also allows for wrapping of low-level resource constructs with higher level operations.

Depends on

Addon Exported Optional

convert

no

yes

facets

yes

no

ui-spi

no

no

org.jboss.forge.furnace.container:cdi

no

no

Setup

This addon requires the following installation steps.

Add configuration to pom.xml

To use this addon, you must add it as a dependency in the pom.xml of your forge-addon classified artifact:

<dependency>
   <groupId>org.jboss.forge.addon</groupId>
   <artifactId>resources</artifactId>
   <classifier>forge-addon</classifier>
   <version>${version}</version>
</dependency>

Features

Abstraction of low-level functionality

This enables abstraction of common operations such as testing for existence, retrieving input streams, naming, deletion, and listing of child resources.

ResourceFactory service for resource creation

The ResourceFactory is used for creating both generic and specific resources from underlying resource instances. When creating resources, the factory will select the most appropriate resource API type to represent the given real or virtual resource.

@Inject
private ResourceFactory factory;
...
Resource<?> resource = factory.create(...);
Tip

If your addon uses a container that does not support "@Inject" annotations, services such as the ResourceFactory may also be accessed via the AddonRegistry:

AddonRegistry registry = ...
Imported<ResourceFactory> imported = registry.getServices(ResourceFactory.class);
ResourceFactory factory = imported.get();
Built-in support for common resource types

The resources addon comes pre-configured with several types for interacting with common resources.

Resource Underlying Type Description

FileResource<?>

java.io.File

Used to interact with the standard Java filesystem API. Can be extended with custom resource types to provide name or contents based specialization. (E.g.: PropertiesFileResource)

DirectoryResource

java.io.File

Used to interact with directories via standard Java filesystem API.

URLResource

java.net.URL

Used to interact with standard Java URLs.

Custom resource types

The resources API may be extended to support custom resource types. This is a two step process involving creation of a new type that extends from Resource, and a ResourceGenerator. These custom resource types will be made automatically available to other addons depending on the resources addon.

public class Thing {
}
public class MyResource extends AbstractResource<Thing> implements Resource<Thing> {
   public void doSomething() {
     // custom functionality for your resource
  }
}

Once the resource interface has been implemented, simply add methods and functionality to the resource implementation; this allows consumers of the resource type to use the functionality you have created. You may then implement a resource generator, which will be responsible for constructing instances via the ResourceFactory.

public class MyResourceGenerator implements ResourceGenerator<MyResource, Thing> {
   @Override
   public boolean handles(Class<?> type, Object resource) {
      return resource instanceof Thing;
   }

   @Override
   public <T extends MyResource> T getResource(ResourceFactory factory, Class<MyResource> type, Thing resource) {
      return (T) new MyResource(resource);
   }

   @Override
   public <T extends MyResource> Class<?> getResourceType(Class<MyResource> type, Thing resource) {
      return MyResource.class;
   }
}
Consistent programming experience

Because the resources API provides a consistent set of interfaces for interacting with real and virtual resources, it is used in a number of addons and should be considered the standard approach for interacting with both the local file-system, as well as with other resource types.

Resource monitoring

The resources API provides a service to monitor FileResource events.

Event type Description

ResourceCreated

Fired when a resource (eg: directory or a file) is created.

ResourceDeleted

Fired when a resource (eg: directory or a file) is deleted.

ResourceModified

Fired when a resource (eg: directory or a file) is modified.

@Inject
private ResourceFactory factory;
...
Resource<?> resource = factory.create(...);
ResourceMonitor monitor = factory.monitor(resource);
monitor.addResourceListener(new ResourceListener() {
	@Override
	public void processEvent(ResourceEvent evt) {
		...
	}
});
...
// If the monitor is no longer needed, dispose properly by calling cancel
monitor.cancel();
Tip
  • It’s always a good practice to cancel monitors when they are no longer needed

  • From a FileResource object, it’s possible to fetch a reference to a ResourceMonitor by simply calling monitor() on it.

Resource transactions

The resources API provides a transaction service on FileResources. If you are familiar with UserTransaction in Java EE applications, this should feel pretty comfortable.

ResourceTransaction transaction = factory.getTransaction();
try {
   // Starts the transaction
   transaction.begin();

   FileResource<?> resource = factory.create(...);
   // The file won't be updated until commit is performed
   resource.setContents("Hello World");

   String contents = resource.getContents(); // Returns "Hello World"

   FileResource<?> anotherResource = factory.create(...);
   // The file won't be deleted until commit is performed
   anotherResource.delete();

   FileResource<?> newResource = factory.create(...);
   // The file won't be created until commit is performed
   newResource.createNewFile();

   transaction.commit();
} catch (Exception e){
    // Discard all changes since the beginning of this transaction
    transaction.rollback();
}

Additionally, transactions support change-set inspection, so you can compare file contents before deciding whether or not a given transaction should be committed or rolled back:

   ...
   Collection<ResourceEvent> changeSet = transaction.getChangeSet();
   ...
   transaction.commit();

According to the above example, this change set contains the following entries:

Collection [
    ResourceModified: <DirectoryResource>,
    ResourceCreated: <FileResource<?>>,
    ResourceModified: <FileResource<?>>,
    ResourceDeleted: <FileResource<?>>,
    ResourceCreated: <FileResource<?>>
]