Excluding sub modules in maven profile - java

I have a maven multi module project which looks like below.
Parent
|_ pom.xml
|_ module1
| |_ pom.xml
|_ module2
|_ pom.xml
And I have a maven profile that I want to execute at Parent level only, module1 and module2 should not execute this profile. How do I achieve this?

Create your parent/pom.xml like this
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>aggregator</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>aggregator</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>profile1</id>
<modules>
<module>module1</module>
</modules>
</profile>
<profile>
<id>profile2</id>
<modules>
<module>module2</module>
</modules>
</profile>
</profiles>
</project>
And run maven with this command line to install the modules inside of profile1 and profile2 respectively
mvn install -P profile1
This work for me running maven 3.1.1
To improve your profile definition you should take look at Maven - Introduction to build profiles

Related

EAR with WARs containing different versions of dependencies

Here is my requirement
EAR
WAR (Code)
----Dependency A v1
WAR (Code same as WAR above)
----Dependency A v2
AS the code for WAR project is same I don't want to create multiple code base for WAR project. So I'm looking for EAR pom.xml in such a way that maven builds the WAR with dependency A v1 which can be passed as some property while building WAR.
EAR pom.xml
...
(modules)
(webmodule)
(artifact)WAR(/artifact)
dependency version v1
(content-path)/warwithv1(/content-path)
(/webmodule)
(webmodule)
(artifact)WAR(/artifact)
dependency version v2
(content-path)/warwithv2(/content-path)
(/webmodule)
...
Thanks
Sorry for the XML Tags
EDIT: Answer changed after clarification in comments.
The question as I now understand it is: How does one use a single POM to create 2 WAR files that both have the same source code but different dependencies.
The solution I propose is to create a parent POM that will specify one module per WAR. One of the modules will contain the source code for the war and specify one version of dependencies. The second module will refer to the first module for its source code and will specify a second version of dependencies.
Here is my high level project structure:
Here is the top level (parent) POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maven-war-diff-depend</groupId>
<artifactId>maven-war-diff-depend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
</project>
Module1 will specify v2.3 of log4j2, here is its POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>maven-war-diff-depend</groupId>
<artifactId>maven-war-diff-depend</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>module1</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
</project>
Module2 will specify v2.8.1 of log4j2 and point to module1 for its source code and web.xml file. Note that you may need to do additional work to refer to any other resources in module1 such as adding more maven plugins and configuration.
Here is the module2 POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>maven-war-diff-depend</groupId>
<artifactId>maven-war-diff-depend</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>module2</artifactId>
<packaging>war</packaging>
<build>
<sourceDirectory>../module1/src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<webXml>../module1/src/main/webapp/WEB-INF/web.xml</webXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
</project>
Note that I only have a single Java class in module1 just to show that in fact this class is compiled and included in both module1 and module2:
Here are the results of a simple clean install build:
Once you have the two WAR files built it's fairly simple to add another module (this would be your EAR) which will include both of the WAR files - I believe that is your final goal.
So, create a third module:
Add the new module to your root level (parent) POM:
<module>module3</module>
Create the necessary configuration in your new module's POM. This involves adding dependencies on the other two artifacts you create with module1 and module2 and configuring the ear plugin as needed.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>maven-war-diff-depend</groupId>
<artifactId>maven-war-diff-depend</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>module3</artifactId>
<packaging>ear</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.10</version>
<configuration>
<applicationXml>${basedir}/target/application.xml</applicationXml>
<modules>
<webModule>
<groupId>maven-war-diff-depend</groupId>
<artifactId>module1</artifactId>
</webModule>
<webModule>
<groupId>maven-war-diff-depend</groupId>
<artifactId>module2</artifactId>
</webModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>maven-war-diff-depend</groupId>
<artifactId>module1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>war</type>
</dependency>
<dependency>
<groupId>maven-war-diff-depend</groupId>
<artifactId>module2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>war</type>
</dependency>
</dependencies>
</project>
Now when you build it will create an EAR that includes the 2 WARs generated by module1 and module2. The ear in this example is simply called module3:
EDIT: Original answer re-added per request in comments.
Here is the POM from the original proposal - using two profiles to specify different dependency versions. As before please note that it's not a good idea to include servlet api inside of a WAR file, it's just being used here as a visual example to show how common dependencies are specified.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maven-war-diff-depend</groupId>
<artifactId>maven-war-diff-depend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>v2.3</id>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>v2.8.1</id>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

Use of environment variable in POM.xml doesn't work

I am trying to pull out the version number of the POM and all the dependencies to a environment variable. For example:
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven- 4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance">
<modelVersion>4.0.0</modelVersion>
<artifactId>example-assembly</artifactId>
<name>example-assembly</name>
<properties>
<current.version>${env.CURRENTVERSION}</current.version>
</properties>
<dependencies>
<dependency>
<groupId>com.example.demo</groupId>
<artifactId>exceptions</artifactId>
<version>${current.version}</version>
</dependency>
<dependencies>
<packaging>war</packaging>
<version>${current.version}</version>
</project>
With the above setup, when I run mvn clean command I am getting following error:
dependencies.dependency.version for example-assembly:war must be a valid version but is '${env.CURRENTVERSION}'
Any idea about what could be the issue?
Note: I am running maven in windows OS
There is a better alternative for updating Versions in pom.xml than using environment variables inside pom.xml: Versions Maven Plugin. This allows you to change pom.xml using maven command line.
Sample scenario
Project Structure:
+ P (Parent - Version 1.0.0-SNAPSHOT)
-- C1 (Child Project 1 - Version 1.0.0-SNAPSHOT)
-- C2 (Child Project 2 - Version 1.0.0-SNAPSHOT also depends on C1)
Task
You want to change version in all pom.xml files to 1.0.1-SNAPSHOT
Parent pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>sample</groupId>
<artifactId>p</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>Parent</name>
<packaging>pom</packaging>
<modules>
<module>c1</module>
<module>c2</module>
</modules>
</project>
Child Project 1 pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>c1</artifactId>
<name>Child Project 1</name>
<packaging>jar</packaging>
<parent>
<groupId>sample</groupId>
<artifactId>p</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
</project>
Child Project 2 pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>c2</artifactId>
<name>Child Project 2</name>
<packaging>jar</packaging>
<parent>
<groupId>sample</groupId>
<artifactId>p</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>sample</groupId>
<artifactId>c1</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Command
Command to set new version in all pom.xml files
mvn -B -DnewVersion=1.0.1-SNAPSHOT versions:set
In case new version is represented by environment variable CURRENTVERSION
mvn -B -DnewVersion=$CURRENTVERSION versions:set
Here -B means --batch-mode (so new version won't be prompted on console)
Resultant files would be
Parent pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>sample</groupId>
<artifactId>p</artifactId>
<version>1.0.1-SNAPSHOT</version>
<name>Parent</name>
<packaging>pom</packaging>
<modules>
<module>c1</module>
<module>c2</module>
</modules>
</project>
Child Project 1 pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>c1</artifactId>
<name>Child Project 1</name>
<packaging>jar</packaging>
<parent>
<groupId>sample</groupId>
<artifactId>p</artifactId>
<version>1.0.1-SNAPSHOT</version>
</parent>
</project>
Child Project 2 pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>c2</artifactId>
<name>Child Project 2</name>
<packaging>jar</packaging>
<parent>
<groupId>sample</groupId>
<artifactId>p</artifactId>
<version>1.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>sample</groupId>
<artifactId>c1</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
The variable you define has the scope in the same pom.xml only and cannot be used in any other pom.
If you want to define the variable globally define it in settings.xml of maven.
Define the variable env.CURRENTVERSION somewhere in the the same pom, root pom or settings.xml
or else provide the exact version value in its place.
<properties>
<current.version>'your correct version'</current.version>
</properties>
e.g.
<properties>
<current.version>1.0.0</current.version>
</properties>

Teamcity, build maven project with parent dependency

I've 1 project with one subproject in my teamcity server. The subproject has the pom.xml file that references parent project.
This is the pom.xml of the project:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>it.company.project</groupId>
<artifactId>MyProject</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>MyProject</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<modules>
<module>Foo</module>
</modules>
</project>
This is the pom.xml of the subproject:
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>it.company.project</groupId>
<artifactId>MyProject</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>Foo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>subproject</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</resource>
</resources>
</build>
</project>
When I run the maven build from my IDE (IntelliJ IDEA) on my subproject, all works fine. Also when I run maven build on the parent project all works fine.
When I run build agent (configured to run pom.xml) from TeamCity server on my subproject it doesn't work, and I've the following errors:
[Step 1/1] Error reading Maven project: Some problems were encountered while processing the POMs:
[FATAL] Non-resolvable parent POM: Could not find artifact it.company.project:MyProject:pom:1.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM # line 5, column 13
.
[14:08:12][Step 1/1] TeamCity is unable to read Maven project. Some features may be unavailable
When I run build agent (configured to run pom.xml) from TeamCity server on my parent project it doesn't work, and I've the following errors:
An error occurred during collecting Maven project information: File not found in any VCS root: subproject/pom.xml.
My subproject build configurations:
What's wrong?
Thanks

Maven module hierarchy

I have two modules(maven projects) in parent maven project: android-module and server-module. This two modules uses identical models(POJO - classes). So I want extract models from both modules and make new module in parent project.
So I whant this:
--Project
|--android-module
| -- pom.xml
|--server-module
| -- pom.xml
-- pom.xml
remake to this:
--Project
|--android-module
| -- pom.xml
|--server-module
| -- pom.xml
|--models-module
| -- pom.xml
-- pom.xml
At the same time I want to root pom.xml compiles and build jar from models-module and store jar in my local repository. Then child pom.xml's were taking it from the repository and included in the android and server modules.
Question: How to tell maven to build and store jar in my local repository automatically.
Is it possible? If no - please, give me some ideas.... Thnks
Just run mvn install. This will install the packaged jar into your local repo in ~/.m2
Make sure you run maven from the root pom
The solution is found. It was much easier.
parent pom.xml:
...
<groupId>com.lutshe</groupId>
<artifactId>doiter</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>doiter-android</module>
<module>doiter-server</module>
<module>doiter-model</module>
</modules>
...
child1 (android project) pom.xml:
...
<parent>
<groupId>com.lutshe</groupId>
<artifactId>doiter</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.lutshe</groupId>
<artifactId>doiter-android</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>apk</packaging>
<dependencies>
<dependency>
<groupId>com.lutshe</groupId>
<artifactId>doiter-models</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
...
child2 (server) pom.xml:
...
<parent>
<groupId>com.lutshe</groupId>
<artifactId>doiter</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.doiter.server</groupId>
<artifactId>doiter-server</artifactId>
<version>0.1.0</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.lutshe</groupId>
<artifactId>doiter-models</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
...
child3 (shared models) pom.xml:
...
<parent>
<groupId>com.lutshe</groupId>
<artifactId>doiter</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.lutshe</groupId>
<artifactId>doiter-model</artifactId>
<version>1.0-SNAPSHOT</version>
...

Invalid packaging for parent pom.xml, must be "pom" but is "ear"

Could anybody suggest me an solution with the following exception. I am going to create a multi-module project.
Parent Project name is LOGICBACKEND
child project name is DBAccess
I need to have ear file of LOGICBACKEND which should contain DBAccess prjoects jar file.
I am getting following exception when i run mav clean install -P Developer.
[ERROR]The project com.project1.Database:DBAccess:1.0-SNAPSHOT (C:\Project1\DBAccess\pom.xml) has 1 error
[ERROR]Invalid packaging for parent POM com.project1.logic:LOGIC:1.0-SNAPSHOT (C:\Project1\pom.xml), must be "pom" but is "ear" # com.project1.logic:LOGIC:1.0-SNAPSHOT, C:\Project1\pom.xml, line 6, column 13
This is how part of my parent pom.xml looks
<modelVersion>4.0.0</modelVersion>
<groupId>com.project1.logic</groupId>
<artifactId>LOGICBACKEND</artifactId>
<packaging>ear</packaging>
<version>1.0-SNAPSHOT</version>
This is how child pom.xml looks
<groupId>com.project1.logic</groupId>
<artifactId>DBAccess</artifactId>
<packaging>ejb</packaging>
<name>DBAccess</name>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>com.project1.logic</groupId>
<artifactId>DBAccess</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
Could anybody help me here to understand what is going wrong here.
Thanks in advance for any help
This simple setup is a good start.
.
├── pom.xml
├── services
| ├── pom.xml
| └── src
| └── main
| └── java
| └── com
| └── stackoverflow
| └── MyEjbService.java
└── application
└── pom.xml
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.stackoverflow.Q13330930</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>${project.artifactId}-${project.version}</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modules>
<module>services</module>
<module>application</module>
</modules>
<dependencies>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.stackoverflow.Q13330930</groupId>
<artifactId>services</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<ejbVersion>3.1</ejbVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
services/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.stackoverflow.Q13330930</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.stackoverflow.Q13330930</groupId>
<artifactId>services</artifactId>
<packaging>ejb</packaging>
<name>${project.artifactId}-${project.version}</name>
</project>
application/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.stackoverflow.Q13330930</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.stackoverflow.Q13330930</groupId>
<artifactId>application</artifactId>
<packaging>ear</packaging>
<name>${project.artifactId}-${project.version}</name>
<dependencies>
<dependency>
<groupId>com.stackoverflow.Q13330930</groupId>
<artifactId>services</artifactId>
<type>ejb</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.7</version>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
</configuration>
</plugin>
</plugins>
</build>
</project>
You are trying to give the parent pom two functions - that is serving as a parent pom (packaging pom) and being the wrapper ear (packaging ear) - at the same time. To solve your issue you should create another maven module under your parent pom that has packaging ear and uses the maven-ear-plugin to define the output.
I got the similar error:
[ERROR]
[ERROR] Invalid packaging for parent POM sandbox:parent:6.5-SNAPSHOT, must be "pom" but is "jar" # sandbox:parent:6.5-SNAPSHOT
I figured out that the root cause was in parent version defined through properties:
<version>${revision}${changelist}</version>
As soon as I set version without referencing the properties the issue gone:
<version>6.5-SNAPSHOT</version>
Might be a maven bug.

Categories

Resources