Merge branch 'master' of ../postgresql
This commit is contained in:
commit
4f6662f00c
|
@ -0,0 +1,4 @@
|
|||
target/
|
||||
.project
|
||||
.settings
|
||||
.classpath
|
|
@ -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.
|
|
@ -0,0 +1,72 @@
|
|||
li.strolch.persistence.postgresql
|
||||
=======================================================================
|
||||
|
||||
[![Build Status](http://jenkins.eitchnet.ch/buildStatus/icon?job=li.strolch.persistence.postgresql)](http://jenkins.eitchnet.ch/view/strolch/job/li.strolch.persistence.postgresql/)
|
||||
|
||||
PostgreSQL Persistence Implementation for Strolch
|
||||
|
||||
Setup
|
||||
=======================================================================
|
||||
1. Install PostgreSQL version with at least version 9.1:
|
||||
$ sudo aptitude install postgresql postgresql-client
|
||||
2. Set a password for user 'postgres'
|
||||
$ sudo -u postgres psql postgres
|
||||
postgres=# \password postgres
|
||||
3. Create the user and DB:
|
||||
$ sudo -u postgres psql
|
||||
$ postgres=#
|
||||
create user testUser with password 'test';
|
||||
create database testdb;
|
||||
GRANT ALL PRIVILEGES ON DATABASE testdb to testuser;
|
||||
GRANT CONNECT ON DATABASE testdb TO testuser ;
|
||||
|
||||
# For tests:
|
||||
create user testUser with password 'test';
|
||||
create database testdb;
|
||||
GRANT ALL PRIVILEGES ON DATABASE testdb to testuser;
|
||||
GRANT CONNECT ON DATABASE testdb TO testuser ;
|
||||
|
||||
create user testuser1 with password 'test';
|
||||
create database testdb1;
|
||||
GRANT ALL PRIVILEGES ON DATABASE testdb1 to testuser1;
|
||||
GRANT CONNECT ON DATABASE testdb1 TO testuser1 ;
|
||||
|
||||
create user testuser2 with password 'test';
|
||||
create database testdb2;
|
||||
GRANT ALL PRIVILEGES ON DATABASE testdb2 to testuser2;
|
||||
GRANT CONNECT ON DATABASE testdb2 TO testuser2 ;
|
||||
|
||||
4. Added new component, setting properties for PostgreSQL DB:
|
||||
<Component>
|
||||
<name>PersistenceHandler</name>
|
||||
<api>li.strolch.persistence.api.StrolchPersistenceHandler</api>
|
||||
<impl>li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler</impl>
|
||||
<Properties>
|
||||
<allowSchemaCreation>false</allowSchemaCreation>
|
||||
<db.url>jdbc:postgresql://localhost/testdb</db.url>
|
||||
<db.username>testUser</db.username>
|
||||
<db.password>test</db.password>
|
||||
</Properties>
|
||||
</Component>
|
||||
|
||||
5. Create tables, or allow strolch to due it for you.
|
||||
|
||||
|
||||
Appendix
|
||||
=======================================================================
|
||||
1. To drop the user and DB:
|
||||
postgres=# revoke ALL PRIVILEGES ON DATABASE testdb from testuser;
|
||||
postgres=# drop user testuser;
|
||||
postgres=# drop database testdb;
|
||||
2. Create a database:
|
||||
$ createdb -p 5432 -O drupal -U drupal -E UTF8 testingsiteone -T template0
|
||||
3. Dropping the database
|
||||
$ dropdb -p 5432 -U drupal testingsiteone
|
||||
4. Dumping the database
|
||||
$ pg_dump -p 5432 -h localhost -Fc -U drupal --no-owner testingsiteone > /tmp/testingsiteone_$(date +"%Y-%m-%d_%s").pgdump
|
||||
5. Restoring the database
|
||||
$ pg_restore -p 5432 -h localhost -Fc -d testingsiteone -U drupal --no-owner < /tmp/path-to-the-file.pgdump
|
||||
|
||||
References
|
||||
=======================================================================
|
||||
http://www.pixelite.co.nz/article/installing-and-configuring-postgresql-91-ubuntu-1204-local-drupal-development
|
|
@ -0,0 +1,102 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>li.strolch</groupId>
|
||||
<artifactId>li.strolch.parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../li.strolch.parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>li.strolch.persistence.postgresql</artifactId>
|
||||
|
||||
<name>li.strolch.persistence.postgresql</name>
|
||||
<description>PostgreSQL Persistence Implementation for Strolch</description>
|
||||
|
||||
<url>https://github.com/eitchnet/li.strolch.persistence.postgresql</url>
|
||||
|
||||
<inceptionYear>2011</inceptionYear>
|
||||
|
||||
<issueManagement>
|
||||
<system>Github Issues</system>
|
||||
<url>https://github.com/eitchnet/li.strolch.persistence.postgresql/issues</url>
|
||||
</issueManagement>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/eitchnet/li.strolch.persistence.postgresql.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:eitch/li.strolch.persistence.postgresql.git</developerConnection>
|
||||
<url>https://github.com/eitchnet/li.strolch.persistence.postgresql</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<!-- main -->
|
||||
<dependency>
|
||||
<groupId>li.strolch</groupId>
|
||||
<artifactId>li.strolch.model</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>li.strolch</groupId>
|
||||
<artifactId>li.strolch.agent</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>9.3-1100-jdbc41</version>
|
||||
</dependency>
|
||||
|
||||
<!-- test -->
|
||||
<dependency>
|
||||
<groupId>li.strolch</groupId>
|
||||
<artifactId>li.strolch.testbase</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>**/componentVersion.properties</include>
|
||||
</includes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>**/componentVersion.properties</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>buildnumber-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import li.strolch.persistence.api.TransactionResult;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public interface DaoCommand {
|
||||
|
||||
public void doComand(TransactionResult txResult);
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import li.strolch.persistence.api.DbConnectionInfo;
|
||||
import li.strolch.runtime.configuration.StrolchConfigurationException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class DbConnectionCheck {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DbConnectionCheck.class);
|
||||
private Map<String, DbConnectionInfo> connetionInfoMap;
|
||||
|
||||
/**
|
||||
* @param connetionInfoMap
|
||||
*/
|
||||
public DbConnectionCheck(Map<String, DbConnectionInfo> connetionInfoMap) {
|
||||
this.connetionInfoMap = connetionInfoMap;
|
||||
}
|
||||
|
||||
public void checkConnections() {
|
||||
Collection<DbConnectionInfo> values = this.connetionInfoMap.values();
|
||||
for (DbConnectionInfo connectionInfo : values) {
|
||||
|
||||
String url = connectionInfo.getUrl();
|
||||
String username = connectionInfo.getUsername();
|
||||
String password = connectionInfo.getPassword();
|
||||
|
||||
try (Connection con = DriverManager.getConnection(url, username, password);
|
||||
Statement st = con.createStatement();) {
|
||||
|
||||
try (ResultSet rs = st.executeQuery("select version()")) { //$NON-NLS-1$
|
||||
if (rs.next()) {
|
||||
logger.info(MessageFormat.format("Connected to: {0}", rs.getString(1))); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
String msg = "Failed to open DB connection to URL {0} due to: {1}"; //$NON-NLS-1$
|
||||
msg = MessageFormat.format(msg, url, e.getMessage());
|
||||
throw new StrolchConfigurationException(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import li.strolch.exception.StrolchException;
|
||||
import li.strolch.persistence.api.DbConnectionInfo;
|
||||
import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||
import li.strolch.runtime.configuration.StrolchConfigurationException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.eitchnet.utils.dbc.DBC;
|
||||
import ch.eitchnet.utils.helper.FileHelper;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
@SuppressWarnings(value = "nls")
|
||||
public class DbSchemaVersionCheck {
|
||||
|
||||
private static final String RESOURCE_DB_VERSION = "/db_version.properties";
|
||||
private static final String PROP_DB_VERSION = "db_version";
|
||||
private static final String PROP_ALLOW_SCHEMA_CREATION = "allowSchemaCreation";
|
||||
private static final String PROP_ALLOW_SCHEMA_DROP = "allowSchemaDrop";
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DbSchemaVersionCheck.class);
|
||||
private Map<String, DbConnectionInfo> connetionInfoMap;
|
||||
private boolean allowSchemaCreation;
|
||||
private boolean allowSchemaDrop;
|
||||
|
||||
/**
|
||||
* @param connetionInfoMap
|
||||
* @param componentConfiguration
|
||||
*/
|
||||
public DbSchemaVersionCheck(Map<String, DbConnectionInfo> connetionInfoMap,
|
||||
ComponentConfiguration componentConfiguration) {
|
||||
this.connetionInfoMap = connetionInfoMap;
|
||||
|
||||
this.allowSchemaCreation = componentConfiguration.getBoolean(PROP_ALLOW_SCHEMA_CREATION, Boolean.FALSE);
|
||||
this.allowSchemaDrop = componentConfiguration.getBoolean(PROP_ALLOW_SCHEMA_DROP, Boolean.FALSE);
|
||||
}
|
||||
|
||||
public void checkSchemaVersion() {
|
||||
|
||||
Collection<DbConnectionInfo> values = this.connetionInfoMap.values();
|
||||
|
||||
for (DbConnectionInfo connectionInfo : values) {
|
||||
String realm = connectionInfo.getRealm();
|
||||
String url = connectionInfo.getUrl();
|
||||
String username = connectionInfo.getUsername();
|
||||
String password = connectionInfo.getPassword();
|
||||
|
||||
logger.info(MessageFormat.format("[{0}] Checking Schema version for: {1}@{2}", realm, username, url));
|
||||
|
||||
try (Connection con = DriverManager.getConnection(url, username, password);
|
||||
Statement st = con.createStatement();) {
|
||||
|
||||
String expectedDbVersion = getExpectedDbVersion();
|
||||
|
||||
// first see if we have any schema
|
||||
String msg = "select table_schema, table_name, table_type from information_schema.tables where table_name=''{0}'';";
|
||||
String checkSchemaExistsSql = MessageFormat.format(msg, PROP_DB_VERSION);
|
||||
try (ResultSet rs = st.executeQuery(checkSchemaExistsSql)) {
|
||||
if (!rs.next()) {
|
||||
createSchema(realm, expectedDbVersion, st);
|
||||
} else {
|
||||
checkCurrentVersion(realm, st, expectedDbVersion);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
String msg = "Failed to open DB connection to URL {0} due to: {1}"; //$NON-NLS-1$
|
||||
msg = MessageFormat.format(msg, url, e.getMessage());
|
||||
throw new StrolchConfigurationException(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCurrentVersion(String realm, Statement st, String expectedDbVersion) throws SQLException {
|
||||
try (ResultSet rs = st.executeQuery("select id, version from db_version order by id desc;")) {
|
||||
if (!rs.next()) {
|
||||
createSchema(realm, expectedDbVersion, st);
|
||||
} else {
|
||||
String currentVersion = rs.getString(2);
|
||||
if (expectedDbVersion.equals(currentVersion)) {
|
||||
String msg = "[{0}] Schema version {1} is the current version. No changes needed.";
|
||||
msg = MessageFormat.format(msg, realm, currentVersion);
|
||||
logger.info(msg);
|
||||
} else {
|
||||
String msg = "[{0}] Schema version is not current. Need to upgrade from {1} to {2}";
|
||||
msg = MessageFormat.format(msg, realm, currentVersion, expectedDbVersion);
|
||||
logger.warn(msg);
|
||||
upgradeSchema(realm, expectedDbVersion, st);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getExpectedDbVersion() {
|
||||
Properties dbVersionProps = new Properties();
|
||||
try (InputStream stream = DbSchemaVersionCheck.class.getResourceAsStream(RESOURCE_DB_VERSION);) {
|
||||
DBC.PRE.assertNotNull(
|
||||
MessageFormat.format("Resource file with name {0} does not exist!", RESOURCE_DB_VERSION), stream);
|
||||
dbVersionProps.load(stream);
|
||||
} catch (IOException e) {
|
||||
String msg = "Expected resource file {0} does not exist or is not a valid properties file: {1}";
|
||||
msg = MessageFormat.format(msg, RESOURCE_DB_VERSION, e.getMessage());
|
||||
throw new StrolchException(msg, e);
|
||||
}
|
||||
String dbVersion = dbVersionProps.getProperty(PROP_DB_VERSION);
|
||||
String msg = "Missing property {0} in resource file {1}";
|
||||
DBC.PRE.assertNotEmpty(MessageFormat.format(msg, PROP_DB_VERSION, RESOURCE_DB_VERSION), dbVersion);
|
||||
return dbVersion;
|
||||
}
|
||||
|
||||
public static String getSql(String dbVersion, String type) {
|
||||
String schemaResourceS = MessageFormat.format("/db_schema_{0}_{1}.sql", dbVersion, type);
|
||||
try (InputStream stream = DbSchemaVersionCheck.class.getResourceAsStream(schemaResourceS);) {
|
||||
DBC.PRE.assertNotNull(
|
||||
MessageFormat.format("Schema Resource file with name {0} does not exist!", schemaResourceS), stream);
|
||||
return FileHelper.readStreamToString(stream);
|
||||
} catch (IOException e) {
|
||||
throw new StrolchException("Schema creation resource file is missing or could not be read: "
|
||||
+ schemaResourceS, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param realm
|
||||
* @param st
|
||||
*/
|
||||
private void createSchema(String realm, String dbVersion, Statement st) {
|
||||
|
||||
if (!this.allowSchemaCreation) {
|
||||
String msg = "[{0}] No schema exists, or is not valid. Schema generation is disabled, thus can not continue!";
|
||||
msg = MessageFormat.format(msg, realm);
|
||||
throw new StrolchConfigurationException(msg);
|
||||
}
|
||||
|
||||
logger.info(MessageFormat.format("[{0}] Creating initial schema...", realm));
|
||||
|
||||
String sql = getSql(dbVersion, "initial");
|
||||
try {
|
||||
st.execute(sql);
|
||||
} catch (SQLException e) {
|
||||
logger.error("Failed to execute schema creation SQL: \n" + sql);
|
||||
throw new StrolchException("Failed to execute schema generation SQL: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
logger.info(MessageFormat.format("[{0}] Successfully created schema for version {1}", realm, dbVersion));
|
||||
}
|
||||
|
||||
private void dropSchema(String realm, String dbVersion, Statement st) {
|
||||
|
||||
if (!this.allowSchemaDrop) {
|
||||
String msg = "[{0}] Dropping Schema is disabled, but is required to upgrade current schema...";
|
||||
msg = MessageFormat.format(msg, realm);
|
||||
throw new StrolchConfigurationException(msg);
|
||||
}
|
||||
|
||||
logger.info(MessageFormat.format("[{0}] Dropping existing schema...", realm));
|
||||
|
||||
String sql = getSql(dbVersion, "drop");
|
||||
try {
|
||||
st.execute(sql);
|
||||
} catch (SQLException e) {
|
||||
logger.error("Failed to execute schema drop SQL: \n" + sql);
|
||||
throw new StrolchException("Failed to execute schema drop SQL: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param st
|
||||
*/
|
||||
private void upgradeSchema(String realm, String dbVersion, Statement st) {
|
||||
dropSchema(realm, dbVersion, st);
|
||||
createSchema(realm, dbVersion, st);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import li.strolch.model.audit.AccessType;
|
||||
import li.strolch.model.audit.Audit;
|
||||
import li.strolch.model.audit.AuditQuery;
|
||||
import li.strolch.model.audit.AuditVisitor;
|
||||
import li.strolch.persistence.api.AuditDao;
|
||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||
import ch.eitchnet.utils.collections.DateRange;
|
||||
import ch.eitchnet.utils.helper.StringHelper;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PostgreSqlAuditDao implements AuditDao {
|
||||
|
||||
public static final String ID = "id";
|
||||
public static final String ACCESS_TYPE = "access_type";
|
||||
public static final String ACCESS_TYPE_TYPE = "::access_type";
|
||||
public static final String ACTION = "action";
|
||||
public static final String NEW_VERSION = "new_version";
|
||||
public static final String ELEMENT_ACCESSED = "element_accessed";
|
||||
public static final String ELEMENT_TYPE = "element_type";
|
||||
public static final String DATE = "date";
|
||||
public static final String LASTNAME = "lastname";
|
||||
public static final String FIRSTNAME = "firstname";
|
||||
public static final String USERNAME = "username";
|
||||
public static final String FIELDS = StringHelper.commaSeparated(ID, USERNAME, FIRSTNAME, LASTNAME, DATE,
|
||||
ELEMENT_TYPE, ELEMENT_ACCESSED, NEW_VERSION, ACTION, ACCESS_TYPE);
|
||||
public static final String TABLE_NAME = "audits";
|
||||
|
||||
private PostgreSqlStrolchTransaction tx;
|
||||
|
||||
/**
|
||||
* @param postgreSqlStrolchTransaction
|
||||
*/
|
||||
public PostgreSqlAuditDao(PostgreSqlStrolchTransaction postgreSqlStrolchTransaction) {
|
||||
this.tx = postgreSqlStrolchTransaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasElement(String type, Long id) {
|
||||
String sql = "select count(*) from " + TABLE_NAME + " where " + ELEMENT_TYPE + " = ? and " + ID + " = ?"; //$NON-NLS-1$
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
statement.setString(1, type);
|
||||
statement.setLong(2, id);
|
||||
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
result.next();
|
||||
long numberOfElements = result.getLong(1);
|
||||
if (numberOfElements == 0)
|
||||
return false;
|
||||
if (numberOfElements == 1)
|
||||
return true;
|
||||
|
||||
String msg = MessageFormat.format("Non unique number of elements with type {0} and id {1}", type, id); //$NON-NLS-1$
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long querySize(DateRange dateRange) {
|
||||
String sql = "select count(*) from " + TABLE_NAME + " where " + DATE + " between ? and ?"; //$NON-NLS-1$
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
statement.setDate(1, new Date(dateRange.getFromDate().getTime()), Calendar.getInstance());
|
||||
statement.setDate(2, new Date(dateRange.getToDate().getTime()), Calendar.getInstance());
|
||||
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
result.next();
|
||||
return result.getLong(1);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long querySize(String type, DateRange dateRange) {
|
||||
String sql = "select count(*) from " + TABLE_NAME + " where " + ELEMENT_TYPE + " = ? and " + DATE + " between ? and ?"; //$NON-NLS-1$
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
statement.setString(1, type);
|
||||
statement.setDate(2, new Date(dateRange.getFromDate().getTime()), Calendar.getInstance());
|
||||
statement.setDate(3, new Date(dateRange.getToDate().getTime()), Calendar.getInstance());
|
||||
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
result.next();
|
||||
return result.getLong(1);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryTypes() {
|
||||
Set<String> keySet = new HashSet<>();
|
||||
|
||||
String sql = "select distinct " + ELEMENT_TYPE + " from " + TABLE_NAME; //$NON-NLS-1$
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
while (result.next()) {
|
||||
keySet.add(result.getString(ELEMENT_TYPE));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Audit queryBy(String type, Long id) {
|
||||
|
||||
String sql = "select " + FIELDS + " from " + TABLE_NAME + " where " + ELEMENT_TYPE + " = ? and " + ID + " = ?"; //$NON-NLS-1$
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
statement.setString(1, type);
|
||||
statement.setLong(2, id);
|
||||
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
if (!result.next()) {
|
||||
return null;
|
||||
}
|
||||
Audit audit = auditFrom(result);
|
||||
if (result.next())
|
||||
throw new StrolchPersistenceException("Non unique result for query: " + sql); //$NON-NLS-1$
|
||||
return audit;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Audit> queryAll(String type, DateRange dateRange) {
|
||||
List<Audit> list = new ArrayList<>();
|
||||
String sql = "select " + FIELDS + " from " + TABLE_NAME + " where " + ELEMENT_TYPE + " = ? and " + DATE + " between ? and ?"; //$NON-NLS-1$
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
statement.setString(1, type);
|
||||
statement.setDate(2, new Date(dateRange.getFromDate().getTime()), Calendar.getInstance());
|
||||
statement.setDate(3, new Date(dateRange.getToDate().getTime()), Calendar.getInstance());
|
||||
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
while (result.next()) {
|
||||
list.add(auditFrom(result));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Audit audit) {
|
||||
String sql = "insert into " + TABLE_NAME + " (" + FIELDS + ") values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::access_type)"; //$NON-NLS-1$
|
||||
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
setAuditFields(audit, preparedStatement);
|
||||
|
||||
int count = preparedStatement.executeUpdate();
|
||||
if (count != 1) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"Expected to create 1 record, but created {0} for audit {2}", count, audit.getId())); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to update Audit {0} due to {1}", audit, //$NON-NLS-1$
|
||||
e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAll(List<Audit> audits) {
|
||||
for (Audit audit : audits) {
|
||||
save(audit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Audit audit) {
|
||||
String sql = "update " + TABLE_NAME + " set " + ID + " = ?, " + USERNAME + " = ?, " + FIRSTNAME + " = ?, "
|
||||
+ LASTNAME + " = ?, " + DATE + " = ?, " + ELEMENT_TYPE + " = ?, " + ELEMENT_ACCESSED + " = ?, "
|
||||
+ NEW_VERSION + " = ?, " + ACTION + " = ?, " + ACCESS_TYPE + " = ?::access_type where " + ID + " = ?"; //$NON-NLS-1$
|
||||
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
setAuditFields(audit, preparedStatement);
|
||||
preparedStatement.setLong(11, audit.getId());
|
||||
|
||||
int count = preparedStatement.executeUpdate();
|
||||
if (count != 1) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"Expected to update 1 record, but updated {0} for audit {2}", count, audit.getId())); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to update Audit {0} due to {1}", audit, //$NON-NLS-1$
|
||||
e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAll(List<Audit> audits) {
|
||||
for (Audit audit : audits) {
|
||||
update(audit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Audit audit) {
|
||||
String sql = "delete from " + TABLE_NAME + " where " + ID + " = ?"; //$NON-NLS-1$
|
||||
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
preparedStatement.setLong(1, audit.getId());
|
||||
|
||||
int count = preparedStatement.executeUpdate();
|
||||
if (count != 1) {
|
||||
String msg = "Expected to delete 1 audit with id {0} but deleted {1} elements!"; //$NON-NLS-1$
|
||||
msg = MessageFormat.format(msg, audit.getId(), count);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove {0} due to {2}", //$NON-NLS-1$
|
||||
audit.getId(), e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll(List<Audit> audits) {
|
||||
for (Audit audit : audits) {
|
||||
remove(audit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long removeAll(String type, DateRange dateRange) {
|
||||
String sql = "delete from " + TABLE_NAME + " where " + ELEMENT_TYPE + " = ? and " + DATE + " between ? and ?"; //$NON-NLS-1$
|
||||
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
preparedStatement.setString(1, type);
|
||||
preparedStatement.setDate(2, new Date(dateRange.getFromDate().getTime()), Calendar.getInstance());
|
||||
preparedStatement.setDate(3, new Date(dateRange.getToDate().getTime()), Calendar.getInstance());
|
||||
|
||||
int modCount = preparedStatement.executeUpdate();
|
||||
return modCount;
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove all elements due to {0}", //$NON-NLS-1$
|
||||
e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> List<U> doQuery(AuditQuery query, AuditVisitor<U> auditVisitor) {
|
||||
|
||||
PostgreSqlAuditQueryVisitor queryVisitor = new PostgreSqlAuditQueryVisitor(FIELDS);
|
||||
query.accept(queryVisitor);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setAuditFields(Audit audit, PreparedStatement ps) throws SQLException {
|
||||
|
||||
// 1 id = ?,
|
||||
// 2 username = ?,
|
||||
// 3 firstname = ?,
|
||||
// 4 lastname = ?,
|
||||
// 5 date = ?,
|
||||
// 6 element_type = ?,
|
||||
// 7 element_accessed = ?,
|
||||
// 8 new_version = ?,
|
||||
// 9 action = ?,
|
||||
// 10 access_type = ?::access_type
|
||||
|
||||
ps.setLong(1, audit.getId());
|
||||
ps.setString(2, audit.getUsername());
|
||||
ps.setString(3, audit.getFirstname());
|
||||
ps.setString(4, audit.getLastname());
|
||||
ps.setDate(5, new Date(audit.getDate().getTime()), Calendar.getInstance());
|
||||
ps.setString(6, audit.getElementType());
|
||||
ps.setString(7, audit.getElementAccessed());
|
||||
|
||||
if (audit.getNewVersion() == null)
|
||||
ps.setDate(8, null);
|
||||
else
|
||||
ps.setDate(8, new Date(audit.getNewVersion().getTime()), Calendar.getInstance());
|
||||
|
||||
ps.setString(9, audit.getAction());
|
||||
ps.setString(10, audit.getAccessType().name());
|
||||
}
|
||||
|
||||
private Audit auditFrom(ResultSet resultSet) throws SQLException {
|
||||
|
||||
Audit audit = new Audit();
|
||||
audit.setId(resultSet.getLong(1));
|
||||
audit.setUsername(resultSet.getString(2));
|
||||
audit.setFirstname(resultSet.getString(3));
|
||||
audit.setLastname(resultSet.getString(4));
|
||||
audit.setDate(resultSet.getDate(5));
|
||||
audit.setElementType(resultSet.getString(6));
|
||||
audit.setElementAccessed(resultSet.getString(7));
|
||||
audit.setNewVersion(resultSet.getDate(8));
|
||||
audit.setAction(resultSet.getString(9));
|
||||
audit.setAccessType(AccessType.valueOf(resultSet.getString(10)));
|
||||
return audit;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import li.strolch.model.audit.AccessType;
|
||||
import li.strolch.model.audit.ActionSelection;
|
||||
import li.strolch.model.audit.AuditQuery;
|
||||
import li.strolch.model.audit.AuditQueryVisitor;
|
||||
import li.strolch.model.audit.ElementSelection;
|
||||
import li.strolch.model.audit.IdentitySelection;
|
||||
import li.strolch.model.query.StringSelection;
|
||||
import ch.eitchnet.utils.StringMatchMode;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PostgreSqlAuditQueryVisitor implements AuditQueryVisitor {
|
||||
|
||||
protected StringBuilder sql;
|
||||
protected StringBuilder sb;
|
||||
protected List<Object> values;
|
||||
protected String indent;
|
||||
private String sqlAsString;
|
||||
|
||||
/**
|
||||
* @param fields
|
||||
*/
|
||||
public PostgreSqlAuditQueryVisitor(String fields) {
|
||||
this.indent = "";
|
||||
this.sql = new StringBuilder();
|
||||
this.sb = new StringBuilder();
|
||||
this.values = new ArrayList<>();
|
||||
|
||||
this.sql.append("select ");
|
||||
this.sql.append(fields);
|
||||
this.sql.append("\nfrom\n");
|
||||
this.sql.append(" ");
|
||||
this.sql.append(PostgreSqlAuditDao.TABLE_NAME);
|
||||
this.indent = " ";
|
||||
}
|
||||
|
||||
public String getSql() {
|
||||
if (this.sqlAsString != null)
|
||||
return this.sqlAsString;
|
||||
|
||||
this.sql.append("\nwhere\n");
|
||||
this.sql.append(this.sb.toString());
|
||||
this.sqlAsString = this.sql.toString();
|
||||
return this.sqlAsString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AuditQuery auditQuery) {
|
||||
ensureAnd();
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(PostgreSqlAuditDao.ELEMENT_TYPE);
|
||||
this.sb.append(" = ?\n");
|
||||
ensureAnd();
|
||||
this.values.add(auditQuery.getElementTypeSelection());
|
||||
PostgreSqlHelper.toSql(this.indent, this.sb, this.values, PostgreSqlAuditDao.DATE, auditQuery.getDateRange());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ElementSelection selection) {
|
||||
if (!selection.isElementsAccessedWildcard()) {
|
||||
StringSelection sel = selection.getElementAccessedSelection();
|
||||
toSql(PostgreSqlAuditDao.ELEMENT_ACCESSED, sel.getMatchMode(), sel.getValues());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IdentitySelection selection) {
|
||||
if (selection.isWildcard())
|
||||
return;
|
||||
|
||||
if (!selection.isFirstnameWildcard()) {
|
||||
StringSelection sel = selection.getFirstnameSelection();
|
||||
toSql(PostgreSqlAuditDao.FIRSTNAME, sel.getMatchMode(), sel.getValues());
|
||||
}
|
||||
|
||||
if (!selection.isLastnameWildcard()) {
|
||||
StringSelection sel = selection.getLastnameSelection();
|
||||
toSql(PostgreSqlAuditDao.LASTNAME, sel.getMatchMode(), sel.getValues());
|
||||
}
|
||||
|
||||
if (!selection.isUsernameWildcard()) {
|
||||
StringSelection sel = selection.getUsernameSelection();
|
||||
toSql(PostgreSqlAuditDao.USERNAME, sel.getMatchMode(), sel.getValues());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ActionSelection selection) {
|
||||
if (!selection.isWildcardAction()) {
|
||||
StringSelection sel = selection.getActionSelection();
|
||||
toSql(PostgreSqlAuditDao.ACTION, sel.getMatchMode(), sel.getValues());
|
||||
}
|
||||
|
||||
if (!selection.isWildcardActionType()) {
|
||||
|
||||
AccessType[] accessTypes = selection.getAccessTypes();
|
||||
ensureAnd();
|
||||
this.sb.append(this.indent);
|
||||
if (accessTypes.length == 1) {
|
||||
this.sb.append(PostgreSqlAuditDao.ACCESS_TYPE + " = ?");
|
||||
this.sb.append(PostgreSqlAuditDao.ACCESS_TYPE_TYPE);
|
||||
this.sb.append("\n");
|
||||
this.values.add(accessTypes[0].name());
|
||||
} else {
|
||||
this.sb.append(PostgreSqlAuditDao.ACCESS_TYPE + " in (");
|
||||
for (int i = 0; i < accessTypes.length; i++) {
|
||||
this.sb.append("?");
|
||||
this.sb.append(PostgreSqlAuditDao.ACCESS_TYPE_TYPE);
|
||||
this.values.add(accessTypes[i].name());
|
||||
if (i < accessTypes.length - 1)
|
||||
this.sb.append(", ");
|
||||
}
|
||||
this.sb.append(" )\n");
|
||||
this.sb.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void toSql(String column, StringMatchMode mm, String[] values) {
|
||||
ensureAnd();
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(PostgreSqlHelper.toSql(column, this.indent, mm, this.values, values));
|
||||
}
|
||||
|
||||
public void setValues(PreparedStatement ps) throws SQLException {
|
||||
for (int i = 0; i < this.values.size(); i++) {
|
||||
ps.setObject(i + 1, this.values.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureAnd() {
|
||||
if (this.sb.length() > 0) {
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append("and \n");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ch.eitchnet.utils.StringMatchMode;
|
||||
import ch.eitchnet.utils.collections.DateRange;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PostgreSqlHelper {
|
||||
|
||||
public static void toSql(String indent, StringBuilder sb, List<Object> values, String column, DateRange dateRange) {
|
||||
|
||||
// TODO handle inclusive/exclusive: between is inclusive
|
||||
|
||||
if (dateRange.isDate()) {
|
||||
sb.append(indent);
|
||||
sb.append(column);
|
||||
sb.append(" = ?\n");
|
||||
values.add(new Date(dateRange.getFromDate().getTime()));
|
||||
} else if (dateRange.isBounded()) {
|
||||
sb.append(indent);
|
||||
sb.append(column);
|
||||
sb.append(" between ? and ?\n");
|
||||
values.add(new Date(dateRange.getFromDate().getTime()));
|
||||
values.add(new Date(dateRange.getToDate().getTime()));
|
||||
} else if (dateRange.isToBounded()) {
|
||||
sb.append(indent);
|
||||
sb.append(column);
|
||||
sb.append(" <= ?\n");
|
||||
values.add(new Date(dateRange.getToDate().getTime()));
|
||||
} else if (dateRange.isFromBounded()) {
|
||||
sb.append(indent);
|
||||
sb.append(column);
|
||||
sb.append(" >= ?\n");
|
||||
values.add(new Date(dateRange.getFromDate().getTime()));
|
||||
}
|
||||
}
|
||||
|
||||
public static String toSql(String column, String indent, StringMatchMode mm, List<Object> values, String... query) {
|
||||
|
||||
// CS EQ
|
||||
// 1. x x
|
||||
// 2. x o
|
||||
// 3. o x
|
||||
// 4. o o
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (mm.isCaseSensitve() && mm.isEquals()) {
|
||||
if (query.length == 1) {
|
||||
sb.append(column + " = ?\n");
|
||||
values.add(query[0]);
|
||||
} else {
|
||||
sb.append(column + " in ( ");
|
||||
for (int i = 0; i < query.length; i++) {
|
||||
sb.append("?");
|
||||
values.add(query[i]);
|
||||
if (i < query.length - 1)
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(" )\n");
|
||||
}
|
||||
} else if (!mm.isCaseSensitve() && mm.isEquals()) {
|
||||
if (query.length == 1) {
|
||||
sb.append("lower(" + column + ") = ?\n");
|
||||
values.add(query[0].toLowerCase());
|
||||
} else {
|
||||
sb.append("lower(" + column + ") in ( ");
|
||||
for (int i = 0; i < query.length; i++) {
|
||||
sb.append("?");
|
||||
values.add(query[i].toLowerCase());
|
||||
if (i < query.length - 1)
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(" )\n");
|
||||
}
|
||||
} else if (!mm.isEquals() && mm.isCaseSensitve()) {
|
||||
if (query.length == 1) {
|
||||
sb.append(column + " like ?\n");
|
||||
values.add("%" + query[0] + "%");
|
||||
} else {
|
||||
sb.append("(\n");
|
||||
for (int i = 0; i < query.length; i++) {
|
||||
sb.append(indent);
|
||||
sb.append(" ");
|
||||
sb.append(column + " like ?");
|
||||
values.add("%" + query[i] + "%");
|
||||
if (i < query.length - 1)
|
||||
sb.append(" or");
|
||||
sb.append("\n");
|
||||
}
|
||||
sb.append(")\n");
|
||||
}
|
||||
} else {
|
||||
if (query.length == 1) {
|
||||
sb.append("lower(" + column + ") like ?\n");
|
||||
values.add("%" + query[0].toLowerCase() + "%");
|
||||
} else {
|
||||
sb.append("(\n");
|
||||
for (int i = 0; i < query.length; i++) {
|
||||
sb.append(indent);
|
||||
sb.append(" ");
|
||||
sb.append("lower(" + column + ") like ?");
|
||||
values.add("%" + query[i].toLowerCase() + "%");
|
||||
if (i < query.length - 1)
|
||||
sb.append(" or");
|
||||
sb.append("\n");
|
||||
}
|
||||
sb.append(")\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ArrayList<Object> values = new ArrayList<>();
|
||||
String sql = toSql("name", " ", StringMatchMode.CONTAINS_CASE_INSENSITIVE, values, "foo", "bar", "fub");
|
||||
System.out.println(sql);
|
||||
System.out.println();
|
||||
|
||||
sql = toSql("name", " ", StringMatchMode.CONTAINS_CASE_INSENSITIVE, values, "foo");
|
||||
System.out.println(sql);
|
||||
System.out.println();
|
||||
|
||||
sql = toSql("name", " ", StringMatchMode.CONTAINS_CASE_SENSITIVE, values, "foo", "bar", "fub");
|
||||
System.out.println(sql);
|
||||
System.out.println();
|
||||
|
||||
sql = toSql("name", " ", StringMatchMode.CONTAINS_CASE_SENSITIVE, values, "foo");
|
||||
System.out.println(sql);
|
||||
System.out.println();
|
||||
|
||||
sql = toSql("name", " ", StringMatchMode.EQUALS_CASE_INSENSITIVE, values, "foo", "bar", "fub");
|
||||
System.out.println(sql);
|
||||
System.out.println();
|
||||
|
||||
sql = toSql("name", " ", StringMatchMode.EQUALS_CASE_INSENSITIVE, values, "foo");
|
||||
System.out.println(sql);
|
||||
System.out.println();
|
||||
|
||||
sql = toSql("name", " ", StringMatchMode.EQUALS_CASE_SENSITIVE, values, "foo", "bar", "fub");
|
||||
System.out.println(sql);
|
||||
System.out.println();
|
||||
|
||||
sql = toSql("name", " ", StringMatchMode.EQUALS_CASE_SENSITIVE, values, "foo");
|
||||
System.out.println(sql);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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 exporders or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Date;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLXML;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import li.strolch.model.Order;
|
||||
import li.strolch.model.OrderVisitor;
|
||||
import li.strolch.model.Tags;
|
||||
import li.strolch.model.query.OrderQuery;
|
||||
import li.strolch.model.xml.OrderToSaxVisitor;
|
||||
import li.strolch.model.xml.SimpleStrolchElementListener;
|
||||
import li.strolch.model.xml.XmlModelSaxReader;
|
||||
import li.strolch.persistence.api.OrderDao;
|
||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao {
|
||||
|
||||
public static final String ORDERS = "orders";
|
||||
|
||||
/**
|
||||
* @param tx
|
||||
*/
|
||||
public PostgreSqlOrderDao(PostgreSqlStrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getClassName() {
|
||||
return Tags.ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTableName() {
|
||||
return ORDERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Order parseFromXml(String id, String type, SQLXML sqlxml) {
|
||||
SimpleStrolchElementListener listener = new SimpleStrolchElementListener();
|
||||
try (InputStream binaryStream = sqlxml.getBinaryStream()) {
|
||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||
parser.parse(binaryStream, new XmlModelSaxReader(listener));
|
||||
} catch (SQLException | IOException | SAXException | ParserConfigurationException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"Failed to extract Order from sqlxml value for {0} / {1}", id, type));
|
||||
}
|
||||
|
||||
if (listener.getOrders().size() == 0)
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"No Orders parsed from sqlxml value for {0} / {1}", id, type));
|
||||
if (listener.getOrders().size() > 1)
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"Multiple Orders parsed from sqlxml value for {0} / {1}", id, type));
|
||||
|
||||
return listener.getOrders().get(0);
|
||||
}
|
||||
|
||||
protected SQLXML createSqlXml(Order order, PreparedStatement preparedStatement) throws SQLException, SAXException {
|
||||
SQLXML sqlxml = this.tx.getConnection().createSQLXML();
|
||||
SAXResult saxResult = sqlxml.setResult(SAXResult.class);
|
||||
ContentHandler contentHandler = saxResult.getHandler();
|
||||
contentHandler.startDocument();
|
||||
new OrderToSaxVisitor(contentHandler).visit(order);
|
||||
contentHandler.endDocument();
|
||||
return sqlxml;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalSave(final Order order) {
|
||||
String sql = "insert into " + getTableName()
|
||||
+ " (id, name, type, state, date, asxml) values (?, ?, ?, ?::order_state, ?, ?)";
|
||||
try (PreparedStatement preparedStatement = PostgreSqlOrderDao.this.tx.getConnection().prepareStatement(sql)) {
|
||||
preparedStatement.setString(1, order.getId());
|
||||
preparedStatement.setString(2, order.getName());
|
||||
preparedStatement.setString(3, order.getType());
|
||||
preparedStatement.setString(4, order.getState().name());
|
||||
preparedStatement.setDate(5, new Date(order.getDate().getTime()), Calendar.getInstance());
|
||||
|
||||
SQLXML sqlxml = createSqlXml(order, preparedStatement);
|
||||
preparedStatement.setSQLXML(6, sqlxml);
|
||||
try {
|
||||
int modCount = preparedStatement.executeUpdate();
|
||||
if (modCount != 1) {
|
||||
String msg = "Expected to save 1 element with id {0} but SQL statement modified {1} elements!";
|
||||
msg = MessageFormat.format(msg, order.getId(), modCount);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
} finally {
|
||||
sqlxml.free();
|
||||
}
|
||||
|
||||
} catch (SQLException | SAXException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Order {0} due to {1}",
|
||||
order.getLocator(), e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalUpdate(final Order order) {
|
||||
String sql = "update " + getTableName()
|
||||
+ " set name = ?, type = ?, state = ?::order_state, date = ?, asxml = ? where id = ? ";
|
||||
try (PreparedStatement preparedStatement = PostgreSqlOrderDao.this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
preparedStatement.setString(1, order.getName());
|
||||
preparedStatement.setString(2, order.getType());
|
||||
preparedStatement.setString(3, order.getState().name());
|
||||
preparedStatement.setDate(4, new Date(order.getDate().getTime()), Calendar.getInstance());
|
||||
preparedStatement.setString(6, order.getId());
|
||||
|
||||
SQLXML sqlxml = createSqlXml(order, preparedStatement);
|
||||
preparedStatement.setSQLXML(5, sqlxml);
|
||||
try {
|
||||
int modCount = preparedStatement.executeUpdate();
|
||||
if (modCount != 1) {
|
||||
String msg = "Expected to update 1 element with id {0} but SQL statement modified {1} elements!";
|
||||
msg = MessageFormat.format(msg, order.getId(), modCount);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
} finally {
|
||||
sqlxml.free();
|
||||
}
|
||||
|
||||
} catch (SQLException | SAXException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to update Order {0} due to {1}",
|
||||
order.getLocator(), e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> List<U> doQuery(OrderQuery query, OrderVisitor<U> orderVisitor) {
|
||||
|
||||
PostgreSqlOrderQueryVisitor queryVisitor = new PostgreSqlOrderQueryVisitor("id, asxml");
|
||||
query.accept(queryVisitor);
|
||||
queryVisitor.validate();
|
||||
|
||||
List<U> list = new ArrayList<>();
|
||||
|
||||
String sql = queryVisitor.getSql();
|
||||
try (PreparedStatement ps = PostgreSqlOrderDao.this.tx.getConnection().prepareStatement(sql)) {
|
||||
queryVisitor.setValues(ps);
|
||||
|
||||
try (ResultSet result = ps.executeQuery()) {
|
||||
while (result.next()) {
|
||||
String id = result.getString("id");
|
||||
SQLXML sqlxml = result.getSQLXML("asxml");
|
||||
Order t = parseFromXml(id, queryVisitor.getType(), sqlxml);
|
||||
list.add(orderVisitor.visit(t));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to perform query due to: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import li.strolch.model.Tags;
|
||||
import li.strolch.model.query.DateSelection;
|
||||
import li.strolch.model.query.OrderQueryVisitor;
|
||||
import li.strolch.model.query.StateSelection;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PostgreSqlOrderQueryVisitor extends PostgreSqlQueryVisitor implements OrderQueryVisitor {
|
||||
|
||||
/**
|
||||
* @param fields
|
||||
*/
|
||||
public PostgreSqlOrderQueryVisitor(String fields) {
|
||||
super(fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getClassName() {
|
||||
return Tags.ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTableName() {
|
||||
return PostgreSqlOrderDao.ORDERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DateSelection selection) {
|
||||
PostgreSqlHelper.toSql(this.indent, this.sb, this.values, "date", selection.getDateRange());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StateSelection selection) {
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append("state = ?::order_state\n");
|
||||
this.values.add(selection.getState().name());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import static ch.eitchnet.utils.helper.StringHelper.DOT;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import li.strolch.agent.api.ComponentContainer;
|
||||
import li.strolch.agent.api.StrolchComponent;
|
||||
import li.strolch.agent.api.StrolchRealm;
|
||||
import li.strolch.persistence.api.AuditDao;
|
||||
import li.strolch.persistence.api.DbConnectionInfo;
|
||||
import li.strolch.persistence.api.OrderDao;
|
||||
import li.strolch.persistence.api.PersistenceHandler;
|
||||
import li.strolch.persistence.api.ResourceDao;
|
||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.runtime.StrolchConstants;
|
||||
import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||
import li.strolch.runtime.configuration.StrolchConfigurationException;
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PostgreSqlPersistenceHandler extends StrolchComponent implements PersistenceHandler {
|
||||
|
||||
private static final String PROP_DB_URL = "db.url"; //$NON-NLS-1$
|
||||
private static final String PROP_DB_USERNAME = "db.username"; //$NON-NLS-1$
|
||||
private static final String PROP_DB_PASSWORD = "db.password"; //$NON-NLS-1$
|
||||
|
||||
private ComponentConfiguration componentConfiguration;
|
||||
private Map<String, DbConnectionInfo> connetionInfoMap;
|
||||
|
||||
public PostgreSqlPersistenceHandler(ComponentContainer container, String componentName) {
|
||||
super(container, componentName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(ComponentConfiguration componentConfiguration) {
|
||||
|
||||
this.componentConfiguration = componentConfiguration;
|
||||
this.connetionInfoMap = new HashMap<>();
|
||||
|
||||
Set<String> realmNames = getContainer().getRealmNames();
|
||||
for (String realmName : realmNames) {
|
||||
|
||||
StrolchRealm realm = getContainer().getRealm(realmName);
|
||||
if (realm.getMode().isTransient())
|
||||
continue;
|
||||
|
||||
String dbUrlKey = PROP_DB_URL;
|
||||
String dbUsernameKey = PROP_DB_USERNAME;
|
||||
String dbPasswordKey = PROP_DB_PASSWORD;
|
||||
if (!realmName.equals(StrolchConstants.DEFAULT_REALM)) {
|
||||
dbUrlKey += DOT + realmName;
|
||||
dbUsernameKey += DOT + realmName;
|
||||
dbPasswordKey += DOT + realmName;
|
||||
}
|
||||
|
||||
String dbUrl = componentConfiguration.getString(dbUrlKey, null);
|
||||
String username = componentConfiguration.getString(dbUsernameKey, null);
|
||||
String password = componentConfiguration.getString(dbPasswordKey, null);
|
||||
|
||||
DbConnectionInfo connectionInfo = new DbConnectionInfo(realmName, dbUrl);
|
||||
connectionInfo.setUsername(username);
|
||||
connectionInfo.setPassword(password);
|
||||
|
||||
loadDriverForConnection(connectionInfo);
|
||||
this.connetionInfoMap.put(realmName, connectionInfo);
|
||||
}
|
||||
|
||||
super.initialize(componentConfiguration);
|
||||
}
|
||||
|
||||
private void loadDriverForConnection(DbConnectionInfo connectionInfo) {
|
||||
Driver driver;
|
||||
try {
|
||||
// server loader does not seem to work in all contexts, thus:
|
||||
org.postgresql.Driver.getLogLevel();
|
||||
|
||||
driver = DriverManager.getDriver(connectionInfo.getUrl());
|
||||
} catch (SQLException e) {
|
||||
String msg = "Failed to load DB driver for URL {0} due to: {1}"; //$NON-NLS-1$
|
||||
msg = MessageFormat.format(msg, connectionInfo.getUrl(), e.getMessage());
|
||||
throw new StrolchConfigurationException(msg, e);
|
||||
}
|
||||
|
||||
String compliant = driver.jdbcCompliant() ? "" : "non"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
String msg = "Realm {0}: Using {1} JDBC compliant Driver {2}.{3}"; //$NON-NLS-1$
|
||||
msg = MessageFormat.format(msg, connectionInfo.getRealm(), compliant, driver.getMajorVersion(),
|
||||
driver.getMinorVersion());
|
||||
logger.info(msg);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
// test all connections
|
||||
DbConnectionCheck connectionCheck = new DbConnectionCheck(this.connetionInfoMap);
|
||||
connectionCheck.checkConnections();
|
||||
|
||||
DbSchemaVersionCheck schemaVersionCheck = new DbSchemaVersionCheck(this.connetionInfoMap,
|
||||
this.componentConfiguration);
|
||||
schemaVersionCheck.checkSchemaVersion();
|
||||
|
||||
super.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StrolchTransaction openTx(StrolchRealm realm, Certificate certificate, String action) {
|
||||
return new PostgreSqlStrolchTransaction(getContainer().getPrivilegeHandler(), realm, certificate, action, this);
|
||||
}
|
||||
|
||||
Connection getConnection(String realm) {
|
||||
DbConnectionInfo dbInfo = this.connetionInfoMap.get(realm);
|
||||
if (dbInfo == null) {
|
||||
String msg = MessageFormat.format("There is no connection registered for the realm {0}", realm); //$NON-NLS-1$
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
|
||||
try {
|
||||
String url = dbInfo.getUrl();
|
||||
String username = dbInfo.getUsername();
|
||||
String password = dbInfo.getPassword();
|
||||
Connection connection = DriverManager.getConnection(url, username, password);
|
||||
connection.setAutoCommit(false);
|
||||
return connection;
|
||||
} catch (SQLException e) {
|
||||
String msg = MessageFormat.format("Failed to get a connection for {0} due to {1}", dbInfo, e.getMessage()); //$NON-NLS-1$
|
||||
throw new StrolchPersistenceException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderDao getOrderDao(StrolchTransaction tx) {
|
||||
return ((PostgreSqlStrolchTransaction) tx).getOrderDao();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceDao getResourceDao(StrolchTransaction tx) {
|
||||
return ((PostgreSqlStrolchTransaction) tx).getResourceDao();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuditDao getAuditDao(StrolchTransaction tx) {
|
||||
return ((PostgreSqlStrolchTransaction) tx).getAuditDao();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import static li.strolch.persistence.postgresql.PostgreSqlHelper.toSql;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import li.strolch.model.query.AndSelection;
|
||||
import li.strolch.model.query.IdSelection;
|
||||
import li.strolch.model.query.NameSelection;
|
||||
import li.strolch.model.query.NotSelection;
|
||||
import li.strolch.model.query.OrSelection;
|
||||
import li.strolch.model.query.ParameterBagSelection;
|
||||
import li.strolch.model.query.ParameterBagSelection.NullParameterBagSelection;
|
||||
import li.strolch.model.query.ParameterSelection.BooleanParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelection.DateParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelection.DateRangeParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelection.FloatParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelection.IntegerParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelection.LongParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelection.NullParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelection.StringListParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelection.StringParameterSelection;
|
||||
import li.strolch.model.query.ParameterSelectionVisitor;
|
||||
import li.strolch.model.query.Selection;
|
||||
import li.strolch.model.query.StrolchRootElementSelectionVisitor;
|
||||
import li.strolch.model.query.StrolchTypeNavigation;
|
||||
import ch.eitchnet.utils.StringMatchMode;
|
||||
import ch.eitchnet.utils.dbc.DBC;
|
||||
import ch.eitchnet.utils.iso8601.ISO8601FormatFactory;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public abstract class PostgreSqlQueryVisitor implements StrolchRootElementSelectionVisitor, ParameterSelectionVisitor {
|
||||
|
||||
protected StringBuilder sql;
|
||||
protected StringBuilder sb;
|
||||
protected String type;
|
||||
protected List<Object> values;
|
||||
protected boolean any;
|
||||
protected String indent;
|
||||
private String sqlAsString;
|
||||
|
||||
public PostgreSqlQueryVisitor(String fields) {
|
||||
this.indent = "";
|
||||
this.sql = new StringBuilder();
|
||||
this.sb = new StringBuilder();
|
||||
this.values = new ArrayList<>();
|
||||
|
||||
this.sql.append("select ");
|
||||
this.sql.append(fields);
|
||||
this.sql.append("\nfrom\n");
|
||||
this.sql.append(" ");
|
||||
this.sql.append(getTableName());
|
||||
this.indent = " ";
|
||||
}
|
||||
|
||||
public String getSql() {
|
||||
if (this.sqlAsString != null)
|
||||
return this.sqlAsString;
|
||||
|
||||
this.sql.append("\nwhere\n");
|
||||
this.sql.append(this.indent);
|
||||
|
||||
if (this.any) {
|
||||
this.sql.append("type = ?");
|
||||
this.sqlAsString = this.sql.toString();
|
||||
return this.sqlAsString;
|
||||
}
|
||||
|
||||
this.sql.append("type = ? and\n");
|
||||
|
||||
this.sql.append(this.sb.toString());
|
||||
this.sqlAsString = this.sql.toString();
|
||||
return this.sqlAsString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the any
|
||||
*/
|
||||
public boolean isAny() {
|
||||
return this.any;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
DBC.INTERIM.assertNotEmpty("No navigation was set!", this.type);
|
||||
}
|
||||
|
||||
protected abstract String getClassName();
|
||||
|
||||
protected abstract String getTableName();
|
||||
|
||||
@Override
|
||||
public void visit(StrolchTypeNavigation navigation) {
|
||||
this.type = navigation.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IdSelection selection) {
|
||||
this.sb.append(this.indent);
|
||||
List<String> ids = selection.getIds();
|
||||
if (ids.isEmpty())
|
||||
return;
|
||||
int size = ids.size();
|
||||
if (size == 1) {
|
||||
this.sb.append("id = ?\n");
|
||||
this.values.add(ids.get(0));
|
||||
} else {
|
||||
this.sb.append("id in (");
|
||||
Iterator<String> iter = ids.iterator();
|
||||
while (iter.hasNext()) {
|
||||
String id = iter.next();
|
||||
this.sb.append("?");
|
||||
this.values.add(id);
|
||||
if (iter.hasNext())
|
||||
this.sb.append(", ");
|
||||
}
|
||||
this.sb.append(" )\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NameSelection selection) {
|
||||
this.sb.append(this.indent);
|
||||
String name = selection.getName();
|
||||
StringMatchMode mm = selection.getMatchMode();
|
||||
this.sb.append(toSql("name", this.indent, mm, this.values, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAny() {
|
||||
this.any = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAnd(AndSelection andSelection) {
|
||||
this.sb.append(this.indent);
|
||||
List<Selection> selections = andSelection.getSelections();
|
||||
this.sb.append("( \n");
|
||||
Iterator<Selection> iter = selections.iterator();
|
||||
String indent = this.indent;
|
||||
this.indent += " ";
|
||||
while (iter.hasNext()) {
|
||||
Selection selection = iter.next();
|
||||
selection.accept(this);
|
||||
if (iter.hasNext()) {
|
||||
this.sb.append(indent);
|
||||
this.sb.append("and\n");
|
||||
}
|
||||
}
|
||||
this.indent = indent;
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(")\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOr(OrSelection orSelection) {
|
||||
this.sb.append(this.indent);
|
||||
List<Selection> selections = orSelection.getSelections();
|
||||
this.sb.append("( \n");
|
||||
Iterator<Selection> iter = selections.iterator();
|
||||
String indent = this.indent;
|
||||
this.indent += " ";
|
||||
while (iter.hasNext()) {
|
||||
Selection selection = iter.next();
|
||||
selection.accept(this);
|
||||
if (iter.hasNext()) {
|
||||
this.sb.append(indent);
|
||||
this.sb.append("or\n");
|
||||
}
|
||||
}
|
||||
this.indent = indent;
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(")\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNot(NotSelection notSelection) {
|
||||
this.sb.append(this.indent);
|
||||
List<Selection> selections = notSelection.getSelections();
|
||||
this.sb.append("not ( \n");
|
||||
Iterator<Selection> iter = selections.iterator();
|
||||
String indent = this.indent;
|
||||
this.indent += " ";
|
||||
while (iter.hasNext()) {
|
||||
Selection selection = iter.next();
|
||||
selection.accept(this);
|
||||
if (iter.hasNext()) {
|
||||
this.sb.append(indent);
|
||||
this.sb.append("and\n");
|
||||
}
|
||||
}
|
||||
this.indent = indent;
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(")\n");
|
||||
}
|
||||
|
||||
private void xpath(String bagKey, String paramKey, String paramValue) {
|
||||
String xpath = "cast(xpath('//Resource/ParameterBag[@Id=\"${bagKey}\"]/Parameter[@Id=\"${paramKey}\" and @Value=\"${paramValue}\"]', asxml) as text[]) != '{}'\n";
|
||||
this.sb.append(this.indent);
|
||||
xpath = xpath.replace("${bagKey}", bagKey);
|
||||
xpath = xpath.replace("${paramKey}", paramKey);
|
||||
xpath = xpath.replace("${paramValue}", paramValue);
|
||||
this.sb.append(xpath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StringParameterSelection selection) {
|
||||
String value = selection.getValue();
|
||||
|
||||
String xpath = "xpath('//Resource/ParameterBag[@Id=\"${bagKey}\"]/Parameter[@Id=\"${paramKey}\"]/@Value', asxml))::TEXT AS content";
|
||||
xpath = xpath.replace("${bagKey}", selection.getBagKey());
|
||||
xpath = xpath.replace("${paramKey}", selection.getParamKey());
|
||||
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append("id in (\n");
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(" SELECT id\n");
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(" FROM (\n");
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(" SELECT id, UNNEST(");
|
||||
this.sb.append(xpath);
|
||||
this.sb.append("\n");
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append("from ");
|
||||
this.sb.append(getTableName());
|
||||
this.sb.append("\n");
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(") AS alias\n");
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append("WHERE ");
|
||||
|
||||
if (selection.getMatchMode().isEquals()) {
|
||||
if (selection.getMatchMode().isCaseSensitve()) {
|
||||
this.sb.append("content = ?\n");
|
||||
} else {
|
||||
this.sb.append("content ILIKE ?\n");
|
||||
}
|
||||
} else {
|
||||
value = "%" + value + "%";
|
||||
if (selection.getMatchMode().isCaseSensitve()) {
|
||||
this.sb.append("content LIKE ?\n");
|
||||
} else {
|
||||
this.sb.append("content ILIKE ?\n");
|
||||
}
|
||||
}
|
||||
|
||||
this.sb.append(this.indent);
|
||||
this.sb.append(")\n");
|
||||
|
||||
this.values.add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IntegerParameterSelection selection) {
|
||||
xpath(selection.getBagKey(), selection.getParamKey(), selection.getValue().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BooleanParameterSelection selection) {
|
||||
xpath(selection.getBagKey(), selection.getParamKey(), selection.getValue().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LongParameterSelection selection) {
|
||||
xpath(selection.getBagKey(), selection.getParamKey(), selection.getValue().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FloatParameterSelection selection) {
|
||||
xpath(selection.getBagKey(), selection.getParamKey(), selection.getValue().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DateParameterSelection selection) {
|
||||
xpath(selection.getBagKey(), selection.getParamKey(),
|
||||
ISO8601FormatFactory.getInstance().formatDate(selection.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullParameterSelection selection) {
|
||||
String xpath = "cast(xpath('//Resource/ParameterBag[@Id=\"${bagKey}\"]/Parameter[@Id=\"${paramKey}\"]', asxml) as text[]) = '{}'\n";
|
||||
this.sb.append(this.indent);
|
||||
xpath = xpath.replace("${bagKey}", selection.getBagKey());
|
||||
xpath = xpath.replace("${paramKey}", selection.getParamKey());
|
||||
this.sb.append(xpath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ParameterBagSelection selection) {
|
||||
String xpath = "cast(xpath('//Resource/ParameterBag[@Id=\"${bagKey}\"]', asxml) as text[]) != '{}'\n";
|
||||
this.sb.append(this.indent);
|
||||
xpath = xpath.replace("${bagKey}", selection.getBagKey());
|
||||
this.sb.append(xpath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullParameterBagSelection selection) {
|
||||
String xpath = "cast(xpath('//Resource/ParameterBag[@Id=\"${bagKey}\"]', asxml) as text[]) = '{}'\n";
|
||||
this.sb.append(this.indent);
|
||||
xpath = xpath.replace("${bagKey}", selection.getBagKey());
|
||||
this.sb.append(xpath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DateRangeParameterSelection selection) {
|
||||
throw new UnsupportedOperationException("Not yet supported!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StringListParameterSelection selection) {
|
||||
throw new UnsupportedOperationException("Not yet supported!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ps
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void setValues(PreparedStatement ps) throws SQLException {
|
||||
if (this.any) {
|
||||
ps.setString(1, this.type);
|
||||
return;
|
||||
}
|
||||
|
||||
ps.setString(1, this.type);
|
||||
for (int i = 0; i < this.values.size(); i++) {
|
||||
ps.setObject(i + 2, this.values.get(i));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLXML;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import li.strolch.model.Resource;
|
||||
import li.strolch.model.ResourceVisitor;
|
||||
import li.strolch.model.Tags;
|
||||
import li.strolch.model.query.ResourceQuery;
|
||||
import li.strolch.model.xml.ResourceToSaxVisitor;
|
||||
import li.strolch.model.xml.SimpleStrolchElementListener;
|
||||
import li.strolch.model.xml.XmlModelSaxReader;
|
||||
import li.strolch.persistence.api.ResourceDao;
|
||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements ResourceDao {
|
||||
|
||||
public static final String RESOURCES = "resources";
|
||||
|
||||
protected PostgreSqlResourceDao(PostgreSqlStrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getClassName() {
|
||||
return Tags.RESOURCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTableName() {
|
||||
return RESOURCES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Resource parseFromXml(String id, String type, SQLXML sqlxml) {
|
||||
SimpleStrolchElementListener listener = new SimpleStrolchElementListener();
|
||||
try (InputStream binaryStream = sqlxml.getBinaryStream()) {
|
||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||
parser.parse(binaryStream, new XmlModelSaxReader(listener));
|
||||
} catch (SQLException | IOException | SAXException | ParserConfigurationException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"Failed to extract Resource from sqlxml value for {0} / {1}", id, type));
|
||||
}
|
||||
|
||||
if (listener.getResources().size() == 0)
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"No Resource parsed from sqlxml value for {0} / {1}", id, type));
|
||||
if (listener.getResources().size() > 1)
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"Multiple Resources parsed from sqlxml value for {0} / {1}", id, type));
|
||||
|
||||
return listener.getResources().get(0);
|
||||
}
|
||||
|
||||
protected SQLXML createSqlXml(Resource res, PreparedStatement preparedStatement) throws SQLException, SAXException {
|
||||
SQLXML sqlxml = this.tx.getConnection().createSQLXML();
|
||||
SAXResult saxResult = sqlxml.setResult(SAXResult.class);
|
||||
ContentHandler contentHandler = saxResult.getHandler();
|
||||
contentHandler.startDocument();
|
||||
new ResourceToSaxVisitor(contentHandler).visit(res);
|
||||
contentHandler.endDocument();
|
||||
return sqlxml;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalSave(final Resource res) {
|
||||
String sql = "insert into " + getTableName() + " (id, name, type, asxml) values (?, ?, ?, ?)";
|
||||
try (PreparedStatement preparedStatement = PostgreSqlResourceDao.this.tx.getConnection().prepareStatement(sql)) {
|
||||
preparedStatement.setString(1, res.getId());
|
||||
preparedStatement.setString(2, res.getName());
|
||||
preparedStatement.setString(3, res.getType());
|
||||
|
||||
SQLXML sqlxml = createSqlXml(res, preparedStatement);
|
||||
preparedStatement.setSQLXML(4, sqlxml);
|
||||
try {
|
||||
int modCount = preparedStatement.executeUpdate();
|
||||
if (modCount != 1) {
|
||||
String msg = "Expected to save 1 element with id {0} but SQL statement modified {1} elements!";
|
||||
msg = MessageFormat.format(msg, res.getId(), modCount);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
} finally {
|
||||
sqlxml.free();
|
||||
}
|
||||
|
||||
} catch (SQLException | SAXException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Resource {0} due to {1}",
|
||||
res.getLocator(), e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalUpdate(final Resource resource) {
|
||||
String sql = "update " + getTableName() + " set name = ?, type = ?, asxml = ? where id = ? ";
|
||||
try (PreparedStatement preparedStatement = PostgreSqlResourceDao.this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
preparedStatement.setString(1, resource.getName());
|
||||
preparedStatement.setString(2, resource.getType());
|
||||
preparedStatement.setString(4, resource.getId());
|
||||
|
||||
SQLXML sqlxml = createSqlXml(resource, preparedStatement);
|
||||
preparedStatement.setSQLXML(3, sqlxml);
|
||||
try {
|
||||
int modCount = preparedStatement.executeUpdate();
|
||||
if (modCount != 1) {
|
||||
String msg = "Expected to update 1 element with id {0} but SQL statement modified {1} elements!";
|
||||
msg = MessageFormat.format(msg, resource.getId(), modCount);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
} finally {
|
||||
sqlxml.free();
|
||||
}
|
||||
|
||||
} catch (SQLException | SAXException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to update Resource {0} due to {1}",
|
||||
resource.getLocator(), e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> List<U> doQuery(ResourceQuery query, ResourceVisitor<U> resourceVisitor) {
|
||||
|
||||
PostgreSqlResourceQueryVisitor queryVisitor = new PostgreSqlResourceQueryVisitor("id, asxml");
|
||||
query.accept(queryVisitor);
|
||||
queryVisitor.validate();
|
||||
|
||||
List<U> list = new ArrayList<>();
|
||||
|
||||
String sql = queryVisitor.getSql();
|
||||
try (PreparedStatement ps = PostgreSqlResourceDao.this.tx.getConnection().prepareStatement(sql)) {
|
||||
queryVisitor.setValues(ps);
|
||||
|
||||
try (ResultSet result = ps.executeQuery()) {
|
||||
while (result.next()) {
|
||||
String id = result.getString("id");
|
||||
SQLXML sqlxml = result.getSQLXML("asxml");
|
||||
Resource t = parseFromXml(id, queryVisitor.getType(), sqlxml);
|
||||
list.add(resourceVisitor.visit(t));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to perform query due to: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import li.strolch.model.Tags;
|
||||
import li.strolch.model.query.ResourceQueryVisitor;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PostgreSqlResourceQueryVisitor extends PostgreSqlQueryVisitor implements ResourceQueryVisitor {
|
||||
|
||||
/**
|
||||
* @param fields
|
||||
*/
|
||||
public PostgreSqlResourceQueryVisitor(String fields) {
|
||||
super(fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getClassName() {
|
||||
return Tags.RESOURCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTableName() {
|
||||
return PostgreSqlResourceDao.RESOURCES;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import li.strolch.agent.api.StrolchRealm;
|
||||
import li.strolch.persistence.api.AbstractTransaction;
|
||||
import li.strolch.persistence.api.AuditDao;
|
||||
import li.strolch.persistence.api.OrderDao;
|
||||
import li.strolch.persistence.api.PersistenceHandler;
|
||||
import li.strolch.persistence.api.ResourceDao;
|
||||
import li.strolch.persistence.api.TransactionResult;
|
||||
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
|
||||
public class PostgreSqlStrolchTransaction extends AbstractTransaction {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PostgreSqlStrolchTransaction.class);
|
||||
private PostgreSqlPersistenceHandler persistenceHandler;
|
||||
|
||||
private PostgresqlDao<?> orderDao;
|
||||
private PostgresqlDao<?> resourceDao;
|
||||
private AuditDao auditDao;
|
||||
private Connection connection;
|
||||
|
||||
public PostgreSqlStrolchTransaction(PrivilegeHandler privilegeHandler, StrolchRealm realm, Certificate certificate,
|
||||
String action, PostgreSqlPersistenceHandler persistenceHandler) {
|
||||
super(privilegeHandler, realm, certificate, action);
|
||||
this.persistenceHandler = persistenceHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeChanges(TransactionResult txResult) throws Exception {
|
||||
|
||||
// first perform DAOs
|
||||
if (this.orderDao != null)
|
||||
this.orderDao.commit(txResult);
|
||||
if (this.resourceDao != null)
|
||||
this.resourceDao.commit(txResult);
|
||||
|
||||
// don't commit the connection, this is done in postCommit when we close the connection
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rollback(TransactionResult txResult) throws Exception {
|
||||
if (this.connection != null) {
|
||||
try {
|
||||
this.connection.rollback();
|
||||
} finally {
|
||||
try {
|
||||
this.connection.close();
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to close connection due to " + e.getMessage(), e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void commit() throws Exception {
|
||||
if (this.connection != null) {
|
||||
this.connection.commit();
|
||||
this.connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
OrderDao getOrderDao() {
|
||||
if (this.orderDao == null)
|
||||
this.orderDao = new PostgreSqlOrderDao(this);
|
||||
return (OrderDao) this.orderDao;
|
||||
}
|
||||
|
||||
ResourceDao getResourceDao() {
|
||||
if (this.resourceDao == null)
|
||||
this.resourceDao = new PostgreSqlResourceDao(this);
|
||||
return (ResourceDao) this.resourceDao;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public AuditDao getAuditDao() {
|
||||
if (this.auditDao == null)
|
||||
this.auditDao = new PostgreSqlAuditDao(this);
|
||||
return this.auditDao;
|
||||
}
|
||||
|
||||
Connection getConnection() {
|
||||
if (this.connection == null) {
|
||||
this.connection = this.persistenceHandler.getConnection(getRealm().getRealm());
|
||||
}
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceHandler getPersistenceHandler() {
|
||||
return this.persistenceHandler;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,396 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLXML;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import li.strolch.model.StrolchElement;
|
||||
import li.strolch.persistence.api.StrolchDao;
|
||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||
import li.strolch.persistence.api.TransactionResult;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public abstract class PostgresqlDao<T extends StrolchElement> implements StrolchDao<T> {
|
||||
|
||||
protected PostgreSqlStrolchTransaction tx;
|
||||
protected List<DaoCommand> commands;
|
||||
|
||||
public PostgresqlDao(PostgreSqlStrolchTransaction tx) {
|
||||
this.tx = tx;
|
||||
this.commands = new ArrayList<>();
|
||||
}
|
||||
|
||||
protected abstract String getClassName();
|
||||
|
||||
protected abstract String getTableName();
|
||||
|
||||
protected abstract T parseFromXml(String id, String type, SQLXML xml);
|
||||
|
||||
@Override
|
||||
public boolean hasElement(String type, String id) {
|
||||
String sql = "select count(*) from " + getTableName() + " where type = ? and id = ?";
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
statement.setString(1, type);
|
||||
statement.setString(2, id);
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
result.next();
|
||||
long numberOfElements = result.getLong(1);
|
||||
if (numberOfElements == 0)
|
||||
return false;
|
||||
if (numberOfElements == 1)
|
||||
return true;
|
||||
|
||||
String msg = MessageFormat.format("Non unique number of elements with type {0} and id {1}", type, id);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long querySize() {
|
||||
String sql = "select count(*) from " + getTableName();
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
result.next();
|
||||
return result.getLong(1);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long querySize(String type) {
|
||||
String sql = "select count(*) from " + getTableName() + " where type = ?";
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
statement.setString(1, type);
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
result.next();
|
||||
return result.getLong(1);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryKeySet() {
|
||||
|
||||
Set<String> keySet = new HashSet<>();
|
||||
|
||||
String sql = "select id from " + getTableName();
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
while (result.next()) {
|
||||
keySet.add(result.getString("id"));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query key set due to: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryKeySet(String type) {
|
||||
Set<String> keySet = new HashSet<>();
|
||||
|
||||
String sql = "select id from " + getTableName() + " where type = ?";
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
statement.setString(1, type);
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
while (result.next()) {
|
||||
keySet.add(result.getString("id"));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query key set due to: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryTypes() {
|
||||
Set<String> keySet = new HashSet<>();
|
||||
|
||||
String sql = "select distinct type from " + getTableName();
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
while (result.next()) {
|
||||
keySet.add(result.getString("type"));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T queryBy(String type, String id) {
|
||||
|
||||
String sql = "select id, name, type, asxml from " + getTableName() + " where id = ? and type = ?";
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
statement.setString(1, id);
|
||||
statement.setString(2, type);
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
if (!result.next()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SQLXML sqlxml = result.getSQLXML("asxml");
|
||||
T t = parseFromXml(id, type, sqlxml);
|
||||
if (result.next())
|
||||
throw new StrolchPersistenceException("Non unique result for query: " + sql);
|
||||
return t;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> queryAll() {
|
||||
|
||||
List<T> list = new ArrayList<>();
|
||||
String sql = "select id, name, type, asxml from " + getTableName();
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
while (result.next()) {
|
||||
String id = result.getString("id");
|
||||
String type = result.getString("type");
|
||||
SQLXML sqlxml = result.getSQLXML("asxml");
|
||||
T t = parseFromXml(id, type, sqlxml);
|
||||
list.add(t);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> queryAll(String type) {
|
||||
|
||||
List<T> list = new ArrayList<>();
|
||||
String sql = "select id, name, type, asxml from " + getTableName() + " where type = ?";
|
||||
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
statement.setString(1, type);
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
while (result.next()) {
|
||||
String id = result.getString("id");
|
||||
SQLXML sqlxml = result.getSQLXML("asxml");
|
||||
T t = parseFromXml(id, type, sqlxml);
|
||||
list.add(t);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final T res) {
|
||||
this.commands.add(new DaoCommand() {
|
||||
@Override
|
||||
public void doComand(TransactionResult txResult) {
|
||||
internalSave(res);
|
||||
txResult.incCreated(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAll(final List<T> elements) {
|
||||
this.commands.add(new DaoCommand() {
|
||||
@Override
|
||||
public void doComand(TransactionResult txResult) {
|
||||
for (T element : elements) {
|
||||
internalSave(element);
|
||||
}
|
||||
txResult.incCreated(elements.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final T element) {
|
||||
this.commands.add(new DaoCommand() {
|
||||
@Override
|
||||
public void doComand(TransactionResult txResult) {
|
||||
internalUpdate(element);
|
||||
txResult.incUpdated(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAll(final List<T> elements) {
|
||||
this.commands.add(new DaoCommand() {
|
||||
@Override
|
||||
public void doComand(TransactionResult txResult) {
|
||||
for (T element : elements) {
|
||||
internalUpdate(element);
|
||||
}
|
||||
txResult.incUpdated(elements.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final T element) {
|
||||
this.commands.add(new DaoCommand() {
|
||||
@Override
|
||||
public void doComand(TransactionResult txResult) {
|
||||
internalRemove(element);
|
||||
txResult.incDeleted(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll(final List<T> elements) {
|
||||
this.commands.add(new DaoCommand() {
|
||||
@Override
|
||||
public void doComand(TransactionResult txResult) {
|
||||
for (T element : elements) {
|
||||
internalRemove(element);
|
||||
}
|
||||
txResult.incDeleted(elements.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public long removeAll() {
|
||||
|
||||
final long toRemove = querySize();
|
||||
|
||||
this.commands.add(new DaoCommand() {
|
||||
@Override
|
||||
public void doComand(TransactionResult txResult) {
|
||||
internalRemoveAll(toRemove);
|
||||
txResult.incDeleted(toRemove);
|
||||
}
|
||||
});
|
||||
|
||||
return toRemove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long removeAllBy(final String type) {
|
||||
|
||||
final long toRemove = querySize(type);
|
||||
|
||||
this.commands.add(new DaoCommand() {
|
||||
@Override
|
||||
public void doComand(TransactionResult txResult) {
|
||||
internalRemoveAllBy(toRemove, type);
|
||||
txResult.incDeleted(toRemove);
|
||||
}
|
||||
});
|
||||
|
||||
return toRemove;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element
|
||||
*/
|
||||
protected abstract void internalSave(T element);
|
||||
|
||||
/**
|
||||
* @param element
|
||||
*/
|
||||
protected abstract void internalUpdate(T element);
|
||||
|
||||
protected void internalRemove(final T element) {
|
||||
String sql = "delete from " + getTableName() + " where id = ?";
|
||||
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
|
||||
preparedStatement.setString(1, element.getId());
|
||||
int modCount = preparedStatement.executeUpdate();
|
||||
if (modCount != 1) {
|
||||
String msg = "Expected to delete 1 element with id {0} but SQL statement modified {1} elements!";
|
||||
msg = MessageFormat.format(msg, element.getId(), modCount);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove {0} due to {2}",
|
||||
element.getLocator(), e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void internalRemoveAll(final long toRemove) {
|
||||
String sql = "delete from " + getTableName();
|
||||
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
int modCount = preparedStatement.executeUpdate();
|
||||
if (modCount != toRemove) {
|
||||
String msg = "Expected to delete {0} elements but SQL statement removed {1} elements!";
|
||||
msg = MessageFormat.format(msg, toRemove, modCount);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove all elements due to {0}",
|
||||
e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void internalRemoveAllBy(final long toRemove, String type) {
|
||||
String sql = "delete from " + getTableName() + " where type = ?";
|
||||
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
|
||||
preparedStatement.setString(1, type);
|
||||
int modCount = preparedStatement.executeUpdate();
|
||||
if (modCount != toRemove) {
|
||||
String msg = "Expected to delete {0} elements of type {1} but SQL statement removed {2} elements!";
|
||||
msg = MessageFormat.format(msg, toRemove, type, modCount);
|
||||
throw new StrolchPersistenceException(msg);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new StrolchPersistenceException(MessageFormat.format(
|
||||
"Failed to remove all elements of type {0} due to {1}", type, e.getLocalizedMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
void commit(TransactionResult txResult) {
|
||||
for (DaoCommand command : this.commands) {
|
||||
command.doComand(txResult);
|
||||
}
|
||||
}
|
||||
|
||||
void rollback() {
|
||||
this.commands.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
groupId=${project.groupId}
|
||||
artifactId=${project.artifactId}
|
||||
artifactVersion=${project.version}
|
||||
scmRevision=r${buildNumber}
|
||||
scmBranch=${scmBranch}
|
||||
buildTimestamp=${buildTimestamp}
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
DROP TABLE IF EXISTS resources, orders, db_version;
|
||||
|
||||
DROP TYPE IF EXISTS order_state;
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
CREATE TABLE IF NOT EXISTS db_version (
|
||||
id SERIAL PRIMARY KEY,
|
||||
version varchar(255),
|
||||
description varchar(255),
|
||||
created timestamp with time zone
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS resources (
|
||||
id varchar(255) PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
type VARCHAR(255),
|
||||
asxml xml
|
||||
);
|
||||
|
||||
CREATE TYPE order_state AS ENUM ('CREATED', 'OPEN', 'EXECUTION', 'CLOSED');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS orders (
|
||||
id varchar(255) PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
type VARCHAR(255),
|
||||
state order_state,
|
||||
date timestamp with time zone,
|
||||
asxml xml
|
||||
);
|
||||
|
||||
INSERT INTO db_version
|
||||
(version, description, created)
|
||||
values(
|
||||
'0.1.0',
|
||||
'Initial schema version',
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
DROP TABLE IF EXISTS resources;
|
||||
DROP TABLE IF EXISTS orders;
|
||||
DROP TABLE IF EXISTS audits;
|
||||
DROP TABLE IF EXISTS db_version;
|
||||
|
||||
DROP TYPE IF EXISTS order_state;
|
||||
DROP TYPE IF EXISTS access_type;
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
-- DB_VERSION
|
||||
CREATE TABLE IF NOT EXISTS db_version (
|
||||
id SERIAL PRIMARY KEY,
|
||||
version varchar(255),
|
||||
description varchar(255),
|
||||
created timestamp with time zone
|
||||
);
|
||||
|
||||
-- RESOURCES
|
||||
CREATE TABLE IF NOT EXISTS resources (
|
||||
id varchar(255) PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
type VARCHAR(255),
|
||||
asxml xml
|
||||
);
|
||||
|
||||
-- ORDERS
|
||||
CREATE TYPE order_state AS ENUM ('CREATED', 'OPEN', 'EXECUTION', 'CLOSED');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS orders (
|
||||
id varchar(255) PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
type VARCHAR(255),
|
||||
state order_state,
|
||||
date timestamp with time zone,
|
||||
asxml xml
|
||||
);
|
||||
|
||||
-- AUDITS
|
||||
CREATE TYPE access_type AS ENUM ('READ', 'CREATE', 'UPDATE', 'DELETE');
|
||||
CREATE TABLE IF NOT EXISTS audits (
|
||||
id bigint PRIMARY KEY,
|
||||
username VARCHAR(255) NOT NULL,
|
||||
firstname VARCHAR(255) NOT NULL,
|
||||
lastname VARCHAR(255) NOT NULL,
|
||||
date timestamp with time zone NOT NULL,
|
||||
|
||||
element_type VARCHAR(255) NOT NULL,
|
||||
element_accessed VARCHAR(255) NOT NULL,
|
||||
new_version timestamp with time zone,
|
||||
|
||||
action VARCHAR(255) NOT NULL,
|
||||
access_type access_type NOT NULL
|
||||
);
|
||||
|
||||
-- set version
|
||||
INSERT INTO db_version
|
||||
(version, description, created)
|
||||
values(
|
||||
'0.1.0',
|
||||
'Initial schema version',
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
INSERT INTO db_version
|
||||
(version, description, created)
|
||||
values(
|
||||
'0.2.0',
|
||||
'Added new table for audits',
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
|
@ -0,0 +1,2 @@
|
|||
# Property file defining what the currently expected version is supposed to be
|
||||
db_version=0.2.0
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql.dao.test;
|
||||
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.CONFIG_SRC;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_PASSWORD;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_STORE_PATH_DIR;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_URL;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_USERNAME;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.RUNTIME_PATH;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.dropSchema;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import li.strolch.agent.api.AuditTrail;
|
||||
import li.strolch.agent.api.StrolchRealm;
|
||||
import li.strolch.model.ModelGenerator;
|
||||
import li.strolch.model.Tags;
|
||||
import li.strolch.model.audit.AccessType;
|
||||
import li.strolch.model.audit.Audit;
|
||||
import li.strolch.model.audit.AuditQuery;
|
||||
import li.strolch.persistence.api.AbstractTransaction;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.persistence.postgresql.PostgreSqlAuditQueryVisitor;
|
||||
import li.strolch.runtime.StrolchConstants;
|
||||
import li.strolch.testbase.runtime.RuntimeMock;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
import ch.eitchnet.utils.StringMatchMode;
|
||||
import ch.eitchnet.utils.collections.DateRange;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class AuditQueryTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AuditQueryTest.class);
|
||||
private static RuntimeMock runtimeMock;
|
||||
|
||||
private static Date past;
|
||||
private static Date earlier;
|
||||
private static Date current;
|
||||
private static Date later;
|
||||
private static Date future;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
|
||||
dropSchema(DB_URL, DB_USERNAME, DB_PASSWORD);
|
||||
|
||||
File rootPath = new File(RUNTIME_PATH);
|
||||
File configSrc = new File(CONFIG_SRC);
|
||||
runtimeMock = new RuntimeMock();
|
||||
runtimeMock.mockRuntime(rootPath, configSrc);
|
||||
new File(rootPath, DB_STORE_PATH_DIR).mkdir();
|
||||
runtimeMock.startContainer();
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.clear();
|
||||
cal.set(2000, 1, 1);
|
||||
past = cal.getTime();
|
||||
cal.set(2000, 4, 1);
|
||||
earlier = cal.getTime();
|
||||
cal.set(2000, 6, 1);
|
||||
current = cal.getTime();
|
||||
cal.set(2000, 8, 1);
|
||||
later = cal.getTime();
|
||||
cal.set(2000, 11, 1);
|
||||
future = cal.getTime();
|
||||
|
||||
Certificate cert = runtimeMock.getPrivilegeHandler().authenticate("test", "test".getBytes());
|
||||
StrolchRealm realm = runtimeMock.getRealm(StrolchConstants.DEFAULT_REALM);
|
||||
int i = 0;
|
||||
try (StrolchTransaction tx = realm.openTx(cert, "test")) {
|
||||
((AbstractTransaction) tx).setSuppressAudits(true);
|
||||
AuditTrail auditTrail = tx.getAuditTrail();
|
||||
|
||||
Audit randomAudit;
|
||||
randomAudit = ModelGenerator.randomAudit();
|
||||
randomAudit.setId(i++);
|
||||
randomAudit.setUsername("earlier");
|
||||
randomAudit.setDate(earlier);
|
||||
randomAudit.setAccessType(AccessType.CREATE);
|
||||
randomAudit.setAction("create");
|
||||
randomAudit.setElementAccessed(randomAudit.getAccessType().name());
|
||||
auditTrail.add(tx, randomAudit);
|
||||
|
||||
randomAudit = ModelGenerator.randomAudit();
|
||||
randomAudit.setId(i++);
|
||||
randomAudit.setDate(current);
|
||||
randomAudit.setUsername("current");
|
||||
randomAudit.setAccessType(AccessType.READ);
|
||||
randomAudit.setAction("read");
|
||||
randomAudit.setElementAccessed(randomAudit.getAccessType().name());
|
||||
auditTrail.add(tx, randomAudit);
|
||||
|
||||
randomAudit = ModelGenerator.randomAudit();
|
||||
randomAudit.setId(i++);
|
||||
randomAudit.setDate(later);
|
||||
randomAudit.setUsername("later");
|
||||
randomAudit.setAccessType(AccessType.UPDATE);
|
||||
randomAudit.setAction("update");
|
||||
randomAudit.setElementAccessed(randomAudit.getAccessType().name());
|
||||
auditTrail.add(tx, randomAudit);
|
||||
|
||||
randomAudit = ModelGenerator.randomAudit();
|
||||
randomAudit.setId(i++);
|
||||
randomAudit.setDate(current);
|
||||
randomAudit.setUsername("current");
|
||||
randomAudit.setAccessType(AccessType.DELETE);
|
||||
randomAudit.setAction("delete");
|
||||
randomAudit.setElementAccessed(randomAudit.getAccessType().name());
|
||||
auditTrail.add(tx, randomAudit);
|
||||
|
||||
randomAudit = ModelGenerator.randomAudit();
|
||||
randomAudit.setId(i++);
|
||||
randomAudit.setDate(current);
|
||||
randomAudit.setUsername("current");
|
||||
randomAudit.setAccessType(AccessType.CREATE);
|
||||
randomAudit.setAction("create");
|
||||
randomAudit.setElementAccessed(randomAudit.getAccessType().name());
|
||||
auditTrail.add(tx, randomAudit);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
runtimeMock.destroyRuntime();
|
||||
}
|
||||
|
||||
public Connection openConn() throws SQLException {
|
||||
String url = "jdbc:postgresql://localhost/testdb";
|
||||
String username = "testuser";
|
||||
String password = "test";
|
||||
Connection connection = DriverManager.getConnection(url, username, password);
|
||||
connection.setAutoCommit(false);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryTypeAndDateRange() throws SQLException {
|
||||
AuditQuery query = new AuditQuery(Tags.AUDIT, new DateRange().from(earlier, true).to(later, true));
|
||||
performQuery(query, Arrays.asList("0", "1", "2", "3", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(current, true).to(current, true));
|
||||
performQuery(query, Arrays.asList("1", "3", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(current, true));
|
||||
performQuery(query, Arrays.asList("1", "2", "3", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().to(current, true));
|
||||
performQuery(query, Arrays.asList("0", "1", "3", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.RESOURCE, new DateRange().from(past, true).to(future, true));
|
||||
performQuery(query, Arrays.<String> asList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryAudits() throws SQLException {
|
||||
AuditQuery query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.action().accessTypes(AccessType.CREATE, AccessType.READ);
|
||||
performQuery(query, Arrays.asList("0", "1", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.action().accessTypes(AccessType.CREATE);
|
||||
performQuery(query, Arrays.asList("0", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.action().accessTypes(AccessType.CREATE, AccessType.READ)
|
||||
.actions(StringMatchMode.EQUALS_CASE_SENSITIVE, "create", "read");
|
||||
performQuery(query, Arrays.asList("0", "1", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.action().accessTypes(AccessType.CREATE, AccessType.READ)
|
||||
.actions(StringMatchMode.EQUALS_CASE_SENSITIVE, "read");
|
||||
performQuery(query, Arrays.asList("1"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.element().elementsAccessed(StringMatchMode.CONTAINS_CASE_INSENSITIVE, "crea");
|
||||
performQuery(query, Arrays.asList("0", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.element().elementsAccessed(StringMatchMode.CONTAINS_CASE_SENSITIVE, "crea");
|
||||
performQuery(query, Arrays.<String> asList());
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.element().elementsAccessed(StringMatchMode.EQUALS_CASE_INSENSITIVE, "create");
|
||||
performQuery(query, Arrays.asList("0", "4"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.identity().usernames(StringMatchMode.EQUALS_CASE_INSENSITIVE, "earlier");
|
||||
performQuery(query, Arrays.asList("0"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.identity().usernames(StringMatchMode.EQUALS_CASE_INSENSITIVE, "earlier", "later");
|
||||
performQuery(query, Arrays.asList("0", "2"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.identity().usernames(StringMatchMode.EQUALS_CASE_INSENSITIVE, "earlier")
|
||||
.firstnames(StringMatchMode.CONTAINS_CASE_INSENSITIVE, "enn");
|
||||
performQuery(query, Arrays.asList("0"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.identity().usernames(StringMatchMode.EQUALS_CASE_INSENSITIVE, "earlier")
|
||||
.firstnames(StringMatchMode.CONTAINS_CASE_INSENSITIVE, "enn")
|
||||
.lastnames(StringMatchMode.CONTAINS_CASE_INSENSITIVE, "kennedy");
|
||||
performQuery(query, Arrays.asList("0"));
|
||||
|
||||
query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true));
|
||||
query.identity().firstnames(StringMatchMode.CONTAINS_CASE_INSENSITIVE, "enn")
|
||||
.lastnames(StringMatchMode.CONTAINS_CASE_INSENSITIVE, "kennedy");
|
||||
performQuery(query, Arrays.asList("0", "1", "2", "3", "4"));
|
||||
}
|
||||
|
||||
private void performQuery(AuditQuery query, List<String> expected) throws SQLException {
|
||||
PostgreSqlAuditQueryVisitor visitor = new PostgreSqlAuditQueryVisitor("id");
|
||||
query.accept(visitor);
|
||||
List<String> ids = queryIds(visitor);
|
||||
assertEquals(new HashSet<>(expected), new HashSet<>(ids));
|
||||
}
|
||||
|
||||
private List<String> queryIds(PostgreSqlAuditQueryVisitor visitor) throws SQLException {
|
||||
String sql = visitor.getSql();
|
||||
logger.info("\n" + sql);
|
||||
List<String> ids = new ArrayList<>();
|
||||
try (Connection con = openConn()) {
|
||||
try (PreparedStatement ps = con.prepareStatement(sql)) {
|
||||
visitor.setValues(ps);
|
||||
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
ids.add(rs.getString(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql.dao.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import li.strolch.persistence.postgresql.DbSchemaVersionCheck;
|
||||
import li.strolch.testbase.runtime.AbstractModelTest;
|
||||
import li.strolch.testbase.runtime.RuntimeMock;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.eitchnet.utils.helper.StringHelper;
|
||||
|
||||
public class CachedDaoTest extends AbstractModelTest {
|
||||
|
||||
public static final String RUNTIME_PATH = "target/cachedStrolchRuntime/"; //$NON-NLS-1$
|
||||
public static final String DB_STORE_PATH_DIR = "dbStore"; //$NON-NLS-1$
|
||||
public static final String CONFIG_SRC = "src/test/resources/cachedruntime"; //$NON-NLS-1$
|
||||
|
||||
public static final String DB_URL = "jdbc:postgresql://localhost/testdb"; //$NON-NLS-1$
|
||||
public static final String DB_USERNAME = "testuser"; //$NON-NLS-1$
|
||||
public static final String DB_PASSWORD = "test"; //$NON-NLS-1$
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CachedDaoTest.class);
|
||||
|
||||
protected static RuntimeMock runtimeMock;
|
||||
|
||||
@Override
|
||||
protected RuntimeMock getRuntimeMock() {
|
||||
return runtimeMock;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
|
||||
dropSchema(DB_URL, DB_USERNAME, DB_PASSWORD);
|
||||
|
||||
File rootPath = new File(RUNTIME_PATH);
|
||||
File configSrc = new File(CONFIG_SRC);
|
||||
runtimeMock = new RuntimeMock();
|
||||
runtimeMock.mockRuntime(rootPath, configSrc);
|
||||
new File(rootPath, DB_STORE_PATH_DIR).mkdir();
|
||||
runtimeMock.startContainer();
|
||||
}
|
||||
|
||||
public static void dropSchema(String dbUrl, String dbUsername, String dbPassword) throws SQLException {
|
||||
String dbVersion = DbSchemaVersionCheck.getExpectedDbVersion();
|
||||
logger.info(MessageFormat.format("Dropping schema for expected version {0}", dbVersion));
|
||||
String sql = DbSchemaVersionCheck.getSql(dbVersion, "drop"); //$NON-NLS-1$
|
||||
logger.info(StringHelper.NEW_LINE + sql);
|
||||
try (Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword)) {
|
||||
connection.prepareStatement(sql).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
runtimeMock.destroyRuntime();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql.dao.test;
|
||||
|
||||
import static li.strolch.model.ModelGenerator.createOrder;
|
||||
import static li.strolch.model.ModelGenerator.createResource;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_PASSWORD;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_URL;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_USERNAME;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.dropSchema;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import li.strolch.agent.api.Observer;
|
||||
import li.strolch.agent.api.StrolchRealm;
|
||||
import li.strolch.model.Order;
|
||||
import li.strolch.model.Resource;
|
||||
import li.strolch.model.State;
|
||||
import li.strolch.model.StrolchRootElement;
|
||||
import li.strolch.model.Tags;
|
||||
import li.strolch.persistence.api.ModificationResult;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.runtime.StrolchConstants;
|
||||
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||
import li.strolch.testbase.runtime.RuntimeMock;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class ObserverUpdateTest {
|
||||
|
||||
public static final String RUNTIME_PATH = "target/observerUpdateStrolchRuntime/"; //$NON-NLS-1$
|
||||
public static final String DB_STORE_PATH_DIR = "dbStore"; //$NON-NLS-1$
|
||||
public static final String CONFIG_SRC = "src/test/resources/cachedruntime"; //$NON-NLS-1$
|
||||
|
||||
protected static RuntimeMock runtimeMock;
|
||||
|
||||
protected RuntimeMock getRuntimeMock() {
|
||||
return runtimeMock;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
|
||||
dropSchema(DB_URL, DB_USERNAME, DB_PASSWORD);
|
||||
|
||||
File rootPath = new File(RUNTIME_PATH);
|
||||
File configSrc = new File(CONFIG_SRC);
|
||||
runtimeMock = new RuntimeMock();
|
||||
runtimeMock.mockRuntime(rootPath, configSrc);
|
||||
new File(rootPath, DB_STORE_PATH_DIR).mkdir();
|
||||
runtimeMock.startContainer();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
runtimeMock.destroyRuntime();
|
||||
}
|
||||
|
||||
public final class ElementAddedObserver implements Observer {
|
||||
|
||||
Map<String, ModificationResult> results = new HashMap<>();
|
||||
|
||||
private ModificationResult getModificationResult(String key) {
|
||||
ModificationResult result = this.results.get(key);
|
||||
if (result == null) {
|
||||
result = new ModificationResult(key);
|
||||
this.results.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, List<StrolchRootElement> elements) {
|
||||
getModificationResult(key).getUpdated().addAll(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String key, List<StrolchRootElement> elements) {
|
||||
getModificationResult(key).getDeleted().addAll(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String key, List<StrolchRootElement> elements) {
|
||||
getModificationResult(key).getCreated().addAll(elements);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReceiveUpdates() {
|
||||
|
||||
// register an observer for orders and resources
|
||||
ElementAddedObserver observer = new ElementAddedObserver();
|
||||
StrolchRealm realm = runtimeMock.getRealm(StrolchConstants.DEFAULT_REALM);
|
||||
realm.getObserverHandler().registerObserver(Tags.ORDER, observer);
|
||||
realm.getObserverHandler().registerObserver(Tags.RESOURCE, observer);
|
||||
|
||||
PrivilegeHandler privilegeHandler = runtimeMock.getAgent().getContainer().getPrivilegeHandler();
|
||||
Certificate certificate = privilegeHandler.authenticate("test", "test".getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
// create order
|
||||
Order newOrder = createOrder("MyTestOrder", "Test Name", "TestType", new Date(), State.CREATED); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
|
||||
try (StrolchTransaction tx = realm.openTx(certificate, "test")) { //$NON-NLS-1$
|
||||
tx.getOrderMap().add(tx, newOrder);
|
||||
}
|
||||
|
||||
// create resource
|
||||
Resource newResource = createResource("MyTestResource", "Test Name", "TestType"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
|
||||
try (StrolchTransaction tx = realm.openTx(certificate, "test");) { //$NON-NLS-1$
|
||||
tx.getResourceMap().add(tx, newResource);
|
||||
}
|
||||
|
||||
assertEquals(2, observer.results.size());
|
||||
assertEquals(1, observer.results.get(Tags.ORDER).getCreated().size());
|
||||
assertEquals(1, observer.results.get(Tags.RESOURCE).getCreated().size());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql.dao.test;
|
||||
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.CONFIG_SRC;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_PASSWORD;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_STORE_PATH_DIR;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_URL;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_USERNAME;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.RUNTIME_PATH;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.dropSchema;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import li.strolch.agent.api.OrderMap;
|
||||
import li.strolch.agent.api.ResourceMap;
|
||||
import li.strolch.agent.api.StrolchRealm;
|
||||
import li.strolch.model.ModelGenerator;
|
||||
import li.strolch.model.State;
|
||||
import li.strolch.model.query.DateSelection;
|
||||
import li.strolch.model.query.IdSelection;
|
||||
import li.strolch.model.query.NameSelection;
|
||||
import li.strolch.model.query.OrSelection;
|
||||
import li.strolch.model.query.OrderQuery;
|
||||
import li.strolch.model.query.ParameterBagSelection;
|
||||
import li.strolch.model.query.ParameterBagSelection.NullParameterBagSelection;
|
||||
import li.strolch.model.query.ParameterSelection;
|
||||
import li.strolch.model.query.ResourceQuery;
|
||||
import li.strolch.model.query.StateSelection;
|
||||
import li.strolch.model.query.StrolchTypeNavigation;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.persistence.postgresql.PostgreSqlOrderQueryVisitor;
|
||||
import li.strolch.persistence.postgresql.PostgreSqlQueryVisitor;
|
||||
import li.strolch.persistence.postgresql.PostgreSqlResourceQueryVisitor;
|
||||
import li.strolch.runtime.StrolchConstants;
|
||||
import li.strolch.testbase.runtime.RuntimeMock;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
import ch.eitchnet.utils.StringMatchMode;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class QueryTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(QueryTest.class);
|
||||
private static RuntimeMock runtimeMock;
|
||||
|
||||
private static Date past;
|
||||
private static Date earlier;
|
||||
private static Date current;
|
||||
private static Date later;
|
||||
private static Date future;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
|
||||
dropSchema(DB_URL, DB_USERNAME, DB_PASSWORD);
|
||||
|
||||
File rootPath = new File(RUNTIME_PATH);
|
||||
File configSrc = new File(CONFIG_SRC);
|
||||
runtimeMock = new RuntimeMock();
|
||||
runtimeMock.mockRuntime(rootPath, configSrc);
|
||||
new File(rootPath, DB_STORE_PATH_DIR).mkdir();
|
||||
runtimeMock.startContainer();
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.clear();
|
||||
cal.set(2000, 1, 1);
|
||||
past = cal.getTime();
|
||||
cal.set(2000, 4, 1);
|
||||
earlier = cal.getTime();
|
||||
cal.set(2000, 6, 1);
|
||||
current = cal.getTime();
|
||||
cal.set(2000, 8, 1);
|
||||
later = cal.getTime();
|
||||
cal.set(2000, 11, 1);
|
||||
future = cal.getTime();
|
||||
|
||||
Certificate cert = runtimeMock.getPrivilegeHandler().authenticate("test", "test".getBytes());
|
||||
StrolchRealm realm = runtimeMock.getRealm(StrolchConstants.DEFAULT_REALM);
|
||||
try (StrolchTransaction tx = realm.openTx(cert, "test")) {
|
||||
OrderMap orderMap = tx.getOrderMap();
|
||||
|
||||
orderMap.add(tx, ModelGenerator.createOrder("@1", "Order 1", "MyType1", earlier, State.CREATED));
|
||||
orderMap.add(tx, ModelGenerator.createOrder("@2", "Order 2", "MyType1", current, State.OPEN));
|
||||
orderMap.add(tx, ModelGenerator.createOrder("@3", "Order 3", "MyType1", later, State.CLOSED));
|
||||
orderMap.add(tx, ModelGenerator.createOrder("@4", "Order 4", "MyType2", earlier, State.CREATED));
|
||||
orderMap.add(tx, ModelGenerator.createOrder("@5", "Order 5", "MyType2", current, State.OPEN));
|
||||
orderMap.add(tx, ModelGenerator.createOrder("@6", "Order 6", "MyType2", later, State.CLOSED));
|
||||
|
||||
ResourceMap resourceMap = tx.getResourceMap();
|
||||
resourceMap.add(tx, ModelGenerator.createResource("@1", "Resource 1", "MyType1"));
|
||||
resourceMap.add(tx, ModelGenerator.createResource("@2", "Resource 2", "MyType1"));
|
||||
resourceMap.add(tx, ModelGenerator.createResource("@3", "Resource 3", "MyType1"));
|
||||
resourceMap.add(tx, ModelGenerator.createResource("@4", "Resource 4", "MyType2"));
|
||||
resourceMap.add(tx, ModelGenerator.createResource("@5", "Resource 5", "MyType2"));
|
||||
resourceMap.add(tx, ModelGenerator.createResource("@6", "Resource 6", "MyType2"));
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
runtimeMock.destroyRuntime();
|
||||
}
|
||||
|
||||
public Connection openConn() throws SQLException {
|
||||
String url = "jdbc:postgresql://localhost/testdb";
|
||||
String username = "testuser";
|
||||
String password = "test";
|
||||
Connection connection = DriverManager.getConnection(url, username, password);
|
||||
connection.setAutoCommit(false);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryOrderAll() throws SQLException {
|
||||
|
||||
OrderQuery query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.withAny();
|
||||
performOrderQuery(query, Arrays.asList("@1", "@2", "@3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceAll() throws SQLException {
|
||||
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType2"));
|
||||
query.withAny();
|
||||
performResourceQuery(query, Arrays.asList("@4", "@5", "@6"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryOrderByDate() throws SQLException {
|
||||
|
||||
// range
|
||||
OrderQuery query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new DateSelection().from(earlier, false).to(later, false));
|
||||
performOrderQuery(query, Arrays.asList("@1", "@2", "@3"));
|
||||
|
||||
// equals current
|
||||
query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new DateSelection().from(current, false).to(current, false));
|
||||
performOrderQuery(query, Arrays.asList("@2"));
|
||||
|
||||
// equals later
|
||||
query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new DateSelection().from(later, false).to(later, false));
|
||||
performOrderQuery(query, Arrays.<String> asList("@3"));
|
||||
|
||||
// equals earlier
|
||||
query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new DateSelection().from(earlier, false).to(earlier, false));
|
||||
performOrderQuery(query, Arrays.<String> asList("@1"));
|
||||
|
||||
// past
|
||||
query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new DateSelection().to(past, false));
|
||||
performOrderQuery(query, Arrays.<String> asList());
|
||||
|
||||
// future
|
||||
query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new DateSelection().from(future, false));
|
||||
performOrderQuery(query, Arrays.<String> asList());
|
||||
|
||||
// earlier
|
||||
query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new DateSelection().from(past, false).to(earlier, true));
|
||||
performOrderQuery(query, Arrays.<String> asList("@1"));
|
||||
|
||||
// later
|
||||
query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new DateSelection().from(later, false).to(future, true));
|
||||
performOrderQuery(query, Arrays.<String> asList("@3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryOrderByState() throws SQLException {
|
||||
|
||||
OrderQuery query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new StateSelection(State.CREATED));
|
||||
performOrderQuery(query, Arrays.asList("@1"));
|
||||
|
||||
query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new StateSelection(State.OPEN));
|
||||
performOrderQuery(query, Arrays.<String> asList("@2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryOrder1() throws SQLException {
|
||||
|
||||
OrderQuery query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new IdSelection("@1", "@2"),
|
||||
new NameSelection("Order 1", StringMatchMode.EQUALS_CASE_SENSITIVE));
|
||||
performOrderQuery(query, Arrays.asList("@1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryOrder2() throws SQLException {
|
||||
|
||||
OrderQuery query = new OrderQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.or().with(new IdSelection("@1", "@2"),
|
||||
new NameSelection("order 1", StringMatchMode.EQUALS_CASE_SENSITIVE));
|
||||
performOrderQuery(query, Arrays.asList("@1", "@2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResource1() throws SQLException {
|
||||
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.or().with(new IdSelection("@1", "@2"),
|
||||
new NameSelection("Resource 1", StringMatchMode.EQUALS_CASE_SENSITIVE));
|
||||
performResourceQuery(query, Arrays.asList("@1", "@2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResource2() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(
|
||||
new OrSelection(new IdSelection("@1"), new IdSelection("@2")),
|
||||
new OrSelection(new NameSelection("Resource 1", StringMatchMode.EQUALS_CASE_SENSITIVE),
|
||||
new NameSelection("Resource 2", StringMatchMode.EQUALS_CASE_SENSITIVE)));
|
||||
performResourceQuery(query, Arrays.asList("@1", "@2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByBooleParam() throws SQLException {
|
||||
|
||||
// select id, name, type, asxml
|
||||
// from
|
||||
// resources
|
||||
// where
|
||||
// type = 'MyType1' and
|
||||
// (
|
||||
// cast(xpath('//Resource/ParameterBag/Parameter[@Id="@param1" and @Value="true"]', asxml) as text[]) != '{}'
|
||||
// )
|
||||
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(ParameterSelection.booleanSelection("@bag01", "@param1", true));
|
||||
performResourceQuery(query, Arrays.asList("@1", "@2", "@3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByFloagParam() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(ParameterSelection.floatSelection("@bag01", "@param2", 44.3));
|
||||
performResourceQuery(query, Arrays.asList("@1", "@2", "@3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByIntegerParam() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(ParameterSelection.integerSelection("@bag01", "@param3", 77));
|
||||
performResourceQuery(query, Arrays.asList("@1", "@2", "@3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByLongParam() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType2"));
|
||||
query.and().with(ParameterSelection.longSelection("@bag01", "@param4", 4453234566L));
|
||||
performResourceQuery(query, Arrays.asList("@4", "@5", "@6"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByStringParam() throws SQLException {
|
||||
|
||||
List<String> expected = Arrays.asList("@1", "@2", "@3");
|
||||
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(
|
||||
ParameterSelection.stringSelection("@bag01", "@param5", "Strolch",
|
||||
StringMatchMode.EQUALS_CASE_SENSITIVE));
|
||||
performResourceQuery(query, expected);
|
||||
|
||||
query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(
|
||||
ParameterSelection.stringSelection("@bag01", "@param5", "strolch",
|
||||
StringMatchMode.EQUALS_CASE_SENSITIVE));
|
||||
performResourceQuery(query, Arrays.<String> asList());
|
||||
|
||||
query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(
|
||||
ParameterSelection.stringSelection("@bag01", "@param5", "strolch",
|
||||
StringMatchMode.EQUALS_CASE_INSENSITIVE));
|
||||
performResourceQuery(query, expected);
|
||||
|
||||
query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(
|
||||
ParameterSelection.stringSelection("@bag01", "@param5", "olch",
|
||||
StringMatchMode.CONTAINS_CASE_INSENSITIVE));
|
||||
performResourceQuery(query, expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByDateParam() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(ParameterSelection.dateSelection("@bag01", "@param6", new Date(1354295525628L)));
|
||||
performResourceQuery(query, Arrays.asList("@1", "@2", "@3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByNullParam1() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(ParameterSelection.nullSelection("@bag01", "@param6"));
|
||||
performResourceQuery(query, Arrays.<String> asList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByNullParam2() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(ParameterSelection.nullSelection("@bag01", "@param"));
|
||||
performResourceQuery(query, Arrays.asList("@1", "@2", "@3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByBag() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new ParameterBagSelection("@bag01"));
|
||||
performResourceQuery(query, Arrays.asList("@1", "@2", "@3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldQueryResourceByNullBag() throws SQLException {
|
||||
ResourceQuery query = new ResourceQuery(new StrolchTypeNavigation("MyType1"));
|
||||
query.and().with(new NullParameterBagSelection("@bag01"));
|
||||
performResourceQuery(query, Arrays.<String> asList());
|
||||
}
|
||||
|
||||
private void performOrderQuery(OrderQuery query, List<String> expected) throws SQLException {
|
||||
PostgreSqlOrderQueryVisitor visitor = new PostgreSqlOrderQueryVisitor("id");
|
||||
query.accept(visitor);
|
||||
List<String> ids = queryIds(visitor);
|
||||
assertEquals(new HashSet<>(expected), new HashSet<>(ids));
|
||||
}
|
||||
|
||||
private void performResourceQuery(ResourceQuery query, List<String> expected) throws SQLException {
|
||||
PostgreSqlResourceQueryVisitor visitor = new PostgreSqlResourceQueryVisitor("id");
|
||||
query.accept(visitor);
|
||||
List<String> ids = queryIds(visitor);
|
||||
assertEquals(new HashSet<>(expected), new HashSet<>(ids));
|
||||
}
|
||||
|
||||
private List<String> queryIds(PostgreSqlQueryVisitor visitor) throws SQLException {
|
||||
String sql = visitor.getSql();
|
||||
logger.info("\n" + sql);
|
||||
List<String> ids = new ArrayList<>();
|
||||
try (Connection con = openConn()) {
|
||||
try (PreparedStatement ps = con.prepareStatement(sql)) {
|
||||
visitor.setValues(ps);
|
||||
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
ids.add(rs.getString(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql.dao.test;
|
||||
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.dropSchema;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import li.strolch.agent.api.StrolchRealm;
|
||||
import li.strolch.agent.impl.DataStoreMode;
|
||||
import li.strolch.model.ModelGenerator;
|
||||
import li.strolch.model.Resource;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||
import li.strolch.testbase.runtime.AbstractModelTest;
|
||||
import li.strolch.testbase.runtime.RuntimeMock;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
|
||||
public class RealmTest extends AbstractModelTest {
|
||||
|
||||
private static final String TESTUSER2 = "testuser2"; //$NON-NLS-1$
|
||||
private static final String TESTUSER1 = "testuser1"; //$NON-NLS-1$
|
||||
private static final String SECOND = "second"; //$NON-NLS-1$
|
||||
private static final String TEST = "test"; //$NON-NLS-1$
|
||||
private static final String FIRST = "first"; //$NON-NLS-1$
|
||||
|
||||
public static final String RUNTIME_PATH = "target/realmtest/"; //$NON-NLS-1$
|
||||
public static final String DB_STORE_PATH_DIR = "dbStore"; //$NON-NLS-1$
|
||||
public static final String CONFIG_SRC = "src/test/resources/realmtest"; //$NON-NLS-1$
|
||||
|
||||
protected static RuntimeMock runtimeMock;
|
||||
|
||||
@Override
|
||||
protected RuntimeMock getRuntimeMock() {
|
||||
return runtimeMock;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
|
||||
dropSchema("jdbc:postgresql://localhost/testdb1", TESTUSER1, TEST); //$NON-NLS-1$
|
||||
dropSchema("jdbc:postgresql://localhost/testdb2", TESTUSER2, TEST); //$NON-NLS-1$
|
||||
|
||||
File rootPath = new File(RUNTIME_PATH);
|
||||
File configSrc = new File(CONFIG_SRC);
|
||||
runtimeMock = new RuntimeMock();
|
||||
runtimeMock.mockRuntime(rootPath, configSrc);
|
||||
new File(rootPath, DB_STORE_PATH_DIR).mkdir();
|
||||
runtimeMock.startContainer();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
this.realmName = SECOND;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDifferentRealms() {
|
||||
|
||||
String expectedId1 = "@realmTestId1"; //$NON-NLS-1$
|
||||
String expectedId2 = "@realmTestId2"; //$NON-NLS-1$
|
||||
String type = "Bla"; //$NON-NLS-1$
|
||||
|
||||
PrivilegeHandler privilegeHandler = runtimeMock.getAgent().getContainer().getPrivilegeHandler();
|
||||
Certificate certificate = privilegeHandler.authenticate(TEST, TEST.getBytes());
|
||||
|
||||
{
|
||||
StrolchRealm firstRealm = runtimeMock.getRealm(FIRST);
|
||||
assertEquals(DataStoreMode.TRANSACTIONAL, firstRealm.getMode());
|
||||
Resource expectedRes1 = ModelGenerator.createResource(expectedId1, "Bla bla", type); //$NON-NLS-1$
|
||||
try (StrolchTransaction tx = firstRealm.openTx(certificate, TEST)) {
|
||||
tx.getResourceMap().add(tx, expectedRes1);
|
||||
}
|
||||
|
||||
try (StrolchTransaction tx = firstRealm.openTx(certificate, TEST)) {
|
||||
Resource res = tx.getResourceMap().getBy(tx, type, expectedId1);
|
||||
assertEquals("Should find object previously added in same realm!", expectedRes1, res); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
StrolchRealm secondRealm = runtimeMock.getRealm(SECOND);
|
||||
assertEquals(DataStoreMode.TRANSACTIONAL, secondRealm.getMode());
|
||||
Resource expectedRes2 = ModelGenerator.createResource(expectedId2, "Bla bla", type); //$NON-NLS-1$
|
||||
try (StrolchTransaction tx = secondRealm.openTx(certificate, TEST)) {
|
||||
tx.getResourceMap().add(tx, expectedRes2);
|
||||
}
|
||||
|
||||
try (StrolchTransaction tx = secondRealm.openTx(certificate, TEST)) {
|
||||
Resource res = tx.getResourceMap().getBy(tx, type, expectedId2);
|
||||
assertEquals("Should find object previously added in same realm!", expectedRes2, res); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
StrolchRealm secondRealm = runtimeMock.getRealm(SECOND);
|
||||
try (StrolchTransaction tx = secondRealm.openTx(certificate, TEST)) {
|
||||
Resource res = tx.getResourceMap().getBy(tx, type, expectedId1);
|
||||
assertNull("Should not find object added in differenct realm!", res); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
runtimeMock.destroyRuntime();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package li.strolch.persistence.postgresql.dao.test;
|
||||
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_PASSWORD;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_URL;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_USERNAME;
|
||||
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.dropSchema;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import li.strolch.testbase.runtime.AbstractModelTest;
|
||||
import li.strolch.testbase.runtime.RuntimeMock;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
public class TransactionalDaoTest extends AbstractModelTest {
|
||||
|
||||
public static final String RUNTIME_PATH = "target/transactionalStrolchRuntime/"; //$NON-NLS-1$
|
||||
public static final String DB_STORE_PATH_DIR = "dbStore"; //$NON-NLS-1$
|
||||
public static final String CONFIG_SRC = "src/test/resources/transactionalruntime"; //$NON-NLS-1$
|
||||
|
||||
protected static RuntimeMock runtimeMock;
|
||||
|
||||
@Override
|
||||
protected RuntimeMock getRuntimeMock() {
|
||||
return runtimeMock;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
|
||||
dropSchema(DB_URL, DB_USERNAME, DB_PASSWORD);
|
||||
|
||||
File rootPath = new File(RUNTIME_PATH);
|
||||
File configSrc = new File(CONFIG_SRC);
|
||||
runtimeMock = new RuntimeMock();
|
||||
runtimeMock.mockRuntime(rootPath, configSrc);
|
||||
new File(rootPath, DB_STORE_PATH_DIR).mkdir();
|
||||
runtimeMock.startContainer();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
runtimeMock.destroyRuntime();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Privilege>
|
||||
|
||||
<Container>
|
||||
|
||||
<Parameters>
|
||||
<!-- parameters for the container itself -->
|
||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
||||
</Parameters>
|
||||
|
||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||
<Parameters>
|
||||
<Parameter name="hashAlgorithm" value="SHA-256" />
|
||||
</Parameters>
|
||||
</EncryptionHandler>
|
||||
|
||||
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
|
||||
<Parameters>
|
||||
<Parameter name="basePath" value="target/strolchRuntime/config" />
|
||||
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
|
||||
</Parameters>
|
||||
</PersistenceHandler>
|
||||
|
||||
</Container>
|
||||
|
||||
<Policies>
|
||||
<Policy name="DefaultPrivilege" class="ch.eitchnet.privilege.policy.DefaultPrivilege" />
|
||||
</Policies>
|
||||
|
||||
</Privilege>
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<UsersAndRoles>
|
||||
|
||||
<Users>
|
||||
<User userId="1" username="agent">
|
||||
<State>SYSTEM</State>
|
||||
<Roles>
|
||||
<Role>agent</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
|
||||
<Firstname>Application</Firstname>
|
||||
<Lastname>Administrator</Lastname>
|
||||
<State>ENABLED</State>
|
||||
<Locale>en_GB</Locale>
|
||||
<Roles>
|
||||
<Role>PrivilegeAdmin</Role>
|
||||
<Role>AppUser</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
</Users>
|
||||
|
||||
<Roles>
|
||||
<Role name="PrivilegeAdmin" />
|
||||
<Role name="agent">
|
||||
<Privilege name="li.strolch.agent.impl.StartRealms" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
</Role>
|
||||
<Role name="AppUser">
|
||||
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
<Privilege name="li.strolch.model.query.StrolchQuery" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
</Role>
|
||||
</Roles>
|
||||
</UsersAndRoles>
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StrolchConfiguration>
|
||||
<env id="dev">
|
||||
<Runtime>
|
||||
<applicationName>StrolchPersistenceTest</applicationName>
|
||||
<Properties>
|
||||
<verbose>true</verbose>
|
||||
</Properties>
|
||||
</Runtime>
|
||||
<Component>
|
||||
<name>PrivilegeHandler</name>
|
||||
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
|
||||
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
|
||||
<Properties>
|
||||
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component>
|
||||
<name>RealmHandler</name>
|
||||
<api>li.strolch.agent.api.RealmHandler</api>
|
||||
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
|
||||
<depends>PrivilegeHandler</depends>
|
||||
<depends>PersistenceHandler</depends>
|
||||
<Properties>
|
||||
<dataStoreMode>TRANSACTIONAL</dataStoreMode>
|
||||
<enableAuditTrail>true</enableAuditTrail>
|
||||
<enableObserverUpdates>true</enableObserverUpdates>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component>
|
||||
<name>PersistenceHandler</name>
|
||||
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
||||
<impl>li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler</impl>
|
||||
<Properties>
|
||||
<allowSchemaCreation>true</allowSchemaCreation>
|
||||
<allowSchemaDrop>true</allowSchemaDrop>
|
||||
<db.url>jdbc:postgresql://localhost/testdb</db.url>
|
||||
<db.username>testuser</db.username>
|
||||
<db.password>test</db.password>
|
||||
</Properties>
|
||||
</Component>
|
||||
</env>
|
||||
</StrolchConfiguration>
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE log4j:configuration PUBLIC
|
||||
"-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
|
||||
<log4j:configuration debug="false" xmlns:log4j='http://jakarta.apache.org/log4j/'>
|
||||
|
||||
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%d %5p [%t] %C{1} %M - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="FILE" class="org.apache.log4j.FileAppender">
|
||||
<param name="File" value="sample.log"/>
|
||||
<param name="BufferedIO" value="true" />
|
||||
<param name="Append" value="true" />
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%d %5p [%t] %C{1} %M - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="ch.eitchnet">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<root>
|
||||
<priority value="info" />
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<!-- appender-ref ref="FILE" / -->
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Privilege>
|
||||
|
||||
<Container>
|
||||
|
||||
<Parameters>
|
||||
<!-- parameters for the container itself -->
|
||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
||||
</Parameters>
|
||||
|
||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||
<Parameters>
|
||||
<Parameter name="hashAlgorithm" value="SHA-256" />
|
||||
</Parameters>
|
||||
</EncryptionHandler>
|
||||
|
||||
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
|
||||
<Parameters>
|
||||
<Parameter name="basePath" value="target/strolchRuntime/config" />
|
||||
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
|
||||
</Parameters>
|
||||
</PersistenceHandler>
|
||||
|
||||
</Container>
|
||||
|
||||
<Policies>
|
||||
<Policy name="DefaultPrivilege" class="ch.eitchnet.privilege.policy.DefaultPrivilege" />
|
||||
</Policies>
|
||||
|
||||
</Privilege>
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<UsersAndRoles>
|
||||
|
||||
<Users>
|
||||
<User userId="1" username="agent">
|
||||
<State>SYSTEM</State>
|
||||
<Roles>
|
||||
<Role>agent</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
|
||||
<Firstname>Application</Firstname>
|
||||
<Lastname>Administrator</Lastname>
|
||||
<State>ENABLED</State>
|
||||
<Locale>en_GB</Locale>
|
||||
<Roles>
|
||||
<Role>PrivilegeAdmin</Role>
|
||||
<Role>AppUser</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
</Users>
|
||||
|
||||
<Roles>
|
||||
<Role name="PrivilegeAdmin" />
|
||||
<Role name="agent">
|
||||
<Privilege name="li.strolch.agent.impl.StartRealms" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
</Role>
|
||||
<Role name="AppUser">
|
||||
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
<Privilege name="li.strolch.model.query.StrolchQuery" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
</Role>
|
||||
</Roles>
|
||||
</UsersAndRoles>
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StrolchConfiguration>
|
||||
<env id="dev">
|
||||
<Runtime>
|
||||
<applicationName>StrolchPersistenceTest</applicationName>
|
||||
<Properties>
|
||||
<verbose>true</verbose>
|
||||
</Properties>
|
||||
</Runtime>
|
||||
<Component>
|
||||
<name>PrivilegeHandler</name>
|
||||
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
|
||||
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
|
||||
<Properties>
|
||||
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component>
|
||||
<name>RealmHandler</name>
|
||||
<api>li.strolch.agent.api.RealmHandler</api>
|
||||
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
|
||||
<depends>PrivilegeHandler</depends>
|
||||
<depends>PersistenceHandler</depends>
|
||||
<Properties>
|
||||
<realms>first, second</realms>
|
||||
<dataStoreMode.first>TRANSACTIONAL</dataStoreMode.first>
|
||||
<dataStoreMode.second>TRANSACTIONAL</dataStoreMode.second>
|
||||
<enableAuditTrail.first>true</enableAuditTrail.first>
|
||||
<enableAuditTrail.second>true</enableAuditTrail.second>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component>
|
||||
<name>PersistenceHandler</name>
|
||||
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
||||
<impl>li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler</impl>
|
||||
<Properties>
|
||||
<allowSchemaCreation>true</allowSchemaCreation>
|
||||
<allowSchemaDrop>true</allowSchemaDrop>
|
||||
|
||||
<db.url.first>jdbc:postgresql://localhost/testdb1</db.url.first>
|
||||
<db.username.first>testuser1</db.username.first>
|
||||
<db.password.first>test</db.password.first>
|
||||
|
||||
<db.url.second>jdbc:postgresql://localhost/testdb2</db.url.second>
|
||||
<db.username.second>testuser2</db.username.second>
|
||||
<db.password.second>test</db.password.second>
|
||||
</Properties>
|
||||
</Component>
|
||||
</env>
|
||||
</StrolchConfiguration>
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Privilege>
|
||||
|
||||
<Container>
|
||||
|
||||
<Parameters>
|
||||
<!-- parameters for the container itself -->
|
||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
||||
</Parameters>
|
||||
|
||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||
<Parameters>
|
||||
<Parameter name="hashAlgorithm" value="SHA-256" />
|
||||
</Parameters>
|
||||
</EncryptionHandler>
|
||||
|
||||
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
|
||||
<Parameters>
|
||||
<Parameter name="basePath" value="target/strolchRuntime/config" />
|
||||
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
|
||||
</Parameters>
|
||||
</PersistenceHandler>
|
||||
|
||||
</Container>
|
||||
|
||||
<Policies>
|
||||
<Policy name="DefaultPrivilege" class="ch.eitchnet.privilege.policy.DefaultPrivilege" />
|
||||
</Policies>
|
||||
|
||||
</Privilege>
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<UsersAndRoles>
|
||||
|
||||
<Users>
|
||||
<User userId="1" username="agent">
|
||||
<State>SYSTEM</State>
|
||||
<Roles>
|
||||
<Role>agent</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
|
||||
<Firstname>Application</Firstname>
|
||||
<Lastname>Administrator</Lastname>
|
||||
<State>ENABLED</State>
|
||||
<Locale>en_GB</Locale>
|
||||
<Roles>
|
||||
<Role>PrivilegeAdmin</Role>
|
||||
<Role>AppUser</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
</Users>
|
||||
|
||||
<Roles>
|
||||
<Role name="PrivilegeAdmin" />
|
||||
<Role name="agent">
|
||||
<Privilege name="li.strolch.agent.impl.StartRealms" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
</Role>
|
||||
<Role name="AppUser">
|
||||
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
<Privilege name="li.strolch.model.query.StrolchQuery" policy="DefaultPrivilege">
|
||||
<AllAllowed>true</AllAllowed>
|
||||
</Privilege>
|
||||
</Role>
|
||||
</Roles>
|
||||
</UsersAndRoles>
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StrolchConfiguration>
|
||||
<env id="dev">
|
||||
<Runtime>
|
||||
<applicationName>StrolchPersistenceTest</applicationName>
|
||||
<Properties>
|
||||
<verbose>true</verbose>
|
||||
</Properties>
|
||||
</Runtime>
|
||||
<Component>
|
||||
<name>PrivilegeHandler</name>
|
||||
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
|
||||
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
|
||||
<Properties>
|
||||
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component>
|
||||
<name>RealmHandler</name>
|
||||
<api>li.strolch.agent.api.RealmHandler</api>
|
||||
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
|
||||
<depends>PrivilegeHandler</depends>
|
||||
<depends>PersistenceHandler</depends>
|
||||
<Properties>
|
||||
<dataStoreMode>TRANSACTIONAL</dataStoreMode>
|
||||
<enableAuditTrail>true</enableAuditTrail>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component>
|
||||
<name>PersistenceHandler</name>
|
||||
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
||||
<impl>li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler</impl>
|
||||
<Properties>
|
||||
<allowSchemaCreation>true</allowSchemaCreation>
|
||||
<allowSchemaDrop>true</allowSchemaDrop>
|
||||
<db.url>jdbc:postgresql://localhost/testdb</db.url>
|
||||
<db.username>testuser</db.username>
|
||||
<db.password>test</db.password>
|
||||
</Properties>
|
||||
</Component>
|
||||
</env>
|
||||
</StrolchConfiguration>
|
Loading…
Reference in New Issue