<commit_before>= Spearal Java

== What is Spearal?

Spearal is a compact binary format for exchanging arbitrary complex data between various endpoints such as Java EE, JavaScript / HTML, Android and iOS applications.

Spearal-Java is the common codebase used in all Spearal / Java specific extensions.


== How to use the library?

=== Add the dependency

The library is available in the Maven central repository, so with Maven or Gradle you simply have to reference 
the dependency on the library in your build system. Note that Javassist is an optional (but necessary to handle
partial objects) dependency of the library: 

[source,xml]
.Maven
----
<dependency>
	<groupId>org.spearal</groupId>
	<artifactId>spearal-java</artifactId>
	<version>${spearal.version}</version>
</dependency>
<dependency>
	<groupId>org.javassist</groupId>
	<artifactId>javassist</artifactId>
	<version>3.18.2-GA</version>
</dependency>
----

[source,java]
.Gradle
----
compile 'org.spearal:spearal-java:${spearal.version}'
compile 'org.javassist:javassist:3.18.2-GA'
----

In any other case, just download the https://github.com/spearal/spearal-java/releases[Spearal-Java] jar from github and add it to your classpath.


=== Basic usage

First, you need to create a `SpearalFactory` that contains the central configuration and internal state of the library:

[source,java]
----
SpearalFactory factory = new DefaultSpearalFactory();
----

Encoding data is then a matter of creating a new encoder and call the `writeAny` method:

[source,java]
----
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SpearalEncoder encoder = factory.newEncoder(baos);
encoder.writeAny(obj);
----

Decoding is achieved the same way with `readAny`:

[source,java]
----
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SpearalDecoder decoder = factory.newEncoder(bais);
Object copy = decoder.readAny();
----

Note that if you know the expected type of the decoded object, you can use the typed version of `readAny`:

[source,java]
----
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SpearalDecoder decoder = factory.newEncoder(bais);
Invoice copy = decoder.readAny(Invoice.class);
----

=== Working with partial encoding:

Spearal lets you encode only a subset of the properties of an object. Let's say you have bean defined by this class:

[source,java]
----
class Person implements Serializable {

    private String firstName;
    private String lastName;
    private List<String> phones;
    
    // getters / setters...
}
----

If you are retrieving a collection of Persons and just need their first and last names, it is useless to serialize their collections of phones. 
Spearal lets you encode just the `firstName` and `lastName` properties with a property filter:

[source,java]
----
SpearalFactory factory = new DefaultSpearalFactory();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SpearalEncoder encoder = factory.newEncoder(baos);

// Only firstName and lastName:
encoder.getPropertyFilter().add(Person.class, "firstName", "lastName");

encoder.writeAny(obj);
----

When decoding the result, you will get a Javassist proxy for each Person, that will throw a `UndefinedPropertyException` if you try to access the phones collection:

[source,java]
----
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SpearalDecoder decoder = factory.newEncoder(bais);
Person copy = decoder.readAny(Person.class);

System.out.println(copy.getFirstName());
System.out.println(copy.getLastName());

// This line throws a UndefinedPropertyException:
System.out.println(copy.getPhones());
----

=== What is the Spearal Mime Type?

Data exchanged in the Spearal format should use the `application/spearal` mime type which is defined as the constant
`Spearal.APPLICATION_SPEARAL`.


== Configuration

Various elements can be configured in the `SpearalFactory`. All configurable elements implement the interface `Configurable` and can be configured
with:

[source,java]
----
spearalFactory.configure(new ConfigurableElement());
----

=== `AliasStrategy`

The first configurable element is the class alias strategy. It is used during serialization and deserialization to convert the name of the class
from a local qualified name to the remote qualified name.

The built-in implementation `PackageTranslatorAliasStrategy` simply translates the package prefix from one name to another. For example with 
a client package prefix `com.mycompany.client` and a server package prefix `com.mycompany.server`, the class name `com.mycompany.server.domain.DomainObject`
will be translated to `com.mycompany.client.domain.DomainObject` and the corresponding class will be instantiated.
The default does not alias or unalias anything.


=== `Introspector`

The role of the introspector is to retrieve (usually by reflection) the list of properties for a specified class.
The default `IntrospectorImpl` is able to instrospect properties of a JavaBean-style class and can be used in most cases.
A custom introspector could be necessary for example to deal with JavaFX objects with bindable properties.


=== `PartialObjectFactory`

Its role is to instantiate partial objects. When Javassist is present in the classpath, the built-in `JavassistPartialObjectFactory` is used and creates a 
Javassist proxy for the class. The default behaviour when Javassist is not present is `NoProxyPartialObjectFactory` which simply instantiates the 
target class. Obviously this is not suitable if you really want to use partial objects because they will be sent as 'full' objects from client to server,
but with some properties set to null (or default values).

The factory must implement the following method:

[source,java]
----
/**
 * Create a proxy instance for the target class
 * @param context the current Spearal context
 * @param cls the class to proxy
 * @param partialProperties the defined properties at initialization
 */
public Object instantiatePartial(SpearalContext context, Class<?> cls, Property[] partialProperties);
----


=== Securizer

The role of the securizer is to allow or forbid the serialization/deserialization of an particular type. It can be important in particular
during deserialization to prevent an attacker to let Spearal instantiate a sensitive class with which it could access the underlying system. 
The default `SecurizerImpl` enforces that the target class must implement `Serializable` but any other policy can be implemented.

The securizer must implement the following method:

[source,java]
----
void checkDecodable(Type type) throws SecurityException;
void checkEncodable(Class<?> cls) throws SecurityException;
----


=== TypeLoader

The role of the loader is to instantiate the target class from its aliased name (or names when muliple interfaces are received).
The default `TypeLoaderImpl` parses the class names, and does the following depending on the cases:

- If there is only one name, it loads the type. If the type is an interface, it instantiates a Java proxy, else it instantiates the class itself.
- If the class is not found, it instantiates the class `ClassNotFound` which is a anonymous object that will contain the deserialized data.
- If there are many names, it tries to create a Java proxy for all the specified interfaces.

If you need that the classes are loaded in a specific `ClassLoader`, just reconfigure the default `TypeLoaderImpl`:

[source,java]
----
spearalFactory.configure(new TypeLoaderImpl(myClassLoader));
----

Any other loading policy can be implemented, for example to get object instances from a pool, an external object factory or apply specific transformations 
or initialization on the instantiated objects. 

The loader must implement the following method:

[source,java]
----
Class<?> loadClass(SpearalContext context, String classNames, Type target);
----


=== UnfilterablePropertiesProvider

TODO



== How to get and build the project?

[source,bash]
----
$ git clone https://github.com/spearal/spearal-java.git
$ cd spearal-java
$ ./gradlew build
----

The library can then be found in the `build/libs` directory.
 <commit_msg>Formatting<commit_after>= Spearal Java

== What is Spearal?

Spearal is a compact binary format for exchanging arbitrary complex data between various endpoints such as Java EE, JavaScript / HTML, Android and iOS applications.

Spearal-Java is the common codebase used in all Spearal / Java specific extensions.


== How to use the library?

=== Add the dependency

The library is available in the Maven central repository, so with Maven or Gradle you simply have to reference 
the dependency on the library in your build system. Note that Javassist is an optional (but necessary to handle
partial objects) dependency of the library: 

[source,xml]
.Maven
----
<dependency>
	<groupId>org.spearal</groupId>
	<artifactId>spearal-java</artifactId>
	<version>${spearal.version}</version>
</dependency>
<dependency>
	<groupId>org.javassist</groupId>
	<artifactId>javassist</artifactId>
	<version>3.18.2-GA</version>
</dependency>
----

[source,java]
.Gradle
----
compile 'org.spearal:spearal-java:${spearal.version}'
compile 'org.javassist:javassist:3.18.2-GA'
----

In any other case, just download the https://github.com/spearal/spearal-java/releases[Spearal-Java] jar from github and add it to your classpath.


=== Basic usage

First, you need to create a `SpearalFactory` that contains the central configuration and internal state of the library:

[source,java]
----
SpearalFactory factory = new DefaultSpearalFactory();
----

Encoding data is then a matter of creating a new encoder and call the `writeAny` method:

[source,java]
----
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SpearalEncoder encoder = factory.newEncoder(baos);
encoder.writeAny(obj);
----

Decoding is achieved the same way with `readAny`:

[source,java]
----
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SpearalDecoder decoder = factory.newEncoder(bais);
Object copy = decoder.readAny();
----

Note that if you know the expected type of the decoded object, you can use the typed version of `readAny`:

[source,java]
----
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SpearalDecoder decoder = factory.newEncoder(bais);
Invoice copy = decoder.readAny(Invoice.class);
----

=== Working with partial encoding:

Spearal lets you encode only a subset of the properties of an object. Let's say you have bean defined by this class:

[source,java]
----
class Person implements Serializable {

    private String firstName;
    private String lastName;
    private List<String> phones;
    
    // getters / setters...
}
----

If you are retrieving a collection of Persons and just need their first and last names, it is useless to serialize their collections of phones. 
Spearal lets you encode just the `firstName` and `lastName` properties with a property filter:

[source,java]
----
SpearalFactory factory = new DefaultSpearalFactory();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SpearalEncoder encoder = factory.newEncoder(baos);

// Only firstName and lastName:
encoder.getPropertyFilter().add(Person.class, "firstName", "lastName");

encoder.writeAny(obj);
----

When decoding the result, you will get a Javassist proxy for each Person, that will throw a `UndefinedPropertyException` if you try to access the phones collection:

[source,java]
----
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SpearalDecoder decoder = factory.newEncoder(bais);
Person copy = decoder.readAny(Person.class);

System.out.println(copy.getFirstName());
System.out.println(copy.getLastName());

// This line throws a UndefinedPropertyException:
System.out.println(copy.getPhones());
----

=== What is the Spearal Mime Type?

Data exchanged in the Spearal format should use the `application/spearal` mime type which is defined as the constant
`Spearal.APPLICATION_SPEARAL`.


== Configuration

Various elements can be configured in the `SpearalFactory`. All configurable elements implement the interface `Configurable` and can be configured
with:

[source,java]
----
spearalFactory.configure(new ConfigurableElement());
----

=== `AliasStrategy`

The first configurable element is the class alias strategy. It is used during serialization and deserialization to convert the name of the class
from a local qualified name to the remote qualified name.

The built-in implementation `PackageTranslatorAliasStrategy` simply translates the package prefix from one name to another. For example with 
a client package prefix `com.mycompany.client` and a server package prefix `com.mycompany.server`, the class name `com.mycompany.server.domain.DomainObject`
will be translated to `com.mycompany.client.domain.DomainObject` and the corresponding class will be instantiated.

The default does not alias or unalias anything.


=== `Introspector`

The role of the introspector is to retrieve (usually by reflection) the list of properties for a specified class.
The default `IntrospectorImpl` is able to instrospect properties of a JavaBean-style class and can be used in most cases.
A custom introspector could be necessary for example to deal with JavaFX objects with bindable properties.


=== `PartialObjectFactory`

Its role is to instantiate partial objects. When Javassist is present in the classpath, the built-in `JavassistPartialObjectFactory` is used and creates a 
Javassist proxy for the class. The default behaviour when Javassist is not present is `NoProxyPartialObjectFactory` which simply instantiates the 
target class. Obviously this is not suitable if you really want to use partial objects because they will be sent as 'full' objects from client to server,
but with some properties set to null (or default values).

The factory must implement the following method:

[source,java]
----
/**
 * Create a proxy instance for the target class
 * @param context the current Spearal context
 * @param cls the class to proxy
 * @param partialProperties the defined properties at initialization
 */
public Object instantiatePartial(SpearalContext context, Class<?> cls, Property[] partialProperties);
----


=== `Securizer`

The role of the securizer is to allow or forbid the serialization/deserialization of any particular type. It can be important in particular
during deserialization to prevent an attacker to let Spearal instantiate a sensitive class with which it could access the underlying system. 
The default `SecurizerImpl` enforces that the target class must implement `Serializable` but any other policy can be implemented.

The securizer must implement the following method:

[source,java]
----
void checkDecodable(Type type) throws SecurityException;
void checkEncodable(Class<?> cls) throws SecurityException;
----


=== `TypeLoader`

The role of the loader is to instantiate the target class from its aliased name (or names when multiple interfaces are received).
The default `TypeLoaderImpl` parses the class names, and does the following depending on the cases:

- If there is only one name, it loads the type. If the type is an interface, it instantiates a Java proxy, else it instantiates the class itself.
- If the class is not found, it instantiates the class `ClassNotFound` which is a anonymous object that will contain the deserialized data.
- If there are many names, it tries to create a Java proxy for all the specified interfaces.

If you need that the classes are loaded in a specific `ClassLoader`, just reconfigure the default `TypeLoaderImpl`:

[source,java]
----
spearalFactory.configure(new TypeLoaderImpl(myClassLoader));
----

Any other loading policy can be implemented, for example to get object instances from a pool, an external object factory or apply specific transformations 
or initialization on the instantiated objects. 

The loader must implement the following method:

[source,java]
----
Class<?> loadClass(SpearalContext context, String classNames, Type target);
----


=== `UnfilterablePropertiesProvider`

TODO



== How to get and build the project?

[source,bash]
----
$ git clone https://github.com/spearal/spearal-java.git
$ cd spearal-java
$ ./gradlew build
----

The library can then be found in the `build/libs` directory.
 
{'fraction_non_alphanumeric': 0.08159252887687392, 'fraction_numerical': 0.0009830425165888424, 'mean_word_length': 4.755657708628005, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 43, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7335879', 'n_tokens_mistral': 4421, 'n_tokens_neox': 4265, 'n_words': 1926}