When producing/verifying an electronic signature there are several steps of the process that may be implemented in different ways, without changing the whole. Examples include key/certificate selection, certificate validation, interaction with time-stamp authorities and marshaling/unmarshaling XML. The XAdES4j library is based on exchangeable components that may be configured independently in order to define how the signatures are produced/verified. The library’s design is based on dependency injection and I’m using Guice to assemble the different components.
One of the reasons that made me choose Guice is that it supports dependencies based on generic types. Consider the following chocolate-based types:
class Twix implements Chocolate{}
class Snickers implements Chocolate{}
interface ChocolateEater<T extends Chocolate>
{
void eat(T choc);
}
We have some chocolates and a generic interface that represents someone who eats a specific type of chocolates. We can also define the guys who actually eat the chocolates:
class ILoveSnickers implements ChocolateEater<Snickers>
{
@Override
public void eat(Snickers choc){}
}
class ILoveTwix implements ChocolateEater<Twix>
{
@Override
public void eat(Twix choc){}
}
These are the one that should be used when someone is needed to eat those types of chocolates. To express this, one does the corresponding binding within a Module. Since Java’s generics are only compile-time, the guys at Google had to come up with another approach to distinguish the eaters of the different types of chocolates. This is done with the TypeLiteral class (actually, with an anonymous subclass that specifies the type parameters):
class ChocolatesModule extends AbstractModule
{
@Override
protected void configure()
{
bind(new TypeLiteral<ChocolateEater<Twix>>(){}).to(ILoveTwix.class);
bind(new TypeLiteral<ChocolateEater<Snickers>>(){}).to(ILoveSnickers.class);
}
}
This is used to define a binding key that identifies the chocolate eater, including the type argument (which doesn’t actually exist at runtime). One can then use the same strategy to get instances of chocolate eaters:
ChocolateEater<Twix> twixEater = injector.getInstance(Key.get(new TypeLiteral<ChocolateEater<Twix>>(){}));
This is ok, but no enough. What if you need to eat a chocolate that you’ll only get at runtime? If this is the case, you use the ParameterizedType class, which allows the identification of a specific generic type by indicating the actual type parameters:
Chocolate c = new Twix();
ParameterizedType pt = Types.newParameterizedType(ChocolateEater.class, c.getClass());
ChocolateEater<?> eater = (ChocolateEater<?>)injector.getInstance(Key.get(TypeLiteral.get(pt)));
In the previous examples I’m using the injector to directly get the chocolate eaters. Nevertheless, generic types can be used in dependencies that are resolved by the injector:
class SomeClass
{
@Inject
public SomeClass(ChocolateEater<Twix> tE, ChocolateEater<Snickers> sE){}
}
injector.getInstance(SomeClass.class);
Back to XAdES4j: I found dependency injection very useful because I had isolated functionality that could (and sometimes had) to be configured independently from the whole. For instance, it doesn’t matter if a key comes from a smart card or a Windows key store; what matters is that you get it to perform the signature operation. The support for generics was handy when I needed to verify the XAdES qualifying properties: each property has a class that performs its verification, but they all implement the same (generic) interface. The difference is in the type of the properties they operate on – a type parameter in the interface. I needed the verifiers to be provided by the injector because they may have dependencies on some components, which in turn may have their own dependencies. If i didn’t have support for generics, I wouldn’t be able to get the verifier for a specific type of property.