Merge branch 'master' of https://gitbox.apache.org/repos/asf/turbine-archetypes
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..a43064b
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Turbine Webapp Component
+Copyright 2006-2016 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README b/README
new file mode 100644
index 0000000..d7e9268
--- /dev/null
+++ b/README
@@ -0,0 +1,5 @@
+If you get that goal integration-test of maven-archetype-plugin fails with
+
+'Cannot run additions goals." cft. https://issues.apache.org/jira/browse/ARCHETYPE-488.
+
+Fastest workaround (Dez 2016) ist to copy mvn.cmd to mvn.bat.
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..ed5ba5e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<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>
+ <parent>
+ <groupId>org.apache</groupId>
+ <artifactId>apache</artifactId>
+ <version>18</version>
+ </parent>
+ <groupId>org.apache.turbine</groupId>
+ <artifactId>turbine-webapp-4.0</artifactId>
+ <version>1.0.2-SNAPSHOT</version>
+ <packaging>maven-archetype</packaging>
+
+ <name>Archetype - Turbine 4.0 WebApp</name>
+ <description>This archetype sets up a web application project based on Apache Turbine 4.0</description>
+ <url>http://turbine.apache.org</url>
+
+ <inceptionYear>2011</inceptionYear>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/turbine/maven/archetypes/trunk/turbine-webapp-4.0/</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/turbine/maven/archetypes/trunk/turbine-webapp-4.0/</developerConnection>
+ <url>http://svn.apache.org/viewvc/turbine/maven/archetypes/trunk/turbine-webapp-4.0/</url>
+ </scm>
+
+<build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.archetype</groupId>
+ <artifactId>archetype-packaging</artifactId>
+ <version>3.0.1</version>
+ </extension>
+ </extensions>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-archetype-plugin</artifactId>
+ <version>3.0.1</version>
+ <!-- skip tests in generated archetype's pom, here the integration-test would be skipped -->
+ <!--configuration>
+ <skip>true</skip>
+ </configuration-->
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+</project>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
new file mode 100644
index 0000000..daeae8a
--- /dev/null
+++ b/src/changes/changes.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<document>
+ <properties>
+ <title>Changes</title>
+ <author email="tv@apache.org">Thomas Vandahl</author>
+ </properties>
+
+ <body>
+ <release version="1.0.2" date="in Subversion">
+ <action type="update" dev="gk" due-to="Jeffery Painter">
+ Added security test to show Turbine Fulcrum Torque consistency
+ </action>
+ <action type="fix" dev="gk" due-to="Jeffery Painter">
+ Fix OM classes and schema, SQL autoincrement by default used
+ </action>
+ <action type="update" dev="gk">
+ war plugin 3.2, mysql connector 5.1.44 Update
+ </action>
+ <action type="update" dev="gk">
+ Integrate JSON, Localization, Model Examples
+ </action>
+ <action type="update" dev="gk">
+ Using Torque Services, Code Cleanup, Removing Classes
+ </action>
+ <action type="update" dev="gk">
+ Turbine 4.0, JUNit 4.12
+ </action>
+ </release>
+ <release version="1.0.1" date="in Subversion">
+ <action dev="gk" type="add">
+ Password change action, Check anonymous login
+ </action>
+ <action dev="gk" type="update">
+ JNDI Jetty Update
+ </action>
+ <action dev="tv" type="add">
+ Add testing in place with "integration-test"
+ </action>
+ <action dev="tv" type="update">
+ Turbine annotations, use auto detect Torque adapter
+ </action>
+ <action dev="gk" type="update">
+ Fulcrum Torque Security added manager, om classes
+ </action>
+ <action dev="painter" type="add">
+ Added readme, docs, helper sql..
+ </action>
+ <action dev="painter" type="update">
+ MySQL is now default
+ </action>
+ <action dev="gk" type="update">
+ Update schema to torque / intake 4.0, dependencies, configurations
+ Update to MemoryGroupManagerImpl, Fulcrum
+ </action>
+ <action dev="gk" type="add">
+ Jetty support
+ </action>
+ <action dev="tv" type="fix">
+ TRB-95
+ </action>
+ <action dev="gk" type="update ">
+ Update to Turbine 4-M2
+ </action>
+ </release>
+ <release version="1.0.0" date="2012-11-06">
+ <action dev="tv" type="fix">
+ Fixed missing dependencies and wrong class names as reported on the mailing list
+ </action>
+ <action dev="tv" type="add">
+ Add information required for a release to the POM
+ </action>
+ <action dev="tv" type="add">
+ Initial version
+ </action>
+ </release>
+ </body>
+</document>
diff --git a/src/main/resources/META-INF/maven/archetype-metadata.xml b/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..bac4dcf
--- /dev/null
+++ b/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<archetype-descriptor
+ xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
+ name="turbine-4.0-webapp">
+
+ <requiredProperties>
+ <requiredProperty key="turbine_app_name">
+ <defaultValue>My Turbine Web Application</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="turbine_intake_file">
+ <defaultValue>intake.xml</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="turbine_database_name">
+ <defaultValue>turbine</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="turbine_database_adapter">
+ <defaultValue>auto</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="turbine_database_jndipath">
+ <defaultValue>jdbc/turbine</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="turbine_database_driver">
+ <defaultValue>com.mysql.jdbc.Driver</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="turbine_database_url">
+ <defaultValue>jdbc:mysql://localhost:3306/</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="turbine_database_user">
+ <defaultValue>db_user</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="turbine_database_password">
+ <defaultValue>db_password</defaultValue>
+ </requiredProperty>
+ </requiredProperties>
+ <fileSets>
+ <fileSet filtered="true" packaged="true">
+ <directory>src/test/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" packaged="false">
+ <directory>src/test/resources</directory>
+ <includes>
+ <include>**/*.properties</include>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="false" packaged="false">
+ <directory>src/test/logs</directory>
+ <includes>
+ <include>**/*.log</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" packaged="false">
+ <directory>src/test/conf</directory>
+ <includes>
+ <include>**/*.properties</include>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" packaged="true" encoding="UTF-8">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ <include>**/*.properties</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="false" packaged="false" encoding="UTF-8">
+ <directory>docs</directory>
+ <includes>
+ <include>**/*.txt</include>
+ <include>**/*.sql</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" packaged="false" encoding="UTF-8">
+ <directory>src/main/torque-schema</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" packaged="false" encoding="UTF-8">
+ <directory>src/main/webapp/META-INF</directory>
+ <includes>
+ <include>**/*.xml</include>
+ <include>**/*.properties</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" packaged="false" encoding="UTF-8">
+ <directory>src/main/webapp/WEB-INF</directory>
+ <includes>
+ <include>**/*.xml</include>
+ <include>**/*.properties</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="false" packaged="false" encoding="UTF-8">
+ <directory>src/main/webapp/templates</directory>
+ <includes>
+ <include>**/*.vm</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="false" packaged="false" encoding="UTF-8">
+ <directory>src/main/webapp/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</archetype-descriptor>
diff --git a/src/main/resources/archetype-resources/docs/README.txt b/src/main/resources/archetype-resources/docs/README.txt
new file mode 100644
index 0000000..fb6c31f
--- /dev/null
+++ b/src/main/resources/archetype-resources/docs/README.txt
@@ -0,0 +1,178 @@
+#*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*#
+
+Notice
+
+About this archetype
+
+Turbine Version: Turbine 4.0.
+
+# Quick Guide to using the new Turbine 4.0 maven archetype
+for skeleton application generation
+
+## Local database Setup
+
+First, you should have a local database installed and configured prior to
+beginning the application setup below.
+
+As we are using MySQL bey default you need to create the database in MySQL, e.g. with
+
+mysql -u <user> -p
+mysql> create database helloWorld;
+mysql> \q
+
+or other tools. The database should have been started and the database user granted enough rights.
+
+## Maven archetype
+
+Next, you can invoke the Maven archetype for turbine-webapp-4.0 from
+the command line as shown below - please update values starting
+with 'groupId' as appropriate.
+
+mvn archetype:generate \
+ -DarchetypeGroupId=org.apache.turbine \
+ -DarchetypeArtifactId=turbine-webapp-4.0 \
+ -DarchetypeVersion=1.0.1-SNAPSHOT \
+ -DgroupId=com.mycompany.webapp \
+ -DartifactId=myhelloworld \
+ -Dversion=1.0 \
+ -Dturbine_app_name=HelloWorld \
+ -Dturbine_database_adapter=mysql \
+ -Dturbine_database_user=db_username \
+ -Dturbine_database_password=db_password \
+ -Dturbine_database_name=helloworld \
+ -Dturbine_database_url=jdbc:mysql://localhost:3306/ \
+ -Dgoals=generate-sources,pre-integration-test
+
+### Notes
+
+When invoking archetype:generate like above, you already have set Turbine goals generate-sources,pre-integration-test
+and you can then skip them later.
+
+Be aware, when you set both mvn commands goals (which are maven phases actually), i.e with
+
+-Dgoals=generate-sources, pre-integration-test
+
+you have to create the database (see above) before finishing the (interactive) archetype commands.
+Otherwise you could catch up doing this later and after that is done calling the phases afterwards as mentioned below.
+
+#### turbine_database_url
+
+Note that the database URL (turbine_database_url)
+will be appended with your database name
+in the final pom.xml, so you do not need to specify that in
+the configuration.
+
+## Project Start and Usage
+
+Next, change into the newly generated project folder, in our case
+
+cd myhelloworld
+
+Skip next two steps, if the build was successfull
+mvn generate-sources ## This will generate the OM layer and SQL
+ ## code for creating the corresponding
+ ## database tables
+
+mvn integration-test ## This executes the SQL code to create
+ ## the application schema defined
+ ## in src/main/torque-schema
+
+You should now check the database tables and if some data is missing
+insert the sample data file in sample-mysql-data (Torque 4.0 has disabled the datasql task).
+
+mvn clean install
+
+If you get an error like "The driver has not received any packets" probably the database is not up and running or the port may be another one.
+
+Last step on the command line is run the server by invoking
+mvn jetty:run ## Now you can launch your new Turbine application
+
+### Logs
+
+Find the Logs in src/main/webapp/logs and
+
+### Application
+
+Open a web browser to http://localhost:8081/app
+
+Login should work with user admin/password or user/password.
+
+## Background
+
+By default Intake is used as an validation mechanism for authentication. You can change to the default login by setting
+
+action.login=LoginUser in TurbineResources.properties and changing Login.vm appropriately (commented form)
+
+## Tests
+
+Prerequisites
+- ignored tests require at least Turbine version 4.0.1
+- database was build successfully e.g. with archetype.
+- running mysql
+
+If running from integration test, check/update
+- in pom.xml turbine.core property,
+- target/test-classes/projects/first/project/integrationtest/src/test/conf/torque/TorqueTest.properties or
+ META-INF/maven/archetype-metadata.xml
+
+The security test is by default skipped as it requires a running mysql. It tests many of the Fulcrum Torque Turbine security aspects,
+activate it by calling
+
+mvn test -DskipTests=false
+
+CAVEAT: If initialization fails, double check your database credentials! If invalid the error might be somewhat hidden behind a
+ Torque exception!
+
+## Eclipse
+
+To enable application development in Eclipse, run the following command
+and then import the project into Eclipse.
+
+mvn eclipse:eclipse
+
+Once imported, update your project to be managed by Maven
+-> Right click on the project name
+-> Configure
+-> Convert to Maven project
+
+To test the application can be deployed by Eclipse, select the run
+configuration "Run On Server" if you have a container configured with
+your eclipse environment.
+
+### Eclipse Debugging
+
+You even could debug the app by setting the environment variable to something like this
+
+set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n
+
+before running the jetty server.
+
+## Starting developing
+
+Be aware of settings and some smaller restrictions, which mostly will be fixed in the upcoming releases.
+
+- Keep groups/roles lower case (which should be fixed in Fulcrum Security 1.1.1/Turbine 4.0)
+- abstract classes and managers are included (because of some minor bugs in Fulcrum Security 1.1.0, same as above)
+- LogoutUser action is included (fix in Turbine 4.0, getUserFromSession)
+- LoginUser action is included (to check for anonymous user, may be fixed in future release)
+- OM (Torque Object Mapper) stub classes are included (until configurable in schema with Torque version 2.1)
+- TurbineConfiguration returns a Commons configuration object, even if field is not assignable (will be fixed in Turbine 4.0, you can then assign e.g. to String instead, cft. SecureScreen)
+- Database connection is done initially by default with JNDI. If you want to change it, check Torque.properties and (1) for Tomcat, META-INF/context.xml or (2) for Jetty, WEB-INF/jetty-env.xml.
+
diff --git a/src/main/resources/archetype-resources/docs/sample-mysql-data/_application-data.sql b/src/main/resources/archetype-resources/docs/sample-mysql-data/_application-data.sql
new file mode 100644
index 0000000..f605246
--- /dev/null
+++ b/src/main/resources/archetype-resources/docs/sample-mysql-data/_application-data.sql
@@ -0,0 +1,15 @@
+
+##
+## application-data.sql
+##
+## Torque will not autogenerate these files anymore - please run
+## this SQL code maually to get your application up and running
+##
+
+INSERT INTO AUTHOR (AUTH_ID, FIRST_NAME, LAST_NAME) values (1, 'Donald', 'Knuth');
+INSERT INTO AUTHOR (AUTH_ID, FIRST_NAME, LAST_NAME) values (2, 'Mickey', 'Mouse' );
+INSERT INTO AUTHOR (AUTH_ID, FIRST_NAME, LAST_NAME) values (3, 'Bill', 'Bryson' );
+
+INSERT INTO BOOK ( BOOK_ID, AUTH_ID, TITLE, SUBJECT ) values ( 1, 1, 'The Art of Computer Programming', 'Computer Science');
+INSERT INTO BOOK ( BOOK_ID, AUTH_ID, TITLE, SUBJECT ) values ( 2, 2, 'Disney: Behind the Scenes', 'Fiction' );
+INSERT INTO BOOK ( BOOK_ID, AUTH_ID, TITLE, SUBJECT ) values ( 3, 3, 'A Walk in the Woods', 'Fiction');
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/docs/sample-mysql-data/_turbine-security-data.sql b/src/main/resources/archetype-resources/docs/sample-mysql-data/_turbine-security-data.sql
new file mode 100644
index 0000000..48ebeeb
--- /dev/null
+++ b/src/main/resources/archetype-resources/docs/sample-mysql-data/_turbine-security-data.sql
@@ -0,0 +1,51 @@
+##
+## turbine-security-data.sql
+##
+## Torque will not autogenerate these files anymore - but sql-maven-plugin!
+## If not, please run
+## this SQL code manually to get your application up and running
+##
+SET FOREIGN_KEY_CHECKS=0;
+
+INSERT INTO TURBINE_USER (USER_ID,LOGIN_NAME,PASSWORD_VALUE,FIRST_NAME,LAST_NAME)
+ VALUES (1,'admin','password','','Admin');
+
+INSERT INTO TURBINE_USER (USER_ID,LOGIN_NAME,PASSWORD_VALUE,FIRST_NAME,LAST_NAME)
+ VALUES (2,'user','password','','User');
+
+INSERT INTO TURBINE_USER (USER_ID,LOGIN_NAME,PASSWORD_VALUE,FIRST_NAME,LAST_NAME)
+ VALUES (3,'anon','nopw','','Anon');
+
+INSERT INTO TURBINE_PERMISSION (`PERMISSION_ID`, `PERMISSION_NAME`) VALUES
+(2, 'Turbine'),
+(1, 'TurbineAdmin');
+
+INSERT INTO TURBINE_ROLE (`ROLE_ID`, `ROLE_NAME`) VALUES
+(1, 'turbineadmin'),
+(2, 'turbineuser');
+
+INSERT INTO TURBINE_GROUP (`GROUP_ID`, `GROUP_NAME`) VALUES
+(1, 'global'),
+(2, 'Turbine');
+
+INSERT INTO TURBINE_ROLE_PERMISSION (`ROLE_ID`, `PERMISSION_ID`) VALUES
+(1, 1),
+(2, 2);
+
+INSERT INTO TURBINE_USER_GROUP_ROLE (`USER_ID`, `GROUP_ID`, `ROLE_ID`) VALUES
+(1, 1, 1),
+(1, 2, 1),
+(2, 2, 2),
+(2, 1, 2);
+
+--
+ALTER TABLE TURBINE_USER MODIFY COLUMN USER_ID INT auto_increment;
+ALTER TABLE TURBINE_PERMISSION MODIFY COLUMN PERMISSION_ID INT auto_increment;
+ALTER TABLE TURBINE_ROLE MODIFY COLUMN ROLE_ID INT auto_increment;
+ALTER TABLE TURBINE_GROUP MODIFY COLUMN GROUP_ID INT auto_increment;
+
+
+##-- use ID_TABLE with idMethod="idbroker" and set appropriate start_id and end_id
+##-- INSERT INTO ID_TABLE (id_table_id, table_name, next_id, quantity) VALUES (1,'TURBINE_USER',start_id, end_id);
+
+
diff --git a/src/main/resources/archetype-resources/pom.xml b/src/main/resources/archetype-resources/pom.xml
new file mode 100644
index 0000000..a1b25f6
--- /dev/null
+++ b/src/main/resources/archetype-resources/pom.xml
@@ -0,0 +1,424 @@
+<?xml version="1.0" encoding="UTF-8"?>
+#*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*#
+#set($dollar = '$')
+#macro (var $label)${dollar}{${label}}#end
+<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>${package}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+ <packaging>war</packaging>
+
+ <name>${turbine_app_name}</name>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.properties</include>
+ </includes>
+ </resource>
+ <!-- (target) resource and filtering is not used at all ?
+ at least removed setting absolute path e.g. with #var("project.build.directory"),
+ which does thrown an exception with mvn eclipse:eclipse - path is then incorrectly relativized.
+ -->
+ <resource>
+ <targetPath>../torque/schema</targetPath>
+ <filtering>true</filtering>
+ <directory>src/main/torque-schema</directory>
+ <includes>
+ <include>*.xml</include>
+ </includes>
+ </resource>
+ </resources>
+ <testSourceDirectory>src/test/java</testSourceDirectory>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <includes>
+ <include>*.xml</include>
+ <include>*.properties</include>
+ </includes>
+ </testResource>
+ </testResources>
+ <plugins>
+ <!-- test will not fail in turbine 4.0.1 -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.20.1</version>
+ <configuration>
+ <skipTests>#var("skipTests")</skipTests>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.5.1</version>
+ <configuration>
+ <source>#var("maven.compile.source")</source>
+ <target>#var("maven.compile.target")</target>
+ <encoding>#var("project.build.sourceEncoding")</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.torque</groupId>
+ <artifactId>torque-maven-plugin</artifactId>
+ <version>4.0</version>
+ <configuration>
+ <schemaDir>#var("project.basedir")/src/main/torque-schema</schemaDir>
+ <useClasspath>true</useClasspath>
+ <runOnlyOnSchemaChange>false</runOnlyOnSchemaChange>
+ <targetDatabase>${turbine_database_adapter}</targetDatabase>
+ </configuration>
+ <executions>
+ <execution>
+ <id>torque-om</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <configuration>
+ <packaging>classpath</packaging>
+ <configPackage>org.apache.torque.templates.om</configPackage>
+ <sourceDir>#var("project.basedir")/src/main/torque-schema</sourceDir>
+ <loglevel>error</loglevel>
+ <options>
+ <torque.database>${turbine_database_adapter}</torque.database>
+ <torque.om.package>${package}.om</torque.om.package>
+ <torque.om.addGetByNameMethods>false</torque.om.addGetByNameMethods>
+ <torque.om.save.saveException>TorqueException</torque.om.save.saveException>
+ <torque.om.useIsForBooleanGetters>true</torque.om.useIsForBooleanGetters>
+ <torque.om.useManagers>false</torque.om.useManagers>
+ <torque.om.addTimeStamp>true</torque.om.addTimeStamp>
+ <torque.om.objectIsCaching>true</torque.om.objectIsCaching>
+ <torque.om.save.addSaveMethods>true</torque.om.save.addSaveMethods>
+ <torque.om.addGetByNameMethods>true</torque.om.addGetByNameMethods>
+ <torque.om.complexObjectModel>true</torque.om.complexObjectModel>
+ </options>
+ <!-- keeping defaultOutputDir in default ${project.build.directory}/generated-sources will havee the base classes there -->
+ <!-- we want the classes, which may be custumoized in the source directory. Ignore the warning about generated-java -->
+ <outputDirMap>
+ <modifiable>#var("project.build.sourceDirectory")</modifiable>
+ </outputDirMap>
+ </configuration>
+ </execution>
+ <execution>
+ <id>torque-sql-mysql</id><!-- ${turbine_database_adapter} -->
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <configuration>
+ <packaging>classpath</packaging>
+ <configPackage>org.apache.torque.templates.sql</configPackage>
+ <sourceDir>#var("project.basedir")/src/main/torque-schema</sourceDir>
+ <defaultOutputDir>#var("project.build.directory")/generated-sql/torque/mysql</defaultOutputDir>
+ <defaultOutputDirUsage>none</defaultOutputDirUsage>
+ <loglevel>error</loglevel>
+ <options>
+ <torque.database>mysql</torque.database>
+ </options>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.torque</groupId>
+ <artifactId>torque-templates</artifactId>
+ <version>4.0</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.2.0</version>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <X-Compile-Source-JDK>#var("maven.compile.source")</X-Compile-Source-JDK>
+ <X-Compile-Target-JDK>#var("maven.compile.target")</X-Compile-Target-JDK>
+ </manifestEntries>
+ </archive>
+ <!-- containerConfigXML>WEB-INF/build/context.xml</containerConfigXML -->
+ </configuration>
+ </plugin>
+ <!-- Required to execute torque database build -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>sql-maven-plugin</artifactId>
+ <version>1.5</version>
+ <configuration>
+ <!-- Please update with your database configuration -->
+ <driver>${turbine_database_driver}</driver>
+ <url>${turbine_database_url}${turbine_database_name}</url>
+ <username>${turbine_database_user}</username>
+ <password>${turbine_database_password}</password>
+ <onError>continue</onError>
+ <autocommit>true</autocommit>
+ <orderFile>descending</orderFile>
+ </configuration>
+ <!-- update with your database driver dependency -->
+ <!-- this is mysql specific -->
+ <dependencies>
+ <dependency>
+ <artifactId>mysql-connector-java</artifactId>
+ <groupId>mysql</groupId>
+ <version>5.1.44</version>
+ </dependency>
+ </dependencies>
+ <!-- this is mysql specific -->
+ <executions>
+ <execution>
+ <id>create-db</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <orderFile>ascending</orderFile>
+ <fileset>
+ <basedir>#var("project.build.directory")/generated-sql/torque/mysql</basedir>
+ <!-- basedir>${basedir}/target/generated-sql</basedir -->
+ <includes>
+ <include>*.sql</include>
+ </includes>
+ </fileset>
+ </configuration>
+ </execution>
+ <execution>
+ <id>create-data</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <orderFile>ascending</orderFile>
+ <srcFiles>
+ <srcFile>#var("project.basedir")/docs/sample-mysql-data/_application-data.sql</srcFile>
+ <srcFile>#var("project.basedir")/docs/sample-mysql-data/_turbine-security-data.sql</srcFile>
+ </srcFiles>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- jetty:run checks deployed war http://localhost:8081/app/
+ Using jetty 8 as supporting java 6. Other specs cft. http://www.eclipse.org/jetty/documentation/9.3.0.v20150612/what-jetty-version.html -->
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <version>8.1.16.v20140903</version>
+ <configuration>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ <dumpOnStart>true</dumpOnStart>
+ <reload>manual</reload>
+ <connectors>
+ <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
+ <port>8081</port>
+ </connector>
+ </connectors>
+ <!--webApp>
+ <contextPath>/app</contextPath>
+ </webApp-->
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+
+ <!-- update with the database driver of your choice -->
+ <dependency>
+ <artifactId>mysql-connector-java</artifactId>
+ <groupId>mysql</groupId>
+ <version>5.1.44</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.activation</groupId>
+ <artifactId>activation</artifactId>
+ <version>1.1.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ <version>1.4.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.turbine</groupId>
+ <artifactId>turbine</artifactId>
+ <version>#var("turbine.core")</version>
+ </dependency>
+ <!-- slf4j still optional in 4.0 -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency> <!-- delegate slf4j to log4j -->
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency> <!-- redirect JCL to slf4j -->
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <!-- yaafi is optional. NOTICE: 1.0.7 has group org.apache.turbine not org.apache.fulcrum -->
+ <dependency>
+ <groupId>org.apache.turbine</groupId>
+ <artifactId>fulcrum-yaafi</artifactId>
+ <version>1.0.7</version>
+ </dependency>
+ <!-- if using intake -->
+ <dependency>
+ <groupId>org.apache.fulcrum</groupId>
+ <artifactId>fulcrum-intake</artifactId>
+ <version>#var("fulcrum.intake")</version>
+ </dependency>
+ <!-- include some optional dependencies required in example componentConfiguration.xml -->
+ <dependency>
+ <groupId>org.apache.fulcrum</groupId>
+ <artifactId>fulcrum-cache</artifactId>
+ <version>1.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.fulcrum</groupId>
+ <artifactId>fulcrum-upload</artifactId>
+ <version>1.0.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.fulcrum</groupId>
+ <artifactId>fulcrum-security-memory</artifactId>
+ <version>#var("fulcrum.security")</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.fulcrum</groupId>
+ <artifactId>fulcrum-security-torque</artifactId>
+ <version>#var("fulcrum.security")</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.fulcrum</groupId>
+ <artifactId>fulcrum-security-api</artifactId>
+ <version>#var("fulcrum.security")</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.fulcrum</groupId>
+ <artifactId>fulcrum-json-jackson2</artifactId>
+ <version>#var("fulcrum.json")</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-json-org</artifactId>
+ <!-- version>$dollar{jackson.version}</version-->
+ <!-- 2.7.x has Java 7 baseline, but not compiled with Java 6 support (version 51 error:), cft. https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.7 Changes: compatibility: .. should still be possible to use Jackson 2.7 on Java 6, but not compile, build. With Jackson 2.8, Java 7 languages features will be allowed -->
+ <version>2.6.6</version>
+ </dependency>
+ <!-- if activating useJsonPath include jayway dependency -->
+ <!-- dependency>
+ <groupId>com.jayway.jsonpath</groupId>
+ <artifactId>json-path</artifactId>
+ <version>2.3.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>net.minidev</groupId>
+ <artifactId>json-smart</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency-->
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.fulcrum</groupId>
+ <artifactId>fulcrum-testcontainer</artifactId>
+ <version>1.0.7</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <maven.compile.source>1.6</maven.compile.source>
+ <maven.compile.target>1.6</maven.compile.target>
+ <project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
+ <fulcrum.json>1.1.1</fulcrum.json>
+ <fulcrum.intake>1.2.3</fulcrum.intake>
+ <fulcrum.security>1.1.2</fulcrum.security>
+ <turbine.core>4.0.1</turbine.core>
+ <slf4j.version>1.7.25</slf4j.version>
+ <skipTests>true</skipTests>
+ </properties>
+
+
+ <profiles>
+ <profile>
+ <id>jetty</id>
+ <build>
+ <defaultGoal>jetty:run</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <configuration>
+ <connectors>
+ <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
+ <port>15000</port>
+ <maxIdleTime>60000</maxIdleTime>
+ </connector>
+ </connectors>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>tomcat</id>
+ <build>
+ <defaultGoal>tomcat:run</defaultGoal>
+ <finalName>#var("project.artifactId")</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>tomcat-maven-plugin</artifactId>
+ <configuration>
+ <port>15000</port>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/src/main/resources/archetype-resources/src/main/java/L10N.properties b/src/main/resources/archetype-resources/src/main/java/L10N.properties
new file mode 100644
index 0000000..f9f58dd
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/L10N.properties
@@ -0,0 +1,24 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+l10nkey=Default value
+username_required_msg=Please enter an email address as user name
+username_min_length_msg=Please enter at least {0} characters
+username_mask_msg=Please enter a valid email address as user name
+password_msg=Please enter a password
+no_permission=You do not have permission, login required.
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/java/L10N_de_DE.properties b/src/main/resources/archetype-resources/src/main/java/L10N_de_DE.properties
new file mode 100644
index 0000000..1921853
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/L10N_de_DE.properties
@@ -0,0 +1,30 @@
+#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+l10nkey = German value
+
+password_msg = Bitte ein Passwort eingeben
+
+username_mask_msg = Geben Sie als Benutzername eine E-Mail-Adresse ein
+
+username_min_length_msg = Es m\u00FCssen {0} Zeichen eingegeben werden
+
+username_required_msg = Bitte einen Benutzernamen eingeben
+
+no_permission=Unautorisierte Aktion erfordert Login.
diff --git a/src/main/resources/archetype-resources/src/main/java/L10N_en_US.properties b/src/main/resources/archetype-resources/src/main/java/L10N_en_US.properties
new file mode 100644
index 0000000..44120d1
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/L10N_en_US.properties
@@ -0,0 +1,23 @@
+#*
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+l10nkey=US-English value
+username_required_msg=Please enter an email address as user name
+username_min_length_msg=Please enter at least {0} characters
+username_mask_msg=Please enter a valid email address as user name
+password_msg=Please enter a password
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxAction.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxAction.java
new file mode 100644
index 0000000..3ba889e
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxAction.java
@@ -0,0 +1,97 @@
+package ${package}.flux.modules.actions;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.fulcrum.localization.LocalizationService;
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.actions.VelocitySecureAction;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+/**
+ * Velocity Secure action.
+ *
+ * Always performs a Security Check that you've defined before executing the
+ * doPerform().
+ */
+public class FluxAction extends VelocitySecureAction {
+
+ @TurbineService
+ private LocalizationService localizationService;
+
+ /**
+ * This currently only checks to make sure that user is allowed to view the
+ * storage area. If you create an action that requires more security then
+ * override this method.
+ *
+ * @param data
+ * Turbine information.
+ * @return True if the user is authorized to access the screen.
+ * @exception Exception,
+ * a generic exception.
+ */
+ /**
+ * This checks if the user has the role mapped in the flux.properties file for
+ * flux.admin.role which you should define
+ */
+ @Override
+ protected boolean isAuthorized(PipelineData data) throws Exception {
+ boolean isAuthorized = false;
+
+ /*
+ * Grab the Flux Admin role listed in the Flux.properties file that is included
+ * in the the standard TurbineResources.properties file.
+ */
+ String fluxAdminRole = Turbine.getConfiguration().getString("flux.admin.role");
+
+ // Get the Turbine ACL implementation
+ TurbineAccessControlList acl = getRunData(data).getACL();
+
+ if (acl == null || !(acl.hasRole(fluxAdminRole))) {
+ String msg = localizationService.getString(localizationService.getDefaultBundleName(),
+ localizationService.getLocale(((RunData) data).getRequest()), "no_permission");
+
+ getRunData(data).setMessage(msg);
+
+ getRunData(data).setScreenTemplate("Login.vm");
+ isAuthorized = false;
+ } else if (acl.hasRole(fluxAdminRole)) {
+ isAuthorized = true;
+ }
+
+ return isAuthorized;
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception,
+ * a generic exception.
+ */
+ public void doPerform(PipelineData data, Context context) throws Exception {
+ User user = getRunData(data).getUser();
+ context.put("user", user);
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxLogin.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxLogin.java
new file mode 100644
index 0000000..09cba49
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxLogin.java
@@ -0,0 +1,97 @@
+package ${package}.flux.modules.actions;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Login for Flux in stand-alone mode.
+ *
+ */
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.StringUtils;
+import org.apache.fulcrum.security.util.FulcrumSecurityException;
+import org.apache.fulcrum.security.util.UnknownEntityException;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+
+/**
+ * This is where we authenticate the user logging into the system against a user
+ * in the database. If the user exists in the database that users last login
+ * time will be updated.
+ *
+ * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
+ * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
+ * @author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+ * @version $Id: LoginUser.java 1725012 2017-11-16 11:38:47Z painter $
+ */
+public class FluxLogin extends org.apache.turbine.modules.actions.LoginUser {
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+ /**
+ * Checks for anonymous user, else calls parent method.
+ *
+ * @param pipelineData
+ * Turbine information.
+ * @exception FulcrumSecurityException
+ * could not get instance of the anonymous user
+ */
+ @Override
+ public void doPerform(PipelineData pipelineData) throws FulcrumSecurityException {
+
+ RunData data = getRunData(pipelineData);
+ String username = data.getParameters().getString(FluxLogin.CGI_USERNAME, "");
+
+ if (StringUtils.isEmpty(username)) {
+ return;
+ }
+
+ if (username.equals(security.getAnonymousUser().getName())) {
+ data.setMessage("Anonymous user cannot login");
+ reset(data);
+ return;
+ }
+
+ super.doPerform(pipelineData);
+ }
+
+ private void reset(RunData data) throws UnknownEntityException {
+ User anonymousUser = security.getAnonymousUser();
+ data.setUser(anonymousUser);
+
+ if (StringUtils.isNotEmpty(conf.getString(TurbineConstants.TEMPLATE_LOGIN, ""))) {
+ // We're running in a templating solution
+ data.setScreenTemplate(conf.getString(TurbineConstants.TEMPLATE_LOGIN));
+ } else {
+ data.setScreen(conf.getString(TurbineConstants.SCREEN_LOGIN));
+ }
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxLogout.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxLogout.java
new file mode 100644
index 0000000..a47af7c
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/FluxLogout.java
@@ -0,0 +1,107 @@
+package ${package}.flux.modules.actions;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.fulcrum.security.util.FulcrumSecurityException;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.Action;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+
+/**
+ * Removes the user from the session and sends them to the screen.homepage
+ * specified in the resources file
+ *
+ */
+public class FluxLogout extends Action {
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+ /**
+ * Clears the PipelineData user object back to an anonymous status not logged
+ * in, and with a null ACL. If the tr.props ACTION_LOGIN is anything except
+ * "LogoutUser", flow is transfered to the SCREEN_HOMEPAGE
+ *
+ * If this action name is the value of action.logout then we are being run
+ * before the session validator, so we don't need to set the screen (we assume
+ * that the session validator will handle that). This is basically still here
+ * simply to preserve old behaviour - it is recommended that action.logout is
+ * set to "LogoutUser" and that the session validator does handle setting the
+ * screen/template for a logged out (read not-logged-in) user.
+ *
+ * @param pipelineData
+ * Turbine information.
+ * @exception FulcrumSecurityException
+ * a problem occurred in the security service.
+ */
+ @Override
+ public void doPerform(PipelineData pipelineData) throws FulcrumSecurityException {
+
+ RunData data = getRunData(pipelineData);
+ // Session validator did not run, so RunData is not populated
+ User user = data.getUserFromSession();
+
+ if (user != null && !security.isAnonymousUser(user)) {
+ // Make sure that the user has really logged in...
+ if (!user.hasLoggedIn()) {
+ return;
+ }
+
+ user.setHasLoggedIn(Boolean.FALSE);
+ security.saveUser(user);
+ }
+
+ data.setMessage(conf.getString(TurbineConstants.LOGOUT_MESSAGE));
+
+ // This will cause the acl to be removed from the session in
+ // the Turbine servlet code.
+ data.setACL(null);
+
+ // Retrieve an anonymous user.
+ User anonymousUser = security.getAnonymousUser();
+ data.setUser(anonymousUser);
+ data.save();
+
+ // In the event that the current screen or related navigations
+ // require acl info, we cannot wait for Turbine to handle
+ // regenerating acl.
+ data.getSession().removeAttribute(TurbineConstants.ACL_SESSION_KEY);
+
+ // If this action name is the value of action.logout then we are
+ // being run before the session validator, so we don't need to
+ // set the screen (we assume that the session validator will handle
+ // that). This is basically still here simply to preserve old behavior
+ // - it is recommended that action.logout is set to "LogoutUser" and
+ // that the session validator does handle setting the screen/template
+ // for a logged out (read not-logged-in) user.
+ if (!conf.getString(TurbineConstants.ACTION_LOGOUT_KEY, TurbineConstants.ACTION_LOGOUT_DEFAULT)
+ .equals(TurbineConstants.ACTION_LOGOUT_DEFAULT)) {
+ data.setScreen(conf.getString(TurbineConstants.SCREEN_HOMEPAGE));
+ }
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/SecureAction.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/SecureAction.java
new file mode 100644
index 0000000..7e35060
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/SecureAction.java
@@ -0,0 +1,116 @@
+package ${package}.flux.modules.actions;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.fulcrum.localization.LocalizationService;
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.actions.VelocitySecureAction;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+/**
+ * Velocity Secure action.
+ *
+ * Always performs a Security Check that you've defined before executing the
+ * doPerform().
+ */
+public class SecureAction extends VelocitySecureAction {
+
+ @TurbineService
+ private LocalizationService localizationService;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+ @TurbineConfiguration(TurbineConstants.TEMPLATE_LOGIN)
+ private Configuration templateLogin;
+
+ @TurbineConfiguration(TurbineConstants.TEMPLATE_HOMEPAGE)
+ private Configuration templateHomepage;
+
+ /**
+ * This currently only checks to make sure that user is allowed to view the
+ * storage area. If you create an action that requires more security then
+ * override this method.
+ *
+ * @param data
+ * Turbine information.
+ * @return True if the user is authorized to access the screen.
+ * @exception Exception,
+ * a generic exception.
+ */
+ @Override
+ protected boolean isAuthorized(PipelineData pipelineData) throws Exception {
+
+ RunData data = getRunData(pipelineData);
+
+ boolean isAuthorized = false;
+
+ /*
+ * Grab the Flux Admin role listed in the Flux.properties file that is included
+ * in the the standard TurbineResources.properties file.
+ */
+ String fluxAdminRole = Turbine.getConfiguration().getString("flux.admin.role");
+
+ // Get the Turbine ACL implementation
+ TurbineAccessControlList acl = data.getACL();
+
+ if (acl == null) {
+ String msg = localizationService.getString(localizationService.getDefaultBundleName(),
+ localizationService.getLocale(((RunData) data).getRequest()), "no_permission");
+
+ data.setMessage(msg);
+
+ log.debug(
+ "call not permitted for template: " + data.getScreenTemplate() + " and action " + data.getAction());
+ data.setScreenTemplate((String) templateHomepage.getProperty(""));
+ isAuthorized = false;
+
+ } else if (acl.hasRole(fluxAdminRole)) {
+ isAuthorized = true;
+ } else {
+ data.setScreenTemplate((String) templateHomepage.getProperty(""));
+ data.setMessage("You do not have access to this part of the site.");
+ isAuthorized = false;
+ }
+ return isAuthorized;
+
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception,
+ * a generic exception.
+ */
+ public void doPerform(PipelineData data, Context context) throws Exception {
+ User user = getRunData(data).getUser();
+ context.put("user", user);
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/group/FluxGroupAction.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/group/FluxGroupAction.java
new file mode 100644
index 0000000..f04bfe0
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/group/FluxGroupAction.java
@@ -0,0 +1,171 @@
+package ${package}.flux.modules.actions.group;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.security.entity.Group;
+import org.apache.fulcrum.security.util.EntityExistsException;
+import org.apache.fulcrum.security.util.UnknownEntityException;
+import org.apache.fulcrum.yaafi.framework.util.StringUtils;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+import ${package}.flux.modules.actions.FluxAction;
+
+/**
+ * Action to manage groups in Turbine.
+ *
+ */
+public class FluxGroupAction extends FluxAction {
+
+ private static Log log = LogFactory.getLog(FluxGroupAction.class);
+ private static String GROUP_ID = "group";
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+ /**
+ * ActionEvent responsible for inserting a new user into the Turbine security
+ * system.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doInsert(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+
+ String name = data.getParameters().getString(GROUP_ID);
+ if (!StringUtils.isEmpty(name)) {
+
+ try {
+ // create the group
+ Group group = security.getGroupInstance();
+ group.setName(name);
+ security.addGroup(group);
+ } catch (EntityExistsException eee) {
+
+ context.put("name", name);
+ context.put("errorTemplate", "group,GroupAlreadyExists.vm");
+
+ /*
+ * We are still in insert mode. So keep this value alive.
+ */
+ data.getParameters().add("mode", "insert");
+ setTemplate(data, "group,GroupForm.vm");
+ } catch (Exception e) {
+ log.error("Something bad happened");
+ }
+ } else {
+ log.error("Cannot add empty group name");
+ }
+
+ }
+
+ /**
+ * Update a group name
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doUpdate(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+ String groupName = data.getParameters().getString("oldName");
+ if (!StringUtils.isEmpty(groupName)) {
+ Group group = security.getGroupByName(groupName);
+ String name = data.getParameters().getString(GROUP_ID);
+ if (group != null && !StringUtils.isEmpty(name)) {
+ try {
+ security.renameGroup(group, name);
+ } catch (UnknownEntityException uee) {
+ /*
+ * Should do something here but I still think we should use the an id so that
+ * this can't happen.
+ */
+ }
+ } else {
+ log.error("Cannot update group to empty name");
+ }
+ } else {
+ log.error("Cannot update group to empty name");
+ }
+ }
+
+ /**
+ * ActionEvent responsible for removing a user.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doDelete(PipelineData pipelineData, Context context) throws Exception {
+
+ RunData data = getRunData(pipelineData);
+
+ try {
+ Group group = security.getGroupByName(data.getParameters().getString(GROUP_ID));
+ if ( group != null ) {
+ security.removeGroup(group);
+ } else {
+ data.setMessage("Could not find group to remove");
+ }
+ } catch (UnknownEntityException uee) {
+ /*
+ * Should do something here but I still think we should use the an id so that
+ * this can't happen.
+ */
+ log.error(uee);
+ }
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doPerform(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+ log.info("Running do perform!");
+ data.setMessage("Can't find the requested action!");
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/permission/FluxPermissionAction.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/permission/FluxPermissionAction.java
new file mode 100644
index 0000000..d9ada4f
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/permission/FluxPermissionAction.java
@@ -0,0 +1,176 @@
+package ${package}.flux.modules.actions.permission;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.security.entity.Role;
+import org.apache.fulcrum.security.torque.om.TurbinePermission;
+import org.apache.fulcrum.security.torque.om.TurbinePermissionPeer;
+import org.apache.fulcrum.security.util.RoleSet;
+import org.apache.fulcrum.yaafi.framework.util.StringUtils;
+import org.apache.torque.criteria.Criteria;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+import ${package}.flux.modules.actions.FluxAction;
+
+/**
+ * Action to manage permissions in Turbine.
+ *
+ * @version $Id: FluxPermissionAction.java,v 1.11 2017/11/16 10:24:41 painter
+ * Exp $
+ */
+public class FluxPermissionAction extends FluxAction {
+ private static Log log = LogFactory.getLog(FluxPermissionAction.class);
+ private static String PERM_ID = "permission";
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+ /**
+ * ActionEvent responsible for inserting a new permission into the Turbine
+ * security system.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doInsert(PipelineData pipelineData, Context context) throws Exception {
+
+ RunData data = getRunData(pipelineData);
+ String name = data.getParameters().getString(PERM_ID);
+ if (!StringUtils.isEmpty(name)) {
+ // create the permission
+ TurbinePermission tp = new TurbinePermission();
+ tp.setName(name);
+ tp.setNew(true);
+ tp.save();
+ } else {
+ data.setMessage("Cannot add permission without a name");
+ data.getParameters().add("mode", "insert");
+ data.setScreen("permission,FluxPermissionForm.vm");
+ }
+
+ }
+
+ /**
+ * ActionEvent responsible updating a permission. Must check the input for
+ * integrity before allowing the user info to be update in the database.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doUpdate(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+
+ String old_name = data.getParameters().getString("oldName");
+ String name = data.getParameters().getString(PERM_ID);
+ if (!StringUtils.isEmpty(name)) {
+
+ /*
+ * broken Permission perm = security.getPermissionByName(old_name);
+ * security.renamePermission(perm, name);
+ */
+
+ // manual rename
+ Criteria criteria = new Criteria();
+ criteria.where(TurbinePermissionPeer.PERMISSION_NAME, old_name);
+ TurbinePermission tp = TurbinePermissionPeer.doSelectSingleRecord(criteria);
+ if (tp != null) {
+ tp.setName(name);
+ tp.save();
+ }
+
+ } else {
+ data.setMessage("Cannot find permission to update");
+ data.setScreen("permission,FluxPermissionList.vm");
+ }
+ }
+
+ /**
+ * ActionEvent responsible for removing a permission.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doDelete(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+
+ try {
+ String permName = data.getParameters().getString(PERM_ID);
+
+ if (!StringUtils.isEmpty(permName)) {
+ // just
+ org.apache.fulcrum.security.model.turbine.entity.TurbinePermission perm = security.<org.apache.fulcrum.security.model.turbine.entity.TurbinePermission>getPermissionByName(
+ permName);
+ // remove the role-permission links
+ RoleSet roles = perm.getRoles();
+ for (Role role : roles) {
+ security.revoke(role, perm);
+ }
+
+ // Remove the permission
+ security.removePermission(perm);
+
+ } else {
+ data.setMessage("Cannot find permission to delete");
+ data.setScreen("permission,FluxPermissionList.vm");
+ }
+ } catch (Exception e) {
+ data.setMessage("An error occured while trying to remove a permission");
+ }
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doPerform(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+ log.info("Running do perform!");
+ data.setMessage("Can't find the requested action!");
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/role/FluxRoleAction.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/role/FluxRoleAction.java
new file mode 100644
index 0000000..a29471e
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/role/FluxRoleAction.java
@@ -0,0 +1,234 @@
+package ${package}.flux.modules.actions.role;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.security.entity.Permission;
+import org.apache.fulcrum.security.entity.Role;
+import org.apache.fulcrum.security.model.turbine.entity.TurbineRole;
+import org.apache.fulcrum.security.torque.om.TurbineUserGroupRolePeer;
+import org.apache.fulcrum.security.util.EntityExistsException;
+import org.apache.fulcrum.security.util.PermissionSet;
+import org.apache.fulcrum.security.util.UnknownEntityException;
+import org.apache.fulcrum.yaafi.framework.util.StringUtils;
+import org.apache.torque.criteria.Criteria;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+import ${package}.flux.modules.actions.FluxAction;
+
+/**
+ * Action to manager roles in Turbine.
+ *
+ */
+public class FluxRoleAction extends FluxAction {
+
+ private static Log log = LogFactory.getLog(FluxRoleAction.class);
+ private static String ROLE_ID = "role";
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+ public void doInsert(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+ Role role = security.getRoleInstance();
+ data.getParameters().setProperties(role);
+
+ String name = data.getParameters().getString(ROLE_ID);
+ role.setName(name);
+
+ try {
+ security.addRole(role);
+ } catch (EntityExistsException eee) {
+ context.put("name", name);
+ context.put("errorTemplate", "role,FluxRoleAlreadyExists.vm");
+ context.put("role", role);
+ /*
+ * We are still in insert mode. So keep this value alive.
+ */
+ data.getParameters().add("mode", "insert");
+ setTemplate(data, "role,FluxRoleForm.vm");
+ }
+
+ }
+
+ /**
+ * ActionEvent responsible updating a role. Must check the input for integrity
+ * before allowing the user info to be update in the database.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doUpdate(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+ Role role = security.getRoleByName(data.getParameters().getString("oldName"));
+ String name = data.getParameters().getString(ROLE_ID);
+ if (role != null && !StringUtils.isEmpty(name)) {
+ try {
+ security.renameRole(role, name);
+ } catch (UnknownEntityException uee) {
+ log.error("Could not rename role: " + uee);
+ }
+ } else {
+ data.setMessage("Cannot update a role to an empty name");
+ log.error("Cannot update role to empty name");
+ }
+ }
+
+ /**
+ * ActionEvent responsible for removing a role.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doDelete(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+
+ try {
+ // find the role
+ Role role = security.getRoleByName(data.getParameters().getString(ROLE_ID));
+
+ if (role != null) {
+ // remove dependencies to users with the role
+ removeRoleFromAllUsers(role);
+
+ // remove all permissions
+ security.revokeAll(role);
+
+ // now remove the role
+ security.removeRole(role);
+ } else {
+ data.setMessage("Role was not found");
+ }
+ } catch (UnknownEntityException uee) {
+ /*
+ * Should do something here but I still think we should use the an id so that
+ * this can't happen.
+ */
+ log.error(uee);
+ } catch (Exception e) {
+ log.error("Could not remove role: " + e);
+ }
+ }
+
+ /**
+ * Update the roles that are to assigned to a user for a project.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doPermissions(PipelineData pipelineData, Context context) throws Exception {
+
+ RunData data = getRunData(pipelineData);
+ /*
+ * Grab the role we are trying to update. Always not null
+ */
+ TurbineRole role = security.<TurbineRole>getRoleByName(data.getParameters().getString(ROLE_ID));
+
+ /*
+ * Grab the permissions for the role we are dealing with.
+ */
+ PermissionSet rolePermissions = role.getPermissions();
+
+ /*
+ * Grab all the permissions.
+ */
+ PermissionSet permissions = security.getAllPermissions();
+
+ // id part one
+ String roleName = role.getName();
+ for (Iterator<Permission> iterator = permissions.iterator(); iterator.hasNext();) {
+ Permission permission = iterator.next();
+ String permissionName = permission.getName();
+ String rolePermission = roleName + permissionName;
+
+ String formRolePermission = data.getParameters().getString(rolePermission);
+ if (formRolePermission != null && !rolePermissions.contains(permission)) {
+ /*
+ * Checkbox has been checked AND the role doesn't already contain this
+ * permission. So assign the permission to the role.
+ */
+ log.debug("adding " + permissionName + " to " + roleName);
+ security.grant(role, permission);
+ // this might also be done with role.addPermission(permission);
+ } else if (formRolePermission == null && rolePermissions.contains(permission)) {
+ /*
+ * Checkbox has not been checked AND the role contains this permission. So
+ * remove this permission from the role.
+ */
+ log.debug("removing " + permissionName + " from " + roleName);
+ security.revoke(role, permission);
+ // this might also be done with role.removePermission(permission);
+ }
+
+ }
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception
+ * a generic exception.
+ */
+ public void doPerform(PipelineData pipelineData, Context context) throws Exception {
+ log.info("Running do perform!");
+ getRunData(pipelineData).setMessage("Can't find the requested action!");
+ }
+
+ /**
+ * Helper method for removing roles, must clear associated users with the role
+ */
+ private void removeRoleFromAllUsers(Role role) {
+ try {
+ Criteria criteria = new Criteria();
+ criteria.where(TurbineUserGroupRolePeer.ROLE_ID, role.getId());
+ TurbineUserGroupRolePeer.doDelete(criteria);
+ } catch (Exception e) {
+ log.error("Error removing user, role associations: " + e.toString());
+ }
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/user/FluxUserAction.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/user/FluxUserAction.java
new file mode 100644
index 0000000..6252f9e
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/actions/user/FluxUserAction.java
@@ -0,0 +1,261 @@
+package ${package}.flux.modules.actions.user;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.security.entity.Group;
+import org.apache.fulcrum.security.entity.Role;
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.fulcrum.security.util.GroupSet;
+import org.apache.fulcrum.security.util.RoleSet;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+import ${package}.flux.modules.actions.FluxAction;
+
+/**
+ * Change Password action.
+ *
+ */
+public class FluxUserAction extends FluxAction {
+ private static Log log = LogFactory.getLog(FluxUserAction.class);
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /**
+ * ActionEvent responsible for inserting a new user into the Turbine security
+ * system.
+ */
+ public void doInsert(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+
+ /*
+ * Grab the username entered in the form.
+ */
+ String username = data.getParameters().getString("username");
+ String password = data.getParameters().getString("password");
+
+ if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
+ /*
+ * Make sure this account doesn't already exist. If the account already exists
+ * then alert the user and make them change the username.
+ */
+ if (security.accountExists(username)) {
+ context.put("username", username);
+ context.put("errorTemplate", "user,FluxUserAlreadyExists.vm");
+
+ data.setMessage("The user already exists");
+ data.getParameters().add("mode", "insert");
+ data.setScreen("user,FluxUserForm.vm");
+ return;
+ } else {
+
+ try {
+ /*
+ * Create a new user modeled directly from the SecurityServiceTest method
+ */
+ User user = security.getUserInstance(username);
+ data.getParameters().setProperties(user);
+ security.addUser(user, password);
+
+ // Use security to force the password
+ security.forcePassword(user, password);
+
+ } catch (Exception e) {
+ log.error("Error adding new user: " + e);
+
+ context.put("username", username);
+ context.put("errorTemplate", "user,FluxUserAlreadyExists.vm");
+
+ data.setMessage("Could not add the user");
+ data.getParameters().add("mode", "insert");
+ data.setScreen("user,FluxUserForm.vm");
+ return;
+ }
+ }
+
+ } else {
+ String msg = "Cannot add user without username or password";
+ log.error(msg);
+ data.setMessage(msg);
+ data.getParameters().add("mode", "insert");
+ data.setScreen("user,FluxUserForm.vm");
+ }
+ }
+
+ /**
+ * ActionEvent responsible updating a user. Must check the input for integrity
+ * before allowing the user info to be update in the database.
+ */
+ public void doUpdate(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+ String username = data.getParameters().getString("username");
+ if (!StringUtils.isEmpty(username)) {
+ if (security.accountExists(username)) {
+
+ // This wrapped user does work for change password though... see below
+ User user = security.getUser(username);
+ if (user != null) {
+
+ // update all properties from form
+ data.getParameters().setProperties(user);
+
+ // save the changes to the user account
+ security.saveUser(user);
+
+ // get the new password from form submit
+ String password = data.getParameters().getString("password");
+
+ // Only update if we received a new (non-empty) password
+ if (!StringUtils.isEmpty(password)) {
+
+ // Change user password
+ security.changePassword(user, user.getPassword(), password);
+
+ // this still works
+ security.forcePassword(user, password);
+ } else {
+ data.setMessage("Cannot provide an empty password");
+ return;
+ }
+
+ }
+
+ } else {
+ log.error("User does not exist!");
+ }
+ }
+ }
+
+ /**
+ * ActionEvent responsible for removing a user from the Tambora system.
+ */
+ public void doDelete(PipelineData pipelineData, Context context) throws Exception {
+
+ try {
+ RunData data = getRunData(pipelineData);
+ String username = data.getParameters().getString("username");
+ if (!StringUtils.isEmpty(username)) {
+ if (security.accountExists(username)) {
+
+ // find the user object and remove using security mgr
+ User user = security.getUser(username);
+ security.removeUser(user);
+
+ } else {
+ log.error("User does not exist!");
+ data.setMessage("User not found!");
+ }
+ }
+ } catch (Exception e) {
+ log.error("Could not remove user: " + e);
+ }
+ }
+
+ /**
+ * Update the roles that are to assigned to a user for a project.
+ */
+ public void doRoles(PipelineData pipelineData, Context context) throws Exception {
+ RunData data = getRunData(pipelineData);
+
+ try {
+ /*
+ * Get the user we are trying to update. The username has been hidden in the
+ * form so we will grab the hidden username and use that to retrieve the user.
+ */
+ String username = data.getParameters().getString("username");
+ if (!StringUtils.isEmpty(username)) {
+ if (security.accountExists(username)) {
+ User user = security.getUser(username);
+
+ // Get the Turbine ACL implementation
+ TurbineAccessControlList acl = security.getUserManager().getACL(user);
+
+ /*
+ * Grab all the Groups and Roles in the system.
+ */
+ GroupSet groups = security.getAllGroups();
+ RoleSet roles = security.getAllRoles();
+
+ for (Group group : groups) {
+ String groupName = group.getName();
+ for (Role role : roles) {
+ String roleName = role.getName();
+
+ /*
+ * In the UserRoleForm.vm we made a checkbox for every possible Group/Role
+ * combination so we will compare every possible combination with the values
+ * that were checked off in the form. If we have a match then we will grant the
+ * user the role in the group.
+ */
+ String groupRole = groupName + roleName;
+ String formGroupRole = data.getParameters().getString(groupRole);
+ boolean addGroupRole = false;
+
+ // signal to add group
+ if (!StringUtils.isEmpty(formGroupRole))
+ addGroupRole = true;
+
+ if (addGroupRole) {
+ // only add if new
+ if (!acl.hasRole(role, group)) {
+ security.grant(user, group, role);
+ }
+
+ } else {
+
+ // only remove if it was previously assigned
+ if (acl.hasRole(role, group)) {
+
+ // revoke the role for this user
+ acl.getRoles(group).remove(role);
+
+ // revoke the user/group/role entry
+ security.revoke(user, group, role);
+ }
+ }
+
+ }
+ }
+
+ } else {
+ log.error("User does not exist!");
+ }
+ }
+
+ } catch (Exception e) {
+ log.error("Error on role assignment: " + e);
+ }
+ }
+
+ /**
+ * Implement this to add information to the context.
+ */
+ public void doPerform(PipelineData pipelineData, Context context) throws Exception {
+ log.info("Running do perform!");
+ getRunData(pipelineData).setMessage("Can't find the requested action!");
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxError.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxError.java
new file mode 100644
index 0000000..dca782d
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxError.java
@@ -0,0 +1,27 @@
+package ${package}.flux.modules.screens;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.turbine.modules.screens.VelocityErrorScreen;
+
+/**
+ * Base screen for secure web acces to the storage side of Tambora.
+ *
+ */
+public class FluxError extends VelocityErrorScreen
+{
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxIndex.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxIndex.java
new file mode 100644
index 0000000..115252c
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxIndex.java
@@ -0,0 +1,92 @@
+package ${package}.flux.modules.screens;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.screens.VelocitySecureScreen;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+/**
+ * Base screen for secure web access to the Flux user manager
+ *
+ */
+public class FluxIndex extends VelocitySecureScreen {
+
+ @TurbineService
+ protected SecurityService securityService;
+
+ @TurbineConfiguration(TurbineConstants.TEMPLATE_LOGIN)
+ private Configuration templateLogin;
+
+ @TurbineConfiguration(TurbineConstants.TEMPLATE_HOMEPAGE)
+ private Configuration templateHomepage;
+
+ /**
+ * This method is called by the Turbine framework when the associated Velocity
+ * template, Index.vm is requested
+ *
+ * @param data
+ * the Turbine request data
+ * @param context
+ * the Velocity context
+ * @throws Exception
+ * a generic Exception
+ */
+ @Override
+ protected void doBuildTemplate(PipelineData data, Context context) throws Exception {
+ }
+
+ @Override
+ protected boolean isAuthorized(PipelineData pipelineData) throws Exception {
+
+ RunData data = getRunData(pipelineData);
+
+ boolean isAuthorized = false;
+
+ /*
+ * Grab the Flux Admin role listed in the Flux.properties file that is included
+ * in the the standard TurbineResources.properties file.
+ */
+ String fluxAdminRole = Turbine.getConfiguration().getString("flux.admin.role");
+
+ // Get the Turbine ACL implementation
+ TurbineAccessControlList acl = data.getACL();
+
+ if (acl == null) {
+ // commons configuration getProperty: prefix removed, the key for the value ..
+ // is an empty string, the result an object
+ data.setScreenTemplate((String) templateLogin.getProperty(""));
+ isAuthorized = false;
+ } else if (acl.hasRole(fluxAdminRole)) {
+ isAuthorized = true;
+ } else {
+ data.setScreenTemplate((String) templateHomepage.getProperty(""));
+ data.setMessage("You do not have access to this part of the site.");
+ isAuthorized = false;
+ }
+ return isAuthorized;
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxScreen.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxScreen.java
new file mode 100644
index 0000000..772eaeb
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/FluxScreen.java
@@ -0,0 +1,94 @@
+package ${package}.flux.modules.screens;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.screens.VelocitySecureScreen;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.velocity.context.Context;
+
+/**
+ * Base screen for secure web acces to the storage side of Tambora.
+ *
+ */
+public abstract class FluxScreen extends VelocitySecureScreen {
+
+ @TurbineService
+ protected SecurityService securityService;
+
+ @TurbineConfiguration(TurbineConstants.TEMPLATE_LOGIN)
+ private Configuration templateLogin;
+
+ @TurbineConfiguration(TurbineConstants.TEMPLATE_HOMEPAGE)
+ private Configuration templateHomepage;
+
+ /**
+ * This method is called by Turbine
+ */
+ @Override
+ protected void doBuildTemplate(PipelineData data, Context context) throws Exception {
+
+ /*
+ * Check to see if the embedded menu should be displayed in the templates.
+ */
+ if (Turbine.getConfiguration().getBoolean("flux.embedded.show.menu", false)) {
+ context.put("showEmbeddedMenu", true);
+ }
+
+ /*
+ * Check to see if we will display the finders on the forms used in Flux.
+ */
+ if (Turbine.getConfiguration().getBoolean("flux.ui.show.finder", false)) {
+ context.put("showFinder", true);
+ }
+
+ }
+
+ @Override
+ protected boolean isAuthorized(PipelineData data) throws Exception {
+ boolean isAuthorized = false;
+
+ /*
+ * Grab the Flux Admin role listed in the Flux.properties file that is included
+ * in the the standard TurbineResources.properties file.
+ */
+ String fluxAdminRole = Turbine.getConfiguration().getString("flux.admin.role");
+
+ // Get the Turbine ACL implementation
+ TurbineAccessControlList acl = getRunData(data).getACL();
+
+ if (acl == null) {
+ // commons configuration getProperty: prefix removed, the key for the value ..
+ // is an empty string, the result an object
+ getRunData(data).setScreenTemplate((String) templateLogin.getProperty(""));
+ isAuthorized = false;
+ } else if (acl.hasRole(fluxAdminRole)) {
+ isAuthorized = true;
+ } else {
+ getRunData(data).setScreenTemplate((String) templateHomepage.getProperty(""));
+ getRunData(data).setMessage("You do not have access to this part of the site.");
+ isAuthorized = false;
+ }
+ return isAuthorized;
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/group/Default.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/group/Default.java
new file mode 100644
index 0000000..5360e93
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/group/Default.java
@@ -0,0 +1,25 @@
+package ${package}.flux.modules.screens.group;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import ${package}.flux.modules.screens.FluxScreen;
+
+/**
+ */
+public class Default extends FluxScreen
+{
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/permission/Default.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/permission/Default.java
new file mode 100644
index 0000000..4d27c70
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/permission/Default.java
@@ -0,0 +1,25 @@
+package ${package}.flux.modules.screens.permission;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import ${package}.flux.modules.screens.FluxScreen;
+
+/**
+ */
+public class Default extends FluxScreen
+{
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/role/Default.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/role/Default.java
new file mode 100644
index 0000000..d4d8962
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/role/Default.java
@@ -0,0 +1,25 @@
+package ${package}.flux.modules.screens.role;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import ${package}.flux.modules.screens.FluxScreen;
+
+/**
+ */
+public class Default extends FluxScreen
+{
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/user/Default.java b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/user/Default.java
new file mode 100644
index 0000000..436ff17
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/modules/screens/user/Default.java
@@ -0,0 +1,25 @@
+package ${package}.flux.modules.screens.user;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import ${package}.flux.modules.screens.FluxScreen;
+
+/**
+ */
+public class Default extends FluxScreen
+{
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/flux/tools/FluxTool.java b/src/main/resources/archetype-resources/src/main/java/flux/tools/FluxTool.java
new file mode 100644
index 0000000..16b7778
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/flux/tools/FluxTool.java
@@ -0,0 +1,297 @@
+package ${package}.flux.tools;
+
+/*
+ * Copyright 2001-2018 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.pool.Recyclable;
+import org.apache.fulcrum.security.acl.AccessControlList;
+import org.apache.fulcrum.security.entity.Group;
+import org.apache.fulcrum.security.entity.Permission;
+import org.apache.fulcrum.security.entity.Role;
+import org.apache.fulcrum.security.torque.om.TurbinePermission;
+import org.apache.fulcrum.security.torque.om.TurbinePermissionPeer;
+import org.apache.fulcrum.security.torque.om.TurbineRolePermissionPeer;
+import org.apache.fulcrum.security.torque.om.TurbineUserPeer;
+import org.apache.fulcrum.security.util.GroupSet;
+import org.apache.fulcrum.security.util.RoleSet;
+import org.apache.torque.criteria.Criteria;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.services.pull.ApplicationTool;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+import org.apache.turbine.util.template.SelectorBox;
+
+/**
+ * The pull api for flux templates
+ *
+ * @version $Id: FluxTool.java,v 1.13 2018/04/02 13:24:41 painter Exp $
+ */
+public class FluxTool implements ApplicationTool, Recyclable {
+
+ /** Used for logging */
+ protected static final Log log = LogFactory.getLog(FluxTool.class);
+
+ /** The object containing request specific data */
+ private RunData data;
+
+ /** A Group object for use within the Flux API. */
+ private Group group = null;
+
+ /** A Issue object for use within the Flux API. */
+ private Role role = null;
+
+ /** A Permission object for use within the Flux API. */
+ private Permission permission = null;
+
+ /** A User object for use within the Flux API. */
+ private User user = null;
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+ /**
+ * Constructor
+ */
+ public FluxTool() {
+ }
+
+ /**
+ * Prepares flux tool for a single request
+ */
+ @Override
+ public void init(Object runData) {
+ this.data = (RunData) runData;
+ }
+
+ public Group getGroup() throws Exception {
+ String groupName = data.getParameters().getString("group");
+ if (StringUtils.isEmpty(groupName)) {
+ group = security.getGroupInstance();
+ } else {
+ group = security.getGroupByName(groupName);
+ }
+ return group;
+ }
+
+ public String getMode() {
+ return data.getParameters().getString("mode");
+ }
+
+ public GroupSet getGroups() throws Exception {
+ return security.getAllGroups();
+ }
+
+ public Role getRole() throws Exception {
+ String roleName = data.getParameters().getString("role");
+ if (StringUtils.isEmpty(roleName)) {
+ role = security.getRoleInstance();
+ } else {
+ role = security.getRoleByName(roleName);
+ }
+ return role;
+ }
+
+ /**
+ */
+ public RoleSet getRoles() throws Exception {
+ return security.getAllRoles();
+ }
+
+ public TurbinePermission getPermission() throws Exception {
+
+ // make sure that the get permission returns the one linked to the role
+ String permissionName = data.getParameters().getString("permission");
+ if (StringUtils.isEmpty(permissionName)) {
+ return null;
+ } else {
+ try {
+ Criteria criteria = new Criteria();
+ criteria.where(TurbinePermissionPeer.PERMISSION_NAME, permissionName);
+ return TurbinePermissionPeer.doSelectSingleRecord(criteria);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Get last cached role - useful after calling getPermissions()
+ *
+ * @return
+ */
+ public Role getCachedRole() {
+ return role;
+ }
+
+ /**
+ * Return all permissions for a role
+ */
+ public List<TurbinePermission> getRolePermissions() throws Exception {
+
+ String roleName = data.getParameters().getString("role");
+ if (StringUtils.isEmpty(roleName)) {
+ role = security.getRoleInstance();
+ } else {
+ role = security.getRoleByName(roleName);
+ }
+
+ if (role != null) {
+ try {
+ Criteria criteria = new Criteria();
+ criteria.where(TurbineRolePermissionPeer.ROLE_ID, role.getId());
+ criteria.addJoin(TurbineRolePermissionPeer.PERMISSION_ID, TurbinePermissionPeer.PERMISSION_ID);
+ criteria.addAscendingOrderByColumn(TurbinePermissionPeer.PERMISSION_NAME);
+ return TurbinePermissionPeer.doSelect(criteria);
+ } catch (Exception e) {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Return all permissions
+ */
+ public List<TurbinePermission> getPermissions() throws Exception {
+
+ try {
+ Criteria criteria = new Criteria();
+ criteria.addAscendingOrderByColumn(TurbinePermissionPeer.PERMISSION_NAME);
+ return TurbinePermissionPeer.doSelect(criteria);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public User getUser() throws Exception {
+ String name = data.getParameters().getString("username");
+ if (StringUtils.isEmpty(name)) {
+ user = security.getUserInstance();
+ } else {
+ user = security.getUser(name);
+ }
+ return user;
+ }
+
+ public AccessControlList getACL() throws Exception {
+ // Get the Turbine ACL implementation
+ return security.getUserManager().getACL(getUser());
+ }
+
+ /**
+ */
+ public SelectorBox getFieldList() throws Exception {
+ Object[] names = { "username", "firstname", "middlename", "lastname" };
+ Object[] values = { "Username", "First Name", "Middle Name", "Last Name" };
+ return new SelectorBox("fieldList", names, values);
+ }
+
+ /**
+ * This is a tie to the DB implementation something should be added the
+ * pluggable pieces to allow decent parameterized searching.
+ */
+ public SelectorBox getUserFieldList() throws Exception {
+
+ Object[] names = { TurbineUserPeer.LOGIN_NAME, TurbineUserPeer.FIRST_NAME, TurbineUserPeer.LAST_NAME };
+ Object[] values = { "User Name", "First Name", "Last Name" };
+
+ return new SelectorBox("fieldList", names, values);
+ }
+
+ /**
+ * Select all the users and place them in an array that can be used within the
+ * UserList.vm template.
+ */
+ public List<User> getUsers() {
+ try {
+ Criteria criteria = new Criteria();
+ String fieldList = data.getParameters().getString("fieldList");
+
+ if (fieldList != null) {
+ // This is completely database centric.
+ String searchField = data.getParameters().getString("searchField");
+ criteria.where(fieldList, searchField, Criteria.LIKE);
+ }
+
+ return (List<User>) security.getUserManager().retrieveList(criteria);
+ } catch (Exception e) {
+ log.error("Could not retrieve user list: " + e.toString());
+ return null;
+ }
+ }
+
+ /**
+ * Implementation of ApplicationTool interface is not needed for this tool as it
+ * is request scoped
+ */
+ @Override
+ public void refresh() {
+ // empty
+ }
+
+ // ****************** Recyclable implementation ************************
+ private boolean disposed;
+
+ /**
+ * Recycles the object for a new client. Recycle methods with parameters must be
+ * added to implementing object and they will be automatically called by pool
+ * implementations when the object is taken from the pool for a new client. The
+ * parameters must correspond to the parameters of the constructors of the
+ * object. For new objects, constructors can call their corresponding recycle
+ * methods whenever applicable. The recycle methods must call their super.
+ */
+ @Override
+ public void recycle() {
+ disposed = false;
+ }
+
+ /**
+ * Disposes the object after use. The method is called when the object is
+ * returned to its pool. The dispose method must call its super.
+ */
+ @Override
+ public void dispose() {
+ group = null;
+ role = null;
+ permission = null;
+ user = null;
+ disposed = true;
+ }
+
+ /**
+ * Checks whether the recyclable has been disposed.
+ *
+ * @return true, if the recyclable is disposed.
+ */
+ @Override
+ public boolean isDisposed() {
+ return disposed;
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/ChangePasswordAction.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/ChangePasswordAction.java
new file mode 100644
index 0000000..ca7255b
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/ChangePasswordAction.java
@@ -0,0 +1,95 @@
+package ${package}.modules.actions;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+
+import org.apache.fulcrum.security.util.PasswordMismatchException;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+/**
+ * Change Password action.
+ *
+ */
+public class ChangePasswordAction extends SecureAction
+
+{
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception,
+ * a generic exception.
+ */
+ @Override
+ public void doPerform(PipelineData data)
+ throws Exception
+ {
+
+ User user = getRunData(data).getUser();
+
+ RunData rundata = getRunData(data);
+ String oldPassword = rundata.getParameters().getString("oldpassword", "");
+ String newPassword = rundata.getParameters().getString("newpassword", "");
+
+ try {
+ security.changePassword(user, oldPassword, newPassword);
+ rundata.setMessage("Password changed!");
+ }
+ catch (PasswordMismatchException e)
+ {
+ rundata.setMessage(e.getMessage());
+ rundata.setScreenTemplate("Password.vm");
+ }
+
+
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception,
+ * a generic exception.
+ */
+ @Override
+ public void doPerform(PipelineData data, Context context) throws Exception
+ {
+
+ context.put("success", "Password changed!!");
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUser.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUser.java
new file mode 100644
index 0000000..3018954
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUser.java
@@ -0,0 +1,114 @@
+package ${package}.modules.actions;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.security.util.FulcrumSecurityException;
+import org.apache.fulcrum.security.util.UnknownEntityException;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+
+/**
+ * This is where we authenticate the user logging into the system
+ * against a user in the database. If the user exists in the database
+ * that users last login time will be updated.
+ *
+ * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
+ * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
+ * @version $Id: LoginUser.java 1725011 2016-01-16 17:38:47Z tv $
+ */
+public class LoginUser
+ extends org.apache.turbine.modules.actions.LoginUser
+{
+
+ /** Logging */
+ private static Log log = LogFactory.getLog(LoginUser.class);
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+
+
+ /**
+ * Checks for anonymous user, else calls parent method.
+ *
+ * @param pipelineData Turbine information.
+ * @exception FulcrumSecurityException could not get instance of the
+ * anonymous user
+ */
+ @Override
+ public void doPerform(PipelineData pipelineData)
+ throws FulcrumSecurityException
+ {
+ RunData data = getRunData(pipelineData);
+ String username = data.getParameters().getString(LoginUser.CGI_USERNAME, "");
+
+ if (StringUtils.isEmpty(username))
+ {
+ return;
+ }
+
+ if (username.equals(security.getAnonymousUser().getName()))
+ {
+ data.setMessage("Anonymous user cannot login");
+ reset(data);
+ return;
+ }
+
+ super.doPerform(pipelineData);
+
+ }
+
+
+
+ private void reset(RunData data) throws UnknownEntityException {
+ User anonymousUser = security.getAnonymousUser();
+ data.setUser(anonymousUser);
+
+ if (StringUtils.isNotEmpty(conf.getString(TurbineConstants.TEMPLATE_LOGIN,"")))
+ {
+ // We're running in a templating solution
+ data.setScreenTemplate(
+ conf.getString(TurbineConstants.TEMPLATE_LOGIN));
+ }
+ else
+ {
+ data.setScreen(
+ conf.getString(TurbineConstants.SCREEN_LOGIN));
+ }
+ }
+
+}
+
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUserIntake.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUserIntake.java
new file mode 100644
index 0000000..4dca1f0
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUserIntake.java
@@ -0,0 +1,186 @@
+package ${package}.modules.actions;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.pool.PoolService;
+import org.apache.fulcrum.security.util.DataBackendException;
+import org.apache.fulcrum.security.util.FulcrumSecurityException;
+import org.apache.fulcrum.security.util.UnknownEntityException;
+import org.apache.fulcrum.intake.model.Group;
+import org.apache.fulcrum.intake.IntakeException;
+import org.apache.turbine.services.TurbineServices;
+import org.apache.turbine.services.intake.IntakeTool;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.modules.Action;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+
+/**
+ * This is where we authenticate the user logging into the system
+ * against a user in the database. If the user exists in the database
+ * that users last login time will be updated.
+ *
+ * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
+ * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
+ * @version $Id$
+ */
+public class LoginUserIntake
+ extends org.apache.turbine.modules.actions.LoginUser
+{
+
+ /** Logging */
+ private static Log log = LogFactory.getLog(LoginUserIntake.class);
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+
+
+ /**
+ * Checks for anonymous user, else calls parent method.
+ *
+ * @param pipelineData Turbine information.
+ * @exception FulcrumSecurityException could not get instance of the
+ * anonymous user
+ */
+ @Override
+ public void doPerform(PipelineData pipelineData)
+ throws FulcrumSecurityException
+ {
+ RunData data = getRunData(pipelineData);
+
+ try
+ {
+ // Get intake group
+ // context only available after ExecutePageValve, could not invoke (IntakeTool)context.get("intake") using pook service instead
+ PoolService poolService = (PoolService)TurbineServices.getInstance().getService(PoolService.ROLE);
+ IntakeTool intake = (IntakeTool) poolService.getInstance(IntakeTool.class);
+
+ intake.init(data);
+ Group group = intake.get("Login", IntakeTool.DEFAULT_KEY);
+ String username = (String)group.get("Username").getValue();
+ if (StringUtils.isEmpty(username))
+ {
+ return;
+ }
+
+ if (username.equals(security.getAnonymousUser().getName()))
+ {
+ data.setMessage("Anonymous user cannot login");
+ reset(data);
+ return;
+ }
+
+ if (username.equals(security.getAnonymousUser().getName()))
+ {
+ throw new Exception("Anonymous user cannot login");
+ }
+
+ String password = (String)group.get("Password").getValue();
+ // Authenticate the user and get the object.
+ User user = security.getAuthenticatedUser(username, password);
+
+ // Store the user object.
+ data.setUser(user);
+
+ // Mark the user as being logged in.
+ user.setHasLoggedIn(Boolean.TRUE);
+
+ // Set the last_login date in the database.
+ user.updateLastLogin();
+
+ // This only happens if the user is valid; otherwise, we
+ // will get a valueBound in the User object when we don't
+ // want to because the username is not set yet. Save the
+ // User object into the session.
+ data.save();
+
+ /*
+ * If the setPage("template.vm") method has not
+ * been used in the template to authenticate the
+ * user (usually Login.vm), then the user will
+ * be forwarded to the template that is specified
+ * by the "template.home" property as listed in
+ * TR.props for the webapp.
+ */
+
+ }
+ catch (Exception e)
+ {
+ if (e instanceof DataBackendException || e instanceof IntakeException)
+ {
+ log.error(e);
+ }
+
+ // Set Error Message and clean out the user.
+ data.setMessage(conf.getString(TurbineConstants.LOGIN_ERROR, ""));
+ User anonymousUser = security.getAnonymousUser();
+ data.setUser(anonymousUser);
+
+ String loginTemplate = conf.getString(
+ TurbineConstants.TEMPLATE_LOGIN);
+
+ if (StringUtils.isNotEmpty(loginTemplate))
+ {
+ // We're running in a templating solution
+ data.setScreenTemplate(loginTemplate);
+ }
+ else
+ {
+ data.setScreen(conf.getString(TurbineConstants.SCREEN_LOGIN));
+ }
+ }
+ }
+
+ private void reset(RunData data) throws UnknownEntityException {
+ User anonymousUser = security.getAnonymousUser();
+ data.setUser(anonymousUser);
+
+ if (StringUtils.isNotEmpty(conf.getString(TurbineConstants.TEMPLATE_LOGIN,"")))
+ {
+ // We're running in a templating solution
+ data.setScreenTemplate(
+ conf.getString(TurbineConstants.TEMPLATE_LOGIN));
+ }
+ else
+ {
+ data.setScreen(
+ conf.getString(TurbineConstants.SCREEN_LOGIN));
+ }
+ }
+
+}
+
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/LogoutUser.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/LogoutUser.java
new file mode 100644
index 0000000..2fea6dd
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/LogoutUser.java
@@ -0,0 +1,121 @@
+package ${package}.modules.actions;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.fulcrum.security.util.FulcrumSecurityException;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.Action;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+
+/**
+ * This action removes a user from the session. It makes sure to save
+ * the User object in the session.
+ *
+ * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
+ * @version $Id: LogoutUser.java 1706239 2015-10-01 13:18:35Z tv $
+ */
+public class LogoutUser
+ extends Action
+{
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+ /**
+ * Clears the PipelineData user object back to an anonymous status not
+ * logged in, and with a null ACL. If the tr.props ACTION_LOGIN
+ * is anything except "LogoutUser", flow is transfered to the
+ * SCREEN_HOMEPAGE
+ *
+ * If this action name is the value of action.logout then we are
+ * being run before the session validator, so we don't need to
+ * set the screen (we assume that the session validator will handle
+ * that). This is basically still here simply to preserve old behaviour
+ * - it is recommended that action.logout is set to "LogoutUser" and
+ * that the session validator does handle setting the screen/template
+ * for a logged out (read not-logged-in) user.
+ *
+ * @param pipelineData Turbine information.
+ * @exception FulcrumSecurityException a problem occurred in the security
+ * service.
+ */
+ @Override
+ public void doPerform(PipelineData pipelineData)
+ throws FulcrumSecurityException
+ {
+ RunData data = getRunData(pipelineData);
+ // Session validator did not run, so RunData is not populated
+ User user = data.getUserFromSession();
+
+ if (user != null && !security.isAnonymousUser(user))
+ {
+ // Make sure that the user has really logged in...
+ if (!user.hasLoggedIn())
+ {
+ return;
+ }
+
+ user.setHasLoggedIn(Boolean.FALSE);
+ security.saveUser(user);
+ }
+
+ data.setMessage(conf.getString(TurbineConstants.LOGOUT_MESSAGE));
+
+ // This will cause the acl to be removed from the session in
+ // the Turbine servlet code.
+ data.setACL(null);
+
+ // Retrieve an anonymous user.
+ User anonymousUser = security.getAnonymousUser();
+ data.setUser(anonymousUser);
+ data.save();
+
+ // In the event that the current screen or related navigations
+ // require acl info, we cannot wait for Turbine to handle
+ // regenerating acl.
+ data.getSession().removeAttribute(TurbineConstants.ACL_SESSION_KEY);
+
+ // If this action name is the value of action.logout then we are
+ // being run before the session validator, so we don't need to
+ // set the screen (we assume that the session validator will handle
+ // that). This is basically still here simply to preserve old behavior
+ // - it is recommended that action.logout is set to "LogoutUser" and
+ // that the session validator does handle setting the screen/template
+ // for a logged out (read not-logged-in) user.
+ if (!conf.getString(TurbineConstants.ACTION_LOGOUT_KEY,
+ TurbineConstants.ACTION_LOGOUT_DEFAULT)
+ .equals(TurbineConstants.ACTION_LOGOUT_DEFAULT))
+ {
+ data.setScreen(conf.getString(TurbineConstants.SCREEN_HOMEPAGE));
+ }
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/SecureAction.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/SecureAction.java
new file mode 100644
index 0000000..c25fae5
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/SecureAction.java
@@ -0,0 +1,98 @@
+package ${package}.modules.actions;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+import org.apache.fulcrum.localization.LocalizationService;
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.actions.VelocitySecureAction;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+/**
+ * Velocity Secure action.
+ *
+ * Always performs a Security Check that you've defined before executing the
+ * doPerform().
+ */
+public class SecureAction extends VelocitySecureAction
+{
+
+ @TurbineService
+ private LocalizationService localizationService;
+ /**
+ * This currently only checks to make sure that user is allowed to view the
+ * storage area. If you create an action that requires more security then
+ * override this method.
+ *
+ * @param data
+ * Turbine information.
+ * @return True if the user is authorized to access the screen.
+ * @exception Exception,
+ * a generic exception.
+ */
+ @Override
+ protected boolean isAuthorized(PipelineData data) throws Exception
+ {
+ boolean isAuthorized = false;
+
+ // Who is our current user?
+ User user = getRunData(data).getUser();
+
+ // Get the Turbine ACL implementation
+ TurbineAccessControlList acl = getRunData(data).getACL();
+
+ if (acl == null || ! ( acl.hasRole("turbineuser") || acl.hasRole("turbineadmin") ) )
+ {
+ String msg = localizationService.getString(localizationService.getDefaultBundleName(),
+ localizationService.getLocale( ((RunData) data).getRequest()), "no_permission");
+
+ getRunData(data).setMessage(msg);
+
+ log.debug( "call not permitted for template: " + getRunData(data).getScreenTemplate() + " and action " + getRunData(data).getAction() );
+ getRunData(data).setScreenTemplate( "Login.vm" );
+ isAuthorized = false;
+ }
+ else if ( acl.hasRole("turbineuser") || acl.hasRole("turbineadmin") )
+ {
+ isAuthorized = true;
+ }
+
+ return isAuthorized;
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception,
+ * a generic exception.
+ */
+ public void doPerform(PipelineData data, Context context) throws Exception
+ {
+ User user = getRunData(data).getUser();
+ context.put("user",user);
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/ShowRecords.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/ShowRecords.java
new file mode 100644
index 0000000..0ec8a8f
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/ShowRecords.java
@@ -0,0 +1,48 @@
+package ${package}.modules.actions;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+import java.util.List;
+
+import org.apache.torque.criteria.Criteria;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+import ${package}.om.Author;
+import ${package}.om.AuthorPeer;
+
+public class ShowRecords extends SecureAction
+{
+
+ @Override
+ public void doPerform( PipelineData pipelineData, Context context )
+ throws Exception
+ {
+ super.doPerform( pipelineData, context );
+ List<Author> authors = AuthorPeer.doSelect( new Criteria() );//all
+ context.put( "authors", authors );
+ RunData data = getRunData(pipelineData);
+ data.setScreenTemplate(Character.toLowerCase(getClass().getSimpleName().charAt(0)) +
+ getClass().getSimpleName().substring(1) + ".vm"
+ );
+
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/screens/Index.java b/src/main/resources/archetype-resources/src/main/java/modules/screens/Index.java
new file mode 100644
index 0000000..6f6fa70
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/screens/Index.java
@@ -0,0 +1,66 @@
+package ${package}.modules.screens;
+#*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*#
+
+import org.apache.fulcrum.json.JsonService;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.TurbineServices;
+import org.apache.velocity.context.Context;
+import org.apache.turbine.modules.screens.VelocitySecureScreen;
+
+
+/**
+ * This class provides the data required for displaying content in the
+ * Velocity page.
+ */
+public class Index extends VelocitySecureScreen
+{
+
+ JsonService jsonService = (JsonService)TurbineServices.getInstance().getService(JsonService.ROLE);
+ /**
+ * This method is called by the Turbine framework when the
+ * associated Velocity template, Index.vm is requested
+ *
+ * @param data the Turbine request data
+ * @param context the Velocity context
+ * @throws Exception a generic Exception
+ */
+ @Override
+ protected void doBuildTemplate(PipelineData data, Context context)
+ throws Exception
+ {
+ context.put("success", "Congratulations, it worked!");
+ }
+
+ /**
+ * This method is called bythe Turbine framework to determine if
+ * the current user is allowed to use this screen. If this method
+ * returns false, the doBuildTemplate() method will not be called.
+ * If a redirect to some "access denied" page is required, do the
+ * necessary redirect here.
+ *
+ * return always <code>true</code>true, to show this screen as default
+ */
+ @Override
+ protected boolean isAuthorized(PipelineData data) throws Exception
+ {
+ // use data.getACL()
+ return true;
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/screens/Password.java b/src/main/resources/archetype-resources/src/main/java/modules/screens/Password.java
new file mode 100644
index 0000000..aff1b2a
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/screens/Password.java
@@ -0,0 +1,53 @@
+package ${package}.modules.screens;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.screens.VelocitySecureScreen;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.velocity.context.Context;
+import org.apache.commons.configuration.Configuration;
+
+/**
+ * This class provides a sample extending a secured screen
+ */
+public class Password extends SecureScreen
+{
+ /**
+ * This method is called by the Turbine framework when the
+ * associated Velocity template, Index.vm is requested
+ *
+ * @param data the Turbine request data
+ * @param context the Velocity context
+ * @throws Exception a generic Exception
+ */
+ @Override
+ protected void doBuildTemplate(PipelineData data, Context context)
+ throws Exception
+ {
+
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/screens/SecureScreen.java b/src/main/resources/archetype-resources/src/main/java/modules/screens/SecureScreen.java
new file mode 100644
index 0000000..2f90b62
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/screens/SecureScreen.java
@@ -0,0 +1,93 @@
+package ${package}.modules.screens;
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.screens.VelocitySecureScreen;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.velocity.context.Context;
+import org.apache.commons.configuration.Configuration;
+
+/**
+ * This class provides a sample implementation for creating a secured screen
+ */
+public class SecureScreen extends VelocitySecureScreen
+{
+ @TurbineService
+ protected SecurityService securityService;
+
+ @TurbineConfiguration( TurbineConstants.TEMPLATE_LOGIN )
+ private Configuration templateLogin;
+
+ @TurbineConfiguration( TurbineConstants.TEMPLATE_HOMEPAGE )
+ private Configuration templateHomepage;
+
+ @Override
+ protected boolean isAuthorized(PipelineData data) throws Exception
+ {
+ boolean isAuthorized = false;
+
+ // Who is our current user?
+ User user = getRunData(data).getUser();
+
+ // Get the Turbine ACL implementation
+ TurbineAccessControlList acl = getRunData(data).getACL();
+
+ if (acl == null)
+ {
+ // commons configuration getProperty: prefix removed, the key for the value .. is an empty string, the result an object
+ getRunData(data).setScreenTemplate( (String) templateLogin.getProperty("") );
+ isAuthorized = false;
+ }
+ else if (acl.hasRole("turbineuser") || acl.hasRole("turbineadmin"))
+ {
+ isAuthorized = true;
+ }
+ else
+ {
+ getRunData(data).setScreenTemplate( (String) templateHomepage.getProperty("") );
+ getRunData(data).setMessage("You do not have access to this part of the site.");
+ isAuthorized = false;
+ }
+ return isAuthorized;
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception,
+ * a generic exception.
+ */
+ @Override
+ protected void doBuildTemplate(PipelineData data, Context context) throws Exception
+ {
+
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/screens/TestSecure.java b/src/main/resources/archetype-resources/src/main/java/modules/screens/TestSecure.java
new file mode 100644
index 0000000..55ba3b1
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/screens/TestSecure.java
@@ -0,0 +1,47 @@
+package ${package}.modules.screens;
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.torque.criteria.Criteria;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.velocity.context.Context;
+
+/**
+ * This class provides the data required for displaying content in the
+ * Velocity page.
+ */
+public class TestSecure extends SecureScreen
+{
+ /**
+ * This method is called by the Turbine framework when the
+ * associated Velocity template, Index.vm is requested
+ *
+ * @param data the Turbine request data
+ * @param context the Velocity context
+ * @throws Exception a generic Exception
+ */
+ @Override
+ protected void doBuildTemplate(PipelineData data, Context context)
+ throws Exception
+ {
+ context.put("success", "Congratulations, it worked here too!");
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineGroupPeer.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineGroupPeer.java
new file mode 100644
index 0000000..d54dcf1
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineGroupPeer.java
@@ -0,0 +1,21 @@
+package ${package}.om;
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Tue Oct 25 15:50:37 CEST 2016]
+ *
+ * This class provides static wrappers for the peer implementation classes.
+ * This class will only be generated as long as it does not already exist
+ * in the output directory.
+ */
+/**
+ * Added Interface
+ * @author gk
+ *
+ */
+public class TurbineGroupPeer
+ extends ${package}.om.BaseTurbineGroupPeer implements org.apache.fulcrum.security.torque.peer.Peer
+{
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineGroupPeerImpl.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineGroupPeerImpl.java
new file mode 100644
index 0000000..94c681d
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineGroupPeerImpl.java
@@ -0,0 +1,25 @@
+package ${package}.om;
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Tue Oct 25 15:50:38 CEST 2016]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+/**
+ * Added Interface
+ * @author gk
+ *
+ */
+public class TurbineGroupPeerImpl
+ extends ${package}.om.BaseTurbineGroupPeerImpl implements org.apache.fulcrum.security.torque.peer.TorqueTurbinePeer<TurbineGroup>
+{
+ /** Serial version */
+ private static final long serialVersionUID = 1477403438057L;
+
+
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbinePermissionPeer.java b/src/main/resources/archetype-resources/src/main/java/om/TurbinePermissionPeer.java
new file mode 100644
index 0000000..bdbdf0f
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbinePermissionPeer.java
@@ -0,0 +1,16 @@
+package ${package}.om;
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Thu Sep 04 12:20:05 CEST 2014]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+public class TurbinePermissionPeer
+ extends ${package}.om.BaseTurbinePermissionPeer implements org.apache.fulcrum.security.torque.peer.Peer
+{
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbinePermissionPeerImpl.java b/src/main/resources/archetype-resources/src/main/java/om/TurbinePermissionPeerImpl.java
new file mode 100644
index 0000000..19bd132
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbinePermissionPeerImpl.java
@@ -0,0 +1,20 @@
+package ${package}.om;
+
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Mon Nov 25 16:49:55 CET 2013]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+
+public class TurbinePermissionPeerImpl
+ extends ${package}.om.BaseTurbinePermissionPeerImpl implements org.apache.fulcrum.security.torque.peer.TorqueTurbinePeer<TurbinePermission>
+{
+ /** Serial version */
+ private static final long serialVersionUID = 138394595924L;
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePeer.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePeer.java
new file mode 100644
index 0000000..739597f
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePeer.java
@@ -0,0 +1,21 @@
+package ${package}.om;
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Tue Oct 25 15:50:37 CEST 2016]
+ *
+ * This class provides static wrappers for the peer implementation classes.
+ * This class will only be generated as long as it does not already exist
+ * in the output directory.
+ */
+/**
+ * Added Interface
+ * @author gk
+ *
+ */
+public class TurbineRolePeer
+ extends ${package}.om.BaseTurbineRolePeer implements org.apache.fulcrum.security.torque.peer.Peer
+{
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePeerImpl.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePeerImpl.java
new file mode 100644
index 0000000..91d307f
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePeerImpl.java
@@ -0,0 +1,27 @@
+package ${package}.om;
+
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Tue Oct 25 15:50:38 CEST 2016]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+/**
+ * Added Interface
+ * @author gk
+ *
+ */
+public class TurbineRolePeerImpl
+ extends ${package}.om.BaseTurbineRolePeerImpl implements org.apache.fulcrum.security.torque.peer.TorqueTurbinePeer<TurbineRole>
+{
+ /** Serial version */
+ private static final long serialVersionUID = 1477403438057L;
+
+
+
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePermission.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePermission.java
new file mode 100644
index 0000000..a26f32e
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineRolePermission.java
@@ -0,0 +1,25 @@
+package ${package}.om;
+
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Tue Oct 25 15:50:37 CEST 2016]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+
+public class TurbineRolePermission
+ extends ${package}.om.BaseTurbineRolePermission
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+
+
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineUser.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineUser.java
new file mode 100644
index 0000000..849439a
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineUser.java
@@ -0,0 +1,79 @@
+package ${package}.om;
+
+import java.sql.Connection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.fulcrum.security.model.turbine.entity.TurbineUserGroupRole;
+import org.apache.torque.TorqueException;
+
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Tue Oct 25 15:50:37 CEST 2016]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ * #set( $H = '#' )
+ * Added Interface
+ * @author gk
+ *
+ */
+public class TurbineUser
+ extends ${package}.om.BaseTurbineUser implements org.apache.fulcrum.security.model.turbine.entity.TurbineUser
+{
+ /** Serial version */
+ private static final long serialVersionUID = 1477403437136L;
+
+ /**
+ * Get the value of id.
+ *
+ * @return Object
+ */
+ @Override
+ public Object getId()
+ {
+
+ return getEntityId();
+ }
+
+ /**
+ * Set the value of id.
+ *
+ * @param v new value
+ */
+ @Override
+ public void setId(Object v)
+ {
+ setEntityId( (Integer) v);
+
+ }
+
+ /**
+ * Get the value of name.
+ *
+ * @return String
+ */
+ @Override
+ public String getName()
+ {
+
+ return getEntityName();
+ }
+
+ /**
+ * Set the value of name.
+ *
+ * @param v new value
+ */
+ @Override
+ public void setName(String v)
+ {
+ setEntityName(v);
+
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineUserGroupRole.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineUserGroupRole.java
new file mode 100644
index 0000000..1e41b24
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineUserGroupRole.java
@@ -0,0 +1,23 @@
+package ${package}.om;
+
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Fri Jan 12 15:33:37 CET 2018]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+
+public class TurbineUserGroupRole
+ extends ${package}.om.BaseTurbineUserGroupRole
+ implements org.apache.fulcrum.security.torque.peer.TurbineUserGroupRoleModelPeerMapper
+{
+ /** Serial version */
+ private static final long serialVersionUID = 1515767617070L;
+
+
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineUserGroupRolePeerImpl.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineUserGroupRolePeerImpl.java
new file mode 100644
index 0000000..036bf71
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineUserGroupRolePeerImpl.java
@@ -0,0 +1,23 @@
+package ${package}.om;
+
+import org.apache.fulcrum.security.torque.peer.TorqueTurbineUserGroupRolePeer;
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Mon Nov 27 14:37:43 CET 2017]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+
+public class TurbineUserGroupRolePeerImpl
+ extends ${package}.om.BaseTurbineUserGroupRolePeerImpl
+ implements TorqueTurbineUserGroupRolePeer
+{
+ /** Serial version */
+ private static final long serialVersionUID = 1511789863339L;
+
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineUserPeer.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineUserPeer.java
new file mode 100644
index 0000000..4c330e2
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineUserPeer.java
@@ -0,0 +1,22 @@
+package ${package}.om;
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Tue Oct 25 15:50:37 CEST 2016]
+ *
+ * This class provides static wrappers for the peer implementation classes.
+ * This class will only be generated as long as it does not already exist
+ * in the output directory.
+ */
+/**
+ * Added Interface
+ * @author gk
+ *
+ */
+
+public class TurbineUserPeer
+ extends ${package}.om.BaseTurbineUserPeer implements org.apache.fulcrum.security.torque.peer.Peer
+{
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/om/TurbineUserPeerImpl.java b/src/main/resources/archetype-resources/src/main/java/om/TurbineUserPeerImpl.java
new file mode 100644
index 0000000..38d7984
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/om/TurbineUserPeerImpl.java
@@ -0,0 +1,25 @@
+package ${package}.om;
+
+
+/**
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [Tue Oct 25 15:50:38 CEST 2016]
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+
+/**
+ * Added Interface
+ * @author gk
+ *
+ */
+public class TurbineUserPeerImpl
+ extends ${package}.om.BaseTurbineUserPeerImpl implements org.apache.fulcrum.security.torque.peer.TorqueTurbinePeer<TurbineUser>
+{
+ /** Serial version */
+ private static final long serialVersionUID = 1477403438057L;
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/services/pull/RelatedTool.java b/src/main/resources/archetype-resources/src/main/java/services/pull/RelatedTool.java
new file mode 100644
index 0000000..f529e20
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/services/pull/RelatedTool.java
@@ -0,0 +1,125 @@
+package ${package}.services.pull;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*#
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.json.JsonService;
+import org.apache.fulcrum.security.entity.Role;
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.fulcrum.security.util.RoleSet;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.services.TurbineServices;
+import org.apache.turbine.services.pull.RunDataApplicationTool;
+import org.apache.turbine.util.RunData;
+import org.apache.turbine.services.security.SecurityService;
+
+
+public class RelatedTool implements RunDataApplicationTool {
+
+ /** Logging */
+ private static Log log = LogFactory.getLog(RelatedTool.class);
+
+ private RunData data = null;
+
+ @Override
+ public void init(Object data) {
+ this.data = (RunData) data;
+
+ }
+
+ @Override
+ public void refresh(RunData data) {
+ this.data = data;
+ }
+
+ public String getUserrole() {
+ try {
+ User user = data.getUser();
+ Role role = null;
+ if (user != null && user.getName() != null) {
+ log.info("reading role for: "+user.getName());
+ if (data.getACL() != null && data.getACL() instanceof TurbineAccessControlList) {
+ RoleSet roles = ((TurbineAccessControlList)data.getACL()).getRoles();
+ if (roles != null && roles.getSet().size() == 1) {
+ Role fulcrumRole = roles.getSet().iterator().next();
+ log.debug("acl role is: "+fulcrumRole.getName());
+ return fulcrumRole.getName();
+ }
+ } else {
+ SecurityService securityService = (SecurityService) TurbineServices.getInstance().getService(SecurityService.SERVICE_NAME);
+ RoleSet roles = securityService.getAllRoles();
+ }
+ } else if (user != null) {
+ SecurityService securityService = (SecurityService) TurbineServices.getInstance().getService(SecurityService.SERVICE_NAME);
+ role = securityService.getRoleByName("user");
+ //.retrieveRole("anon");
+ }
+ return (role != null)? role.getName(): null;
+ } catch (Exception e) {
+ log.error("RelatedTool - failure in reading role: ", e);
+ return null;
+ }
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public <T> Object getJson(Object src, String className, String mixinCN, Boolean refresh, String... props ) {
+ String result= null;
+ JsonService jsonService = (JsonService)TurbineServices
+ .getInstance().getService(JsonService.ROLE);
+ try
+ {
+ log.info( "refresh is:"+ refresh );
+ log.info( "jsonService:"+ jsonService );
+ log.info( "source class is:"+ className );
+ log.info( "target object is:"+ src );
+ Class clazz = Class.forName(className);
+ if (props != null) {
+ log.info( "props length:"+ props.length);
+ for ( int i = 0; i < props.length; i++ )
+ {
+ log.debug( "props:"+ props[i]);
+ }
+ }
+ if (mixinCN != null ) {
+ Class mixin = Class.forName(mixinCN);
+ if (mixin != null ) {
+ Set<Class> mixins = new HashSet<Class>();
+ mixins.add( mixin );
+ log.info( "adding adapter mixinCN:"+ mixinCN);
+ jsonService.addAdapter( mixinCN, clazz, mixin );
+ }
+ }
+ String serialized = jsonService.serializeOnlyFilter( src, clazz, refresh, props );
+ log.debug( "serialized:"+serialized );
+ return serialized;
+ }
+ catch ( Exception e )
+ {
+ log.error(e.getMessage(),e );
+ result = e.getMessage();
+ }
+ return result;
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/wrapper/TurbineUserWrapper.java b/src/main/resources/archetype-resources/src/main/java/wrapper/TurbineUserWrapper.java
new file mode 100644
index 0000000..44088e4
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/wrapper/TurbineUserWrapper.java
@@ -0,0 +1,36 @@
+package ${package}.wrapper;
+
+/*
+ * Copyright 2001-2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.fulcrum.security.model.turbine.entity.TurbineUser;
+import org.apache.turbine.om.security.DefaultUserImpl;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * Custom Wrapper instead fo default Turbine wrapper class {@link DefaultUserImpl} to allow for annotations,
+ * - th single requirment for wrappers is to implement a constructor with parameter {@link TurbineUser}
+ *
+ */
+ @JsonIgnoreProperties( {"permStorage", "type","objectdata" } )
+public class TurbineUserWrapper
+ extends DefaultUserImpl
+{
+ public TurbineUserWrapper(TurbineUser user) {
+ super(user);
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/torque-schema/application-data.xml b/src/main/resources/archetype-resources/src/main/torque-schema/application-data.xml
new file mode 100644
index 0000000..eeef5cd
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/torque-schema/application-data.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+#*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*#
+<!DOCTYPE dataset SYSTEM "file://application-data.dtd">
+
+<!-- =============================================================================== -->
+<!-- -->
+<!-- Application Data in XML. Add your custom values to this file -->
+<!-- -->
+<!-- @version $Id: application-data.xml 615328 2008-01-25 20:25:05Z tv $ -->
+<!-- -->
+<!-- =============================================================================== -->
+
+<dataset name="all"/>
+
diff --git a/src/main/resources/archetype-resources/src/main/torque-schema/application-schema.xml b/src/main/resources/archetype-resources/src/main/torque-schema/application-schema.xml
new file mode 100644
index 0000000..8e867d5
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/torque-schema/application-schema.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<!-- ============================================================================== -->
+<!-- -->
+<!-- Database Definition for the Application -->
+<!-- -->
+<!-- @version $Id: application-schema.xml -->
+<!-- -->
+<!-- ============================================================================== -->
+
+<database xmlns="http://db.apache.org/torque/4.0/templates/database"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://db.apache.org/torque/4.0/templates/database
+ http://db.apache.org/torque/4.0/templates/database-strict.xsd"
+ name="${turbine_database_name}"
+ defaultIdMethod="native">
+
+
+ <!-- Simple author/book database example -->
+ <table name="AUTHOR" idMethod="idbroker">
+ <column name="AUTH_ID" required="true" primaryKey="true" type="INTEGER" />
+ <column name="FIRST_NAME" required="true" size="64" type="VARCHAR" />
+ <column name="LAST_NAME" required="true" size="64" type="VARCHAR" />
+ </table>
+
+ <table name="BOOK" idMethod="idbroker">
+ <column name="BOOK_ID" required="true" primaryKey="true" type="INTEGER" />
+ <column name="AUTH_ID" required="true" type="INTEGER" />
+ <column name="TITLE" required="true" size="64" type="VARCHAR" />
+ <column name="SUBJECT" required="true" size="64" type="VARCHAR" />
+ <foreign-key foreignTable="AUTHOR">
+ <reference local="AUTH_ID" foreign="AUTH_ID"></reference>
+ </foreign-key>
+ </table>
+</database>
diff --git a/src/main/resources/archetype-resources/src/main/torque-schema/id-table-schema.xml b/src/main/resources/archetype-resources/src/main/torque-schema/id-table-schema.xml
new file mode 100644
index 0000000..5002f21
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/torque-schema/id-table-schema.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<!-- ========================================================================= -->
+<!-- -->
+<!-- Table definition for the ID Broker Table used by Torque -->
+<!-- -->
+<!-- @version $Id: id-table-schema.xml 615328 2008-01-25 20:25:05Z tv $ -->
+<!-- -->
+<!-- ========================================================================= -->
+
+<database xmlns="http://db.apache.org/torque/4.0/templates/database"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://db.apache.org/torque/4.0/templates/database
+ http://db.apache.org/torque/4.0/templates/database-strict.xsd"
+ name="${turbine_database_name}"
+ defaultIdMethod="native">
+
+ <table name="ID_TABLE" idMethod="idbroker">
+ <column name="ID_TABLE_ID" required="true" primaryKey="true" type="INTEGER" javaName="IdTableId"/>
+ <column name="TABLE_NAME" required="true" size="255" type="VARCHAR" javaName="TableName"/>
+ <column name="NEXT_ID" required="true" type="INTEGER" javaName="NextId"/>
+ <column name="QUANTITY" required="true" type="INTEGER" javaName="Quantity"/>
+
+ <unique>
+ <unique-column name="TABLE_NAME"/>
+ </unique>
+
+ </table>
+</database>
diff --git a/src/main/resources/archetype-resources/src/main/torque-schema/torque-security-data.xml b/src/main/resources/archetype-resources/src/main/torque-schema/torque-security-data.xml
new file mode 100644
index 0000000..8503f8f
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/torque-schema/torque-security-data.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+#*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*#
+<!DOCTYPE dataset SYSTEM "file://torque-security-data.dtd">
+
+<!-- =============================================================================== -->
+<!-- -->
+<!-- Default Values for Admin and normal User -->
+<!-- -->
+<!-- @version $Id: turbine-security-data.xml 615328 2008-01-25 20:25:05Z tv $ -->
+<!-- -->
+<!-- =============================================================================== -->
+
+<dataset name="all">
+
+ <TurbineUser UserId="1"
+ UserName="admin"
+ Password="password"
+ FirstName=""
+ LastName="Admin"/>
+
+ <TurbineUser UserId="2"
+ UserName="user"
+ Password="password"
+ FirstName=""
+ LastName="User"/>
+
+ <!-- Turbine Permissions -->
+
+ <TurbinePermission PermissionId="1" Name="turbineadmin"/>
+ <TurbinePermission PermissionId="2" Name="turbine"/>
+
+ <!-- Turbine Roles -->
+
+ <TurbineRole RoleId="1" Name="turbineadmin"/>
+ <TurbineRole RoleId="2" Name="turbineuser"/>
+
+ <!-- Turbine Groups -->
+
+ <TurbineGroup GroupId="1" Name="global"/>
+ <TurbineGroup GroupId="2" Name="Turbine"/>
+
+ <TurbineRolePermission RoleId="1" PermissionId="1"/>
+ <TurbineRolePermission RoleId="2" PermissionId="2"/>
+
+ <!-- Associate Users, Groups, and Roles -->
+
+ <TurbineUserGroupRole UserId="1" GroupId="2" RoleId="1"/>
+ <TurbineUserGroupRole UserId="2" GroupId="2" RoleId="2"/>
+
+</dataset>
diff --git a/src/main/resources/archetype-resources/src/main/torque-schema/torque-security-schema.xml b/src/main/resources/archetype-resources/src/main/torque-schema/torque-security-schema.xml
new file mode 100644
index 0000000..a4901fe
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/torque-schema/torque-security-schema.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+
+<!-- ======================================================================== -->
+<!-- -->
+<!-- Turbine Torque based Security Service Schema -->
+<!-- -->
+<!-- Schema documentation -->
+<!-- http://db.apache.org/torque/torque-4.0/documentation/orm-reference/database-4-0-strict.xsd -->
+<!-- http://db.apache.org/torque/torque-4.0/documentation/orm-reference/database-4-0.xsd -->
+<!-- -->
+<!-- $Id: turbine-security-schema.xml 615328 2008-01-25 20:25:05Z tv $ -->
+<!-- -->
+<!-- ======================================================================== -->
+
+<database xmlns="http://db.apache.org/torque/4.0/templates/database"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://db.apache.org/torque/4.0/templates/database
+ http://db.apache.org/torque/4.0/templates/database-strict.xsd"
+ name="${turbine_database_name}"
+ defaultIdMethod="none">
+
+
+ <table name="TURBINE_PERMISSION" idMethod="native" baseClass="org.apache.fulcrum.security.torque.turbine.DefaultAbstractTurbinePermission" interface="org.apache.fulcrum.security.model.turbine.entity.TurbinePermission">
+ <column name="PERMISSION_ID" required="true" primaryKey="true" type="INTEGER" javaType="object" javaName="EntityId" autoIncrement="true"/>
+ <column name="PERMISSION_NAME" required="true" size="64" type="VARCHAR" javaName="EntityName"/>
+
+ <unique>
+ <unique-column name="PERMISSION_NAME"/>
+ </unique>
+
+ </table>
+
+ <table name="TURBINE_ROLE" idMethod="native" baseClass="org.apache.fulcrum.security.torque.turbine.DefaultAbstractTurbineRole" interface="org.apache.fulcrum.security.model.turbine.entity.TurbineRole">
+ <column name="ROLE_ID" required="true" primaryKey="true" type="INTEGER" javaType="object" javaName="EntityId" autoIncrement="true"/>
+ <column name="ROLE_NAME" required="true" size="64" type="VARCHAR" javaName="EntityName"/>
+
+ <unique>
+ <unique-column name="ROLE_NAME"/>
+ </unique>
+
+ </table>
+
+ <table name="TURBINE_GROUP" idMethod="native" baseClass="org.apache.fulcrum.security.torque.turbine.DefaultAbstractTurbineGroup" interface="org.apache.fulcrum.security.model.turbine.entity.TurbineGroup">
+ <column name="GROUP_ID" required="true" primaryKey="true" type="INTEGER" javaType="object" javaName="EntityId" autoIncrement="true"/>
+ <column name="GROUP_NAME" required="true" type="VARCHAR" size="64" javaName="EntityName"/>
+
+ <unique>
+ <unique-column name="GROUP_NAME"/>
+ </unique>
+
+ </table>
+
+ <table name="TURBINE_ROLE_PERMISSION">
+ <column name="ROLE_ID" required="true" primaryKey="true" type="INTEGER"/>
+ <column name="PERMISSION_ID" required="true" primaryKey="true" type="INTEGER"/>
+
+ <!-- Turbine service revokeAll(role) manages removal, but you might want to handle it just with onDelete="cascade" -->
+ <foreign-key foreignTable="TURBINE_ROLE">
+ <reference local="ROLE_ID" foreign="ROLE_ID"/>
+ </foreign-key>
+
+ <foreign-key foreignTable="TURBINE_PERMISSION">
+ <reference local="PERMISSION_ID" foreign="PERMISSION_ID"/>
+ </foreign-key>
+ </table>
+
+ <!-- org.apache.fulcrum.security.torque.TorqueAbstractSecurityEntity -->
+ <table name="TURBINE_USER" idMethod="native" baseClass="org.apache.fulcrum.security.torque.turbine.DefaultAbstractTurbineUser"
+ interface="org.apache.fulcrum.security.model.turbine.entity.TurbineUser">
+ <column name="USER_ID" required="true" primaryKey="true" type="INTEGER" javaType="object" javaName="EntityId" autoIncrement="true"/>
+ <column name="LOGIN_NAME" required="true" size="64" type="VARCHAR" javaName="EntityName"/>
+ <column name="PASSWORD_VALUE" required="true" size="16" type="VARCHAR" javaName="Password"/>
+ <column name="FIRST_NAME" required="true" size="64" type="VARCHAR"/>
+ <column name="LAST_NAME" required="true" size="64" type="VARCHAR"/>
+ <column name="EMAIL" size="64" type="VARCHAR"/>
+ <column name="CONFIRM_VALUE" size="16" type="VARCHAR" javaName="Confirmed"/>
+ <column name="MODIFIED_DATE" type="TIMESTAMP" javaName="ModifiedDate"/>
+ <column name="CREATED" type="TIMESTAMP" javaName="CreateDate"/>
+ <column name="LAST_LOGIN" type="TIMESTAMP"/>
+ <column name="OBJECTDATA" type="VARBINARY"/>
+
+ <unique>
+ <unique-column name="LOGIN_NAME"/>
+ </unique>
+
+ </table>
+
+ <table name="TURBINE_USER_GROUP_ROLE" interface="org.apache.fulcrum.security.torque.peer.TurbineUserGroupRoleModelPeerMapper">
+ <column name="USER_ID" required="true" primaryKey="true" type="INTEGER"/>
+ <column name="GROUP_ID" required="true" primaryKey="true" type="INTEGER"/>
+ <column name="ROLE_ID" required="true" primaryKey="true" type="INTEGER"/>
+ <!-- Turbine service revokeAll(user) manages removal, but you might want to handle it just with onDelete="cascade" -->
+ <foreign-key foreignTable="TURBINE_USER">
+ <reference local="USER_ID" foreign="USER_ID"/>
+ </foreign-key>
+
+ <foreign-key foreignTable="TURBINE_GROUP">
+ <reference local="GROUP_ID" foreign="GROUP_ID"/>
+ </foreign-key>
+
+ <foreign-key foreignTable="TURBINE_ROLE">
+ <reference local="ROLE_ID" foreign="ROLE_ID"/>
+ </foreign-key>
+ </table>
+
+</database>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/META-INF/context.xml b/src/main/resources/archetype-resources/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..f458f40
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='utf-8'?>
+<Context>
+ <WatchedResource>WEB-INF/web.xml</WatchedResource>
+ <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
+ <Resource name="${turbine_database_jndipath}" global="${turbine_database_jndipath}" auth="Container" type="javax.sql.DataSource"
+ driverClassName="${turbine_database_driver}"
+ url="${turbine_database_url}${turbine_database_name}"
+ username="${turbine_database_user}" password="${turbine_database_password}"
+ maxTotal="100" maxIdle="20" minIdle="5" maxWaitMillis="10000"/>
+</Context>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/Torque.properties b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/Torque.properties
new file mode 100644
index 0000000..023ef76
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/Torque.properties
@@ -0,0 +1,126 @@
+#*
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+*#
+# -------------------------------------------------------------------
+#
+# This is the configuration file for Torque.
+#
+# Note that strings containing "," (comma) characters must backslash
+# escape the comma (i.e. '\,')
+#
+# -------------------------------------------------------------------
+#
+# T O R Q U E P R O P E R T I E S
+#
+# -------------------------------------------------------------------
+# These are your database settings. Look in the
+# org.apache.torque.pool.* packages for more information.
+#
+# The parameters to connect to the default database. You MUST
+# configure these properly.
+# -------------------------------------------------------------------
+
+
+
+#
+# For JNDI configuration please see: https://db.apache.org/torque/torque-4.0/documentation/orm-reference/initialisation-configuration.html
+#
+#
+torque.dsfactory.${turbine_database_name}.factory=org.apache.torque.dsfactory.JndiDataSourceFactory
+torque.dsfactory.${turbine_database_name}.jndi.path=java:comp/env/${turbine_database_jndipath}
+torque.dsfactory.${turbine_database_name}.jndi.ttl=300000
+
+# -------------------------------------------------------------------
+#
+# Shared Pool Data Source Factory
+#
+# -------------------------------------------------------------------
+#torque.database.default=${turbine_database_name}
+torque.database.${turbine_database_name}.adapter=${turbine_database_adapter}
+
+#torque.database.${turbine_database_name}.user=${turbine_database_user}
+#torque.database.${turbine_database_name}.password=${turbine_database_password}
+#
+#torque.defaults.pool.maxActive = 30
+#torque.defaults.pool.testOnBorrow = true
+#torque.defaults.pool.validationQuery = SELECT 1
+#
+#torque.defaults.connection.driver = ${turbine_database_driver}
+#torque.defaults.connection.url = ${turbine_database_url}${turbine_database_name}
+#torque.defaults.connection.user = ${turbine_database_user}
+#torque.defaults.connection.password = ${turbine_database_password}
+#
+#torque.dsfactory.${turbine_database_name}.connection.driver = ${turbine_database_driver}
+#torque.dsfactory.${turbine_database_name}.connection.url = ${turbine_database_url}${turbine_database_name}
+#torque.dsfactory.${turbine_database_name}.connection.user = ${turbine_database_user}
+#torque.dsfactory.${turbine_database_name}.connection.password = ${turbine_database_password}
+#torque.dsfactory.${turbine_database_name}.factory=org.apache.torque.dsfactory.SharedPoolDataSourceFactory
+# -------------------------------------------------------------------
+
+# Determines if the quantity column of the IDBroker's id_table should
+# be increased automatically if requests for ids reaches a high
+# volume.
+
+torque.idbroker.cleverquantity=true
+
+# Determines whether the managers cache instances of the business objects.
+# And also whether the MethodResultCache will really cache results.
+torque.manager.useCache = true
+
+# Determines if IDBroker should prefetch IDs or not. If set to false
+# this property has the effect of shutting off the housekeeping thread
+# that attempts to prefetch the id's. It also sets the # of id's grabbed
+# per request to 1 regardless of the settings in the database.
+# Default: true
+torque.idbroker.prefetch = true
+
+# Controls the starting id of table entries when creating SQL for
+# the id-table. If you have two projects that use the same id-table
+# in the same database with different tables, make sure that they have
+# different initialID settings and the ranges (initialID is incremented
+# for every new table) don't overlap.
+torque.idbroker.initialId = 101
+
+# The start value of the ID broker for supplying IDs to Torque. This value
+# is incremented every time Torque requests ID keys from the broker. If you
+# pre-load your table straight from SQL, make sure that you don't accidentially
+# overlap with this setting, because Torque doesn't keep record of what IDs are
+# already taken in the database. If you overlap, inserting new objects will fail
+# because the ID assigned by Torque is already taken.
+torque.idBroker.initialIdValue = 100
+
+# For performance reasons, the ID Broker does not request a single ID at a time
+# but fetches a whole range and increments the current next ID Value in the ID
+# Table by this step. If you have to do lots of inserts straight in a row, increment
+# this value to get slightly better performance.
+torque.idbroker.initialIdStep = 500
+
+# IDBroker can grab its own connection from the pool to use when retrieving
+# more id's to minimize the amount of time ID_TABLE will be locked.
+# Some usage of IDBroker or assumptions made by connection pools or jdbc
+# drivers may disallow this optimization in which case the property
+# should be set to false.
+torque.idbroker.usenewconnection = true
+
+# Comment if not using shared data source factory
+torque.database.default=${turbine_database_name}
+
+
+
+
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/TurbineConfigurationBuilder.xml b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/TurbineConfigurationBuilder.xml
new file mode 100644
index 0000000..4c6407e
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/TurbineConfigurationBuilder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<configuration>
+ <header>
+ <!-- Meta data about the resulting combined configuration -->
+ </header>
+ <override><!-- only allowed configurations are user and turbine, realtive paths -->
+ <properties config-name="user" fileName="WEB-INF/conf/usersettings.properties" config-optional="true" config-forceCreate="true"/>
+ <!-- xml fileName="conf/test/TurbineResources.xml"/-->
+ <properties config-name="turbine" fileName="WEB-INF/conf/TurbineResources.properties" throwExceptionOnMissing="true"/>
+ </override>
+ <additional>
+ <!-- Configuration declarations that form a union configuration, always provide a unique config-name attribute -->
+ </additional>
+</configuration>
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/TurbineResources.properties b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/TurbineResources.properties
new file mode 100644
index 0000000..4e954dc
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/TurbineResources.properties
@@ -0,0 +1,661 @@
+#*
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+*#
+# -------------------------------------------------------------------
+#
+# This is the configuration file for Turbine.
+#
+# Note that strings containing "," (comma) characters must backslash
+# escape the comma (i.e. '\,')
+#
+# -------------------------------------------------------------------
+
+# -------------------------------------------------------------------
+#
+# P I P E L I N E
+#
+# -------------------------------------------------------------------
+pipeline.default.descriptor = WEB-INF/conf/turbine-classic-pipeline.xml
+
+# -------------------------------------------------------------------
+#
+# L O G 4 J - L O G G I N G
+#
+# -------------------------------------------------------------------
+
+log4j.file = WEB-INF/conf/log4j.properties
+
+# -------------------------------------------------------------------
+#
+# M A I L S E R V E R
+#
+# -------------------------------------------------------------------
+# Your mail server for outgoing email.
+#
+# Default: null
+# -------------------------------------------------------------------
+
+mail.server=
+
+# -------------------------------------------------------------------
+# SMTP-From header for your outgoing messages
+#
+# All failed delivery messages will be returned to this address.
+# If unset, these messages will be sent to the address in the
+# From header (standard behaviour)
+#
+# Default: null
+# -------------------------------------------------------------------
+
+mail.smtp.from=
+
+# -------------------------------------------------------------------
+#
+# S E R V E R D A T A
+#
+# -------------------------------------------------------------------
+# Default ServerData that can be used if asked for before the first
+# request is made.
+#
+# Defaults:
+#
+# serverdata.default.serverName=
+# serverdata.default.serverPort=80
+# serverdata.default.serverScheme=http
+# serverdata.default.scriptName=
+# serverdata.default.contextPath=
+# -------------------------------------------------------------------
+
+serverdata.default.serverName=
+serverdata.default.serverPort=80
+serverdata.default.serverScheme=http
+serverdata.default.scriptName=
+serverdata.default.contextPath=
+
+# -------------------------------------------------------------------
+#
+# M O D U L E C A C H I N G
+#
+# -------------------------------------------------------------------
+# This determines whether or not to cache the modules in memory. For
+# development, turn this off. For production, turn this on.
+#
+# Default: false
+# -------------------------------------------------------------------
+
+module.cache=false
+
+# If module.cache=true, then how large should we make the hashtables
+# by default.
+
+action.cache.size=20
+layout.cache.size=10
+navigation.cache.size=10
+page.cache.size=5
+screen.cache.size=50
+scheduledjob.cache.size=10
+
+# -------------------------------------------------------------------
+#
+# M O D U L E P A C K A G E S
+#
+# -------------------------------------------------------------------
+# This is the "classpath" for Turbine. In order to locate your own
+# modules, you should add them to this path. For example, if you have
+# com.company.actions, com.company.screens, com.company.navigations,
+# then this setting would be "com.company,org.apache.turbine.modules".
+# This path is searched in order. For example, Turbine comes with a
+# screen module named "Login". If you wanted to have your own screen
+# module named "Login", then you would specify the path to your
+# modules before the others.
+#
+# Note: org.apache.turbine.modules will always be added to the search
+# path. If it is not explicitly added here, it will be added to the
+# end.
+#
+# Default: org.apache.turbine.modules
+# -------------------------------------------------------------------
+
+module.packages=${package}.modules,${package}.flux.modules,org.apache.turbine.modules
+
+# -------------------------------------------------------------------
+#
+# F R A M E W O R K S E T T I N G S
+#
+# -------------------------------------------------------------------
+# These are settings that control the behavior of the framework,
+# such as determining whether a template system is in use, what
+# the default templates and screens are and session handling settings.
+# -------------------------------------------------------------------
+
+# Used to set the template homepage if you are using a template
+# layout. This is the template that will be displayed to the user
+# when no specific template is requested. This is normally executed
+# as the first template the user sees when they access the system.
+#
+# Default: Index.vm
+
+template.homepage=Index.vm
+
+# This is the default screen to show to people when they first access
+# the system. This is only used if there is no value for
+# template.homepage. This is for use when you are not using a
+# templating system such as Velocity or JSP.
+#
+# Default: Login
+
+screen.homepage=
+
+# This is the template that is shown on an incorrect login attempt.
+# Setting this property will override any value of screen.login specified
+# below.
+#
+# Default: Login.vm
+
+template.login=Login.vm
+
+# This is the page that is shown on an incorrect login attempt. It is
+# referenced in the LoginUser action. This is only used if there is no value
+# for template.login. This is for use when you are not using a
+# templating system such as Velocity or JSP.
+#
+# Default: Login
+
+screen.login=
+
+# This is the template that is used by the respective Template based
+# ErrorScreen for displaying the error. If you are not using a Template based
+# ErrorScreen, then this is ignored.
+#
+# Default: Error.vm
+
+template.error=Error.vm
+
+# This is the default error screen.
+#
+# Default: VelocityErrorScreen
+
+screen.error=VelocityErrorScreen
+
+# This is the screen that is displayed when the user's web page is in
+# an invalid state.
+#
+# Default: error.InvalidState
+
+screen.invalidstate=error.InvalidState
+
+# Set the components of the default Doctype for use in html documents.
+#
+# Defaults: There are no defaults - if default.html.doctype.root.element is not
+# set then no default doctype will be available.
+
+default.html.doctype.root.element=HTML
+default.html.doctype.identifier=-//W3C//DTD HTML 4.01 Transitional//EN
+default.html.doctype.url=http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd
+
+# This is the default action to log a user in. If you write your own
+# implementation of the login action, make sure that you change this
+# to reflect the new name.
+
+action.login=LoginUserIntake
+
+# This is the default action to log a user out. If you write your own
+# implementation of the logout action, make sure that you change this
+# to reflect the new name.
+
+action.logout=LogoutUser
+
+# This is the default action to validate whether or not a session is
+# valid. For example, if you want to make sure if a user has already
+# logged in or not.
+#
+# Default: SessionValidator
+
+action.sessionvalidator=sessionvalidator.TemplateSessionValidator
+
+#
+# Use this setting if you want your application to display the Login Screen
+# as first action and does not allow any operation before the user has
+# logged in
+#
+# action.sessionvalidator=sessionvalidator.TemplateSecureSessionValidator
+
+# This is the timeout in seconds for sessions. If left commented out, the
+# servlet container's default timeout will be left as is.
+
+# session.timeout=1800
+
+# This is the default action that builds up the AccessControlList for
+# the individual users session.
+
+action.accesscontroller=AccessController
+
+#
+# Set this value to true if you want to be able to submit multiple
+# events to an Action by doing eventSubmit_do<action> and consider
+# only events that have a non-empty, non-zero value. This is useful
+# if you submit your form with JavaScript
+#
+action.eventsubmit.needsvalue = false
+
+# If the web container does not supply an explicit encoding for the
+# request data, assume that is has this encoding. If you use e.g.
+# UTF-8 or ISO-8859-<something>, change this parameter to keep your
+# special characters. Default is ISO-8859-1
+input.encoding=UTF-8
+
+
+# -------------------------------------------------------------------
+#
+# J N D I C O N T E X T S
+#
+# -------------------------------------------------------------------
+
+# This indicates whether Turbine should try to create JNDI contexts.
+#
+# Default: false
+#
+# contexts=true
+
+# These are the JNDI context properties. Each context's properties
+# are defined by the properties beginning with context.name.
+#
+# Default: none
+#
+# Example: The following will create a JNDI context named "name" in
+# the data.contexts Hashtable. It will point at the RMI registry on
+# localhost running on port 1099, and will use
+# com.sun.jndi.rmi.registry.RegistryContextFactory as the initial
+# context factory:
+#
+# context.name.java.naming.provider.url=rmi://localhost:1099
+# context.name.java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory
+
+# -------------------------------------------------------------------
+#
+# M E S S A G E S
+#
+# -------------------------------------------------------------------
+# Note that strings containing "," (comma) characters must backslash
+# escape the comma (i.e. '\,')
+
+# The message that can be displayed before a user logs in.
+
+login.message=Thank you for your visit. Please log into the system.
+
+# The message that can be displayed when no screen is defined.
+
+login.message.noscreen=There has been an error. Your session is valid but the screen variable is not defined.
+
+# The message that can be displayed when a user enters an incorrect
+# password or username.
+
+login.error=Sorry your username or password is incorrect!
+
+# The message that can be displayed when a user logs out.
+
+logout.message=Thank you for using the system. Please come back soon.
+
+# -------------------------------------------------------------------
+#
+# S E C U R E S O C K E T S L A Y E R
+#
+# -------------------------------------------------------------------
+# Whether the web server is able to use SSL. Links in Turbine can
+# check this property to determine if SSL can be used.
+#
+# Default: true
+# -------------------------------------------------------------------
+
+use.ssl=true
+
+# -------------------------------------------------------------------
+#
+# S E R V I C E S
+#
+# -------------------------------------------------------------------
+# Classes for Turbine Services should be defined here.
+# Format: services.[name].classname=[implementing class]
+#
+# To specify properties of a service use the following syntax:
+# service.[name].[property]=[value]
+#
+# The order that these services is listed is important! The
+# order that is stated here is the order in which the services
+# will be initialized. Keep this is mind if you have services
+# that depend on other services during initialization.
+# -------------------------------------------------------------------
+services.AvalonComponentService.classname=org.apache.turbine.services.avaloncomponent.TurbineYaafiComponentService
+
+services.RunDataService.classname=org.apache.turbine.services.rundata.TurbineRunDataService
+services.ServletService.classname=org.apache.turbine.services.servlet.TurbineServletService
+services.AssemblerBrokerService.classname=org.apache.turbine.services.assemblerbroker.TurbineAssemblerBrokerService
+services.PullService.classname=org.apache.turbine.services.pull.TurbinePullService
+services.TemplateService.classname=org.apache.turbine.services.template.TurbineTemplateService
+services.UIService.classname = org.apache.turbine.services.ui.TurbineUIService
+services.VelocityService.classname=org.apache.turbine.services.velocity.TurbineVelocityService
+services.JsonRpcService.classname=org.apache.turbine.services.jsonrpc.TurbineJsonRpcService
+
+# -------------------------------------------------------------------
+#
+# R U N D A T A S E R V I C E
+#
+# -------------------------------------------------------------------
+# Default implementations of base interfaces for request processing.
+# Additional configurations can be defined by using other keys
+# in the place of the <default> key.
+# -------------------------------------------------------------------
+
+services.RunDataService.default.run.data=org.apache.turbine.services.rundata.DefaultTurbineRunData
+services.RunDataService.default.parameter.parser=org.apache.fulcrum.parser.DefaultParameterParser
+services.RunDataService.default.cookie.parser=org.apache.fulcrum.parser.DefaultCookieParser
+
+# -------------------------------------------------------------------
+#
+# A S S E M B L E R B R O K E R S E R V I C E
+#
+# -------------------------------------------------------------------
+# A list of AssemblerFactory classes that will be registered
+# with TurbineAssemblerBrokerService
+# -------------------------------------------------------------------
+
+services.AssemblerBrokerService.screen=org.apache.turbine.services.assemblerbroker.util.java.JavaScreenFactory
+services.AssemblerBrokerService.action=org.apache.turbine.services.assemblerbroker.util.java.JavaActionFactory
+services.AssemblerBrokerService.layout=org.apache.turbine.services.assemblerbroker.util.java.JavaLayoutFactory
+services.AssemblerBrokerService.page=org.apache.turbine.services.assemblerbroker.util.java.JavaPageFactory
+services.AssemblerBrokerService.navigation=org.apache.turbine.services.assemblerbroker.util.java.JavaNavigationFactory
+services.AssemblerBrokerService.scheduledjob=org.apache.turbine.services.assemblerbroker.util.java.JavaScheduledJobFactory
+
+# -------------------------------------------------------------------
+#
+# T E M P L A T E S E R V I C E
+#
+# -------------------------------------------------------------------
+
+# Roughly, the number of templates in each category.
+#
+# Defaults: layout=2, navigation=10, screen=50
+
+services.TemplateService.layout.cache.size=2
+services.TemplateService.navigation.cache.size=10
+services.TemplateService.screen.cache.size=50
+
+# -------------------------------------------------------------------
+#
+# P U L L S E R V I C E
+#
+# -------------------------------------------------------------------
+# These are the properties for the Pull Service, the service
+# that works in conjunction with the Turbine Pull Model API.
+# -------------------------------------------------------------------
+
+services.PullService.earlyInit= true
+
+# This determines whether the non-request tools are refreshed
+# on each request (request tools aren't ever, because they're
+# instantiated for the request only anyway).
+
+#services.PullService.tools.per.request.refresh=true
+
+# Path to the resources of the application tools, relative to the
+# application root
+
+services.PullService.tools.resources.dir=/resources/
+
+# These are tools that are placed in the context by the service
+# These tools will be made available to all your
+# templates. You list the tools in the following way:
+#
+# tool.<scope>.<id> = <classname>
+#
+# <scope> is the tool scope: global, request, session
+# or persistent (see below for more details)
+# <id> is the name of the tool in the context
+#
+# You can configure the tools in this way:
+# tool.<id>.<parameter> = <value>
+#
+# So if you find "global", "request", "session" or "persistent" as second
+# part, it is a configuration to put a tool into the toolbox, else it is a
+# tool specific configuration.
+#
+# For example:
+#
+# tool.global.ui = org.apache.turbine.util.pull.tools.UITool
+# tool.global.mm = org.apache.turbine.util.pull.MessageManager
+# tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink
+# tool.request.page = org.apache.turbine.util.template.HtmlPageAttributes
+#
+# Then:
+#
+# tool.ui.skin = default
+#
+# configures the value of "skin" for the "ui" tool.
+#
+# Tools are accessible in all templates by the <id> given
+# to the tool. So for the above listings the UITool would
+# be available as $ui, the MessageManager as $mm, the TemplateLink
+# as $link and the HtmlPageAttributes as $page.
+#
+# You should avoid using tool names called "global", "request",
+# "session" or "persistent" because of clashes with the possible Scopes.
+#
+# Scopes:
+#
+# global: tool is instantiated once and that instance is available
+# to all templates for all requests. Tool must be threadsafe.
+#
+# request: tool is instantiated once for each request (although the
+# PoolService is used to recycle instances). Tool need not
+# be threadsafe.
+#
+# session: tool is instantiated once for each user session, and is
+# stored in the user's temporary hashtable. Tool should be
+# threadsafe.
+#
+# authorized: tool is instantiated once for each user session once the
+# user logs in. After this, it is a normal session tool.
+#
+# Defaults: none
+
+tool.request.link=org.apache.turbine.services.pull.tools.TemplateLink
+tool.request.page=org.apache.turbine.util.template.HtmlPageAttributes
+tool.request.content=org.apache.turbine.services.pull.tools.ContentTool
+
+# Localization and Internationalization
+tool.request.l10n=org.apache.turbine.services.localization.LocalizationTool
+
+# This pull tool is to allow for easy formatting of Date object into Strings
+tool.request.dateFormatter=org.apache.turbine.services.pull.util.DateFormatter
+
+# Use this tool if you need a place to store data that will persist between
+# requests. Any data stored using this tool will be stored in the session.
+tool.session.sessionData=org.apache.turbine.services.pull.util.SessionData
+
+# These are intake tools.
+tool.request.intake=org.apache.turbine.services.intake.IntakeTool
+
+tool.request.related=${package}.services.pull.RelatedTool
+
+# This is a tool that allows access to the scheduler service.
+# tool.request.scheduler=org.apache.turbine.services.SchedulerTool
+
+# The UITool will allow you to skin your Turbine application using simple
+# properties files that are located in the WEBAPP/resources/ directory
+# hierarchy.
+tool.global.ui=org.apache.turbine.services.pull.tools.UITool
+
+# Path to the UI resources, relative to the resources directory defined above
+# tool.ui.dir.skin=/ui/skins
+
+# Path to the images of a skin, relative to the skin directory defined above
+# tool.ui.dir.image=/images
+
+# Default CSS file for a skin
+tool.ui.css=page.css
+
+# Default skin name
+# tool.ui.skin=default
+
+#
+# The ui tool normally returns absolute URIs.
+# Setting this property to true allows you to change the behavior if you
+# want only relative URIs (e.g. if you run behind a reverse proxy or a load
+# balancer).
+tool.ui.want.relative=true
+
+#
+# The content tool can put its URIs through the Servlet container,
+# which might attach things like the jsessionid even to URIs that
+# are not served by the container.
+#
+# The default behavior was not to put these through the container.
+#
+# Set this to true if you need things like jsessionid attached to all
+# links generated from the $content pull tool.
+#
+tool.content.want.encoding = false
+
+#
+# Both the link and the content tool normally return absolute URIs
+# You can change this by exchanging the tool classes but this is not
+# really recommended. Setting these properties to true allow you
+# to change the behaviour if you want only relative URIs (e.g. if you
+# run behind a reverse proxy or a load balancer).
+#
+tool.content.want.relative = true
+tool.link.want.relative = true
+
+# Flux tool
+tool.request.flux=${package}.flux.tools.FluxTool
+
+# -------------------------------------------------------------------
+#
+# V E L O C I T Y S E R V I C E
+#
+# -------------------------------------------------------------------
+
+# The location of Velocity configuration file, relative to webapp root
+# These properties will override the default properties set by Velocity.
+# You should specify the path to the templates directories as well as
+# the path to the log file and they should also be relative to webapp root
+
+services.VelocityService.template.extension=vm
+services.VelocityService.default.page = VelocityPage
+services.VelocityService.default.screen = VelocityScreen
+services.VelocityService.default.layout = VelocityOnlyLayout
+services.VelocityService.default.navigation = VelocityNavigation
+services.VelocityService.default.error.screen = VelocityErrorScreen
+services.VelocityService.default.layout.template = Default.vm
+
+#
+# Set this to true to catch Velocity Errors and display them in the log file
+services.VelocityService.catch.errors = true
+
+services.VelocityService.input.encoding=UTF-8
+
+#
+# Class Path Loader, Turbine jar
+services.VelocityService.velocimacro.library = macros/TurbineMacros.vm,macros/applicationMacros.vm
+
+# Set the following line to true to cause velocity to automatically reload
+# library macro files if they change. This is useful for debugging.
+services.VelocityService.velocimacro.library.autoreload = true
+
+services.VelocityService.resource.loader = file
+services.VelocityService.file.resource.loader.description = Velocity File Resource Loader
+services.VelocityService.file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
+services.VelocityService.file.resource.loader.path = /templates/app,/templates/flux
+services.VelocityService.file.resource.loader.cache = false
+services.VelocityService.file.resource.loader.modificationCheckInterval = 2
+
+services.VelocityService.resource.loader = classpath
+services.VelocityService.classpath.resource.loader.description = Velocity Classpath Resource Loader
+services.VelocityService.classpath.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
+
+# -------------------------------------------------------------------
+#
+# S C H E D U L E R S E R V I C E
+#
+# -------------------------------------------------------------------
+
+#
+# Set enabled to true to start the scheduler. The scheduler can be
+# stopped and started after Turbine has been initialized. See the
+# javadocs for org.apache.turbine.services.schedule.TurbineScheduler
+# for the methods calls.
+#
+# Default = false
+#
+
+services.SchedulerService.enabled=false
+
+# Determines if the scheduler service should be initialized early. This
+# Should always be set to true!!!!
+
+services.SchedulerService.earlyInit=true
+
+# -------------------------------------------------------------------
+#
+# S E C U R I T Y S E R V I C E
+#
+# -------------------------------------------------------------------
+
+# Configure Torque Security Service
+services.SecurityService.classname=org.apache.turbine.services.security.DefaultSecurityService
+services.SecurityService.user.manager = org.apache.turbine.services.security.DefaultUserManager
+
+services.SecurityService.user.class=org.apache.fulcrum.security.model.turbine.entity.impl.TurbineUserImpl
+# define custom wrapper
+services.SecurityService.wrapper.class = ${package}.wrapper.TurbineUserWrapper
+
+
+# -------------------------------------------------------------------
+#
+# A V A L O N C O M P O N E N T S E R V I C E
+#
+# -------------------------------------------------------------------
+# Components implementing the Avalon lifecycle interfaces can be loaded,
+# configured and initialized by Turbine
+# -------------------------------------------------------------------
+
+#
+# Name and location to the configuration file for the components.
+#
+services.AvalonComponentService.containerConfiguration = /WEB-INF/conf/containerConfiguration.xml
+#
+# Name and location to the configuration file for the component roles.
+#
+#services.AvalonComponentService.componentRoles = /WEB-INF/conf/roleConfiguration.xml
+#
+#services.AvalonComponentService.componentConfiguration = /WEB-INF/conf/componentConfiguration.xml
+
+# -------------------------------------------------------------------
+#
+# A D D I T I O N A L P R O P E R T I E S
+#
+# -------------------------------------------------------------------
+# The full path name to an additional properties file. Properties in
+# this file will be included in this property set. Duplicate name
+# values will be replaced, so be careful.
+#
+# Default: none
+# -------------------------------------------------------------------
+
+# Required to enable the flux library
+include=flux.properties
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/componentConfiguration.xml b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/componentConfiguration.xml
new file mode 100644
index 0000000..438eb5a
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/componentConfiguration.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+#*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*#
+<componentConfig>
+ <!-- Torque Component -->
+ <torque>
+ <configfile>/WEB-INF/conf/Torque.properties</configfile>
+ </torque>
+ <cache cacheInitialSize="20" cacheCheckFrequency="5"/>
+ <mimetype/>
+ <crypto>
+ <algorithm>
+ <unix>org.apache.fulcrum.crypto.provider.UnixCrypt</unix>
+ <clear>org.apache.fulcrum.crypto.provider.ClearCrypt</clear>
+ <java>org.apache.fulcrum.crypto.provider.JavaCrypt</java>
+ <oldjava>org.apache.fulcrum.crypto.provider.OldJavaCrypt</oldjava>
+ </algorithm>
+ </crypto>
+ <localization>
+ <bundles>
+ <bundle>${package}.L10N</bundle>
+ </bundles>
+ </localization>
+ <!-- Disable if you experience startup problems with Java8 -->
+ <intake>
+ <serialDataPath>WEB-INF/appData.ser</serialDataPath>
+ <xmlPaths>
+ <xmlPath>WEB-INF/conf/${turbine_intake_file}</xmlPath>
+ </xmlPaths>
+ </intake>
+ <factory/>
+ <pool/>
+ <parser>
+ <!-- <urlCaseFolding>lower</urlCaseFolding> -->
+ <parameterEncoding>utf-8</parameterEncoding>
+ <automaticUpload>true</automaticUpload>
+ </parser>
+ <!-- defining specific inspectors -->
+ <json>
+ <annotationInspectors>
+ <primary>org.apache.fulcrum.json.jackson.SimpleNameIntrospector</primary>
+ <secondary>com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector</secondary>
+ <features>
+ <feature value="false" type="com.fasterxml.jackson.databind.SerializationFeature">FAIL_ON_EMPTY_BEANS</feature>
+ <feature value="false" type="com.fasterxml.jackson.databind.SerializationFeature">INDENT_OUTPUT</feature>
+ <feature value="true" type="com.fasterxml.jackson.core.JsonParser">ALLOW_UNQUOTED_FIELD_NAMES</feature>
+ </features>
+ </annotationInspectors>
+ <dateFormat>MM/dd/yyyy</dateFormat>
+ <cacheFilters>true</cacheFilters>
+ <!-- security feature -->
+ <escapeCharsGlobal>true</escapeCharsGlobal>
+ <!-- escapeCharsClass>net.example.EscapeCharClass</escapeCharsClass -->
+ <defaultTyping type="OBJECT_AND_NON_CONCRETE" key="type"/><!-- defaultTyping type="NON_FINAL" key="type"/-->
+ <!-- requires com.jayway dependency in pom -->
+ <!-- useJsonPath>true</useJsonPath -->
+ </json>
+
+ <upload repository="/tmp" sizeMax="1048576" sizeThreshold="10240"/>
+ <!-- These components belong to the Fulcrum-Security services -->
+ <securityService/>
+ <authenticator/>
+ <!-- <authenticator>
+ <algorithm>java</algorithm>
+ <cipher>SHA1</cipher> </authenticator> -->
+
+ <modelManager/>
+ <aclFactory/>
+
+ <!--
+ Fulcrum Components, e.g. json, XmlRpcServerComponent, cft. Fulcrum Component Configurations
+ -->
+
+
+ <!--
+ Pure Fulcrum Model
+ -->
+ <!--
+ <userManager>
+ <className>org.apache.fulcrum.security.torque.om.TorqueTurbineUser</className>
+ </userManager>
+ <groupManager>
+ <className>org.apache.fulcrum.security.torque.om.TorqueTurbineGroup</className>
+ </groupManager>
+ <roleManager>
+ <className>org.apache.fulcrum.security.torque.om.TorqueTurbineRole</className>
+ </roleManager>
+ <permissionManager>
+ <className>org.apache.fulcrum.security.torque.om.TorqueTurbinePermission</className>
+ </permissionManager>
+ -->
+
+ <!--
+ Default classes implementing org.apache.fulcrum.security.model.turbine.entity interfaces
+ -->
+ <!--userManager>
+ <className>org.apache.fulcrum.security.model.turbine.entity.impl.TurbineUserImpl</className>
+ </userManager>
+ <groupManager>
+ <className>org.apache.fulcrum.security.model.turbine.entity.impl.TurbineGroupImpl</className>
+ </groupManager>
+ <roleManager>
+ <className>org.apache.fulcrum.security.model.turbine.entity.impl.TurbineRoleImpl</className>
+ </roleManager>
+ <permissionManager>
+ <className>org.apache.fulcrum.security.model.turbine.entity.impl.TurbinePermissionImpl</className>
+ </permissionManager -->
+
+ <!--
+ Custom Turbine ORM Torque classes could not yet be used:
+ - requires Torque 4.1 or if using Torque 4.0 reqires manually adding the interfaces in T-classes
+ - requires attribute baseClass in fulcrum-turbine-schema.xml table elements set to appropriate org.apache.fulcrum.security.model.turbine.entity interfaces
+ - requires attribute peerClass in fulcrum-turbine-schema.xml table elements set to org.apache.fulcrum.security.torque.peer.TorqueTurbinePeer
+ -->
+
+ <userManager>
+ <className>${package}.om.TurbineUser</className>
+ <peerClassName>${package}.om.TurbineUserPeerImpl</peerClassName>
+ <userGroupRoleManager><!-- using custom peers requires now since fulcrum security 1.1.2 this element -->
+ <!-- className>org.apache.fulcrum.security.torque.om.TurbineUserGroupRole</className-->
+ <peerClassName>${package}.om.TurbineUserGroupRolePeerImpl</peerClassName>
+ </userGroupRoleManager>
+ </userManager>
+ <groupManager><!-- might have lazy="true" attribute -->
+ <className>${package}.om.TurbineGroup</className>
+ <peerClassName>${package}.om.TurbineGroupPeerImpl</peerClassName>
+ </groupManager>
+ <roleManager><!-- might have lazy="true" attribute -->
+ <className>${package}.om.TurbineRole</className>
+ <peerClassName>${package}.om.TurbineRolePeerImpl</peerClassName>
+ </roleManager>
+ <permissionManager>
+ <className>${package}.om.TurbinePermission</className>
+ <peerClassName>${package}.om.TurbinePermissionPeerImpl</peerClassName>
+ </permissionManager>
+ <peerManager/>
+
+</componentConfig>
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/containerConfiguration.xml b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/containerConfiguration.xml
new file mode 100644
index 0000000..f676999
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/containerConfiguration.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+#*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*#
+<fulcrum-yaafi>
+ <containerFlavour>yaafi</containerFlavour>
+ <containerClazzName>org.apache.fulcrum.yaafi.framework.container.ServiceContainerImpl</containerClazzName>
+ <componentRoles>
+ <location>/WEB-INF/conf/roleConfiguration.xml</location>
+ <isEncrypted>false</isEncrypted>
+ </componentRoles>
+ <componentConfiguration>
+ <location>/WEB-INF/conf/componentConfiguration.xml</location>
+ <isEncrypted>false</isEncrypted>
+ </componentConfiguration>
+ <parameters>
+ <location>/WEB-INF/conf/parameters.properties</location>
+ <isEncrypted>false</isEncrypted>
+ </parameters>
+</fulcrum-yaafi>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/flux.properties b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/flux.properties
new file mode 100644
index 0000000..687afc8
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/flux.properties
@@ -0,0 +1,37 @@
+# -------------------------------------------------------------------
+#
+# F L U X S E R V I C E
+#
+# -------------------------------------------------------------------
+
+# ------------------------------------------------------------------------
+# Security Properties
+# ------------------------------------------------------------------------
+flux.admin.role = turbineadmin
+
+# ------------------------------------------------------------------------
+# Mode Properties
+# ------------------------------------------------------------------------
+# Flux can work in stand-alone mode and in embedded mode.
+# ------------------------------------------------------------------------
+
+flux.mode = embedded
+
+# ------------------------------------------------------------------------
+# Embedded Properties
+# ------------------------------------------------------------------------
+
+flux.embedded.layout = /Default.vm
+flux.embedded.show.menu = true
+
+# ------------------------------------------------------------------------
+# Stand-Alone Properties
+# ------------------------------------------------------------------------
+
+flux.stand.alone.layout = /FluxDefault.vm
+
+# ------------------------------------------------------------------------
+# UI Properties
+# ------------------------------------------------------------------------
+
+flux.ui.show.finder = false
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/intake.xml b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/intake.xml
new file mode 100644
index 0000000..7c00de2
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/intake.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+#*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*#
+
+<!-- ======================================================================== -->
+<!-- -->
+<!-- Default Intake file for Turbine Skeleton -->
+<!-- -->
+<!-- $Id: intake.xml 615350 2008-01-25 21:28:10Z tv $ -->
+<!-- -->
+<!-- ======================================================================== -->
+
+<input-data xmlns="http://turbine.apache.org/schema/intake/4.0"
+ basePackage="${package}.">
+ <group name="example" key="example" mapToObject="om.Table1">
+ <field name="TestCol2" key="testCol2" type="String"/>
+ </group>
+ <group name="Login" key="login">
+ <field name="Username" key="u" type="String">
+ <!-- l10n keys -->
+ <rule name="required" value="true">username_required_msg</rule>
+ <rule name="minLength" value="4">username_min_length_msg</rule>
+ <!--rule name="mask" value=".+@.+\..+">username_mask_msg</rule-->
+ </field>
+ <field name="Password" key="p" type="String">
+ <rule name="required" value="true">password_msg</rule>
+ </field>
+</group>
+</input-data>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/log4j.properties b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/log4j.properties
new file mode 100644
index 0000000..b1b2301
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/log4j.properties
@@ -0,0 +1,137 @@
+#*
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+*#
+##set($dollar = '$')
+##macro (var $label)${dollar}{${label}}#end
+# Turbine logging configuration
+#
+# If we don't know the logging facility, put it into the
+# turbine.log
+#
+log4j.rootLogger = INFO, app, console
+
+#
+# App log
+#
+log4j.logger.${package} = DEBUG, app
+log4j.additivity.${package} = false
+
+#
+# Avalon log
+#
+log4j.logger.avalon = DEBUG, app
+log4j.additivity.avalon = false
+
+#
+# Scheduler Category
+#
+log4j.logger.scheduler = INFO, app
+log4j.additivity.scheduler = false
+
+#
+# sql log
+# allows TRACE
+log4j.logger.org.apache.torque.util = DEBUG, sql, console
+log4j.additivity.org.apache.torque.util = false
+
+#
+# Torque log
+# allows TRACE
+log4j.logger.org.apache.torque = DEBUG, torque
+log4j.additivity.org.apache.torque = false
+
+#
+# Turbine goes into "turbine" loggers
+#
+log4j.logger.org.apache.turbine = DEBUG, turbine
+log4j.additivity.org.apache.turbine = false
+
+#
+# Velocity log
+#
+log4j.logger.velocity = INFO, velocity
+log4j.additivity.velocity = false
+
+# #######################################################################
+#
+# Logfile definitions
+#
+# #######################################################################
+
+#
+# Application.log
+#
+log4j.appender.app = org.apache.log4j.RollingFileAppender
+log4j.appender.app.MaxFileSize=5MB
+log4j.appender.app.MaxBackupIndex=5
+log4j.appender.app.file = ${applicationRoot}/logs/application.log
+log4j.appender.app.layout = org.apache.log4j.PatternLayout
+log4j.appender.app.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.app.append = false
+
+#
+# turbine.log
+#
+log4j.appender.turbine = org.apache.log4j.RollingFileAppender
+log4j.appender.turbine.MaxFileSize=5MB
+log4j.appender.turbine.MaxBackupIndex=5
+log4j.appender.turbine.file = ${applicationRoot}/logs/turbine.log
+log4j.appender.turbine.layout = org.apache.log4j.PatternLayout
+log4j.appender.turbine.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.turbine.append = false
+
+#
+# sql.log
+#
+log4j.appender.sql = org.apache.log4j.RollingFileAppender
+log4j.appender.sql.file = ${applicationRoot}/logs/sql.log
+log4j.appender.sql.MaxFileSize=5MB
+log4j.appender.sql.MaxBackupIndex=5
+log4j.appender.sql.layout = org.apache.log4j.PatternLayout
+log4j.appender.sql.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.sql.append = true
+
+#
+# console
+#
+log4j.appender.console = org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout = org.apache.log4j.PatternLayout
+log4j.appender.console.layout.conversionPattern = %d [%t] %-5p %C{1} - %m%n
+
+#
+# torque.log
+#
+log4j.appender.torque = org.apache.log4j.RollingFileAppender
+log4j.appender.torque.MaxFileSize=5MB
+log4j.appender.torque.MaxBackupIndex=5
+log4j.appender.torque.file = ${applicationRoot}/logs/torque.log
+log4j.appender.torque.layout = org.apache.log4j.PatternLayout
+log4j.appender.torque.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.torque.append = false
+
+#
+# Velocity gets configured to write its output onto the velocity
+# category.
+#
+log4j.appender.velocity = org.apache.log4j.RollingFileAppender
+log4j.appender.velocity.MaxFileSize=5MB
+log4j.appender.velocity.MaxBackupIndex=5
+log4j.appender.velocity.file = ${applicationRoot}/logs/velocity.log
+log4j.appender.velocity.layout = org.apache.log4j.PatternLayout
+log4j.appender.velocity.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.velocity.append = false
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/roleConfiguration.xml b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/roleConfiguration.xml
new file mode 100644
index 0000000..d4ea1a3
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/roleConfiguration.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+#*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*#
+<role-list>
+ <!-- Torque Component Role Configuration -->
+ <role name="org.apache.torque.avalon.Torque"
+ shorthand="torque"
+ default-class="org.apache.torque.avalon.TorqueComponent"
+ early-init = "true" />
+
+ <role
+ name="org.apache.fulcrum.cache.GlobalCacheService"
+ shorthand="cache"
+ default-class="org.apache.fulcrum.cache.impl.DefaultGlobalCacheService"/>
+
+ <role
+ name="org.apache.fulcrum.mimetype.MimeTypeService"
+ shorthand="mimetype"
+ default-class="org.apache.fulcrum.mimetype.DefaultMimeTypeService"/>
+
+ <role
+ name="org.apache.fulcrum.crypto.CryptoService"
+ shorthand="crypto"
+ default-class="org.apache.fulcrum.crypto.DefaultCryptoService"/>
+
+ <role
+ name="org.apache.fulcrum.localization.LocalizationService"
+ shorthand="localization"
+ default-class="org.apache.fulcrum.localization.DefaultLocalizationService"/>
+
+ <!-- Disable if you experience startup problems with Java8 -->
+ <role
+ name="org.apache.fulcrum.intake.IntakeService"
+ shorthand="intake"
+ default-class="org.apache.fulcrum.intake.IntakeServiceImpl"/>
+
+ <role
+ name="org.apache.fulcrum.factory.FactoryService"
+ shorthand="factory"
+ default-class="org.apache.fulcrum.factory.DefaultFactoryService"/>
+
+ <role
+ name="org.apache.fulcrum.pool.PoolService"
+ shorthand="pool"
+ default-class="org.apache.fulcrum.pool.DefaultPoolService"/>
+
+ <role
+ name="org.apache.fulcrum.upload.UploadService"
+ shorthand="upload"
+ default-class="org.apache.fulcrum.upload.DefaultUploadService"/>
+
+ <role
+ name="org.apache.fulcrum.parser.ParserService"
+ shorthand="parser"
+ default-class="org.apache.fulcrum.parser.DefaultParserService"/>
+
+ <!-- using Jackson as mapper by default -->
+ <role
+ name="org.apache.fulcrum.json.JsonService"
+ shorthand="json"
+ default-class="org.apache.fulcrum.json.jackson.Jackson2MapperService"/>
+
+ <role
+ name="org.apache.fulcrum.xslt.XSLTService"
+ shorthand="xslt"
+ default-class="org.apache.fulcrum.xslt.DefaultXSLTService"/>
+
+ <!-- These components belong to the Fulcrum-Security services -->
+ <role
+ name="org.apache.fulcrum.security.SecurityService"
+ shorthand="securityService"
+ default-class="org.apache.fulcrum.security.BaseSecurityService"/>
+
+ <role
+ name="org.apache.fulcrum.security.UserManager"
+ shorthand="userManager"
+ early-init="true"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbineUserManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.GroupManager"
+ shorthand="groupManager"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbineGroupManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.RoleManager"
+ shorthand="roleManager"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbineRoleManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.PermissionManager"
+ shorthand="permissionManager"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbinePermissionManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.torque.peer.PeerManager"
+ shorthand="peerManager"
+ default-class="org.apache.fulcrum.security.torque.peer.PeerManagerDefaultImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.ModelManager"
+ shorthand="modelManager"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbineModelManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.authenticator.Authenticator"
+ shorthand="authenticator"
+ default-class="org.apache.fulcrum.security.authenticator.TextMatchAuthenticator"/>
+
+ <role
+ name="org.apache.fulcrum.security.model.ACLFactory"
+ shorthand="aclFactory"
+ default-class="org.apache.fulcrum.security.model.turbine.TurbineACLFactory"/>
+
+
+ <!-- Add your services here -->
+
+</role-list>
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/turbine-classic-pipeline.xml b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/turbine-classic-pipeline.xml
new file mode 100644
index 0000000..bd8f3fd
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/turbine-classic-pipeline.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<pipeline>
+ <valves>
+ <valve>org.apache.turbine.pipeline.DetermineActionValve</valve>
+ <valve>org.apache.turbine.pipeline.DetermineTargetValve</valve>
+ <valve>org.apache.turbine.pipeline.DefaultSessionTimeoutValve</valve>
+ <valve>org.apache.turbine.pipeline.DefaultLoginValve</valve>
+ <valve>org.apache.turbine.pipeline.DefaultSessionValidationValve</valve>
+ <valve>org.apache.turbine.pipeline.DefaultACLCreationValve</valve>
+ <valve>org.apache.turbine.pipeline.ExecutePageValve</valve>
+ <valve>org.apache.turbine.pipeline.CleanUpValve</valve>
+ <valve>org.apache.turbine.pipeline.DetermineRedirectRequestedValve</valve>
+ </valves>
+</pipeline>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/usersettings.properties b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/usersettings.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/conf/usersettings.properties
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/jetty-env.xml b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/jetty-env.xml
new file mode 100644
index 0000000..64f7b2c
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/jetty-env.xml
@@ -0,0 +1,15 @@
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+ <New id="Turbine" class="org.eclipse.jetty.plus.jndi.Resource">
+ <Arg></Arg> <!-- reference to WebAppContext requires jetty 9.x only -->
+ <Arg>${turbine_database_jndipath}</Arg>
+ <Arg>
+ <New class="org.apache.commons.dbcp.BasicDataSource">
+ <Set name="driverClassName">${turbine_database_driver}</Set>
+ <Set name="url">${turbine_database_url}${turbine_database_name}</Set>
+ <Set name="username">${turbine_database_user}</Set>
+ <Set name="password">${turbine_database_password}</Set>
+ <Set name="validationQuery">SELECT 1</Set>
+ </New>
+ </Arg>
+ </New>
+</Configure>
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/web.xml b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ac18069
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<web-app id="WebApp_ID" version="2.5"
+ xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+<!-- ======================================================================== -->
+<!-- -->
+<!-- Web Application descriptor -->
+<!-- -->
+<!-- ======================================================================== -->
+
+<!-- ======================================================================== -->
+<!-- -->
+<!-- Uncomment the following block if you want to use the Session Service -->
+<!-- -->
+<!-- ======================================================================== -->
+<!--
+ <listener>
+ <listener-class>org.apache.turbine.services.session.SessionListener</listener-class>
+ </listener>
+-->
+
+ <servlet>
+ <description>${turbine_app_name}</description>
+ <servlet-name>Turbine</servlet-name>
+ <servlet-class>org.apache.turbine.Turbine</servlet-class>
+ <init-param>
+ <param-name>applicationRoot</param-name>
+ <param-value>webContext</param-value>
+ </init-param>
+ <init-param>
+ <param-name>loggingRoot</param-name>
+ <param-value>/.</param-value>
+ </init-param>
+ <init-param>
+ <param-name>properties</param-name>
+ <param-value>WEB-INF/conf/TurbineResources.properties</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Turbine</servlet-name>
+ <url-pattern>/app/*</url-pattern>
+ </servlet-mapping>
+
+<!-- ======================================================================== -->
+<!-- -->
+<!-- Redirect the home page of the application to the turbine servlet -->
+<!-- -->
+<!-- ======================================================================== -->
+
+ <welcome-file-list>
+ <welcome-file>app</welcome-file>
+ </welcome-file-list>
+
+
+ <!-- ======================================================================== -->
+<!-- -->
+<!-- JNDI Ressource -->
+<!-- ======================================================================== -->
+
+ <resource-ref>
+ <res-ref-name>${turbine_database_jndipath}</res-ref-name>
+ <res-type>javax.sql.DataSource</res-type>
+ <res-auth>Container</res-auth>
+ </resource-ref>
+
+<!-- ======================================================================== -->
+<!-- -->
+<!-- Make sure that templates and logs are not available through -->
+<!-- the servlet container. Remove security constraints or add an authen- -->
+<!-- tication role if you need access to these paths. -->
+<!-- -->
+<!-- ======================================================================== -->
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>templates</web-resource-name>
+ <url-pattern>/templates/*</url-pattern>
+ </web-resource-collection>
+ <web-resource-collection>
+ <web-resource-name>logs</web-resource-name>
+ <url-pattern>/logs/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint/>
+ </security-constraint>
+</web-app>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/pb-turbine100px.png b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/pb-turbine100px.png
new file mode 100644
index 0000000..5439b20
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/pb-turbine100px.png
Binary files differ
diff --git a/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/turbine-project.png b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/turbine-project.png
new file mode 100644
index 0000000..6d80184
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/turbine-project.png
Binary files differ
diff --git a/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/turbine4-project.png b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/turbine4-project.png
new file mode 100644
index 0000000..f19c013
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/images/turbine4-project.png
Binary files differ
diff --git a/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/page.css b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/page.css
new file mode 100644
index 0000000..420260e
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/page.css
@@ -0,0 +1,121 @@
+/*
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+*/
+
+book {
+ display: flex;
+ flex-direction: column;
+}
+
+@supports(display: grid) {
+ book {
+ width: auto;
+ }
+}
+
+book:nth-of-type(2) {
+ grid-column: 2;
+ grid-row: 2 / span 2;
+}
+
+h3 {
+ order: 0;
+}
+
+footer {
+ background-color: #9E2064;
+ text-align: right;
+ padding-right: 20px;
+}
+
+section {
+ background-color: #dfe5e8;
+ display: grid;
+ grid-template: [header-left] "head head" 30px [header-right]
+ [main-left] "nav main" 1fr [main-right]
+ [gridfooter-left] "nav foot" 30px [gridfooter-right];
+ grid-gap: 0.5em;
+ width: 100%;
+ height: 250px;
+}
+
+section:after {
+ clear: both;
+ content: "";
+ display: table;
+}
+
+header {
+ background-color: #F69923;
+ grid-area: head;
+}
+
+nav {
+ background-color: #F79A23;
+ grid-area: nav;
+}
+
+main {
+ background-color: #E97826;
+ grid-area: main;
+}
+
+gridfooter {
+ background-color: #9E2064;
+ text-align: center;
+ grid-column: foot;
+}
+
+.tabs-nav-container {
+ display: flex;
+ flex-direction: column;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.tabs-nav {
+ text-align: center;
+}
+
+.tabs-nav:hover {
+ color: #6d6d6d;
+}
+
+.tabs-nav.is-active {
+ color: white;
+ background-color: #C92037;
+ min-width: 400px;
+}
+
+.tabs-nav span {
+ display: none;
+}
+
+.tab {
+ display: none;
+ background-color: #dfe5e8;
+}
+
+.tab.is-active {
+ display: block;
+}
+
+.tab-content {
+ padding: 0.5em;
+}
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/page.js b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/page.js
new file mode 100644
index 0000000..e3e0bdd
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/page.js
@@ -0,0 +1,21 @@
+/*
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+*/
+(function() {
+ //TODO
+})();
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/skin.props b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/skin.props
new file mode 100644
index 0000000..dde7066
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/resources/ui/skins/default/skin.props
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Configuration file for the user interface
+bgcolor=#023262
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/layouts/Default.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/layouts/Default.vm
new file mode 100644
index 0000000..798ecba
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/layouts/Default.vm
@@ -0,0 +1,58 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+
+$page.addStyleSheet("http://www.w3schools.com/lib/w3.css")
+$page.addStyleSheet("http://www.w3schools.com/lib/w3-theme-blue-grey.css")
+$page.setTitle("Sample Apache Turbine Application")
+$page.addScript($ui.getScript("page.js"))
+<html>
+
+#TurbineHtmlHead()
+
+<link href="$ui.getStylecss()" rel="stylesheet" type="text/css" />
+
+<body #TurbineHtmlBodyAttributes() class="w3-theme-l4">
+
+ <div class="w3-wrapper">
+
+ <!-- Header -->
+ <header class="w3-container w3-center w3-padding-32 w3-theme">
+ <img class="w3-right" src="$ui.image('turbine4-project.png')" />
+ #if ( $data.getUser().hasLoggedIn() )
+ #set ( $u = $data.getUser() )
+ <div class="w3-right">
+ <h5>Hello $!u.FirstName</h5>
+ </div>
+ #end
+ </header>
+
+ <!-- Default Menu -->
+ $navigation.setTemplate("/Menu.vm")
+
+ <!-- Content -->
+ <div class="w3-left w3-padding" id="content">
+ $screen_placeholder
+ </div>
+
+ <!-- Footer -->
+ <footer class="w3-bottom">
+ <p>Powered by <img src="$ui.image('pb-turbine100px.png')"/></p>
+ </footer>
+ </div>
+
+</body>
+</html>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/macros/applicationMacros.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/macros/applicationMacros.vm
new file mode 100644
index 0000000..9acccea
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/macros/applicationMacros.vm
@@ -0,0 +1,151 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+
+##
+## $Id: TurbineMacros.vm 222027 2016-10-20 16:11:37Z painter $
+##
+## Put your Application macros in this file.
+##
+
+#* ------------------------------------------------------------------
+# Global Macros
+*# ------------------------------------------------------------------
+
+#* ------------------------------------------------------------------
+# Drop down select option for yes/no questions
+*# ------------------------------------------------------------------
+#macro (selectYesNo $label $selection)
+ <select name="$label">
+ #if ( $selection == "true" )
+ <option value="1" selected>Yes</option>
+ <option value="0">No</option>
+ #else
+ <option value="1">Yes</option>
+ <option value="0" selected>No</option>
+ #end
+ </select>
+#end
+
+
+#* ------------------------------------------------------------------
+# Standard action form controls - Using w3.css styling
+*# ------------------------------------------------------------------
+
+#macro (insert)
+ <input type="submit" name="eventSubmit_doInsert" value="Insert"/>
+#end
+
+#macro (save)
+ <input type="submit" name="eventSubmit_doUpdate" value="Update"/>
+#end
+
+#macro (remove)
+ <input type="submit" name="eventSubmit_doDelete" value="Remove"/>
+#end
+
+
+#macro (warning $msg)
+<div class="w3-panel w3-orange w3-card-8">
+ $msg
+</div>
+#end
+
+#macro (error $msg)
+<div class="w3-panel w3-red w3-card-8">
+ $msg
+</div>
+#end
+
+#macro(info $msg)
+<div class="w3-panel w3-blue w3-card-8">
+ $msg
+</div>
+#end
+
+
+#* ------------------------------------------------------------------
+#
+# Macros that are used for displaying input forms. Using w3.css styling
+#
+*# ------------------------------------------------------------------
+
+#macro (formLabel $label)
+ <label>$!label</label>
+#end
+
+#macro (fileUpload $label $name)
+ <label>$!label</label>
+ <input class="w3-input" type="file" name="$!name">
+#end
+
+#macro (formCheckBox $label $name $checked)
+ #formLabel( $label )
+ #checkBox( $name $checked )
+#end
+
+#macro (checkBox $name $checked)
+ <input id="$!name" class="w3-check" type="checkbox" checked="$!checked">
+#end
+
+#macro (formLabelRequired $label)
+ <label class="w3-label w3-validate">$!label</label>
+#end
+
+#macro (formTextField $name $value)
+ <input class="w3-input" type="text" name="$!name" value="$!value">
+#end
+
+#macro (smallFormTextField $name $value)
+ <input class="w3-input" type="text" name="$!name" value="$!value">
+#end
+
+#macro (textField $name $value)
+ <input class="w3-input" type="text" name="$!name" value="$!value">
+#end
+
+#macro (textareaField $label $name $value)
+ <p>
+ <label class="w3-label">$label</label>
+ <textarea class="w3-input" style="width:90%" rows="6" name="$name" required>$!value</textarea>
+ </p>
+
+#end
+
+#macro (formPasswordCell $label $name $value)
+ <p>
+ #formLabel( $label )
+ <input class="w3-input" type="password" name="$!name" value="$!value">
+ </p>
+#end
+
+#macro (formCellRequired $label $name $value)
+ <p>
+ #formLabelRequired($label)
+ #formTextField($name $value)
+ </p>
+#end
+
+#macro (formCell $label $name $value)
+ #formLabel($label)
+ #formTextField($name $value)
+#end
+
+#macro (smallFormCell $label $name $value)
+ #formLabel($label)
+ #smallFormTextField($name $value)
+#end
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/navigations/Menu.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/navigations/Menu.vm
new file mode 100644
index 0000000..ba6d0c7
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/navigations/Menu.vm
@@ -0,0 +1,52 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+
+
+#if ( $data.getUser().hasLoggedIn() )
+<nav class="w3-navbar w3-theme">
+ <li><a href="$link.setPage("Index.vm")">Home</a></li>
+ <li class="w3-dropdown-hover">
+ <a href="#">Administration <i class="fa fa-caret-down"></i></a>
+ <div class="w3-dropdown-content w3-white w3-card-4">
+ ## every user can change their password
+ <a href="$link.setPage("Password.vm")">Update Password <i class="fa fa-unlock"></i></a>
+ #if ( $data.getACL().hasRole("turbineadmin") )
+ <a href="$link.setPage("user,FluxUserList.vm")">User List <div class="w3-right"><i class="fa fa-users"></i></div></a>
+ <a href="$link.setPage("role,FluxRoleList.vm")">User Roles <div class="w3-right"><i class="fa fa-user-plus"></i></div></a>
+ <a href="$link.setPage("user,FluxUserForm.vm")?mode=insert">Add User <div class="w3-right"><i class="fa fa-user"></i></div></a>
+ #end
+ </div>
+ </li>
+ #if ( $data.getACL().hasRole("turbineuser") )
+ <li class="w3-dropdown-hover">
+ <a href="#">Records <i class="fa fa-caret-down"></i></a>
+ <div class="w3-dropdown-content w3-white w3-card-4">
+ <a href="$link.setAction("ShowRecords")">Show Records <i class="fa fa-unlock"></i></a>
+ </div>
+ </li>
+ #end
+
+ <li class="w3-right"><a href="$link.setAction("LogoutUser")">Logout</a></li>
+
+</nav>
+#else
+<nav class="w3-navbar w3-theme">
+ <li><a href="$link.setPage("Index.vm")">Home</a></li>
+ <li class="w3-right"><a href="$link.setPage("Login.vm")">Login</a></li>
+</nav>
+
+#end
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Error.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Error.vm
new file mode 100644
index 0000000..897e5f1
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Error.vm
@@ -0,0 +1,7 @@
+E R R O R
+
+$message
+
+$error
+
+$exception
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Index.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Index.vm
new file mode 100644
index 0000000..578e66f
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Index.vm
@@ -0,0 +1,45 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+
+
+
+#if ( $data.getMessage() )
+ #info( $data.getMessage() )
+#end
+
+#if ($!success) <div align="center"><h1>$success</h1></div>
+ <p>
+ You're now successfully running a <a href="http://turbine.apache.org/">Turbine</a> based
+ application, deployed to <font color="red">$data.ServerData.ContextPath</a></font> on
+ your web container.
+ </p>
+
+ <p>
+ You can (and should!) change or remove this page at any time. It is
+ intended to give you immediate feedback if you just deployed an newly
+ setup Turbine application.
+ </p>
+#end
+
+ ## including a secured does not trigger the security check, as it is just handled by velocity, not turbine
+ #parse("/screens/TestSecure.vm")
+
+ ## trigger the security check, but without all context
+ ## <a href="$link.setPage("TestSecure.vm")">Test a secure access without context</a>
+ ## trigger the security check
+ <a href="$link.setPage("TestSecure.vm").addPathInfo("action","SecureAction")">Test a secure access with context</a>
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Login.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Login.vm
new file mode 100644
index 0000000..7a9b423
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Login.vm
@@ -0,0 +1,104 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+
+##
+## If you want to use intake to process the data, uncomment below
+##
+
+#set ( $loginGroup = $intake.Login.Default )
+
+#set ( $valid = true )
+#if (!$loginGroup.Username.isValid() )
+ ## this should be improved ...
+ #if ("$loginGroup.Username.Message" == "username_min_length_msg")
+ #info( $l10n.format("$loginGroup.Username.Message","4") )
+ #else
+ #info( $l10n.get("$loginGroup.Username.Message") )
+ #end
+ #set ( $valid = false )
+ #end
+
+ #if ( !$loginGroup.Password.isValid() )
+ #info( $l10n.get("$loginGroup.Password.Message") )
+ #set ( $valid = false )
+ #end
+
+<p/>
+ #if (! $data.user.hasLoggedIn())
+
+ <div class="w3-display-middle w3-card-8 w3-center w3-light-grey" style="max-width: 500px">
+
+ <form class="w3-container w3-light-grey" name="login" method="post" enctype="application/x-www-form-urlencoded" action="$link.setAction("LoginUserIntake").setPage($data.templateInfo.screenTemplate)">
+ <div class="w3-section">
+
+ <p>
+ <input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="Username" type="text" name="$loginGroup.Username.Key" value="$!loginGroup.Username" tabindex="1" autocomplete="off" autofocus="">
+ </p>
+
+ <p>
+ <input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="Password" type="password" name="$loginGroup.Password.Key" value="" tabindex="2" autocomplete="off">
+ </p>
+
+ <button type="submit" name="submit" id="submit" value="eventSubmit_doPerform" class="w3-ripple" tabindex="3">#if (! $valid ) Retry #else Sign in #end</button>
+
+ <p/>
+ ##$intake.declareGroups()
+
+ </div>
+ </form>
+
+ <!-- default login without Intake -->
+ <!--
+ <form class="w3-container w3-light-grey" name="login" method="post" action="$link.setAction("LoginUser").setPage($data.templateInfo.screenTemplate)">
+ <div class="w3-section">
+
+ <p>
+ <input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="Username" type="text" name="username" value="" tabindex="1" autocomplete="off" autofocus="">
+ </p>
+
+ <p>
+ <input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="Password" type="password" name="password" value="" tabindex="2" autocomplete="off">
+ </p>
+
+ <button type="submit" name="submit" id="submit" value="eventSubmit_doPerform" class="w3-ripple" tabindex="3">Sign in</button>
+
+ <p/>
+
+ </div>
+ </form>
+
+
+
+ -->
+
+
+ <div class="w3-container w3-border-top w3-padding-16 w3-light-grey">
+ <span class="w3-right w3-padding w3-hide-small">Forgot <a href="#">password?</a></span>
+ </div>
+
+ ## Display System messages here if there are any
+ #if($data.getMessage())
+ #info( $data.getMessage() ) <br/>
+ #end
+
+
+ </div>
+ #else
+ #parse("/screens/Index.vm")
+ #end
+
+## $intake.declareGroups()
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Password.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Password.vm
new file mode 100644
index 0000000..c5c2b83
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/Password.vm
@@ -0,0 +1,56 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+
+
+ <div class="w3-display-middle w3-card-8 w3-center w3-light-grey" style="max-width: 500px">
+
+ <form class="w3-container w3-light-grey" name="password_change" method="post" action="$link.setAction("ChangePasswordAction").setPage("Index.vm")">
+ <div class="w3-section">
+
+
+ <p>
+ <input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="Old Password" type="password" name="oldpassword" value="" tabindex="2" autocomplete="off">
+ </p>
+
+ <p>
+ <input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="New Password" type="password" name="newpassword" value="" tabindex="2" autocomplete="off">
+ </p>
+
+ <button type="submit" name="submit" id="submit" value="eventSubmit_doPerform" class="w3-ripple">Change Password</button>
+
+ <button type="button" name="cancel" id="cancel" value="cancel" class="w3-ripple" onCLick="doCancel()">Cancel</button>
+
+ <script>
+ function doCancel() {
+ location.href="$link.setPage('TestSecure.vm')";
+ return false;
+ }
+ </script>
+
+ <p/>
+
+
+ </div>
+ </form>
+
+
+ ## Display System messages here if there are any
+ #if($data.getMessage())
+ #info( $data.getMessage() ) <br/>
+ #end
+
+ </div>
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/TestSecure.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/TestSecure.vm
new file mode 100644
index 0000000..dc2ffed
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/TestSecure.vm
@@ -0,0 +1,27 @@
+#if ( $data.getMessage() )
+ #info( $data.getMessage() )
+#end
+
+## its null for anon
+#if ( $!related.getUserrole() )
+<h1> Secured #if ($!user) User#else Role #end Access Page </h1>
+ #if ($!user && $!success)<div align="center"><h1>$success</h1></div>#end
+ <p>
+ #if ($user)
+ Hi "$user.firstName, $user.lastName"
+ #else
+ Role: $related.getUserrole()
+ #end
+ <script type="text/javascript">
+ var jsonObject;
+ #if ($user)
+ jsonObject = $related.getJson($user,"org.apache.turbine.om.security.User", null, true,"lastLogin", "permStorage");
+ if (jsonObject != undefined && jsonObject.permStorage == undefined) {
+ alert("successfully read JSON:" + jsonObject.lastLogin);
+ } else {
+ alert("error json object not as expected" + JSON.stringify(jsonObject));
+ }
+ #end
+ </script>
+ </p>
+#end
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/showRecords.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/showRecords.vm
new file mode 100644
index 0000000..b4a5618
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/app/screens/showRecords.vm
@@ -0,0 +1,51 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+ <div id="tabs" class="no-js">
+ #foreach ($author in $authors)
+ <div class="tabs-nav-container">
+ <a href="#" class="tabs-nav #if($velocityCount ==1)is-active#end">$author.firstName $author.lastName</a>
+ </div>
+ #end
+ #foreach ($author in $authors)
+ <div class="tab #if($velocityCount ==1)is-active#end">
+ <div class="tab-content">
+ <section>
+ <header>Author´s Book Record Box</header>
+ <nav>$author.firstName $author.lastName</nav>
+ #set($books = $author.books)
+ <main>
+ #foreach ($book in $books)
+ <book><a href="#">
+ $book.title
+ </a> (subject: $book.subject)
+ </book>
+ #end
+ </main>
+ <footer>$velocityCount</footer>
+ </section>
+ </div>
+ </div>
+ #end
+
+ </div>
+
+ <p>Authors: $authors.size()</p>
+
+ <script>
+ /*
+ */
+</script>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/layouts/FluxDefault.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/layouts/FluxDefault.vm
new file mode 100644
index 0000000..32f5bef
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/layouts/FluxDefault.vm
@@ -0,0 +1,30 @@
+<table class="w3-table">
+ <tr>
+ <td colspan="2" align="left">
+ $navigation.setTemplate("/FluxTop.vm")
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <hr noshade size="1">
+ </td>
+ </tr>
+ <tr>
+ <td width="10%" valign="top" align="left">
+ $navigation.setTemplate("/FluxMenu.vm")
+ </td>
+ <td width="*" valign="center">
+ $screen_placeholder
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <hr noshade size="1">
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ $navigation.setTemplate("/FluxBottom.vm")
+ </td>
+ </tr>
+</table>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/macros/fluxMacros.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/macros/fluxMacros.vm
new file mode 100644
index 0000000..9acccea
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/macros/fluxMacros.vm
@@ -0,0 +1,151 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+
+##
+## $Id: TurbineMacros.vm 222027 2016-10-20 16:11:37Z painter $
+##
+## Put your Application macros in this file.
+##
+
+#* ------------------------------------------------------------------
+# Global Macros
+*# ------------------------------------------------------------------
+
+#* ------------------------------------------------------------------
+# Drop down select option for yes/no questions
+*# ------------------------------------------------------------------
+#macro (selectYesNo $label $selection)
+ <select name="$label">
+ #if ( $selection == "true" )
+ <option value="1" selected>Yes</option>
+ <option value="0">No</option>
+ #else
+ <option value="1">Yes</option>
+ <option value="0" selected>No</option>
+ #end
+ </select>
+#end
+
+
+#* ------------------------------------------------------------------
+# Standard action form controls - Using w3.css styling
+*# ------------------------------------------------------------------
+
+#macro (insert)
+ <input type="submit" name="eventSubmit_doInsert" value="Insert"/>
+#end
+
+#macro (save)
+ <input type="submit" name="eventSubmit_doUpdate" value="Update"/>
+#end
+
+#macro (remove)
+ <input type="submit" name="eventSubmit_doDelete" value="Remove"/>
+#end
+
+
+#macro (warning $msg)
+<div class="w3-panel w3-orange w3-card-8">
+ $msg
+</div>
+#end
+
+#macro (error $msg)
+<div class="w3-panel w3-red w3-card-8">
+ $msg
+</div>
+#end
+
+#macro(info $msg)
+<div class="w3-panel w3-blue w3-card-8">
+ $msg
+</div>
+#end
+
+
+#* ------------------------------------------------------------------
+#
+# Macros that are used for displaying input forms. Using w3.css styling
+#
+*# ------------------------------------------------------------------
+
+#macro (formLabel $label)
+ <label>$!label</label>
+#end
+
+#macro (fileUpload $label $name)
+ <label>$!label</label>
+ <input class="w3-input" type="file" name="$!name">
+#end
+
+#macro (formCheckBox $label $name $checked)
+ #formLabel( $label )
+ #checkBox( $name $checked )
+#end
+
+#macro (checkBox $name $checked)
+ <input id="$!name" class="w3-check" type="checkbox" checked="$!checked">
+#end
+
+#macro (formLabelRequired $label)
+ <label class="w3-label w3-validate">$!label</label>
+#end
+
+#macro (formTextField $name $value)
+ <input class="w3-input" type="text" name="$!name" value="$!value">
+#end
+
+#macro (smallFormTextField $name $value)
+ <input class="w3-input" type="text" name="$!name" value="$!value">
+#end
+
+#macro (textField $name $value)
+ <input class="w3-input" type="text" name="$!name" value="$!value">
+#end
+
+#macro (textareaField $label $name $value)
+ <p>
+ <label class="w3-label">$label</label>
+ <textarea class="w3-input" style="width:90%" rows="6" name="$name" required>$!value</textarea>
+ </p>
+
+#end
+
+#macro (formPasswordCell $label $name $value)
+ <p>
+ #formLabel( $label )
+ <input class="w3-input" type="password" name="$!name" value="$!value">
+ </p>
+#end
+
+#macro (formCellRequired $label $name $value)
+ <p>
+ #formLabelRequired($label)
+ #formTextField($name $value)
+ </p>
+#end
+
+#macro (formCell $label $name $value)
+ #formLabel($label)
+ #formTextField($name $value)
+#end
+
+#macro (smallFormCell $label $name $value)
+ #formLabel($label)
+ #smallFormTextField($name $value)
+#end
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxBottom.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxBottom.vm
new file mode 100644
index 0000000..2e988c3
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxBottom.vm
@@ -0,0 +1,2 @@
+<font face="verdana,geneva,helvetica">
+</font>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxMenu.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxMenu.vm
new file mode 100644
index 0000000..2c4f800
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxMenu.vm
@@ -0,0 +1,16 @@
+## -----------------------------------------------------------------------
+## Menu.vm
+##
+## Main menu for the Turbine administration application.
+## -----------------------------------------------------------------------
+<font size="-1" face="$ui.sansSerifFonts">
+ <a href="$link.setPage("user,FluxUserList.vm")">Users</a>
+ <br>
+ <a href="$link.setPage("group,FluxGroupList.vm")">Groups</a>
+ <br>
+ <a href="$link.setPage("role,FluxRoleList.vm")">Roles</a>
+ <br>
+ <a href="$link.setPage("permission,FluxPermissionList.vm")">Permissions</a>
+ <p>
+ <a href="$link.setAction("FluxLogout").setPage("FluxLogin.vm")">Logout</a>
+</font>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxTop.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxTop.vm
new file mode 100644
index 0000000..ff1450c
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/navigations/FluxTop.vm
@@ -0,0 +1,3 @@
+<img src="$ui.image($ui.logo)">
+<font face="verdana,geneva,helvetica">
+</font>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxEmbeddedMenu.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxEmbeddedMenu.vm
new file mode 100644
index 0000000..3abf426
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxEmbeddedMenu.vm
@@ -0,0 +1,12 @@
+## -----------------------------------------------------------------------
+## Menu.vm
+##
+## Main menu for the Turbine administration application.
+## -----------------------------------------------------------------------
+<div class="w3-container">
+ <a href="$link.setPage("user,FluxUserList.vm")" class="w3-btn w3-round w3-white w3-border w3-border-blue">Users</a>
+ <a href="$link.setPage("group,FluxGroupList.vm")" class="w3-btn w3-round w3-white w3-border w3-border-blue">Groups</a>
+ <a href="$link.setPage("role,FluxRoleList.vm")" class="w3-btn w3-round w3-white w3-border w3-border-blue">Roles</a>
+ <a href="$link.setPage("permission,FluxPermissionList.vm")" class="w3-btn w3-round w3-white w3-border w3-border-blue">Permissions</a>
+</div>
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxError.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxError.vm
new file mode 100644
index 0000000..782f192
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxError.vm
@@ -0,0 +1,26 @@
+#**
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxError.vm,v 1.1.1.1 2003-06-19 23:07:21 painter Exp $
+
+*#
+
+$page.setBgColor($ui.bgcolor)
+$page.setTitle("")
+
+<font face="$ui.sansSerifFonts">
+
+The reason for the error was:
+<p>
+<pre>
+$processingException
+
+</pre>
+
+<P>
+The stacktrace is as follows:
+<pre>
+$stackTrace
+</pre>
+
+</font>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxIndex.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxIndex.vm
new file mode 100644
index 0000000..666a155
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxIndex.vm
@@ -0,0 +1,15 @@
+#**
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxIndex.vm,v 1.1.1.1 2003-06-19 23:07:21 painter Exp $
+
+*#
+
+$page.setBgColor($ui.bgcolor)
+$page.setTitle("Home Page")
+
+<font face="$ui.sansSerifFonts">
+
+This is the administration application.
+
+</font>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxLogin.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxLogin.vm
new file mode 100644
index 0000000..9d4e80a
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/FluxLogin.vm
@@ -0,0 +1,28 @@
+#**
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxLogin.vm,v 1.1.1.1 2003-06-19 23:07:21 painter Exp $
+
+*#
+
+$page.setTitle("Please Login")
+$page.setBgColor($ui.bgcolor)
+
+<form method="post" action="$link.setAction("FluxLogin").setPage("FluxIndex.vm")">
+ <table>
+ <tr>
+ #formCell ("User" "username" "")
+ </tr>
+ <tr>
+ #formPasswordCell ("Password" "password" "")
+ </tr>
+ <tr>
+ <td>
+ <font face="$ui.sansSerifFonts">
+ <input type="submit" value="Login">
+ </font>
+ </td>
+ </tr>
+ </table>
+</form>
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupAlreadyExists.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupAlreadyExists.vm
new file mode 100644
index 0000000..c8b7c55
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupAlreadyExists.vm
@@ -0,0 +1,13 @@
+#**
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@version $Id: FluxGroupAlreadyExists.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+<div class="w3-panel w3-red">
+The group name <b>$name</b> is currently is use. Group names
+must be unique, please choose another group name.
+</div>
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupForm.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupForm.vm
new file mode 100644
index 0000000..ec00606
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupForm.vm
@@ -0,0 +1,50 @@
+#**
+
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxGroupForm.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+
+#if ($errorTemplate)
+ #parse ($errorTemplate)
+#end
+
+
+<form
+ method="post"
+ action="$link.setPage("group,FluxGroupList.vm").setAction("group.FluxGroupAction")">
+
+ <table class="w3-table w3-striped w3-bordered">
+ <tr>
+ #formCell ("Group Name" "group" $!flux.Group.Name)
+ </tr>
+ </table>
+
+ #*
+ Check for a mode, the update and delete buttons
+ shouldn't appear when inserting a new user.
+ *#
+
+ #if ($flux.Mode == "modify")
+ <input type="hidden" name="oldName" value="$!flux.Group.Name">
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doUpdate" value="Update Group"/>
+ </div>
+ #elseif ($flux.Mode == "delete")
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doDelete" value="Confirm Deletion"/>
+ </div>
+ #else
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doInsert" value="Add Group"/>
+ </div>
+ #end
+
+</form>
+
+#if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+#end
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupList.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupList.vm
new file mode 100644
index 0000000..3b96ff8
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/group/FluxGroupList.vm
@@ -0,0 +1,43 @@
+#**
+
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxGroupList.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+$page.setTitle("Group Adminstration")
+$page.setBgColor($ui.bgcolor)
+
+#set ( $headings = ["Group Name"] )
+
+<div class="w3-container w3-padding"> <h2>Current Groups</h2> </div>
+
+<table class="w3-table w3-striped w3-bordered">
+ <tr>
+ #foreach ($heading in $headings)
+ <th>$heading</th>
+ #end
+ </tr>
+
+ #foreach ($group in $flux.Groups)
+ <tr>
+ <td>$group.Name</td>
+ <td>
+ <a href="$link.setPage("group,FluxGroupForm.vm").addPathInfo("group",$group.Name).addQueryData("mode","modify")">Details</a>
+ <a href="$link.setPage("group,FluxGroupForm.vm").addPathInfo("group",$group.Name).addQueryData("mode","delete")">Remove</a>
+ </td>
+ </tr>
+ #end
+</table>
+
+
+<div class="w3-container w3-padding w3-center">
+ <a class="w3-btn w3-blue w3-round" style="width: 180px;"
+ href="$link.setPage("group,FluxGroupForm.vm").addQueryData("mode","insert")">Add Group</a>
+</div>
+
+#if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+#end
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionAlreadyExists.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionAlreadyExists.vm
new file mode 100644
index 0000000..48f0f79
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionAlreadyExists.vm
@@ -0,0 +1,11 @@
+#**
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxPermissionAlreadyExists.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+<div class="w3-panel w3-red">
+The permission name <b>$name</b> is currently is use. Permission
+names must be unique, please choose another name.
+</div>
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionForm.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionForm.vm
new file mode 100644
index 0000000..5462737
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionForm.vm
@@ -0,0 +1,48 @@
+#**
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxPermissionForm.vm,v 1.1.1.1 2003-06-19 23:07:21 painter Exp $
+
+*#
+
+#if ($errorTemplate)
+ #parse ($errorTemplate)
+#end
+
+<form
+ method="post"
+ action="$link.setPage("permission,FluxPermissionList.vm").setAction("permission.FluxPermissionAction")">
+
+ <table class="w3-table w3-striped w3-bordered">
+ <tr>
+ #formCell ("Permission Name" "permission" $!flux.Permission.Name)
+ </tr>
+ </table>
+
+
+ #*
+ Check for a mode, the update and delete buttons
+ shouldn't appear when inserting a new user.
+ *#
+
+ #if ($flux.Mode == "modify")
+ <input type="hidden" name="oldName" value="$!flux.Permission.Name">
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doUpdate" value="Update Permission"/>
+ </div>
+ #elseif ($flux.Mode == "delete")
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doDelete" value="Confirm Deletion"/>
+ </div>
+ #else
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doInsert" value="Add Permission"/>
+ </div>
+ #end
+
+</form>
+
+#if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+#end
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionList.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionList.vm
new file mode 100644
index 0000000..72266eb
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxPermissionList.vm
@@ -0,0 +1,42 @@
+#**
+
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxPermissionList.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+## Load permissions
+#set ( $permissions = $flux.Permissions )
+
+<h2>All Permissions</h2>
+
+#set ( $headings = ["Permission Name"] )
+
+<table class="w3-table w3-bordered">
+ <tr>
+ #foreach ($heading in $headings)
+ <th>$heading</th>
+ #end
+ </tr>
+
+ #foreach ($permission in $permissions )
+ <tr>
+ <td> $permission.Name </td>
+ <td>
+ <a href="$link.setPage("permission,FluxPermissionForm.vm").addPathInfo("permission",$permission.Name).addQueryData("mode","modify")">Details</a>
+ <a href="$link.setPage("permission,FluxPermissionForm.vm").addPathInfo("permission",$permission.Name).addQueryData("mode","delete")">Remove</a>
+ </td>
+ </tr>
+ #end
+</table>
+
+<div class="w3-container w3-padding w3-center">
+ <a class="w3-btn w3-blue w3-round" style="width: 180px;"
+ href="$link.setPage("permission,FluxPermissionForm.vm").addQueryData("mode","insert")">Add New Permission</a>
+</div>
+
+#if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+#end
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxRolePermissionList.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxRolePermissionList.vm
new file mode 100644
index 0000000..aa2c8aa
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/permission/FluxRolePermissionList.vm
@@ -0,0 +1,56 @@
+#**
+
+This template is used to display the permissions
+for a role.
+
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxRolePermissionForm.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+#set ( $role = $flux.Role )
+
+## Load permissions
+#set ( $permissions = $flux.Permissions )
+<h2>Permissions for the $role.Name role</h2>
+
+<form method="post" action="$link.setAction("role.FluxRoleAction").setPage("role,FluxRoleList.vm")">
+
+ <input type="hidden" name="role" value="$role.Name">
+
+ <table class="w3-table w3-bordered">
+ <tr>
+ <th> Permission </th>
+ <th> Assign to Role </th>
+ </tr>
+
+ #foreach ($permission in $permissions)
+ <tr>
+ <td align="right"> <b>$!permission.Name</b> </td>
+ <td align="center">
+ #if ($role.Permissions.contains($permission))
+ #set ($checked = "checked")
+ #else
+ #set ($checked = "")
+ #end
+ <input type="checkbox" name="${role.Name}${permission.Name}" $checked>
+ </td>
+ </tr>
+ #end
+
+ <tr>
+ <td>
+ <input class="w3-button w3-blue" type="submit" name="eventSubmit_doPermissions" value="Update Permissions">
+ </td>
+ </tr>
+ </table>
+
+</form>
+
+#if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+#end
+
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleAlreadyExists.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleAlreadyExists.vm
new file mode 100644
index 0000000..775ce2e
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleAlreadyExists.vm
@@ -0,0 +1,16 @@
+#**
+
+Display this template when the administrator
+tries to add a user with a role that is
+already being used by the security system.
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxRoleAlreadyExists.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+<div class="w3-panel w3-red">
+The role name <b>$name</b> is currently in use. Role names
+must be unique, please choose another role name.
+</div>
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleForm.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleForm.vm
new file mode 100644
index 0000000..21ff042
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleForm.vm
@@ -0,0 +1,51 @@
+#**
+
+This template is used to display the details of
+a role.
+
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxRoleForm.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+#if ($errorTemplate)
+ #parse ($errorTemplate)
+#end
+
+<form
+ method="post"
+ action="$link.setPage("role,FluxRoleList.vm").setAction("role.FluxRoleAction")">
+
+ <table class="w3-table w3-striped w3-bordered">
+ <tr>
+ #formCell ("Role Name" "role" $!flux.Role.Name)
+ </tr>
+ </table>
+
+ #*
+ Check for a mode, the update and delete buttons
+ shouldn't appear when inserting a new user.
+ *#
+
+ #if ($flux.Mode == "modify")
+ <input type="hidden" name="oldName" value="$!flux.Role.Name">
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doUpdate" value="Update Role"/>
+ </div>
+ #elseif ($flux.Mode == "delete")
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doDelete" value="Confirm Deletion"/>
+ </div>
+ #else
+ <div class="w3-container w3-padding w3-center">
+ <input class="w3-btn w3-blue w3-round" style="width: 180px;" type="submit" name="eventSubmit_doInsert" value="Add Role"/>
+ </div>
+ #end
+
+</form>
+
+#if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+#end
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleList.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleList.vm
new file mode 100644
index 0000000..99da13b
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/role/FluxRoleList.vm
@@ -0,0 +1,42 @@
+#**
+
+Used to display the roles currently being used in
+the application.
+
+*#
+#set ( $headings = ["Role Name"] )
+
+<div class="w3-container w3-padding"> <h2>Current Roles</h2> </div>
+
+<table class="w3-table w3-striped w3-bordered">
+ <tr>
+ #foreach ($heading in $headings)
+ <th>$heading</th>
+ #end
+ </tr>
+
+ #foreach ($role in $flux.Roles)
+ #if ( $role.Name != "super_admin" )
+ <tr>
+ <td> $role.Name </td>
+ <td>
+ <a href="$link.setPage("permission,FluxRolePermissionList.vm").addPathInfo("role",$role.Name)">Permissions</a>
+ <a href="$link.setPage("role,FluxRoleForm.vm").addPathInfo("role",$role.Name).addQueryData("mode","modify")">Details</a>
+ <a href="$link.setPage("role,FluxRoleForm.vm").addPathInfo("role",$role.Name).addQueryData("mode","delete")">Remove</a>
+ </td>
+ </tr>
+ #end
+ #end
+
+</table>
+
+ <div class="w3-container w3-padding w3-center">
+ <a class="w3-btn w3-blue w3-round" style="width: 180px;"
+ href="$link.setPage("role,FluxRoleForm.vm").addQueryData("mode","insert")">Add New Role</a>
+ </div>
+
+
+#if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+#end
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxMissingRequiredInputs.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxMissingRequiredInputs.vm
new file mode 100644
index 0000000..534c640
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxMissingRequiredInputs.vm
@@ -0,0 +1,15 @@
+#*
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@version $Id: FluxMissingRequiredInputs.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+*#
+
+<div class="w3-panel w3-red">
+The following fields are required and must be entered before
+this request can be processed:
+<ul>
+#foreach ($missingRequiredInput in $missingRequiredInputs)
+ <li>$missingRequiredInput</li>
+#end
+</ul>
+</div>
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserAlreadyExists.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserAlreadyExists.vm
new file mode 100644
index 0000000..a2b3572
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserAlreadyExists.vm
@@ -0,0 +1,13 @@
+#*
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@version $Id: FluxUserAlreadyExists.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+<div class="w3-panel w3-red">
+The username <b>$username</b> is currently is use. Usernames
+must be unique for all users, please choose another username.
+</div>
+
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserForm.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserForm.vm
new file mode 100644
index 0000000..5858b11
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserForm.vm
@@ -0,0 +1,66 @@
+#**
+
+Display the details of a user.
+
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@version $Id: FluxUserForm.vm,v 1.10 2017-11-17 19:21:40 painter Exp $
+
+*#
+
+<!-- Primary edit screen -->
+<form
+ name="user"
+ method="post"
+ action="$link.setAction("user.FluxUserAction").setPage("user,FluxUserList.vm")">
+
+ #set ( $user = $flux.User )
+
+ <div class="w3-container w3-padding w3-gray">
+
+ <div class="w3-row-padding">
+
+ <!-- User Info -->
+ <div class="w3-half">
+ <div class="w3-card-8 w3-padding w3-white">
+ <div id="newUser" style="display: block;">
+ <h2>User Details</h2>
+ #formCell( "Username" "username" $!user.Name )
+ #formCell( "First Name" "firstName" $!user.FirstName )
+ #formCell( "Last Name" "lastName" $!user.LastName )
+ #formCell( "Email" "email" $!user.Email )
+ </div>
+ </div>
+ </div>
+ <div class="w3-half">
+ <div id="userPassword" class="w3-card-8 w3-padding w3-white">
+ <h2>Password</h2>
+
+ <p>
+ Password required for user to login. If you are just
+ updating a user's details, leave the password field
+ blank, otherwise, new password will be set
+
+ #formPasswordCell( "New Password" "password" "" )
+
+ </div>
+ </div>
+ </div>
+ </div>
+ <p>
+ #if ($flux.Mode == "modify")
+ <input type="submit" name="eventSubmit_doUpdate" value="Update User">
+ #elseif ($flux.Mode == "delete")
+ <input type="submit" name="eventSubmit_doDelete" value="Delete User">
+ #else
+ <input type="submit" name="eventSubmit_doInsert" value="Add User">
+ #end
+
+ <p>
+
+ #if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+ #end
+
+</form>
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserList.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserList.vm
new file mode 100644
index 0000000..cdc0d43
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserList.vm
@@ -0,0 +1,38 @@
+#set ( $headings = ["Username","First Name", "Last Name", "Email", "Admin" ] )
+
+
+<div class="w3-container w3-padding"> <h2>Current Users</h2> </div>
+
+<table class="w3-table w3-striped w3-bordered">
+ <tr>
+ #foreach ($heading in $headings)
+ <th>$heading</th>
+ #end
+ </tr>
+
+ #foreach ($user in $flux.getUsers() )
+ <tr>
+ <td>$!user.Name</td>
+ <td>$!user.FirstName</td>
+ <td>$!user.LastName</td>
+ <td><a href=mailto:$!user.Email>$!user.Email</a></td>
+ <td><a href="$link.setPage("user,FluxUserForm.vm").addQueryData("username","$user.Name").addQueryData("mode","modify")">Details</a>
+ <a href="$link.setPage("user,FluxUserRoleForm.vm").addQueryData("username","$user.Name").addQueryData("mode","modify")">Roles</a>
+ <a href="$link.setPage("user,FluxUserForm.vm").addQueryData("username","$user.Name").addQueryData("mode","delete")">Remove</a>
+ </td>
+ </tr>
+ #end
+
+</table>
+<p>
+ <div class="w3-container w3-padding w3-center">
+ <a class="w3-btn w3-blue w3-round" style="width: 180px;"
+ href="$link.setPage("user,FluxUserForm.vm").addQueryData("mode","insert")">Add
+ New User</a>
+ </div>
+
+#if ($showEmbeddedMenu)
+ <hr size="1" noshade>
+ #parse ("screens/FluxEmbeddedMenu.vm")
+#end
+
\ No newline at end of file
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserRoleForm.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserRoleForm.vm
new file mode 100644
index 0000000..e11ad78
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/flux/screens/user/FluxUserRoleForm.vm
@@ -0,0 +1,63 @@
+#**
+
+@author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+@author <a href="mailto:jeff@jivecast.com">Jeffery Painter</a>
+@version $Id: FluxUserRoleForm.vm,v 1.1.1.1 2017-11-26 23:07:21 painter Exp $
+
+*#
+
+#set ($user = $flux.User)
+#set ($acl = $flux.ACL)
+
+<h2>Roles for $user.FirstName $user.LastName</h2>
+
+<form method="post" action="$link.setAction("user.FluxUserAction").setPage("user,FluxUserList.vm")">
+
+<input type="hidden" name="username" value="$user.Name">
+<table class="w3-table w3-bordered">
+ <tr>
+ <th> </th>
+
+ #foreach ($role in $flux.Roles)
+ #if ( $role.Name != "super_admin" )
+ <th>
+ <b>$role.Name</b>
+ </th>
+ #end
+ #end
+
+ </tr>
+
+
+ #foreach ($group in $flux.Groups)
+ <tr>
+ <td>
+ <b>$group.Name</b>
+ </td>
+
+ #foreach ($role in $flux.Roles)
+ #if ( $role.Name != "super_admin" )
+ #if ($acl.hasRole($role, $group))
+ #set ($checked = "checked")
+ #else
+ #set ($checked = "")
+ #end
+
+ <td align="center">
+ <input type="checkbox" class="w3-checkbox" name="${group.Name}${role.Name}" $checked>
+ </td>
+ #end
+ #end
+
+ </tr>
+ #end
+
+ <tr>
+ <td>
+ <input type="submit" name="eventSubmit_doRoles" value="Update Roles">
+ </td>
+ </tr>
+
+</table>
+
+</form>
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/TorqueTest.properties b/src/main/resources/archetype-resources/src/test/conf/torque/TorqueTest.properties
new file mode 100644
index 0000000..5375724
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/TorqueTest.properties
@@ -0,0 +1,83 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+torque.applicationRoot = .
+#pipeline.default.descriptor = src/test/conf/torque/turbine-classic-pipeline.xml
+# torque.defaults.pool.defaultMaxActive=30
+torque.defaults.pool.testOnBorrow=true
+torque.defaults.pool.validationQuery=SELECT 1
+
+torque.idbroker.cleverquantity=true
+torque.idbroker.prefetch=true
+torque.idbroker.usenewconnection=true
+
+#torque.database.default=default
+torque.database.schema =
+
+# supported auto, hsqldb, mysql..
+#torque.database.default.adapter=hsqldb
+
+#torque.dsfactory.default.factory=org.apache.torque.dsfactory.SharedPoolDataSourceFactory
+
+#torque.dsfactory.default.pool.testOnBorrow=true
+#torque.dsfactory.default.pool.validationQuery=SELECT 1 from INFORMATION_SCHEMA.SYSTEM_USERS
+#torque.dsfactory.default.connection.driver = org.hsqldb.jdbcDriver
+#torque.dsfactory.default.connection.url = jdbc:hsqldb:.
+#torque.dsfactory.default.connection.user = sa
+#torque.dsfactory.default.connection.password =
+
+##################
+#
+# For JNDI configuration please see: https://db.apache.org/torque/torque-4.0/documentation/orm-reference/initialisation-configuration.html
+#
+#
+#torque.dsfactory.${turbine_database_name}.factory=org.apache.torque.dsfactory.JndiDataSourceFactory
+#torque.dsfactory.${turbine_database_name}.jndi.path=java:comp/env/${turbine_database_jndipath}
+#torque.dsfactory.${turbine_database_name}.jndi.ttl=300000
+
+# -------------------------------------------------------------------
+#
+# Shared Pool Data Source Factory
+#
+# -------------------------------------------------------------------
+#torque.database.default=turbine
+torque.database.${turbine_database_name}.adapter=${turbine_database_adapter}
+
+#torque.database.${turbine_database_name}.user=${turbine_database_user}
+#torque.database.${turbine_database_name}.password=${turbine_database_password}
+#
+#torque.defaults.pool.maxActive = 30
+#torque.defaults.pool.testOnBorrow = true
+#torque.defaults.pool.validationQuery = SELECT 1
+#
+#torque.defaults.connection.driver = ${turbine_database_driver}
+#torque.defaults.connection.url = ${turbine_database_url}${turbine_database_name}
+#torque.defaults.connection.user = ${turbine_database_user}
+#torque.defaults.connection.password = ${turbine_database_password}
+#
+torque.dsfactory.${turbine_database_name}.connection.driver = ${turbine_database_driver}
+torque.dsfactory.${turbine_database_name}.connection.url = ${turbine_database_url}${turbine_database_name}
+torque.dsfactory.${turbine_database_name}.connection.user = ${turbine_database_user}
+torque.dsfactory.${turbine_database_name}.connection.password = ${turbine_database_password}
+torque.dsfactory.${turbine_database_name}.factory=org.apache.torque.dsfactory.SharedPoolDataSourceFactory
+# -------------------------------------------------------------------
+
+# Comment if not using shared data source factory
+torque.database.default=${turbine_database_name}
+
+
+
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumComponentConfiguration.xml b/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumComponentConfiguration.xml
new file mode 100644
index 0000000..612e0a8
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumComponentConfiguration.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!--
+ This configuration file for Avalon components is used for testing the Fulcrum components
+ with Turbine.
+-->
+
+<componentConfig>
+ <!-- Torque Component -->
+ <torque>
+ <configfile>src/test/conf/torque/TorqueTest.properties</configfile>
+ </torque>
+ <cache cacheInitialSize="20" cacheCheckFrequency="5"/>
+ <mimetype/>
+ <crypto>
+ <algorithm>
+ <unix>org.apache.fulcrum.crypto.provider.UnixCrypt</unix>
+ <clear>org.apache.fulcrum.crypto.provider.ClearCrypt</clear>
+ <java>org.apache.fulcrum.crypto.provider.JavaCrypt</java>
+ <oldjava>org.apache.fulcrum.crypto.provider.OldJavaCrypt</oldjava>
+ </algorithm>
+ </crypto>
+
+ <factory/>
+ <pool/>
+ <parser>
+ <parameterEncoding>utf-8</parameterEncoding>
+ <automaticUpload>true</automaticUpload>
+ </parser>
+
+ <!-- These components belong to the Fulcrum-Security services -->
+ <securityService/>
+ <authenticator/>
+ <modelManager/>
+ <aclFactory/>
+
+ <userManager>
+ <className>${package}.om.TurbineUser</className>
+ <peerClassName>${package}.om.TurbineUserPeerImpl</peerClassName>
+ </userManager>
+ <groupManager>
+ <className>${package}.om.TurbineGroup</className>
+ <peerClassName>${package}.om.TurbineGroupPeerImpl</peerClassName>
+ </groupManager>
+ <roleManager>
+ <className>${package}.om.TurbineRole</className>
+ <peerClassName>${package}.om.TurbineRolePeerImpl</peerClassName>
+ </roleManager>
+ <permissionManager>
+ <className>${package}.om.TurbinePermission</className>
+ <peerClassName>${package}.om.TurbinePermissionPeerImpl</peerClassName>
+ </permissionManager>
+ <peerManager/>
+
+
+
+</componentConfig>
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumRoleConfiguration.xml b/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumRoleConfiguration.xml
new file mode 100644
index 0000000..9187ccb
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/fulcrumRoleConfiguration.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!--
+ This configuration file for Avalon components is used for testing the Fulcrum Components with
+ Turbine.
+-->
+
+<role-list>
+ <!-- Torque Component Role Configuration -->
+ <role name="org.apache.torque.avalon.Torque"
+ shorthand="torque"
+ default-class="org.apache.torque.avalon.TorqueComponent" />
+
+ <role
+ name="org.apache.fulcrum.cache.GlobalCacheService"
+ shorthand="cache"
+ default-class="org.apache.fulcrum.cache.impl.DefaultGlobalCacheService"/>
+
+ <role
+ name="org.apache.fulcrum.mimetype.MimeTypeService"
+ shorthand="mimetype"
+ default-class="org.apache.fulcrum.mimetype.DefaultMimeTypeService"/>
+
+ <role
+ name="org.apache.fulcrum.crypto.CryptoService"
+ shorthand="crypto"
+ default-class="org.apache.fulcrum.crypto.DefaultCryptoService"/>
+
+ <role
+ name="org.apache.fulcrum.localization.LocalizationService"
+ shorthand="localization"
+ default-class="org.apache.fulcrum.localization.DefaultLocalizationService"/>
+
+ <role
+ name="org.apache.fulcrum.factory.FactoryService"
+ shorthand="factory"
+ default-class="org.apache.fulcrum.factory.DefaultFactoryService"/>
+
+ <role
+ name="org.apache.fulcrum.pool.PoolService"
+ shorthand="pool"
+ default-class="org.apache.fulcrum.pool.DefaultPoolService"/>
+
+ <role
+ name="org.apache.fulcrum.parser.ParserService"
+ shorthand="parser"
+ default-class="org.apache.fulcrum.parser.DefaultParserService"/>
+
+ <role
+ name="org.apache.fulcrum.xslt.XSLTService"
+ shorthand="xslt"
+ default-class="org.apache.fulcrum.xslt.DefaultXSLTService"/>
+
+ <!-- These components belong to the Fulcrum-Security services -->
+ <role
+ name="org.apache.fulcrum.security.SecurityService"
+ shorthand="securityService"
+ default-class="org.apache.fulcrum.security.BaseSecurityService"/>
+
+<role
+ name="org.apache.fulcrum.security.UserManager"
+ shorthand="userManager"
+ early-init="true"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbineUserManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.GroupManager"
+ shorthand="groupManager"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbineGroupManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.RoleManager"
+ shorthand="roleManager"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbineRoleManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.PermissionManager"
+ shorthand="permissionManager"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbinePermissionManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.torque.peer.PeerManager"
+ shorthand="peerManager"
+ default-class="org.apache.fulcrum.security.torque.peer.PeerManagerDefaultImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.ModelManager"
+ shorthand="modelManager"
+ default-class="org.apache.fulcrum.security.torque.turbine.TorqueTurbineModelManagerImpl"/>
+
+ <role
+ name="org.apache.fulcrum.security.authenticator.Authenticator"
+ shorthand="authenticator"
+ default-class="org.apache.fulcrum.security.authenticator.TextMatchAuthenticator"/>
+
+ <role
+ name="org.apache.fulcrum.security.model.ACLFactory"
+ shorthand="aclFactory"
+ default-class="org.apache.fulcrum.security.model.turbine.TurbineACLFactory"/>
+
+
+
+</role-list>
+
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/turbine/CompleteTurbineResources.properties b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/CompleteTurbineResources.properties
new file mode 100644
index 0000000..d5de6fc
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/CompleteTurbineResources.properties
@@ -0,0 +1,631 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# resource relative to context
+pipeline.default.descriptor = /src/test/conf/torque/turbine/turbine-classic-pipeline.xml
+# -------------------------------------------------------------------
+#
+# L O G 4 J - L O G G I N G
+#
+# -------------------------------------------------------------------
+
+log4j.file = /src/test/resources/log4j.properties
+
+# -------------------------------------------------------------------
+#
+# M A I L S E R V E R
+#
+# -------------------------------------------------------------------
+# Your mail server for outgoing email.
+#
+# Default: null
+# -------------------------------------------------------------------
+
+mail.server=
+
+# -------------------------------------------------------------------
+# SMTP-From header for your outgoing messages
+#
+# All failed delivery messages will be returned to this address.
+# If unset, these messages will be sent to the address in the
+# From header (standard behaviour)
+#
+# Default: null
+# -------------------------------------------------------------------
+
+mail.smtp.from=
+
+# -------------------------------------------------------------------
+#
+# S E R V E R D A T A
+#
+# -------------------------------------------------------------------
+# Default ServerData that can be used if asked for before the first
+# request is made.
+#
+# Defaults:
+#
+# serverdata.default.serverName=
+# serverdata.default.serverPort=80
+# serverdata.default.serverScheme=http
+# serverdata.default.scriptName=
+# serverdata.default.contextPath=
+# -------------------------------------------------------------------
+
+serverdata.default.serverName=
+serverdata.default.serverPort=80
+serverdata.default.serverScheme=http
+serverdata.default.scriptName=
+serverdata.default.contextPath=
+
+# -------------------------------------------------------------------
+#
+# M O D U L E C A C H I N G
+#
+# -------------------------------------------------------------------
+# This determines whether or not to cache the modules in memory. For
+# development, turn this off. For production, turn this on.
+#
+# Default: false
+# -------------------------------------------------------------------
+
+module.cache=false
+
+# If module.cache=true, then how large should we make the hashtables
+# by default.
+
+action.cache.size=20
+layout.cache.size=10
+navigation.cache.size=10
+page.cache.size=5
+screen.cache.size=50
+scheduledjob.cache.size=10
+
+# -------------------------------------------------------------------
+#
+# M O D U L E P A C K A G E S
+#
+# -------------------------------------------------------------------
+# This is the "classpath" for Turbine. In order to locate your own
+# modules, you should add them to this path. For example, if you have
+# com.company.actions, com.company.screens, com.company.navigations,
+# then this setting would be "com.company,org.apache.turbine.modules".
+# This path is searched in order. For example, Turbine comes with a
+# screen module named "Login". If you wanted to have your own screen
+# module named "Login", then you would specify the path to your
+# modules before the others.
+#
+# Note: org.apache.turbine.modules will always be added to the search
+# path. If it is not explictly added here, it will be added to the
+# end.
+#
+# Default: org.apache.turbine.modules
+# -------------------------------------------------------------------
+
+module.packages=org.apache.turbine.modules, org.apache.turbine.services.template.modules, org.apache.turbine.services.template.modules.screens.existing.dflt
+
+# -------------------------------------------------------------------
+#
+# F R A M E W O R K S E T T I N G S
+#
+# -------------------------------------------------------------------
+# These are settings that control the behavior of the framework,
+# such as determining whether a template system is in use, what
+# the default templates and screens are and session handling settings.
+# -------------------------------------------------------------------
+
+# Used to set the template homepage if you are using a template
+# layout. This is the template that will be displayed to the user
+# when no specific template is requested. This is normally executed
+# as the first template the user sees when they access the system.
+#
+# Default: Index.vm
+
+template.homepage=Index.vm
+
+# This is the default screen to show to people when they first access
+# the system. This is only used if there is no value for
+# template.homepage. This is for use when you are not using a
+# templating system such as Velocity or JSP.
+#
+# Default: Login
+
+screen.homepage=
+
+# This is the template that is shown on an incorrect login attempt.
+# Setting this property will override any value of screen.login specified
+# below.
+#
+# Default: Login.vm
+
+template.login=Login.vm
+
+# This is the page that is shown on an incorrect login attempt. It is
+# referenced in the LoginUser action. This is only used if there is no value
+# for template.login. This is for use when you are not using a
+# templating system such as Velocity or JSP.
+#
+# Default: Login
+
+screen.login=
+
+# This is the template that is used by the respective Template based
+# ErrorScreen for displaying the error. If you are not using a Template based
+# ErrorScreen, then this is ignored.
+#
+# Default: Error.vm
+
+template.error=Error.vm
+
+# This is the default error screen.
+#
+# Default: VelocityErrorScreen
+
+screen.error=VelocityErrorScreen
+
+# This is the screen that is displayed when the user's web page is in
+# an invalid state.
+#
+# Default: error.InvalidState
+
+screen.invalidstate=error.InvalidState
+
+# Set the components of the default Doctype for use in html documents.
+#
+# Defaults: There are no defaults - if default.html.doctype.root.element is not
+# set then no default doctype will be available.
+
+default.html.doctype.root.element=HTML
+default.html.doctype.identifier=-//W3C//DTD HTML 4.01 Transitional//EN
+default.html.doctype.url=http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd
+
+# This is the default action to log a user in. If you write your own
+# implementation of the login action, make sure that you change this
+# to reflect the new name.
+
+action.login=LoginUser
+
+# This is the default action to log a user out. If you write your own
+# implementation of the logout action, make sure that you change this
+# to reflect the new name.
+
+action.logout=LogoutUser
+
+# This is the default action to validate whether or not a session is
+# valid. For example, if you want to make sure if a user has already
+# logged in or not.
+#
+# Default: SessionValidator
+
+action.sessionvalidator=sessionvalidator.TemplateSessionValidator
+
+# This is the timeout in seconds for sessions. If left commented out, the
+# servlet container's default timeout will be left as is.
+
+# session.timeout=1800
+
+# This is the default action that builds up the AccessControlList for
+# the individual users session.
+
+action.accesscontroller=AccessController
+
+#
+# Set this value to true if you want to be able to submit multiple
+# events to an Action by doing eventSubmit_do<action> and consider
+# only events that have a non-empty, non-zero value. This is useful
+# if you submit your form with JavaScript
+#
+action.eventsubmit.needsvalue = false
+
+# -------------------------------------------------------------------
+#
+# J N D I C O N T E X T S
+#
+# -------------------------------------------------------------------
+
+# This indicates whether Turbine should try to create JNDI contexts.
+#
+# Default: false
+#
+# contexts=true
+
+# These are the JNDI context properties. Each context's properties
+# are defined by the properties beginning with context.name.
+#
+# Default: none
+#
+# Example: The following will create a JNDI context named "name" in
+# the data.contexts Hashtable. It will point at the RMI registry on
+# localhost running on port 1099, and will use
+# com.sun.jndi.rmi.registry.RegistryContextFactory as the initial
+# context factory:
+#
+# context.name.java.naming.provider.url=rmi://localhost:1099
+# context.name.java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory
+
+# -------------------------------------------------------------------
+#
+# M E S S A G E S
+#
+# -------------------------------------------------------------------
+# Note that strings containing "," (comma) characters must backslash
+# escape the comma (i.e. '\,')
+
+# The message that can be displayed before a user logs in.
+
+login.message=Thank you for your visit. Please log into the system.
+
+# The message that can be displayed when no screen is defined.
+
+login.message.noscreen=There has been an error. Your session is valid but the screen variable is not defined.
+
+# The message that can be displayed when a user enters an incorrect
+# password or username.
+
+login.error=Sorry your username or password is incorrect!
+
+# The message that can be displayed when a user logs out.
+
+logout.message=Thank you for using the system. Please come back soon.
+
+# -------------------------------------------------------------------
+#
+# S E C U R E S O C K E T S L A Y E R
+#
+# -------------------------------------------------------------------
+# Whether the web server is able to use SSL. Links in Turbine can
+# check this property to determine if SSL can be used.
+#
+# Default: true
+# -------------------------------------------------------------------
+
+use.ssl=true
+
+# -------------------------------------------------------------------
+#
+# S E R V I C E S
+#
+# -------------------------------------------------------------------
+# Classes for Turbine Services should be defined here.
+# Format: services.[name].classname=[implementing class]
+#
+# To specify properties of a service use the following syntax:
+# service.[name].[property]=[value]
+#
+# The order that these services is listed is important! The
+# order that is stated here is the order in which the services
+# will be initialized. Keep this is mind if you have services
+# that depend on other services during initialization.
+# -------------------------------------------------------------------
+
+# Choose between the two available implementations of an Avalon container - ECM or YAAFI
+
+# services.AvalonComponentService.classname=org.apache.turbine.services.avaloncomponent.TurbineAvalonComponentService
+services.AvalonComponentService.classname=org.apache.turbine.services.avaloncomponent.TurbineYaafiComponentService
+
+services.RunDataService.classname=org.apache.turbine.services.rundata.TurbineRunDataService
+services.ServletService.classname=org.apache.turbine.services.servlet.TurbineServletService
+services.AssemblerBrokerService.classname=org.apache.turbine.services.assemblerbroker.TurbineAssemblerBrokerService
+services.UniqueIdService.classname=org.apache.turbine.services.uniqueid.TurbineUniqueIdService
+# Default
+services.SecurityService.classname=org.apache.turbine.services.security.DefaultSecurityService
+services.PullService.classname=org.apache.turbine.services.pull.TurbinePullService
+services.TemplateService.classname=org.apache.turbine.services.template.TurbineTemplateService
+services.UIService.classname = org.apache.turbine.services.ui.TurbineUIService
+# services.SessionService.classname=org.apache.turbine.services.session.TurbineSessionService
+
+# Turn on the appropriate template service.
+services.VelocityService.classname=org.apache.turbine.services.velocity.TurbineVelocityService
+
+# -------------------------------------------------------------------
+#
+# R U N D A T A S E R V I C E
+#
+# -------------------------------------------------------------------
+# Default implementations of base interfaces for request processing.
+# Additional configurations can be defined by using other keys
+# in the place of the <default> key.
+# -------------------------------------------------------------------
+
+services.RunDataService.default.run.data=org.apache.turbine.services.rundata.DefaultTurbineRunData
+services.RunDataService.default.parameter.parser=org.apache.fulcrum.parser.DefaultParameterParser
+services.RunDataService.default.cookie.parser=org.apache.fulcrum.parser.DefaultCookieParser
+
+# -------------------------------------------------------------------
+#
+# A S S E M B L E R B R O K E R S E R V I C E
+#
+# -------------------------------------------------------------------
+# A list of AssemblerFactory classes that will be registered
+# with TurbineAssemblerBrokerService
+# -------------------------------------------------------------------
+
+services.AssemblerBrokerService.screen=org.apache.turbine.services.assemblerbroker.util.java.JavaScreenFactory
+# services.AssemblerBrokerService.screen=org.apache.turbine.services.assemblerbroker.util.python.PythonScreenFactory
+services.AssemblerBrokerService.action=org.apache.turbine.services.assemblerbroker.util.java.JavaActionFactory
+services.AssemblerBrokerService.layout=org.apache.turbine.services.assemblerbroker.util.java.JavaLayoutFactory
+services.AssemblerBrokerService.page=org.apache.turbine.services.assemblerbroker.util.java.JavaPageFactory
+services.AssemblerBrokerService.navigation=org.apache.turbine.services.assemblerbroker.util.java.JavaNavigationFactory
+services.AssemblerBrokerService.scheduledjob=org.apache.turbine.services.assemblerbroker.util.java.JavaScheduledJobFactory
+
+# -------------------------------------------------------------------
+#
+# T E M P L A T E S E R V I C E
+#
+# -------------------------------------------------------------------
+
+# Roughly, the number of templates in each category.
+#
+# Defaults: layout=2, navigation=10, screen=50
+
+services.TemplateService.layout.cache.size=2
+services.TemplateService.navigation.cache.size=10
+services.TemplateService.screen.cache.size=50
+
+#
+# These are the mapper classes responsible for the lookup of Page, Screen, Layout and Navigation classes according
+# to the supplied template Name. They also map template names on the Layout and Screen file names to be used.
+#
+# services.TemplateService.mapper.page.class = org.apache.turbine.services.template.mapper.DirectTemplateMapper
+# services.TemplateService.mapper.screen.class = org.apache.turbine.services.template.mapper.ClassMapper
+# services.TemplateService.mapper.layout.class = org.apache.turbine.services.template.mapper.ClassMapper
+# services.TemplateService.mapper.navigation.class = org.apache.turbine.services.template.mapper.ClassMapper
+# services.TemplateService.mapper.layout.template.class = org.apache.turbine.services.template.mapper.LayoutTemplateMapper
+# services.TemplateService.mapper.screen.template.class = org.apache.turbine.services.template.mapper.ScreenTemplateMapper
+
+# -------------------------------------------------------------------
+#
+# P U L L S E R V I C E
+#
+# -------------------------------------------------------------------
+# These are the properties for the Pull Service, the service
+# that works in conjuction with the Turbine Pull Model API.
+# -------------------------------------------------------------------
+
+services.PullService.earlyInit= true
+
+# This determines whether the non-request tools are refreshed
+# on each request (request tools aren't ever, because they're
+# instantiated for the request only anyway).
+services.PullService.tools.per.request.refresh=true
+
+# Path to the resources of the application tools, relative to the
+# application root
+services.PullService.tools.resources.dir=/conf/test/turbine-resources/
+
+# These are tools that are placed in the context by the service
+# These tools will be made available to all your
+# templates. You list the tools in the following way:
+#
+# tool.<scope>.<id> = <classname>
+#
+# <scope> is the tool scope: global, request, session
+# or persistent (see below for more details)
+# <id> is the name of the tool in the context
+#
+# You can configure the tools in this way:
+# tool.<id>.<parameter> = <value>
+#
+# So if you find "global", "request", "session" or "persistent" as second
+# part, it is a configuration to put a tool into the toolbox, else it is a
+# tool specific configuration.
+#
+# For example:
+#
+# tool.global.ui = org.apache.turbine.util.pull.tools.UITool
+# tool.global.mm = org.apache.turbine.util.pull.MessageManager
+# tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink
+# tool.request.page = org.apache.turbine.util.template.TemplatePageAttributes
+#
+# Then:
+#
+# tool.ui.skin = default
+#
+# configures the value of "skin" for the "ui" tool.
+#
+# Tools are accessible in all templates by the <id> given
+# to the tool. So for the above listings the UIManager would
+# be available as $ui, the MessageManager as $mm, the TemplateLink
+# as $link and the TemplatePageAttributes as $page.
+#
+# You should avoid using tool names called "global", "request",
+# or "session" because of clashes with the possible Scopes.
+#
+# Scopes:
+#
+# global: tool is instantiated once and that instance is available
+# to all templates for all requests. Tool must be threadsafe.
+#
+# request: tool is instantiated once for each request (although the
+# PoolService is used to recycle instances). Tool need not
+# be threadsafe.
+#
+# session: tool is instantiated once for each user session, and is
+# stored in the user's temporary hashtable. Tool should be
+# threadsafe.
+#
+# authorized: tool is instantiated once for each user session once the
+# user logs in. After this, it is a normal session tool.
+#
+# Defaults: none
+
+tool.request.link=org.apache.turbine.services.pull.tools.TemplateLink
+tool.request.page=org.apache.turbine.util.template.HtmlPageAttributes
+tool.request.content=org.apache.turbine.services.pull.tools.ContentTool
+tool.request.l10n=org.apache.turbine.services.localization.LocalizationTool
+
+# This pull tool is to allow for easy formatting of Date object into Strings
+tool.request.dateFormatter=org.apache.turbine.services.pull.util.DateFormatter
+
+# Use this tool if you need a place to store data that will persist between
+# requests. Any data stored using this tool will be stored in the session.
+tool.session.sessionData=org.apache.turbine.services.pull.util.SessionData
+
+# These are intake tools.
+# tool.request.intake=org.apache.turbine.services.intake.IntakeTool
+
+# This is a tool that allows access to the scheduler service.
+# tool.request.scheduler=org.apache.turbine.services.SchedulerTool
+
+# This pull tool can be used to provide skins to an application
+tool.global.ui = org.apache.turbine.services.pull.tools.UITool
+
+# # These properties apply to both the old UIManager and the newer UIService
+tool.ui.dir.skin = /turbine-skins/
+tool.ui.dir.image = /turbine-images/
+tool.ui.skin = myskin
+tool.ui.css = skins.css
+
+#
+# The content tool can put its URIs through the Servlet container,
+# which might attach things like the jsessionid even to URIs that
+# are not served by the container.
+#
+# The default behavior was not to put these through the container.
+#
+# Set this to true if you need things like jsessionid attached to all
+# links generated from the $content pull tool.
+#
+tool.content.want.encoding = false
+
+#
+# Both the link and the content tool normally return absolute URIs
+# You can change this by exchanging the tool classes but this is not
+# really recommended. Setting these properties to true allow you
+# to change the behavior if you want only relative URIs (e.g. if you
+# run behind a reverse proxy or a load balancer).
+#
+tool.content.want.relative = false
+tool.link.want.relative = false
+
+# Set the retriever factory for OMTool
+tool.om.factory=org.apache.turbine.om.MockRetrieverFactory
+
+# -------------------------------------------------------------------
+#
+# V E L O C I T Y S E R V I C E
+#
+# -------------------------------------------------------------------
+
+
+services.VelocityService.earlyInit = true
+services.VelocityService.template.extension = vm
+
+services.VelocityService.default.page = VelocityPage
+services.VelocityService.default.screen = VelocityScreen
+services.VelocityService.default.layout = VelocityOnlyLayout
+services.VelocityService.default.navigation = VelocityNavigation
+services.VelocityService.default.layout.template = Default.vm
+
+services.VelocityService.resource.loader = file
+services.VelocityService.file.resource.loader.description = Velocity File Resource Loader
+services.VelocityService.file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
+services.VelocityService.file.resource.loader.path = src/templates/test
+services.VelocityService.file.resource.loader.cache = false
+services.VelocityService.file.resource.loader.modificationCheckInterval = 2
+
+# -------------------------------------------------------------------
+#
+# J S P S E R V I C E
+#
+# -------------------------------------------------------------------
+
+services.JspService.template.extension=jsp
+services.JspService.default.page = JspPage
+services.JspService.default.screen=BaseJspScreen
+services.JspService.default.layout = JspLayout
+services.JspService.default.navigation=BaseJspNavigation
+services.JspService.default.error.screen = JspErrorScreen
+services.JspService.default.layout.template = Default.jsp
+
+services.JspService.templates = /templates/app
+services.JspService.buffer.size = 8192
+
+# -------------------------------------------------------------------
+#
+# S C H E D U L E R S E R V I C E
+#
+# -------------------------------------------------------------------
+
+#
+# Set enabled to true to start the scheduler. The scheduler can be
+# stopped and started after Turbine has been intialized. See the
+# javadocs for org.apache.turbine.services.schedule.TurbineScheduler
+# for the methods calls.
+#
+# Default = false
+#
+
+services.SchedulerService.enabled=false
+
+# Determines if the scheduler service should be initialized early. This
+# Should always be set to true!!!!
+
+services.SchedulerService.earlyInit=true
+
+# -------------------------------------------------------------------
+#
+# S E C U R I T Y S E R V I C E
+#
+# -------------------------------------------------------------------
+
+#
+# This is the class that implements the UserManager interface to
+# manage User objects. Default is the PassiveUserManager
+#
+# Override this setting if you want your User information stored
+# on a different medium (LDAP directory is a good example).
+#
+# Adjust this setting if you change the Setting of the SecurityService class (see above).
+
+# Default: org.apache.turbine.services.security.passive.PassiveUserManager
+# The MockUserManager is used in testing...
+services.SecurityService.user.manager = org.apache.turbine.services.security.DefaultUserManager
+
+# -------------------------------------------------------------------
+#
+# A V A L O N C O M P O N E N T S E R V I C E
+#
+# -------------------------------------------------------------------
+# Components implementing the Avalon lifecycle interfaces can be loaded,
+# configured and initialized by Turbine
+# -------------------------------------------------------------------
+
+#
+# Name and location to the configuration file for the container.
+#
+services.AvalonComponentService.containerConfiguration = /src/test/conf/torque/turbine/fulcrumContainerConfiguration.xml
+
+# -------------------------------------------------------------------
+#
+# S E S S I O N S E R V I C E
+#
+# -------------------------------------------------------------------
+
+services.SessionService.earlyInit=true
+
+# -------------------------------------------------------------------
+#
+# A D D I T I O N A L P R O P E R T I E S
+#
+# -------------------------------------------------------------------
+# The full path name to an additional properties file. Properties in
+# this file will be included in this property set. Duplicate name
+# values will be replaced, so be careful.
+#
+# Default: none
+# -------------------------------------------------------------------
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/turbine/fulcrumContainerConfiguration.xml b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/fulcrumContainerConfiguration.xml
new file mode 100644
index 0000000..e0b4bf7
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/fulcrumContainerConfiguration.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<fulcrum-yaafi>
+ <componentRoles>
+ <location>/src/test/conf/torque/fulcrumRoleConfiguration.xml</location>
+ </componentRoles>
+ <componentConfiguration>
+ <location>/src/test/conf/torque/fulcrumComponentConfiguration.xml</location>
+ </componentConfiguration>
+</fulcrum-yaafi>
diff --git a/src/main/resources/archetype-resources/src/test/conf/torque/turbine/turbine-classic-pipeline.xml b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/turbine-classic-pipeline.xml
new file mode 100644
index 0000000..f8457b0
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/conf/torque/turbine/turbine-classic-pipeline.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<pipeline name="default">
+ <valves>
+ <valve>org.apache.turbine.pipeline.DetermineActionValve</valve>
+ <valve>org.apache.turbine.pipeline.DetermineTargetValve</valve>
+ <valve>org.apache.turbine.pipeline.DefaultSessionTimeoutValve</valve>
+ <valve>org.apache.turbine.pipeline.DefaultLoginValve</valve>
+ <valve>org.apache.turbine.pipeline.DefaultSessionValidationValve</valve>
+ <valve>org.apache.turbine.pipeline.DefaultACLCreationValve</valve>
+ <valve>org.apache.turbine.pipeline.ExecutePageValve</valve>
+ <valve>org.apache.turbine.pipeline.CleanUpValve</valve>
+ <valve>org.apache.turbine.pipeline.DetermineRedirectRequestedValve</valve>
+ </valves>
+</pipeline>
diff --git a/src/main/resources/archetype-resources/src/test/java/services/security/AbstractFulcrumTorqueModelManagerTest.java b/src/main/resources/archetype-resources/src/test/java/services/security/AbstractFulcrumTorqueModelManagerTest.java
new file mode 100644
index 0000000..2ffc5de
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/java/services/security/AbstractFulcrumTorqueModelManagerTest.java
@@ -0,0 +1,488 @@
+package ${package}.services.security;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import static org.junit.Assert.*;
+
+import java.util.Set;
+
+import org.apache.fulcrum.security.GroupManager;
+import org.apache.fulcrum.security.PermissionManager;
+import org.apache.fulcrum.security.RoleManager;
+import org.apache.fulcrum.security.SecurityService;
+import org.apache.fulcrum.security.UserManager;
+import org.apache.fulcrum.security.entity.ExtendedUser;
+import org.apache.fulcrum.security.entity.Group;
+import org.apache.fulcrum.security.entity.Permission;
+import org.apache.fulcrum.security.entity.Role;
+import org.apache.fulcrum.security.entity.User;
+import org.apache.fulcrum.security.model.turbine.TurbineModelManager;
+import org.apache.fulcrum.security.model.turbine.entity.TurbineGroup;
+import org.apache.fulcrum.security.model.turbine.entity.TurbineRole;
+import org.apache.fulcrum.security.model.turbine.entity.TurbineUser;
+import org.apache.fulcrum.security.model.turbine.entity.TurbineUserGroupRole;
+import org.apache.fulcrum.security.util.DataBackendException;
+import org.apache.fulcrum.security.util.EntityExistsException;
+import org.apache.fulcrum.security.util.PermissionSet;
+import org.apache.fulcrum.security.util.UnknownEntityException;
+import org.apache.fulcrum.testcontainer.BaseUnit4Test;
+import org.apache.torque.ConstraintViolationException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Initialization of services in implementing tests
+ *
+ * @author gkallidis
+ * @version $Id$
+ *
+ */
+public abstract class AbstractFulcrumTorqueModelManagerTest extends BaseUnit4Test
+{
+ protected Role role;
+
+ protected TurbineModelManager modelManager;
+
+ protected RoleManager roleManager;
+
+ protected GroupManager groupManager;
+
+ protected PermissionManager permissionManager;
+
+ protected UserManager userManager;
+
+ protected SecurityService securityService;
+
+ boolean onDeleteCascade = true;
+
+ // By default org.slf4j.LoggerFactory is optional in 4.0, but included in webapp
+ Logger log = LoggerFactory.getLogger( getClass().getName() );
+
+ @Before
+ public void setUp() throws Exception
+ {
+ securityService = (SecurityService) lookup(SecurityService.ROLE);
+ roleManager = securityService.getRoleManager();
+ userManager = securityService.getUserManager();
+ groupManager = securityService.getGroupManager();
+ permissionManager = securityService.getPermissionManager();
+ modelManager = (TurbineModelManager) securityService.getModelManager();
+ }
+
+ @Override
+ @After
+ public void tearDown()
+ {
+ modelManager = null;
+ securityService = null;
+ }
+
+ @Test
+ public void testGetGlobalGroup() throws Exception
+ {
+ Group global = modelManager.getGlobalGroup();
+ assertNotNull(global);
+ assertEquals(global.getName(), modelManager.getGlobalGroupName());
+ }
+ @Test
+ public void testGrantRolePermission() throws Exception
+ {
+ Permission permission = permissionManager.getPermissionInstance();
+ permission.setName("ANSWER_PHONE");
+ checkAndAddPermission( permission );
+ role = roleManager.getRoleInstance("RECEPTIONIST");
+ checkAndAddRole( role );
+ checkAndGrant( permission );
+ role = roleManager.getRoleById(role.getId());
+ PermissionSet permissions = ((TurbineRole) role).getPermissions();
+ assertEquals(1, permissions.size());
+ assertTrue(((TurbineRole) role).getPermissions().contains(permission));
+
+ checkAndRevoke( permission );
+ deletePermission( permission );
+ deleteRole();
+ }
+
+ @Test
+ public void testRevokeRolePermission() throws Exception
+ {
+ Permission permission = securityService.getPermissionManager().getPermissionInstance();
+ permission.setName("ANSWER_FAX");
+ checkAndAddPermission( permission );
+ role = roleManager.getRoleInstance("SECRETARY");
+ checkAndAddRole( role );
+ checkAndGrant( permission );
+ role = roleManager.getRoleById(role.getId());
+ PermissionSet permissions = ((TurbineRole) role).getPermissions();
+ assertEquals(1, permissions.size());
+ checkAndRevoke( permission );
+ role = roleManager.getRoleById(role.getId());
+ permissions = ((TurbineRole) role).getPermissions();
+ assertEquals(0, permissions.size());
+ assertFalse(((TurbineRole) role).getPermissions().contains(permission));
+ deletePermission( permission );
+ deleteRole();
+ }
+ @Test
+ public void testRevokeAllRole() throws Exception
+ {
+ Permission permission = securityService.getPermissionManager().getPermissionInstance();
+ Permission permission2 = securityService.getPermissionManager().getPermissionInstance();
+ permission.setName("SEND_SPAM");
+ permission2.setName("ANSWER_EMAIL");
+ checkAndAddPermission( permission );
+ checkAndAddPermission( permission2 );
+ role = roleManager.getRoleInstance("HELPER");
+ checkAndAddRole( role );
+ checkAndGrant( permission );
+ checkAndGrant( permission2);
+ role = roleManager.getRoleById(role.getId());
+ PermissionSet permissions = ((TurbineRole) role).getPermissions();
+ assertEquals(2, permissions.size());
+ try {
+ modelManager.revokeAll(role);
+ } catch (Exception e) {
+ log.info( "Might fail " + e.getMessage() );
+ }
+ role = roleManager.getRoleById(role.getId());
+ permissions = ((TurbineRole) role).getPermissions();
+ assertEquals(0, permissions.size());
+ checkAndRevoke( permission );
+ checkAndRevoke( permission2 );
+ deletePermission( permission );
+ deletePermission( permission2 );
+ deleteRole();
+ }
+
+ @Test
+ public void testRevokeAllUser() throws Exception
+ {
+ Group group = securityService.getGroupManager().getGroupInstance();
+ group.setName("TEST_REVOKEALLUSER_GROUP");
+ group = checkAndAddGroup( group );
+
+ role = securityService.getRoleManager().getRoleInstance();
+ role.setName("TEST_REVOKEALLUSER_ROLE");
+ checkAndAddRole( role );
+
+ User user = userManager.getUserInstance("calvin");
+ user = checkAndAddUser( user, "calvin" );
+ try {
+ modelManager.grant(user, group, role);
+ } catch (DataBackendException e ){
+ if (e.getCause() != null && e.getCause() instanceof ConstraintViolationException) {
+ log.info( "error due to " + e.getCause().getMessage() );
+ } else {
+ log.info( "error due to " + e.getMessage() );
+ }
+ }
+
+ group = groupManager.getGroupById(group.getId());
+ Set<TurbineUserGroupRole> userGroupRoleSet = ((TurbineGroup) group).getUserGroupRoleSet();
+ assertEquals(1, userGroupRoleSet.size());
+ Set<TurbineUserGroupRole> userGroupRoleSet2 = ((TurbineGroup) group).getUserGroupRoleSet();
+ assertEquals(1, userGroupRoleSet2.size());
+
+ try {
+ modelManager.revokeAll(user);
+ } catch (Exception e) {
+ log.info( "error due to " + e.getMessage() );
+ }
+ group = groupManager.getGroupById(group.getId());
+ assertEquals(0, ((TurbineGroup) group).getUserGroupRoleSet().size());
+ role = securityService.getRoleManager().getRoleByName("TEST_REVOKEALLUSER_ROLE");
+
+ // assertFalse(((TurbineRole) role).getGroups().contains(group));
+ // cleanup ;
+ deleteGroup( group );
+ deleteRole();
+ deleteUser( user );
+
+ }
+
+ @Test
+ public void testGrantUserGroupRole() throws Exception
+ {
+ Group group = securityService.getGroupManager().getGroupInstance();
+ group.setName("TEST_GROUP");
+ group = checkAndAddGroup( group );
+ role = roleManager.getRoleInstance();
+ role.setName("TEST_Role");
+ checkAndAddRole( role );
+ User user = userManager.getUserInstance("Clint");
+
+ user = checkAndAddUser( user, "clint" );
+
+ try {
+ modelManager.grant(user, group, role);
+ } catch (DataBackendException e ){
+ if (e.getCause() != null && e.getCause() instanceof ConstraintViolationException) {
+ log.info( "error due to " + e.getCause().getMessage() );
+ } else {
+ log.info( "error due to " + e.getMessage() );
+ }
+ }
+ boolean ugrFound = false;
+ TurbineUserGroupRole ugrTest = null;
+ for (TurbineUserGroupRole ugr : ((TurbineUser) user).getUserGroupRoleSet())
+ {
+ if (ugr.getUser().equals(user) && ugr.getGroup().equals(group) && ugr.getRole().equals(role))
+ {
+ ugrFound = true;
+ ugrTest = ugr;
+ break;
+ }
+ }
+ assertTrue(ugrFound);
+ assertTrue(ugrTest.getGroup().equals(group));
+ assertTrue(ugrTest.getUser().equals(user));
+
+ try {
+ modelManager.revoke(user, group, role);
+ } catch (DataBackendException e ){
+ if (e.getCause() != null && e.getCause() instanceof ConstraintViolationException) {
+ log.info( "error due to " + e.getCause().getMessage() );
+ } else {
+ log.info( "error due to " + e.getMessage() );
+ }
+ }
+ deleteGroup( group );
+ deleteRole();
+ deleteUser( user );
+ }
+ @Test
+ public void testRevokeUserGroupRole() throws Exception
+ {
+ Group group = securityService.getGroupManager().getGroupInstance();
+ group.setName("TEST_REVOKE");
+ group = checkAndAddGroup( group );
+ User user = userManager.getUserInstance("Lima");
+
+ user = checkAndAddUser( user, "pet" );
+ role = roleManager.getRoleInstance();
+ role.setName("TEST_REVOKE_ROLE");
+ checkAndAddRole( role );
+ try {
+ modelManager.grant(user, group, role);
+ } catch (DataBackendException e ){
+ if (e.getCause() != null && e.getCause() instanceof ConstraintViolationException) {
+ log.info( "error due to " + e.getCause().getMessage() );
+ } else {
+ log.info( "error due to " + e.getMessage() );
+ }
+ }
+ try {
+ modelManager.revoke(user, group, role);
+ } catch (DataBackendException e ){
+ if (e.getCause() != null && e.getCause() instanceof ConstraintViolationException) {
+ log.info( "error due to " + e.getCause().getMessage() );
+ } else {
+ log.info( "error due to " + e.getMessage() );
+ }
+ }
+ boolean ugrFound = false;
+ for (TurbineUserGroupRole ugr : ((TurbineUser) user).getUserGroupRoleSet())
+ {
+ if (ugr.getUser().equals(user) && ugr.getGroup().equals(group) && ugr.getRole().equals(role))
+ {
+ ugrFound = true;
+ break;
+ }
+ }
+ assertFalse(ugrFound);
+ deleteGroup( group );
+ deleteRole();
+ deleteUser( user );
+
+ }
+
+ private void checkAndAddPermission( Permission permission )
+ throws DataBackendException, UnknownEntityException, EntityExistsException
+ {
+ // cleanup if using real db
+ Permission dbPermission;
+ if (securityService.getPermissionManager().checkExists( permission )) {
+ dbPermission = securityService.getPermissionManager().getPermissionByName( permission.getName() );
+ // this might fail as it is referenced
+// try {
+// securityService.getPermissionManager().removePermission( permission );
+// } catch (Exception e) {
+// System.out.println("removing permission failed" + e.getMessage() );
+// }
+ } else {
+ dbPermission =securityService.getPermissionManager().addPermission(permission);
+ }
+ permission.setId( dbPermission.getId() );
+
+ }
+
+ // adds user
+ private User checkAndAddUser( User user, String password )
+ throws DataBackendException, UnknownEntityException, EntityExistsException
+ {
+ if (user instanceof ExtendedUser) {
+ // set first last name which might be required (cft. schema definition)
+ ((ExtendedUser)user).setFirstName( user.getName() );
+ ((ExtendedUser)user).setLastName( user.getName() );
+ }
+ if (userManager.checkExists( user )) {
+ return userManager.getUser( user.getName() );
+ //userManager.removeUser( dbUser );
+ } else {
+ return userManager.addUser(user, password );
+ }
+ }
+
+ private Group checkAndAddGroup( Group group )
+ throws DataBackendException, UnknownEntityException, EntityExistsException
+ {
+ // cleanup if using real db
+ if (securityService.getGroupManager().checkExists( group )) {
+ return securityService.getGroupManager().getGroupByName( group.getName() );
+ // might fail as it is referenced
+// try {
+// securityService.getGroupManager().removeGroup( group );
+// } catch (Exception e) {
+// System.out.println("removing group failed" + e.getMessage() );
+// }
+ } else {
+ return securityService.getGroupManager().addGroup(group);
+ }
+ }
+
+
+ private void checkAndAddRole( Role role )
+ throws DataBackendException, UnknownEntityException, EntityExistsException
+ {
+ Role dbRole;
+ // cleanup if using real db
+ if (securityService.getRoleManager().checkExists( role )) {
+ dbRole = securityService.getRoleManager().getRoleByName( role.getName() );
+ // might fail as it is referenced
+// try {
+// securityService.getRoleManager().removeRole( role );
+// } catch (Exception e) {
+// System.out.println("removing role failed " + e.getMessage() );
+// }
+ } else {
+ dbRole = securityService.getRoleManager().addRole(role);
+ }
+ if (this.role != null) {
+ this.role.setId( dbRole.getId() );
+ } else {
+ this.role =dbRole;
+ }
+ }
+
+ private void checkAndGrant( Permission permission )
+ throws UnknownEntityException
+ {
+ // short cut if duplicate entry use acl ...
+ try {
+ modelManager.grant(role, permission);
+ } catch (DataBackendException e) {
+ log.info( "Might be duplicate TODO ACL check" + e.getMessage() );
+ }
+ }
+
+ private void checkAndRevoke( Permission permission )
+ throws UnknownEntityException
+ {
+ // short cut if duplicate entry use acl ...
+ try {
+ modelManager.revoke(role, permission);
+ } catch (DataBackendException e) {
+ log.info( "Might be duplicate TODO ACL check" + e.getMessage() );
+ }
+ }
+
+ private void deleteUser( User user )
+ {
+ if (onDeleteCascade) {
+ try {
+ userManager.removeUser( user );
+ log.info( "try to delete user " + user.getName() );
+ } catch (Exception e) {
+ log.error( "deleting user " + user.getName() + " failed. " + e.getMessage());
+ if (e.getCause() != null && e.getCause() instanceof ConstraintViolationException) {
+ log.info( "error due to " + e.getCause().getMessage() );
+ } else {
+ log.info( "error due to " + e.getMessage() );
+ }
+ }
+ } else {
+ log.info( "onDeleteCascade false, user " + user.getName() + " not deleted!");
+ }
+ }
+
+ private void deleteRole()
+ {
+ log.info("deleting role ");
+ if (role != null) {
+ try
+ {
+ log.info("deleting role "+ role.getName());
+ roleManager.removeRole( role );
+ role =null;
+ }
+ catch ( Exception e )
+ {
+ // fail
+ log.error( e.getMessage(),e);
+ }
+ }
+ }
+
+ private void deletePermission(Permission permission)
+ {
+ log.info("deleting permission *");
+ if (role != null) {
+ try
+ {
+ log.info("deleting permission "+ permission.getName());
+ permissionManager.removePermission( permission );
+ }
+ catch ( Exception e )
+ {
+ // fail
+ log.error( e.getMessage(),e);
+ }
+ }
+ }
+
+ private void deleteGroup(Group group)
+ {
+ log.info("deleting group *");
+ if (role != null) {
+ try
+ {
+ log.info("deleting group "+ group.getName());
+ groupManager.removeGroup( group );
+ }
+ catch ( Exception e )
+ {
+ // fail
+ log.error( e.getMessage(),e);
+ }
+ }
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/test/java/services/security/FulcrumTorqueDefaultModelManagerTest.java b/src/main/resources/archetype-resources/src/test/java/services/security/FulcrumTorqueDefaultModelManagerTest.java
new file mode 100644
index 0000000..67f5781
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/java/services/security/FulcrumTorqueDefaultModelManagerTest.java
@@ -0,0 +1,63 @@
+package ${package}.services.security;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import static org.junit.Assert.fail;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Ignore;
+
+/**
+ * Test Fulcrum Integration.
+ *
+ * Stub for further tests, relying on Fulcrum.
+ *
+ * @author gkallidis
+ * @version $Id$
+ */
+public class FulcrumTorqueDefaultModelManagerTest
+ extends AbstractFulcrumTorqueModelManagerTest
+{
+
+ @Override
+ @Before
+ public void setUp() throws Exception
+ {
+ try
+ {
+ // just Fulcrum
+ setConfigurationFileName("src/test/conf/torque/fulcrumComponentConfiguration.xml");
+ setRoleFileName("src/test/conf/torque/fulcrumRoleConfiguration.xml");
+ super.setUp();
+
+ }
+ catch (Exception e)
+ {
+ fail(e.toString());
+ }
+ }
+
+ @Test
+ public void testDummy() {
+ // all tests in abstract
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/test/java/services/security/TurbineSecurityServiceTest.java b/src/main/resources/archetype-resources/src/test/java/services/security/TurbineSecurityServiceTest.java
new file mode 100644
index 0000000..aa38651
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/java/services/security/TurbineSecurityServiceTest.java
@@ -0,0 +1,404 @@
+package ${package}.services.security;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.fulcrum.security.ModelManager;
+import org.apache.fulcrum.security.entity.ExtendedUser;
+import org.apache.fulcrum.security.entity.Group;
+import org.apache.fulcrum.security.entity.Permission;
+import org.apache.fulcrum.security.entity.Role;
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.fulcrum.security.model.turbine.TurbineModelManager;
+import org.apache.fulcrum.security.model.turbine.entity.TurbineUser;
+import org.apache.fulcrum.security.model.turbine.entity.TurbineUserGroupRole;
+import org.apache.fulcrum.security.util.DataBackendException;
+import org.apache.fulcrum.security.util.EntityExistsException;
+import org.apache.fulcrum.security.util.UnknownEntityException;
+import org.apache.fulcrum.testcontainer.BaseUnit4Test;
+import org.apache.torque.ConstraintViolationException;
+import org.apache.turbine.annotation.AnnotationProcessor;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.DefaultUserImpl;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.services.ServiceManager;
+import org.apache.turbine.services.TurbineServices;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.TurbineConfig;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test that the SecurityService works properly by comparing behaviour of Turbine and Fulcrum security services using
+ * Torque and Turbine user manager. Requires MySQL
+ *
+ * @author gkallidis
+ * @version $Id$
+ */
+
+public class TurbineSecurityServiceTest
+ extends BaseUnit4Test
+{
+
+ org.apache.fulcrum.security.SecurityService fulcrumSecurityService;
+
+ @TurbineService
+ SecurityService turbineSecurityService;
+
+ static TurbineConfig tc;
+
+ ModelManager modelManager;
+
+ boolean onDeleteCascade = true;
+
+ // By default org.slf4j.LoggerFactory is optional in 4.0, but included in webapp
+ Logger log = LoggerFactory.getLogger( getClass().getName() );
+
+ @BeforeClass
+ public static void init()
+ throws Exception
+ {
+ tc = new TurbineConfig( ".", "src/test/conf/torque/turbine/CompleteTurbineResources.properties" );
+ tc.initialize();
+ }
+
+ @Before
+ public void setUpBefore()
+ throws Exception
+ {
+ AnnotationProcessor.process(this);
+// turbineSecurityService = (SecurityService) TurbineServices.getInstance().getService( SecurityService.SERVICE_NAME );
+
+ ServiceManager serviceManager = TurbineServices.getInstance();
+ fulcrumSecurityService = (org.apache.fulcrum.security.SecurityService) serviceManager.getService( org.apache.fulcrum.security.SecurityService.ROLE );
+
+// setConfigurationFileName("src/test/conf/torque/fulcrumComponentConfiguration.xml");
+// setRoleFileName("src/test/conf/torque/fulcrumRoleConfiguration.xml");
+// fulcrumSecurityService = (org.apache.fulcrum.security.SecurityService) lookup(org.apache.fulcrum.security.SecurityService.ROLE);
+// factory = (ACLFactory) lookup(ACLFactory.ROLE);
+// modelManager = (TurbineModelManager) lookup(TurbineModelManager.ROLE);
+ }
+
+ @Test
+ public void testAccountExists()
+ throws Exception
+ {
+ // User user = new org.apache.turbine.om.security.DefaultUserImpl(new TurbineUserImpl());
+ User user = turbineSecurityService.getUserInstance();
+ user.setAccessCounter( 5 );
+ assertFalse( turbineSecurityService.accountExists( user ) );
+ assertFalse( fulcrumSecurityService.getUserManager().checkExists( user ) );
+
+ }
+
+ @Test
+ // @Ignore(value="Turbine security service supported requires Turbine 4.0.1")
+ public void testCreateUser()
+ throws Exception
+ {
+ User user = turbineSecurityService.getUserInstance();
+ user.setAccessCounter( 5 );
+ user.setName( "ringo" );
+ // required not null constraint
+ ( (ExtendedUser) user ).setFirstName( user.getName() );
+ ( (ExtendedUser) user ).setLastName( user.getName() );
+ turbineSecurityService.addUser( user, "fakepasswrod" );
+ assertTrue( turbineSecurityService.accountExists( user ) );
+ assertTrue( fulcrumSecurityService.getUserManager().checkExists( user ) );
+ deleteUser( user );
+ }
+
+ @Test
+ // @Ignore(value="Turbine security service supported requires Turbine 4.0.1")
+ public void testPermissionRole()
+ {
+ Role role = null;
+ Permission permission = null;
+ Permission permission2 = null;
+ try {
+ role = turbineSecurityService.getRoleInstance( "TEST_SECRETARY" );
+ role = turbineSecurityService.addRole( role );
+ permission = turbineSecurityService.getPermissionInstance("TEST_ANSWER_FAX");
+ permission = turbineSecurityService.addPermission( permission );
+
+ permission2 = turbineSecurityService.getPermissionInstance("TEST_ANSWER_PHONE");
+ turbineSecurityService.addPermission( permission2 );
+
+ turbineSecurityService.grant( role, permission );
+ turbineSecurityService.grant( role, permission2 );
+
+ role = turbineSecurityService.getRoleById( (Integer) role.getId());
+
+ turbineSecurityService.revokeAll( role );
+ turbineSecurityService.removeRole( role );
+ // not necessarily required
+ permission = turbineSecurityService.getPermissionById( (Integer) permission.getId() );
+ turbineSecurityService.removePermission( permission );
+ //permission2 = turbineSecurityService.getPermissionByName( permission2.getName() );
+ //turbineSecurityService.removePermission( permission2 );
+ } catch (EntityExistsException e) {
+ if (role != null) deleteRole( role );
+ if (permission != null) deletePermission( permission );
+ if (permission2 != null) deletePermission( permission2 );
+ } catch (Exception e) {
+ log.error( "error" , e);
+ fail();
+ }
+ }
+
+ /**
+ * Tests Turbine and Fulcrum.
+ *
+ * @throws Exception
+ */
+ @Test
+ // @Ignore(value="Turbine security service supported requires Turbine 4.0.1")
+ public void testGrantUserGroupRole()
+ throws Exception
+ {
+ Group group = null;
+ Role role = null;
+ User user = null;
+ TurbineUser fulcrumUser = null;
+ try
+ {
+ group = turbineSecurityService.getGroupInstance( "TEST_GROUP" );
+ group = turbineSecurityService.addGroup( group ); // assign here to delete later as
+ role = turbineSecurityService.getRoleInstance( "TEST_Role" );
+ role = turbineSecurityService.addRole( role );
+ // Turbine security service returns a wrapped instance: org.apache.turbine.om.security.DefaultUserImpl
+ // which implements org.apache.turbine.om.security.User
+ user = turbineSecurityService.getUserInstance( "Clint" );
+ // required not null constraint
+ ( (ExtendedUser) user ).setFirstName( user.getName() );
+ ( (ExtendedUser) user ).setLastName( user.getName() );
+
+ turbineSecurityService.addUser( user, "clint" );
+ turbineSecurityService.grant( user, group, role );
+
+ // existing role
+ Group existingGroup = turbineSecurityService.getGroupByName( "global" );
+ Role existingRole = turbineSecurityService.getRoleByName( "turbineuser" );
+ turbineSecurityService.grant( user, existingGroup, existingRole );
+ assertTrue( user.getUserGroupRoleSet().size() == 2 );
+ // get fresh db user
+ user = turbineSecurityService.getUser( "Clint" );
+ existingGroup = turbineSecurityService.getGroupByName( "turbine" );
+ existingRole = turbineSecurityService.getRoleByName( "turbineadmin" );
+ turbineSecurityService.grant( user, existingGroup, existingRole );
+ assertTrue( user.getUserGroupRoleSet().size() == 3 );
+
+ TurbineAccessControlList tacl = turbineSecurityService.<TurbineAccessControlList>getACL( user );
+
+ assertTrue(tacl.hasRole( existingRole, existingGroup ) );
+ assertTrue(tacl.hasRole( "turbineuser" ));
+
+ turbineSecurityService.revoke( user, existingGroup, existingRole );
+
+ //user = turbineSecurityService.getUser( "Clint" );
+ assertTrue( user.getUserGroupRoleSet().size() == 2 );
+ userGroupRoleCheck( group, role, user.getUserDelegate() );
+ // compare
+ // Fulcrum security service returns a raw
+ // org.apache.fulcrum.security.model.turbine.entity.impl.TurbineUserImpl,
+ org.apache.fulcrum.security.UserManager userManager = fulcrumSecurityService.getUserManager();
+ fulcrumUser = userManager.getUserInstance( "Clint2" );
+ // required not null constraint
+ ( (ExtendedUser) fulcrumUser ).setFirstName( fulcrumUser.getName() );
+ ( (ExtendedUser) fulcrumUser ).setLastName( fulcrumUser.getName() );
+ userManager.addUser( fulcrumUser, "clint2" );
+ ( (TurbineModelManager) fulcrumSecurityService.getModelManager() ).grant( fulcrumUser, group, role );
+ userGroupRoleCheck( group, role, fulcrumUser );
+
+ tacl = turbineSecurityService.getACL( user );
+ // revoked
+ assertFalse(tacl.hasRole( existingRole, existingGroup ) );
+;
+
+
+ } catch (EntityExistsException e) {
+ // cft. finally
+ fail();
+ } catch (Exception e) {
+ log.error( "error" , e);
+ fail();
+ }
+ finally
+ {
+ if ( fulcrumUser != null )
+ deleteUser( new DefaultUserImpl( fulcrumUser ) );
+ if ( user != null )
+ deleteUser( user );
+ // not needed as user remove revokes all :
+ // if (group != null && role != null && user != null) turbineSecurityService.revoke(user, group, role);
+ if ( group != null )
+ deleteGroup( group );
+ if ( role != null )
+ deleteRole( role );
+ }
+ }
+
+ public void testCreatingTurbineACLandModel() throws Exception
+ {
+
+ }
+
+
+ /**
+ * Fulcrum contract check
+ *
+ * @param group Fulcrum interface
+ * @param role Fulcrum interface
+ * @param user Fulcrum interface
+ * @throws EntityExistsException
+ * @throws DataBackendException
+ * @throws UnknownEntityException
+ */
+ private void userGroupRoleCheck( Group group, Role role, TurbineUser user ) throws DataBackendException
+ {
+
+ boolean ugrFound = false;
+ TurbineUserGroupRole ugrTest = null;
+ for ( TurbineUserGroupRole ugr : ( (TurbineUser) user ).getUserGroupRoleSet() )
+ {
+ if ( ugr.getUser().equals( user ) && ugr.getGroup().equals( group ) && ugr.getRole().equals( role ) )
+ {
+ ugrFound = true;
+ ugrTest = ugr;
+ break;
+ }
+ }
+ assertTrue( ugrFound );
+ assertTrue( ugrTest.getGroup().equals( group ) );
+ assertTrue( ugrTest.getUser().equals( user ) );
+ }
+
+ @AfterClass
+ public static void setupAfter()
+ {
+ ServiceManager serviceManager = TurbineServices.getInstance();
+ serviceManager.shutdownService( org.apache.turbine.services.security.SecurityService.SERVICE_NAME );
+ serviceManager.shutdownServices();
+ // TODO cleanup added users, roles, permissions ..
+ }
+
+ private void deletePermission( Permission permission )
+ {
+ try
+ {
+ if (permission.getId() == null) {
+ permission = turbineSecurityService.getPermissionByName(permission.getName() );
+ }
+ log.info( "deleting permission " + permission.getName() );
+ turbineSecurityService.removePermission( permission );
+ permission = null;// not needed
+ }
+ catch ( UnknownEntityException e )
+ {
+ // not found / existing
+ log.error( e.getMessage(), e );
+ }
+ catch (Exception e ) {
+ log.error( e.getMessage(), e );
+ fail();
+ }
+ }
+
+ private void deleteRole( Role role )
+ {
+ try
+ {
+ if (role.getId() == null) {
+ role = turbineSecurityService.getRoleByName(role.getName() );
+ }
+ log.info( "deleting role " + role.getName() );
+ turbineSecurityService.removeRole( role );
+ role = null;
+ }
+ catch ( UnknownEntityException e )
+ {
+ // not found / existing
+ log.error( e.getMessage(), e );
+ }
+ catch (Exception e ) {
+ log.error( e.getMessage(), e );
+ fail();
+ }
+ }
+
+ private void deleteGroup( Group group )
+ {
+ try
+ {
+ if (group.getId() == null) {
+ group = turbineSecurityService.getGroupByName(group.getName() );
+ }
+ log.info( "deleting group " + group.getName() );
+
+ turbineSecurityService.removeGroup( group );
+ group = null;
+ }
+ catch ( UnknownEntityException e )
+ {
+ // not found / existing
+ log.error( e.getMessage(), e );
+ }
+ catch (Exception e ) {
+ log.error( e.getMessage(), e );
+ fail();
+ }
+ }
+
+ private void deleteUser( User user )
+ {
+ if ( onDeleteCascade )
+ {
+ try
+ {
+ // revokeAll is called before user delete
+ turbineSecurityService.removeUser( user );
+ log.info( "try to delete user " + user.getName() );
+ }
+ catch ( Exception e )
+ {
+ log.error( "deleting user " + user.getName() + " failed. " + e.getMessage() );
+ if ( e.getCause() != null && e.getCause() instanceof ConstraintViolationException )
+ {
+ log.info( "error due to " + e.getCause().getMessage() );
+ }
+ else
+ {
+ log.info( "error due to " + e.getMessage() );
+ }
+ }
+ }
+ else
+ {
+ log.info( "onDeleteCascade false, user " + user.getName() + " not deleted!" );
+ }
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/test/resources/log4j.properties b/src/main/resources/archetype-resources/src/test/resources/log4j.properties
new file mode 100644
index 0000000..651c914
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/test/resources/log4j.properties
@@ -0,0 +1,89 @@
+
+# Turbine logging configuration
+#
+# If we don't know the logging facility, put it into the
+# turbine.log
+#
+log4j.rootLogger = INFO, app, console
+
+
+log4j.logger.${package} = DEBUG, app, console
+log4j.additivity.${package} = false
+
+#
+# Avalon log
+#
+log4j.logger.avalon = DEBUG, app, console
+log4j.additivity.avalon = false
+
+
+#
+# sql log
+# allows TRACE
+log4j.logger.org.apache.torque.util = DEBUG, sql, console
+log4j.additivity.org.apache.torque.util = false
+
+#
+# Torque log
+# allows TRACE
+log4j.logger.org.apache.torque = DEBUG, torque
+log4j.additivity.org.apache.torque = false
+
+# turbine log
+# allows TRACE
+log4j.logger.org.apache.turbine = INFO, turbine
+log4j.additivity.org.apache.turbine = false
+
+
+# #
+# Logfile definitions
+#
+
+# application.log
+log4j.appender.app = org.apache.log4j.RollingFileAppender
+log4j.appender.app.file = src/test/logs/application.log
+log4j.appender.app.MaxFileSize=5MB
+log4j.appender.app.MaxBackupIndex=5
+log4j.appender.app.layout = org.apache.log4j.PatternLayout
+log4j.appender.app.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.app.append = true
+
+#
+# sql.log
+#
+log4j.appender.sql = org.apache.log4j.RollingFileAppender
+log4j.appender.sql.file = src/test/logs/sql.log
+log4j.appender.sql.MaxFileSize=5MB
+log4j.appender.sql.MaxBackupIndex=5
+log4j.appender.sql.layout = org.apache.log4j.PatternLayout
+log4j.appender.sql.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.sql.append = true
+
+#
+# console
+#
+log4j.appender.console = org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout = org.apache.log4j.PatternLayout
+log4j.appender.console.layout.conversionPattern = %d [%t] %-5p %C{1} - %m%n
+
+#
+# torque.log
+#
+log4j.appender.torque = org.apache.log4j.RollingFileAppender
+log4j.appender.torque.MaxFileSize=5MB
+log4j.appender.torque.MaxBackupIndex=5
+log4j.appender.torque.file = src/test/logs/torque.log
+log4j.appender.torque.layout = org.apache.log4j.PatternLayout
+log4j.appender.torque.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.torque.append = false
+
+#
+# turbine.log
+#
+log4j.appender.turbine = org.apache.log4j.RollingFileAppender
+log4j.appender.turbine.MaxFileSize=5MB
+log4j.appender.turbine.MaxBackupIndex=5
+log4j.appender.turbine.file = src/test/logs/turbine.log
+log4j.appender.turbine.layout = org.apache.log4j.PatternLayout
+log4j.appender.turbine.layout.conversionPattern = %d [%t] %-5p %c - %m%n
+log4j.appender.turbine.append = false
\ No newline at end of file
diff --git a/src/test/resources/projects/first/archetype.properties b/src/test/resources/projects/first/archetype.properties
new file mode 100644
index 0000000..0a96356
--- /dev/null
+++ b/src/test/resources/projects/first/archetype.properties
@@ -0,0 +1,13 @@
+groupId=org.apache.turbine.test
+artifactId=integrationtest
+version=1.0.0-SNAPSHOT
+package=org.apache.turbine.test.integrationtest
+turbine_app_name=My Turbine Web Application
+turbine_intake_file=intake.xml
+turbine_database_name=turbine
+turbine_database_adapter=auto
+turbine_database_jndipath=jdbc/turbine
+turbine_database_driver=com.mysql.jdbc.Driver
+turbine_database_url=jdbc:mysql://localhost:3306/
+turbine_database_user=db_user
+turbine_database_password=db_password
diff --git a/src/test/resources/projects/first/goal.txt b/src/test/resources/projects/first/goal.txt
new file mode 100644
index 0000000..597acc7
--- /dev/null
+++ b/src/test/resources/projects/first/goal.txt
@@ -0,0 +1 @@
+package
\ No newline at end of file