Compare commits

...

169 Commits

Author SHA1 Message Date
Robert von Burg 3054d5fca5
[Minor] Added ExceptionHelper.getRootCauseMessage() 2024-05-03 10:08:10 +02:00
Robert von Burg 19825b37a8
[Major] Refactored facet generation for reports
simplified code, move facet value generation into policy, added extension point for formatting criteria to Json, so the facet value's name can be changed in subclasses.
2024-05-02 12:43:21 +02:00
Robert von Burg c65c6624fb
[Fix] Ignoring more bundles in I18nMessage 2024-04-30 12:50:54 +02:00
Robert von Burg 4d7b3faf3f
[Fix] Fixed RestfulStrolchComponent not starting 2024-04-23 15:30:59 +02:00
Robert von Burg dc93800fd1
[Project] Set new version 2.3.0-SNAPSHOT 2024-04-23 14:46:57 +02:00
Robert von Burg 4b78b30600
[Minor] Updated restful logging 2024-04-23 14:29:03 +02:00
Robert von Burg 3edcec4d08
[Minor] Cleaned up logging in BasicAuth and ServletRequestHelper 2024-04-23 11:37:09 +02:00
Robert von Burg cf4ae20d0b
[Minor] Fixed HTTP return code for BasicAuth errors 2024-04-23 10:33:12 +02:00
Robert von Burg 68bd3dd6d6
[New] Added ServletRequestHelper.logRequest() 2024-04-23 10:32:52 +02:00
Robert von Burg c4ac21ec98
[New] Added ExceptionHelper.getRootCauseExceptionMessage() 2024-04-23 10:32:43 +02:00
Robert von Burg a45475f783
[Fix] BasicAuth should check root cause of exception 2024-04-23 09:47:31 +02:00
Robert von Burg baa7a0af4e
[New] Added enabled flag to notifications 2024-04-23 08:19:52 +02:00
Robert von Burg 1080096549
[New] Added LogRequestFilter to log requests prior to filter mapping 2024-04-22 15:01:05 +02:00
Robert von Burg 393659ff19
[Fix] Fixed Strolch exception i18n hierarchy 2024-03-25 10:18:43 +01:00
Robert von Burg a7258f0d06
[Major] Refactored basic auth and getRemoteIp() helper 2024-03-21 14:23:49 +01:00
Robert von Burg 2aca456729
[New] Added CertificateThreadLocal 2024-03-21 14:23:04 +01:00
Robert von Burg f4f9e2c798
[Project] Removed duplicate version declaration 2024-03-21 12:06:48 +01:00
Robert von Burg f051008d68
[Project] Updated dependencies to JAX-WS 2024-03-18 11:11:51 +01:00
Robert von Burg 1e6ac0c042
[Minor] Code cleanup 2024-03-14 16:06:56 +01:00
Robert von Burg a103864eb8
[Project] Updated to camel 3.22.1 2024-03-11 08:31:06 +01:00
Robert von Burg 125dfe9b03
[Fix] Notification only visible to all if forAll
otherwise role, etc. must be set and match
2024-03-07 12:26:51 +01:00
Robert von Burg 2914889172
[Minor] Code cleanup 2024-03-05 15:33:34 +01:00
Robert von Burg d3c261b750
[Fix] Fixed action name in NotificationResource 2024-03-05 15:33:02 +01:00
Robert von Burg de8d35480d
[Minor] Code cleanup 2024-03-05 13:31:15 +01:00
Robert von Burg 1158acfd90
[Fix] Use existing TX when writing audits for invalidating sessions 2024-03-05 13:30:46 +01:00
Robert von Burg faf05126b4
[Fix] Fixed CME in tx.streamCached*() methods 2024-03-05 11:12:12 +01:00
Robert von Burg d00b00d234
[Fix] Fixed updating sessions on changes of user or roles 2024-03-05 10:16:32 +01:00
Robert von Burg 76d38e9af0
[Minor] Made methods public 2024-03-04 17:21:55 +01:00
Robert von Burg f850367d2b
[Fix] Trying to fix broken test 2024-03-04 16:28:44 +01:00
Robert von Burg a4119ef1da
[New] Completed implementation of notifications 2024-03-04 16:10:38 +01:00
Robert von Burg abe089f95c
[Minor] Allow RoleAccessPrivilege to use String parameter 2024-03-04 16:10:14 +01:00
Robert von Burg 15b2788b9a
[WIP] Further implementing notifications 2024-03-01 16:22:11 +01:00
Robert von Burg f02b541848
[Minor] Sorting of supported languages 2024-03-01 16:21:52 +01:00
Robert von Burg 5526f20220
[New] Added StrolchAgent.getRuntimeConfiguration() 2024-03-01 09:58:19 +01:00
Robert von Burg a9c393f02a
[Fix] Implemented to JSON for notifications 2024-02-29 17:05:45 +01:00
Robert von Burg 22359e51d8
[New] Added CRUD services for notifications 2024-02-27 16:44:53 +01:00
Robert von Burg 7b9f2f867f
[New] Extended builder pattern 2024-02-27 14:46:41 +01:00
Robert von Burg a9067bf161
[Major] Refactored SimpleExecution.runWith* actions to take a Consumer<Throwable> in the event of an exception 2024-02-27 12:01:42 +01:00
dependabot[bot] e91a96b549
Bump org.postgresql:postgresql from 42.5.1 to 42.7.2 (#31)
Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.5.1 to 42.7.2.
- [Release notes](https://github.com/pgjdbc/pgjdbc/releases)
- [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pgjdbc/pgjdbc/commits)

---
updated-dependencies:
- dependency-name: org.postgresql:postgresql
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-22 10:28:07 +01:00
Robert von Burg 5c2bcc1620
[New] Added NotificationResource 2024-02-15 17:24:35 +01:00
Robert von Burg f3adc63af2
[New] Added new FileHelper.getTempFile() option MILLIS_FIRST, code cleanup 2024-02-13 09:49:39 +01:00
Robert von Burg a07bd83249
[WIP] Implementing system notifications 2024-02-12 16:43:57 +01:00
Robert von Burg c46c60c8fe
[Project] Changed final name to include strolch- prefix 2024-02-12 12:48:38 +01:00
Robert von Burg a2c720ce48
[New] Allow override of methods in DefaultStrolchSessionHandler 2024-02-09 11:27:40 +01:00
Robert von Burg c66446391a
[Fix] Fixed NPE in toString() 2024-02-06 15:22:43 +01:00
Robert von Burg 69d1f77364
[Fix] Searches should search on items in cache as well
But then ignore the item from the ElementMap stream
2024-02-06 08:00:44 +01:00
Robert von Burg e33950b7a1
[New] Better cache management in TX
- Added items to cache when modified
- added streaming of cached elements
2024-02-06 07:59:28 +01:00
Robert von Burg 56098c96fa
[Minor] Changed the toString()-methods to include the Locator 2024-02-05 14:01:13 +01:00
Robert von Burg 63670a77b6
[Fix] Fixed ExecutionPolicy not initialized before use 2024-01-19 10:22:41 +01:00
Robert von Burg 9c15d0d1d2
[Fix] Don't set Action to WARNING if already Executed 2024-01-18 14:46:34 +01:00
Robert von Burg 77cd9264d0
[Minor] Code cleanup 2024-01-15 14:37:12 +01:00
Robert von Burg bf01876f7c
[Minor] Don't log exception for session validation 2024-01-11 16:24:31 +01:00
Robert von Burg 373235f5e2
[Fix] Renamed varargs methd ExpressionBuilder.isInArray 2024-01-11 14:21:41 +01:00
Robert von Burg 2eeda52f86
[New] ObjectHelper.isIn() extended to allow left and right side to be an array/collection 2024-01-11 13:35:32 +01:00
Robert von Burg ce22f180af
[New] Added new SearchExpressions.paramOnBagType()
This allows to search to have a search, where multiple bags of the same type having a parameter with a given ID, yet different values is searched using the .isIn().

For example:

    paramOnBagType("Owner", "name").isIn("Felix", "Jill")

This allows for one less where clause with lambdas.
2024-01-11 12:33:51 +01:00
Robert von Burg 8b20e4392d
[New] ObjectHelper.isIn() extended to allow left and right side to be an array/collection 2024-01-11 12:32:03 +01:00
Robert von Burg 83f575de41
[New] Added new SearchExpression extract(Function<T, Object>) 2024-01-08 15:40:50 +01:00
Robert von Burg 23054a5bad
[Project] Updated maven-deploy-plugin version to 3.1.1 2024-01-04 15:54:41 +01:00
Robert von Burg d0008f9951
[Project] Removed qodana badge 2024-01-04 11:22:07 +01:00
Robert von Burg 1e2965d588
[Project] Added deployment to repo.strolch.li 2024-01-04 11:09:11 +01:00
Robert von Burg 7a8edc7cc6
[Project] Updated SECURITY.md 2024-01-04 09:40:33 +01:00
Robert von Burg 22e2e5cc68
[Project] Added deployment to repo.strolch.li 2024-01-02 20:32:43 +01:00
Robert von Burg f6a8746069
[Project] Added deployment to repo.strolch.li 2024-01-02 20:28:33 +01:00
Robert von Burg fd5f344764
[Project] Added deployment to repo.strolch.li 2024-01-02 14:47:13 +01:00
Robert von Burg ec8965eee2
[Project] Added deployment to repo.strolch.li 2024-01-01 13:37:16 +01:00
Robert von Burg c17b23b72f
[Fix] Fixed LoggingLoader.reloadLogging() 2023-12-17 20:46:47 +01:00
Robert von Burg 5064249e72
[Project] Updated logback to 1.4.14 2023-12-13 21:08:55 +01:00
Robert von Burg 269bd83ded
[New] search with contains() extended for matchAny or matchAll (default) 2023-12-11 15:00:28 +01:00
Robert von Burg 529c1d0e3b
[Minor] Fixed NPE 2023-12-08 09:31:22 +01:00
Robert von Burg 974c3955ee
[Fix] Fixed NPE in ExecutionPolicy.handleStopped() 2023-12-06 12:24:25 +01:00
Robert von Burg 0d674cf947
[Fix] Fixed ObjectHelper.contains() for left=string,right=array 2023-12-01 10:58:36 +01:00
Robert von Burg ecb4db2377
[Fix] Fixed NPE in GenericReport 2023-11-30 15:42:27 +01:00
Robert von Burg 48968972be
[Fix] BaseLdapPrivilegeHandler throws InvalidCredentialsException on AuthenticationException 2023-11-30 15:17:36 +01:00
Robert von Burg 4e0e0ab22a
[Fix] Refactored AuthenticationResource exception handling 2023-11-30 15:12:55 +01:00
Robert von Burg 92f87cbc77
[Fix] Refactored AuthenticationResource exception handling 2023-11-30 15:05:50 +01:00
Robert von Burg 3c2aac3b9e
[Fix] encode user provider input for LDAP query
Remove OWASP ESAPI as it has too many dependencies
2023-11-30 14:42:48 +01:00
Robert von Burg 004c6775c0
[Minor] Handle lossy conversion of long to int 2023-11-30 13:39:11 +01:00
Robert von Burg 4b0b031b2b
[Fix] Updated AesCryptoHelper
Inspired by https://github.com/tozny/java-aes-crypto/blob/master/aes-crypto/src/main/java/com/tozny/crypto/android/AesCbcWithIntegrity.java
2023-11-30 13:32:01 +01:00
Robert von Burg c5402ba4fb
[Fix] encode user provider input for LDAP query 2023-11-30 13:30:36 +01:00
Robert von Burg 30086f36cc
[Fix] Added missing default branch 2023-11-30 13:12:35 +01:00
Robert von Burg 792221e190
[Fix] Replaced MD5 with SHA256 2023-11-30 13:11:44 +01:00
Robert von Burg 91a2f5651c
[Fix] Updated AesCryptoHelper
Inspired by https://github.com/tozny/java-aes-crypto/blob/master/aes-crypto/src/main/java/com/tozny/crypto/android/AesCbcWithIntegrity.java
2023-11-30 13:10:01 +01:00
Robert von Burg 579cd0b0e5
[Fix] Always use SAXParserFactory feature disallow-doctype-decl=true 2023-11-30 12:16:28 +01:00
Robert von Burg 2ab8d95c0b
[Minor] Handle lossy conversion of long to int 2023-11-30 11:11:50 +01:00
Robert von Burg ed16e969f2
[Project] Downgrade to logback 1.4.8, as 1.4.12 has incompatible API change 2023-11-30 10:49:45 +01:00
Robert von Burg dc0836773c
[Minor] Handle lossy conversion of long to int 2023-11-30 10:36:18 +01:00
dependabot[bot] 3fbb0acc4c
Bump ch.qos.logback:logback-classic from 1.4.5 to 1.4.12 (#30)
Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.4.5 to 1.4.12.
- [Commits](https://github.com/qos-ch/logback/compare/v_1.4.5...v_1.4.12)

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-classic
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-30 10:11:09 +01:00
Robert von Burg 74ba243b2f
[Project] Updated codeql to use Java 21 2023-11-30 10:10:22 +01:00
Robert von Burg ec72200d15
[Minor] Added logging of time to init report 2023-11-28 15:42:45 +01:00
Robert von Burg 7867f206a1
[New] Added TypedTuple.equals and .hashCode() 2023-11-28 15:42:22 +01:00
Robert von Burg 4bee5990ac
[Fix] Fixed locator not updated on new IActivityElement parent 2023-11-27 15:48:21 +01:00
Robert von Burg bd03144b6a
[Project] Updated to JDK 21 2023-11-27 08:21:58 +01:00
Robert von Burg 4c8dd9b0d1
[Project] Set new version 2.2.0-SNAPSHOT 2023-11-27 07:53:36 +01:00
Robert von Burg 4f419f02e5
[Fix] Fixed broken tests 2023-11-24 15:17:48 +01:00
Robert von Burg d2627d13e7
[New] Added ExecutionPolicy.getActivityType() 2023-11-24 12:52:11 +01:00
Robert von Burg d6cfc6711a
[Minor] Better Exception handling in ElementLockingHandler 2023-11-24 07:57:05 +01:00
Robert von Burg 6ee6326390
[Project] Updated intellij formatter.xml 2023-11-23 14:44:33 +01:00
Robert von Burg 589f251aa2
[Fix] Fixed bad inspector privilege check 2023-11-21 12:11:08 +01:00
Robert von Burg 68a13d0e77
[Major] Renamed REST classes to have Resource suffix 2023-11-21 10:20:07 +01:00
Robert von Burg 52ae1574f4
[Fix] Fixed not copying user properties to UserRep 2023-11-21 10:19:43 +01:00
Robert von Burg 1bd986d755
[Minor] GenericReport fixes
- allowMissingColumns is now default enabled
- make sure direct criteria is always available on the filter criteria
2023-11-09 14:05:36 +01:00
Robert von Burg f105147ec1
[Project] Updated IntelliJ formatter for chopping down long chains 2023-11-02 09:55:08 +01:00
Robert von Burg 8e7ee2341a
[New] Added StrolchPolicy.isTxOpen() 2023-10-30 12:04:42 +01:00
Robert von Burg 857affbdea
[New] ExecutionPolicy now controls delayed task life cycle 2023-10-30 12:04:26 +01:00
Robert von Burg e80d0a7944
[New] ExecutionHandler.addForExecution() now returns the controller 2023-10-30 12:03:37 +01:00
Robert von Burg 256ab666b3
[Minor] Don't allow to call Activity.ensureModifiable() no a sub activity 2023-10-30 12:03:04 +01:00
Robert von Burg 1ce5411888
[Fix] SimpleExecution used wrong locator for changing states 2023-10-27 16:32:14 +02:00
Robert von Burg 0b2df5a3b4
[New] Added check to not set Action to execution state if already executed in ExecutionPolicy.setActionState() 2023-10-27 16:22:41 +02:00
Robert von Burg 380f5b6597
[New] State.canSetToError() is also for STOPPED 2023-10-27 16:22:05 +02:00
Robert von Burg da946f1acb
[New] Added new NetworkHelper.streamStrolchNetworkInterface()
This now streams over all interfaces, no matter if it is running or not.
2023-10-10 16:23:33 +02:00
Robert von Burg 6fc822fe52
[Major] Refactoring in BaseLdapPrivilegeHandler 2023-10-10 11:57:59 +02:00
Robert von Burg 9cb12e5a58
[Major] Refactoring in BaseLdapPrivilegeHandler 2023-10-10 11:28:05 +02:00
Robert von Burg 4e85333da3
[Major] Handling PartialResultException in BaseLdapPrivilegeHandler 2023-10-10 11:03:22 +02:00
Robert von Burg 87a90b5a12
[Minor] Update logging in BaseLdapPrivilegeHandler 2023-10-09 17:23:56 +02:00
Robert von Burg be0c3a806c
[Minor] Code cleanup 2023-10-09 14:44:35 +02:00
Robert von Burg 6d0b3f5fb9
[Minor] Rewrote StringHelper.toPrettyHexString() 2023-10-06 17:53:10 +02:00
Robert von Burg f2f5a4481e
[Fix] PrivilegeRemoveUserCommand refreshes sessions, and not invalidates its own session 2023-10-05 15:51:48 +02:00
Robert von Burg 5e7f5c88be
[Project] Updated session handler properties 2023-10-05 15:51:19 +02:00
Robert von Burg 0f3767a73b
[New] Added SessionHandler.refreshSessions(), removed session.reload property 2023-10-05 15:50:45 +02:00
Robert von Burg 03decdcaf8
[Fix] Fixed broken test 2023-10-05 15:08:19 +02:00
Robert von Burg 4b3a537171
[Major] Refactored SessionHandler by moving to module agent 2023-10-05 14:23:59 +02:00
Robert von Burg f8c77275f2
[Minor] Code cleanup 2023-10-05 14:03:27 +02:00
Robert von Burg e5bc8434c7
[Project] Updated PrivilegeAdmin role in all PrivilegeRoles.xml 2023-10-05 13:50:07 +02:00
Robert von Burg 6b6a61ab62
[Major] Privilege refactorings, remove unused services and actions 2023-10-05 13:43:57 +02:00
Robert von Burg 6f729554c8
[New] Allow to add an additionalFilter in LDAP search 2023-10-05 12:30:42 +02:00
Robert von Burg d8402bad61
[New] Allow to add an additionalFilter in LDAP search 2023-10-05 12:15:26 +02:00
Robert von Burg 6c09715b44
[Minor] Better message on forbidden access 2023-09-26 09:51:00 +02:00
Robert von Burg 48d121882e
[Major] Implemented groups in privilege. Refactored nearly everything 2023-09-25 10:51:09 +02:00
Robert von Burg 648553409c
[Minor] Code cleanup 2023-09-22 16:33:30 +02:00
Robert von Burg bcba0264e4
[Major] Rewrote privilege XML to use SAX for writing and parsing 2023-09-19 09:49:35 +02:00
Robert von Burg 96b24ca03d
[Minor] code cleanup 2023-09-19 09:48:37 +02:00
Robert von Burg f1dde73da1
[Minor] Logger is not error 2023-09-19 09:48:20 +02:00
Robert von Burg d9daad36f2
[Minor] Only show privilege duration if > 100ms 2023-09-18 14:57:18 +02:00
Robert von Burg 189c97a111
[Fix] Fixed wrong check on users/roles config property 2023-09-18 14:56:48 +02:00
Robert von Burg 7cea2fd6f3
[Project] Updated PrivilegeConfig.xml with default values 2023-09-18 14:05:18 +02:00
Robert von Burg 2f86493671
[Project] Using default values for PrivilegeUsers.xml and PrivilegeRoles.xml 2023-09-18 13:57:39 +02:00
Robert von Burg 17d9ffb245
[Minor] Set default value for caseInsensitiveUsername=true 2023-09-18 13:45:49 +02:00
Robert von Burg 080e2daacc
[Project] Remove default privilegeConflictResolution value 2023-09-18 13:42:12 +02:00
Robert von Burg 57d61887e3
[Minor] Set default value for privilegeConflictResolution=MERGE 2023-09-18 13:39:46 +02:00
Robert von Burg e5cd14ac17
[Minor] Persist user model async 2023-09-12 16:03:43 +02:00
Robert von Burg da0f8a0516
[Fix] Fix persisting user after password update 2023-09-12 16:03:24 +02:00
Robert von Burg 20f04d83d0
[Project] Set new version 2.1.0-SNAPSHOT 2023-09-12 08:01:03 +02:00
Robert von Burg c89a3158af
[Project] Removed default configuration values 2023-09-11 09:41:41 +02:00
Robert von Burg fa5296499d
[New] Observer updates are now enabled by default 2023-09-11 09:37:33 +02:00
Robert von Burg 7e45617c69
Update codeql.yml 2023-09-11 09:04:38 +02:00
Robert von Burg e86625d4c2
Update codeql.yml 2023-09-11 09:02:45 +02:00
Robert von Burg adbd415ab6
Create codeql.yml 2023-09-11 08:54:50 +02:00
Robert von Burg 561e1579cc
[Project] Removed unnecessary github actions 2023-09-11 08:53:44 +02:00
Robert von Burg 7b4c399808
[Minor] Code cleanup 2023-09-11 08:51:22 +02:00
Robert von Burg 492b556089
[Fix] Fixed broken tests 2023-09-10 00:32:24 +02:00
Robert von Burg af78eb4ac8
[Minor] Implemented CryptTest after password parsing refactorings 2023-09-08 22:21:24 +02:00
Robert von Burg 4093e5e17b
[Minor] Fixed compile errors 2023-09-08 22:11:00 +02:00
Robert von Burg ff773e76fd
[Major] Refactoring password parsing 2023-09-08 16:36:17 +02:00
Robert von Burg 9f86f84f35
[Project] Updated intellij formatter 2023-09-05 14:36:14 +02:00
Robert von Burg a67850f6fb
[New] Added Supplier<String> to DBC methods 2023-09-05 14:36:00 +02:00
Robert von Burg 40f9470db2
[Project] Updated intellij style formatter.xml 2023-09-04 11:06:40 +02:00
Robert von Burg d9da84093d
[New] Versions.toJson() require boolean isAdminRequest, triggering what is added to the JSON 2023-08-28 15:47:29 +02:00
Robert von Burg aba85f5d7c
[New] Versions.toJson() require boolean isAdminRequest, triggering what is added to the JSON 2023-08-28 15:04:10 +02:00
Robert von Burg c4fd605c5b
[New] Added Search results for concrete root elements 2023-08-25 12:52:26 +02:00
Robert von Burg 517d9ff0de
[New] Added search predicates isBefore() and isAfter() for ZonedDateTime 2023-08-25 09:47:07 +02:00
Robert von Burg fb13290edc
[New] Added Order constructor with ZonedDateTime 2023-08-25 09:46:39 +02:00
Robert von Burg 45426db150
[Minor] Added additional tests for non-unique IDs 2023-08-24 15:29:41 +02:00
Robert von Burg 2d751e0d1a
[Fix] Use type and ID when updating elements in DB tables 2023-08-24 08:13:17 +02:00
Robert von Burg f6f3a65f9c
[Fix] Fixed postgre SQL deletion only by ID, added type 2023-08-22 13:27:48 +02:00
Robert von Burg 9c4ac3e7a4
[New] Added StrolchTransaction.getStatistics() 2023-08-21 16:12:27 +02:00
Robert von Burg 2fdc7118e4
[New] Added ObjectFilter.toStatistics() 2023-08-21 16:12:13 +02:00
Robert von Burg 5c90e7f42e
[Project] Exclude angus-activation from transitive dependencies 2023-08-04 15:16:58 +02:00
Robert von Burg e197a3eb6b
[Minor] Added logger to send mail with attachment 2023-08-03 16:52:59 +02:00
Robert von Burg 2ae0389f2c
[Minor] Catch throwable mail sending exceptions 2023-08-03 16:52:44 +02:00
293 changed files with 9337 additions and 8430 deletions

View File

@ -1,23 +0,0 @@
name: Qodana
on:
workflow_dispatch:
pull_request:
push:
branches:
- develop
jobs:
qodana:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 'Qodana Scan'
uses: JetBrains/qodana-action@main
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
- name: 'Github CodeQL Upload'
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{ runner.temp }}/qodana/results/qodana.sarif.json

88
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,88 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "develop", "release/*" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "develop" ]
schedule:
- cron: '25 16 * * 3'
jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
- uses: actions/setup-java@v1
with:
distribution: 'zulu'
java-version: '21'
cache: 'maven'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

View File

@ -1,20 +0,0 @@
# Dependency Review Action
#
# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
#
# Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
name: 'Dependency Review'
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v2

View File

@ -7,7 +7,6 @@
[![Stars](https://img.shields.io/github/stars/strolch-li/strolch?style=flat-square "Stars")](https://github.com/strolch-li/strolch/stargazers)
[![Issues](https://img.shields.io/github/issues/strolch-li/strolch?style=flat-square "Issues")](https://github.com/strolch-li/strolch/issues)
[![Build Status](https://ci.atexxi.ch/buildStatus/icon?job=strolch)](https://ci.atexxi.ch/job/strolch/)
[![Qodana](https://github.com/strolch-li/strolch/actions/workflows/code_quality.yml/badge.svg)](https://github.com/strolch-li/strolch/actions/workflows/code_quality.yml)
[![Project Map](https://sourcespy.com/shield.svg)](https://sourcespy.com/github/strolchlistrolch/)
The main repository which contains all of Strolch.

View File

@ -4,15 +4,14 @@
The current branches are supported with security fixes:
| Version | Supported |
| ------- | ------------------ |
| 2.0.x | :white_check_mark: |
| 1.8.x | :white_check_mark: |
| 1.7.x | :white_check_mark: |
| <= 1.6.x | :x: |
| Version | Supported |
|----------|--------------------|
| 2.2.x | :white_check_mark: |
| 2.1.x | :white_check_mark: |
| <= 2.0.x | :x: |
## Reporting a Vulnerability
If you find a security vulnerability, then please send an email to eitch@eitchnet.ch. You might encrypt it using KeyOxide with my public GPG key: https://kxd.eitchnet.ch/b1359c320a72a2907f1a7f7875db9c85c74331f7
If you find a security vulnerability, then please email eitch@eitchnet.ch. You might encrypt it using KeyOxide with my public GPG key: https://kxd.eitchnet.ch/b1359c320a72a2907f1a7f7875db9c85c74331f7
We will then consider the vulnerability and shall try our best to close the vulnerability as soon as possible if it is part of an active branch and a fix is possible.

View File

@ -6,7 +6,7 @@
<parent>
<groupId>li.strolch</groupId>
<artifactId>strolch</artifactId>
<version>2.0.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -50,8 +50,8 @@ public class AgentVersion extends StrolchVersion {
}
@Override
public JsonObject toJson() {
JsonObject jsonObject = super.toJson();
public JsonObject toJson(boolean isAdminRequest) {
JsonObject jsonObject = super.toJson(isAdminRequest);
jsonObject.addProperty(AGENT_NAME, this.agentName);
jsonObject.addProperty(ENVIRONMENT, this.environment);
@ -63,10 +63,10 @@ public class AgentVersion extends StrolchVersion {
@Override
public String toString() {
return "AgentVersion{agentName='" + this.agentName + "' , environment='" + this.environment + "' , locale='"
+ this.locale + "' , timezone='" + this.timezone + "' , groupId='" + getGroupId() + "' , artifactId='"
+ getArtifactId() + "' , artifactVersion='" + getArtifactVersion() + "' , scmRevision='"
+ getScmRevision() + "' , scmBranch='" + getScmBranch() + "' , buildTimestamp='" + getBuildTimestamp()
+ "' }";
return "AgentVersion{agentName='" + this.agentName + "' , environment='" + this.environment + "' , locale='" +
this.locale + "' , timezone='" + this.timezone + "' , groupId='" + getGroupId() + "' , artifactId='" +
getArtifactId() + "' , artifactVersion='" + getArtifactVersion() + "' , scmRevision='" +
getScmRevision() + "' , scmBranch='" + getScmBranch() + "' , buildTimestamp='" + getBuildTimestamp() +
"' }";
}
}

View File

@ -42,8 +42,8 @@ public class ComponentVersion extends StrolchVersion {
}
@Override
public JsonObject toJson() {
JsonObject jsonObject = super.toJson();
public JsonObject toJson(boolean isAdminRequest) {
JsonObject jsonObject = super.toJson(isAdminRequest);
jsonObject.addProperty(COMPONENT_NAME, this.componentName);
@ -52,9 +52,9 @@ public class ComponentVersion extends StrolchVersion {
@Override
public String toString() {
return "ComponentVersion{componentName='" + this.componentName + "' , groupId='" + getGroupId()
+ "' , artifactId='" + getArtifactId() + "' , artifactVersion='" + getArtifactVersion()
+ "' , scmRevision='" + getScmRevision() + "' , scmBranch='" + getScmBranch() + "' , buildTimestamp='"
+ getBuildTimestamp() + "' }";
return "ComponentVersion{componentName='" + this.componentName + "' , groupId='" + getGroupId() +
"' , artifactId='" + getArtifactId() + "' , artifactVersion='" + getArtifactVersion() +
"' , scmRevision='" + getScmRevision() + "' , scmBranch='" + getScmBranch() + "' , buildTimestamp='" +
getBuildTimestamp() + "' }";
}
}

View File

@ -2,12 +2,12 @@ package li.strolch.agent.api;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.classic.util.DefaultJoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.MalformedURLException;
public class LoggingLoader {
@ -25,22 +25,25 @@ public class LoggingLoader {
"Not changing logback configuration as " + logConfigFile.getAbsolutePath() + " does not exist.");
} else {
if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext loggerContext)) {
logger.error(logConfigFile.getAbsolutePath() +
" exists, but LoggerFactory is not instance of ch.qos.logback.classic.LoggerContext. Ignoring.");
logger.error(logConfigFile.getAbsolutePath()
+ " exists, but LoggerFactory is not instance of ch.qos.logback.classic.LoggerContext. Ignoring.");
} else {
logger.info(logConfigFile.getAbsolutePath() + " file exists. Reloading logging configuration from " +
logConfigFile);
logger.info(logConfigFile.getAbsolutePath()
+ " file exists. Reloading logging configuration from "
+ logConfigFile);
try {
loggerContext.reset();
new ContextInitializer(loggerContext).configureByResource(logConfigFile.toURI().toURL());
DefaultJoranConfigurator configurator = new DefaultJoranConfigurator();
configurator.setContext(loggerContext);
configurator.configureByResource(logConfigFile.toURI().toURL());
logger.info("Reloaded logger configuration from " + logConfigFile.getAbsolutePath());
lastConfigFile = logConfigFile;
} catch (MalformedURLException | JoranException e) {
} catch (Exception e) {
try {
new ContextInitializer(loggerContext).autoConfig();
} catch (JoranException e1) {
logger.error("Failed to reload original config after failure to load new config from " +
logConfigFile.getAbsolutePath(), e);
logger.error("Failed to reload original config after failure to load new config from "
+ logConfigFile.getAbsolutePath(), e);
}
logger.error("Failed to reload logback configuration from file " + logConfigFile, e);
}
@ -55,10 +58,12 @@ public class LoggingLoader {
reloadLogging(lastConfigFile.getParentFile());
} else {
if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext loggerContext)) {
logger.error("LoggerFactory is not instance of " + LoggerContext.class.getName() +
". Ignoring request to reload configuration!");
System.out.println("LoggerFactory is not instance of " + LoggerContext.class.getName() +
". Ignoring request to reload configuration!");
logger.error("LoggerFactory is not instance of "
+ LoggerContext.class.getName()
+ ". Ignoring request to reload configuration!");
System.out.println("LoggerFactory is not instance of "
+ LoggerContext.class.getName()
+ ". Ignoring request to reload configuration!");
} else {
logger.info(
"Resetting logging configuration using auto config as no previous config fila available...");
@ -69,6 +74,7 @@ public class LoggingLoader {
} catch (JoranException e) {
logger.error("Failed to do logging auto configuration", e);
System.out.println("Failed to do logging auto configuration");
//noinspection CallToPrintStackTrace
e.printStackTrace();
}
}

View File

@ -81,20 +81,14 @@ public class StrolchAgent {
this.appVersion = appVersion;
}
/**
* Return the {@link StrolchConfiguration}
*
* @return the {@link StrolchConfiguration}
*/
public StrolchConfiguration getStrolchConfiguration() {
return this.strolchConfiguration;
}
/**
* Return the container
*
* @return the container
*/
public RuntimeConfiguration getRuntimeConfiguration() {
return this.strolchConfiguration.getRuntimeConfiguration();
}
public ComponentContainer getContainer() {
return this.container;
}
@ -411,8 +405,9 @@ public class StrolchAgent {
public JsonObject getSystemState(long updateInterval, TimeUnit updateIntervalUnit) {
if (this.systemState == null ||
System.currentTimeMillis() - this.systemStateUpdateTime > updateIntervalUnit.toMillis(updateInterval)) {
if (this.systemState == null
|| System.currentTimeMillis() - this.systemStateUpdateTime > updateIntervalUnit.toMillis(
updateInterval)) {
this.systemState = new JsonObject();
JsonObject osJ = new JsonObject();
@ -474,8 +469,8 @@ public class StrolchAgent {
File configPathF = runtimeConfig.getConfigPath();
File dataPathF = runtimeConfig.getDataPath();
File tempPathF = runtimeConfig.getTempPath();
StrolchConfiguration newConfig = parseConfiguration(runtimeConfig.getEnvironment(), configPathF,
dataPathF, tempPathF);
StrolchConfiguration newConfig = parseConfiguration(runtimeConfig.getEnvironment(), configPathF, dataPathF,
tempPathF);
for (String name : this.container.getComponentNames()) {
ComponentConfiguration newComponentConfig = newConfig.getComponentConfiguration(name);

View File

@ -90,23 +90,25 @@ public class StrolchVersion {
this.buildTimestamp = buildTimestamp;
}
public JsonObject toJson() {
public JsonObject toJson(boolean isAdminRequest) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(GROUP_ID, this.groupId);
jsonObject.addProperty(ARTIFACT_ID, this.artifactId);
jsonObject.addProperty(ARTIFACT_VERSION, this.artifactVersion);
jsonObject.addProperty(SCM_REVISION, this.scmRevision);
jsonObject.addProperty(SCM_BRANCH, this.scmBranch);
jsonObject.addProperty(BUILD_TIMESTAMP, this.buildTimestamp);
if (isAdminRequest) {
jsonObject.addProperty(SCM_REVISION, this.scmRevision);
jsonObject.addProperty(SCM_BRANCH, this.scmBranch);
jsonObject.addProperty(BUILD_TIMESTAMP, this.buildTimestamp);
}
return jsonObject;
}
@Override
public String toString() {
return "StrolchVersion{groupId='" + groupId + "' , artifactId='" + artifactId + "', artifactVersion='"
+ artifactVersion + "' , scmRevision='" + scmRevision + "' , scmBranch='" + scmBranch
+ "' , buildTimestamp='" + buildTimestamp + "' }";
return "StrolchVersion{groupId='" + groupId + "' , artifactId='" + artifactId + "', artifactVersion='" +
artifactVersion + "' , scmRevision='" + scmRevision + "' , scmBranch='" + scmBranch +
"' , buildTimestamp='" + buildTimestamp + "' }";
}
}

View File

@ -15,13 +15,13 @@
*/
package li.strolch.agent.api;
import static li.strolch.model.Tags.Json.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import static li.strolch.model.Tags.Json.*;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
@ -83,20 +83,22 @@ public class VersionQueryResult {
return this.errors != null && !this.errors.isEmpty();
}
public JsonObject toJson() {
public JsonObject toJson(boolean isAdminRequest) {
JsonObject jsonObject = new JsonObject();
jsonObject.add(APP_VERSION, this.appVersion.toJson());
jsonObject.add(AGENT_VERSION, this.agentVersion.toJson());
jsonObject.add(APP_VERSION, this.appVersion.toJson(isAdminRequest));
jsonObject.add(AGENT_VERSION, this.agentVersion.toJson(isAdminRequest));
JsonArray componentVersionsJ = new JsonArray();
this.componentVersions.forEach(c -> componentVersionsJ.add(c.toJson()));
this.componentVersions.forEach(c -> componentVersionsJ.add(c.toJson(isAdminRequest)));
jsonObject.add(COMPONENT_VERSIONS, componentVersionsJ);
if (this.errors != null) {
JsonArray errorsJ = new JsonArray();
this.errors.forEach(errorsJ::add);
jsonObject.add(ERRORS, errorsJ);
if (isAdminRequest) {
if (this.errors != null) {
JsonArray errorsJ = new JsonArray();
this.errors.forEach(errorsJ::add);
jsonObject.add(ERRORS, errorsJ);
}
}
return jsonObject;

View File

@ -31,6 +31,8 @@ import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.privilege.PrivilegeHandler;
import li.strolch.utils.dbc.DBC;
import static li.strolch.runtime.StrolchConstants.*;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -70,9 +72,9 @@ public class DefaultRealmHandler extends StrolchComponent implements RealmHandle
@Override
public void setup(ComponentConfiguration configuration) {
this.realms = new HashMap<>(1);
String[] realms = configuration.getStringArray(PROP_REALMS, StrolchConstants.DEFAULT_REALM);
String[] realms = configuration.getStringArray(PROP_REALMS, DEFAULT_REALM);
for (String realmName : realms) {
String dataStoreModeKey = StrolchConstants.makeRealmKey(realmName, PREFIX_DATA_STORE_MODE);
String dataStoreModeKey = makeRealmKey(realmName, PREFIX_DATA_STORE_MODE);
String realmMode = configuration.getString(dataStoreModeKey, null);
InternalStrolchRealm realm = buildRealm(realmName, realmMode);
this.realms.put(realmName, realm);

View File

@ -89,7 +89,7 @@ public abstract class InternalStrolchRealm implements StrolchRealm {
// observer updates
String updateObserversKey = makeRealmKey(getRealm(), PROP_ENABLE_OBSERVER_UPDATES);
this.updateObservers = configuration.getBoolean(updateObserversKey, false);
this.updateObservers = configuration.getBoolean(updateObserversKey, true);
if (this.updateObservers) {
this.observerHandler = new DefaultObserverHandler(container.getAgent(), this);
}

View File

@ -30,6 +30,8 @@ import li.strolch.runtime.configuration.StrolchConfigurationException;
import li.strolch.utils.dbc.DBC;
import li.strolch.utils.helper.StringHelper;
import static li.strolch.agent.impl.DefaultRealmHandler.*;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -87,7 +89,7 @@ public class TransientRealm extends InternalStrolchRealm {
public void initialize(ComponentContainer container, ComponentConfiguration configuration) {
super.initialize(container, configuration);
String key = StrolchConstants.makeRealmKey(getRealm(), DefaultRealmHandler.PREFIX_DATA_STORE_FILE);
String key = StrolchConstants.makeRealmKey(getRealm(), PREFIX_DATA_STORE_FILE);
if (!configuration.hasProperty(key)) {
String msg = "There is no data store file for realm {0}. Set a property with key {1}";
msg = MessageFormat.format(msg, getRealm(), key);

View File

@ -34,14 +34,15 @@ import li.strolch.utils.collections.MapOfMaps;
import li.strolch.utils.dbc.DBC;
import li.strolch.utils.helper.StringHelper;
import li.strolch.utils.objectfilter.ObjectFilter;
import li.strolch.utils.objectfilter.ObjectFilterStatistics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import static java.text.MessageFormat.format;
import static li.strolch.agent.api.StrolchAgent.getUniqueId;
import static li.strolch.model.StrolchModelConstants.*;
import static li.strolch.model.Tags.*;
@ -62,6 +63,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
private final TransactionResult txResult;
private final ObjectFilter objectFilter;
private ObjectFilterStatistics objectFilterStatistics;
private final MapOfMaps<String, String, Resource> resourceCache;
private final MapOfMaps<String, String, Order> orderCache;
private final MapOfMaps<String, String, Activity> activityCache;
@ -285,6 +287,13 @@ public abstract class AbstractTransaction implements StrolchTransaction {
return (!this.objectFilter.isEmpty()) || !this.commands.isEmpty() || !this.flushedCommands.isEmpty();
}
@Override
public ObjectFilterStatistics getStatistics() {
if (this.objectFilterStatistics == null)
return this.objectFilter.toStatistics();
return this.objectFilterStatistics;
}
@Override
public boolean hasLock(Locator locator) throws StrolchLockException {
return this.lockedElements.contains(locator);
@ -506,7 +515,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (locator.getSize() < 3) {
String msg
= "The locator is invalid as it does not have at least three path elements (e.g. Resource/MyType/@id): {0}";
msg = MessageFormat.format(msg, locator.toString());
msg = format(msg, locator.toString());
throw new StrolchModelException(msg);
}
@ -526,7 +535,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (allowNull)
return null;
String msg = "No top level object could be found with locator {0}";
throw new StrolchModelException(MessageFormat.format(msg, locator));
throw new StrolchModelException(format(msg, locator));
}
if (elements.size() == 3)
@ -542,7 +551,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (allowNull)
return null;
String msg = "Could not find ParameterBag for locator {0} on element {1}";
throw new StrolchModelException(MessageFormat.format(msg, locator, rootElement.getLocator()));
throw new StrolchModelException(format(msg, locator, rootElement.getLocator()));
}
if (elements.size() == 5)
@ -554,7 +563,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (allowNull)
return null;
String msg = "Could not find Parameter for locator {0} on element {1}";
throw new StrolchModelException(MessageFormat.format(msg, locator, bag.getLocator()));
throw new StrolchModelException(format(msg, locator, bag.getLocator()));
}
return (T) parameter;
@ -562,7 +571,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (elements.size() != 5) {
String msg = "Missing state Id on locator {0}";
throw new StrolchModelException(MessageFormat.format(msg, locator));
throw new StrolchModelException(format(msg, locator));
}
Resource resource = rootElement.asResource();
@ -580,7 +589,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (!(element instanceof Activity)) {
String msg = "Invalid locator {0} with part {1} as not an Activity but deeper element specified";
throw new StrolchModelException(MessageFormat.format(msg, locator, next));
throw new StrolchModelException(format(msg, locator, next));
}
element = ((Activity) element).getElement(next);
@ -593,7 +602,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
return null;
String msg = "Invalid locator {0} with part {1}";
throw new StrolchModelException(MessageFormat.format(msg, locator, stateOrBagOrActivity));
throw new StrolchModelException(format(msg, locator, stateOrBagOrActivity));
}
@Override
@ -632,8 +641,8 @@ public abstract class AbstractTransaction implements StrolchTransaction {
break;
if (!parents.add(parent))
throw new IllegalStateException(
"circular dependencies from " + element.getLocator() + " to " + parent.getLocator() +
" on relations parameter " + parentParamKey);
format("circular dependencies from {0} to {1} on relations parameter {2}", element.getLocator(),
parent.getLocator(), parentParamKey));
t = parent.getParameter(bagKey, paramKey);
}
@ -778,7 +787,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (assertExists && refP.isEmpty()) {
String msg = "The Order with type \"{0}\" and id \"{1}\" does not exist for param \"{2}\"";
throw new StrolchException(MessageFormat.format(msg, refP.getUom(), refP.getValue(), refP.getLocator()));
throw new StrolchException(format(msg, refP.getUom(), refP.getValue(), refP.getLocator()));
}
if (refP.isEmpty())
@ -892,7 +901,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (assertExists && refP.isEmpty()) {
String msg = "The Resource with type \"{0}\" and id \"{1}\" does not exist for param \"{2}\"";
throw new StrolchException(MessageFormat.format(msg, refP.getUom(), refP.getValue(), refP.getLocator()));
throw new StrolchException(format(msg, refP.getUom(), refP.getValue(), refP.getLocator()));
}
if (refP.isEmpty())
@ -1022,7 +1031,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (assertExists && refP.isEmpty()) {
String msg = "The Activity with type \"{0}\" and id \"{1}\" does not exist for param \"{2}\"";
throw new StrolchException(MessageFormat.format(msg, refP.getUom(), refP.getValue(), refP.getLocator()));
throw new StrolchException(format(msg, refP.getUom(), refP.getValue(), refP.getLocator()));
}
if (refP.isEmpty())
@ -1125,6 +1134,21 @@ public abstract class AbstractTransaction implements StrolchTransaction {
this.objectFilter.removeObjectCache(locator.get(0), locator);
}
@Override
public boolean isResourceCached(String type, String id) {
return this.resourceCache.containsElement(type, id);
}
@Override
public boolean isOrderCached(String type, String id) {
return this.orderCache.containsElement(type, id);
}
@Override
public boolean isActivityCached(String type, String id) {
return this.activityCache.containsElement(type, id);
}
@Override
public Resource getCachedResource(String type, String id) {
return this.resourceCache.getElement(type, id);
@ -1140,6 +1164,66 @@ public abstract class AbstractTransaction implements StrolchTransaction {
return this.activityCache.getElement(type, id);
}
@Override
public Stream<Resource> streamCachedResources(String... types) {
if (types.length == 0)
return this.resourceCache.values().stream();
if (types.length == 1) {
String type = types[0];
if (!this.resourceCache.containsMap(type))
return Stream.empty();
return new ArrayList<>(this.resourceCache.getMap(type).values()).stream();
}
return this.resourceCache.values().stream().filter(element -> {
String resType = element.getType();
for (String type : types) {
if (resType.equals(type))
return true;
}
return false;
});
}
@Override
public Stream<Order> streamCachedOrders(String... types) {
if (types.length == 0)
return this.orderCache.values().stream();
if (types.length == 1) {
String type = types[0];
if (!this.orderCache.containsMap(type))
return Stream.empty();
return new ArrayList<>(this.orderCache.getMap(type).values()).stream();
}
return this.orderCache.values().stream().filter(element -> {
String resType = element.getType();
for (String type : types) {
if (resType.equals(type))
return true;
}
return false;
});
}
@Override
public Stream<Activity> streamCachedActivities(String... types) {
if (types.length == 0)
return this.activityCache.values().stream();
if (types.length == 1) {
String type = types[0];
if (!this.activityCache.containsMap(type))
return Stream.empty();
return new ArrayList<>(this.activityCache.getMap(type).values()).stream();
}
return this.activityCache.values().stream().filter(element -> {
String resType = element.getType();
for (String type : types) {
if (resType.equals(type))
return true;
}
return false;
});
}
@Override
public boolean hasResource(String type, String id) {
boolean inFilter = hasElementInFilter(Tags.RESOURCE, Resource.locatorFor(type, id));
@ -1244,6 +1328,8 @@ public abstract class AbstractTransaction implements StrolchTransaction {
lock(resource);
this.objectFilter.add(Tags.RESOURCE, resource.getLocator(), resource);
}
this.resourceCache.addElement(resource.getType(), resource.getId(), resource);
}
@Override
@ -1262,6 +1348,8 @@ public abstract class AbstractTransaction implements StrolchTransaction {
lock(order);
this.objectFilter.add(Tags.ORDER, order.getLocator(), order);
}
this.orderCache.addElement(order.getType(), order.getId(), order);
}
@Override
@ -1280,6 +1368,8 @@ public abstract class AbstractTransaction implements StrolchTransaction {
lock(activity);
this.objectFilter.add(Tags.ACTIVITY, activity.getLocator(), activity);
}
this.activityCache.addElement(activity.getType(), activity.getId(), activity);
}
@Override
@ -1289,6 +1379,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
resource.assertNotReadonly();
lock(resource);
this.objectFilter.add(Tags.RESOURCE, resource.getLocator(), resource);
this.resourceCache.addElement(resource.getType(), resource.getId(), resource);
}
@Override
@ -1298,6 +1389,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
order.assertNotReadonly();
lock(order);
this.objectFilter.add(Tags.ORDER, order.getLocator(), order);
this.orderCache.addElement(order.getType(), order.getId(), order);
}
@Override
@ -1307,6 +1399,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
activity.assertNotReadonly();
lock(activity);
this.objectFilter.add(Tags.ACTIVITY, activity.getLocator(), activity);
this.activityCache.addElement(activity.getType(), activity.getId(), activity);
}
@Override
@ -1315,6 +1408,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
DBC.PRE.assertNotNull("resource must not be null", resource);
resource.assertNotReadonly();
this.objectFilter.update(Tags.RESOURCE, resource.getLocator(), resource);
this.resourceCache.addElement(resource.getType(), resource.getId(), resource);
}
@Override
@ -1323,6 +1417,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
DBC.PRE.assertNotNull("order must not be null", order);
order.assertNotReadonly();
this.objectFilter.update(Tags.ORDER, order.getLocator(), order);
this.orderCache.addElement(order.getType(), order.getId(), order);
}
@Override
@ -1331,6 +1426,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
DBC.PRE.assertNotNull("activity must not be null", activity);
activity.assertNotReadonly();
this.objectFilter.update(Tags.ACTIVITY, activity.getLocator(), activity);
this.activityCache.addElement(activity.getType(), activity.getId(), activity);
}
@Override
@ -1374,7 +1470,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
List<Resource> changedR = this.objectFilter.getRemoved(Resource.class, Tags.RESOURCE);
if (changedR.size() == 1) {
RemoveResourceCommand cmd = new RemoveResourceCommand(this);
cmd.setResource(changedR.get(0));
cmd.setResource(changedR.getFirst());
add(cmd);
} else if (changedR.size() > 1) {
RemoveResourcesCommand cmd = new RemoveResourcesCommand(this);
@ -1386,7 +1482,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
changedR = this.objectFilter.getUpdated(Resource.class, Tags.RESOURCE);
if (changedR.size() == 1) {
UpdateResourceCommand cmd = new UpdateResourceCommand(this);
cmd.setResource(changedR.get(0));
cmd.setResource(changedR.getFirst());
add(cmd);
} else if (changedR.size() > 1) {
UpdateResourcesCommand cmd = new UpdateResourcesCommand(this);
@ -1398,7 +1494,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
changedR = this.objectFilter.getAdded(Resource.class, Tags.RESOURCE);
if (changedR.size() == 1) {
AddResourceCommand cmd = new AddResourceCommand(this);
cmd.setResource(changedR.get(0));
cmd.setResource(changedR.getFirst());
add(cmd);
} else if (changedR.size() > 1) {
AddResourcesCommand cmd = new AddResourcesCommand(this);
@ -1413,7 +1509,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
List<Order> changedO = this.objectFilter.getRemoved(Order.class, Tags.ORDER);
if (changedO.size() == 1) {
RemoveOrderCommand cmd = new RemoveOrderCommand(this);
cmd.setOrder(changedO.get(0));
cmd.setOrder(changedO.getFirst());
add(cmd);
} else if (changedO.size() > 1) {
RemoveOrdersCommand cmd = new RemoveOrdersCommand(this);
@ -1425,7 +1521,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
changedO = this.objectFilter.getUpdated(Order.class, Tags.ORDER);
if (changedO.size() == 1) {
UpdateOrderCommand cmd = new UpdateOrderCommand(this);
cmd.setOrder(changedO.get(0));
cmd.setOrder(changedO.getFirst());
add(cmd);
} else if (changedO.size() > 1) {
UpdateOrdersCommand cmd = new UpdateOrdersCommand(this);
@ -1437,7 +1533,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
changedO = this.objectFilter.getAdded(Order.class, Tags.ORDER);
if (changedO.size() == 1) {
AddOrderCommand cmd = new AddOrderCommand(this);
cmd.setOrder(changedO.get(0));
cmd.setOrder(changedO.getFirst());
add(cmd);
} else if (changedO.size() > 1) {
AddOrdersCommand cmd = new AddOrdersCommand(this);
@ -1452,7 +1548,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
List<Activity> changedA = this.objectFilter.getRemoved(Activity.class, Tags.ACTIVITY);
if (changedA.size() == 1) {
RemoveActivityCommand cmd = new RemoveActivityCommand(this);
cmd.setActivity(changedA.get(0));
cmd.setActivity(changedA.getFirst());
add(cmd);
} else if (changedA.size() > 1) {
RemoveActivitiesCommand cmd = new RemoveActivitiesCommand(this);
@ -1464,7 +1560,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
changedA = this.objectFilter.getUpdated(Activity.class, Tags.ACTIVITY);
if (changedA.size() == 1) {
UpdateActivityCommand cmd = new UpdateActivityCommand(this);
cmd.setActivity(changedA.get(0));
cmd.setActivity(changedA.getFirst());
add(cmd);
} else if (changedA.size() > 1) {
UpdateActivitiesCommand cmd = new UpdateActivitiesCommand(this);
@ -1476,7 +1572,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
changedA = this.objectFilter.getAdded(Activity.class, Tags.ACTIVITY);
if (changedA.size() == 1) {
AddActivityCommand cmd = new AddActivityCommand(this);
cmd.setActivity(changedA.get(0));
cmd.setActivity(changedA.getFirst());
add(cmd);
} else if (changedA.size() > 1) {
AddActivitiesCommand cmd = new AddActivitiesCommand(this);
@ -1484,6 +1580,13 @@ public abstract class AbstractTransaction implements StrolchTransaction {
add(cmd);
}
if (this.objectFilterStatistics == null) {
this.objectFilterStatistics = this.objectFilter.toStatistics();
} else {
ObjectFilterStatistics statistics = this.objectFilter.toStatistics();
this.objectFilterStatistics = this.objectFilterStatistics.merge(statistics);
}
// clear, so that we don't do it twice in case of a flush()
this.objectFilter.clearCache();
}
@ -1515,7 +1618,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
this.closeStrategy = TransactionCloseStrategy.ROLLBACK;
String msg = "Strolch Transaction for realm {0} failed due to {1}";
msg = MessageFormat.format(msg, getRealmName(), getExceptionMessage(e));
msg = format(msg, getRealmName(), getExceptionMessage(e));
throw new StrolchTransactionException(msg, e);
}
}
@ -1579,7 +1682,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
@Override
public void autoCloseableRollback() {
long start = System.nanoTime();
logger.warn(MessageFormat.format("Rolling back TX for realm {0}...", getRealmName()));
logger.warn(format("Rolling back TX for realm {0}...", getRealmName()));
try {
this.txResult.setState(TransactionState.ROLLING_BACK);
undoCommands();
@ -1792,12 +1895,13 @@ public abstract class AbstractTransaction implements StrolchTransaction {
OperationsLog operationsLog = container.getComponent(OperationsLog.class);
operationsLog.addMessage(new LogMessage(this.realm.getRealm(), this.certificate.getUsername(),
Locator.valueOf(AGENT, "tx", this.action, getUniqueId()), LogSeverity.Exception,
LogMessageState.Information, ResourceBundle.getBundle("strolch-agent"),
"agent.tx.failed").withException(e).value("reason", e));
LogMessageState.Information, ResourceBundle.getBundle("strolch-agent"), "agent.tx.failed")
.withException(e)
.value("reason", e));
}
String msg = "Strolch Transaction for realm {0} failed due to {1}\n{2}";
msg = MessageFormat.format(msg, getRealmName(), getExceptionMessage(e), sb.toString());
msg = format(msg, getRealmName(), getExceptionMessage(e), sb.toString());
StrolchTransactionException ex = new StrolchTransactionException(msg, e);
if (throwEx)
@ -1906,10 +2010,10 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (this.auditTrail != null && !isSuppressAuditsForAudits()) {
if (this.realm.isAuditTrailEnabledForRead())
auditsForAudits(audits, AccessType.READ, Tags.AUDIT, this.auditTrail.getRead());
auditsForAudits(audits, AccessType.CREATE, Tags.AUDIT, this.auditTrail.getCreated());
auditsForAudits(audits, AccessType.UPDATE, Tags.AUDIT, this.auditTrail.getUpdated());
auditsForAudits(audits, AccessType.DELETE, Tags.AUDIT, this.auditTrail.getDeleted());
auditsForAudits(audits, AccessType.READ, this.auditTrail.getRead());
auditsForAudits(audits, AccessType.CREATE, this.auditTrail.getCreated());
auditsForAudits(audits, AccessType.UPDATE, this.auditTrail.getUpdated());
auditsForAudits(audits, AccessType.DELETE, this.auditTrail.getDeleted());
}
if (!audits.isEmpty())
@ -1924,9 +2028,9 @@ public abstract class AbstractTransaction implements StrolchTransaction {
}
}
private void auditsForAudits(List<Audit> audits, AccessType accessType, String elementType, Set<Audit> elements) {
private void auditsForAudits(List<Audit> audits, AccessType accessType, Set<Audit> elements) {
for (Audit element : elements) {
audits.add(auditFrom(accessType, elementType, StringHelper.DASH, element.getId().toString()));
audits.add(auditFrom(accessType, Tags.AUDIT, StringHelper.DASH, element.getId().toString()));
}
}

View File

@ -42,6 +42,7 @@ import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.runtime.StrolchConstants;
import li.strolch.service.api.Command;
import li.strolch.utils.objectfilter.ObjectFilterStatistics;
/**
* <p>
@ -1570,6 +1571,21 @@ public interface StrolchTransaction extends AutoCloseable {
*/
void removeFromCache(Locator locator);
/**
* Returns true if the given resource is currently cached
*/
boolean isResourceCached(String type, String id);
/**
* Returns true if the given order is currently cached
*/
boolean isOrderCached(String type, String id);
/**
* Returns true if the given activity is currently cached
*/
boolean isActivityCached(String type, String id);
/**
* Returns the cached resource with the given type and id, or null if not yet fetched
*
@ -1606,6 +1622,21 @@ public interface StrolchTransaction extends AutoCloseable {
*/
Activity getCachedActivity(String type, String id);
/**
* Returns a stream of resources in the cache
*/
Stream<Resource> streamCachedResources(String... types);
/**
* Returns a stream of orders in the cache
*/
Stream<Order> streamCachedOrders(String... types);
/**
* Returns a stream of activities in the cache
*/
Stream<Activity> streamCachedActivities(String... types);
/**
* Returns true if the @{@link Resource} exists with the given type and ID
*
@ -1891,4 +1922,9 @@ public interface StrolchTransaction extends AutoCloseable {
* if the session for this TX does not have any of the given roles
*/
void assertHasAnyRole(String... roleNames) throws AccessDeniedException;
/**
* Returns the statistics of this TX, i.e. the number of elements added, updated and removed in this TX
*/
ObjectFilterStatistics getStatistics();
}

View File

@ -61,7 +61,8 @@ public class InMemoryStrolchDao<T extends StrolchRootElement> implements Strolch
public List<T> queryAll(String... types) throws StrolchPersistenceException {
List<T> values = new ArrayList<>();
for (String type : types) {
values.addAll(this.elements.getList(type));
if (this.elements.containsList(type))
values.addAll(this.elements.getList(type));
}
return values;
}

View File

@ -15,8 +15,6 @@
*/
package li.strolch.policy;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.PARAM_ORDER;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchAgent;
import li.strolch.agent.api.StrolchComponent;
@ -27,6 +25,8 @@ import li.strolch.service.api.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.PARAM_ORDER;
/**
* Interface for all Strolch policies, which are instantiated by the {@link PolicyHandler}
*
@ -103,6 +103,14 @@ public abstract class StrolchPolicy {
return this.tx;
}
/**
* Returns true if this TX is still open, or committing, and thus can still be used
* @return true if this TX is still open, or committing, and thus can still be used
*/
protected boolean isTxOpen() {
return this.tx.isOpen() || this.tx.isCommitting();
}
protected Order getOrder(IActivityElement element) {
return tx().getOrderByRelation(element.getRootElement(), PARAM_ORDER, true);
}

View File

@ -0,0 +1,59 @@
package li.strolch.policy.notifications;
import li.strolch.model.Resource;
import li.strolch.model.StrolchModelConstants;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.utils.collections.DateRange;
import java.time.ZonedDateTime;
import java.util.List;
import static li.strolch.model.StrolchModelConstants.*;
public class DefaultNotificationsPolicy extends NotificationsPolicy {
public DefaultNotificationsPolicy(StrolchTransaction tx) {
super(tx);
}
@Override
public List<Resource> findUserNotifications() {
return tx().streamResources(StrolchModelConstants.TYPE_NOTIFICATION).filter(this::isForUser).toList();
}
@Override
public boolean canView(Resource notification) {
return isForAll(notification) || isForRole(notification) || isForGroup(notification);
}
protected boolean isForUser(Resource notification) {
if (!isActive(notification))
return false;
return isEnabled(notification) && (
isForAll(notification) || isForRole(notification) || isForGroup(notification));
}
protected boolean isActive(Resource notification) {
return new DateRange()
.from(notification.getDate(BAG_VISIBILITY, PARAM_VISIBLE_FROM), true)
.to(notification.getDate(BAG_VISIBILITY, PARAM_VISIBLE_TO), true)
.contains(ZonedDateTime.now());
}
protected boolean isEnabled(Resource notification) {
return notification.getBoolean(BAG_VISIBILITY, PARAM_ENABLED);
}
protected boolean isForAll(Resource notification) {
return notification.getBoolean(BAG_VISIBILITY, PARAM_FOR_ALL);
}
protected boolean isForRole(Resource notification) {
List<String> roles = notification.getStringList(BAG_VISIBILITY, PARAM_ROLES);
return roles.stream().anyMatch(r -> tx().getCertificate().hasRole(r));
}
protected boolean isForGroup(Resource notification) {
List<String> groups = notification.getStringList(BAG_VISIBILITY, PARAM_GROUPS);
return groups.stream().anyMatch(r -> tx().getCertificate().hasGroup(r));
}
}

View File

@ -0,0 +1,28 @@
package li.strolch.policy.notifications;
import li.strolch.model.Resource;
import li.strolch.model.policy.PolicyDef;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.policy.StrolchPolicy;
import java.util.List;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.POLICY_DEFAULT;
import static li.strolch.model.policy.PolicyDef.getJavaPolicy;
import static li.strolch.model.policy.PolicyDef.getKeyPolicy;
public abstract class NotificationsPolicy extends StrolchPolicy {
public NotificationsPolicy(StrolchTransaction tx) {
super(tx);
}
public abstract List<Resource> findUserNotifications();
public abstract boolean canView(Resource notification);
public static NotificationsPolicy getDefaultPolicy(StrolchTransaction tx) {
PolicyDef defaultDef = getKeyPolicy(NotificationsPolicy.class, POLICY_DEFAULT);
PolicyDef fallbackDef = getJavaPolicy(NotificationsPolicy.class, DefaultNotificationsPolicy.class);
return tx.getPolicy(NotificationsPolicy.class, defaultDef, fallbackDef);
}
}

View File

@ -87,6 +87,8 @@ public class StrolchConstants extends StrolchModelConstants {
public static final String PRIVILEGE_SET_USER_STATE = PrivilegeHandler.PRIVILEGE_SET_USER_STATE;
public static final String PRIVILEGE_SET_USER_PASSWORD = PrivilegeHandler.PRIVILEGE_SET_USER_PASSWORD;
public static final String PRIVILEGE_INSPECTOR = "Inspector";
public static final String PRIVILEGE_INVALIDATE_SESSION = "InvalidateSession";
public static final String PRIVILEGE_GET_SESSION = "GetSession";
@ -94,5 +96,8 @@ public class StrolchConstants extends StrolchModelConstants {
public static final String PRIVILEGE_UPDATE_PREFIX = "Update";
public static final String PRIVILEGE_REMOVE_PREFIX = "Remove";
public static final String PRIVILEGE_GET_PREFIX = "Get";
public static final String PRIVILEGE_GET_NOTIFICATIONS = "GetNotifications";
public static final String PRIVILEGE_GET_NOTIFICATION = "GetNotification";
public static final String PRIVILEGE_GET_NOTIFICATIONS_ALL = "GetNotificationsAll";
}
}

View File

@ -15,19 +15,6 @@
*/
package li.strolch.runtime.privilege;
import static java.lang.Boolean.parseBoolean;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static li.strolch.privilege.handler.PrivilegeHandler.PARAM_PERSIST_SESSIONS;
import static li.strolch.privilege.handler.PrivilegeHandler.PARAM_PERSIST_SESSIONS_PATH;
import static li.strolch.privilege.helper.XmlConstants.XML_PARAM_BASE_PATH;
import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.*;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.Map;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
import li.strolch.agent.api.StrolchRealm;
@ -48,6 +35,21 @@ import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.configuration.RuntimeConfiguration;
import li.strolch.utils.helper.XmlHelper;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.Map;
import static java.lang.Boolean.parseBoolean;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static li.strolch.persistence.api.TransactionThreadLocal.getTx;
import static li.strolch.persistence.api.TransactionThreadLocal.hasTx;
import static li.strolch.privilege.handler.PrivilegeHandler.PARAM_PERSIST_SESSIONS;
import static li.strolch.privilege.handler.PrivilegeHandler.PARAM_PERSIST_SESSIONS_PATH;
import static li.strolch.privilege.helper.XmlConstants.PARAM_BASE_PATH;
import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.*;
public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements PrivilegeHandler {
public static final String PROP_PRIVILEGE_CONFIG_FILE = "privilegeConfigFile";
@ -89,8 +91,7 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
/**
* Initializes the {@link DefaultPrivilegeHandler} from the configuration file
*
* @param privilegeXmlFile
* a {@link File} reference to the XML file containing the configuration for Privilege
* @param privilegeXmlFile a {@link File} reference to the XML file containing the configuration for Privilege
*
* @return the initialized {@link PrivilegeHandler} where the {@link EncryptionHandler} and
* {@link PersistenceHandler} are set and initialized as well
@ -126,7 +127,7 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
if (containerModel.getPersistenceHandlerClassName().equals(XmlPersistenceHandler.class.getName())) {
Map<String, String> xmlParams = containerModel.getPersistenceHandlerParameterMap();
File configPath = runtimeConfig.getConfigPath();
xmlParams.put(XML_PARAM_BASE_PATH, configPath.getPath());
xmlParams.put(PARAM_BASE_PATH, configPath.getPath());
}
return new PrivilegeInitializer(getScheduledExecutor(getName())).initializeFromXml(containerModel);
@ -185,13 +186,17 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
private void writeAudit(Certificate certificate, String login, AccessType accessType, String username) {
StrolchRealm realm = getContainer().getRealm(certificate);
try (StrolchTransaction tx = realm.openTx(certificate, login, false).silentThreshold(1, NANOSECONDS)) {
try (StrolchTransaction tx = hasTx() ? getTx() : openTx(certificate, login, realm)) {
tx.setSuppressAudits(true);
Audit audit = tx.auditFrom(accessType, PRIVILEGE, CERTIFICATE, username);
tx.getAuditTrail().add(tx, audit);
}
}
private static StrolchTransaction openTx(Certificate certificate, String login, StrolchRealm realm) {
return realm.openTx(certificate, login, false).silentThreshold(1, NANOSECONDS);
}
@Override
public PrivilegeContext validate(Certificate certificate) throws PrivilegeException {
return this.privilegeHandler.validate(certificate);

View File

@ -9,7 +9,7 @@ import li.strolch.model.StrolchRootElement;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Role;
@ -20,10 +20,10 @@ public class ModelPrivilege implements PrivilegePolicy {
/**
* The value of {@link Restrictable#getPrivilegeValue()} is used to check if the {@link Role} has this privilege
*
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, IPrivilege, Restrictable)
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, Privilege, Restrictable)
*/
@Override
public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@ -31,15 +31,15 @@ public class ModelPrivilege implements PrivilegePolicy {
/**
* The value of {@link Restrictable#getPrivilegeValue()} is used to check if the {@link Role} has this privilege
*
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, IPrivilege, Restrictable)
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, Privilege, Restrictable)
*/
@Override
public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
preValidate(privilege, restrictable);

View File

@ -13,21 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.rest;
import static java.util.function.Function.identity;
import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.PRIVILEGE_GET_SESSION;
import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.PRIVILEGE_INVALIDATE_SESSION;
import java.text.MessageFormat;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
package li.strolch.runtime.sessions;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
@ -38,13 +24,25 @@ import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.SimpleRestrictable;
import li.strolch.privilege.model.Usage;
import li.strolch.rest.model.UserSession;
import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.privilege.PrivilegeHandler;
import li.strolch.utils.dbc.DBC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.MessageFormat;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static java.util.function.Function.identity;
import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.PRIVILEGE_GET_SESSION;
import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.PRIVILEGE_INVALIDATE_SESSION;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -52,12 +50,10 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
public static final String PARAM_SESSION_TTL_MINUTES = "session.ttl.minutes";
public static final String PARAM_SESSION_MAX_KEEP_ALIVE_MINUTES = "session.maxKeepAlive.minutes";
public static final String PARAM_SESSION_RELOAD_SESSIONS = "session.reload";
private static final Logger logger = LoggerFactory.getLogger(DefaultStrolchSessionHandler.class);
private PrivilegeHandler privilegeHandler;
private final Map<String, Certificate> certificateMap;
private boolean reloadSessions;
private int sessionTtlMinutes;
private int maxKeepAliveMinutes;
@ -74,6 +70,29 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
return this.sessionTtlMinutes;
}
@Override
public void refreshSessions() {
Map<String, Certificate> certificates;
try {
certificates = runAsAgentWithResult(ctx -> {
Certificate cert = ctx.getCertificate();
return this.privilegeHandler.getPrivilegeHandler().getCertificates(cert).stream()
.filter(c -> !c.getUserState().isSystem())
.collect(Collectors.toMap(Certificate::getAuthToken, identity()));
});
} catch (Exception e) {
throw new IllegalStateException("Failed to refresh sessions!", e);
}
synchronized (this.certificateMap) {
this.certificateMap.clear();
this.certificateMap.putAll(certificates);
}
checkSessionsForTimeout();
logger.info("Restored " + certificates.size() + " sessions of which " +
(certificates.size() - this.certificateMap.size()) + " had timed out and were removed.");
}
@Override
public int getSessionMaxKeepAliveMinutes() {
return this.maxKeepAliveMinutes;
@ -89,30 +108,14 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
this.sessionTtlMinutes = configuration.getInt(PARAM_SESSION_TTL_MINUTES, 30);
this.maxKeepAliveMinutes = configuration.getInt(PARAM_SESSION_MAX_KEEP_ALIVE_MINUTES,
Math.max(this.sessionTtlMinutes, 30));
this.reloadSessions = configuration.getBoolean(PARAM_SESSION_RELOAD_SESSIONS, false);
super.initialize(configuration);
}
@Override
public void start() throws Exception {
this.privilegeHandler = getContainer().getComponent(PrivilegeHandler.class);
this.certificateMap.clear();
if (this.reloadSessions) {
Map<String, Certificate> certificates = runAsAgentWithResult(ctx -> {
Certificate cert = ctx.getCertificate();
return this.privilegeHandler.getPrivilegeHandler()
.getCertificates(cert)
.stream()
.filter(c -> !c.getUserState().isSystem())
.collect(Collectors.toMap(Certificate::getAuthToken, identity()));
});
this.certificateMap.putAll(certificates);
checkSessionsForTimeout();
logger.info("Restored " + certificates.size() + " sessions of which " + (certificates.size()
- this.certificateMap.size()) + " had timed out and were removed.");
}
refreshSessions();
this.validateSessionsTask = getScheduledExecutor("SessionHandler").scheduleWithFixedDelay(
this::checkSessionsForTimeout, 5, 1, TimeUnit.MINUTES);
@ -126,27 +129,6 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
if (this.validateSessionsTask != null)
this.validateSessionsTask.cancel(true);
if (this.reloadSessions) {
if (this.privilegeHandler != null)
persistSessions();
} else {
Map<String, Certificate> certificateMap;
synchronized (this.certificateMap) {
certificateMap = new HashMap<>(this.certificateMap);
this.certificateMap.clear();
}
for (Certificate certificate : certificateMap.values()) {
try {
this.privilegeHandler.invalidate(certificate);
} catch (Exception e) {
logger.error("Failed to invalidate certificate " + certificate, e);
}
}
}
this.privilegeHandler = null;
super.stop();
}
@ -320,9 +302,9 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
return certificate;
}
private void checkSessionsForTimeout() {
ZonedDateTime maxKeepAliveTime = ZonedDateTime.now().minus(this.maxKeepAliveMinutes, ChronoUnit.MINUTES);
ZonedDateTime timeOutTime = ZonedDateTime.now().minus(this.sessionTtlMinutes, ChronoUnit.MINUTES);
protected void checkSessionsForTimeout() {
ZonedDateTime maxKeepAliveTime = ZonedDateTime.now().minusMinutes(this.maxKeepAliveMinutes);
ZonedDateTime timeOutTime = ZonedDateTime.now().minusMinutes(this.sessionTtlMinutes);
Map<String, Certificate> certificateMap = getCertificateMapCopy();
for (Certificate certificate : certificateMap.values()) {
@ -344,7 +326,7 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
}
}
private void sessionTimeout(Certificate certificate) {
protected void sessionTimeout(Certificate certificate) {
DBC.PRE.assertNotNull("Certificate must be given!", certificate);
Certificate removedCert = this.certificateMap.remove(certificate.getAuthToken());

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.rest;
package li.strolch.runtime.sessions;
import java.util.List;
import java.util.Locale;
@ -24,7 +24,6 @@ import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Usage;
import li.strolch.rest.model.UserSession;
/**
* The {@link StrolchSessionHandler} implements session management. It authenticates, validates and invalidates session
@ -34,6 +33,11 @@ import li.strolch.rest.model.UserSession;
*/
public interface StrolchSessionHandler {
/**
* Refreshes the sessions from the {@link li.strolch.runtime.privilege.PrivilegeHandler}
*/
void refreshSessions();
/**
* Returns the time to live for a session in minutes
*

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.rest.model;
package li.strolch.runtime.sessions;
import java.time.ZonedDateTime;
import java.util.Locale;

View File

@ -1,9 +1,12 @@
package li.strolch.search;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.PARAM_ORDER;
import li.strolch.model.Order;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
import java.util.stream.Stream;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.PARAM_ORDER;
/**
* Performs a search for {@link Activity} elements
@ -19,7 +22,13 @@ public class ActivitySearch extends StrolchSearch<Activity> {
@Override
public ActivitySearch types(String... types) {
this.navigator = tx -> tx.streamActivities(types);
this.navigator = tx -> {
Stream<Activity> cachedStream = tx.streamCachedActivities(types);
Stream<Activity> stream = tx
.streamActivities(types)
.filter(e -> !tx.isActivityCached(e.getType(), e.getId()));
return Stream.concat(cachedStream, stream);
};
return this;
}
@ -40,4 +49,9 @@ public class ActivitySearch extends StrolchSearch<Activity> {
super.internal();
return this;
}
@Override
public ActivitySearchResult search(StrolchTransaction tx) {
return new ActivitySearchResult(prepareSearch(tx));
}
}

View File

@ -0,0 +1,11 @@
package li.strolch.search;
import li.strolch.model.activity.Activity;
import java.util.stream.Stream;
public class ActivitySearchResult extends RootElementSearchResult<Activity> {
public ActivitySearchResult(Stream<Activity> stream) {
super(stream);
}
}

View File

@ -3,6 +3,8 @@ package li.strolch.search;
import li.strolch.model.StrolchRootElement;
import li.strolch.utils.collections.DateRange;
import java.time.ZonedDateTime;
/**
* An interface to add search expressions to easily discover the possible search expressions
*/
@ -61,10 +63,16 @@ public interface ExpressionBuilder {
default <T extends StrolchRootElement> SearchExpression<T> containsIgnoreCase(Object right) {
return element -> PredicatesSupport.containsIgnoreCase(right).matches(extract(element));
}
default <T extends StrolchRootElement> SearchExpression<T> containsIgnoreCaseMatchAny(Object right) {
return element -> PredicatesSupport.containsIgnoreCaseMatchAny(right).matches(extract(element));
}
default <T extends StrolchRootElement> SearchExpression<T> isIn(Object right) {
return element -> PredicatesSupport.isIn(right).matches(extract(element));
}
default <T extends StrolchRootElement> SearchExpression<T> isInArray(Object... right) {
return element -> PredicatesSupport.isIn(right).matches(extract(element));
}
default <T extends StrolchRootElement> SearchExpression<T> isInIgnoreCase(Object right) {
return element -> PredicatesSupport.isInIgnoreCase(right).matches(extract(element));
@ -73,4 +81,12 @@ public interface ExpressionBuilder {
default <T extends StrolchRootElement> SearchExpression<T> inRange(DateRange range) {
return element -> PredicatesSupport.inRange(range).matches(extract(element));
}
default <T extends StrolchRootElement> SearchExpression<T> isBefore(ZonedDateTime date, boolean inclusive) {
return element -> PredicatesSupport.isBefore(date, inclusive).matches(extract(element));
}
default <T extends StrolchRootElement> SearchExpression<T> isAfter(ZonedDateTime date, boolean inclusive) {
return element -> PredicatesSupport.isAfter(date, inclusive).matches(extract(element));
}
}

View File

@ -1,10 +1,5 @@
package li.strolch.search;
import static li.strolch.model.StrolchModelConstants.*;
import java.util.function.Function;
import java.util.function.Supplier;
import li.strolch.model.*;
import li.strolch.model.activity.Activity;
import li.strolch.model.parameter.Parameter;
@ -12,6 +7,12 @@ import li.strolch.model.parameter.StringParameter;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.utils.iso8601.ISO8601FormatFactory;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import static li.strolch.model.StrolchModelConstants.*;
/**
* Implements search expressions to be statically imported when writing searches
*/
@ -148,6 +149,26 @@ public class ExpressionsSupport {
};
}
public static <T extends StrolchRootElement> ExpressionBuilder paramOnBagType(String bagType, String paramId) {
return element -> {
List<Object> result = element
.streamOfParameterBagsByType(bagType)
.filter(b -> b.isParamSet(paramId))
.map(b -> b.getParameter(paramId, true).getValue())
.toList();
if (result.size() == 1)
return result.getFirst();
return result.toArray();
};
}
public static <T extends StrolchRootElement> ExpressionBuilder extract(Function<T, Object> extractor) {
return element -> {
@SuppressWarnings("unchecked") T e = (T) element;
return extractor.apply(e);
};
}
public static <T extends StrolchRootElement> SearchExpression<T> paramNull(String paramId) {
return paramNull(BAG_PARAMETERS, paramId);
}

View File

@ -1,12 +1,14 @@
package li.strolch.search;
import static java.util.stream.Collectors.toList;
import java.util.Arrays;
import java.util.List;
import li.strolch.model.Order;
import li.strolch.model.State;
import li.strolch.persistence.api.StrolchTransaction;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
/**
* Performs a search of {@link Order} elements
@ -22,7 +24,11 @@ public class OrderSearch extends StrolchSearch<Order> {
@Override
public OrderSearch types(String... types) {
this.navigator = tx -> tx.streamOrders(types);
this.navigator = tx -> {
Stream<Order> cachedStream = tx.streamCachedOrders(types);
Stream<Order> stream = tx.streamOrders(types).filter(e -> !tx.isOrderCached(e.getType(), e.getId()));
return Stream.concat(cachedStream, stream);
};
return this;
}
@ -61,4 +67,9 @@ public class OrderSearch extends StrolchSearch<Order> {
super.internal();
return this;
}
@Override
public OrderSearchResult search(StrolchTransaction tx) {
return new OrderSearchResult(prepareSearch(tx));
}
}

View File

@ -0,0 +1,37 @@
package li.strolch.search;
import li.strolch.model.Order;
import li.strolch.model.StrolchElement;
import java.util.Comparator;
import java.util.stream.Stream;
public class OrderSearchResult extends RootElementSearchResult<Order> {
public OrderSearchResult(Stream<Order> stream) {
super(stream);
}
/**
* Appends a comparator to the stream of elements to compare by date
*
* @return this for chaining
*/
public OrderSearchResult orderByDate() {
return orderByDate(false);
}
/**
* Appends a comparator to the stream of elements to compare by date
*
* @param reversed flag to reverse the comparison
*
* @return this for chaining
*/
public OrderSearchResult orderByDate(boolean reversed) {
Comparator<Order> comparator = Comparator.comparing(Order::getDate);
if (reversed)
comparator = comparator.reversed();
this.stream = this.stream.sorted(comparator);
return this;
}
}

View File

@ -3,6 +3,8 @@ package li.strolch.search;
import li.strolch.search.predicates.*;
import li.strolch.utils.collections.DateRange;
import java.time.ZonedDateTime;
/**
* Implements predicates to be used as static imports when writing searches
*/
@ -45,7 +47,11 @@ public class PredicatesSupport {
}
public static SearchPredicate contains(Object right) {
return new ContainsPredicate(right, false);
return new ContainsPredicate(right, false, false);
}
public static SearchPredicate containsMatchAny(Object right) {
return new ContainsPredicate(right, false, true);
}
public static SearchPredicate collectionContains(Object right) {
@ -53,7 +59,11 @@ public class PredicatesSupport {
}
public static SearchPredicate containsIgnoreCase(Object right) {
return new ContainsPredicate(right, true);
return new ContainsPredicate(right, true, false);
}
public static SearchPredicate containsIgnoreCaseMatchAny(Object right) {
return new ContainsPredicate(right, true, true);
}
public static SearchPredicate isIn(Object right) {
@ -67,4 +77,12 @@ public class PredicatesSupport {
public static SearchPredicate inRange(DateRange range) {
return new InRangePredicate(range);
}
public static SearchPredicate isBefore(ZonedDateTime dateTime, boolean inclusive) {
return new IsBeforePredicate(dateTime, inclusive);
}
public static SearchPredicate isAfter(ZonedDateTime dateTime, boolean inclusive) {
return new IsAfterPredicate(dateTime, inclusive);
}
}

View File

@ -1,6 +1,9 @@
package li.strolch.search;
import li.strolch.model.Resource;
import li.strolch.persistence.api.StrolchTransaction;
import java.util.stream.Stream;
/**
* Performs a search for {@link Resource} elements
@ -16,7 +19,13 @@ public class ResourceSearch extends StrolchSearch<Resource> {
@Override
public ResourceSearch types(String... types) {
this.navigator = tx -> tx.streamResources(types);
this.navigator = tx -> {
Stream<Resource> cachedStream = tx.streamCachedResources(types);
Stream<Resource> stream = tx
.streamResources(types)
.filter(e -> !tx.isResourceCached(e.getType(), e.getId()));
return Stream.concat(cachedStream, stream);
};
return this;
}
@ -31,4 +40,9 @@ public class ResourceSearch extends StrolchSearch<Resource> {
super.internal();
return this;
}
@Override
public ResourceSearchResult search(StrolchTransaction tx) {
return new ResourceSearchResult(prepareSearch(tx));
}
}

View File

@ -0,0 +1,11 @@
package li.strolch.search;
import li.strolch.model.Resource;
import java.util.stream.Stream;
public class ResourceSearchResult extends RootElementSearchResult<Resource> {
public ResourceSearchResult(Stream<Resource> stream) {
super(stream);
}
}

View File

@ -6,6 +6,7 @@ import li.strolch.model.Order;
import li.strolch.model.Resource;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
/**
* Performs a search for any kind of root element, allowing to mix {@link Resource}, {@link Order} and {@link Activity}
@ -33,4 +34,9 @@ public class RootElementSearch extends StrolchSearch<StrolchRootElement> {
return this;
}
@Override
public RootElementSearchResult<StrolchRootElement> search(StrolchTransaction tx) {
return new RootElementSearchResult<>(prepareSearch(tx));
}
}

View File

@ -1,17 +1,17 @@
package li.strolch.search;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import static li.strolch.model.StrolchModelConstants.BAG_RELATIONS;
import java.util.function.Function;
import java.util.function.Supplier;
import li.strolch.model.Order;
import li.strolch.model.Resource;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
import java.util.function.Function;
import java.util.function.Supplier;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import static li.strolch.model.StrolchModelConstants.BAG_RELATIONS;
/**
* Declares specific search expressions, i.e. extracting the relevant data for a where clause
*/
@ -77,6 +77,10 @@ public interface SearchExpressions {
return ExpressionsSupport.param(BAG_PARAMETERS, paramId);
}
default <T extends StrolchRootElement> ExpressionBuilder extract(Function<T, Object> extractor) {
return ExpressionsSupport.extract(extractor);
}
default ExpressionBuilder relation(String paramId) {
return ExpressionsSupport.param(BAG_RELATIONS, paramId);
}
@ -106,6 +110,10 @@ public interface SearchExpressions {
return ExpressionsSupport.paramNull(bagId, paramId);
}
default ExpressionBuilder paramOnBagType(String bagType, String paramId) {
return ExpressionsSupport.paramOnBagType(bagType, paramId);
}
default ExpressionBuilder relationName(StrolchTransaction tx, String paramId) {
return ExpressionsSupport.relationName(tx, paramId);
}

View File

@ -43,8 +43,7 @@ public abstract class StrolchSearch<T extends StrolchRootElement>
/**
* Used to configure the navigator, i.e. which <code>type</code> of root elements are to be queried
*
* @param types
* the types of elements to search
* @param types the types of elements to search
*
* @return this for chaining
*/
@ -60,8 +59,7 @@ public abstract class StrolchSearch<T extends StrolchRootElement>
/**
* Adds the given {@link SearchExpression} to the current search
*
* @param expression
* the {@link SearchExpression} to add to this search
* @param expression the {@link SearchExpression} to add to this search
*
* @return this for chaining
*/
@ -87,12 +85,13 @@ public abstract class StrolchSearch<T extends StrolchRootElement>
/**
* Performs the actual search, by first validating the privilege context
*
* @param tx
* the TX on which to perform the search
* @param tx the TX on which to perform the search
*
* @return the search result
*/
public RootElementSearchResult<T> search(StrolchTransaction tx) {
public abstract RootElementSearchResult<T> search(StrolchTransaction tx);
protected Stream<T> prepareSearch(StrolchTransaction tx) {
try {
tx.getPrivilegeContext().validateAction(this);
} catch (AccessDeniedException e) {
@ -101,8 +100,7 @@ public abstract class StrolchSearch<T extends StrolchRootElement>
if (tx.getContainer().hasComponent(OperationsLog.class)) {
String realmName = tx.getRealmName();
String searchName = this.privilegeValue.equals(INTERNAL) ?
(getClass().getName() + " (INTERNAL)") :
String searchName = this.privilegeValue.equals(INTERNAL) ? (getClass().getName() + " (INTERNAL)") :
this.privilegeValue;
LogMessage logMessage = new LogMessage(realmName, username,
Locator.valueOf(AGENT, PrivilegeHandler.class.getSimpleName(), getPrivilegeName(), searchName),
@ -114,8 +112,7 @@ public abstract class StrolchSearch<T extends StrolchRootElement>
operationsLog.addMessage(logMessage);
}
String searchName = this.privilegeValue.equals(INTERNAL) ?
(getClass().getSimpleName() + " (INTERNAL)") :
String searchName = this.privilegeValue.equals(INTERNAL) ? (getClass().getSimpleName() + " (INTERNAL)") :
getClass().getSimpleName();
I18nMessage i18n = new I18nMessage(
ResourceBundle.getBundle("strolch-agent", tx.getCertificate().getLocale()),
@ -134,8 +131,7 @@ public abstract class StrolchSearch<T extends StrolchRootElement>
if (this.expression != null)
stream = stream.filter(e -> this.expression.matches(e));
return new RootElementSearchResult<>(stream);
return stream;
}
/**

View File

@ -3,18 +3,20 @@ package li.strolch.search.predicates;
import li.strolch.utils.ObjectHelper;
/**
* Implements the contains predicate, delegating to {@link ObjectHelper#contains(Object, Object, boolean)}
* Implements the contains predicate, delegating to {@link ObjectHelper#contains(Object, Object, boolean, boolean)}
*/
public class ContainsPredicate extends AbstractSearchPredicate {
private final boolean ignoreCase;
private final boolean matchAny;
public ContainsPredicate(Object right, boolean ignoreCase) {
public ContainsPredicate(Object right, boolean ignoreCase, boolean matchAny) {
super(right);
this.ignoreCase = ignoreCase;
this.matchAny = matchAny;
}
@Override
public boolean matches(Object left) {
return ObjectHelper.contains(left, this.right, this.ignoreCase);
return ObjectHelper.contains(left, this.right, this.ignoreCase, !this.matchAny);
}
}

View File

@ -0,0 +1,29 @@
package li.strolch.search.predicates;
import li.strolch.search.SearchPredicate;
import li.strolch.search.ValueCoercer;
import java.time.ZonedDateTime;
import java.util.Date;
/**
* <p>A date predicate, concrete classes implement matching.</p>
*
* <b>Note:</b> Can only be used with {@link Date} elements
*/
public abstract class DatePredicate implements SearchPredicate {
protected final ZonedDateTime dateTime;
protected final boolean inclusive;
public DatePredicate(ZonedDateTime dateTime, boolean inclusive) {
this.dateTime = dateTime;
this.inclusive = inclusive;
}
@Override
public SearchPredicate coerce(ValueCoercer coercer) {
// nothing to coerce
return this;
}
}

View File

@ -1,5 +1,6 @@
package li.strolch.search.predicates;
import java.time.ZonedDateTime;
import java.util.Date;
import li.strolch.search.SearchPredicate;
@ -9,7 +10,7 @@ import li.strolch.utils.collections.DateRange;
/**
* <p>Implements the date in range predicate.</p>
*
* <b>Note:</b> Can only be used with {@link Date} elements
* <b>Note:</b> Can only be used with {@link Date} or {@link ZonedDateTime} objects
*/
public class InRangePredicate implements SearchPredicate {
private final DateRange range;
@ -20,7 +21,11 @@ public class InRangePredicate implements SearchPredicate {
@Override
public boolean matches(Object left) {
return range.contains((Date) left);
if (left instanceof Date)
return this.range.contains((Date) left);
else if (left instanceof ZonedDateTime)
return this.range.contains((ZonedDateTime) left);
throw new IllegalStateException("Unhandled object type " + left.getClass());
}
@Override

View File

@ -0,0 +1,31 @@
package li.strolch.search.predicates;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
/**
* <p>Implements the date is after predicate.</p>
*
* <b>Note:</b> Can only be used with {@link Date} or {@link ZonedDateTime} objects
*/
public class IsAfterPredicate extends DatePredicate {
public IsAfterPredicate(ZonedDateTime dateTime, boolean inclusive) {
super(dateTime, inclusive);
}
@Override
public boolean matches(Object left) {
if (left instanceof Date other) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(other.toInstant(), ZoneId.systemDefault());
if (this.inclusive && this.dateTime.isEqual(zdt))
return true;
return zdt.isAfter(this.dateTime);
} else if (left instanceof ZonedDateTime zdt) {
if (this.inclusive && this.dateTime.isEqual(zdt))
return true;
return zdt.isAfter(this.dateTime);
}
throw new IllegalStateException("Unhandled object type " + left.getClass());
}
}

View File

@ -0,0 +1,31 @@
package li.strolch.search.predicates;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
/**
* <p>Implements the date is before predicate.</p>
*
* <b>Note:</b> Can only be used with {@link Date} or {@link ZonedDateTime} objects
*/
public class IsBeforePredicate extends DatePredicate {
public IsBeforePredicate(ZonedDateTime dateTime, boolean inclusive) {
super(dateTime, inclusive);
}
@Override
public boolean matches(Object left) {
if (left instanceof Date other) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(other.toInstant(), ZoneId.systemDefault());
if (this.inclusive && this.dateTime.isEqual(zdt))
return true;
return zdt.isBefore(this.dateTime);
} else if (left instanceof ZonedDateTime zdt) {
if (this.inclusive && this.dateTime.isEqual(zdt))
return true;
return zdt.isBefore(this.dateTime);
}
throw new IllegalStateException("Unhandled object type " + left.getClass());
}
}

View File

@ -24,6 +24,7 @@ import java.util.Locale;
import java.util.ResourceBundle;
import com.google.gson.JsonObject;
import li.strolch.exception.StrolchException;
import li.strolch.exception.StrolchUserMessageException;
import li.strolch.model.Tags;
import li.strolch.model.i18n.I18nMessageToJsonVisitor;
@ -229,10 +230,8 @@ public class ServiceResult {
json.addProperty(EXCEPTION_MSG, getExceptionMessageWithCauses(this.throwable, false));
json.addProperty(THROWABLE, formatException(this.throwable));
if (this.throwable instanceof StrolchUserMessageException
&& ((StrolchUserMessageException) this.throwable).hasI18n())
json.add(I_18_N, ((StrolchUserMessageException) this.throwable).getI18n()
.accept(new I18nMessageToJsonVisitor()));
if (this.throwable instanceof StrolchException ex && ex.hasI18n())
json.add(I_18_N, ex.getI18n().accept(new I18nMessageToJsonVisitor()));
}
if (!json.has(I_18_N) && this.i18nMessage != null)

View File

@ -1,20 +1,7 @@
package li.strolch.search;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static li.strolch.agent.api.StrolchAgent.getUniqueId;
import static li.strolch.model.ModelGenerator.*;
import static li.strolch.search.ExpressionsSupport.*;
import static li.strolch.search.PredicatesSupport.*;
import static org.junit.Assert.assertEquals;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.google.gson.JsonObject;
import li.strolch.RuntimeMock;
import li.strolch.agent.ParallelTests;
import li.strolch.agent.api.StrolchRealm;
import li.strolch.model.Order;
import li.strolch.model.ParameterBag;
@ -27,6 +14,7 @@ import li.strolch.model.parameter.StringParameter;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.Certificate;
import li.strolch.utils.collections.DateRange;
import li.strolch.utils.iso8601.ISO8601;
import li.strolch.utils.iso8601.ISO8601FormatFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@ -34,12 +22,28 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static java.time.ZoneId.systemDefault;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static li.strolch.agent.api.StrolchAgent.getUniqueId;
import static li.strolch.model.ModelGenerator.*;
import static li.strolch.search.ExpressionsSupport.*;
import static li.strolch.search.PredicatesSupport.*;
import static org.junit.Assert.assertEquals;
public class StrolchSearchTest {
public static final Logger logger = LoggerFactory.getLogger(StrolchSearchTest.class);
private static final String TARGET_PATH = "target/" + StrolchSearchTest.class.getSimpleName();
private static final String SOURCE_PATH = "src/test/resources/transienttest";
public static final String SORTING_TYPE = "SortingType";
private static RuntimeMock runtimeMock;
private static Certificate cert;
@ -51,7 +55,7 @@ public class StrolchSearchTest {
cert = runtimeMock.getPrivilegeHandler().authenticate("test", "test".toCharArray());
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, false)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, false)) {
{
Resource ball = createResource("the-id", "Yellow Ball", "Ball");
@ -62,6 +66,11 @@ public class StrolchSearchTest {
bag.addParameter(new StringParameter("status", "Status", "bla"));
bag.addParameter(new StringParameter("color", "Color", "yellow"));
ball.addParameterBag(new ParameterBag("owner1", "Owner", "Owner"));
ball.setString("owner1", "name", "Felix");
ball.addParameterBag(new ParameterBag("owner2", "Owner", "Owner"));
ball.setString("owner2", "name", "Fox");
tx.add(ball);
}
@ -78,20 +87,25 @@ public class StrolchSearchTest {
bag.addParameter(new StringListParameter("stateList", "Status",
asList(State.EXECUTION.name(), State.EXECUTED.name())));
ball.addParameterBag(new ParameterBag("owner1", "Owner", "Owner"));
ball.setString("owner1", "name", "Jill");
ball.addParameterBag(new ParameterBag("owner2", "Owner", "Owner"));
ball.setString("owner2", "name", "Jane");
tx.add(ball);
}
String id;
id = "ggg";
tx.add(createOrder(id, id.toUpperCase(), "SortingType"));
tx.add(createOrder(id, id.toUpperCase(), SORTING_TYPE));
id = "ccc";
tx.add(createOrder(id, id.toUpperCase(), "SortingType"));
tx.add(createOrder(id, id.toUpperCase(), SORTING_TYPE));
id = "aaa";
tx.add(createOrder(id, id.toUpperCase(), "SortingType"));
tx.add(createOrder(id, id.toUpperCase(), SORTING_TYPE));
id = "bbb";
tx.add(createOrder(id, id.toUpperCase(), "SortingType"));
tx.add(createOrder(id, id.toUpperCase(), SORTING_TYPE));
id = "ddd";
tx.add(createOrder(id, id.toUpperCase(), "SortingType"));
tx.add(createOrder(id, id.toUpperCase(), SORTING_TYPE));
tx.commitOnClose();
}
@ -112,7 +126,7 @@ public class StrolchSearchTest {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
List<JsonObject> result = new BallSearch("the-id", "STATUS", "yellow")
// do search, returns SearchResult
@ -133,11 +147,13 @@ public class StrolchSearchTest {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
List<JsonObject> result = new BallSearch("the-id", "STATUS", "yellow")
.where(element -> element.hasTimedState(STATE_FLOAT_ID)).search(tx)
.map(a -> a.accept(toJsonVisitor)).toList();
.where(element -> element.hasTimedState(STATE_FLOAT_ID))
.search(tx)
.map(a -> a.accept(toJsonVisitor))
.toList();
assertEquals(2, result.size());
}
@ -150,7 +166,7 @@ public class StrolchSearchTest {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
List<JsonObject> result = new NewBallSearch().id("the-id").status("bla").color("yellow")
@ -168,21 +184,27 @@ public class StrolchSearchTest {
@Test
public void shouldSearchResources3() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
assertEquals(4,
new ResourceSearch().types().where(param(BAG_ID, PARAM_STRING_ID, contains("rol"))).search(tx)
.toList().size());
assertEquals(4,
new ResourceSearch().types().where(param(BAG_ID, PARAM_STRING_ID, startsWithIgnoreCase("STR")))
.search(tx).toList().size());
assertEquals(4, new ResourceSearch()
.types()
.where(param(BAG_ID, PARAM_STRING_ID, contains("rol")))
.search(tx)
.toList()
.size());
assertEquals(4, new ResourceSearch()
.types()
.where(param(BAG_ID, PARAM_STRING_ID, startsWithIgnoreCase("STR")))
.search(tx)
.toList()
.size());
}
}
@Test
public void shouldSearchResources4() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
assertEquals(8, new ResourceSearch().types().search(tx).toList().size());
}
@ -191,7 +213,7 @@ public class StrolchSearchTest {
@Test
public void shouldSearchResources5() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
assertEquals(2, new ResourceSearch().types("sdf", "Ball").search(tx).toList().size());
assertEquals(2, new ResourceSearch().types("Ball", "sdf").search(tx).toList().size());
@ -202,7 +224,7 @@ public class StrolchSearchTest {
@Test
public void shouldSearchResources6() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
assertEquals(1, new ResourceSearch().types("TestType") //
.where(relationName(tx, "other").isEqualTo("Yellow")) //
@ -220,19 +242,22 @@ public class StrolchSearchTest {
@Test
public void shouldSearchOrders() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
List<Order> result = new OrderSearch() {
@Override
public void define() {
DateRange dateRange = new DateRange()
.from(ISO8601FormatFactory.getInstance().parseDate("2012-01-01T00:00:00.000+01:00"), true)
.to(ISO8601FormatFactory.getInstance().parseDate("2013-01-01T00:00:00.000+01:00"), true);
.from(ISO8601.parseToZdt("2012-01-01T00:00:00.000+01:00"), true)
.to(ISO8601.parseToZdt("2013-01-01T00:00:00.000+01:00"), true);
types().where(date(isEqualTo(new Date(1384929777699L))).or(state(isEqualTo(State.CREATED))
.and(param(BAG_ID, PARAM_STRING_ID, isEqualTo("Strolch")))
.and(param(BAG_ID, PARAM_DATE_ID, inRange(dateRange)))));
types().where(date()
.isEqualTo(Instant.ofEpochMilli(1384929777699L).atZone(systemDefault()))
.or(state()
.isEqualTo(State.CREATED)
.and(param(BAG_ID, PARAM_STRING_ID).isEqualTo("Strolch"))
.and(param(BAG_ID, PARAM_DATE_ID).inRange(dateRange))));
}
}.search(tx).toList();
@ -243,12 +268,12 @@ public class StrolchSearchTest {
@Test
public void shouldSearchOrders1() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
StrolchSearch<Order> search = new OrderSearch() {
@Override
public void define() {
types("SortingType").where(state(isEqualTo(State.CREATED)));
types(SORTING_TYPE).where(state(isEqualTo(State.CREATED)));
}
};
@ -267,19 +292,52 @@ public class StrolchSearchTest {
@Test
public void shouldSearchOrders2() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
assertEquals(5, new OrderSearch().types("sdf", "SortingType").search(tx).toList().size());
assertEquals(5, new OrderSearch().types("SortingType", "sdf").search(tx).toList().size());
assertEquals(5, new OrderSearch().types("4gdf", "SortingType", "sdf").search(tx).toList().size());
assertEquals(5, new OrderSearch().types("sdf", SORTING_TYPE).search(tx).toList().size());
assertEquals(5, new OrderSearch().types(SORTING_TYPE, "sdf").search(tx).toList().size());
assertEquals(5, new OrderSearch().types("4gdf", SORTING_TYPE, "sdf").search(tx).toList().size());
assertEquals(7, new OrderSearch().types().search(tx).toList().size());
}
}
@Test
public void shouldSearchOrders3() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
ZonedDateTime dateTime = ISO8601.parseToZdt("2013-11-20T07:42:57.699+01:00");
assertEquals(0, new OrderSearch()
.types("TestType")
.where(date().isBefore(dateTime, false))
.search(tx)
.toList()
.size());
assertEquals(1, new OrderSearch()
.types("TestType")
.where(date().isBefore(dateTime, true))
.search(tx)
.toList()
.size());
assertEquals(0, new OrderSearch()
.types("TestType")
.where(date().isAfter(dateTime, false))
.search(tx)
.toList()
.size());
assertEquals(1, new OrderSearch()
.types("TestType")
.where(date().isAfter(dateTime, true))
.search(tx)
.toList()
.size());
}
}
@Test
public void shouldSearchActivities() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
Map<String, State> states = new ActivitySearch() {
@Override
@ -295,7 +353,7 @@ public class StrolchSearchTest {
@Test
public void shouldSearchActivities1() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
Map<String, State> states = new ActivitySearch()
@ -310,7 +368,7 @@ public class StrolchSearchTest {
@Test
public void shouldSearchActivities2() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
assertEquals(2, new ActivitySearch().types("sdf", "ActivityType").search(tx).toList().size());
assertEquals(2, new ActivitySearch().types("ActivityType", "sdf").search(tx).toList().size());
@ -322,20 +380,24 @@ public class StrolchSearchTest {
@Test
public void shouldSearchActivities3() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
assertEquals(1, new ActivitySearch().types("sdf", "ActivityType")
.where(element -> element.getActionsByType("Use").size() == 4).search(tx).toList().size());
assertEquals(1, new ActivitySearch()
.types("sdf", "ActivityType")
.where(element -> element.getActionsByType("Use").size() == 4)
.search(tx)
.toList()
.size());
}
}
@Test
public void shouldSearchRootElements() {
StrolchRealm realm = runtimeMock.getAgent().getContainer().getRealm(cert);
try (StrolchTransaction tx = realm.openTx(cert, ParallelTests.class, true)) {
try (StrolchTransaction tx = realm.openTx(cert, StrolchSearchTest.class, true)) {
assertEquals(9,
new RootElementSearch().types("SortingType", "Ball", "ActivityType").search(tx).toList().size());
new RootElementSearch().types(SORTING_TYPE, "Ball", "ActivityType").search(tx).toList().size());
assertEquals(17, new RootElementSearch().types().search(tx).toList().size());
assertEquals(2, new RootElementSearch().types("ActivityType").search(tx).toList().size());
}
@ -401,9 +463,9 @@ public class StrolchSearchTest {
.and(param(BAG_ID, PARAM_STRING_ID, isIn("Strolch", "sdf")))
.and(param(BAG_ID, PARAM_STRING_ID, isInIgnoreCase("strolch")))
.and(param(BAG_ID, PARAM_STRING_ID, isInIgnoreCase("strolch", "dfgdfg")))
.and(param(BAG_ID, PARAM_STRING_ID, contains(new String[] { "Str", "rol" })))
.and(param(BAG_ID, PARAM_STRING_ID, contains(new String[]{"Str", "rol"})))
.and(param(BAG_ID, PARAM_STRING_ID, containsIgnoreCase("ROL")))
.and(param(BAG_ID, PARAM_STRING_ID, containsIgnoreCase(new String[] { "STR", "ROL" })))
.and(param(BAG_ID, PARAM_STRING_ID, containsIgnoreCase(new String[]{"STR", "ROL"})))
.and(param(BAG_ID, PARAM_STRING_ID, startsWith("Str")))
.and(param(BAG_ID, PARAM_STRING_ID, startsWithIgnoreCase("str")))
.and(param(BAG_ID, PARAM_STRING_ID, endsWith("lch")))
@ -433,9 +495,9 @@ public class StrolchSearchTest {
.and(param(BAG_ID, PARAM_LIST_LONG_ID, isEqualTo(asList(7L, 12L, 17L))))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, isEqualTo(asList("Hello", "World"))))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, isEqualToIgnoreCase(asList("hello", "world"))))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, contains(new String[] { "Hel", "wor" })))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, containsIgnoreCase(new String[] { "Hel", "wor" })))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, containsIgnoreCase(new String[] { "hel" })))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, contains(new String[]{"Hel", "wor"})))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, containsIgnoreCase(new String[]{"Hel", "wor"})))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, containsIgnoreCase(new String[]{"hel"})))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, isIn(asList("Hello", "World"))))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, isIn(asList("Hello", "World", "Extra"))))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, isIn(asList("Extra", "Sauce")).not()))
@ -444,6 +506,8 @@ public class StrolchSearchTest {
.and(param(BAG_ID, PARAM_LIST_STRING_ID, listContains("World")))
.and(param(BAG_ID, PARAM_LIST_STRING_ID, listContains("World1")).not())
.and(paramOnBagType("Owner", "name").isInArray("Felix", "Jill"))
.and(paramNull(BAG_ID, "non-existant"))
//
));

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -20,7 +20,6 @@
<Properties>
<dataStoreMode>TRANSIENT</dataStoreMode>
<dataStoreFile>StrolchModel.xml</dataStoreFile>
<enableObserverUpdates>true</enableObserverUpdates>
</Properties>
</Component>
<Component>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>li.strolch</groupId>
<artifactId>strolch</artifactId>
<version>2.0.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -26,14 +26,12 @@ public class StrolchAccessDeniedException extends StrolchException {
private final Certificate certificate;
private final Restrictable restrictable;
private final I18nMessage i18n;
public StrolchAccessDeniedException(Certificate certificate, Restrictable restrictable, I18nMessage i18n,
Throwable cause) {
super(i18n.getMessage(), cause);
super(i18n, cause);
this.certificate = certificate;
this.restrictable = restrictable;
this.i18n = i18n;
}
public Certificate getCertificate() {
@ -43,8 +41,4 @@ public class StrolchAccessDeniedException extends StrolchException {
public Restrictable getRestrictable() {
return restrictable;
}
public I18nMessage getI18n() {
return this.i18n;
}
}

View File

@ -15,16 +15,17 @@
*/
package li.strolch.exception;
import java.util.Locale;
import li.strolch.utils.I18nMessage;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class StrolchException extends RuntimeException {
private I18nMessage i18n;
protected I18nMessage i18n;
public StrolchException(String message, Throwable cause) {
super(message, cause);
@ -36,6 +37,41 @@ public class StrolchException extends RuntimeException {
public StrolchException(I18nMessage i18n) {
super(i18n.getMessage(Locale.getDefault()));
this.i18n = i18n;
if (i18n.hasException())
initCause(i18n.getException());
}
public StrolchException(I18nMessage i18n, Throwable cause) {
super(i18n.getMessage(Locale.getDefault()), cause);
this.i18n = i18n;
}
public StrolchException(ResourceBundle bundle, String key) {
this(new I18nMessage(bundle, key));
}
public StrolchException(ResourceBundle bundle, String key, String prop, Object value) {
this(new I18nMessage(bundle, key).value(prop, value));
}
public StrolchException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2,
Object value2) {
this(new I18nMessage(bundle, key).value(prop1, value1).value(prop2, value2));
}
public StrolchException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2, Object value2,
String prop3, Object value3) {
this(new I18nMessage(bundle, key).value(prop1, value1).value(prop2, value2).value(prop3, value3));
}
public StrolchException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2, Object value2,
String prop3, Object value3, String prop4, Object value4) {
this(new I18nMessage(bundle, key)
.value(prop1, value1)
.value(prop2, value2)
.value(prop3, value3)
.value(prop4, value4));
}
public boolean hasI18n() {
@ -54,4 +90,9 @@ public class StrolchException extends RuntimeException {
this.i18n = i18n;
return this;
}
public StrolchException cause(Throwable cause) {
initCause(cause);
return this;
}
}

View File

@ -1,78 +1,40 @@
package li.strolch.exception;
import li.strolch.utils.I18nMessage;
import java.util.Locale;
import java.util.ResourceBundle;
import li.strolch.utils.I18nMessage;
public class StrolchUserMessageException extends StrolchException {
private I18nMessage i18n;
public StrolchUserMessageException(I18nMessage i18n) {
super(i18n.getMessage(Locale.getDefault()));
this.i18n = i18n;
if (i18n.hasException())
initCause(i18n.getException());
super(i18n);
}
public StrolchUserMessageException(I18nMessage i18n, Throwable cause) {
super(i18n.getMessage(Locale.getDefault()), cause);
this.i18n = i18n;
super(i18n, cause);
}
public StrolchUserMessageException(ResourceBundle bundle, String key) {
this(new I18nMessage(bundle, key));
super(bundle, key);
}
public StrolchUserMessageException(ResourceBundle bundle, String key, String prop, Object value) {
this(new I18nMessage(bundle, key) //
.value(prop, value));
super(bundle, key, prop, value);
}
public StrolchUserMessageException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2,
Object value2) {
this(new I18nMessage(bundle, key) //
.value(prop1, value1) //
.value(prop2, value2));
super(bundle, key, prop1, value1, prop2, value2);
}
public StrolchUserMessageException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2,
Object value2, String prop3, Object value3) {
this(new I18nMessage(bundle, key) //
.value(prop1, value1) //
.value(prop2, value2) //
.value(prop3, value3));
super(bundle, key, prop1, value1, prop2, value2, prop3, value3);
}
public StrolchUserMessageException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2,
Object value2, String prop3, Object value3, String prop4, Object value4) {
this(new I18nMessage(bundle, key) //
.value(prop1, value1) //
.value(prop2, value2) //
.value(prop3, value3) //
.value(prop4, value4));
}
public StrolchUserMessageException cause(Throwable cause) {
initCause(cause);
return this;
}
public boolean hasI18n() {
return this.i18n != null;
}
public I18nMessage getI18n() {
return this.i18n;
}
public void setI18n(I18nMessage i18n) {
this.i18n = i18n;
}
public StrolchUserMessageException i18n(I18nMessage i18n) {
this.i18n = i18n;
return this;
super(bundle, key, prop1, value1, prop2, value2, prop3, value3, prop4, value4);
}
}

View File

@ -42,10 +42,8 @@ public abstract class AbstractStrolchElement implements StrolchElement {
/**
* Default constructor
*
* @param id
* id of this {@link StrolchElement}
* @param name
* name of this {@link StrolchElement}
* @param id id of this {@link StrolchElement}
* @param name name of this {@link StrolchElement}
*/
public AbstractStrolchElement(String id, String name) {
setId(id);
@ -98,16 +96,15 @@ public abstract class AbstractStrolchElement implements StrolchElement {
* Used to build a {@link Locator} for this {@link StrolchElement}. It must be implemented by the concrete
* implemented as parents must first add their {@link Locator} information
*
* @param locatorBuilder
* the {@link LocatorBuilder} to which the {@link StrolchElement} must add its locator information
* @param locatorBuilder the {@link LocatorBuilder} to which the {@link StrolchElement} must add its locator
* information
*/
protected abstract void fillLocator(LocatorBuilder locatorBuilder);
/**
* fills the {@link StrolchElement} clone with the id, name and type
*
* @param clone
* the clone to fill
* @param clone the clone to fill
*/
protected void fillClone(AbstractStrolchElement clone) {
clone.id = this.id;
@ -139,5 +136,7 @@ public abstract class AbstractStrolchElement implements StrolchElement {
public abstract int hashCode();
@Override
public abstract String toString();
public String toString() {
return getLocator().toString();
}
}

View File

@ -22,7 +22,6 @@ import li.strolch.model.policy.PolicyDefs;
import li.strolch.model.visitor.StrolchElementVisitor;
import li.strolch.model.xml.StrolchXmlHelper;
import li.strolch.utils.dbc.DBC;
import li.strolch.utils.iso8601.ISO8601;
import java.text.MessageFormat;
import java.time.*;
@ -84,6 +83,22 @@ public class Order extends AbstractStrolchRootElement implements StrolchRootElem
setDate(date);
}
/**
* Extended Constructor for date and {@link State}
*
* @param id the id
* @param name the name
* @param type the type
* @param date the date
* @param state the state
*/
public Order(String id, String name, String type, ZonedDateTime date, State state) {
super(id, name, type);
setState(state);
setDate(date);
}
@Override
public void setId(String id) {
this.locator = null;
@ -315,9 +330,9 @@ public class Order extends AbstractStrolchRootElement implements StrolchRootElem
@Override
public String toString() {
return "Order [id=" + this.id + ", name=" + this.name + ", type=" + this.type + ", state=" + this.state +
", date=" + ISO8601.toString(this.date) + ", version=" + this.version + "]";
if (this.version == null)
return getLocator().toString();
return getLocator() + ", Version: " + this.version.getVersion();
}
@Override

View File

@ -191,7 +191,9 @@ public class Resource extends AbstractStrolchRootElement implements StrolchRootE
if (this.timedStateMap == null || this.timedStateMap.isEmpty())
return Stream.empty();
return this.timedStateMap.values().stream()
return this.timedStateMap
.values()
.stream()
.filter(s -> s.getInterpretation().equals(interpretation) && s.getUom().equals(uom));
}
@ -399,8 +401,9 @@ public class Resource extends AbstractStrolchRootElement implements StrolchRootE
@Override
public String toString() {
return "Resource [id=" + this.id + ", name=" + this.name + ", type=" + this.type + ", version=" + this.version;
if (this.version == null)
return getLocator().toString();
return getLocator() + ", Version: " + this.version.getVersion();
}
@Override

View File

@ -213,10 +213,10 @@ public enum State {
}
/**
* @return true if {@link #PLANNED} or {@link #EXECUTION} or {@link #WARNING} or {@link #ERROR}
* @return true if {@link #PLANNED} or {@link #EXECUTION} or {@link #WARNING} or {@link #ERROR} or {@link #STOPPED}
*/
public boolean canSetToError() {
return this == PLANNED || this == EXECUTION || this == WARNING || this == ERROR;
return this == PLANNED || this == EXECUTION || this == WARNING || this == ERROR || this == STOPPED;
}
/**
@ -282,8 +282,8 @@ public enum State {
// execution
if (states.contains(EXECUTABLE) || states.contains(EXECUTION))
return EXECUTION;
if (states.contains(EXECUTED) && (states.contains(CREATED) || states.contains(PLANNING) || states.contains(
PLANNED)))
if (states.contains(EXECUTED) &&
(states.contains(CREATED) || states.contains(PLANNING) || states.contains(PLANNED)))
return EXECUTION;
// executed

View File

@ -72,6 +72,7 @@ public class StrolchModelConstants {
public static final String BAG_RELATIONS = "relations";
public static final String BAG_PARAMETERS = "parameters";
public static final String BAG_VISIBILITY = "visibility";
public static final String TYPE_PARAMETERS = "Parameters";
public static final String TYPE_VERSION = "Version";
public static final String TYPE_MEMORY = "Memory";
@ -82,6 +83,10 @@ public class StrolchModelConstants {
public static final String TYPE_CONFIGURATION = "Configuration";
public static final String TYPE_OBJECTIVES = "Objectives";
public static final String TYPE_METRIC = "Metric";
public static final String TYPE_NOTIFICATION = "Notification";
public static final String TYPE_VISIBILITY = "Visibility";
public static final String TYPE_TEXT = "Text";
public static final String TYPE_LOCATION = "Location";
public static final String RES_CONFIGURATION = "configuration";
@ -99,6 +104,17 @@ public class StrolchModelConstants {
public static final String PARAM_START_DATE = "startDate";
public static final String PARAM_MODE = "mode";
public static final String PARAM_GROUP = "group";
public static final String PARAM_ENABLED = "enabled";
public static final String PARAM_VISIBLE_FROM = "visibleFrom";
public static final String PARAM_VISIBLE_TO = "visibleTo";
public static final String PARAM_TITLE = "title";
public static final String PARAM_TEXT = "text";
public static final String PARAM_FOR_ALL = "forAll";
public static final String PARAM_ROLES = "roles";
public static final String PARAM_LOCATIONS = "locations";
public static final String PARAM_LOCATION_NAMES = "locationNames";
public static final String PARAM_LANGUAGES = "languages";
public static final String PARAM_GROUPS = "groups";
public static class PolicyConstants {
public static final String POLICY_DEFAULT = "Default";

View File

@ -16,15 +16,6 @@
package li.strolch.model.activity;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import static li.strolch.model.StrolchModelConstants.BAG_RELATIONS;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.BAG_OBJECTIVES;
import static li.strolch.utils.helper.StringHelper.isNotEmpty;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
import java.text.MessageFormat;
import java.util.*;
import li.strolch.exception.StrolchModelException;
import li.strolch.exception.StrolchPolicyException;
import li.strolch.model.*;
@ -37,6 +28,15 @@ import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.visitor.StrolchElementVisitor;
import li.strolch.utils.dbc.DBC;
import java.text.MessageFormat;
import java.util.*;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import static li.strolch.model.StrolchModelConstants.BAG_RELATIONS;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.BAG_OBJECTIVES;
import static li.strolch.utils.helper.StringHelper.isNotEmpty;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
/**
* An {@link Action} represents a single step within an {@link Activity}, that is, one that is not further decomposed
* within the {@link Activity}. A {@link Activity} applies {@link IValueChange} objects at the start and end time of the
@ -107,8 +107,7 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
}
/**
* @param resourceId
* the id of the {@link Resource} the {@link Action} acts on
* @param resourceId the id of the {@link Resource} the {@link Action} acts on
*/
public void setResourceId(String resourceId) {
assertNotReadonly();
@ -124,8 +123,7 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
}
/**
* @param state
* the target {@code State} of the a {@code Action}
* @param state the target {@code State} of the a {@code Action}
*/
public void setState(State state) {
assertNotReadonly();
@ -140,8 +138,7 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
}
/**
* @param resourceType
* the resource type
* @param resourceType the resource type
*/
public void setResourceType(String resourceType) {
assertNotReadonly();
@ -151,8 +148,7 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
/**
* Sets the resource type and id from the given {@link Resource}
*
* @param resource
* the resource from which to get the type and id
* @param resource the resource from which to get the type and id
*/
public void setResource(Resource resource) {
assertNotReadonly();
@ -182,8 +178,7 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
*
* @return the {@link Locator} for the {@link Resource} for this action
*
* @throws IllegalStateException
* if the resource is not defined
* @throws IllegalStateException if the resource is not defined
*/
public Locator getResourceLocator() {
if (!isResourceDefined())
@ -201,8 +196,7 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
}
/**
* @param change
* {@code IValueChange} to be applied to the {@code Resource}
* @param change {@code IValueChange} to be applied to the {@code Resource}
*
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
@ -383,14 +377,14 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
@Override
public String toString() {
return "Action [id=" + this.id + ", name=" + this.name + ", type=" + this.type + ", resourceId="
+ this.resourceId + ", state=" + this.state + "]";
return getLocator() + ", resourceId: " + this.resourceId + ", state=" + this.state;
}
@Override
public void setParent(Activity activity) {
assertNotReadonly();
this.parent = activity;
this.locator = null;
}
@Override

View File

@ -495,7 +495,8 @@ public class Activity extends AbstractStrolchRootElement
public <T extends IActivityElement> T findElement(Predicate<IActivityElement> predicate,
Supplier<String> msgSupplier) {
@SuppressWarnings("unchecked") T t = (T) streamElements().filter(predicate)
@SuppressWarnings("unchecked") T t = (T) streamElements()
.filter(predicate)
.collect(singletonCollector(msgSupplier));
return t;
}
@ -740,6 +741,8 @@ public class Activity extends AbstractStrolchRootElement
@Override
public Activity ensureModifiable() {
if (!this.isRootElement())
throw new IllegalStateException("Only call this method on the root element!");
if (isReadOnly())
return getClone(true);
return this;
@ -776,23 +779,17 @@ public class Activity extends AbstractStrolchRootElement
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("Activity [id=");
builder.append(this.id);
builder.append(", name=");
builder.append(this.name);
builder.append(", type=");
builder.append(this.type);
builder.append(getLocator());
builder.append(", state=");
builder.append(getState());
builder.append(", start=");
builder.append(getStart());
builder.append(", end=");
builder.append(getEnd());
if (isRootElement()) {
if (isRootElement() && this.version != null) {
builder.append(", version=");
builder.append(this.version);
builder.append(this.version.getVersion());
}
builder.append("]");
return builder.toString();
}
@ -890,6 +887,7 @@ public class Activity extends AbstractStrolchRootElement
public void setParent(Activity activity) {
assertNotReadonly();
this.parent = activity;
this.locator = null;
}
/**

View File

@ -4,6 +4,8 @@ import li.strolch.model.PolicyContainer;
import li.strolch.model.activity.Action;
import li.strolch.utils.dbc.DBC;
import static li.strolch.model.builder.BuilderHelper.buildParamName;
public class ActionBuilder extends PolicyContainerBuilder<ActionBuilder> implements ActivityElementBuilder {
private final ActivityBuilder builder;
@ -11,11 +13,19 @@ public class ActionBuilder extends PolicyContainerBuilder<ActionBuilder> impleme
private String resourceId;
private String resourceType;
public ActionBuilder(String id, String type) {
this(id, buildParamName(id), type);
}
public ActionBuilder(String id, String name, String type) {
super(id, name, type);
this.builder = null;
}
public ActionBuilder(ActivityBuilder builder, String id, String type) {
this(builder, id, buildParamName(id), type);
}
public ActionBuilder(ActivityBuilder builder, String id, String name, String type) {
super(id, name, type);
this.builder = builder;

View File

@ -7,6 +7,8 @@ import li.strolch.model.activity.Activity;
import li.strolch.model.activity.TimeOrdering;
import li.strolch.utils.dbc.DBC;
import static li.strolch.model.builder.BuilderHelper.*;
public class ActivityBuilder extends RootElementBuilder<ActivityBuilder> implements ActivityElementBuilder {
private final StrolchElementBuilder builder;
@ -15,6 +17,10 @@ public class ActivityBuilder extends RootElementBuilder<ActivityBuilder> impleme
private final List<ActivityElementBuilder> builders;
public ActivityBuilder(String id, String type, TimeOrdering timeOrdering) {
this(id, buildParamName(id), type, timeOrdering);
}
public ActivityBuilder(String id, String name, String type, TimeOrdering timeOrdering) {
super(id, name, type);
this.builder = null;
@ -23,6 +29,10 @@ public class ActivityBuilder extends RootElementBuilder<ActivityBuilder> impleme
this.builders = new ArrayList<>();
}
public ActivityBuilder(StrolchElementBuilder builder, String id, String type, TimeOrdering timeOrdering) {
this(builder, id, buildParamName(id), type, timeOrdering);
}
public ActivityBuilder(StrolchElementBuilder builder, String id, String name, String type,
TimeOrdering timeOrdering) {
super(id, name, type);
@ -32,6 +42,11 @@ public class ActivityBuilder extends RootElementBuilder<ActivityBuilder> impleme
this.builders = new ArrayList<>();
}
public ActivityBuilder(StrolchElementBuilder builder, ActivityBuilder parentBuilder, String id, String type,
TimeOrdering timeOrdering) {
this(builder, parentBuilder, id, buildParamName(id), type, timeOrdering);
}
public ActivityBuilder(StrolchElementBuilder builder, ActivityBuilder parentBuilder, String id, String name,
String type, TimeOrdering timeOrdering) {
super(id, name, type);
@ -41,12 +56,20 @@ public class ActivityBuilder extends RootElementBuilder<ActivityBuilder> impleme
this.builders = new ArrayList<>();
}
public ActivityBuilder subActivity(String id, String type, TimeOrdering timeOrdering) {
return subActivity(id, buildParamName(id), type, timeOrdering);
}
public ActivityBuilder subActivity(String id, String name, String type, TimeOrdering timeOrdering) {
ActivityBuilder builder = new ActivityBuilder(this.builder, this, id, name, type, timeOrdering);
this.builders.add(builder);
return builder;
}
public ActionBuilder action(String id, String type) {
return action(id, buildParamName(id), type);
}
public ActionBuilder action(String id, String name, String type) {
ActionBuilder builder = new ActionBuilder(this, id, name, type);
this.builders.add(builder);

View File

@ -7,6 +7,8 @@ import li.strolch.model.ParameterBag;
import li.strolch.model.ParameterBagContainer;
import li.strolch.model.builder.params.*;
import static li.strolch.model.builder.BuilderHelper.buildParamName;
public class BagBuilder<T extends ParameterBagContainerBuilder<T>> {
private final T builder;
@ -15,6 +17,10 @@ public class BagBuilder<T extends ParameterBagContainerBuilder<T>> {
private final String type;
private final List<ParameterBuilder<?, ?, ?>> parameters;
public BagBuilder(T builder, String id, String type) {
this(builder, id, buildParamName(id), type);
}
public BagBuilder(T builder, String id, String name, String type) {
this.builder = builder;
this.id = id;
@ -23,72 +29,120 @@ public class BagBuilder<T extends ParameterBagContainerBuilder<T>> {
this.parameters = new ArrayList<>();
}
public StringParamBuilder<T> string(String id) {
return string(id, buildParamName(id));
}
public StringParamBuilder<T> string(String id, String name) {
StringParamBuilder<T> builder = new StringParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public TextParamBuilder<T> text(String id) {
return text(id, buildParamName(id));
}
public TextParamBuilder<T> text(String id, String name) {
TextParamBuilder<T> builder = new TextParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public BooleanParamBuilder<T> booleanB(String id) {
return booleanB(id, buildParamName(id));
}
public BooleanParamBuilder<T> booleanB(String id, String name) {
BooleanParamBuilder<T> builder = new BooleanParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public IntegerParamBuilder<T> integer(String id) {
return integer(id, buildParamName(id));
}
public IntegerParamBuilder<T> integer(String id, String name) {
IntegerParamBuilder<T> builder = new IntegerParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public LongParamBuilder<T> longB(String id) {
return longB(id, buildParamName(id));
}
public LongParamBuilder<T> longB(String id, String name) {
LongParamBuilder<T> builder = new LongParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public FloatParamBuilder<T> floatB(String id) {
return floatB(id, buildParamName(id));
}
public FloatParamBuilder<T> floatB(String id, String name) {
FloatParamBuilder<T> builder = new FloatParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public DateParamBuilder<T> date(String id) {
return date(id, buildParamName(id));
}
public DateParamBuilder<T> date(String id, String name) {
DateParamBuilder<T> builder = new DateParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public DurationParamBuilder<T> duration(String id) {
return duration(id, buildParamName(id));
}
public DurationParamBuilder<T> duration(String id, String name) {
DurationParamBuilder<T> builder = new DurationParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public StringListParamBuilder<T> stringList(String id) {
return stringList(id, buildParamName(id));
}
public StringListParamBuilder<T> stringList(String id, String name) {
StringListParamBuilder<T> builder = new StringListParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public IntegerListParamBuilder<T> integerList(String id) {
return integerList(id, buildParamName(id));
}
public IntegerListParamBuilder<T> integerList(String id, String name) {
IntegerListParamBuilder<T> builder = new IntegerListParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public LongListParamBuilder<T> longList(String id) {
return longList(id, buildParamName(id));
}
public LongListParamBuilder<T> longList(String id, String name) {
LongListParamBuilder<T> builder = new LongListParamBuilder<>(this, id, name);
this.parameters.add(builder);
return builder;
}
public FloatListParamBuilder<T> floatList(String id) {
return floatList(id, buildParamName(id));
}
public FloatListParamBuilder<T> floatList(String id, String name) {
FloatListParamBuilder<T> builder = new FloatListParamBuilder<>(this, id, name);
this.parameters.add(builder);

View File

@ -5,15 +5,25 @@ import li.strolch.model.State;
import li.strolch.utils.dbc.DBC;
import li.strolch.utils.iso8601.ISO8601;
import static li.strolch.model.builder.BuilderHelper.*;
public class OrderBuilder extends RootElementBuilder<OrderBuilder> {
private final StrolchElementBuilder builder;
public OrderBuilder(String id, String type) {
this(id, buildParamName(id), type);
}
public OrderBuilder(String id, String name, String type) {
super(id, name, type);
this.builder = null;
}
public OrderBuilder(StrolchElementBuilder builder, String id, String type) {
this(builder, id, buildParamName(id), type);
}
public OrderBuilder(StrolchElementBuilder builder, String id, String name, String type) {
super(id, name, type);
this.builder = builder;

View File

@ -1,19 +1,20 @@
package li.strolch.model.builder;
import static java.util.Collections.emptyList;
import static li.strolch.model.StrolchModelConstants.*;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.BAG_OBJECTIVES;
import static li.strolch.model.builder.BuilderHelper.buildParamId;
import java.util.HashMap;
import java.util.Map;
import li.strolch.model.ParameterBag;
import li.strolch.model.ParameterBagContainer;
import li.strolch.model.Tags;
import li.strolch.model.parameter.StringListParameter;
import li.strolch.model.parameter.StringParameter;
import java.util.HashMap;
import java.util.Map;
import static java.util.Collections.emptyList;
import static li.strolch.model.StrolchModelConstants.*;
import static li.strolch.model.StrolchModelConstants.PolicyConstants.BAG_OBJECTIVES;
import static li.strolch.model.builder.BuilderHelper.buildParamId;
import static li.strolch.model.builder.BuilderHelper.buildParamName;
public abstract class ParameterBagContainerBuilder<T extends ParameterBagContainerBuilder<T>> {
private final String id;
@ -24,6 +25,10 @@ public abstract class ParameterBagContainerBuilder<T extends ParameterBagContain
private final Map<String, String[]> singleRelations;
private final Map<String, String[]> multiRelations;
public ParameterBagContainerBuilder(String id, String type) {
this(id, buildParamName(id), type);
}
public ParameterBagContainerBuilder(String id, String name, String type) {
this.id = id;
this.name = name;
@ -58,9 +63,12 @@ public abstract class ParameterBagContainerBuilder<T extends ParameterBagContain
return bag(BAG_RELATIONS, TYPE_RELATIONS, TYPE_RELATIONS);
}
public BagBuilder<T> bag(String id, String type) {
return bag(id, buildParamName(id), type);
}
public BagBuilder<T> bag(String id, String name, String type) {
@SuppressWarnings("unchecked")
BagBuilder<T> bagBuilder = new BagBuilder<>((T) this, id, name, type);
@SuppressWarnings("unchecked") BagBuilder<T> bagBuilder = new BagBuilder<>((T) this, id, name, type);
if (this.parametersBags.put(id, bagBuilder) != null)
throw new IllegalArgumentException("Bag builder for " + id + " already exists!");
return bagBuilder;
@ -70,11 +78,14 @@ public abstract class ParameterBagContainerBuilder<T extends ParameterBagContain
return resourceRelation(buildParamId(type), type, type);
}
public T resourceRelation(String paramId, String type) {
return resourceRelation(paramId, buildParamName(paramId), type);
}
public T resourceRelation(String paramId, String paramName, String type) {
assertNotMapped(paramId);
this.singleRelations.put(paramId, new String[] { paramName, type, Tags.RESOURCE });
@SuppressWarnings("unchecked")
T t = (T) this;
this.singleRelations.put(paramId, new String[]{paramName, type, Tags.RESOURCE});
@SuppressWarnings("unchecked") T t = (T) this;
return t;
}
@ -82,11 +93,14 @@ public abstract class ParameterBagContainerBuilder<T extends ParameterBagContain
return resourceRelations(buildParamId(type), type + "s", type);
}
public T resourceRelations(String paramId, String type) {
return resourceRelations(paramId, buildParamName(paramId), type);
}
public T resourceRelations(String paramId, String paramName, String type) {
assertNotMapped(paramId);
this.multiRelations.put(paramId, new String[] { paramName, type, Tags.RESOURCE });
@SuppressWarnings("unchecked")
T t = (T) this;
this.multiRelations.put(paramId, new String[]{paramName, type, Tags.RESOURCE});
@SuppressWarnings("unchecked") T t = (T) this;
return t;
}
@ -94,11 +108,14 @@ public abstract class ParameterBagContainerBuilder<T extends ParameterBagContain
return orderRelation(buildParamId(type), type, type);
}
public T orderRelation(String paramId, String type) {
return orderRelation(paramId, buildParamName(paramId), type);
}
public T orderRelation(String paramId, String paramName, String type) {
assertNotMapped(paramId);
this.singleRelations.put(paramId, new String[] { paramName, type, Tags.ORDER });
@SuppressWarnings("unchecked")
T t = (T) this;
this.singleRelations.put(paramId, new String[]{paramName, type, Tags.ORDER});
@SuppressWarnings("unchecked") T t = (T) this;
return t;
}
@ -106,11 +123,14 @@ public abstract class ParameterBagContainerBuilder<T extends ParameterBagContain
return orderRelations(buildParamId(type), type + "s", type);
}
public T orderRelations(String paramId, String type) {
return orderRelations(paramId, buildParamName(paramId), type);
}
public T orderRelations(String paramId, String paramName, String type) {
assertNotMapped(paramId);
this.multiRelations.put(paramId, new String[] { paramName, type, Tags.ORDER });
@SuppressWarnings("unchecked")
T t = (T) this;
this.multiRelations.put(paramId, new String[]{paramName, type, Tags.ORDER});
@SuppressWarnings("unchecked") T t = (T) this;
return t;
}
@ -118,11 +138,14 @@ public abstract class ParameterBagContainerBuilder<T extends ParameterBagContain
return activityRelation(buildParamId(type), type, type);
}
public T activityRelation(String paramId, String type) {
return activityRelation(paramId, buildParamName(paramId), type);
}
public T activityRelation(String paramId, String paramName, String type) {
assertNotMapped(paramId);
this.singleRelations.put(paramId, new String[] { paramName, type, Tags.ACTIVITY });
@SuppressWarnings("unchecked")
T t = (T) this;
this.singleRelations.put(paramId, new String[]{paramName, type, Tags.ACTIVITY});
@SuppressWarnings("unchecked") T t = (T) this;
return t;
}
@ -130,11 +153,14 @@ public abstract class ParameterBagContainerBuilder<T extends ParameterBagContain
return activityRelations(buildParamId(type), type + "s", type);
}
public T activityRelations(String paramId, String type) {
return activityRelations(paramId, buildParamName(paramId), type);
}
public T activityRelations(String paramId, String paramName, String type) {
assertNotMapped(paramId);
this.multiRelations.put(paramId, new String[] { paramName, type, Tags.ACTIVITY });
@SuppressWarnings("unchecked")
T t = (T) this;
this.multiRelations.put(paramId, new String[]{paramName, type, Tags.ACTIVITY});
@SuppressWarnings("unchecked") T t = (T) this;
return t;
}

View File

@ -3,18 +3,23 @@ package li.strolch.model.builder;
import li.strolch.model.ParameterBagContainer;
import li.strolch.model.PolicyContainer;
import static li.strolch.model.builder.BuilderHelper.buildParamName;
public class PolicyContainerBuilder<T extends ParameterBagContainerBuilder<T>> extends ParameterBagContainerBuilder<T> {
private PoliciesBuilder<T> policies;
public PolicyContainerBuilder(String id, String type) {
super(id, buildParamName(id), type);
}
public PolicyContainerBuilder(String id, String name, String type) {
super(id, name, type);
}
public PoliciesBuilder<T> policies() {
if (this.policies == null) {
@SuppressWarnings("unchecked")
T t = (T) this;
@SuppressWarnings("unchecked") T t = (T) this;
this.policies = new PoliciesBuilder<>(t);
}
return policies;

View File

@ -1,65 +1,104 @@
package li.strolch.model.builder;
import java.util.ArrayList;
import java.util.List;
import li.strolch.model.Resource;
import li.strolch.model.builder.states.*;
import li.strolch.utils.dbc.DBC;
import java.util.ArrayList;
import java.util.List;
import static li.strolch.model.builder.BuilderHelper.buildParamName;
import static li.strolch.utils.helper.StringHelper.getUniqueId;
public class ResourceBuilder extends RootElementBuilder<ResourceBuilder> {
private final StrolchElementBuilder builder;
private final List<TimedStateBuilder<?>> timedStates;
public ResourceBuilder(String name, String type) {
this(getUniqueId(), name, type);
}
public ResourceBuilder(String id, String name, String type) {
super(id, name, type);
this.builder = null;
this.timedStates = new ArrayList<>();
}
public ResourceBuilder(StrolchElementBuilder builder, String name, String type) {
this(builder, getUniqueId(), name, type);
}
public ResourceBuilder(StrolchElementBuilder builder, String id, String name, String type) {
super(id, name, type);
this.builder = builder;
this.timedStates = new ArrayList<>();
}
public BooleanStateBuilder booleanState(String id) {
return booleanState(id, buildParamName(id));
}
public BooleanStateBuilder booleanState(String id, String name) {
BooleanStateBuilder builder = new BooleanStateBuilder(this, id, name);
this.timedStates.add(builder);
return builder;
}
public FloatStateBuilder floatState(String id) {
return floatState(id, buildParamName(id));
}
public FloatStateBuilder floatState(String id, String name) {
FloatStateBuilder builder = new FloatStateBuilder(this, id, name);
this.timedStates.add(builder);
return builder;
}
public IntegerStateBuilder integerState(String id) {
return integerState(id, buildParamName(id));
}
public IntegerStateBuilder integerState(String id, String name) {
IntegerStateBuilder builder = new IntegerStateBuilder(this, id, name);
this.timedStates.add(builder);
return builder;
}
public LongStateBuilder longState(String id) {
return longState(id, buildParamName(id));
}
public LongStateBuilder longState(String id, String name) {
LongStateBuilder builder = new LongStateBuilder(this, id, name);
this.timedStates.add(builder);
return builder;
}
public FloatListStateBuilder floatListState(String id) {
return floatListState(id, buildParamName(id));
}
public FloatListStateBuilder floatListState(String id, String name) {
FloatListStateBuilder builder = new FloatListStateBuilder(this, id, name);
this.timedStates.add(builder);
return builder;
}
public IntegerListStateBuilder integerListState(String id) {
return integerListState(id, buildParamName(id));
}
public IntegerListStateBuilder integerListState(String id, String name) {
IntegerListStateBuilder builder = new IntegerListStateBuilder(this, id, name);
this.timedStates.add(builder);
return builder;
}
public StringSetStateBuilder stringSetState(String id) {
return stringSetState(id, buildParamName(id));
}
public StringSetStateBuilder stringSetState(String id, String name) {
StringSetStateBuilder builder = new StringSetStateBuilder(this, id, name);
this.timedStates.add(builder);

View File

@ -1,10 +1,15 @@
package li.strolch.model.builder;
import li.strolch.model.PolicyContainer;
import li.strolch.model.StrolchRootElement;
import static li.strolch.model.builder.BuilderHelper.buildParamName;
public abstract class RootElementBuilder<T extends ParameterBagContainerBuilder<T>> extends PolicyContainerBuilder<T> {
public RootElementBuilder(String id, String type) {
super(id, buildParamName(id), type);
}
public RootElementBuilder(String id, String name, String type) {
super(id, name, type);
}

View File

@ -27,19 +27,19 @@ public class StrolchElementBuilder {
this.activityBuilders = new HashMap<>();
}
public ResourceBuilder resource(String name, String type) {
public ResourceBuilder resourceTemplate(String name, String type) {
ResourceBuilder builder = new ResourceBuilder(this, type, name, TEMPLATE);
this.resourceBuilders.put(type, builder);
return builder;
}
public OrderBuilder order(String name, String type) {
public OrderBuilder orderTemplate(String name, String type) {
OrderBuilder builder = new OrderBuilder(this, type, name, TEMPLATE);
this.orderBuilders.put(type, builder);
return builder;
}
public ActivityBuilder activity(String name, String type, TimeOrdering timeOrdering) {
public ActivityBuilder activityTemplate(String name, String type, TimeOrdering timeOrdering) {
ActivityBuilder builder = new ActivityBuilder(this, type, name, TEMPLATE, timeOrdering);
this.activityBuilders.put(type, builder);
return builder;
@ -62,7 +62,7 @@ public class StrolchElementBuilder {
public List<StrolchRootElement> buildTemplates() {
return concat(concat(this.resourceBuilders.values().stream(), //
this.orderBuilders.values().stream()), //
this.orderBuilders.values().stream()), //
this.activityBuilders.values().stream()) //
.map(RootElementBuilder::build).collect(toList());
}
@ -71,24 +71,24 @@ public class StrolchElementBuilder {
ResourceBuilder builder = this.resourceBuilders.get(type);
if (builder == null)
throw new IllegalArgumentException("No resource template defined for type " + type);
return updateFields(type, newName, builder.build());
return setInitialFields(type, newName, builder.build());
}
public Order newOrder(String type, String newName) {
OrderBuilder builder = this.orderBuilders.get(type);
if (builder == null)
throw new IllegalArgumentException("No resource template defined for type " + type);
return updateFields(type, newName, builder.build());
return setInitialFields(type, newName, builder.build());
}
public Activity newActivity(String type, String newName) {
ActivityBuilder builder = this.activityBuilders.get(type);
if (builder == null)
throw new IllegalArgumentException("No resource template defined for type " + type);
return updateFields(type, newName, builder.build());
return setInitialFields(type, newName, builder.build());
}
private <T extends StrolchRootElement> T updateFields(String type, String newName, T element) {
private <T extends StrolchRootElement> T setInitialFields(String type, String newName, T element) {
element.setId(StringHelper.getUniqueId());
element.setName(newName);
element.setType(type);

View File

@ -1,7 +1,5 @@
package li.strolch.model.json;
import java.util.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@ -11,6 +9,8 @@ import li.strolch.privilege.model.RoleRep;
import li.strolch.privilege.model.UserRep;
import li.strolch.privilege.model.UserState;
import java.util.*;
public class PrivilegeElementFromJsonVisitor {
public UserRep userRepFromJson(String string) {
@ -32,11 +32,12 @@ public class PrivilegeElementFromJsonVisitor {
String name = nameE == null ? null : nameE.getAsString().trim();
List<PrivilegeRep> privileges = new ArrayList<>();
Map<String, PrivilegeRep> privileges = new HashMap<>();
if (privilegesE != null) {
JsonArray privilegesArr = privilegesE.getAsJsonArray();
for (JsonElement privilegeE : privilegesArr) {
privileges.add(privilegeRepFromJson(privilegeE.getAsJsonObject()));
PrivilegeRep privilegeRep = privilegeRepFromJson(privilegeE.getAsJsonObject());
privileges.put(privilegeRep.getName(), privilegeRep);
}
}
@ -82,6 +83,7 @@ public class PrivilegeElementFromJsonVisitor {
JsonElement lastNameE = jsonObject.get("lastname");
JsonElement userStateE = jsonObject.get("userState");
JsonElement localeE = jsonObject.get("locale");
JsonElement groupsE = jsonObject.get("groups");
JsonElement rolesE = jsonObject.get("roles");
JsonElement propertiesE = jsonObject.get("properties");
@ -90,16 +92,11 @@ public class PrivilegeElementFromJsonVisitor {
String firstname = firstNameE == null ? null : firstNameE.getAsString().trim();
String lastname = lastNameE == null ? null : lastNameE.getAsString().trim();
UserState userState = userStateE == null ? null : UserState.valueOf(userStateE.getAsString().trim());
Locale locale = localeE == null ? null : new Locale(localeE.getAsString().trim());
Locale locale = localeE == null ? null : Locale.forLanguageTag(localeE.getAsString().trim());
Set<String> roles = null;
if (rolesE != null) {
roles = new HashSet<>();
JsonArray rolesArr = rolesE.getAsJsonArray();
for (JsonElement role : rolesArr) {
roles.add(role.getAsString().trim());
}
}
Set<String> groups = jsonArrayToSet(groupsE);
Set<String> roles = jsonArrayToSet(rolesE);
Map<String, String> properties = null;
if (propertiesE != null) {
@ -111,6 +108,19 @@ public class PrivilegeElementFromJsonVisitor {
}
}
return new UserRep(userId, username, firstname, lastname, userState, roles, locale, properties, null);
return new UserRep(userId, username, firstname, lastname, userState, groups, roles, locale, properties, null);
}
private Set<String> jsonArrayToSet(JsonElement array) {
if (array == null)
return Set.of();
Set<String> result = new HashSet<>();
JsonArray rolesArr = array.getAsJsonArray();
for (JsonElement role : rolesArr) {
result.add(role.getAsString().trim());
}
return result;
}
}

View File

@ -53,7 +53,7 @@ public class PrivilegeElementToJsonVisitor implements PrivilegeElementVisitor<Js
jsonObject.addProperty("name", roleRep.getName());
JsonArray privilegesJ = new JsonArray();
roleRep.getPrivileges().forEach(p -> privilegesJ.add(p.accept(this)));
roleRep.getPrivileges().values().forEach(p -> privilegesJ.add(p.accept(this)));
jsonObject.add("privileges", privilegesJ);
return jsonObject;

View File

@ -1,11 +1,14 @@
package li.strolch.model.xml;
import static java.nio.charset.StandardCharsets.UTF_8;
import static li.strolch.model.StrolchModelConstants.DEFAULT_ENCODING;
import static li.strolch.model.StrolchModelConstants.DEFAULT_XML_VERSION;
import javanet.staxutils.IndentingXMLStreamWriter;
import li.strolch.model.Order;
import li.strolch.model.Resource;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.Tags;
import li.strolch.model.activity.Activity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
@ -19,14 +22,10 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javanet.staxutils.IndentingXMLStreamWriter;
import li.strolch.model.Order;
import li.strolch.model.Resource;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.Tags;
import li.strolch.model.activity.Activity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.nio.charset.StandardCharsets.UTF_8;
import static li.strolch.model.StrolchModelConstants.DEFAULT_ENCODING;
import static li.strolch.model.StrolchModelConstants.DEFAULT_XML_VERSION;
import static li.strolch.utils.helper.XmlHelper.getSaxParser;
public class StrolchXmlHelper {
@ -69,8 +68,7 @@ public class StrolchXmlHelper {
private static SimpleStrolchElementListener parse(String xml) {
try {
SimpleStrolchElementListener elementListener = new SimpleStrolchElementListener();
SAXParser sp = SAXParserFactory.newInstance().newSAXParser();
sp.parse(new ByteArrayInputStream(xml.getBytes(UTF_8)), new XmlModelSaxReader(elementListener));
getSaxParser().parse(new ByteArrayInputStream(xml.getBytes(UTF_8)), new XmlModelSaxReader(elementListener));
return elementListener;
} catch (Exception e) {
throw new IllegalStateException("Failed to parse XML", e);

View File

@ -15,19 +15,19 @@
*/
package li.strolch.model.xml;
import static li.strolch.utils.helper.StringHelper.*;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import li.strolch.exception.StrolchException;
import li.strolch.model.Tags;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import java.io.File;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import static li.strolch.utils.helper.StringHelper.formatNanoDuration;
import static li.strolch.utils.helper.StringHelper.isEmpty;
import static li.strolch.utils.helper.XmlHelper.getSaxParser;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -61,7 +61,8 @@ public class XmlModelSaxFileReader extends XmlModelSaxReader {
File includeFile = new File(this.modelFile.getParentFile(), includeFileS);
if (!includeFile.exists() || !includeFile.canRead()) {
String msg = "The IncludeFile does not exist, or is not readable. Source model: {0} with IncludeFile: {1}";
String msg
= "The IncludeFile does not exist, or is not readable. Source model: {0} with IncludeFile: {1}";
msg = MessageFormat.format(msg, this.modelFile.getAbsolutePath(), includeFileS);
throw new IllegalArgumentException(msg);
}
@ -78,10 +79,7 @@ public class XmlModelSaxFileReader extends XmlModelSaxReader {
long startNanos = System.nanoTime();
this.statistics.startTime = LocalDateTime.now();
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
sp.parse(this.modelFile, this);
getSaxParser().parse(this.modelFile, this);
long endNanos = System.nanoTime();
this.statistics.durationNanos = endNanos - startNanos;

View File

@ -15,11 +15,14 @@
*/
package li.strolch.model.xml;
import static li.strolch.model.StrolchModelConstants.DEFAULT_ENCODING;
import li.strolch.exception.StrolchException;
import li.strolch.model.Tags;
import li.strolch.utils.helper.StringHelper;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -27,12 +30,8 @@ import java.io.UnsupportedEncodingException;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import li.strolch.exception.StrolchException;
import li.strolch.model.Tags;
import li.strolch.utils.helper.StringHelper;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import static li.strolch.model.StrolchModelConstants.DEFAULT_ENCODING;
import static li.strolch.utils.helper.XmlHelper.getSaxParser;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
@ -85,10 +84,7 @@ public class XmlModelSaxStreamReader extends XmlModelSaxReader {
long startNanos = System.nanoTime();
this.statistics.startTime = LocalDateTime.now();
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
sp.parse(this.source, this);
getSaxParser().parse(this.source, this);
long endNanos = System.nanoTime();
this.statistics.durationNanos = endNanos - startNanos;

View File

@ -33,7 +33,7 @@ public class StrolchElementBuilderTest {
*/
// person
.resource("Person Template", "Person") //
.resourceTemplate("Person Template", "Person") //
.defaultBag() //
.date("birthdate", "Birthdate").value(ZonedDateTime.now()).end() //
.string("case", "Case").interpretation("Case").uom("Simple").end() //
@ -47,7 +47,7 @@ public class StrolchElementBuilderTest {
.endResource() //
// cars
.resource("Car Template", "Car") //
.resourceTemplate("Car Template", "Car") //
.defaultBag() //
.string("color", "Color").value("white").end() //
.endBag() //
@ -56,7 +56,7 @@ public class StrolchElementBuilderTest {
.endResource() //
// machines
.resource("Machine Template", "Machine") //
.resourceTemplate("Machine Template", "Machine") //
.defaultBag() //
.string("color", "Color").end() //
.endBag() //
@ -68,7 +68,7 @@ public class StrolchElementBuilderTest {
*/
// orders
.order("Order Template", "Order") //
.orderTemplate("Order Template", "Order") //
.defaultBag() //
.string("description", "Description").end() //
.endBag() //
@ -83,7 +83,7 @@ public class StrolchElementBuilderTest {
*/
// ToStock
.activity("ToStock Template", "ToStock", TimeOrdering.SERIES) //
.activityTemplate("ToStock Template", "ToStock", TimeOrdering.SERIES) //
.defaultBag() //
.string("description", "Description").end() //
.endBag() //
@ -211,7 +211,7 @@ public class StrolchElementBuilderTest {
Resource car1 = new StrolchElementBuilder() //
.resource("Car Template", "Car") //
.resourceTemplate("Car Template", "Car") //
.defaultBag() //
.string("color", "Color").value("white").end() //
.endBag() //

View File

@ -1,19 +1,5 @@
package li.strolch.model.activity;
import static li.strolch.model.ModelGenerator.*;
import static org.junit.Assert.assertEquals;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.io.StringWriter;
import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.timevalue.impl.IntegerValue;
import li.strolch.model.timevalue.impl.ValueChange;
@ -25,6 +11,19 @@ import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.io.StringWriter;
import static li.strolch.model.ModelGenerator.*;
import static li.strolch.utils.helper.XmlHelper.getDocumentBuilder;
import static org.junit.Assert.assertEquals;
public class ActionTest {
private static final Logger logger = LoggerFactory.getLogger(ActionTest.class);
@ -76,8 +75,7 @@ public class ActionTest {
// @Test
public void showToDOM() throws ParserConfigurationException, TransformerException {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = db.newDocument();
Document document = getDocumentBuilder().newDocument();
Element dom = new StrolchElementToDomVisitor().toDom(this.action);
document.appendChild(dom);

View File

@ -15,10 +15,16 @@
*/
package li.strolch.model.activity;
import static org.junit.Assert.*;
import li.strolch.exception.StrolchException;
import li.strolch.model.ModelGenerator;
import li.strolch.model.State;
import li.strolch.model.xml.StrolchElementToDomVisitor;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
@ -31,15 +37,8 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import li.strolch.exception.StrolchException;
import li.strolch.model.ModelGenerator;
import li.strolch.model.State;
import li.strolch.model.xml.StrolchElementToDomVisitor;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import static li.strolch.utils.helper.XmlHelper.getDocumentBuilder;
import static org.junit.Assert.*;
public class ActivityTest {
@ -342,9 +341,7 @@ public class ActivityTest {
// @Test
public void showToDOM() throws ParserConfigurationException, TransformerException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
Document document = getDocumentBuilder().newDocument();
Element dom = new StrolchElementToDomVisitor().toDom(this.activity);
document.appendChild(dom);

View File

@ -5,7 +5,7 @@
<parent>
<groupId>li.strolch</groupId>
<artifactId>strolch</artifactId>
<version>2.0.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -15,15 +15,6 @@
*/
package li.strolch.persistence.postgresql;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.text.MessageFormat;
import java.util.Calendar;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import li.strolch.model.activity.Activity;
@ -35,18 +26,32 @@ import li.strolch.persistence.api.StrolchPersistenceException;
import li.strolch.persistence.api.TransactionResult;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.text.MessageFormat;
import java.util.Calendar;
import static li.strolch.utils.helper.XmlHelper.getSaxParser;
@SuppressWarnings("nls")
public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements ActivityDao {
public static final String ACTIVITIES = "activities";
private static final String insertAsXmlSqlS = "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, asxml) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?)";
private static final String insertAsJsonSqlS = "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, asjson) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?)";
private static final String insertAsXmlSqlS
= "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, asxml) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?)";
private static final String insertAsJsonSqlS
= "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, asjson) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?)";
private static final String updateAsXmlSqlS = "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, type = ?, state = ?::order_state, asxml = ? where id = ? and version = ?";
private static final String updateAsJsonSqlS = "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, type = ?, state = ?::order_state, asjson = ? where id = ? and version = ?";
private static final String updateAsXmlSqlS
= "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, state = ?::order_state, asxml = ? where type = ? and id = ? and version = ?";
private static final String updateAsJsonSqlS
= "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, state = ?::order_state, asjson = ? where type = ? and id = ? and version = ?";
private static final String updateLatestSqlS = "update {0} SET latest = false WHERE id = ? AND version = ?";
private static final String updateLatestSqlS
= "update {0} SET latest = false WHERE type = ? and id = ? AND version = ?";
public PostgreSqlActivityDao(DataType dataType, Connection connection, TransactionResult txResult,
boolean versioningEnabled) {
@ -62,14 +67,13 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
protected Activity 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));
getSaxParser().parse(binaryStream, new XmlModelSaxReader(listener));
} catch (SQLException | IOException | SAXException | ParserConfigurationException e) {
throw new StrolchPersistenceException(
MessageFormat.format("Failed to extract Activity from sqlxml value for {0} / {1}", id, type), e);
}
if (listener.getActivities().size() == 0)
if (listener.getActivities().isEmpty())
throw new StrolchPersistenceException(
MessageFormat.format("No Activity parsed from sqlxml value for {0} / {1}", id, type));
if (listener.getActivities().size() > 1)
@ -126,9 +130,9 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
}
} catch (SQLException | SAXException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to insert Activity {0} due to {1}", activity.getLocator(), e.getLocalizedMessage()),
e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to insert Activity {0} due to {1}", activity.getLocator(),
e.getLocalizedMessage()), e);
}
if (activity.getVersion().isFirstVersion()) {
@ -140,20 +144,22 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {
// primary key
preparedStatement.setString(1, activity.getId());
preparedStatement.setInt(2, activity.getVersion().getPreviousVersion());
preparedStatement.setString(1, activity.getType());
preparedStatement.setString(2, activity.getId());
preparedStatement.setInt(3, activity.getVersion().getPreviousVersion());
int modCount = preparedStatement.executeUpdate();
if (modCount != 1) {
String msg = "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
String msg
= "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
msg = MessageFormat.format(msg, activity.getId(), activity.getVersion().getPreviousVersion(), modCount);
throw new StrolchPersistenceException(msg);
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to update previous version of Activity {0} due to {1}", activity.getVersion(),
e.getLocalizedMessage()), e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to update previous version of Activity {0} due to {1}",
activity.getVersion(), e.getLocalizedMessage()), e);
}
}
@ -168,15 +174,15 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
// make sure is first version when versioning is not enabled
if (!activity.getVersion().isFirstVersion()) {
throw new StrolchPersistenceException(MessageFormat
.format("Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
activity.getVersion()));
throw new StrolchPersistenceException(MessageFormat.format(
"Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
activity.getVersion()));
}
// and also not marked as deleted!
if (activity.getVersion().isDeleted()) {
throw new StrolchPersistenceException(MessageFormat
.format("Versioning is not enabled, so version can not be marked as deleted for {0}",
throw new StrolchPersistenceException(
MessageFormat.format("Versioning is not enabled, so version can not be marked as deleted for {0}",
activity.getVersion()));
}
@ -196,12 +202,12 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
// attributes
preparedStatement.setString(6, activity.getName());
preparedStatement.setString(7, activity.getType());
preparedStatement.setString(8, activity.getState().name());
preparedStatement.setString(7, activity.getState().name());
SQLXML sqlxml = writeObject(preparedStatement, activity, 9);
SQLXML sqlxml = writeObject(preparedStatement, activity, 8);
// primary key
preparedStatement.setString(9, activity.getType());
preparedStatement.setString(10, activity.getId());
preparedStatement.setInt(11, activity.getVersion().getVersion());
@ -218,9 +224,9 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
}
} catch (SQLException | SAXException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to update Activity {0} due to {1}", activity.getLocator(), e.getLocalizedMessage()),
e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to update Activity {0} due to {1}", activity.getLocator(),
e.getLocalizedMessage()), e);
}
}
}

View File

@ -15,17 +15,6 @@
*/
package li.strolch.persistence.postgresql;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import li.strolch.model.Order;
@ -39,31 +28,54 @@ import li.strolch.utils.collections.DateRange;
import li.strolch.utils.iso8601.ISO8601;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import static li.strolch.utils.helper.XmlHelper.getSaxParser;
@SuppressWarnings("nls")
public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao {
public static final String ORDERS = "orders";
private static final String querySizeDrSqlS = "select count(*) from {0} where latest = true {1}";
private static final String querySizeOfTypeDrSqlS = "select count(*) from {0} where type = ANY(?) and latest = true {1}";
private static final String querySizeOfTypeDrSqlS
= "select count(*) from {0} where type = ANY(?) and latest = true {1}";
private static final String queryAllDrAsXmlSqlS = "select id, type, asxml from {0} where latest = true {1}";
private static final String queryAllDrAsXmlLimitSqlS = "select id, type, asxml from {0} where latest = true {1} order by date {2} limit {3} offset {4}";
private static final String queryAllDrAsXmlLimitSqlS
= "select id, type, asxml from {0} where latest = true {1} order by date {2} limit {3} offset {4}";
private static final String queryAllDrAsJsonSqlS = "select id, type, asjson from {0} where latest = true {1}";
private static final String queryAllDrAsJsonLimitSqlS = "select id, type, asjson from {0} where latest = true {1} order by date {2} limit {3} offset {4}";
private static final String queryAllDrAsJsonLimitSqlS
= "select id, type, asjson from {0} where latest = true {1} order by date {2} limit {3} offset {4}";
private static final String queryAllByTypeDrAsXmlSqlS = "select id, type, asxml from {0} where type = ANY(?) and latest = true {1}";
private static final String queryAllByTypeDrAsXmlLimitSqlS = "select id, type, asxml from {0} where type = ANY(?) and latest = true {1} order by date {2} limit {3,number,#} offset {4,number,#}";
private static final String queryAllByTypeDrAsJsonSqlS = "select id, type, asjson from {0} where type = ANY(?) and latest = true {1}";
private static final String queryAllByTypeDrAsJsonLimitSqlS = "select id, type, asjson from {0} where type = ANY(?) and latest = true {1} order by date {2} limit {3,number,#} offset {4,number,#}";
private static final String queryAllByTypeDrAsXmlSqlS
= "select id, type, asxml from {0} where type = ANY(?) and latest = true {1}";
private static final String queryAllByTypeDrAsXmlLimitSqlS
= "select id, type, asxml from {0} where type = ANY(?) and latest = true {1} order by date {2} limit {3,number,#} offset {4,number,#}";
private static final String queryAllByTypeDrAsJsonSqlS
= "select id, type, asjson from {0} where type = ANY(?) and latest = true {1}";
private static final String queryAllByTypeDrAsJsonLimitSqlS
= "select id, type, asjson from {0} where type = ANY(?) and latest = true {1} order by date {2} limit {3,number,#} offset {4,number,#}";
private static final String insertAsXmlSqlS = "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, date, asxml) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?, ?)";
private static final String insertAsJsonSqlS = "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, date, asjson) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?, ?)";
private static final String insertAsXmlSqlS
= "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, date, asxml) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?, ?)";
private static final String insertAsJsonSqlS
= "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, date, asjson) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?, ?)";
private static final String updateAsXmlSqlS = "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, type = ?, state = ?::order_state, date = ?, asxml = ? where id = ? and version = ?";
private static final String updateAsJsonSqlS = "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, type = ?, state = ?::order_state, date = ?, asjson = ? where id = ? and version = ?";
private static final String updateAsXmlSqlS
= "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, state = ?::order_state, date = ?, asxml = ? where type = ? and id = ? and version = ?";
private static final String updateAsJsonSqlS
= "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, state = ?::order_state, date = ?, asjson = ? where type = ? and id = ? and version = ?";
private static final String updateLatestSqlS = "update {0} SET latest = false WHERE id = ? AND version = ?";
private static final String updateLatestSqlS
= "update {0} SET latest = false WHERE type = ? and id = ? AND version = ?";
public PostgreSqlOrderDao(DataType dataType, Connection connection, TransactionResult txResult,
boolean versioningEnabled) {
@ -79,14 +91,13 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
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));
getSaxParser().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), e);
}
if (listener.getOrders().size() == 0)
if (listener.getOrders().isEmpty())
throw new StrolchPersistenceException(
MessageFormat.format("No Orders parsed from sqlxml value for {0} / {1}", id, type));
if (listener.getOrders().size() > 1)
@ -115,10 +126,10 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
// version
preparedStatement.setInt(2, order.getVersion().getVersion());
preparedStatement.setString(3, order.getVersion().getCreatedBy());
preparedStatement
.setTimestamp(4, new Timestamp(order.getVersion().getCreated().getTime()), Calendar.getInstance());
preparedStatement
.setTimestamp(5, new Timestamp(order.getVersion().getUpdated().getTime()), Calendar.getInstance());
preparedStatement.setTimestamp(4, new Timestamp(order.getVersion().getCreated().getTime()),
Calendar.getInstance());
preparedStatement.setTimestamp(5, new Timestamp(order.getVersion().getUpdated().getTime()),
Calendar.getInstance());
preparedStatement.setBoolean(6, order.getVersion().isDeleted());
preparedStatement.setBoolean(7, !order.getVersion().isDeleted());
@ -144,8 +155,9 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
}
} catch (SQLException | SAXException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to insert Order {0} due to {1}", order.getVersion(), e.getLocalizedMessage()), e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to insert Order {0} due to {1}", order.getVersion(),
e.getLocalizedMessage()), e);
}
if (order.getVersion().isFirstVersion()) {
@ -157,20 +169,22 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {
// primary key
preparedStatement.setString(1, order.getId());
preparedStatement.setInt(2, order.getVersion().getPreviousVersion());
preparedStatement.setString(1, order.getType());
preparedStatement.setString(2, order.getId());
preparedStatement.setInt(3, order.getVersion().getPreviousVersion());
int modCount = preparedStatement.executeUpdate();
if (modCount != 1) {
String msg = "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
String msg
= "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
msg = MessageFormat.format(msg, order.getId(), order.getVersion().getPreviousVersion(), modCount);
throw new StrolchPersistenceException(msg);
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to update previous version of Order {0} due to {1}", order.getVersion(),
e.getLocalizedMessage()), e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to update previous version of Order {0} due to {1}",
order.getVersion(), e.getLocalizedMessage()), e);
}
}
@ -185,15 +199,15 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
// make sure is first version when versioning is not enabled
if (!order.getVersion().isFirstVersion()) {
throw new StrolchPersistenceException(MessageFormat
.format("Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
order.getVersion()));
throw new StrolchPersistenceException(MessageFormat.format(
"Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
order.getVersion()));
}
// and also not marked as deleted!
if (order.getVersion().isDeleted()) {
throw new StrolchPersistenceException(MessageFormat
.format("Versioning is not enabled, so version can not be marked as deleted for {0}",
throw new StrolchPersistenceException(
MessageFormat.format("Versioning is not enabled, so version can not be marked as deleted for {0}",
order.getVersion()));
}
@ -204,30 +218,31 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
// version
preparedStatement.setString(1, order.getVersion().getCreatedBy());
preparedStatement
.setTimestamp(2, new Timestamp(order.getVersion().getCreated().getTime()), Calendar.getInstance());
preparedStatement
.setTimestamp(3, new Timestamp(order.getVersion().getUpdated().getTime()), Calendar.getInstance());
preparedStatement.setTimestamp(2, new Timestamp(order.getVersion().getCreated().getTime()),
Calendar.getInstance());
preparedStatement.setTimestamp(3, new Timestamp(order.getVersion().getUpdated().getTime()),
Calendar.getInstance());
preparedStatement.setBoolean(4, order.getVersion().isDeleted());
preparedStatement.setBoolean(5, !order.getVersion().isDeleted());
// attributes
preparedStatement.setString(6, order.getName());
preparedStatement.setString(7, order.getType());
preparedStatement.setString(8, order.getState().name());
preparedStatement.setTimestamp(9, new Timestamp(order.getDate().getTime()), Calendar.getInstance());
preparedStatement.setString(7, order.getState().name());
preparedStatement.setTimestamp(8, new Timestamp(order.getDate().getTime()), Calendar.getInstance());
SQLXML sqlxml = writeObject(preparedStatement, order, 10);
SQLXML sqlxml = writeObject(preparedStatement, order, 9);
// primary key
preparedStatement.setString(10, order.getType());
preparedStatement.setString(11, order.getId());
preparedStatement.setInt(12, order.getVersion().getVersion());
try {
int modCount = preparedStatement.executeUpdate();
if (modCount != 1) {
String msg = "Expected to update 1 element with id {0} and version {1} but SQL statement modified {2} elements!";
String msg
= "Expected to update 1 element with id {0} and version {1} but SQL statement modified {2} elements!";
msg = MessageFormat.format(msg, order.getId(), order.getVersion().getVersion(), modCount);
throw new StrolchPersistenceException(msg);
}
@ -237,8 +252,9 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
}
} catch (SQLException | SAXException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to update Order {0} due to {1}", order.getLocator(), e.getLocalizedMessage()), e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to update Order {0} due to {1}", order.getLocator(),
e.getLocalizedMessage()), e);
}
}

View File

@ -15,15 +15,6 @@
*/
package li.strolch.persistence.postgresql;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.text.MessageFormat;
import java.util.Calendar;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import li.strolch.model.Resource;
@ -35,18 +26,32 @@ import li.strolch.persistence.api.StrolchPersistenceException;
import li.strolch.persistence.api.TransactionResult;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.text.MessageFormat;
import java.util.Calendar;
import static li.strolch.utils.helper.XmlHelper.getSaxParser;
@SuppressWarnings("nls")
public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements ResourceDao {
public static final String RESOURCES = "resources";
private static final String insertAsXmlSqlS = "insert into {0} (id, version, created_by, updated_at, created_at, deleted, latest, name, type, asxml) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static final String insertAsJsonSqlS = "insert into {0} (id, version, created_by, updated_at, created_at, deleted, latest, name, type, asjson) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static final String insertAsXmlSqlS
= "insert into {0} (id, version, created_by, updated_at, created_at, deleted, latest, name, type, asxml) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static final String insertAsJsonSqlS
= "insert into {0} (id, version, created_by, updated_at, created_at, deleted, latest, name, type, asjson) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static final String updateAsXmlSqlS = "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, type = ?, asxml = ? where id = ? and version = ?";
private static final String updateAsJsonSqlS = "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, type = ?, asjson = ? where id = ? and version = ?";
private static final String updateAsXmlSqlS
= "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, asxml = ? where type = ? and id = ? and version = ?";
private static final String updateAsJsonSqlS
= "update {0} set created_by = ?, created_at = ?, updated_at = ?, deleted = ?, latest = ?, name = ?, asjson = ? where type = ? and id = ? and version = ?";
private static final String updateLatestSqlS = "update {0} SET latest = false WHERE id = ? AND version = ?";
private static final String updateLatestSqlS
= "update {0} SET latest = false WHERE type = ? and id = ? AND version = ?";
protected PostgreSqlResourceDao(DataType dataType, Connection connection, TransactionResult txResult,
boolean versioningEnabled) {
@ -62,14 +67,13 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
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));
getSaxParser().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), e);
}
if (listener.getResources().size() == 0)
if (listener.getResources().isEmpty())
throw new StrolchPersistenceException(
MessageFormat.format("No Resource parsed from sqlxml value for {0} / {1}", id, type));
if (listener.getResources().size() > 1)
@ -125,9 +129,9 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
}
} catch (SQLException | SAXException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to insert Resource {0} due to {1}", resource.getLocator(), e.getLocalizedMessage()),
e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to insert Resource {0} due to {1}", resource.getLocator(),
e.getLocalizedMessage()), e);
}
if (resource.getVersion().isFirstVersion()) {
@ -139,20 +143,22 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {
// primary key
preparedStatement.setString(1, resource.getId());
preparedStatement.setInt(2, resource.getVersion().getPreviousVersion());
preparedStatement.setString(1, resource.getType());
preparedStatement.setString(2, resource.getId());
preparedStatement.setInt(3, resource.getVersion().getPreviousVersion());
int modCount = preparedStatement.executeUpdate();
if (modCount != 1) {
String msg = "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
String msg
= "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
msg = MessageFormat.format(msg, resource.getId(), resource.getVersion().getPreviousVersion(), modCount);
throw new StrolchPersistenceException(msg);
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to insert Resource {0} due to {1}", resource.getLocator(), e.getLocalizedMessage()),
e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to insert Resource {0} due to {1}", resource.getLocator(),
e.getLocalizedMessage()), e);
}
}
@ -167,15 +173,15 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
// make sure is first version when versioning is not enabled
if (!resource.getVersion().isFirstVersion()) {
throw new StrolchPersistenceException(MessageFormat
.format("Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
resource.getVersion()));
throw new StrolchPersistenceException(MessageFormat.format(
"Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
resource.getVersion()));
}
// and also not marked as deleted!
if (resource.getVersion().isDeleted()) {
throw new StrolchPersistenceException(MessageFormat
.format("Versioning is not enabled, so version can not be marked as deleted for {0}",
throw new StrolchPersistenceException(
MessageFormat.format("Versioning is not enabled, so version can not be marked as deleted for {0}",
resource.getVersion()));
}
@ -196,18 +202,19 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
// attributes
preparedStatement.setString(6, resource.getName());
preparedStatement.setString(7, resource.getType());
SQLXML sqlxml = writeObject(preparedStatement, resource, 8);
SQLXML sqlxml = writeObject(preparedStatement, resource, 7);
// primary key
preparedStatement.setString(8, resource.getType());
preparedStatement.setString(9, resource.getId());
preparedStatement.setInt(10, resource.getVersion().getVersion());
try {
int modCount = preparedStatement.executeUpdate();
if (modCount != 1) {
String msg = "Expected to update 1 element with id {0} and version {1} but SQL statement modified {2} elements!";
String msg
= "Expected to update 1 element with id {0} and version {1} but SQL statement modified {2} elements!";
msg = MessageFormat.format(msg, resource.getId(), resource.getVersion().getVersion(), modCount);
throw new StrolchPersistenceException(msg);
}
@ -217,9 +224,9 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
}
} catch (SQLException | SAXException e) {
throw new StrolchPersistenceException(MessageFormat
.format("Failed to update Resource {0} due to {1}", resource.getLocator(), e.getLocalizedMessage()),
e);
throw new StrolchPersistenceException(
MessageFormat.format("Failed to update Resource {0} due to {1}", resource.getLocator(),
e.getLocalizedMessage()), e);
}
}
}

View File

@ -44,7 +44,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
private static final String updateLatestSqlS = "update {0} set latest = true where type = ? and id = ? and version = ?";
private static final String deleteElementSqlS = "delete from {0} where id = ?";
private static final String deleteElementSqlS = "delete from {0} where type = ? and id = ?";
private static final String deleteVersionSqlS = "delete from {0} where type = ? and id = ? and version = ? and latest = true";
private static final String deleteAllSqlS = "delete from {0}";
private static final String deleteAllByTypeSqlS = "delete from {0} where type = ?";
@ -511,7 +511,8 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
sql = MessageFormat.format(deleteElementSqlS, getTableName());
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {
preparedStatement.setString(1, element.getId());
preparedStatement.setString(1, element.getType());
preparedStatement.setString(2, element.getId());
int modCount = preparedStatement.executeUpdate();
if (modCount != count) {

View File

@ -1,46 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege"/>
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege"/>
<Policy name="RoleAccessPrivilege" class="li.strolch.privilege.policy.RoleAccessPrivilege"/>
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege"/>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
<Policy name="RoleAccessPrivilege" class="li.strolch.privilege.policy.RoleAccessPrivilege" />
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -21,7 +21,6 @@
<Properties>
<dataStoreMode>CACHED</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
<enableObserverUpdates>true</enableObserverUpdates>
<dataStoreFile>StrolchModel.xml</dataStoreFile>
</Properties>
</Component>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -21,7 +21,6 @@
<Properties>
<dataStoreMode>CACHED</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
<enableObserverUpdates>true</enableObserverUpdates>
<enableVersioning>true</enableVersioning>
<dataStoreFile>StrolchModel.xml</dataStoreFile>
</Properties>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -21,7 +21,6 @@
<Properties>
<dataStoreMode>CACHED</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
<enableObserverUpdates>true</enableObserverUpdates>
<dataStoreFile>StrolchModel.xml</dataStoreFile>
</Properties>
</Component>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -21,7 +21,6 @@
<Properties>
<dataStoreMode>CACHED</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
<enableObserverUpdates>true</enableObserverUpdates>
<enableVersioning>true</enableVersioning>
<dataStoreFile>StrolchModel.xml</dataStoreFile>
</Properties>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>li.strolch</groupId>
<artifactId>strolch</artifactId>
<version>2.0.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -69,7 +69,7 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
return this.tx.getMetadataDao().querySize(subTypeRef, file -> true);
}
int size = 0;
long size = 0;
for (String type : types) {
SubTypeRef subTypeRef = getTypeRef(type);
size += this.tx.getMetadataDao().querySize(subTypeRef, file -> true);

View File

@ -91,7 +91,7 @@ public class XmlOrderDao extends AbstractDao<Order> implements OrderDao {
return this.tx.getMetadataDao().querySize(subTypeRef, getDateRangePredicate(dateRange));
}
int size = 0;
long size = 0;
for (String type : types) {
SubTypeRef subTypeRef = getTypeRef(type);
size += this.tx.getMetadataDao().querySize(subTypeRef, getDateRangePredicate(dateRange));

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

View File

@ -21,7 +21,6 @@
<Properties>
<dataStoreMode>CACHED</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
<enableObserverUpdates>true</enableObserverUpdates>
<dataStoreFile>DefaultRealm.xml</dataStoreFile>
</Properties>
</Component>

View File

@ -1,40 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="secretKey" value="58d27145-5d1a-48ea-9e1c-f5a522f6a19f"/>
<Parameter name="secretSalt" value="25bd8911-0008-464f-82b8-4c5200db8dd7"/>
<Parameter name="secretKey" value="CHANGE-ME"/>
<Parameter name="secretSalt" value="CHANGE-ME"/>
<Parameter name="autoPersistOnUserChangesData" value="true" />
<Parameter name="privilegeConflictResolution" value="MERGE"/>
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<!-- WARNING: If you change iterations or keyLength, then all passwords are invalid -->
<!-- default algorithm is: PBKDF2WithHmacSHA512 -->
<Parameter name="hashAlgorithm" value="PBKDF2WithHmacSHA512" />
<!-- default iterations: 200000 -->
<Parameter name="hashIterations" value="10000" />
<!-- default key length: 256 -->
<Parameter name="hashKeyLength" value="256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler">
</UserChallengeHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler"/>
<UserChallengeHandler class="li.strolch.privilege.handler.ConsoleUserChallengeHandler"/>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="ModelPrivilege" class="li.strolch.runtime.privilege.ModelPrivilege" />
@ -42,5 +23,4 @@
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
<Policy name="UserSessionAccessPrivilege" class="li.strolch.privilege.policy.UsernameFromCertificatePrivilege"/>
</Policies>
</Privilege>

Some files were not shown because too many files have changed in this diff Show More