== resources
:idprefix: id_ 


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

[options="header"]
|===
|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:

[source,xml] 
----
<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.
+
[source,java]
----
@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.
+
[options="header"]
|===
|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.
+
[source,java]
----
public class Thing {
}
----
+
[source,java]
----
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`.
+
[source,java]
----
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.
+
[options="header"]
|===
|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.

|===
+
[source,java]
----
@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.
+
[source,java]
----
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:
+
[source:java]
----
   ...
   Collection<ResourceEvent> changeSet = transaction.getChangeSet();
   ...   
   transaction.commit();
----
+
According to the above example, this change set contains the following entries:
+
[source:java]
----
Collection [
    ResourceModified: <DirectoryResource>, 
    ResourceCreated: <FileResource<?>>, 
    ResourceModified: <FileResource<?>>, 
    ResourceDeleted: <FileResource<?>>, 
    ResourceCreated: <FileResource<?>>
]
----
