diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 68e24de4..b903da55 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,27 +3,31 @@ name: Java CI -on: [push, pull_request,workflow_dispatch] +on: [push, pull_request, workflow_dispatch] jobs: build: runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '__CI__')" env: - luceeVersion: light-6.0.0.316-SNAPSHOT + luceeVersion: 6.0.0.316-SNAPSHOT steps: - uses: actions/checkout@v3 + - name: Set up JDK 11 uses: actions/setup-java@v3 with: java-version: '11' - distribution: 'adopt' + distribution: 'temurin' + - name: Cache Maven packages uses: actions/cache@v3 with: path: ~/.m2 key: lucee-script-runner-maven-cache + - name: Cache Lucee files uses: actions/cache@v3 with: @@ -31,32 +35,125 @@ jobs: key: lucee-downloads-${{ env.luceeVersion }} restore-keys: | lucee-downloads + - name: Build with Ant run: ant -noinput -verbose -buildfile build.xml + - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: hibernate-lex path: dist/*.lex + - name: Checkout Lucee uses: actions/checkout@v3 with: repository: lucee/lucee path: lucee - - name: Run Lucee Test Suite (testFilter="orm") + + - name: Run Lucee Test Suite (testLabels="orm") uses: lucee/script-runner@main with: webroot: ${{ github.workspace }}/lucee/test execute: /bootstrap-tests.cfm - luceeVersion: ${{ env.luceeVersion }} + luceeVersion: light-${{ env.luceeVersion }} extensionDir: ${{ github.workspace }}/dist env: testLabels: orm testAdditional: ${{ github.workspace }}/tests + - name: Publish Test Results uses: EnricoMi/publish-unit-test-result-action@v1 if: always() with: - files: ${{ github.workspace }}/lucee/test/reports/junit-test-results.xml + files: ${{ github.workspace }}/lucee/test/reports/junit-test-results-${{env.luceeVersion}}.xml check_name: "Test Results" + maven_build: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '__CI__')" + strategy: + fail-fast: false + matrix: + lucee_version: ["5.3.10.97"] + java_version: [ "8", "11", "17" ] + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK + uses: actions/setup-java@v3 + with: + java-version: '${{matrix.java_version}}' + distribution: 'temurin' + + - name: Build with Maven + run: mvn --batch-mode -f pom.xml -Dlucee.version=${{matrix.lucee_version}} -Djdk.version=${{matrix.java_version}} compile + + javadocs: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '__CI__')" + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: maven-cache + + - name: Generate Javadocs + run: mvn --batch-mode -f pom.xml javadoc:javadoc + + - name: Get Project Version for Javadocs Versioning + id: current_version + # For Maven builds (future) + # run: echo "VERSION=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`" >> $GITHUB_ENV + # For Ant builds (still the default) + run: echo "VERSION=`ant -silent -quiet version`" >> $GITHUB_ENV + + - name: Upload API Docs to S3 + uses: jakejarvis/s3-sync-action@master + with: + args: --acl public-read + env: + AWS_S3_BUCKET: ${{ secrets.AWS_APIDOCS_BUCKET }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_ACCESS_SECRET }} + SOURCE_DIR: "docs" + DEST_DIR: "lucee/hibernate-extension/${{ env.VERSION }}/" + + format: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '__CI__')" + steps: + - uses: actions/checkout@v3 + with: + token: ${{secrets.GH_TOKEN}} + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: maven-cache + + - name: Format Java source code + run: mvn --batch-mode -f pom.xml formatter:format + + - name: Commit formatting changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + file_pattern: "docs" + commit_message: "🤖 CI: Auto-format Java source __CI__" diff --git a/.gitignore b/.gitignore index 695e4b88..7ed7aa96 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,24 @@ -/dist -temp -**/.DS_Store +# Editor and OS artifacts +.vscode +.DS_Store **/.svn/ /*.project va specific + +# build files/dist +/bin +/build +/dist +/temp *.class -target -target/* +/target *.lock *.DS_Store -/cache \ No newline at end of file +/cache +/docs + +# Test artifacts +WEB-INF/ + +# Lucee source for CFML tests +/lucee \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..30fb67ea --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ +# Lucee Hibernate Extension (ORM) + +[![Java CI](https://github.com/lucee/extension-hibernate/actions/workflows/main.yml/badge.svg?branch=5.4)](https://github.com/lucee/extension-hibernate/actions/workflows/main.yml) 5.4 + +[![Java CI](https://github.com/lucee/extension-hibernate/actions/workflows/main.yml/badge.svg?branch=3.5.5)](https://github.com/lucee/extension-hibernate/actions/workflows/main.yml) 3.5.5 + +[![Java CI](https://github.com/lucee/extension-hibernate/actions/workflows/main.yml/badge.svg)](https://github.com/lucee/extension-hibernate/actions/workflows/main.yml) Master + +* A [Hibernate ORM](https://hibernate.org/orm/) wrapper for the [Lucee CFML language](https://www.lucee.org/) + +* Issues: https://luceeserver.atlassian.net/issues/?jql=labels%20%3D%20%22orm%22 +* Documentation: https://docs.lucee.org/categories/orm.html + +## Contributing + +You will need to install the following for extension development: + +* Java 1.8+ (JRE and JDK) +* [ant](https://www.osradar.com/install-apache-ant-ubuntu-20-04/) (for building the extension `.lex` file) +* [maven](https://linuxize.com/post/how-to-install-apache-maven-on-ubuntu-20-04/) (for other automated tooling) +* [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/) (for managing test database servers) + +### Getting Started + +1. Install the repo - `git clone git@github.com:lucee/extension-hibernate.git` +2. Make changes.. +3. [Build extension via `ant dist`](#building) +4. Test via `./test.sh` (See [#Testing](#testing) for more info) + +**Before you send a PR:** + +1. Don't forget to run tests! + 1. (if you can't get tests to pass, ask for help!) +2. Format java source code: `mvn formatter:format` + +## Building + +Using ant builds (for now): + +* `ant clean` - clean build directories +* `ant compile` - compile code +* `ant dist` - Package the extension into a Lucee-installable `.lex` extension file + +Using the Maven builds: + +* `mvn test` run java-based (junit) tests +* `mvn javadoc:javadoc` generate java docs +* `mvn formatter:format` [format java source](https://code.revelc.net/formatter-maven-plugin/usage.html) +* `mvn verify` Run OWASP dependency checker to look for vulnerabilities + +## Testing + +See Lucee documentation on [testing-a-lucee-extension-locally](https://docs.lucee.org/guides/working-with-source/building-and-testing-extensions.html#testing-a-lucee-extension-locally). + +To run CFML tests against the extension: + +1. Check out [lucee/Lucee](https://github.com/lucee/lucee) to the parent directory - `git clone git@github.com:lucee/Lucee.git ../lucee` +2. Check out [lucee/script-runner](https://github.com/lucee/script-runner) to the parent directory - `git clone git@github.com:lucee/Lucee.git ../script-runner`. + +Next, start the test databases using the Docker-compose setup: + +```bash +cd tests && docker-compose up +``` + +This will start Postgres, MySQL, and MSSQL containers using the credentials specified in `tests/.env`. + +Finally, you can run tests from the extension root: + +```bash +./test.sh +``` + +To build a .lex and test it immediately, chain `ant dist` and `./test.sh`: + +```bash +ant dist && ./test.sh +``` \ No newline at end of file diff --git a/build.xml b/build.xml index 0d04fb43..069f8268 100644 --- a/build.xml +++ b/build.xml @@ -13,7 +13,10 @@ - + + + + @@ -38,6 +41,10 @@ + + + ${bundleversion}${build.number}${versionAppendix} + @@ -78,10 +85,19 @@ lucee-core-version: "${luceeCoreVersion}" + + + + + - + + + + + - 4.0.0 - - org.lucee - extension.hibernate - 5.0.0.99-SNAPSHOT - jar - - Extension Hibernate - Lucee Extension for Hibernate ORM Engine. - http://maven.lucee.org/extension/hibernate - - - - hibernate.extension + + 4.0.0 + + org.lucee + hibernate.extension + + 5.4.29.75-BETA + bundle + + Ortus Hibernate Extension + Lucee Extension for Hibernate ORM Engine. + http://maven.lucee.org/extension/hibernate + + + Hibernate ORM Engine + hibernate-extension FAD1E8CB-4F45-4184-86359145767C29DE - Hibernate ORM (Hibernate in short) is an object-relational mapping library for the Java language, - providing a framework for mapping an object-oriented domain model to a traditional relational database. - Hibernate solves object-relational impedance mismatch problems by replacing direct persistence-related - database accesses with high-level object handling functions. + Hibernate ORM (Hibernate in short) is an object-relational mapping library for the Java language, providing a framework for mapping an object-oriented domain model to a traditional relational database. Hibernate solves object-relational impedance mismatch problems by replacing direct persistence-related database accesses with high-level object handling functions. org.lucee.extension.orm.hibernate.HibernateORMEngine - - - - - The GNU Lesser General Public License, Version 2.1 - http://www.gnu.org/licenses/lgpl-2.1.txt - repo - - - - - - micstriit - Michael Offner - michael@lucee.org - Lucee Association Switzerland - http://lucee.org - - Project-Administrator - Developer - - +1 - - - - + + + 5.3.10.97 + 5.4.29.Final + + + 1.8 + ${jdk.version} + ${jdk.version} + UTF-8 + + + + + The GNU Lesser General Public License, Version 2.1 + http://www.gnu.org/licenses/lgpl-2.1.txt + repo + + + + + + micstriit + Michael Offner + michael@lucee.org + Lucee Association Switzerland + http://lucee.org + + Project-Administrator + Developer + + +1 + + + + - + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + add-source + generate-sources + + add-source + + + + ${project.basedir}/source/java/src/ + + + + + + - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - - - - - + org.apache.maven.plugins - maven-jar-plugin - 2.6 - true - + maven-javadoc-plugin + 3.4.1 + + + attach-javadocs + + jar + + + - - .* - - - src/main/java/META-INF/MANIFEST.MF - - ${main.class} - - - - - + ${project.basedir} + docs + -Xdoclint:none + false + + + org.apache.maven.plugins - maven-compiler-plugin - 3.3 - - 1.7 - 1.7 - - - - - - - - - - + maven-compiler-plugin + 3.3 + + + org.apache.felix + maven-bundle-plugin + 5.1.8 + true + + + ${project.artifactId} + ${project.artifactId} + org.lucee.extension.orm.hibernate + + org.lucee.extension.orm.hibernate,org.lucee.extension.orm.hibernate.jdbc + + net.sf.ehcache.hibernate + org.lucee.hibernate;bundle-version=5.4.29.1,org.lucee.antlr;bundle-version=2.7.6,org.lucee.dom4j;bundle-version=1.6.1,org.lucee.javassist;bundle-version=3.9.0.GA,org.lucee.jta;bundle-version=1.1.0,slf4j.api;bundle-version=1.7.36,org.apache.commons.collections;bundle-version=3.2.1,org.lucee.xml.apis;bundle-version=1.4.1,com.fasterxml.classmate;bundle-version=1.5.1,net.bytebuddy.byte-buddy;bundle-version=1.10.21,org.lucee.hibernate-annotations;bundle-version=5.1.2.Final,javax.persistence-api;bundle-version=2.2,org.lucee.hibernate-ehcache;bundle-version=5.4.29.Final,org.lucee.ehcache;bundle-version=2.10.6,jakarta.xml.bind-api;bundle-version=2.3.3,org.glassfish.jaxb.runtime;bundle-version=2.3.4 + + + <_noimportjava>true + + + + + + + com.github.ekryd.echo-maven-plugin + echo-maven-plugin + 1.3.2 + false + + + copy-starter-manifest + package + + echo + + + /${project.basedir}/source/java/src/META-INF/EXTENSION.MF + + target/META-INF/MANIFEST.MF + + + + append-manifest-entries + package + + echo + + + +name: ${name} +id: ${id} +description: ${description} +version: ${project.version} +orm: [{'class':'${class}','name':'${project.artifactId}','version':'${project.version}'}] +lucee-core-version: ${lucee.version} + + + target/META-INF/MANIFEST.MF + + true + + + + - - - - junit - junit - 4.12 - + + maven-assembly-plugin + + + package + + single + + + + + + + source/lex.xml + + + + + + + + com.coderplus.maven.plugins + copy-rename-maven-plugin + 1.0.1 + + + copy-file + package + + rename + + + ${project.build.directory}/${project.build.finalName}-lex.zip + ${project.build.directory}/${project.build.finalName}.lex + + + + + + + + + org.owasp + dependency-check-maven + 7.3.2 + + + + check + + + + + + net.revelc.code.formatter + formatter-maven-plugin + 2.21.0 + + + ${project.basedir}/source/java/src/ + ${project.basedir}/src/test/java + + + + - - org.lucee - lucee - - - org.lucee - lucee - 3.1.0 - + - - - compile - org.apache.felix - org.apache.felix.framework - 4.2.1 - - - javax.servlet - javax.servlet-api - 3.1.0 - - - javax.servlet.jsp - jsp-api - 2.2 - - - javax.el - javax.el-api - 3.0.0 - - - org.apache.ant - ant - 1.9.5 - - - - org.apache.tika - tika-core - 1.10 - - - - - - org.apache.sanselan - sanselan - 0.97-incubator - - - - - - org.apache.commons - codec - 1.6.0 - - - - - - - - - - org.apache.commons - commons-collections4 - 4.0 - - - - - - - - org.apache.commons - commons-compress - 1.9 - - - - - commons-discovery - commons-discovery - 0.5 - - - - - org.apache.commons - commons-email - 1.2 - - - - - org.apache.commons - fileupload - 1.2.1 - - - - - org.lucee - commons-httpclient - 3.1 - - - - - commons-io - commons-io - 2.4 - - - - - commons-lang - commons-lang - 2.6 - - - - - - - - org.apache.commons.logging - adapters - 1.1.1 - - - - - org.apache.commons.logging - api - jar - 1.1.1 - - - - org.apache.commons - logging - jar - 1.1.1 - + + + + org.junit + junit-bom + 5.9.2 + pom + import + + + - - - commons-net - commons-net - 3.3 - - - + - org.apache - oro - jar - 2.0.8 + org.junit.jupiter + junit-jupiter + 5.9.2 + test - - - log4j - log4j - 1.2.17 - - - - - apache.poi.ooxml - schemas - jar - 3.8.0 - - - - org.apache.poi - ooxml - jar - 3.8.0 - - - - apache.poi.tm - extractors - jar - 3.8.0 - - - - org.apache - poi - jar - 3.8.0 - - - - apache.ws.axis - ant - jar - 1.4.0 - - - - apache.ws - axis - jar - 1.4.0.L004 - - - - apache.xml - xalan - jar - 2.7.1 - - - - apache.xml - xerces - jar - 2.11.0 - - - - backport.util - concurrent - jar - 2.2.0 - - - - bcprov - jdk14 - jar - 1.36.0 - - - - - edu.oswego.cs.gee - concurrent - jar - 1.3.3 - - - - - net.sf.ehcache - ehcache - 2.10.0 - - - - - - ESAPI - ESAPI - jar - 2.1.0 - - - - - flex.messaging - common - jar - 3.3.0.22497 - - - - flex.messaging - core - jar - 3.3.0.22497 - - - - flex.messaging - opt - jar - 3.3.0.22497 - - - - flex.messaging - proxy - jar - 3.3.0.22497 - - - - flex.messaging - remoting - jar - 3.3.0.22497 - - - - fusiondebug.api - server - jar - 1.0.20 - - - - apache.http.components - client - jar - 4.5.0.0001L - - - - apache.http.components - core - jar - 4.4.1 - - - - apache.http.components - mime - jar - 4.5.0 - - - - hsqldb - hsqldb - jar - 1.8.0 - - - - icepdf - core - jar - 3.1.0.3 - - - jacob - jacob - jar - 1.16.1 + org.mockito + mockito-inline + 4.0.0 + test - - javaparser - javaparser - jar - 1.0.8 - - - - javasysmon - javasysmon - jar - 0.3.3 + org.mockito + mockito-junit-jupiter + 4.0.0 + test - - - org.samba - jcifs - jar - 1.3.17 - - - - jcommon - jcommon - jar - 1.0.10 - - - - jencrypt - jencrypt - jar - 1.4.2.04 - - - - jffmpeg - jffmpeg - jar - 1.4.2.09 - - - - jfreechart - patch - jar - 1.0.12 - - - - jfreechart - jfreechart - jar - 1.0.12 - - - + - org.joda - time - jar - 2.1.0 - - - - jpedal - gpl - jar - 3.51.12 + org.lucee + lucee + ${lucee.version} + + provided - - - lowagie - itext - jar - 2.1.2.1 - - - - metadata - extractor - jar - 2.6.4 + org.lucee + txw2 + 2011.8.9 - - - org.ow2.asm - asm-all - 4.2 - - - + - ojdbc14 - ojdbc14 - jar - 0.0.0 + org.hibernate + hibernate-core + ${hibernate.version} - + - openamf - astranslator - jar - 1.5.8 - - - - openamf - openamf - jar - 1.5.8 - - - - org.apache.pdfbox - pdfbox - 1.8.9 - - - - - - org.apache.pdfbox - fontbox - 1.8.9 - - - - - org.apache.pdfbox - jempbox - 1.8.9 - - - - - PDFRenderer - PDFRenderer - jar - 1.0.5 - - - - resolver - resolver - jar - 1.2.0 - - - - serializer - serializer - jar - 2.7.1 - + org.hibernate + hibernate-ehcache + ${hibernate.version} - - - org.slf4j - slf4j-api - 1.7.12 - - - - - org.slf4j - slf4j-nop - 1.7.12 - - - - - ss - css2 - jar - 0.9.4 - - - - stax - api - jar - 1.0.1 + + + + org.glassfish.jaxb + txw2 + + - - - sun - activation - jar - 1.1.0 - - - - sun.jai - codec - jar - 1.1.2 - - - - sun.jai - core - jar - 1.2.1 - - - - sun.jndi - ldap - jar - 1.2.4 - - - - sun.jndi - ldapbp - jar - 1.2.4 - - - - sun.jndi - ldapsec - jar - 1.2.4 - - - - sun.jndi - providerutil - jar - 1.2.4 - - - - sun - mail - jar - 1.3.3.01 - - - - sun.security - jaas - jar - 1.2.4 - - - - sun.xml - jaxrpc - jar - 1.2.1 - - - - sun.xml - wsdl4j - jar - 1.5.1 - - - - sun.xml - saaj - jar - 1.2.1 - - - - tagsoup - tagsoup - jar - 1.2.1 - - + w3c dom jar 1.1.0 - - - xdb - xdb - jar - 1.0.0 - - - - xml - apis - jar - 1.3.2 - - - - xmlbeans - xmlbeans - jar - 2.3.0.r540734 - - + + - xmlparserv2 - xmlparserv2 - jar - 1.2.2 + com.sun.xml.bind + jaxb-osgi + 2.3.7 + + repo https://raw.githubusercontent.com/lucee/mvn/master/releases - - snapi - https://oss.sonatype.org/content/repositories/snapshots - + - - https://github.com/lucee/Lucee - scm:git:git://github.com/lucee/Lucee.git - scm:git:git@github.com:lucee/Lucee.git - ${project.version} - - - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - + + https://github.com/michaelborn/extension-hibernate + scm:git:git://github.com/michaelborn/extension-hibernate.git + scm:git:git@github.com:michaelborn/extension-hibernate.git + ${project.version} + + + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + \ No newline at end of file diff --git a/source/fld/ormFunctions.fld b/source/fld/ormFunctions.fld new file mode 100644 index 00000000..2b7e6d36 --- /dev/null +++ b/source/fld/ormFunctions.fld @@ -0,0 +1,476 @@ + + + + + 1.00 + Hibernate-extension + https://github.com/lucee/extension-hibernate + Hibernate + + Functions to interact with Hibernate + + + + + EntityDelete + org.lucee.extension.orm.functions.EntityDelete + Deletes the record from the database for the specified entity. +EntityDelete(entity) + + name + object + Yes + Name of the entity being deleted. + + + void + + + + + + entityLoad + org.lucee.extension.orm.functions.EntityLoad + Loads and returns an array of entities of the specified entityName. +EntityLoad (entityName, filterCriteria [,unique] +EntityLoad(entityName, filterCriteria, sortOrder [, options]) + + name + string + Yes + Name of the entity to be loaded. + + + idOrFilter + id,filter + any + no + The primary key value of the entity that must be loaded or Key-value pair (Struct) of property names and values. + If there are more than one key-value pair, then the AND operator is used.If specified, loads and returns an array of entities of the specified entity name that matches the filterCriteria. + + + uniqueOrOrder + unique,order + any + no + when the second argument is an id then this argument defines the boolean "unique" otherwise it defines the order. + +- unique: +If unique is set to true, then the entity is returned. +If you are sure that only one record exists that matches this filterCriteria, then you can specify unique=true, so that a single entity is returned instead of an array. +If you set unique=true and multiple records are returned, then an exception occurs. + +- order: +String used to specify the sortOrder of the entities that are returned.If specified, loads and returns an array of entities that satisfy the filterCriteria sorted as specified by the sortOrder. + + + + + options + any + no + +The following options to customize the output (only used when second argument is "id"): +- ignoreCase: Ignores the case of sort order when set to true. Use only if you specify the sortOrder parameter. +- offset: Specifies the position from which to retrieve the objects. +- maxResults: Specifies the maximum number of objects to be retrieved. +- cacheable: Whether the result has to be cached in the secondary cache. Default is false. +- cacheName: Name of the cache in secondary cache. +- timeout: Specifies the timeout value (in seconds) for the query. + + + + any + + + + + + EntityLoadByPK + org.lucee.extension.orm.functions.EntityLoadByPK + Loads and returns an array of objects for given primary key. + + name + string + Yes + Name of the entity to be loaded. + + + id + any + yes + The primary key value of the entity that must be loaded + + + unique + boolean + no + If unique is set to true, then the entity is returned. +If you are sure that only one record exists that matches this filtercriteria, then you can specify unique=true, so that a single entity is returned instead of an array. +If you set unique=true and multiple records are returned, then an exception occurs. + + + any + + + + + + EntityLoadByExample + org.lucee.extension.orm.functions.EntityLoadByExample + Loads and returns an array of objects that match the sample entity. +entityLoadByExample(sampleEntity,[unique]) + + sampleEntity + object + yes + Name of the sample entity that is used to match and filter similar entities to load. + + + unique + boolean + no + If unique is set to true, then the entity is returned. +If you are sure that only one record exists that matches this filtercriteria, then you can specify unique=true, so that a single entity is returned instead of an array. +If you set unique=true and multiple records are returned, then an exception occurs. + + + any + + + + + + EntityMerge + org.lucee.extension.orm.functions.EntityMerge + Attaches given entity to current ORM session + + entity + any + yes + The entity that must be attached to the ORM session. + + + any + + + + + + EntityNew + org.lucee.extension.orm.functions.EntityNew + Creates a new instance of the persistent CFC with the entity name that you provide. + + entityName + string + yes + Name of the instance being created. + + + properties + struct + no + a struct containing data to populate the entity properties. + + + any + + + + + + EntityNameArray + org.lucee.extension.orm.functions.EntityNameArray + return all loaded entities as array + + array + + + + + + EntityNameList + org.lucee.extension.orm.functions.EntityNameList + return all loaded entities as string list + + delimiter + string + no + delimiter used for the list + + + string + + + + + + EntityReload + org.lucee.extension.orm.functions.EntityReload + Reloads data for an entity that is already loaded. + + entity + object + yes + name of the entity + + + void + + + + + + EntitySave + org.lucee.extension.orm.functions.EntitySave + Saves or updates data of the entity and all related entities to the database. +EntitySave(entity, [forceInsert]) + + entity + object + yes + Name of the entity that must be saved in the database. + + + forceInsert + boolean + no + If true, then Lucee always tries to insert the entity as a new record. + + + void + + + + + + EntityToQuery + org.lucee.extension.orm.functions.EntityToQuery + Converts the input entity object or the input array of entity objects to a query object. + + entity + object + yes + entity or array of entities + + + name + string + no + name of the entities + + + query + + + + + + + ORMExecuteQuery + org.lucee.extension.orm.functions.ORMExecuteQuery + Runs the HQL on the default data source specified for the application. + + hql + string + yes + + + + paramsOrUnique + params + any + no + + + + uniqueOrQueryOptions + unique + any + no + + + + queryOptions + any + no + + + + any + + + + + ORMClearSession + org.lucee.extension.orm.functions.ORMClearSession + Removes all the entities that are loaded or created in the session. This clears the first level cache and removes the objects that are not yet saved to the database. + + datasource + string + no + datasource used for the session, if nor defined the datasource defined in application.cfc/cfapplication is used. + + + void + + + + + ORMCloseSession + org.lucee.extension.orm.functions.ORMCloseSession + Closes the current ORM session. + + datasource + string + no + datasource used for the session, if nor defined the datasource defined in application.cfc/cfapplication is used. + + + void + + + + + ORMCloseAllSessions + org.lucee.extension.orm.functions.ORMCloseAllSessions + Closes all ORM session. + + void + + + + + ORMEvictCollection + org.lucee.extension.orm.functions.ORMEvictCollection + This will remove all the entries with the specified relation/collection name in the specified component. +ormEvictCollection(componentName,relationName,[id]) + + + entityName + String + yes + + + + collectionName + String + yes + + + + primaryKey + String + no + + + + + void + + + + + ORMEvictEntity + org.lucee.extension.orm.functions.ORMEvictEntity + This will remove all the entries for the specified component name from the entity cache. +ormEvictEntity(componentName,[id]) + + + entityName + String + yes + + + + primaryKey + String + no + + + + + void + + + + + ORMEvictQueries + org.lucee.extension.orm.functions.ORMEvictQueries + This will remove all the queries from the named query cache. +If name is not specified, all queries from default cache will be removed. +ormEvictQueries([cacheName]) + + cacheName + cache,region + String + no + + + + datasource + string + no + datasource used for the session, if nor defined the datasource defined in application.cfc/cfapplication is used. + + + void + + + + + ORMFlush + org.lucee.extension.orm.functions.ORMFlush + Flushes the current ORM session. ORMFlush flushes all the pending CRUD operations in that request. Any changes made in the objects, in the current ORM session, are saved to the database. + + datasource + string + no + datasource used for the session, if nor defined the datasource defined in application.cfc/cfapplication is used. + + + void + + + + + ORMGetSession + org.lucee.extension.orm.functions.ORMGetSession + Returns the current ORM session + + datasource + string + no + datasource used for the session, if nor defined the datasource defined in application.cfc/cfapplication is used. + + + object + + + + + ORMGetSessionFactory + org.lucee.extension.orm.functions.ORMGetSessionFactory + Returns ORM session factory instance + + datasource + string + no + datasource used for the session, if nor defined the datasource defined in application.cfc/cfapplication is used. + + + object + + + + + ORMReload + org.lucee.extension.orm.functions.ORMReload + Returns ORM session factory instance + + void + + + + \ No newline at end of file diff --git a/source/java/.project b/source/java/.project index 1d65b9dd..0e3a1937 100644 --- a/source/java/.project +++ b/source/java/.project @@ -14,4 +14,15 @@ org.eclipse.jdt.core.javanature + + + 1674334952723 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/source/java/src/META-INF/EXTENSION.MF b/source/java/src/META-INF/EXTENSION.MF new file mode 100644 index 00000000..9d885be5 --- /dev/null +++ b/source/java/src/META-INF/EXTENSION.MF @@ -0,0 +1 @@ +Manifest-Version: 1.0 diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityDelete.java b/source/java/src/org/lucee/extension/orm/functions/EntityDelete.java new file mode 100755 index 00000000..b15cc765 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityDelete.java @@ -0,0 +1,48 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * Delete an entity or array of entities with this CFML built-in function. + */ +public class EntityDelete extends BIF { + public static String call(PageContext pc, Object obj) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + session.delete(pc, obj); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + + if (args.length == 1) return call(pc, args[0]); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityDelete", 1, 1, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityLoad.java b/source/java/src/org/lucee/extension/orm/functions/EntityLoad.java new file mode 100755 index 00000000..f43eb1a7 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityLoad.java @@ -0,0 +1,106 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.type.Struct; + +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to load an ORM entity or entities by ID or criteria + */ +public class EntityLoad extends BIF { + + public static Object call(PageContext pc, String name) throws PageException { + + ORMSession session = ORMUtil.getSession(pc); + return session.loadAsArray(pc, name, CommonUtil.createStruct()); + } + + public static Object call(PageContext pc, String name, Object idOrFilter) throws PageException { + return call(pc, name, idOrFilter, Boolean.FALSE); + } + + public static Object call(PageContext pc, String name, Object idOrFilter, Object uniqueOrOptions) + throws PageException { + ORMSession session = ORMUtil.getSession(pc); + + // id + if (CommonUtil.isSimpleValue(idOrFilter)) { + // id,unique + if (CommonUtil.isCastableToBoolean(uniqueOrOptions)) { + // id,unique=true + if (CommonUtil.toBooleanValue(uniqueOrOptions)) + return session.load(pc, name, CommonUtil.toString(idOrFilter)); + // id,unique=false + return session.loadAsArray(pc, name, CommonUtil.toString(idOrFilter)); + } else if (CommonUtil.isString(uniqueOrOptions)) { + return session.loadAsArray(pc, name, CommonUtil.toString(idOrFilter), + CommonUtil.toString(uniqueOrOptions)); + } + + // id,options + return session.loadAsArray(pc, name, CommonUtil.toString(idOrFilter)); + } + + // filter,[unique|sortorder] + if (CommonUtil.isSimpleValue(uniqueOrOptions)) { + // filter,unique + if (CommonUtil.isBoolean(uniqueOrOptions)) { + if (CommonUtil.toBooleanValue(uniqueOrOptions)) + return session.load(pc, name, CommonUtil.toStruct(idOrFilter)); + return session.loadAsArray(pc, name, CommonUtil.toStruct(idOrFilter)); + } + // filter,sortorder + return session.loadAsArray(pc, name, CommonUtil.toStruct(idOrFilter), (Struct) null, + CommonUtil.toString(uniqueOrOptions)); + } + // filter,options + return session.loadAsArray(pc, name, CommonUtil.toStruct(idOrFilter), CommonUtil.toStruct(uniqueOrOptions)); + } + + public static Object call(PageContext pc, String name, Object filter, Object order, Object options) + throws PageException { + ORMSession session = ORMUtil.getSession(pc); + return session.loadAsArray(pc, name, CommonUtil.toStruct(filter), CommonUtil.toStruct(options), + CommonUtil.toString(order)); + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 1) return call(pc, cast.toString(args[0])); + if (args.length == 2) return call(pc, cast.toString(args[0]), args[1]); + if (args.length == 3) return call(pc, cast.toString(args[0]), args[1], args[2]); + if (args.length == 4) return call(pc, cast.toString(args[0]), args[1], args[2], args[3]); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityLoad", 1, 4, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityLoadByExample.java b/source/java/src/org/lucee/extension/orm/functions/EntityLoadByExample.java new file mode 100755 index 00000000..06d51b6a --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityLoadByExample.java @@ -0,0 +1,56 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * Built-in CFML method to load entity which matches the sample entity. + */ +public class EntityLoadByExample extends BIF { + public static Object call(PageContext pc, Object sampleEntity) throws PageException { + return call(pc, sampleEntity, false); + } + + public static Object call(PageContext pc, Object sampleEntity, boolean unique) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + if (unique) + return session.loadByExample(pc, sampleEntity); + return session.loadByExampleAsArray(pc, sampleEntity); + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 2) return call(pc, args[0], cast.toBoolean(args[1])); + if (args.length == 1) return call(pc, args[0]); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityLoadByExample", 2, 3, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityLoadByPK.java b/source/java/src/org/lucee/extension/orm/functions/EntityLoadByPK.java new file mode 100755 index 00000000..d76a34fd --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityLoadByPK.java @@ -0,0 +1,38 @@ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * Built-in CFML method to load entity by primary key. + */ +public class EntityLoadByPK extends BIF { + public static Object call(PageContext pc, String name, Object oID) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + String id; + if (CommonUtil.isBinary(oID)) + id = CommonUtil.toBase64(oID); + else + id = CommonUtil.toString(oID); + return session.load(pc, name, id); + // FUTURE call instead load(..,..,OBJECT); + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 2) return call(pc, cast.toString(args[0]), args[1]); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityLoadByPK", 2, 2, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityMerge.java b/source/java/src/org/lucee/extension/orm/functions/EntityMerge.java new file mode 100755 index 00000000..6053b423 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityMerge.java @@ -0,0 +1,48 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * Merge a detached or transient entity into the Hibernate session. + */ +public class EntityMerge extends BIF { + + public static Object call(PageContext pc, Object obj) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + return session.merge(pc, obj); + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + + if (args.length == 1) return call(pc, args[0]); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityMerge", 1, 1, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityNameArray.java b/source/java/src/org/lucee/extension/orm/functions/EntityNameArray.java new file mode 100755 index 00000000..a39fa277 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityNameArray.java @@ -0,0 +1,49 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.type.Array; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; +/** + * CFML built-in function to retrieve an array of all ORM entity names. + */ +public class EntityNameArray extends BIF { + + public static Array call(PageContext pc) throws PageException { + return CommonUtil.toArray( + ORMUtil.getSession(pc).getEntityNames() + ); + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + + if (args.length == 0) return call(pc); + + throw engine.getExceptionUtil().createFunctionException(pc, "entityNameArray", 0, 0, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityNameList.java b/source/java/src/org/lucee/extension/orm/functions/EntityNameList.java new file mode 100755 index 00000000..9d82d8ae --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityNameList.java @@ -0,0 +1,55 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to retrieve a list of all ORM entity names. + */ +public class EntityNameList extends BIF { + + public static String call(PageContext pc) throws PageException { + return call(pc, ","); + } + + public static String call(PageContext pc, String delimiter) throws PageException { + ORMSession sess = ORMUtil.getSession(pc); + return String.join(delimiter, sess.getEntityNames()); + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 0) return call(pc); + if (args.length == 1) return call(pc, cast.toString(args[0])); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityNameList", 0, 1, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityNew.java b/source/java/src/org/lucee/extension/orm/functions/EntityNew.java new file mode 100755 index 00000000..b03d6dd0 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityNew.java @@ -0,0 +1,95 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import java.util.Iterator; +import java.util.Map.Entry; + +import lucee.runtime.Component; +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.type.Collection.Key; +import lucee.runtime.type.Struct; +import lucee.runtime.type.UDF; + +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to create a new instance of a Hibernate session entity. + */ +public class EntityNew extends BIF { + + public static Object call(PageContext pc, String name) throws PageException { + return call(pc, name, null); + } + + public static Object call(PageContext pc, String name, Struct properties) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + if (properties == null) + return session.create(pc, name); + + Component entity = session.create(pc, name); + setPropeties(pc, entity, properties, false); + return entity; + + } + + public static void setPropeties(PageContext pc, Component c, Struct properties, boolean ignoreNotExisting) + throws PageException { + if (properties == null) + return; + + // argumentCollection + if (properties.size() == 1 && properties.containsKey(CommonUtil.createKey("argumentCollection")) + && !c.containsKey(CommonUtil.createKey("setArgumentCollection"))) { + properties = CommonUtil.toStruct(properties.get(CommonUtil.createKey("argumentCollection"))); + } + + Iterator> it = properties.entryIterator(); + Entry e; + while (it.hasNext()) { + e = it.next(); + Key funcName = CommonUtil.createKey("set" + e.getKey().getString()); + if (ignoreNotExisting) { + if (c.get(funcName, null) instanceof UDF) + c.call(pc, funcName, new Object[] { e.getValue() }); + } else { + c.call(pc, funcName, new Object[] { e.getValue() }); + } + } + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 1) return call(pc, cast.toString(args[0])); + if (args.length == 2) return call(pc, cast.toString(args[0]), cast.toStruct(args[1])); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityNew", 1, 2, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityReload.java b/source/java/src/org/lucee/extension/orm/functions/EntityReload.java new file mode 100755 index 00000000..7cafa2ae --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityReload.java @@ -0,0 +1,50 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; + +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to reload an ORM entity. + */ +public class EntityReload extends BIF { + + public static String call(PageContext pc, Object obj) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + session.reload(pc, obj); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + + if (args.length == 1) return call(pc, args[0]); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityReload", 1, 1, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntitySave.java b/source/java/src/org/lucee/extension/orm/functions/EntitySave.java new file mode 100755 index 00000000..72a53dc4 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntitySave.java @@ -0,0 +1,56 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to persist an entity to the database. + */ +public class EntitySave extends BIF { + + public static String call(PageContext pc, Object obj) throws PageException { + return call(pc, obj, false); + } + + public static String call(PageContext pc, Object obj, boolean forceInsert) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + session.save(pc, obj, forceInsert); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 1) return call(pc, args[0]); + if (args.length == 2) return call(pc, args[0], cast.toBoolean(args[1])); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntitySave", 1, 2, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/EntityToQuery.java b/source/java/src/org/lucee/extension/orm/functions/EntityToQuery.java new file mode 100755 index 00000000..a73ee138 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/EntityToQuery.java @@ -0,0 +1,57 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.type.Query; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to convert an entity to a query object. + */ +public class EntityToQuery extends BIF { + + public static Query call(PageContext pc, Object obj) throws PageException { + return call(pc, obj, null); + } + + public static Query call(PageContext pc, Object obj, String name) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + return session.toQuery(pc, obj, name); + + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 1) return call(pc, args[0]); + if (args.length == 2) return call(pc, args[0], cast.toString(args[1])); + + throw engine.getExceptionUtil().createFunctionException(pc, "EntityToQuery", 1, 2, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMClearSession.java b/source/java/src/org/lucee/extension/orm/functions/ORMClearSession.java new file mode 100755 index 00000000..021c443e --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMClearSession.java @@ -0,0 +1,58 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.loader.util.Util; +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to clear the ORM session. + */ +public class ORMClearSession extends BIF { + + public static String call(PageContext pc) throws PageException { + return call(pc, null); + } + + public static String call(PageContext pc, String datasource) throws PageException { + if (Util.isEmpty(datasource, true)) + ORMUtil.getSession(pc).clear(pc); + else + ORMUtil.getSession(pc).clear(pc, datasource.trim()); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 0) return call(pc); + if (args.length == 1) return call(pc, cast.toString(args[0])); + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMClearSession", 0, 1, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMCloseAllSessions.java b/source/java/src/org/lucee/extension/orm/functions/ORMCloseAllSessions.java new file mode 100644 index 00000000..eb403166 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMCloseAllSessions.java @@ -0,0 +1,46 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to close all open ORM sessions. + */ +public class ORMCloseAllSessions extends BIF { + public static String call(PageContext pc) throws PageException { + ORMUtil.getSession(pc).closeAll(pc); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + + if (args.length == 0) return call(pc); + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMCloseAllSessions", 0, 0, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMCloseSession.java b/source/java/src/org/lucee/extension/orm/functions/ORMCloseSession.java new file mode 100755 index 00000000..2a8cde66 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMCloseSession.java @@ -0,0 +1,58 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.loader.util.Util; +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to close the ORM session for the named datasource. + */ +public class ORMCloseSession extends BIF { + + public static String call(PageContext pc) throws PageException { + return call(pc, null); + } + + public static String call(PageContext pc, String datasource) throws PageException { + if (Util.isEmpty(datasource, true)) + ORMUtil.getSession(pc).close(pc); + else + ORMUtil.getSession(pc).close(pc, datasource.trim()); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 0) return call(pc); + if (args.length == 1) return call(pc, cast.toString(args[0])); + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMCloseSession", 0, 1, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMEvictCollection.java b/source/java/src/org/lucee/extension/orm/functions/ORMEvictCollection.java new file mode 100755 index 00000000..cf1434e7 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMEvictCollection.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.loader.util.Util; +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to evict a collection for the given entity/collection name. + */ +public class ORMEvictCollection extends BIF { + public static String call(PageContext pc, String entityName, String collectionName) throws PageException { + return call(pc, entityName, collectionName, null); + } + + public static String call(PageContext pc, String entityName, String collectionName, String primaryKey) + throws PageException { + ORMSession session = ORMUtil.getSession(pc); + if (Util.isEmpty(primaryKey)) + session.evictCollection(pc, entityName, collectionName); + else + session.evictCollection(pc, entityName, collectionName, primaryKey); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 2) return call(pc, cast.toString(args[0]), cast.toString(args[1])); + if (args.length == 3) return call(pc, cast.toString(args[0]), cast.toString(args[1]), cast.toString(args[2])); + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMEvictCollection", 2, 3, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMEvictEntity.java b/source/java/src/org/lucee/extension/orm/functions/ORMEvictEntity.java new file mode 100755 index 00000000..baa88e6a --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMEvictEntity.java @@ -0,0 +1,59 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.loader.util.Util; +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to evict an entity from the current ORM session. + */ +public class ORMEvictEntity extends BIF { + public static String call(PageContext pc, String entityName) throws PageException { + return call(pc, entityName, null); + } + + public static String call(PageContext pc, String entityName, String primaryKey) throws PageException { + ORMSession session = ORMUtil.getSession(pc); + if (Util.isEmpty(primaryKey)) + session.evictEntity(pc, entityName); + else + session.evictEntity(pc, entityName, primaryKey); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 1) return call(pc, cast.toString(args[0])); + if (args.length == 2) return call(pc, cast.toString(args[0]), cast.toString(args[1])); + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMEvictEntity", 1, 2, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMEvictQueries.java b/source/java/src/org/lucee/extension/orm/functions/ORMEvictQueries.java new file mode 100755 index 00000000..6c7dbcc8 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMEvictQueries.java @@ -0,0 +1,58 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to evict queries from the named query cache. + */ +public class ORMEvictQueries extends BIF { + public static String call(PageContext pc) throws PageException { + return call(pc, null, null); + } + + public static String call(PageContext pc, String cacheName) throws PageException { + return call(pc, cacheName, null); + } + + public static String call(PageContext pc, String cacheName, String datasource) throws PageException { + ORMUtil.getSession(pc).evictQueries(pc, cacheName, datasource); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 0) return call(pc); + if (args.length == 1) return call(pc, cast.toString(args[0])); + if (args.length == 2) return call(pc, cast.toString(args[0]), cast.toString(args[1])); + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMEvictQueries", 0, 2, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMExecuteQuery.java b/source/java/src/org/lucee/extension/orm/functions/ORMExecuteQuery.java new file mode 100755 index 00000000..53d7083e --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMExecuteQuery.java @@ -0,0 +1,121 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ExceptionUtil; +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import java.util.List; +import java.util.Map; + +import lucee.loader.util.Util; +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.type.Array; +import lucee.runtime.type.Struct; + +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to execute an HQL query through Hibernate ORM. + */ +public class ORMExecuteQuery extends BIF { + + public static Object call(PageContext pc, String hql) throws PageException { + return _call(pc, hql, null, false, null); + } + + public static Object call(PageContext pc, String hql, Object paramsOrUnique) throws PageException { + if (CommonUtil.isCastableToBoolean(paramsOrUnique)) { + return _call(pc, hql, null, CommonUtil.toBooleanValue(paramsOrUnique), null); + } + return _call(pc, hql, paramsOrUnique, false, null); + } + + public static Object call(PageContext pc, String hql, Object paramsOrUnique, Object uniqueOrQueryOptions) + throws PageException { + if (CommonUtil.isCastableToBoolean(paramsOrUnique)) { + return _call(pc, hql, null, CommonUtil.toBooleanValue(paramsOrUnique), + CommonUtil.toStruct(uniqueOrQueryOptions)); + } + if (CommonUtil.isCastableToBoolean(uniqueOrQueryOptions)) { + return _call(pc, hql, paramsOrUnique, CommonUtil.toBooleanValue(uniqueOrQueryOptions), null); + } + return _call(pc, hql, paramsOrUnique, false, CommonUtil.toStruct(uniqueOrQueryOptions)); + } + + public static Object call(PageContext pc, String hql, Object params, boolean isUnique, Struct queryOptions) + throws PageException { + return _call(pc, hql, params, isUnique, queryOptions); + } + + private static Object _call(PageContext pc, String hql, Object params, boolean unique, Struct queryOptions) + throws PageException { + ORMSession session = ORMUtil.getSession(pc); + String dsn = null; + if (queryOptions != null) + dsn = CommonUtil.toString(queryOptions.get(CommonUtil.createKey("datasource"), null), null); + if (Util.isEmpty(dsn, true)) + dsn = ORMUtil.getDefaultDataSource(pc).getName(); + + if (params == null) + return toCFML(session.executeQuery(pc, dsn, hql, CommonUtil.createArray(), unique, queryOptions)); + else if (CommonUtil.isStruct(params)) + return toCFML(session.executeQuery(pc, dsn, hql, CommonUtil.toStruct(params), unique, queryOptions)); + else if (CommonUtil.isArray(params)) + return toCFML(session.executeQuery(pc, dsn, hql, CommonUtil.toArray(params), unique, queryOptions)); + else if (CommonUtil.isCastableToStruct(params)) + return toCFML(session.executeQuery(pc, dsn, hql, CommonUtil.toStruct(params), unique, queryOptions)); + else if (CommonUtil.isCastableToArray(params)) + return toCFML(session.executeQuery(pc, dsn, hql, CommonUtil.toArray(params), unique, queryOptions)); + else + throw ExceptionUtil.createException("ORMExecuteQuery : cannot convert the params to an array or a struct"); + + } + + private static Object toCFML(Object obj) throws PageException { + if (obj instanceof List && !(obj instanceof Array)) + return CommonUtil.toArray(obj); + if (obj instanceof Map && !(obj instanceof Struct)) + return CommonUtil.toStruct(obj); + return obj; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 1) return call(pc, cast.toString(args[0])); + if (args.length == 2) return call(pc, cast.toString(args[0]), args[1]); + if (args.length == 3) return call(pc, cast.toString(args[0]), args[1], args[2]); + if (args.length == 4) { + Struct queryOptions = null; + if (args[1] != null){ queryOptions = cast.toStruct(args[1]); } + return call(pc, cast.toString(args[0]), args[1], cast.toBoolean(args[1],false), queryOptions); + } + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMExecuteQuery", 1, 4, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMFlush.java b/source/java/src/org/lucee/extension/orm/functions/ORMFlush.java new file mode 100755 index 00000000..d83e9915 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMFlush.java @@ -0,0 +1,57 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.loader.util.Util; +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.util.Cast; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to flush the current session. + */ +public class ORMFlush extends BIF { + public static String call(PageContext pc) throws PageException { + return call(pc, null); + } + + public static String call(PageContext pc, String datasource) throws PageException { + if (Util.isEmpty(datasource, true)) + ORMUtil.getSession(pc).flush(pc); + else + ORMUtil.getSession(pc).flush(pc, datasource.trim()); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + Cast cast = engine.getCastUtil(); + + if (args.length == 0) return call(pc); + if (args.length == 1) return call(pc, cast.toString(args[0])); + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMFlush", 0, 1, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMGetSession.java b/source/java/src/org/lucee/extension/orm/functions/ORMGetSession.java new file mode 100755 index 00000000..1fc4ad0a --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMGetSession.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.ext.function.BIF; + +public class ORMGetSession extends BIF { + + private static final long serialVersionUID = 349899413869883140L; + + public static Object call(PageContext pc) throws PageException { + return call(pc, null); + } + + public static Object call(PageContext pc, String datasource) throws PageException { + String dsn = ORMUtil.getDataSource(pc, datasource).getName(); + return ORMUtil.getSession(pc).getRawSession(dsn); + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + if (args.length == 0) + return call(pc); + return call(pc, CommonUtil.toString(args[0])); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMGetSessionFactory.java b/source/java/src/org/lucee/extension/orm/functions/ORMGetSessionFactory.java new file mode 100755 index 00000000..b1ae405e --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMGetSessionFactory.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.ext.function.BIF; + +public class ORMGetSessionFactory extends BIF { + + private static final long serialVersionUID = -8739815940242857106L; + + public static Object call(PageContext pc) throws PageException { + return call(pc, null); + } + + public static Object call(PageContext pc, String datasource) throws PageException { + String dsn = ORMUtil.getDataSource(pc, datasource).getName(); + return ORMUtil.getSession(pc).getRawSessionFactory(dsn); + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + if (args.length == 0) + return call(pc); + return call(pc, CommonUtil.toString(args[0])); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/functions/ORMReload.java b/source/java/src/org/lucee/extension/orm/functions/ORMReload.java new file mode 100755 index 00000000..65389b56 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/functions/ORMReload.java @@ -0,0 +1,59 @@ +/** + * + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + **/ +package org.lucee.extension.orm.functions; + +import org.lucee.extension.orm.hibernate.util.ORMUtil; + +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMConfiguration; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.ext.function.BIF; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.engine.CFMLEngine; + +/** + * CFML built-in function to flush the current session. + */ +public class ORMReload extends BIF { + public static String call(PageContext pc) throws PageException { + + // flush and close session + ORMSession session = ORMUtil.getSession(pc, false); + if (session != null) {// MUST do the same with all sesson using the same engine + ORMConfiguration config = session.getEngine().getConfiguration(pc); + if (config.autoManageSession()) { + session.flushAll(pc); + session.closeAll(pc); + } + } + pc.getApplicationContext().reinitORM(pc); + ORMUtil.resetEngine(pc, true); + return null; + } + + @Override + public Object invoke(PageContext pc, Object[] args) throws PageException { + CFMLEngine engine = CFMLEngineFactory.getInstance(); + + if (args.length == 0) return call(pc); + + throw engine.getExceptionUtil().createFunctionException(pc, "ORMReload", 0, 0, args.length); + } +} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/ColumnInfo.java b/source/java/src/org/lucee/extension/orm/hibernate/ColumnInfo.java index bd9adc14..49558e02 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/ColumnInfo.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/ColumnInfo.java @@ -2,93 +2,99 @@ public class ColumnInfo { - private String name; - private int type; - private String typeName; - private int size; - private boolean nullable; + private String name; + private int type; + private String typeName; + private int size; + private boolean nullable; - public ColumnInfo(String name, int type, String typeName, int size, boolean nullable) { + public ColumnInfo(String name, int type, String typeName, int size, boolean nullable) { - this.name = name; - this.type = type; - this.typeName = typeName; - this.size = size; - this.nullable = nullable; - } + this.name = name; + this.type = type; + this.typeName = typeName; + this.size = size; + this.nullable = nullable; + } - /** - * @return the name - */ - public String getName() { - return name; - } + /** + * @return the name + */ + public String getName() { + return name; + } - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } + /** + * @param name + * the name to set + */ + public void setName(String name) { + this.name = name; + } - /** - * @return the type - */ - public int getType() { - return type; - } + /** + * @return the type + */ + public int getType() { + return type; + } - /** - * @param type the type to set - */ - public void setType(int type) { - this.type = type; - } + /** + * @param type + * the type to set + */ + public void setType(int type) { + this.type = type; + } - /** - * @return the typeName - */ - public String getTypeName() { - return typeName; - } + /** + * @return the typeName + */ + public String getTypeName() { + return typeName; + } - /** - * @param typeName the typeName to set - */ - public void setTypeName(String typeName) { - this.typeName = typeName; - } + /** + * @param typeName + * the typeName to set + */ + public void setTypeName(String typeName) { + this.typeName = typeName; + } - /** - * @return the size - */ - public int getSize() { - return size; - } + /** + * @return the size + */ + public int getSize() { + return size; + } - /** - * @param size the size to set - */ - public void setSize(int size) { - this.size = size; - } + /** + * @param size + * the size to set + */ + public void setSize(int size) { + this.size = size; + } - /** - * @return the nullable - */ - public boolean isNullable() { - return nullable; - } + /** + * @return the nullable + */ + public boolean isNullable() { + return nullable; + } - /** - * @param nullable the nullable to set - */ - public void setNullable(boolean nullable) { - this.nullable = nullable; - } + /** + * @param nullable + * the nullable to set + */ + public void setNullable(boolean nullable) { + this.nullable = nullable; + } - @Override - public String toString() { - return "name:" + name + ";type:" + type + ";typeName:" + typeName + ";size:" + size + ";nullable:" + nullable + ";"; - } + @Override + public String toString() { + return "name:" + name + ";type:" + type + ";typeName:" + typeName + ";size:" + size + ";nullable:" + nullable + + ";"; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/CommonUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/CommonUtil.java deleted file mode 100644 index 0f5016c7..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/CommonUtil.java +++ /dev/null @@ -1,961 +0,0 @@ -package org.lucee.extension.orm.hibernate; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Serializable; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.nio.charset.Charset; -import java.sql.ResultSet; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.TimeZone; - -import org.hibernate.JDBCException; -import org.hibernate.exception.ConstraintViolationException; -import org.lucee.extension.orm.hibernate.util.XMLUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import lucee.commons.io.res.Resource; -import lucee.commons.lang.types.RefBoolean; -import lucee.loader.engine.CFMLEngineFactory; -import lucee.loader.util.Util; -import lucee.runtime.Component; -import lucee.runtime.Mapping; -import lucee.runtime.PageContext; -import lucee.runtime.component.Property; -import lucee.runtime.config.Config; -import lucee.runtime.db.DataSource; -import lucee.runtime.db.DatasourceConnection; -import lucee.runtime.db.SQL; -import lucee.runtime.db.SQLItem; -import lucee.runtime.exp.PageException; -import lucee.runtime.type.Array; -import lucee.runtime.type.Collection; -import lucee.runtime.type.Collection.Key; -import lucee.runtime.type.Query; -import lucee.runtime.type.Struct; -import lucee.runtime.type.dt.DateTime; -import lucee.runtime.type.scope.Argument; -import lucee.runtime.util.Cast; -import lucee.runtime.util.Creation; -import lucee.runtime.util.DBUtil; -import lucee.runtime.util.Decision; -import lucee.runtime.util.ORMUtil; -import lucee.runtime.util.Operation; - -public class CommonUtil { - - public static final Key ENTITY_NAME = CommonUtil.createKey("entityname"); - public static final Key FIELDTYPE = CommonUtil.createKey("fieldtype"); - public static final Key POST_INSERT = CommonUtil.createKey("postInsert"); - public static final Key POST_UPDATE = CommonUtil.createKey("postUpdate"); - public static final Key PRE_DELETE = CommonUtil.createKey("preDelete"); - public static final Key POST_DELETE = CommonUtil.createKey("postDelete"); - public static final Key PRE_LOAD = CommonUtil.createKey("preLoad"); - public static final Key POST_LOAD = CommonUtil.createKey("postLoad"); - public static final Key PRE_UPDATE = CommonUtil.createKey("preUpdate"); - public static final Key PRE_INSERT = CommonUtil.createKey("preInsert"); - public static final Key ON_FLUSH = CommonUtil.createKey("onFlush"); - public static final Key ON_AUTO_FLUSH = CommonUtil.createKey("onAutoFlush"); - public static final Key ON_CLEAR = CommonUtil.createKey("onClear"); - public static final Key ON_DELETE = CommonUtil.createKey("onDelete"); - public static final Key ON_DIRTY_CHECK = CommonUtil.createKey("onDirtyCheck"); - public static final Key ON_EVICT = CommonUtil.createKey("onEvict"); - - public static final Key INIT = CommonUtil.createKey("init"); - private static final short INSPECT_UNDEFINED = (short) 4; /* ConfigImpl.INSPECT_UNDEFINED */ - private static final Class[] ZEROC = new Class[] {}; - private static final Object[] ZEROO = new Object[] {}; - private static final Class[] GET_DSCONN = new Class[] { PageContext.class, DataSource.class, String.class, String.class, boolean.class }; - private static final Class[] REL_DSCONN = new Class[] { PageContext.class, DatasourceConnection.class, boolean.class }; - // private static final Class[] GET_CONN = new Class[] { PageContext.class, DataSource.class, - // String.class, String.class }; - // private static final Class[] REL_CONN = new Class[] { PageContext.class, - // DatasourceConnection.class }; - // releaseConnection(pageContext, dc); - private static Charset _charset; - - public static Charset _UTF8; - // public static Charset ISO88591; - public static Charset _UTF16BE; - public static Charset _UTF16LE; - - public static Charset getCharset() { - if (_charset == null) { - String strCharset = System.getProperty("file.encoding"); - if (strCharset == null || strCharset.equalsIgnoreCase("MacRoman")) strCharset = "cp1252"; - - if (strCharset.equalsIgnoreCase("utf-8")) _charset = UTF8(); - else _charset = toCharset(strCharset); - } - return _charset; - } - - public static Charset UTF8() { - if (_UTF8 == null) _UTF8 = toCharset("UTF-8"); - return _UTF8; - } - - private static Charset UTF16LE() { - if (_UTF16LE == null) _UTF16LE = toCharset("UTF-16LE"); - return _UTF16LE; - } - - private static Charset UTF16BE() { - if (_UTF16BE == null) _UTF16BE = toCharset("UTF-16BE"); - return _UTF16BE; - } - - private static Charset toCharset(String charset) { - try { - return CFMLEngineFactory.getInstance().getCastUtil().toCharset(charset); - } - catch (PageException pe) { - throw CFMLEngineFactory.getInstance().getExceptionUtil().createPageRuntimeException(pe); - } - } - - private static Cast caster; - private static Decision decision; - private static Creation creator; - private static Operation op; - private static lucee.runtime.util.XMLUtil xml; - private static lucee.runtime.util.ListUtil list; - private static DBUtil db; - private static ORMUtil orm; - // private static Method mGetDataSourceManager; - // private static Method mGetConnection; - // private static Method mReleaseConnection; - - private static Method mGetDatasourceConnection; - private static Method mReleaseDatasourceConnection; - - public static Object castTo(PageContext pc, Class trgClass, Object obj) throws PageException { - return caster().castTo(pc, trgClass, obj); - } - - public static Array toArray(Object obj) throws PageException { - return caster().toArray(obj); - } - - public static Array toArray(Object obj, Array defaultValue) { - return caster().toArray(obj, defaultValue); - } - - public static Boolean toBoolean(String str) throws PageException { - return caster().toBoolean(str); - } - - public static Boolean toBoolean(String str, Boolean defaultValue) { - return caster().toBoolean(str, defaultValue); - } - - public static Boolean toBoolean(Object obj) throws PageException { - return caster().toBoolean(obj); - } - - public static Boolean toBoolean(Object obj, Boolean defaultValue) { - return caster().toBoolean(obj, defaultValue); - } - - public static Boolean toBooleanValue(String str) throws PageException { - return caster().toBooleanValue(str); - } - - public static Boolean toBooleanValue(String str, Boolean defaultValue) { - return caster().toBooleanValue(str, defaultValue); - } - - public static boolean toBooleanValue(Object obj) throws PageException { - return caster().toBooleanValue(obj); - } - - public static boolean toBooleanValue(Object obj, boolean defaultValue) { - return caster().toBooleanValue(obj, defaultValue); - } - - public static Component toComponent(Object obj) throws PageException { - return caster().toComponent(obj); - } - - public static Component toComponent(Object obj, Component defaultValue) { - return caster().toComponent(obj, defaultValue); - } - - public static Object toList(String[] arr, String delimiter) { - return list().toList(arr, delimiter); - } - - public static String toString(Object obj, String defaultValue) { - return caster().toString(obj, defaultValue); - } - - public static String toString(Object obj) throws PageException { - return caster().toString(obj); - } - - public static String toString(boolean b) { - return caster().toString(b); - } - - public static String toString(double d) { - return caster().toString(d); - } - - public static String toString(int i) { - return caster().toString(i); - } - - public static String toString(long l) { - return caster().toString(l); - } - - /** - * reads String data from File - * - * @param file - * @param charset - * @return readed string - * @throws IOException - */ - public static String toString(Resource file, Charset charset) throws IOException { - Reader r = null; - try { - r = getReader(file, charset); - String str = toString(r); - return str; - } - finally { - closeEL(r); - } - } - - public static String toString(Reader reader) throws IOException { - StringWriter sw = new StringWriter(512); - copy(toBufferedReader(reader), sw); - sw.close(); - return sw.toString(); - } - - public static BufferedReader toBufferedReader(Reader r) { - if (r instanceof BufferedReader) return (BufferedReader) r; - return new BufferedReader(r); - } - - private static final void copy(Reader r, Writer w) throws IOException { - copy(r, w, 0xffff); - } - - private static final void copy(Reader r, Writer w, int blockSize) throws IOException { - char[] buffer = new char[blockSize]; - int len; - - while ((len = r.read(buffer)) != -1) - w.write(buffer, 0, len); - } - - public static Reader getReader(Resource res, Charset charset) throws IOException { - InputStream is = null; - try { - is = res.getInputStream(); - boolean markSupported = is.markSupported(); - if (markSupported) is.mark(4); - int first = is.read(); - int second = is.read(); - // FE FF UTF-16, big-endian - if (first == 0xFE && second == 0xFF) { - return _getReader(is, UTF16BE()); - } - // FF FE UTF-16, little-endian - if (first == 0xFF && second == 0xFE) { - return _getReader(is, UTF16LE()); - } - - int third = is.read(); - // EF BB BF UTF-8 - if (first == 0xEF && second == 0xBB && third == 0xBF) { - // is.reset(); - return _getReader(is, UTF8()); - } - - if (markSupported) { - is.reset(); - return _getReader(is, charset); - } - } - catch (IOException ioe) { - closeEL(is); - throw ioe; - } - - // when mark not supported return new reader - closeEL(is); - is = null; - try { - is = res.getInputStream(); - } - catch (IOException ioe) { - closeEL(is); - throw ioe; - } - return _getReader(is, charset); - } - - private static Reader _getReader(InputStream is, Charset cs) { - if (cs == null) cs = getCharset(); - return new BufferedReader(new InputStreamReader(is, cs)); - } - - public static String[] toStringArray(String list, String delimiter) { - return list().toStringArray(list().toArray(list, delimiter), ""); // TODO better - } - - public static Float toFloat(Object obj) throws PageException { - return caster().toFloat(obj); - } - - public static Float toFloat(Object obj, Float defaultValue) { - return caster().toFloat(obj, defaultValue); - } - - public static float toFloatValue(Object obj) throws PageException { - return caster().toFloatValue(obj); - } - - public static float toFloatValue(Object obj, float defaultValue) { - return caster().toFloatValue(obj, defaultValue); - } - - public static Double toDouble(Object obj) throws PageException { - return caster().toDouble(obj); - } - - public static Double toDouble(Object obj, Double defaultValue) { - return caster().toDouble(obj, defaultValue); - } - - public static double toDoubleValue(Object obj) throws PageException { - return caster().toDoubleValue(obj); - } - - public static double toDoubleValue(Object obj, double defaultValue) { - return caster().toDoubleValue(obj, defaultValue); - } - - public static BigDecimal toBigDecimal(Object obj) throws PageException { - return caster().toBigDecimal(obj); - } - - public static BigDecimal toBigDecimal(Object obj, BigDecimal defaultValue) { - return caster().toBigDecimal(obj, defaultValue); - } - - public static Short toShort(Object obj) throws PageException { - return caster().toShort(obj); - } - - public static Short toShort(Object obj, Short defaultValue) { - return caster().toShort(obj, defaultValue); - } - - public static double toShortValue(Object obj) throws PageException { - return caster().toShortValue(obj); - } - - public static double toShortValue(Object obj, short defaultValue) { - return caster().toShortValue(obj, defaultValue); - } - - public static Integer toInteger(Object obj) throws PageException { - return caster().toInteger(obj); - } - - public static Integer toInteger(Object obj, Integer defaultValue) { - return caster().toInteger(obj, defaultValue); - } - - public static Long toLong(Object obj) throws PageException { - return caster().toLong(obj); - } - - public static Long toLong(Object obj, Long defaultValue) { - return caster().toLong(obj, defaultValue); - } - - public static long toLongValue(Object obj) throws PageException { - return caster().toLongValue(obj); - } - - public static long toLongValue(Object obj, long defaultValue) { - return caster().toLongValue(obj, defaultValue); - } - - public static byte[] toBinary(Object obj) throws PageException { - return caster().toBinary(obj); - } - - public static byte[] toBinary(Object obj, byte[] defaultValue) { - return caster().toBinary(obj, defaultValue); - } - - public static int toIntValue(Object obj) throws PageException { - return caster().toIntValue(obj); - } - - public static int toIntValue(Object obj, int defaultValue) { - return caster().toIntValue(obj, defaultValue); - } - - public static Array toArray(Argument arg) { - Array trg = createArray(); - int[] keys = arg.intKeys(); - for (int i = 0; i < keys.length; i++) { - trg.setEL(keys[i], arg.get(keys[i], null)); - } - return trg; - } - - public static PageException toPageException(Throwable t) { - PageException pe = caster().toPageException(t); - if (t instanceof org.hibernate.HibernateException) { - org.hibernate.HibernateException he = (org.hibernate.HibernateException) t; - Throwable cause = he.getCause(); - if (cause != null) { - pe = caster().toPageException(cause); - ExceptionUtil.setAdditional(pe, CommonUtil.createKey("hibernate exception"), t); - } - } - if (t instanceof JDBCException) { - JDBCException je = (JDBCException) t; - ExceptionUtil.setAdditional(pe, CommonUtil.createKey("sql"), je.getSQL()); - } - if (t instanceof ConstraintViolationException) { - ConstraintViolationException cve = (ConstraintViolationException) t; - if (!Util.isEmpty(cve.getConstraintName())) { - ExceptionUtil.setAdditional(pe, CommonUtil.createKey("constraint name"), cve.getConstraintName()); - } - } - return pe; - } - - public static Serializable toSerializable(Object obj) throws PageException { - return caster().toSerializable(obj); - } - - public static Serializable toSerializable(Object obj, Serializable defaultValue) { - return caster().toSerializable(obj, defaultValue); - } - - public static Struct toStruct(Object obj) throws PageException { - return caster().toStruct(obj); - } - - public static Struct toStruct(Object obj, Struct defaultValue) { - return caster().toStruct(obj, defaultValue); - } - - public static SQLItem toSQLItem(Object value, int type) { - return db().toSQLItem(value, type); - } - - public static SQL toSQL(String sql, SQLItem[] items) { - return db().toSQL(sql, items); - } - - public static Object toSqlType(SQLItem item) throws PageException { - return db().toSqlType(item); - } - - public static Object[] toNativeArray(Object obj) throws PageException { - return caster().toNativeArray(obj); - } - - public static Key toKey(String str) { - return caster().toKey(str); - } - - public static String toTypeName(Object obj) { - return caster().toTypeName(obj); - } - - public static Node toXML(Object obj) throws PageException { - return XMLUtil.toNode(obj); - } - /* - * public static Node toXML(Object obj, Node defaultValue) { return - * caster().toXML(obj,defaultValue); } - */ - - public static Document toDocument(Resource res, Charset cs) throws PageException { - return XMLUtil.parse(XMLUtil.toInputSource(res, cs), null, false); - } - - public static boolean isArray(Object obj) { - return decision().isArray(obj); - } - - public static boolean isStruct(Object obj) { - return decision().isStruct(obj); - } - - public static boolean isAnyType(String type) { - return decision().isAnyType(type); - } - - public static Array createArray() { - return creator().createArray(); - } - - public static DateTime createDateTime(long time) { - return creator().createDateTime(time); - } - - public static Property createProperty(String name, String type) { - return creator().createProperty(name, type); - } - - public static Struct createStruct() { - return creator().createStruct(); - } - - public static Collection.Key createKey(String key) { - return creator().createKey(key); - } - - public static Query createQuery(Collection.Key[] columns, int rows, String name) throws PageException { - return creator().createQuery(columns, rows, name); - } - - public static Query createQuery(Collection.Key[] columns, String[] types, int rows, String name) throws PageException { - return creator().createQuery(columns, types, rows, name); - } - - public static Query createQuery(Array names, Array types, int rows, String name) throws PageException { - Collection.Key[] knames = new Collection.Key[names.size()]; - String[] ktypes = new String[types.size()]; - for (int i = names.size() - 1; i >= 0; i--) { - knames[i] = caster().toKey(names.getE(i + 1)); - ktypes[i] = caster().toString(types.getE(i + 1)); - } - return creator().createQuery(knames, ktypes, rows, name); - } - - public static RefBoolean createRefBoolean() { - return new RefBooleanImpl(); - } - - public static Key[] keys(Collection coll) { - if (coll == null) return new Key[0]; - Iterator it = coll.keyIterator(); - List rtn = new ArrayList(); - if (it != null) while (it.hasNext()) { - rtn.add(it.next()); - } - return rtn.toArray(new Key[rtn.size()]); - } - - private static Creation creator() { - if (creator == null) creator = CFMLEngineFactory.getInstance().getCreationUtil(); - return creator; - } - - private static Decision decision() { - if (decision == null) decision = CFMLEngineFactory.getInstance().getDecisionUtil(); - return decision; - } - - private static Cast caster() { - if (caster == null) caster = CFMLEngineFactory.getInstance().getCastUtil(); - return caster; - } - - private static Operation op() { - if (op == null) op = CFMLEngineFactory.getInstance().getOperatonUtil(); - return op; - } - - private static lucee.runtime.util.ListUtil list() { - if (list == null) list = CFMLEngineFactory.getInstance().getListUtil(); - return list; - } - - private static ORMUtil orm() { - if (orm == null) orm = CFMLEngineFactory.getInstance().getORMUtil(); - return orm; - } - - private static DBUtil db() { - if (db == null) db = CFMLEngineFactory.getInstance().getDBUtil(); - return db; - } - - /** - * represents a SQL Statement with his defined arguments for a prepared statement - */ - static class SQLImpl implements SQL { - - private String strSQL; - - /** - * Constructor only with SQL String - * - * @param strSQL SQL String - */ - public SQLImpl(String strSQL) { - this.strSQL = strSQL; - } - - public void addItems(SQLItem item) { - - } - - @Override - public SQLItem[] getItems() { - return new SQLItem[0]; - } - - @Override - public int getPosition() { - return 0; - } - - @Override - public void setPosition(int position) { - } - - @Override - public String getSQLString() { - return strSQL; - } - - @Override - public void setSQLString(String strSQL) { - this.strSQL = strSQL; - } - - @Override - public String toString() { - return strSQL; - } - - @Override - public String toHashString() { - return strSQL; - } - } - - /** - * Integer Type that can be modified - */ - public static final class RefBooleanImpl implements RefBoolean {// MUST add interface Castable - - private boolean value; - - public RefBooleanImpl() { - } - - /** - * @param value - */ - public RefBooleanImpl(boolean value) { - this.value = value; - } - - /** - * @param value - */ - @Override - public void setValue(boolean value) { - this.value = value; - } - - /** - * @return returns value as Boolean Object - */ - @Override - public Boolean toBoolean() { - return value ? Boolean.TRUE : Boolean.FALSE; - } - - /** - * @return returns value as boolean value - */ - @Override - public boolean toBooleanValue() { - return value; - } - - @Override - public String toString() { - return value ? "true" : "false"; - } - } - - public static DataSource getDataSource(PageContext pc, String dsn, DataSource defaultValue) { - if (Util.isEmpty(dsn, true) || dsn.equals("__default__")) return orm().getDefaultDataSource(pc, defaultValue); - return pc.getDataSource(dsn.trim(), defaultValue); - } - - public static DataSource getDataSource(PageContext pc, String name) throws PageException { - if (Util.isEmpty(name, true)) return orm().getDefaultDataSource(pc); - return pc.getDataSource(name); - } - - /* - * private static Object getDatasourceManager(PageContext pc) throws PageException { try { if - * (mGetDataSourceManager == null || pc.getClass() != mGetDataSourceManager.getDeclaringClass()) - * mGetDataSourceManager = pc.getClass().getMethod("getDataSourceManager", ZEROC); return - * mGetDataSourceManager.invoke(pc, ZEROO); } catch (Exception e) { throw - * CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); } } - */ - - public static DatasourceConnection getDatasourceConnection(PageContext pc, DataSource ds, String user, String pass, boolean transactionSensitive) throws PageException { - if (transactionSensitive) { - return pc.getDataSourceManager().getConnection(pc, ds, user, pass); - - } - - DBUtil dbutil = db(); - try { - if (mGetDatasourceConnection == null || dbutil.getClass() != mGetDatasourceConnection.getDeclaringClass()) { - mGetDatasourceConnection = dbutil.getClass().getMethod("getDatasourceConnection", GET_DSCONN); - } - return (DatasourceConnection) mGetDatasourceConnection.invoke(dbutil, new Object[] { pc, ds, user, pass, false }); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - /* - * Object manager = getDatasourceManager(pc); try { if (mGetConnection == null || manager.getClass() - * != mGetConnection.getDeclaringClass()) { mGetConnection = - * manager.getClass().getMethod("getConnection", GET_CONN); } return (DatasourceConnection) - * mGetConnection.invoke(manager, new Object[] { pc, ds, user, pass }); } catch (Exception e) { - * throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); } - */ - } - - public static void releaseDatasourceConnection(PageContext pc, DatasourceConnection dc, boolean transactionSensitive) throws PageException { - // print.ds("rel:" + transactionSensitive); - if (transactionSensitive) { - pc.getDataSourceManager().releaseConnection(pc, dc); - return; - } - - DBUtil dbutil = db(); - try { - if (mReleaseDatasourceConnection == null || dbutil.getClass() != mReleaseDatasourceConnection.getDeclaringClass()) { - mReleaseDatasourceConnection = dbutil.getClass().getMethod("releaseDatasourceConnection", REL_DSCONN); - } - mReleaseDatasourceConnection.invoke(dbutil, new Object[] { pc, dc, false }); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - - /* - * Object manager = getDatasourceManager(pc); try { if (mReleaseConnection == null || - * manager.getClass() != mReleaseConnection.getDeclaringClass()) { mReleaseConnection = - * manager.getClass().getMethod("releaseConnection", REL_CONN); } mReleaseConnection.invoke(manager, - * new Object[] { pc, dc }); } catch (Exception e) { throw - * CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); } - */ - } - - public static Mapping createMapping(Config config, String virtual, String physical) { - return creator().createMapping(config, virtual, physical, null, INSPECT_UNDEFINED, true, false, false, false, true, true, null, -1, -1); - } - - public static String last(String list, String delimiter) { - return list().last(list, delimiter, true); - } - - public static int listFindNoCaseIgnoreEmpty(String list, String value, char delimiter) { - return list().findNoCaseIgnoreEmpty(list, value, delimiter); - } - - public static String[] trimItems(String[] arr) { - for (int i = 0; i < arr.length; i++) { - arr[i] = arr[i].trim(); - } - return arr; - } - - public static Document getDocument(Node node) { - return XMLUtil.getDocument(node); - } - - public static Document newDocument() throws PageException { - return XMLUtil.newDocument(); - } - - public static void setFirst(Node parent, Node node) { - XMLUtil.setFirst(parent, node); - } - - public static Property[] getProperties(Component c, boolean onlyPeristent, boolean includeBaseProperties, boolean preferBaseProperties, boolean inheritedMappedSuperClassOnly) { - return c.getProperties(onlyPeristent, includeBaseProperties, preferBaseProperties, inheritedMappedSuperClassOnly); - } - - public static void write(Resource res, String string, Charset cs, boolean append) throws IOException { - if (cs == null) cs = getCharset(); - - Writer writer = null; - try { - writer = getWriter(res, cs, append); - writer.write(string); - } - finally { - closeEL(writer); - } - } - - public static Writer getWriter(Resource res, Charset charset, boolean append) throws IOException { - OutputStream os = null; - try { - os = res.getOutputStream(append); - } - catch (IOException ioe) { - closeEL(os); - throw ioe; - } - return getWriter(os, charset); - } - - public static Writer getWriter(OutputStream os, Charset cs) { - if (cs == null) cs = getCharset(); - return new BufferedWriter(new OutputStreamWriter(os, getCharset())); - } - - public static BufferedReader toBufferedReader(Resource res, Charset charset) throws IOException { - return toBufferedReader(getReader(res, (Charset) null)); - } - - public static boolean equalsComplexEL(Object left, Object right) { - return op().equalsComplexEL(left, right, false, true); - } - - public static PageContext pc() { - return CFMLEngineFactory.getInstance().getThreadPageContext(); - } - - public static Config config() { - return pc().getConfig(); - } - - public static void closeEL(OutputStream os) { - if (os != null) { - try { - os.close(); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } - } - - public static void closeEL(Writer w) { - if (w != null) { - try { - w.close(); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } - } - - public static void closeEL(ResultSet rs) { - if (rs != null) { - try { - rs.close(); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } - } - - public static void closeEL(InputStream is) { - try { - if (is != null) is.close(); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } - - public static void closeEL(Reader r) { - try { - if (r != null) r.close(); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } - - public static boolean isRelated(Property property) { - return orm().isRelated(property); - } - - public static Object convertToSimpleMap(String paramsStr) { - return orm().convertToSimpleMap(paramsStr); - } - - public static String getDataSourceName(PageContext pc, Component cfc) throws PageException { - return orm().getDataSourceName(pc, cfc); - } - - public static DataSource getDataSource(PageContext pc, Component cfc) throws PageException { - return orm().getDataSource(pc, cfc); - } - - public static boolean equals(Component l, Component r) { - // TODO Auto-generated method stub - return orm().equals(l, r); - } - - public static DataSource getDefaultDataSource(PageContext pc) throws PageException { - return orm().getDefaultDataSource(pc); - } - - public static Object getPropertyValue(Component cfc, String name, Object defaultValue) { - return orm().getPropertyValue(cfc, name, defaultValue); - } - - public static String toString(Node node, boolean omitXMLDecl, boolean indent, String publicId, String systemId, String encoding) throws PageException { - return XMLUtil.toString(node, omitXMLDecl, indent, publicId, systemId, encoding); - } - - public static Locale toLocale(String strLocale) throws PageException { - return caster().toLocale(strLocale); - } - - public static TimeZone toTimeZone(Object value, Object obj) throws PageException { - return caster().toTimeZone(obj); - } - - public static Character toCharacter(Object value) throws PageException { - return caster().toCharacter(value); - } - - public static DateTime toDate(Object value, TimeZone timeZone) throws PageException { - return caster().toDate(value, timeZone); - } - - public static Calendar toCalendar(DateTime date, TimeZone timeZone, Locale locale) { - return caster().toCalendar(date.getTime(), timeZone, locale); - } -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/Dialect.java b/source/java/src/org/lucee/extension/orm/hibernate/Dialect.java index 97b736b6..dc7bf948 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/Dialect.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/Dialect.java @@ -6,169 +6,194 @@ import java.util.Iterator; import org.apache.felix.framework.BundleWiringImpl.BundleClassLoader; +import org.lucee.extension.orm.hibernate.util.CommonUtil; import org.osgi.framework.Bundle; -import lucee.loader.engine.CFMLEngineFactory; import lucee.loader.util.Util; import lucee.runtime.db.DataSource; import lucee.runtime.type.Struct; -import lucee.runtime.util.ListUtil; +/** + * Hibernate Dialect manager + */ public class Dialect { - private static Struct dialects = CommonUtil.createStruct(); + private static Struct dialects = CommonUtil.createStruct(); - static { + static { - try { - BundleClassLoader bcl = (BundleClassLoader) org.hibernate.dialect.SybaseDialect.class.getClassLoader(); - Bundle b = bcl.getBundle(); + try { + BundleClassLoader bcl = (BundleClassLoader) org.hibernate.dialect.SybaseDialect.class.getClassLoader(); + Bundle b = bcl.getBundle(); - // List all XML files in the OSGI-INF directory and below - ListUtil util = CFMLEngineFactory.getInstance().getListUtil(); - Enumeration e = b.findEntries("org/hibernate/dialect", "*.class", true); - String path; - while (e.hasMoreElements()) { - try { - path = e.nextElement().getPath(); - if (path.startsWith("/")) path = path.substring(1); - else if (path.startsWith("\\")) path = path.substring(1); - if (path.endsWith(".class")) path = path.substring(0, path.length() - 6); - path = path.replace('/', '.'); - path = path.replace('\\', '.'); - String name; - Class clazz = bcl.loadClass(path); - if (org.hibernate.dialect.Dialect.class.isAssignableFrom(clazz) && !Modifier.isAbstract(clazz.getModifiers())) { - dialects.setEL(CommonUtil.createKey(path), path); - dialects.setEL(CommonUtil.createKey(CommonUtil.last(path, ".")), path); - name = CommonUtil.last(path, "."); - dialects.setEL(CommonUtil.createKey(name), path); - if (name.endsWith("Dialect")) { - name = name.substring(0, name.length() - 7); - dialects.setEL(CommonUtil.createKey(name), path); - } + // List all XML files in the OSGI-INF directory and below + Enumeration e = b.findEntries("org/hibernate/dialect", "*.class", true); + String path; + while (e.hasMoreElements()) { + try { + path = e.nextElement().getPath(); + if (path.startsWith("/")) + path = path.substring(1); + else if (path.startsWith("\\")) + path = path.substring(1); + if (path.endsWith(".class")) + path = path.substring(0, path.length() - 6); + path = path.replace('/', '.'); + path = path.replace('\\', '.'); + String name; + Class clazz = bcl.loadClass(path); + if (org.hibernate.dialect.Dialect.class.isAssignableFrom(clazz) + && !Modifier.isAbstract(clazz.getModifiers())) { + dialects.setEL(CommonUtil.createKey(path), path); + dialects.setEL(CommonUtil.createKey(CommonUtil.last(path, ".")), path); + name = CommonUtil.last(path, "."); + dialects.setEL(CommonUtil.createKey(name), path); + if (name.endsWith("Dialect")) { + name = name.substring(0, name.length() - 7); + dialects.setEL(CommonUtil.createKey(name), path); + } - // print.e("dialects.setEL(\"" + name + "\",\"" + path + "\");"); - } - } - catch (Exception exx) { - exx.printStackTrace(); - } - } - } - catch (Exception ex) { - ex.printStackTrace(); - } - dialects.setEL("CUBRID", "org.hibernate.dialect.CUBRIDDialect"); - dialects.setEL("Cache71", "org.hibernate.dialect.Cache71Dialect"); - dialects.setEL("CockroachDB192", "org.hibernate.dialect.CockroachDB192Dialect"); - dialects.setEL("CockroachDB201", "org.hibernate.dialect.CockroachDB201Dialect"); - dialects.setEL("DB2390", "org.hibernate.dialect.DB2390Dialect"); - dialects.setEL("DB2390V8", "org.hibernate.dialect.DB2390V8Dialect"); - dialects.setEL("DB2400", "org.hibernate.dialect.DB2400Dialect"); - dialects.setEL("DB2400V7R3", "org.hibernate.dialect.DB2400V7R3Dialect"); - dialects.setEL("DB297", "org.hibernate.dialect.DB297Dialect"); - dialects.setEL("DB2", "org.hibernate.dialect.DB2Dialect"); - dialects.setEL("DataDirectOracle9", "org.hibernate.dialect.DataDirectOracle9Dialect"); - dialects.setEL("Derby", "org.hibernate.dialect.DerbyDialect"); - dialects.setEL("DerbyTenFive", "org.hibernate.dialect.DerbyTenFiveDialect"); - dialects.setEL("DerbyTenSeven", "org.hibernate.dialect.DerbyTenSevenDialect"); - dialects.setEL("DerbyTenSix", "org.hibernate.dialect.DerbyTenSixDialect"); - dialects.setEL("Firebird", "org.hibernate.dialect.FirebirdDialect"); - dialects.setEL("FrontBase", "org.hibernate.dialect.FrontBaseDialect"); - dialects.setEL("H2", "org.hibernate.dialect.H2Dialect"); - dialects.setEL("HANACloudColumnStore", "org.hibernate.dialect.HANACloudColumnStoreDialect"); - dialects.setEL("HANAColumnStore", "org.hibernate.dialect.HANAColumnStoreDialect"); - dialects.setEL("HANARowStore", "org.hibernate.dialect.HANARowStoreDialect"); - dialects.setEL("HSQL", "org.hibernate.dialect.HSQLDialect"); - dialects.setEL("Informix10", "org.hibernate.dialect.Informix10Dialect"); - dialects.setEL("Informix", "org.hibernate.dialect.InformixDialect"); - dialects.setEL("Ingres10", "org.hibernate.dialect.Ingres10Dialect"); - dialects.setEL("Ingres9", "org.hibernate.dialect.Ingres9Dialect"); - dialects.setEL("Ingres", "org.hibernate.dialect.IngresDialect"); - dialects.setEL("Interbase", "org.hibernate.dialect.InterbaseDialect"); - dialects.setEL("JDataStore", "org.hibernate.dialect.JDataStoreDialect"); - dialects.setEL("MariaDB102", "org.hibernate.dialect.MariaDB102Dialect"); - dialects.setEL("MariaDB103", "org.hibernate.dialect.MariaDB103Dialect"); - dialects.setEL("MariaDB10", "org.hibernate.dialect.MariaDB10Dialect"); - dialects.setEL("MariaDB53", "org.hibernate.dialect.MariaDB53Dialect"); - dialects.setEL("MariaDB", "org.hibernate.dialect.MariaDBDialect"); - dialects.setEL("Mckoi", "org.hibernate.dialect.MckoiDialect"); - dialects.setEL("MimerSQL", "org.hibernate.dialect.MimerSQLDialect"); - dialects.setEL("MySQL55", "org.hibernate.dialect.MySQL55Dialect"); - dialects.setEL("MySQL57", "org.hibernate.dialect.MySQL57Dialect"); - dialects.setEL("MySQL57InnoDB", "org.hibernate.dialect.MySQL57InnoDBDialect"); - dialects.setEL("MySQL5", "org.hibernate.dialect.MySQL5Dialect"); - dialects.setEL("MySQL5InnoDB", "org.hibernate.dialect.MySQL5InnoDBDialect"); - dialects.setEL("MySQL8", "org.hibernate.dialect.MySQL8Dialect"); - dialects.setEL("MySQL", "org.hibernate.dialect.MySQL8Dialect"); - dialects.setEL("MySQLInnoDB", "org.hibernate.dialect.MySQLInnoDBDialect"); - dialects.setEL("MySQLMyISAM", "org.hibernate.dialect.MySQLMyISAMDialect"); - dialects.setEL("Oracle10g", "org.hibernate.dialect.Oracle10gDialect"); - dialects.setEL("Oracle12c", "org.hibernate.dialect.Oracle12cDialect"); - dialects.setEL("Oracle8i", "org.hibernate.dialect.Oracle8iDialect"); - dialects.setEL("Oracle9", "org.hibernate.dialect.Oracle9Dialect"); - dialects.setEL("Oracle9i", "org.hibernate.dialect.Oracle9iDialect"); - dialects.setEL("Oracle", "org.hibernate.dialect.OracleDialect"); - dialects.setEL("Pointbase", "org.hibernate.dialect.PointbaseDialect"); - dialects.setEL("PostgreSQL10", "org.hibernate.dialect.PostgreSQL10Dialect"); - dialects.setEL("PostgreSQL81", "org.hibernate.dialect.PostgreSQL81Dialect"); - dialects.setEL("PostgreSQL82", "org.hibernate.dialect.PostgreSQL82Dialect"); - dialects.setEL("PostgreSQL91", "org.hibernate.dialect.PostgreSQL91Dialect"); - dialects.setEL("PostgreSQL92", "org.hibernate.dialect.PostgreSQL92Dialect"); - dialects.setEL("PostgreSQL93", "org.hibernate.dialect.PostgreSQL93Dialect"); - dialects.setEL("PostgreSQL94", "org.hibernate.dialect.PostgreSQL94Dialect"); - dialects.setEL("PostgreSQL95", "org.hibernate.dialect.PostgreSQL95Dialect"); - dialects.setEL("PostgreSQL9", "org.hibernate.dialect.PostgreSQL9Dialect"); - dialects.setEL("PostgreSQL", "org.hibernate.dialect.PostgreSQLDialect"); - dialects.setEL("PostgresPlus", "org.hibernate.dialect.PostgresPlusDialect"); - dialects.setEL("Progress", "org.hibernate.dialect.ProgressDialect"); - dialects.setEL("RDMSOS2200", "org.hibernate.dialect.RDMSOS2200Dialect"); - dialects.setEL("SAPDB", "org.hibernate.dialect.SAPDBDialect"); - dialects.setEL("SQLServer2005", "org.hibernate.dialect.SQLServer2005Dialect"); - dialects.setEL("SQLServer2008", "org.hibernate.dialect.SQLServer2008Dialect"); - dialects.setEL("SQLServer2012", "org.hibernate.dialect.SQLServer2012Dialect"); - dialects.setEL("SQLServer", "org.hibernate.dialect.SQLServerDialect"); - dialects.setEL("Sybase11", "org.hibernate.dialect.Sybase11Dialect"); - dialects.setEL("SybaseASE157", "org.hibernate.dialect.SybaseASE157Dialect"); - dialects.setEL("SybaseASE15", "org.hibernate.dialect.SybaseASE15Dialect"); - dialects.setEL("SybaseAnywhere", "org.hibernate.dialect.SybaseAnywhereDialect"); - dialects.setEL("Sybase", "org.hibernate.dialect.SybaseDialect"); - dialects.setEL("Teradata14", "org.hibernate.dialect.Teradata14Dialect"); - dialects.setEL("Teradata", "org.hibernate.dialect.TeradataDialect"); - dialects.setEL("TimesTen", "org.hibernate.dialect.TimesTenDialect"); + // print.e("dialects.setEL(\"" + name + "\",\"" + path + "\");"); + } + } catch (Exception exx) { + exx.printStackTrace(); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } - } + dialects.setEL(CommonUtil.createKey("CUBRID"), "org.hibernate.dialect.CUBRIDDialect"); + dialects.setEL(CommonUtil.createKey("Cache71"), "org.hibernate.dialect.Cache71Dialect"); + dialects.setEL(CommonUtil.createKey("CockroachDB192"), "org.hibernate.dialect.CockroachDB192Dialect"); + dialects.setEL(CommonUtil.createKey("CockroachDB201"), "org.hibernate.dialect.CockroachDB201Dialect"); + dialects.setEL(CommonUtil.createKey("DB2390"), "org.hibernate.dialect.DB2390Dialect"); + dialects.setEL(CommonUtil.createKey("DB2390V8"), "org.hibernate.dialect.DB2390V8Dialect"); + dialects.setEL(CommonUtil.createKey("DB2400"), "org.hibernate.dialect.DB2400Dialect"); + dialects.setEL(CommonUtil.createKey("DB2400V7R3"), "org.hibernate.dialect.DB2400V7R3Dialect"); + dialects.setEL(CommonUtil.createKey("DB297"), "org.hibernate.dialect.DB297Dialect"); + dialects.setEL(CommonUtil.createKey("DB2"), "org.hibernate.dialect.DB2Dialect"); + dialects.setEL(CommonUtil.createKey("DataDirectOracle9"), "org.hibernate.dialect.DataDirectOracle9Dialect"); + dialects.setEL(CommonUtil.createKey("Derby"), "org.hibernate.dialect.DerbyDialect"); + dialects.setEL(CommonUtil.createKey("DerbyTenFive"), "org.hibernate.dialect.DerbyTenFiveDialect"); + dialects.setEL(CommonUtil.createKey("DerbyTenSeven"), "org.hibernate.dialect.DerbyTenSevenDialect"); + dialects.setEL(CommonUtil.createKey("DerbyTenSix"), "org.hibernate.dialect.DerbyTenSixDialect"); + dialects.setEL(CommonUtil.createKey("Firebird"), "org.hibernate.dialect.FirebirdDialect"); + dialects.setEL(CommonUtil.createKey("FrontBase"), "org.hibernate.dialect.FrontBaseDialect"); + dialects.setEL(CommonUtil.createKey("H2"), "org.hibernate.dialect.H2Dialect"); + dialects.setEL(CommonUtil.createKey("HANACloudColumnStore"), + "org.hibernate.dialect.HANACloudColumnStoreDialect"); + dialects.setEL(CommonUtil.createKey("HANAColumnStore"), "org.hibernate.dialect.HANAColumnStoreDialect"); + dialects.setEL(CommonUtil.createKey("HANARowStore"), "org.hibernate.dialect.HANARowStoreDialect"); + dialects.setEL(CommonUtil.createKey("HSQL"), "org.hibernate.dialect.HSQLDialect"); + dialects.setEL(CommonUtil.createKey("Informix10"), "org.hibernate.dialect.Informix10Dialect"); + dialects.setEL(CommonUtil.createKey("Informix"), "org.hibernate.dialect.InformixDialect"); + dialects.setEL(CommonUtil.createKey("Ingres10"), "org.hibernate.dialect.Ingres10Dialect"); + dialects.setEL(CommonUtil.createKey("Ingres9"), "org.hibernate.dialect.Ingres9Dialect"); + dialects.setEL(CommonUtil.createKey("Ingres"), "org.hibernate.dialect.IngresDialect"); + dialects.setEL(CommonUtil.createKey("Interbase"), "org.hibernate.dialect.InterbaseDialect"); + dialects.setEL(CommonUtil.createKey("JDataStore"), "org.hibernate.dialect.JDataStoreDialect"); + dialects.setEL(CommonUtil.createKey("MariaDB102"), "org.hibernate.dialect.MariaDB102Dialect"); + dialects.setEL(CommonUtil.createKey("MariaDB103"), "org.hibernate.dialect.MariaDB103Dialect"); + dialects.setEL(CommonUtil.createKey("MariaDB10"), "org.hibernate.dialect.MariaDB10Dialect"); + dialects.setEL(CommonUtil.createKey("MariaDB53"), "org.hibernate.dialect.MariaDB53Dialect"); + dialects.setEL(CommonUtil.createKey("MariaDB"), "org.hibernate.dialect.MariaDBDialect"); + dialects.setEL(CommonUtil.createKey("Mckoi"), "org.hibernate.dialect.MckoiDialect"); + dialects.setEL(CommonUtil.createKey("MimerSQL"), "org.hibernate.dialect.MimerSQLDialect"); + dialects.setEL(CommonUtil.createKey("MySQL55"), "org.hibernate.dialect.MySQL55Dialect"); + dialects.setEL(CommonUtil.createKey("MySQL57"), "org.hibernate.dialect.MySQL57Dialect"); + dialects.setEL(CommonUtil.createKey("MySQL57InnoDB"), "org.hibernate.dialect.MySQL57InnoDBDialect"); + dialects.setEL(CommonUtil.createKey("MySQL5"), "org.hibernate.dialect.MySQL5Dialect"); + dialects.setEL(CommonUtil.createKey("MySQL5InnoDB"), "org.hibernate.dialect.MySQL5InnoDBDialect"); + dialects.setEL(CommonUtil.createKey("MySQL8"), "org.hibernate.dialect.MySQL8Dialect"); + dialects.setEL(CommonUtil.createKey("MySQL"), "org.hibernate.dialect.MySQL8Dialect"); + dialects.setEL(CommonUtil.createKey("MySQLInnoDB"), "org.hibernate.dialect.MySQLInnoDBDialect"); + dialects.setEL(CommonUtil.createKey("MySQLMyISAM"), "org.hibernate.dialect.MySQLMyISAMDialect"); + dialects.setEL(CommonUtil.createKey("Oracle10g"), "org.hibernate.dialect.Oracle10gDialect"); + dialects.setEL(CommonUtil.createKey("Oracle12c"), "org.hibernate.dialect.Oracle12cDialect"); + dialects.setEL(CommonUtil.createKey("Oracle8i"), "org.hibernate.dialect.Oracle8iDialect"); + dialects.setEL(CommonUtil.createKey("Oracle9"), "org.hibernate.dialect.Oracle9Dialect"); + dialects.setEL(CommonUtil.createKey("Oracle9i"), "org.hibernate.dialect.Oracle9iDialect"); + dialects.setEL(CommonUtil.createKey("Oracle"), "org.hibernate.dialect.OracleDialect"); + dialects.setEL(CommonUtil.createKey("Pointbase"), "org.hibernate.dialect.PointbaseDialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL10"), "org.hibernate.dialect.PostgreSQL10Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL81"), "org.hibernate.dialect.PostgreSQL81Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL82"), "org.hibernate.dialect.PostgreSQL82Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL91"), "org.hibernate.dialect.PostgreSQL91Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL92"), "org.hibernate.dialect.PostgreSQL92Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL93"), "org.hibernate.dialect.PostgreSQL93Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL94"), "org.hibernate.dialect.PostgreSQL94Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL95"), "org.hibernate.dialect.PostgreSQL95Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL9"), "org.hibernate.dialect.PostgreSQL9Dialect"); + dialects.setEL(CommonUtil.createKey("PostgreSQL"), "org.hibernate.dialect.PostgreSQLDialect"); + dialects.setEL(CommonUtil.createKey("PostgresPlus"), "org.hibernate.dialect.PostgresPlusDialect"); + dialects.setEL(CommonUtil.createKey("Progress"), "org.hibernate.dialect.ProgressDialect"); + dialects.setEL(CommonUtil.createKey("RDMSOS2200"), "org.hibernate.dialect.RDMSOS2200Dialect"); + dialects.setEL(CommonUtil.createKey("SAPDB"), "org.hibernate.dialect.SAPDBDialect"); + dialects.setEL(CommonUtil.createKey("SQLServer2005"), "org.hibernate.dialect.SQLServer2005Dialect"); + dialects.setEL(CommonUtil.createKey("SQLServer2008"), "org.hibernate.dialect.SQLServer2008Dialect"); + dialects.setEL(CommonUtil.createKey("SQLServer2012"), "org.hibernate.dialect.SQLServer2012Dialect"); + dialects.setEL(CommonUtil.createKey("SQLServer"), "org.hibernate.dialect.SQLServerDialect"); + dialects.setEL(CommonUtil.createKey("Sybase11"), "org.hibernate.dialect.Sybase11Dialect"); + dialects.setEL(CommonUtil.createKey("SybaseASE157"), "org.hibernate.dialect.SybaseASE157Dialect"); + dialects.setEL(CommonUtil.createKey("SybaseASE15"), "org.hibernate.dialect.SybaseASE15Dialect"); + dialects.setEL(CommonUtil.createKey("SybaseAnywhere"), "org.hibernate.dialect.SybaseAnywhereDialect"); + dialects.setEL(CommonUtil.createKey("Sybase"), "org.hibernate.dialect.SybaseDialect"); + dialects.setEL(CommonUtil.createKey("Teradata14"), "org.hibernate.dialect.Teradata14Dialect"); + dialects.setEL(CommonUtil.createKey("Teradata"), "org.hibernate.dialect.TeradataDialect"); + dialects.setEL(CommonUtil.createKey("TimesTen"), "org.hibernate.dialect.TimesTenDialect"); - /** - * return a SQL dialect that match the given Name - * - * @param name - * @return - */ - public static String getDialect(DataSource ds) { - String name = ds.getClassDefinition().getClassName(); - if ("net.sourceforge.jtds.jdbc.Driver".equalsIgnoreCase(name)) { - String dsn = ds.getDsnTranslated(); - if (dsn.toLowerCase().indexOf("sybase") != -1) return getDialect("Sybase"); - return getDialect("SQLServer"); - } - return getDialect(name); - } + } - public static String getDialect(String name) { - String d = _getDialect(name); + /** + * Get the Hibernate dialect for the given Datasource + * + * @param ds + * - Datasource object to check dialect on + * + * @return the string dialect value, like "org.hibernate.dialect.PostgreSQLDialect" + */ + public static String getDialect(DataSource ds) { + String name = ds.getClassDefinition().getClassName(); + if ("net.sourceforge.jtds.jdbc.Driver".equalsIgnoreCase(name)) { + String dsn = ds.getConnectionStringTranslated(); + if (dsn.toLowerCase().indexOf("sybase") != -1) + return getDialect("Sybase"); + return getDialect("SQLServer"); + } + return getDialect(name); + } - // print.e(name + ":" + d); - return d; - } + /** + * Return a SQL dialect that match the given Name + * + * @param name + * - Dialect name like "Oracle" or "MySQL57" + * + * @return the full dialect string name, like "org.hibernate.dialect.OracleDialect" or + * "org.hibernate.dialect.MySQL57Dialect" + */ + public static String getDialect(String name) { + if (Util.isEmpty(name)) + return null; + String dialect = (String) dialects.get(CommonUtil.createKey(name), null); + return dialect; + } - public static String _getDialect(String name) { - if (Util.isEmpty(name)) return null; - String dialect = (String) dialects.get(CommonUtil.createKey(name), null); - return dialect; - } + /** + * Get all configurable dialects + * + * @return the configured dialects + */ + public static Struct getDialects() { + return dialects; + } - public static Iterator getDialectNames() { - return dialects.keysAsStringIterator(); - } + /** + * Get an iterator of dialect key names + * + * @return a String iteratator to iterate over all known dialects + */ + public static Iterator getDialectNames() { + return dialects.keysAsStringIterator(); + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/Entity.java b/source/java/src/org/lucee/extension/orm/hibernate/Entity.java deleted file mode 100755 index 173e6a41..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/Entity.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.lucee.extension.orm.hibernate; - -public interface Entity { - public String name(); -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/ExceptionUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/ExceptionUtil.java deleted file mode 100644 index 35be5014..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/ExceptionUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.lucee.extension.orm.hibernate; - -import java.lang.reflect.Method; - -import lucee.loader.engine.CFMLEngineFactory; -import lucee.runtime.Component; -import lucee.runtime.db.DataSource; -import lucee.runtime.exp.PageException; -import lucee.runtime.orm.ORMSession; -import lucee.runtime.type.Collection.Key; - -public class ExceptionUtil { - - private static Method setAdditional; - - public static PageException createException(SessionFactoryData data, Component cfc, String msg, String detail) { - - PageException pe = createException((ORMSession) null, cfc, msg, detail); - if (data != null) setAddional(pe, data); - return pe; - } - - public static PageException createException(SessionFactoryData data, Component cfc, Throwable t) { - PageException pe = createException((ORMSession) null, cfc, t); - if (data != null) setAddional(pe, data); - return pe; - } - - public static PageException createException(ORMSession session, Component cfc, Throwable t) { - return CFMLEngineFactory.getInstance().getORMUtil().createException(session, cfc, t); - } - - public static PageException createException(ORMSession session, Component cfc, String message, String detail) { - return CFMLEngineFactory.getInstance().getORMUtil().createException(session, cfc, message, detail); - } - - private static void setAddional(PageException pe, SessionFactoryData data) { - setAdditional(pe, CommonUtil.createKey("Entities"), CFMLEngineFactory.getInstance().getListUtil().toListEL(data.getEntityNames(), ", ")); - setAddional(pe, data.getDataSources()); - } - - private static void setAddional(PageException pe, DataSource... sources) { - if (sources != null && sources.length > 0) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < sources.length; i++) { - if (i > 0) sb.append(", "); - sb.append(sources[i].getName()); - } - setAdditional(pe, CommonUtil.createKey("_Datasource"), sb.toString()); - } - } - - public static void setAdditional(PageException pe, Key name, Object value) { - try { - if (setAdditional == null || setAdditional.getDeclaringClass() != pe.getClass()) { - setAdditional = pe.getClass().getMethod("setAdditional", new Class[] { Key.class, Object.class }); - } - setAdditional.invoke(pe, new Object[] { name, value }); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HBMCreator.java b/source/java/src/org/lucee/extension/orm/hibernate/HBMCreator.java index ef596811..f939f16d 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/HBMCreator.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/HBMCreator.java @@ -1,5 +1,6 @@ package org.lucee.extension.orm.hibernate; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -11,7 +12,6 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; -import lucee.commons.io.log.Log; import lucee.loader.util.Util; import lucee.runtime.Component; import lucee.runtime.PageContext; @@ -20,1797 +20,2188 @@ import lucee.runtime.exp.PageException; import lucee.runtime.type.Collection; import lucee.runtime.type.Collection.Key; + +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ExceptionUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; +import org.lucee.extension.orm.hibernate.util.ORMConfigurationUtil; +import org.lucee.extension.orm.hibernate.util.XMLUtil; import lucee.runtime.type.Struct; +import lucee.commons.io.res.Resource; public class HBMCreator { - private static final Collection.Key PROPERTY = CommonUtil.createKey("property"); - private static final Collection.Key LINK_TABLE = CommonUtil.createKey("linktable"); - private static final Collection.Key CFC = CommonUtil.createKey("cfc"); - private static final Collection.Key GENERATOR = CommonUtil.createKey("generator"); - private static final Collection.Key PARAMS = CommonUtil.createKey("params"); - private static final Collection.Key SEQUENCE = CommonUtil.createKey("sequence"); - private static final Collection.Key UNIQUE_KEY_NAME = CommonUtil.createKey("uniqueKeyName"); - private static final Collection.Key GENERATED = CommonUtil.createKey("generated"); - private static final Collection.Key FIELDTYPE = CommonUtil.createKey("fieldtype"); - private static final Collection.Key KEY = CommonUtil.createKey("key"); - private static final Collection.Key TYPE = CommonUtil.createKey("type"); - - public static void createXMLMapping(PageContext pc, DatasourceConnection dc, Component cfc, Element hibernateMapping, SessionFactoryData data) throws PageException { - - // MUST Support for embeded objects - Struct meta = cfc.getMetaData(pc); - - String extend = cfc.getExtends(); - boolean isClass = Util.isEmpty(extend); - - // MZ: Fetches all inherited persistent properties - // Property[] _props=getAllPersistentProperties(pc,cfc,dc,meta,isClass); - - Property[] _props = getProperties(pc, cfc, dc, meta, isClass, true, data); - - Map joins = new HashMap(); - PropertyCollection propColl = splitJoins(cfc, joins, _props, data); - - // create class element and attach - Document doc = CommonUtil.getDocument(hibernateMapping); - - StringBuilder comment = new StringBuilder(); - comment.append("\nsource:").append(cfc.getPageSource().getDisplayPath()); - comment.append("\ncompilation-time:").append(CommonUtil.createDateTime(HibernateUtil.getCompileTime(pc, cfc.getPageSource()))); - comment.append("\ndatasource:").append(dc.getDatasource().getName()); - comment.append("\n"); - - hibernateMapping.appendChild(doc.createComment(comment.toString())); - - // print.e(cfc.getAbsName()+";"+isClass+" -> "+cfci.getBaseAbsName()+":"+cfci.isBasePeristent()); - if (!isClass && !cfc.isBasePeristent()) { - isClass = true; - } - - Element join = null; - boolean doTable = true; - - Element clazz; - if (isClass) { - clazz = doc.createElement("class"); - hibernateMapping.appendChild(clazz); - } - // extended CFC - else { - // MZ: Fetches one level deep - _props = getProperties(pc, cfc, dc, meta, isClass, false, data); - // MZ: Reinitiate the property collection - propColl = splitJoins(cfc, joins, _props, data); - - String ext = CommonUtil.last(extend, ".").trim(); - try { - Component base = data.getEntityByCFCName(ext, false); - ext = HibernateCaster.getEntityName(base); - } - catch (Exception e) { - Log log = pc.getConfig().getLog("orm"); - log.error("hibernate", e); - } - - String discriminatorValue = toString(cfc, null, meta, "discriminatorValue", data); - if (!Util.isEmpty(discriminatorValue, true)) { - doTable = false; - clazz = doc.createElement("subclass"); - hibernateMapping.appendChild(clazz); - // addClassAttributes(classNode); - clazz.setAttribute("extends", ext); - clazz.setAttribute("discriminator-value", discriminatorValue); - - String joincolumn = toString(cfc, null, meta, "joincolumn", false, data); - if (!Util.isEmpty(joincolumn)) { - join = doc.createElement("join"); - clazz.appendChild(join); - doTable = true; - Element key = doc.createElement("key"); - join.appendChild(key); - key.setAttribute("column", formatColumn(joincolumn, data)); - } - - } - else { - // MZ: Match on joinColumn for a joined subclass, otherwise use a union subclass - String joinColumn = toString(cfc, null, meta, "joincolumn", false, data); - if (!Util.isEmpty(joinColumn, true)) { - clazz = doc.createElement("joined-subclass"); - hibernateMapping.appendChild(clazz); - clazz.setAttribute("extends", ext); - Element key = doc.createElement("key"); - clazz.appendChild(key); - key.setAttribute("column", formatColumn(joinColumn, data)); - } - else { - // MZ: When no joinColumn exists, default to an explicit table per class - clazz = doc.createElement("union-subclass"); - clazz.setAttribute("extends", ext); - doTable = true; - hibernateMapping.appendChild(clazz); - } - - } - } - - // createXMLMappingTuplizer(clazz,pc); - - addGeneralClassAttributes(pc, cfc, meta, clazz, data); - String tableName = getTableName(pc, meta, cfc, data); - - if (join != null) clazz = join; - if (doTable) addGeneralTableAttributes(pc, dc, cfc, meta, clazz, data); - - Struct columnsInfo = null; - if (data.getORMConfiguration().useDBForMapping()) { - columnsInfo = data.getTableInfo(dc, getTableName(pc, meta, cfc, data)); - } - - if (isClass) setCacheStrategy(cfc, null, doc, meta, clazz, data); - - // id - if (isClass) addId(cfc, doc, clazz, meta, propColl, columnsInfo, tableName, data); - - // discriminator - if (isClass) addDiscriminator(cfc, doc, clazz, pc, meta, data); - - // version - if (isClass) addVersion(cfc, clazz, pc, propColl, columnsInfo, tableName, data); - - // property - addProperty(cfc, clazz, pc, propColl, columnsInfo, tableName, data); - - // relations - addRelation(cfc, clazz, pc, propColl, columnsInfo, tableName, dc, data); - - // collection - addCollection(cfc, clazz, pc, propColl, columnsInfo, tableName, data); - - // join - addJoin(cfc, clazz, pc, joins, columnsInfo, tableName, dc, data); - - } - - private static Property[] getProperties(PageContext pc, Component cfc, DatasourceConnection dc, Struct meta, boolean isClass, boolean recursivePersistentMappedSuperclass, - SessionFactoryData data) throws PageException, PageException { - Property[] _props; - if (recursivePersistentMappedSuperclass) { - _props = CommonUtil.getProperties(cfc, true, true, true, true); - } - else { - _props = cfc.getProperties(true, false, false, false); - } - - if (isClass && _props.length == 0 && data.getORMConfiguration().useDBForMapping()) { - if (meta == null) meta = cfc.getMetaData(pc); - _props = HibernateUtil.createPropertiesFromTable(dc, getTableName(pc, meta, cfc, data)); - } - return _props; - } - - private static void addId(Component cfc, Document doc, Element clazz, Struct meta, PropertyCollection propColl, Struct columnsInfo, String tableName, SessionFactoryData data) - throws PageException { - Property[] _ids = getIds(cfc, propColl, data); - - // Property[] _ids = ids.toArray(new Property[ids.size()]); - - if (_ids.length == 1) createXMLMappingId(cfc, clazz, _ids[0], columnsInfo, tableName, data); - else if (_ids.length > 1) createXMLMappingCompositeId(cfc, clazz, _ids, columnsInfo, tableName, data); - else throw ExceptionUtil.createException(data, cfc, "missing id property for entity [" + HibernateCaster.getEntityName(cfc) + "]", null); - } - - private static PropertyCollection splitJoins(Component cfc, Map joins, Property[] props, SessionFactoryData data) { - Struct sct = CommonUtil.createStruct(); - ArrayList others = new ArrayList(); - java.util.List list; - String table; - Property prop; - String fieldType; - boolean isJoin; - for (int i = 0; i < props.length; i++) { - prop = props[i]; - table = getTable(cfc, prop, data); - // joins - if (!Util.isEmpty(table, true)) { - isJoin = true; - // wrong field type - try { - fieldType = toString(cfc, prop, sct, FIELDTYPE, false, data); - - if ("collection".equalsIgnoreCase(fieldType)) isJoin = false; - else if ("primary".equals(fieldType)) isJoin = false; - else if ("version".equals(fieldType)) isJoin = false; - else if ("timestamp".equals(fieldType)) isJoin = false; - } - catch (PageException e) { - } - - // missing column - String columns = null; - try { - if (CommonUtil.isRelated(props[i])) { - columns = toString(cfc, props[i], prop.getDynamicAttributes(), "fkcolumn", data); - } - else { - columns = toString(cfc, props[i], prop.getDynamicAttributes(), "joincolumn", data); - } - } - catch (PageException e) { - } - if (Util.isEmpty(columns)) isJoin = false; - - if (isJoin) { - table = table.trim(); - list = (java.util.List) sct.get(table, null); - if (list == null) { - list = new ArrayList(); - sct.setEL(CommonUtil.createKey(table), list); - } - list.add(prop); - continue; - } - } - others.add(prop); - } - - // fill to joins - Iterator> it = sct.entryIterator(); - Entry e; - while (it.hasNext()) { - e = it.next(); - list = (java.util.List) e.getValue(); - joins.put(e.getKey().getString(), new PropertyCollection(e.getKey().getString(), list)); - } - - return new PropertyCollection(null, others); - } - - private static Property[] getIds(Component cfc, PropertyCollection pc, SessionFactoryData data) { - return getIds(cfc, pc.getProperties(), pc.getTableName(), false, data); - } - - private static Property[] getIds(Component cfc, Property[] props, String tableName, boolean ignoreTableName, SessionFactoryData data) { - ArrayList ids = new ArrayList(); - for (int y = 0; y < props.length; y++) { - if (!ignoreTableName && !hasTable(cfc, props[y], tableName, data)) continue; - - String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, null), null); - if ("id".equalsIgnoreCase(fieldType) || CommonUtil.listFindNoCaseIgnoreEmpty(fieldType, "id", ',') != -1) ids.add(props[y]); - } - - // no id field defined - if (ids.size() == 0) { - String fieldType; - for (int y = 0; y < props.length; y++) { - if (!ignoreTableName && !hasTable(cfc, props[y], tableName, data)) continue; - fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, null), null); - if (Util.isEmpty(fieldType, true) && props[y].getName().equalsIgnoreCase("id")) { - ids.add(props[y]); - props[y].getDynamicAttributes().setEL(FIELDTYPE, "id"); - } - } - } - - // still no id field defined - if (ids.size() == 0 && props.length > 0) { - String owner = props[0].getOwnerName(); - if (!Util.isEmpty(owner)) owner = CommonUtil.last(owner, ".").trim(); - - String fieldType; - if (!Util.isEmpty(owner)) { - String id = owner + "id"; - for (int y = 0; y < props.length; y++) { - if (!ignoreTableName && !hasTable(cfc, props[y], tableName, data)) continue; - fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, null), null); - if (Util.isEmpty(fieldType, true) && props[y].getName().equalsIgnoreCase(id)) { - ids.add(props[y]); - props[y].getDynamicAttributes().setEL(FIELDTYPE, "id"); - } - } - } - } - return ids.toArray(new Property[ids.size()]); - } - - private static void addVersion(Component cfc, Element clazz, PageContext pc, PropertyCollection propColl, Struct columnsInfo, String tableName, SessionFactoryData data) - throws PageException { - Property[] props = propColl.getProperties(); - for (int y = 0; y < props.length; y++) { - String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, null), null); - if ("version".equalsIgnoreCase(fieldType)) createXMLMappingVersion(clazz, pc, cfc, props[y], data); - else if ("timestamp".equalsIgnoreCase(fieldType)) createXMLMappingTimestamp(clazz, pc, cfc, props[y], data); - } - } - - private static void addCollection(Component cfc, Element clazz, PageContext pc, PropertyCollection propColl, Struct columnsInfo, String tableName, SessionFactoryData data) - throws PageException { - Property[] props = propColl.getProperties(); - for (int y = 0; y < props.length; y++) { - String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, "column"), "column"); - if ("collection".equalsIgnoreCase(fieldType)) createXMLMappingCollection(clazz, pc, cfc, props[y], data); - } - } - - private static void addJoin(Component cfc, Element clazz, PageContext pc, Map joins, Struct columnsInfo, String tableName, DatasourceConnection dc, - SessionFactoryData data) throws PageException { - - Iterator> it = joins.entrySet().iterator(); - Entry entry; - while (it.hasNext()) { - entry = it.next(); - addJoin(cfc, pc, columnsInfo, clazz, entry.getValue(), dc, data); - } - - } - - private static void addJoin(Component cfc, PageContext pc, Struct columnsInfo, Element clazz, PropertyCollection coll, DatasourceConnection dc, SessionFactoryData data) - throws PageException { - String table = coll.getTableName(); - Property[] properties = coll.getProperties(); - if (properties.length == 0) return; - - Document doc = CommonUtil.getDocument(clazz); - - Element join = doc.createElement("join"); - clazz.appendChild(join); - - join.setAttribute("table", escape(HibernateUtil.convertTableName(data, coll.getTableName()))); - // addTableInfo(joinNode, table, schema, catalog); - - Property first = properties[0]; - String schema = null, catalog = null, mappedBy = null, columns = null; - if (CommonUtil.isRelated(first)) { - catalog = toString(cfc, first, first.getDynamicAttributes(), "linkcatalog", data); - schema = toString(cfc, first, first.getDynamicAttributes(), "linkschema", data); - columns = toString(cfc, first, first.getDynamicAttributes(), "fkcolumn", data); - - } - else { - catalog = toString(cfc, first, first.getDynamicAttributes(), "catalog", data); - schema = toString(cfc, first, first.getDynamicAttributes(), "schema", data); - mappedBy = toString(cfc, first, first.getDynamicAttributes(), "mappedby", data); - columns = toString(cfc, first, first.getDynamicAttributes(), "joincolumn", data); - } - - if (!Util.isEmpty(catalog)) join.setAttribute("catalog", catalog); - if (!Util.isEmpty(schema)) join.setAttribute("schema", schema); - - Element key = doc.createElement("key"); - join.appendChild(key); - if (!Util.isEmpty(mappedBy)) key.setAttribute("property-ref", mappedBy); - setColumn(doc, key, columns, data); - - addProperty(cfc, join, pc, coll, columnsInfo, table, data); - int count = addRelation(cfc, join, pc, coll, columnsInfo, table, dc, data); - - if (count > 0) join.setAttribute("inverse", "true"); - - } - - private static int addRelation(Component cfc, Element clazz, PageContext pc, PropertyCollection propColl, Struct columnsInfo, String tableName, DatasourceConnection dc, - SessionFactoryData data) throws PageException { - Property[] props = propColl.getProperties(); - int count = 0; - for (int y = 0; y < props.length; y++) { - String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, "column"), "column"); - if ("one-to-one".equalsIgnoreCase(fieldType)) { - createXMLMappingOneToOne(clazz, pc, cfc, props[y], data); - count++; - } - else if ("many-to-one".equalsIgnoreCase(fieldType)) { - createXMLMappingManyToOne(clazz, pc, cfc, props[y], propColl, data); - count++; - } - else if ("one-to-many".equalsIgnoreCase(fieldType)) { - createXMLMappingOneToMany(dc, cfc, propColl, clazz, pc, props[y], data); - count++; - } - else if ("many-to-many".equalsIgnoreCase(fieldType)) { - createXMLMappingManyToMany(dc, cfc, propColl, clazz, pc, props[y], data); - count++; - } - } - return count; - } - - private static void addProperty(Component cfc, Element clazz, PageContext pc, PropertyCollection propColl, Struct columnsInfo, String tableName, SessionFactoryData data) - throws PageException { - Property[] props = propColl.getProperties(); - for (int y = 0; y < props.length; y++) { - String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, "column"), "column"); - if ("column".equalsIgnoreCase(fieldType)) createXMLMappingProperty(clazz, pc, cfc, props[y], columnsInfo, tableName, data); - } - } - - private static void addDiscriminator(Component cfc, Document doc, Element clazz, PageContext pc, Struct meta, SessionFactoryData data) throws DOMException, PageException { - - String str = toString(cfc, null, meta, "discriminatorColumn", data); - if (!Util.isEmpty(str, true)) { - Element disc = doc.createElement("discriminator"); - clazz.appendChild(disc); - disc.setAttribute("column", formatColumn(str, data)); - } - - } - - private static void addGeneralClassAttributes(PageContext pc, Component cfc, Struct meta, Element clazz, SessionFactoryData data) throws PageException { - - // name - clazz.setAttribute("node", HibernateCaster.toComponentName(cfc)); - - // entity-name - String str = toString(cfc, null, meta, "entityname", data); - if (Util.isEmpty(str, true)) str = HibernateCaster.getEntityName(cfc); - clazz.setAttribute("entity-name", str); - - // batch-size - Integer i = toInteger(cfc, meta, "batchsize", data); - if (i != null && i.intValue() > 0) clazz.setAttribute("batch-size", CommonUtil.toString(i)); - - // dynamic-insert - Boolean b = toBoolean(cfc, meta, "dynamicinsert", data); - if (b != null && b.booleanValue()) clazz.setAttribute("dynamic-insert", "true"); - - // dynamic-update - b = toBoolean(cfc, meta, "dynamicupdate", data); - if (b != null && b.booleanValue()) clazz.setAttribute("dynamic-update", "true"); - - // lazy (dtd defintion:) - b = toBoolean(cfc, meta, "lazy", data); - if (b == null) b = Boolean.TRUE; - clazz.setAttribute("lazy", CommonUtil.toString(b.booleanValue())); - - // select-before-update - b = toBoolean(cfc, meta, "selectbeforeupdate", data); - if (b != null && b.booleanValue()) clazz.setAttribute("select-before-update", "true"); - - // optimistic-lock - str = toString(cfc, null, meta, "optimisticLock", data); - if (!Util.isEmpty(str, true)) { - str = str.trim().toLowerCase(); - if ("all".equals(str) || "dirty".equals(str) || "none".equals(str) || "version".equals(str)) clazz.setAttribute("optimistic-lock", str); - else throw ExceptionUtil.createException(data, cfc, - "invalid value [" + str + "] for attribute [optimisticlock] of tag [component], valid values are [all,dirty,none,version]", null); - } - - // read-only - b = toBoolean(cfc, meta, "readOnly", data); - if (b != null && b.booleanValue()) clazz.setAttribute("mutable", "false"); - - // rowid - str = toString(cfc, null, meta, "rowid", data); - if (!Util.isEmpty(str, true)) clazz.setAttribute("rowid", str); - - // where - str = toString(cfc, null, meta, "where", data); - if (!Util.isEmpty(str, true)) clazz.setAttribute("where", str); - - } - - private static void addGeneralTableAttributes(PageContext pc, DatasourceConnection dc, Component cfc, Struct meta, Element clazz, SessionFactoryData data) - throws PageException { - // table - clazz.setAttribute("table", escape(getTableName(pc, meta, cfc, data))); - - // catalog - String str = toString(cfc, null, meta, "catalog", data); - if (str == null) // empty string is allowed as input - str = ORMConfigurationUtil.getCatalog(data.getORMConfiguration(), dc.getDatasource().getName()); - - if (!Util.isEmpty(str, true)) clazz.setAttribute("catalog", str); - - // schema - str = toString(cfc, null, meta, "schema", data); - if (str == null)// empty string is allowed as input - str = ORMConfigurationUtil.getSchema(data.getORMConfiguration(), dc.getDatasource().getName()); - if (!Util.isEmpty(str, true)) clazz.setAttribute("schema", str); - - } - - private static String escape(String str) { - if (HibernateUtil.isKeyword(str)) return "`" + str + "`"; - return str; - } - - private static String getTableName(PageContext pc, Struct meta, Component cfc, SessionFactoryData data) throws PageException { - String tableName = toString(cfc, null, meta, "table", data); - if (Util.isEmpty(tableName, true)) tableName = HibernateCaster.getEntityName(cfc); - return HibernateUtil.convertTableName(data, tableName); - } - - private static String getTable(Component cfc, Property prop, SessionFactoryData data) { - try { - return HibernateUtil.convertTableName(data, toString(cfc, prop, prop.getDynamicAttributes(), "table", data)); - } - catch (PageException e) { - return null; - } - } - - private static boolean hasTable(Component cfc, Property prop, String tableName, SessionFactoryData data) { - String t = getTable(cfc, prop, data); - boolean left = Util.isEmpty(t, true); - boolean right = Util.isEmpty(tableName, true); - if (left && right) return true; - if (left || right) return false; - return tableName.trim().equalsIgnoreCase(t.trim()); - } - - private static void createXMLMappingCompositeId(Component cfc, Element clazz, Property[] props, Struct columnsInfo, String tableName, SessionFactoryData data) - throws PageException { - Struct meta; - - Document doc = CommonUtil.getDocument(clazz); - Element cid = doc.createElement("composite-id"); - clazz.appendChild(cid); - - // cid.setAttribute("mapped","true"); - - Property prop; - String fieldType; - // ids - for (int y = 0; y < props.length; y++) { - prop = props[y]; - - // do not add "key-property" for many-to-one - meta = prop.getDynamicAttributes(); - fieldType = toString(cfc, prop, meta, "fieldType", data); - if (CommonUtil.listFindNoCaseIgnoreEmpty(fieldType, "many-to-one", ',') != -1) continue; - - Element key = doc.createElement("key-property"); - cid.appendChild(key); - - // name - key.setAttribute("name", prop.getName()); - - // column - Element column = doc.createElement("column"); - key.appendChild(column); - - String str = toString(cfc, prop, meta, "column", data); - if (Util.isEmpty(str, true)) str = prop.getName(); - column.setAttribute("name", formatColumn(str, data)); - ColumnInfo info = getColumnInfo(columnsInfo, tableName, str, null); - - str = toString(cfc, prop, meta, "sqltype", data); - if (!Util.isEmpty(str, true)) column.setAttribute("sql-type", str); - str = toString(cfc, prop, meta, "length", data); - if (!Util.isEmpty(str, true)) column.setAttribute("length", str); - - String generator = toString(cfc, prop, meta, "generator", data); - String type = getType(info, cfc, prop, meta, getDefaultTypeForGenerator(generator, "string"), data); - if (!Util.isEmpty(type)) key.setAttribute("type", type); - } - - // many-to-one - for (int y = 0; y < props.length; y++) { - prop = props[y]; - meta = prop.getDynamicAttributes(); - fieldType = toString(cfc, prop, meta, "fieldType", data); - if (CommonUtil.listFindNoCaseIgnoreEmpty(fieldType, "many-to-one", ',') == -1) continue; - - Element key = doc.createElement("key-many-to-one"); - cid.appendChild(key); - - // name - key.setAttribute("name", prop.getName()); - - // entity-name - setForeignEntityName(cfc, prop, meta, key, false, data); - - // fkcolum - String str = toString(cfc, prop, meta, "fkcolumn", data); - setColumn(doc, key, str, data); - - // lazy - setLazy(cfc, prop, meta, key, data); - } - } - - private static void createXMLMappingId(Component cfc, Element clazz, Property prop, Struct columnsInfo, String tableName, SessionFactoryData data) throws PageException { - Struct meta = prop.getDynamicAttributes(); - String str; - - Document doc = CommonUtil.getDocument(clazz); - Element id = doc.createElement("id"); - clazz.appendChild(id); - - // access - str = toString(cfc, prop, meta, "access", data); - if (!Util.isEmpty(str, true)) id.setAttribute("access", str); - - // name - id.setAttribute("name", prop.getName()); - - // column - Element column = doc.createElement("column"); - id.appendChild(column); - - str = toString(cfc, prop, meta, "column", data); - if (Util.isEmpty(str, true)) str = prop.getName(); - column.setAttribute("name", formatColumn(str, data)); - ColumnInfo info = getColumnInfo(columnsInfo, tableName, str, null); - StringBuilder foreignCFC = new StringBuilder(); - String generator = createXMLMappingGenerator(id, cfc, prop, foreignCFC, data); - - str = toString(cfc, prop, meta, "length", data); - if (!Util.isEmpty(str, true)) column.setAttribute("length", str); - - // type - String type = getType(info, cfc, prop, meta, getDefaultTypeForGenerator(generator, foreignCFC, data), data); - // print.o(prop.getName()+":"+type+"::"+getDefaultTypeForGenerator(generator,foreignCFC)); - if (!Util.isEmpty(type)) id.setAttribute("type", type); - - // unsaved-value - str = toString(cfc, prop, meta, "unsavedValue", data); - if (str != null) id.setAttribute("unsaved-value", str); - - } - - private static String getDefaultTypeForGenerator(String generator, StringBuilder foreignCFC, SessionFactoryData data) { - String value = getDefaultTypeForGenerator(generator, null); - if (value != null) return value; - - if ("foreign".equalsIgnoreCase(generator)) { - if (!Util.isEmpty(foreignCFC.toString())) { - try { - Component cfc = data.getEntityByCFCName(foreignCFC.toString(), false); - if (cfc != null) { - Property[] ids = getIds(cfc, cfc.getProperties(true, false, false, false), null, true, data); - if (ids != null && ids.length > 0) { - Property id = ids[0]; - id.getDynamicAttributes(); - Struct meta = id.getDynamicAttributes(); - if (meta != null) { - String type = CommonUtil.toString(meta.get(TYPE, null)); - - if (!Util.isEmpty(type) && (!type.equalsIgnoreCase("any") && !type.equalsIgnoreCase("object"))) { - return type; - } - - String g = CommonUtil.toString(meta.get(GENERATOR, null)); - if (!Util.isEmpty(g)) { - return getDefaultTypeForGenerator(g, foreignCFC, data); - } - - } - } - } - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } - return "string"; - } - - return "string"; - } - - public static String getDefaultTypeForGenerator(String generator, String defaultValue) { - if ("increment".equalsIgnoreCase(generator)) return "integer"; - if ("identity".equalsIgnoreCase(generator)) return "integer"; - if ("native".equalsIgnoreCase(generator)) return "integer"; - if ("seqhilo".equalsIgnoreCase(generator)) return "string"; - if ("uuid".equalsIgnoreCase(generator)) return "string"; - if ("guid".equalsIgnoreCase(generator)) return "string"; - if ("select".equalsIgnoreCase(generator)) return "string"; - return defaultValue; - } - - private static String getType(ColumnInfo info, Component cfc, Property prop, Struct meta, String defaultValue, SessionFactoryData data) throws PageException { - // ormType - String type = toString(cfc, prop, meta, "ormType", data); - // type=HibernateCaster.toHibernateType(info,type,null); - - // dataType - if (Util.isEmpty(type, true)) { - type = toString(cfc, prop, meta, "dataType", data); - // type=HibernateCaster.toHibernateType(info,type,null); - } - - // type - if (Util.isEmpty(type, true)) { - type = prop.getType(); - // type=HibernateCaster.toHibernateType(info,type,null); - } - - // type from db info - if (Util.isEmpty(type, true)) { - if (info != null) { - type = info.getTypeName(); - // type=HibernateCaster.toHibernateType(info,type,defaultValue); - } - else return defaultValue; - } - return HibernateCaster.toHibernateType(info, type, defaultValue); - } - - private static ColumnInfo getColumnInfo(Struct columnsInfo, String tableName, String columnName, ColumnInfo defaultValue) { - if (columnsInfo != null) { - ColumnInfo info = (ColumnInfo) columnsInfo.get(CommonUtil.createKey(columnName), null); - if (info == null) return defaultValue; - return info; - } - return defaultValue; - } - - private static String createXMLMappingGenerator(Element id, Component cfc, Property prop, StringBuilder foreignCFC, SessionFactoryData data) throws PageException { - Struct meta = prop.getDynamicAttributes(); - - // generator - String className = toString(cfc, prop, meta, "generator", data); - if (Util.isEmpty(className, true)) return null; - - Document doc = CommonUtil.getDocument(id); - Element generator = doc.createElement("generator"); - id.appendChild(generator); - - generator.setAttribute("class", className); - - // print.e("generator:"+className); - - // params - Object obj = meta.get(PARAMS, null); - // if(obj!=null){ - Struct sct = null; - if (obj == null) obj = CommonUtil.createStruct(); - else if (obj instanceof String) obj = CommonUtil.convertToSimpleMap((String) obj); - - if (CommonUtil.isStruct(obj)) sct = CommonUtil.toStruct(obj); - else throw ExceptionUtil.createException(data, cfc, "invalid value for attribute [params] of tag [property]", null); - className = className.trim().toLowerCase(); - - // special classes - if ("foreign".equals(className)) { - if (!sct.containsKey(PROPERTY)) sct.setEL(PROPERTY, toString(cfc, prop, meta, PROPERTY, true, data)); - - if (sct.containsKey(PROPERTY)) { - String p = CommonUtil.toString(sct.get(PROPERTY), null); - if (!Util.isEmpty(p)) foreignCFC.append(p); - } - - } - else if ("select".equals(className)) { - // print.e("select:"+toString(meta, "selectKey",true)); - if (!sct.containsKey(KEY)) sct.setEL(KEY, toString(cfc, prop, meta, "selectKey", true, data)); - } - else if ("sequence".equals(className)) { - if (!sct.containsKey(SEQUENCE)) sct.setEL(SEQUENCE, toString(cfc, prop, meta, "sequence", true, data)); - } - - // Key[] keys = sct.keys(); - Iterator> it = sct.entryIterator(); - Entry e; - Element param; - while (it.hasNext()) { - e = it.next(); - param = doc.createElement("param"); - generator.appendChild(param); - - param.setAttribute("name", e.getKey().getLowerString()); - param.appendChild(doc.createTextNode(CommonUtil.toString(e.getValue()))); - - } - // } - return className; - } - - private static void createXMLMappingProperty(Element clazz, PageContext pc, Component cfc, Property prop, Struct columnsInfo, String tableName, SessionFactoryData data) - throws PageException { - Struct meta = prop.getDynamicAttributes(); - - // get table name - String columnName = toString(cfc, prop, meta, "column", data); - if (Util.isEmpty(columnName, true)) columnName = prop.getName(); - - ColumnInfo info = getColumnInfo(columnsInfo, tableName, columnName, null); - - Document doc = CommonUtil.getDocument(clazz); - final Element property = doc.createElement("property"); - clazz.appendChild(property); - - // name - property.setAttribute("name", prop.getName()); - - // type - String str = getType(info, cfc, prop, meta, "string", data); - property.setAttribute("type", str); - - // formula or column - str = toString(cfc, prop, meta, "formula", data); - Boolean b; - if (!Util.isEmpty(str, true)) { - property.setAttribute("formula", "(" + str + ")"); - } - else { - // property.setAttribute("column",columnName); - - Element column = doc.createElement("column"); - property.appendChild(column); - column.setAttribute("name", escape(HibernateUtil.convertColumnName(data, columnName))); - - // check - str = toString(cfc, prop, meta, "check", data); - if (!Util.isEmpty(str, true)) column.setAttribute("check", str); - - // default - str = toString(cfc, prop, meta, "dbDefault", data); - if (!Util.isEmpty(str, true)) column.setAttribute("default", str); - - // index - str = toString(cfc, prop, meta, "index", data); - if (!Util.isEmpty(str, true)) column.setAttribute("index", str); - - // length - Integer i = toInteger(cfc, meta, "length", data); - if (i != null && i > 0) column.setAttribute("length", CommonUtil.toString(i.intValue())); - - // not-null - b = toBoolean(cfc, meta, "notnull", data); - if (b != null && b.booleanValue()) column.setAttribute("not-null", "true"); - - // precision - i = toInteger(cfc, meta, "precision", data); - if (i != null && i > -1) column.setAttribute("precision", CommonUtil.toString(i.intValue())); - - // scale - i = toInteger(cfc, meta, "scale", data); - if (i != null && i > -1) column.setAttribute("scale", CommonUtil.toString(i.intValue())); - - // sql-type - str = toString(cfc, prop, meta, "sqltype", data); - if (!Util.isEmpty(str, true)) column.setAttribute("sql-type", str); - - // unique - b = toBoolean(cfc, meta, "unique", data); - if (b != null && b.booleanValue()) column.setAttribute("unique", "true"); - - // unique-key - str = toString(cfc, prop, meta, "uniqueKey", data); - if (Util.isEmpty(str)) str = CommonUtil.toString(meta.get(UNIQUE_KEY_NAME, null), null); - if (!Util.isEmpty(str, true)) column.setAttribute("unique-key", str); - - } - - // generated - str = toString(cfc, prop, meta, "generated", data); - if (!Util.isEmpty(str, true)) { - str = str.trim().toLowerCase(); - - if ("always".equals(str) || "insert".equals(str) || "never".equals(str)) property.setAttribute("generated", str); - else throw invalidValue(cfc, prop, "generated", str, "always,insert,never", data); - // throw new ORMException("invalid value ["+str+"] for attribute [generated] of column - // ["+columnName+"], valid values are [always,insert,never]"); - } - - // update - b = toBoolean(cfc, meta, "update", data); - if (b != null && !b.booleanValue()) property.setAttribute("update", "false"); - - // insert - b = toBoolean(cfc, meta, "insert", data); - if (b != null && !b.booleanValue()) property.setAttribute("insert", "false"); - - // lazy (dtd defintion:) - b = toBoolean(cfc, meta, "lazy", data); - if (b != null && b.booleanValue()) property.setAttribute("lazy", "true"); - - // optimistic-lock - b = toBoolean(cfc, meta, "optimisticlock", data); - if (b != null && !b.booleanValue()) property.setAttribute("optimistic-lock", "false"); - - } - - /* - * MUST dies kommt aber nicht hier sondern in verarbeitung in component - */ - private static void createXMLMappingOneToOne(Element clazz, PageContext pc, Component cfc, Property prop, SessionFactoryData data) throws PageException { - Struct meta = prop.getDynamicAttributes(); - - Boolean b; - - Document doc = CommonUtil.getDocument(clazz); - Element x2o; - - // column - String fkcolumn = toString(cfc, prop, meta, "fkcolumn", data); - String linkTable = toString(cfc, prop, meta, "linkTable", data); - - if (!Util.isEmpty(linkTable, true) || !Util.isEmpty(fkcolumn, true)) { - clazz = getJoin(clazz); - - x2o = doc.createElement("many-to-one"); - // x2o.setAttribute("column", fkcolumn); - x2o.setAttribute("unique", "true"); - - if (!Util.isEmpty(linkTable, true)) { - setColumn(doc, x2o, linkTable, data); - } - else { - setColumn(doc, x2o, fkcolumn, data); - } - - // update - b = toBoolean(cfc, meta, "update", data); - if (b != null) x2o.setAttribute("update", CommonUtil.toString(b.booleanValue())); - - // insert - b = toBoolean(cfc, meta, "insert", data); - if (b != null) x2o.setAttribute("insert", CommonUtil.toString(b.booleanValue())); - - // not-null - b = toBoolean(cfc, meta, "notNull", data); - if (b != null) x2o.setAttribute("not-null", CommonUtil.toString(b.booleanValue())); - - // optimistic-lock - b = toBoolean(cfc, meta, "optimisticLock", data); - if (b != null) x2o.setAttribute("optimistic-lock", CommonUtil.toString(b.booleanValue())); - - // not-found - b = toBoolean(cfc, meta, "missingRowIgnored", data); - if (b != null && b.booleanValue()) x2o.setAttribute("not-found", "ignore"); - - /* - * / index str=toString(meta,"index"); if(!Util.isEmpty(str,true)) x2o.setAttribute("index", str); - */ - - } - else { - x2o = doc.createElement("one-to-one"); - } - clazz.appendChild(x2o); - - // access - String str = toString(cfc, prop, meta, "access", data); - if (!Util.isEmpty(str, true)) x2o.setAttribute("access", str); - - // constrained - b = toBoolean(cfc, meta, "constrained", data); - if (b != null && b.booleanValue()) x2o.setAttribute("constrained", "true"); - - // formula - str = toString(cfc, prop, meta, "formula", data); - if (!Util.isEmpty(str, true)) x2o.setAttribute("formula", str); - - // embed-xml - str = toString(cfc, prop, meta, "embedXml", data); - if (!Util.isEmpty(str, true)) x2o.setAttribute("embed-xml", str); - - // property-ref - str = toString(cfc, prop, meta, "mappedBy", data); - if (!Util.isEmpty(str, true)) x2o.setAttribute("property-ref", str); - - // foreign-key - str = toString(cfc, prop, meta, "foreignKeyName", data); - if (Util.isEmpty(str, true)) str = toString(cfc, prop, meta, "foreignKey", data); - if (!Util.isEmpty(str, true)) x2o.setAttribute("foreign-key", str); - - setForeignEntityName(cfc, prop, meta, x2o, true, data); - - createXMLMappingXToX(x2o, pc, cfc, prop, meta, data); - } - - private static Component loadForeignCFC(PageContext pc, Component cfc, Property prop, Struct meta, SessionFactoryData data) throws PageException { - // entity - String str = toString(cfc, prop, meta, "entityName", data); - Component fcfc = null; - - if (!Util.isEmpty(str, true)) { - fcfc = data.getEntityByEntityName(str, false); - if (fcfc != null) return fcfc; - } - - str = toString(cfc, prop, meta, "cfc", false, data); - if (!Util.isEmpty(str, true)) { - return data.getEntityByCFCName(str, false); - } - return null; - } - - private static void createXMLMappingCollection(Element clazz, PageContext pc, Component cfc, Property prop, SessionFactoryData data) throws PageException { - Struct meta = prop.getDynamicAttributes(); - Document doc = CommonUtil.getDocument(clazz); - Element el = null; - - // collection type - String str = prop.getType(); - if (Util.isEmpty(str, true) || "any".equalsIgnoreCase(str) || "object".equalsIgnoreCase(str)) str = "array"; - else str = str.trim().toLowerCase(); - - // bag - if ("array".equals(str) || "bag".equals(str)) { - el = doc.createElement("bag"); - } - // map - else if ("struct".equals(str) || "map".equals(str)) { - el = doc.createElement("map"); - - // map-key - str = toString(cfc, prop, meta, "structKeyColumn", true, data); - if (!Util.isEmpty(str, true)) { - Element mapKey = doc.createElement("map-key"); - el.appendChild(mapKey); - mapKey.setAttribute("column", str); - - // type - str = toString(cfc, prop, meta, "structKeyType", data); - if (!Util.isEmpty(str, true)) mapKey.setAttribute("type", str); - else mapKey.setAttribute("type", "string"); - } - } - else throw invalidValue(cfc, prop, "collectiontype", str, "array,struct", data); - // throw new ORMException("invalid value ["+str+"] for attribute [collectiontype], valid values are - // [array,struct]"); - - setBeforeJoin(clazz, el); - - // name - el.setAttribute("name", prop.getName()); - - // table - str = toString(cfc, prop, meta, "table", true, data); - el.setAttribute("table", escape(HibernateUtil.convertTableName(data, str))); - - // catalog - str = toString(cfc, prop, meta, "catalog", data); - if (!Util.isEmpty(str, true)) el.setAttribute("catalog", str); - - // schema - str = toString(cfc, prop, meta, "schema", data); - if (!Util.isEmpty(str, true)) el.setAttribute("schema", str); - - // mutable - Boolean b = toBoolean(cfc, meta, "readonly", data); - if (b != null && b.booleanValue()) el.setAttribute("mutable", "false"); - - // order-by - str = toString(cfc, prop, meta, "orderby", data); - if (!Util.isEmpty(str, true)) el.setAttribute("order-by", str); - - // element-column - str = toString(cfc, prop, meta, "elementcolumn", data); - if (!Util.isEmpty(str, true)) { - Element element = doc.createElement("element"); - el.appendChild(element); - - // column - element.setAttribute("column", formatColumn(str, data)); - - // type - str = toString(cfc, prop, meta, "elementtype", data); - if (!Util.isEmpty(str, true)) element.setAttribute("type", str); - } - - // batch-size - Integer i = toInteger(cfc, meta, "batchsize", data); - if (i != null && i.intValue() > 1) el.setAttribute("batch-size", CommonUtil.toString(i.intValue())); - - // column - str = toString(cfc, prop, meta, "fkcolumn", data); - if (Util.isEmpty(str, true)) str = toString(cfc, prop, meta, "column", data); - if (!Util.isEmpty(str, true)) { - Element key = doc.createElement("key"); - CommonUtil.setFirst(el, key); - // el.appendChild(key); - - // column - key.setAttribute("column", formatColumn(str, data)); - - // property-ref - str = toString(cfc, prop, meta, "mappedBy", data); - if (!Util.isEmpty(str, true)) key.setAttribute("property-ref", str); - } - - // cache - setCacheStrategy(cfc, prop, doc, meta, el, data); - - // optimistic-lock - b = toBoolean(cfc, meta, "optimisticlock", data); - if (b != null && !b.booleanValue()) el.setAttribute("optimistic-lock", "false"); - - } - - private static void setBeforeJoin(Element clazz, Element el) { - Element join; - if (clazz.getNodeName().equals("join")) { - join = clazz; - clazz = getClazz(clazz); - } - else { - join = getJoin(clazz); - } - - if (join == clazz) clazz.appendChild(el); - else clazz.insertBefore(el, join); - - } - - private static Element getClazz(Element join) { - if (join.getNodeName().equals("join")) { - return (Element) join.getParentNode(); - } - return join; - } - - private static Element getJoin(Element clazz) { - if (clazz.getNodeName().equals("subclass")) { - NodeList joins = clazz.getElementsByTagName("join"); - if (joins != null && joins.getLength() > 0) return (Element) joins.item(0); - } - return clazz; - } - - private static void createXMLMappingManyToMany(DatasourceConnection dc, Component cfc, PropertyCollection propColl, Element clazz, PageContext pc, Property prop, - SessionFactoryData data) throws PageException { - Element el = createXMLMappingXToMany(propColl, clazz, pc, cfc, prop, data); - Struct meta = prop.getDynamicAttributes(); - Document doc = CommonUtil.getDocument(clazz); - Element m2m = doc.createElement("many-to-many"); - el.appendChild(m2m); - - // link - setLink(dc, cfc, prop, el, meta, true, data); - - setForeignEntityName(cfc, prop, meta, m2m, true, data); - - // order-by - String str = toString(cfc, prop, meta, "orderby", data); - if (!Util.isEmpty(str, true)) m2m.setAttribute("order-by", str); - - // column - str = toString(cfc, prop, meta, "inversejoincolumn", data); - - // build fkcolumn name - if (Util.isEmpty(str, true)) { - Component other = loadForeignCFC(pc, cfc, prop, meta, data); - if (other != null) { - boolean isClass = Util.isEmpty(other.getExtends()); - // MZ: Recursive search for persistent mappedSuperclass properties - Property[] _props = getProperties(pc, other, dc, meta, isClass, true, data); - PropertyCollection _propColl = splitJoins(cfc, new HashMap(), _props, data); - _props = _propColl.getProperties(); - - Struct m; - Property _prop = null; - for (int i = 0; i < _props.length; i++) { - m = _props[i].getDynamicAttributes(); - // fieldtype - String fieldtype = CommonUtil.toString(m.get(FIELDTYPE, null), null); - if ("many-to-many".equalsIgnoreCase(fieldtype)) { - // linktable - String currLinkTable = CommonUtil.toString(meta.get(LINK_TABLE, null), null); - String othLinkTable = CommonUtil.toString(m.get(LINK_TABLE, null), null); - if (currLinkTable.equals(othLinkTable)) { - // cfc name - String cfcName = CommonUtil.toString(m.get(CFC, null), null); - if (cfc.equalTo(cfcName)) { - _prop = _props[i]; - } - } - } - } - str = createM2MFKColumnName(other, _prop, _propColl, data); - } - } - setColumn(doc, m2m, str, data); - - // not-found - Boolean b = toBoolean(cfc, meta, "missingrowignored", data); - if (b != null && b.booleanValue()) m2m.setAttribute("not-found", "ignore"); - - // property-ref - str = toString(cfc, prop, meta, "mappedby", data); - if (!Util.isEmpty(str, true)) m2m.setAttribute("property-ref", str); - - // foreign-key - str = toString(cfc, prop, meta, "foreignKeyName", data); - if (Util.isEmpty(str, true)) str = toString(cfc, prop, meta, "foreignKey", data); - if (!Util.isEmpty(str, true)) m2m.setAttribute("foreign-key", str); - } - - private static boolean setLink(DatasourceConnection dc, Component cfc, Property prop, Element el, Struct meta, boolean linkTableRequired, SessionFactoryData data) - throws PageException { - String str = toString(cfc, prop, meta, "linktable", linkTableRequired, data); - - if (!Util.isEmpty(str, true)) { - - el.setAttribute("table", escape(HibernateUtil.convertTableName(data, str))); - - // schema - str = toString(cfc, prop, meta, "linkschema", data); - if (Util.isEmpty(str, true)) str = ORMConfigurationUtil.getSchema(data.getORMConfiguration(), dc.getDatasource().getName()); - if (!Util.isEmpty(str, true)) el.setAttribute("schema", str); - - // catalog - str = toString(cfc, prop, meta, "linkcatalog", data); - if (Util.isEmpty(str, true)) str = ORMConfigurationUtil.getCatalog(data.getORMConfiguration(), dc.getDatasource().getName()); - if (!Util.isEmpty(str, true)) el.setAttribute("catalog", str); - return true; - } - return false; - } - - private static void createXMLMappingOneToMany(DatasourceConnection dc, Component cfc, PropertyCollection propColl, Element clazz, PageContext pc, Property prop, - SessionFactoryData data) throws PageException { - Element el = createXMLMappingXToMany(propColl, clazz, pc, cfc, prop, data); - Struct meta = prop.getDynamicAttributes(); - Document doc = CommonUtil.getDocument(clazz); - Element x2m; - - // order-by - String str = toString(cfc, prop, meta, "orderby", data); - if (!Util.isEmpty(str, true)) el.setAttribute("order-by", str); - - // link - if (setLink(dc, cfc, prop, el, meta, false, data)) { - x2m = doc.createElement("many-to-many"); - x2m.setAttribute("unique", "true"); - - str = toString(cfc, prop, meta, "inversejoincolumn", data); - setColumn(doc, x2m, str, data); - } - else { - x2m = doc.createElement("one-to-many"); - } - el.appendChild(x2m); - - // entity-name - - setForeignEntityName(cfc, prop, meta, x2m, true, data); - - } - - private static Element createXMLMappingXToMany(PropertyCollection propColl, Element clazz, PageContext pc, Component cfc, Property prop, SessionFactoryData data) - throws PageException { - final Struct meta = prop.getDynamicAttributes(); - Document doc = CommonUtil.getDocument(clazz); - Element el = null; - - // collection type - String str = prop.getType(); - if (Util.isEmpty(str, true) || "any".equalsIgnoreCase(str) || "object".equalsIgnoreCase(str)) str = "array"; - else str = str.trim().toLowerCase(); - - Element mapKey = null; - // bag - if ("array".equals(str) || "bag".equals(str)) { - el = doc.createElement("bag"); - - } - // map - else if ("struct".equals(str) || "map".equals(str)) { - el = doc.createElement("map"); - - // map-key - mapKey = doc.createElement("map-key"); - // el.appendChild(mapKey); - - // column - str = toString(cfc, prop, meta, "structKeyColumn", true, data); - mapKey.setAttribute("column", formatColumn(str, data)); - - // type - str = toString(cfc, prop, meta, "structKeyType", data); - if (!Util.isEmpty(str, true)) mapKey.setAttribute("type", str); - else mapKey.setAttribute("type", "string");// MUST get type dynamicly - } - else throw invalidValue(cfc, prop, "collectiontype", str, "array,struct", data); - // throw new ORMException("invalid value ["+str+"] for attribute [collectiontype], valid values are - // [array,struct]"); - - setBeforeJoin(clazz, el); - - // batch-size - Integer i = toInteger(cfc, meta, "batchsize", data); - if (i != null) { - if (i.intValue() > 1) el.setAttribute("batch-size", CommonUtil.toString(i.intValue())); - } - - // cacheUse - setCacheStrategy(cfc, prop, doc, meta, el, data); - - // column - str = createFKColumnName(cfc, prop, propColl, data); - - if (!Util.isEmpty(str, true)) { - Element key = doc.createElement("key"); - el.appendChild(key); - - // column - setColumn(doc, key, str, data); - - // property-ref - str = toString(cfc, prop, meta, "mappedBy", data); - if (!Util.isEmpty(str, true)) key.setAttribute("property-ref", str); - } - - // inverse - Boolean b = toBoolean(cfc, meta, "inverse", data); - if (b != null && b.booleanValue()) el.setAttribute("inverse", "true"); - - // mutable - b = toBoolean(cfc, meta, "readonly", data); - if (b != null && b.booleanValue()) el.setAttribute("mutable", "false"); - - // optimistic-lock - b = toBoolean(cfc, meta, "optimisticlock", data); - if (b != null && !b.booleanValue()) el.setAttribute("optimistic-lock", "false"); - - // where - str = toString(cfc, prop, meta, "where", data); - if (!Util.isEmpty(str, true)) el.setAttribute("where", str); - - // add map key - if (mapKey != null) el.appendChild(mapKey); - - createXMLMappingXToX(el, pc, cfc, prop, meta, data); - - return el; - } - - private static String createFKColumnName(Component cfc, Property prop, PropertyCollection propColl, SessionFactoryData data) throws PageException { - - // fk column from local defintion - String str = prop == null ? null : toString(cfc, prop, prop.getDynamicAttributes(), "fkcolumn", data); - if (!Util.isEmpty(str)) return str; - - // no local defintion, get from Foreign enity - Struct meta = prop.getDynamicAttributes(); - String type = toString(cfc, prop, meta, "fieldtype", false, data); - String otherType; - if ("many-to-one".equalsIgnoreCase(type)) otherType = "one-to-many"; - else if ("one-to-many".equalsIgnoreCase(type)) otherType = "many-to-one"; - else return createM2MFKColumnName(cfc, prop, propColl, data); - - String feName = toString(cfc, prop, meta, "cfc", true, data); - Component feCFC = data.getEntityByCFCName(feName, false); - Property[] feProps = feCFC.getProperties(true, false, false, false); - - Property p; - Component _cfc; - for (int i = 0; i < feProps.length; i++) { - p = feProps[i]; - - // compare fieldType - str = toString(feCFC, p, p.getDynamicAttributes(), "fieldtype", false, data); - if (!otherType.equalsIgnoreCase(str)) continue; - - // compare cfc - str = toString(feCFC, p, p.getDynamicAttributes(), "cfc", false, data); - if (Util.isEmpty(str)) continue; - _cfc = data.getEntityByCFCName(str, false); - if (_cfc == null || !_cfc.equals(cfc)) continue; - - // get fkcolumn - str = toString(_cfc, p, p.getDynamicAttributes(), "fkcolumn", data); - if (!Util.isEmpty(str)) return str; - - } - throw ExceptionUtil.createException(data, null, "cannot terminate foreign key column name for component " + cfc.getName(), null); - } - - private static String createM2MFKColumnName(Component cfc, Property prop, PropertyCollection propColl, SessionFactoryData data) throws PageException { - - String str = prop == null ? null : toString(cfc, prop, prop.getDynamicAttributes(), "fkcolumn", data); - if (Util.isEmpty(str)) { - Property[] ids = getIds(cfc, propColl, data); - if (ids.length == 1) { - str = toString(cfc, ids[0], ids[0].getDynamicAttributes(), "column", data); - if (Util.isEmpty(str, true)) str = ids[0].getName(); - } - else if (prop != null) str = toString(cfc, prop, prop.getDynamicAttributes(), "fkcolumn", true, data); - else throw ExceptionUtil.createException(data, null, "cannot terminate foreign key column name for component " + cfc.getName(), null); - - str = HibernateCaster.getEntityName(cfc) + "_" + str; - } - return str; - } - - private static void setForeignEntityName(Component cfc, Property prop, Struct meta, Element el, boolean cfcRequired, SessionFactoryData data) throws PageException { - // entity - String str = cfcRequired ? null : toString(cfc, prop, meta, "entityName", data); - if (!Util.isEmpty(str, true)) { - el.setAttribute("entity-name", str); - } - else { - // cfc - // createFKColumnName( cfc, prop, propColl); - - str = toString(cfc, prop, meta, "cfc", cfcRequired, data); - if (!Util.isEmpty(str, true)) { - Component _cfc = data.getEntityByCFCName(str, false); - str = HibernateCaster.getEntityName(_cfc); - el.setAttribute("entity-name", str); - } - } - } - - private static void setCacheStrategy(Component cfc, Property prop, Document doc, Struct meta, Element el, SessionFactoryData data) throws PageException { - String strategy = toString(cfc, prop, meta, "cacheuse", data); - - if (!Util.isEmpty(strategy, true)) { - strategy = strategy.trim().toLowerCase(); - if ("read-only".equals(strategy) || "nonstrict-read-write".equals(strategy) || "read-write".equals(strategy) || "transactional".equals(strategy)) { - Element cache = doc.createElement("cache"); - CommonUtil.setFirst(el, cache); - el.appendChild(cache); - cache.setAttribute("usage", strategy); - String name = toString(cfc, prop, meta, "cacheName", data); - if (!Util.isEmpty(name, true)) { - cache.setAttribute("region", name); - } - } - else throw ExceptionUtil.createException(data, cfc, - "invalid value [" + strategy + "] for attribute [cacheuse], valid values are [read-only,nonstrict-read-write,read-write,transactional]", null); - } - - } - - private static void setColumn(Document doc, Element el, String columnValue, SessionFactoryData data) throws PageException { - if (Util.isEmpty(columnValue, true)) return; - - String[] arr = CommonUtil.toStringArray(columnValue, ","); - if (arr.length == 1) { - el.setAttribute("column", formatColumn(arr[0], data)); - } - else { - Element column; - for (int i = 0; i < arr.length; i++) { - column = doc.createElement("column"); - el.appendChild(column); - column.setAttribute("name", formatColumn(arr[i], data)); - } - } - } - - private static void createXMLMappingManyToOne(Element clazz, PageContext pc, Component cfc, Property prop, PropertyCollection propColl, SessionFactoryData data) - throws PageException { - Struct meta = prop.getDynamicAttributes(); - Boolean b; - - Document doc = CommonUtil.getDocument(clazz); - clazz = getJoin(clazz); - - Element m2o = doc.createElement("many-to-one"); - clazz.appendChild(m2o); - - // columns - String linktable = toString(cfc, prop, meta, "linktable", data); - String _columns; - if (!Util.isEmpty(linktable, true)) _columns = toString(cfc, prop, meta, "inversejoincolumn", data); - else _columns = createFKColumnName(cfc, prop, propColl, data);// toString(cfc,prop,meta,"fkcolumn"); - setColumn(doc, m2o, _columns, data); - - // cfc - setForeignEntityName(cfc, prop, meta, m2o, true, data); - - // column - // String str=toString(prop,meta,"column",true); - // m2o.setAttribute("column", str); - - // insert - b = toBoolean(cfc, meta, "insert", data); - if (b != null && !b.booleanValue()) m2o.setAttribute("insert", "false"); - - // update - b = toBoolean(cfc, meta, "update", data); - if (b != null && !b.booleanValue()) m2o.setAttribute("update", "false"); - - // property-ref - String str = toString(cfc, prop, meta, "mappedBy", data); - if (!Util.isEmpty(str, true)) m2o.setAttribute("property-ref", str); - - // update - b = toBoolean(cfc, meta, "unique", data); - if (b != null && b.booleanValue()) m2o.setAttribute("unique", "true"); - - // not-null - b = toBoolean(cfc, meta, "notnull", data); - if (b != null && b.booleanValue()) m2o.setAttribute("not-null", "true"); - - // optimistic-lock - b = toBoolean(cfc, meta, "optimisticLock", data); - if (b != null && !b.booleanValue()) m2o.setAttribute("optimistic-lock", "false"); - - // not-found - b = toBoolean(cfc, meta, "missingRowIgnored", data); - if (b != null && b.booleanValue()) m2o.setAttribute("not-found", "ignore"); - - // index - str = toString(cfc, prop, meta, "index", data); - if (!Util.isEmpty(str, true)) m2o.setAttribute("index", str); - - // unique-key - str = toString(cfc, prop, meta, "uniqueKeyName", data); - if (Util.isEmpty(str, true)) str = toString(cfc, prop, meta, "uniqueKey", data); - if (!Util.isEmpty(str, true)) m2o.setAttribute("unique-key", str); - - // foreign-key - str = toString(cfc, prop, meta, "foreignKeyName", data); - if (Util.isEmpty(str, true)) str = toString(cfc, prop, meta, "foreignKey", data); - if (!Util.isEmpty(str, true)) m2o.setAttribute("foreign-key", str); - - // access - str = toString(cfc, prop, meta, "access", data); - if (!Util.isEmpty(str, true)) m2o.setAttribute("access", str); - - createXMLMappingXToX(m2o, pc, cfc, prop, meta, data); - - } - - private static String formatColumn(String name, SessionFactoryData data) throws PageException { - name = name.trim(); - return escape(HibernateUtil.convertColumnName(data, name)); - } - - /* - * - * - * - * - */ - private static void createXMLMappingXToX(Element x2x, PageContext pc, Component cfc, Property prop, Struct meta, SessionFactoryData data) throws PageException { - x2x.setAttribute("name", prop.getName()); - - // cascade - String str = toString(cfc, prop, meta, "cascade", data); - if (!Util.isEmpty(str, true)) x2x.setAttribute("cascade", str); - - // fetch - str = toString(cfc, prop, meta, "fetch", data); - if (!Util.isEmpty(str, true)) { - str = str.trim().toLowerCase(); - if ("join".equals(str) || "select".equals(str)) x2x.setAttribute("fetch", str); - else throw invalidValue(cfc, prop, "fetch", str, "join,select", data); - // throw new ORMException("invalid value ["+str+"] for attribute [fetch], valid values are - // [join,select]"); - } - - // lazy - setLazy(cfc, prop, meta, x2x, data); - - } - - private static void setLazy(Component cfc, Property prop, Struct meta, Element x2x, SessionFactoryData data) throws PageException { - String str = toString(cfc, prop, meta, "lazy", data); - if (!Util.isEmpty(str, true)) { - str = str.trim(); - String name = x2x.getNodeName(); - Boolean b = CommonUtil.toBoolean(str, null); - - // - // - if ("many-to-one".equals(name) || "one-to-one".equals(name)) { - if (b != null) x2x.setAttribute("lazy", b.booleanValue() ? "proxy" : "false"); - else if ("proxy".equalsIgnoreCase(str)) x2x.setAttribute("lazy", "proxy"); - else if ("no-proxy".equalsIgnoreCase(str)) x2x.setAttribute("lazy", "no-proxy"); - else throw invalidValue(cfc, prop, "lazy", str, "true,false,proxy,no-proxy", data); - } - - // - // - else if ("many-to-many".equals(name) || "key-many-to-one".equals(name)) { - if (b != null) x2x.setAttribute("lazy", b.booleanValue() ? "proxy" : "false"); - else if ("proxy".equalsIgnoreCase(str)) x2x.setAttribute("lazy", "proxy"); - throw invalidValue(cfc, prop, "lazy", str, "true,false,proxy", data); - - } - - else { - if (b != null) x2x.setAttribute("lazy", b.booleanValue() ? "true" : "false"); - else if ("extra".equalsIgnoreCase(str)) x2x.setAttribute("lazy", "extra"); - else throw invalidValue(cfc, prop, "lazy", str, "true,false,extra", data); - } - } - } - - private static void createXMLMappingTimestamp(Element clazz, PageContext pc, Component cfc, Property prop, SessionFactoryData data) throws PageException { - Struct meta = prop.getDynamicAttributes(); - String str; - Boolean b; - - Document doc = CommonUtil.getDocument(clazz); - Element timestamp = doc.createElement("timestamp"); - clazz.appendChild(timestamp); - - timestamp.setAttribute("name", prop.getName()); - - // access - str = toString(cfc, prop, meta, "access", data); - if (!Util.isEmpty(str, true)) timestamp.setAttribute("access", str); - - // column - str = toString(cfc, prop, meta, "column", data); - if (Util.isEmpty(str, true)) str = prop.getName(); - timestamp.setAttribute("column", formatColumn(str, data)); - - // generated - b = toBoolean(cfc, meta, "generated", data); - if (b != null) timestamp.setAttribute("generated", b.booleanValue() ? "always" : "never"); - - // source - str = toString(cfc, prop, meta, "source", data); - if (!Util.isEmpty(str, true)) { - str = str.trim().toLowerCase(); - if ("db".equals(str) || "vm".equals(str)) timestamp.setAttribute("source", str); - else throw invalidValue(cfc, prop, "source", str, "db,vm", data); - } - - // unsavedValue - str = toString(cfc, prop, meta, "unsavedValue", data); - if (!Util.isEmpty(str, true)) { - str = str.trim().toLowerCase(); - if ("null".equals(str) || "undefined".equals(str)) timestamp.setAttribute("unsaved-value", str); - else throw invalidValue(cfc, prop, "unsavedValue", str, "null, undefined", data); - // throw new ORMException("invalid value ["+str+"] for attribute [unsavedValue], valid values are - // [null, undefined]"); - } - } - - private static PageException invalidValue(Component cfc, Property prop, String attrName, String invalid, String valid, SessionFactoryData data) { - String owner = prop.getOwnerName(); - if (Util.isEmpty(owner)) return ExceptionUtil.createException(data, cfc, - "invalid value [" + invalid + "] for attribute [" + attrName + "] of property [" + prop.getName() + "], valid values are [" + valid + "]", null); - return ExceptionUtil.createException(data, cfc, "invalid value [" + invalid + "] for attribute [" + attrName + "] of property [" + prop.getName() + "] of Component [" - + CommonUtil.last(owner, ".") + "], valid values are [" + valid + "]", null); - } - - private static void createXMLMappingVersion(Element clazz, PageContext pc, Component cfc, Property prop, SessionFactoryData data) throws PageException { - Struct meta = prop.getDynamicAttributes(); - - Document doc = CommonUtil.getDocument(clazz); - Element version = doc.createElement("version"); - clazz.appendChild(version); - - version.setAttribute("name", prop.getName()); - - // column - String str = toString(cfc, prop, meta, "column", data); - if (Util.isEmpty(str, true)) str = prop.getName(); - version.setAttribute("column", formatColumn(str, data)); - - // access - str = toString(cfc, prop, meta, "access", data); - if (!Util.isEmpty(str, true)) version.setAttribute("access", str); - - // generated - Object o = meta.get(GENERATED, null); - if (o != null) { - Boolean b = CommonUtil.toBoolean(o, null); - str = null; - if (b != null) { - str = b.booleanValue() ? "always" : "never"; - } - else { - str = CommonUtil.toString(o, null); - if ("always".equalsIgnoreCase(str)) str = "always"; - else if ("never".equalsIgnoreCase(str)) str = "never"; - else throw invalidValue(cfc, prop, "generated", o.toString(), "true,false,always,never", data); - // throw new ORMException("invalid value ["+o+"] for attribute [generated] of property - // ["+prop.getName()+"], valid values are [true,false,always,never]"); - } - version.setAttribute("generated", str); - } - - // insert - Boolean b = toBoolean(cfc, meta, "insert", data); - if (b != null && !b.booleanValue()) version.setAttribute("insert", "false"); - - // type - String typeName = "dataType"; - str = toString(cfc, prop, meta, typeName, data); - if (Util.isEmpty(str, true)) { - typeName = "ormType"; - str = toString(cfc, prop, meta, typeName, data); - } - if (!Util.isEmpty(str, true)) { - str = str.trim().toLowerCase(); - if ("int".equals(str) || "integer".equals(str)) version.setAttribute("type", "integer"); - else if ("long".equals(str)) version.setAttribute("type", "long"); - else if ("short".equals(str)) version.setAttribute("type", "short"); - else throw invalidValue(cfc, prop, typeName, str, "int,integer,long,short", data); - // throw new ORMException("invalid value ["+str+"] for attribute ["+typeName+"], valid values are - // [int,integer,long,short]"); - } - else version.setAttribute("type", "integer"); - - // unsavedValue - str = toString(cfc, prop, meta, "unsavedValue", data); - if (!Util.isEmpty(str, true)) { - str = str.trim().toLowerCase(); - if ("null".equals(str) || "negative".equals(str) || "undefined".equals(str)) version.setAttribute("unsaved-value", str); - else throw invalidValue(cfc, prop, "unsavedValue", str, "null, negative, undefined", data); - // throw new ORMException("invalid value ["+str+"] for attribute [unsavedValue], valid values are - // [null, negative, undefined]"); - } - } - - private static String toString(Component cfc, Property prop, Struct sct, String key, SessionFactoryData data) throws PageException { - return toString(cfc, prop, sct, key, false, data); - } - - private static String toString(Component cfc, Property prop, Struct sct, String key, boolean throwErrorWhenNotExist, SessionFactoryData data) throws PageException { - return toString(cfc, prop, sct, CommonUtil.createKey(key), throwErrorWhenNotExist, data); - } - - private static String toString(Component cfc, Property prop, Struct sct, Collection.Key key, boolean throwErrorWhenNotExist, SessionFactoryData data) throws PageException { - Object value = sct.get(key, null); - if (value == null) { - if (throwErrorWhenNotExist) { - if (prop == null) throw ExceptionUtil.createException(data, cfc, "attribute [" + key + "] is required", null); - throw ExceptionUtil.createException(data, cfc, "attribute [" + key + "] of property [" + prop.getName() + "] of Component [" + _getCFCName(prop) + "] is required", - null); - } - return null; - } - - String str = CommonUtil.toString(value, null); - if (str == null) { - if (prop == null) - throw ExceptionUtil.createException(data, cfc, "invalid type [" + CommonUtil.toTypeName(value) + "] for attribute [" + key + "], value must be a string", null); - throw ExceptionUtil.createException(data, cfc, "invalid type [" + CommonUtil.toTypeName(value) + "] for attribute [" + key + "] of property [" + prop.getName() - + "] of Component [" + _getCFCName(prop) + "], value must be a string", null); - } - return str; - } - - private static String _getCFCName(Property prop) { - String owner = prop.getOwnerName(); - return CommonUtil.last(owner, "."); - } - - private static Boolean toBoolean(Component cfc, Struct sct, String key, SessionFactoryData data) throws PageException { - Object value = sct.get(CommonUtil.createKey(key), null); - if (value == null) return null; - - Boolean b = CommonUtil.toBoolean(value, null); - if (b == null) - throw ExceptionUtil.createException(data, cfc, "invalid type [" + CommonUtil.toTypeName(value) + "] for attribute [" + key + "], value must be a boolean", null); - return b; - } - - private static Integer toInteger(Component cfc, Struct sct, String key, SessionFactoryData data) throws PageException { - Object value = sct.get(CommonUtil.createKey(key), null); - if (value == null) return null; - - Integer i = CommonUtil.toInteger(value, null); - if (i == null) - throw ExceptionUtil.createException(data, cfc, "invalid type [" + CommonUtil.toTypeName(value) + "] for attribute [" + key + "], value must be a numeric value", null); - return i; - } - + /** + * Hibernate DOCTYPE mapping ID + * + * @see Hibernate documentation schema-generation-database-objects + */ + public static final String HIBERNATE_3_PUBLIC_ID = "-//Hibernate/Hibernate Mapping DTD 3.0//EN"; + + /** + * Hibernate doctype reference + * + * @see Hibernate documentation schema-generation-database-objects + */ + // public static final String HIBERNATE_3_SYSTEM_ID = "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"; + public static final String HIBERNATE_3_SYSTEM_ID = "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"; + + /** + * Full XML doctype for Hibernate mappings + * + * @see Hibernate documentation schema-generation-database-objects + */ + public static final String HIBERNATE_3_DOCTYPE_DEFINITION = ""; + + private static final Collection.Key PROPERTY = CommonUtil.createKey("property"); + private static final Collection.Key LINK_TABLE = CommonUtil.createKey("linktable"); + private static final Collection.Key CFC = CommonUtil.createKey("cfc"); + private static final Collection.Key GENERATOR = CommonUtil.createKey("generator"); + private static final Collection.Key PARAMS = CommonUtil.createKey("params"); + private static final Collection.Key SEQUENCE = CommonUtil.createKey("sequence"); + private static final Collection.Key UNIQUE_KEY_NAME = CommonUtil.createKey("uniqueKeyName"); + private static final Collection.Key GENERATED = CommonUtil.createKey("generated"); + private static final Collection.Key FIELDTYPE = CommonUtil.createKey("fieldtype"); + private static final Collection.Key KEY = CommonUtil.createKey("key"); + private static final Collection.Key TYPE = CommonUtil.createKey("type"); + + /** + * Generate an XML node tree defining a Hibernate mapping for the given Component + * + * @param pc + * Lucee PageContext object + * @param dc + * Lucee DatasourceConnection object + * @param cfc + * Lucee Component to create the mapping XML for + * @param data + * SessionFactoryData instance to pull Hibernate metadata from + * + * @return XML root node + * + * @throws PageException + */ + public static Element createXMLMapping(PageContext pc, DatasourceConnection dc, Component cfc, + SessionFactoryData data) throws PageException { + Document doc = XMLUtil.newDocument(); + + Element hibernateMapping = doc.createElement("hibernate-mapping"); + doc.appendChild(hibernateMapping); + + // MUST Support for embeded objects + Struct meta = cfc.getMetaData(pc); + + String extend = cfc.getExtends(); + boolean isClass = Util.isEmpty(extend); + + // MZ: Fetches all inherited persistent properties + // Property[] _props=getAllPersistentProperties(pc,cfc,dc,meta,isClass); + + Property[] _props = getProperties(pc, cfc, dc, meta, isClass, true, data); + + Map joins = new HashMap(); + PropertyCollection propColl = splitJoins(cfc, joins, _props, data); + + StringBuilder comment = new StringBuilder(); + comment.append("\nsource:").append(cfc.getPageSource().getDisplayPath()); + comment.append("\ncompilation-time:") + .append(CommonUtil.createDateTime(HibernateUtil.getCompileTime(pc, cfc.getPageSource()))); + comment.append("\ndatasource:").append(dc.getDatasource().getName()); + comment.append("\n"); + + hibernateMapping.appendChild(doc.createComment(comment.toString())); + + // print.e(cfc.getAbsName()+";"+isClass+" -> "+cfci.getBaseAbsName()+":"+cfci.isBasePeristent()); + if (!isClass && !cfc.isBasePeristent()) { + isClass = true; + } + + Element join = null; + boolean doTable = true; + + Element clazz; + if (isClass) { + clazz = doc.createElement("class"); + hibernateMapping.appendChild(clazz); + } + // extended CFC + else { + // MZ: Fetches one level deep + _props = getProperties(pc, cfc, dc, meta, isClass, false, data); + // MZ: Reinitiate the property collection + propColl = splitJoins(cfc, joins, _props, data); + + String ext = CommonUtil.last(extend, ".").trim(); + Component base = data.getEntityByCFCName(ext, false); + ext = HibernateCaster.getEntityName(base); + + String discriminatorValue = toString(cfc, null, meta, "discriminatorValue", data); + if (!Util.isEmpty(discriminatorValue, true)) { + doTable = false; + clazz = doc.createElement("subclass"); + hibernateMapping.appendChild(clazz); + // addClassAttributes(classNode); + clazz.setAttribute("extends", ext); + clazz.setAttribute("discriminator-value", discriminatorValue); + + String joincolumn = toString(cfc, null, meta, "joincolumn", false, data); + if (!Util.isEmpty(joincolumn)) { + join = doc.createElement("join"); + clazz.appendChild(join); + doTable = true; + Element key = doc.createElement("key"); + join.appendChild(key); + key.setAttribute("column", formatColumn(joincolumn, data)); + } + + } else { + // MZ: Match on joinColumn for a joined subclass, otherwise use a union subclass + String joinColumn = toString(cfc, null, meta, "joincolumn", false, data); + if (!Util.isEmpty(joinColumn, true)) { + clazz = doc.createElement("joined-subclass"); + hibernateMapping.appendChild(clazz); + clazz.setAttribute("extends", ext); + Element key = doc.createElement("key"); + clazz.appendChild(key); + key.setAttribute("column", formatColumn(joinColumn, data)); + } else { + // MZ: When no joinColumn exists, default to an explicit table per class + clazz = doc.createElement("union-subclass"); + clazz.setAttribute("extends", ext); + doTable = true; + hibernateMapping.appendChild(clazz); + } + + } + } + + // createXMLMappingTuplizer(clazz,pc); + + addGeneralClassAttributes(pc, cfc, meta, clazz, data); + String tableName = getTableName(pc, meta, cfc, data); + + if (join != null) + clazz = join; + if (doTable) + addGeneralTableAttributes(pc, dc, cfc, meta, clazz, data); + + Struct columnsInfo = null; + if (data.getORMConfiguration().useDBForMapping()) { + columnsInfo = data.getTableInfo(dc, getTableName(pc, meta, cfc, data)); + } + + if (isClass) + setCacheStrategy(cfc, null, doc, meta, clazz, data); + + // id + if (isClass) + addId(cfc, doc, clazz, meta, propColl, columnsInfo, tableName, data); + + // discriminator + if (isClass) + addDiscriminator(cfc, doc, clazz, pc, meta, data); + + // version + if (isClass) + addVersion(cfc, clazz, pc, propColl, columnsInfo, tableName, data); + + // property + addProperty(cfc, clazz, pc, propColl, columnsInfo, tableName, data); + + // relations + addRelation(cfc, clazz, pc, propColl, columnsInfo, tableName, dc, data); + + // collection + addCollection(cfc, clazz, pc, propColl, columnsInfo, tableName, data); + + // join + addJoin(cfc, clazz, pc, joins, columnsInfo, tableName, dc, data); + + return hibernateMapping; + } + + private static Property[] getProperties(PageContext pc, Component cfc, DatasourceConnection dc, Struct meta, + boolean isClass, boolean recursivePersistentMappedSuperclass, SessionFactoryData data) + throws PageException, PageException { + Property[] _props; + if (recursivePersistentMappedSuperclass) { + _props = CommonUtil.getProperties(cfc, true, true, true, true); + } else { + _props = cfc.getProperties(true, false, false, false); + } + + if (isClass && _props.length == 0 && data.getORMConfiguration().useDBForMapping()) { + if (meta == null) + meta = cfc.getMetaData(pc); + _props = HibernateUtil.createPropertiesFromTable(dc, getTableName(pc, meta, cfc, data)); + } + return _props; + } + + private static void addId(Component cfc, Document doc, Element clazz, Struct meta, PropertyCollection propColl, + Struct columnsInfo, String tableName, SessionFactoryData data) throws PageException { + Property[] _ids = getIds(cfc, propColl, data); + + // Property[] _ids = ids.toArray(new Property[ids.size()]); + + if (_ids.length == 1) + createXMLMappingId(cfc, clazz, _ids[0], columnsInfo, tableName, data); + else if (_ids.length > 1) + createXMLMappingCompositeId(cfc, clazz, _ids, columnsInfo, tableName, data); + else + throw ExceptionUtil.createException(data, cfc, + "missing id property for entity [" + HibernateCaster.getEntityName(cfc) + "]", null); + } + + private static PropertyCollection splitJoins(Component cfc, Map joins, Property[] props, + SessionFactoryData data) { + Struct sct = CommonUtil.createStruct(); + ArrayList others = new ArrayList(); + java.util.List list; + String table; + Property prop; + String fieldType; + boolean isJoin; + for (int i = 0; i < props.length; i++) { + prop = props[i]; + table = getTable(cfc, prop, data); + // joins + if (!Util.isEmpty(table, true)) { + isJoin = true; + // wrong field type + try { + fieldType = toString(cfc, prop, sct, FIELDTYPE, false, data); + + if ("collection".equalsIgnoreCase(fieldType)) + isJoin = false; + else if ("primary".equals(fieldType)) + isJoin = false; + else if ("version".equals(fieldType)) + isJoin = false; + else if ("timestamp".equals(fieldType)) + isJoin = false; + } catch (PageException e) { + } + + // missing column + String columns = null; + try { + if (CommonUtil.isRelated(props[i])) { + columns = toString(cfc, props[i], prop.getDynamicAttributes(), "fkcolumn", data); + } else { + columns = toString(cfc, props[i], prop.getDynamicAttributes(), "joincolumn", data); + } + } catch (PageException e) { + } + if (Util.isEmpty(columns)) + isJoin = false; + + if (isJoin) { + table = table.trim(); + list = (java.util.List) sct.get(table, null); + if (list == null) { + list = new ArrayList(); + sct.setEL(CommonUtil.createKey(table), list); + } + list.add(prop); + continue; + } + } + others.add(prop); + } + + // fill to joins + Iterator> it = sct.entryIterator(); + Entry e; + while (it.hasNext()) { + e = it.next(); + list = (java.util.List) e.getValue(); + joins.put(e.getKey().getString(), new PropertyCollection(e.getKey().getString(), list)); + } + + return new PropertyCollection(null, others); + } + + private static Property[] getIds(Component cfc, PropertyCollection pc, SessionFactoryData data) { + return getIds(cfc, pc.getProperties(), pc.getTableName(), false, data); + } + + private static Property[] getIds(Component cfc, Property[] props, String tableName, boolean ignoreTableName, + SessionFactoryData data) { + ArrayList ids = new ArrayList(); + for (int y = 0; y < props.length; y++) { + if (!ignoreTableName && !hasTable(cfc, props[y], tableName, data)) + continue; + + String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, null), null); + if ("id".equalsIgnoreCase(fieldType) || CommonUtil.listFindNoCaseIgnoreEmpty(fieldType, "id", ',') != -1) + ids.add(props[y]); + } + + // no id field defined + if (ids.size() == 0) { + String fieldType; + for (int y = 0; y < props.length; y++) { + if (!ignoreTableName && !hasTable(cfc, props[y], tableName, data)) + continue; + fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, null), null); + if (Util.isEmpty(fieldType, true) && props[y].getName().equalsIgnoreCase("id")) { + ids.add(props[y]); + props[y].getDynamicAttributes().setEL(FIELDTYPE, "id"); + } + } + } + + // still no id field defined + if (ids.size() == 0 && props.length > 0) { + String owner = props[0].getOwnerName(); + if (!Util.isEmpty(owner)) + owner = CommonUtil.last(owner, ".").trim(); + + String fieldType; + if (!Util.isEmpty(owner)) { + String id = owner + "id"; + for (int y = 0; y < props.length; y++) { + if (!ignoreTableName && !hasTable(cfc, props[y], tableName, data)) + continue; + fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, null), null); + if (Util.isEmpty(fieldType, true) && props[y].getName().equalsIgnoreCase(id)) { + ids.add(props[y]); + props[y].getDynamicAttributes().setEL(FIELDTYPE, "id"); + } + } + } + } + return ids.toArray(new Property[ids.size()]); + } + + private static void addVersion(Component cfc, Element clazz, PageContext pc, PropertyCollection propColl, + Struct columnsInfo, String tableName, SessionFactoryData data) throws PageException { + Property[] props = propColl.getProperties(); + for (int y = 0; y < props.length; y++) { + String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, null), null); + if ("version".equalsIgnoreCase(fieldType)) + createXMLMappingVersion(clazz, pc, cfc, props[y], data); + else if ("timestamp".equalsIgnoreCase(fieldType)) + createXMLMappingTimestamp(clazz, pc, cfc, props[y], data); + } + } + + private static void addCollection(Component cfc, Element clazz, PageContext pc, PropertyCollection propColl, + Struct columnsInfo, String tableName, SessionFactoryData data) throws PageException { + Property[] props = propColl.getProperties(); + for (int y = 0; y < props.length; y++) { + String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, "column"), "column"); + if ("collection".equalsIgnoreCase(fieldType)) + createXMLMappingCollection(clazz, pc, cfc, props[y], data); + } + } + + private static void addJoin(Component cfc, Element clazz, PageContext pc, Map joins, + Struct columnsInfo, String tableName, DatasourceConnection dc, SessionFactoryData data) + throws PageException { + + Iterator> it = joins.entrySet().iterator(); + Entry entry; + while (it.hasNext()) { + entry = it.next(); + addJoin(cfc, pc, columnsInfo, clazz, entry.getValue(), dc, data); + } + + } + + private static void addJoin(Component cfc, PageContext pc, Struct columnsInfo, Element clazz, + PropertyCollection coll, DatasourceConnection dc, SessionFactoryData data) throws PageException { + String table = coll.getTableName(); + Property[] properties = coll.getProperties(); + if (properties.length == 0) + return; + + Document doc = XMLUtil.getDocument(clazz); + + Element join = doc.createElement("join"); + clazz.appendChild(join); + + join.setAttribute("table", escape(HibernateUtil.convertTableName(data, coll.getTableName()))); + // addTableInfo(joinNode, table, schema, catalog); + + Property first = properties[0]; + String schema = null, catalog = null, mappedBy = null, columns = null; + if (CommonUtil.isRelated(first)) { + catalog = toString(cfc, first, first.getDynamicAttributes(), "linkcatalog", data); + schema = toString(cfc, first, first.getDynamicAttributes(), "linkschema", data); + columns = toString(cfc, first, first.getDynamicAttributes(), "fkcolumn", data); + + } else { + catalog = toString(cfc, first, first.getDynamicAttributes(), "catalog", data); + schema = toString(cfc, first, first.getDynamicAttributes(), "schema", data); + mappedBy = toString(cfc, first, first.getDynamicAttributes(), "mappedby", data); + columns = toString(cfc, first, first.getDynamicAttributes(), "joincolumn", data); + } + + if (!Util.isEmpty(catalog)) + join.setAttribute("catalog", catalog); + if (!Util.isEmpty(schema)) + join.setAttribute("schema", schema); + + Element key = doc.createElement("key"); + join.appendChild(key); + if (!Util.isEmpty(mappedBy)) + key.setAttribute("property-ref", mappedBy); + setColumn(doc, key, columns, data); + + addProperty(cfc, join, pc, coll, columnsInfo, table, data); + int count = addRelation(cfc, join, pc, coll, columnsInfo, table, dc, data); + + if (count > 0) + join.setAttribute("inverse", "true"); + + } + + private static int addRelation(Component cfc, Element clazz, PageContext pc, PropertyCollection propColl, + Struct columnsInfo, String tableName, DatasourceConnection dc, SessionFactoryData data) + throws PageException { + Property[] props = propColl.getProperties(); + int count = 0; + for (int y = 0; y < props.length; y++) { + String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, "column"), "column"); + if ("one-to-one".equalsIgnoreCase(fieldType)) { + createXMLMappingOneToOne(clazz, pc, cfc, props[y], data); + count++; + } else if ("many-to-one".equalsIgnoreCase(fieldType)) { + createXMLMappingManyToOne(clazz, pc, cfc, props[y], propColl, data); + count++; + } else if ("one-to-many".equalsIgnoreCase(fieldType)) { + createXMLMappingOneToMany(dc, cfc, propColl, clazz, pc, props[y], data); + count++; + } else if ("many-to-many".equalsIgnoreCase(fieldType)) { + createXMLMappingManyToMany(dc, cfc, propColl, clazz, pc, props[y], data); + count++; + } + } + return count; + } + + private static void addProperty(Component cfc, Element clazz, PageContext pc, PropertyCollection propColl, + Struct columnsInfo, String tableName, SessionFactoryData data) throws PageException { + Property[] props = propColl.getProperties(); + for (int y = 0; y < props.length; y++) { + String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(FIELDTYPE, "column"), "column"); + if ("column".equalsIgnoreCase(fieldType)) + createXMLMappingProperty(clazz, pc, cfc, props[y], columnsInfo, tableName, data); + } + } + + private static void addDiscriminator(Component cfc, Document doc, Element clazz, PageContext pc, Struct meta, + SessionFactoryData data) throws DOMException, PageException { + + String str = toString(cfc, null, meta, "discriminatorColumn", data); + if (!Util.isEmpty(str, true)) { + Element disc = doc.createElement("discriminator"); + clazz.appendChild(disc); + disc.setAttribute("column", formatColumn(str, data)); + } + + } + + private static void addGeneralClassAttributes(PageContext pc, Component cfc, Struct meta, Element clazz, + SessionFactoryData data) throws PageException { + + // name + clazz.setAttribute("node", HibernateCaster.toComponentName(cfc)); + + // entity-name + String str = toString(cfc, null, meta, "entityname", data); + if (Util.isEmpty(str, true)) + str = HibernateCaster.getEntityName(cfc); + clazz.setAttribute("entity-name", str); + + // batch-size + Integer i = toInteger(cfc, meta, "batchsize", data); + if (i != null && i.intValue() > 0) + clazz.setAttribute("batch-size", CommonUtil.toString(i)); + + // dynamic-insert + Boolean b = toBoolean(cfc, meta, "dynamicinsert", data); + if (b != null && b.booleanValue()) + clazz.setAttribute("dynamic-insert", "true"); + + // dynamic-update + b = toBoolean(cfc, meta, "dynamicupdate", data); + if (b != null && b.booleanValue()) + clazz.setAttribute("dynamic-update", "true"); + + // lazy (dtd defintion:) + b = toBoolean(cfc, meta, "lazy", data); + if (b == null) + b = Boolean.TRUE; + clazz.setAttribute("lazy", CommonUtil.toString(b.booleanValue())); + + // select-before-update + b = toBoolean(cfc, meta, "selectbeforeupdate", data); + if (b != null && b.booleanValue()) + clazz.setAttribute("select-before-update", "true"); + + // optimistic-lock + str = toString(cfc, null, meta, "optimisticLock", data); + if (!Util.isEmpty(str, true)) { + str = str.trim().toLowerCase(); + if ("all".equals(str) || "dirty".equals(str) || "none".equals(str) || "version".equals(str)) + clazz.setAttribute("optimistic-lock", str); + else + throw ExceptionUtil.createException(data, cfc, "invalid value [" + str + + "] for attribute [optimisticlock] of tag [component], valid values are [all,dirty,none,version]", + null); + } + + // read-only + b = toBoolean(cfc, meta, "readOnly", data); + if (b != null && b.booleanValue()) + clazz.setAttribute("mutable", "false"); + + // rowid + str = toString(cfc, null, meta, "rowid", data); + if (!Util.isEmpty(str, true)) + clazz.setAttribute("rowid", str); + + // where + str = toString(cfc, null, meta, "where", data); + if (!Util.isEmpty(str, true)) + clazz.setAttribute("where", str); + + } + + private static void addGeneralTableAttributes(PageContext pc, DatasourceConnection dc, Component cfc, Struct meta, + Element clazz, SessionFactoryData data) throws PageException { + // table + clazz.setAttribute("table", escape(getTableName(pc, meta, cfc, data))); + + // catalog + String str = toString(cfc, null, meta, "catalog", data); + if (str == null) // empty string is allowed as input + str = ORMConfigurationUtil.getCatalog(data.getORMConfiguration(), dc.getDatasource().getName()); + + if (!Util.isEmpty(str, true)) + clazz.setAttribute("catalog", str); + + // schema + str = toString(cfc, null, meta, "schema", data); + if (str == null)// empty string is allowed as input + str = ORMConfigurationUtil.getSchema(data.getORMConfiguration(), dc.getDatasource().getName()); + if (!Util.isEmpty(str, true)) + clazz.setAttribute("schema", str); + + } + + private static String escape(String str) { + if (HibernateUtil.isKeyword(str)) + return "`" + str + "`"; + return str; + } + + private static String getTableName(PageContext pc, Struct meta, Component cfc, SessionFactoryData data) + throws PageException { + String tableName = toString(cfc, null, meta, "table", data); + if (Util.isEmpty(tableName, true)) + tableName = HibernateCaster.getEntityName(cfc); + return HibernateUtil.convertTableName(data, tableName); + } + + private static String getTable(Component cfc, Property prop, SessionFactoryData data) { + try { + return HibernateUtil.convertTableName(data, + toString(cfc, prop, prop.getDynamicAttributes(), "table", data)); + } catch (PageException e) { + return null; + } + } + + private static boolean hasTable(Component cfc, Property prop, String tableName, SessionFactoryData data) { + String t = getTable(cfc, prop, data); + boolean left = Util.isEmpty(t, true); + boolean right = Util.isEmpty(tableName, true); + if (left && right) + return true; + if (left || right) + return false; + return tableName.trim().equalsIgnoreCase(t.trim()); + } + + private static void createXMLMappingCompositeId(Component cfc, Element clazz, Property[] props, Struct columnsInfo, + String tableName, SessionFactoryData data) throws PageException { + Struct meta; + + Document doc = XMLUtil.getDocument(clazz); + Element cid = doc.createElement("composite-id"); + clazz.appendChild(cid); + + // cid.setAttribute("mapped","true"); + + Property prop; + String fieldType; + // ids + for (int y = 0; y < props.length; y++) { + prop = props[y]; + + // do not add "key-property" for many-to-one + meta = prop.getDynamicAttributes(); + fieldType = toString(cfc, prop, meta, "fieldType", data); + if (CommonUtil.listFindNoCaseIgnoreEmpty(fieldType, "many-to-one", ',') != -1) + continue; + + Element key = doc.createElement("key-property"); + cid.appendChild(key); + + // name + key.setAttribute("name", prop.getName()); + + // column + Element column = doc.createElement("column"); + key.appendChild(column); + + String str = toString(cfc, prop, meta, "column", data); + if (Util.isEmpty(str, true)) + str = prop.getName(); + column.setAttribute("name", formatColumn(str, data)); + ColumnInfo info = getColumnInfo(columnsInfo, tableName, str, null); + + str = toString(cfc, prop, meta, "sqltype", data); + if (!Util.isEmpty(str, true)) + column.setAttribute("sql-type", str); + str = toString(cfc, prop, meta, "length", data); + if (!Util.isEmpty(str, true)) + column.setAttribute("length", str); + + String generator = toString(cfc, prop, meta, "generator", data); + String type = getType(info, cfc, prop, meta, getDefaultTypeForGenerator(generator, "string"), data); + if (!Util.isEmpty(type)) + key.setAttribute("type", type); + } + + // many-to-one + for (int y = 0; y < props.length; y++) { + prop = props[y]; + meta = prop.getDynamicAttributes(); + fieldType = toString(cfc, prop, meta, "fieldType", data); + if (CommonUtil.listFindNoCaseIgnoreEmpty(fieldType, "many-to-one", ',') == -1) + continue; + + Element key = doc.createElement("key-many-to-one"); + cid.appendChild(key); + + // name + key.setAttribute("name", prop.getName()); + + // entity-name + setForeignEntityName(cfc, prop, meta, key, false, data); + + // fkcolum + String str = toString(cfc, prop, meta, "fkcolumn", data); + setColumn(doc, key, str, data); + + // lazy + setLazy(cfc, prop, meta, key, data); + } + } + + private static void createXMLMappingId(Component cfc, Element clazz, Property prop, Struct columnsInfo, + String tableName, SessionFactoryData data) throws PageException { + Struct meta = prop.getDynamicAttributes(); + String str; + + Document doc = XMLUtil.getDocument(clazz); + Element id = doc.createElement("id"); + clazz.appendChild(id); + + // access + str = toString(cfc, prop, meta, "access", data); + if (!Util.isEmpty(str, true)) + id.setAttribute("access", str); + + // name + id.setAttribute("name", prop.getName()); + + // column + Element column = doc.createElement("column"); + id.appendChild(column); + + str = toString(cfc, prop, meta, "column", data); + if (Util.isEmpty(str, true)) + str = prop.getName(); + column.setAttribute("name", formatColumn(str, data)); + ColumnInfo info = getColumnInfo(columnsInfo, tableName, str, null); + StringBuilder foreignCFC = new StringBuilder(); + String generator = createXMLMappingGenerator(id, cfc, prop, foreignCFC, data); + + str = toString(cfc, prop, meta, "length", data); + if (!Util.isEmpty(str, true)) + column.setAttribute("length", str); + + // type + String type = getType(info, cfc, prop, meta, getDefaultTypeForGenerator(generator, foreignCFC, data), data); + // print.o(prop.getName()+":"+type+"::"+getDefaultTypeForGenerator(generator,foreignCFC)); + if (!Util.isEmpty(type)) + id.setAttribute("type", type); + + // unsaved-value + str = toString(cfc, prop, meta, "unsavedValue", data); + if (str != null) + id.setAttribute("unsaved-value", str); + + } + + private static String getDefaultTypeForGenerator(String generator, StringBuilder foreignCFC, + SessionFactoryData data) { + String value = getDefaultTypeForGenerator(generator, null); + if (value != null) + return value; + + if ("foreign".equalsIgnoreCase(generator)) { + if (!Util.isEmpty(foreignCFC.toString())) { + try { + Component cfc = data.getEntityByCFCName(foreignCFC.toString(), false); + if (cfc != null) { + Property[] ids = getIds(cfc, cfc.getProperties(true, false, false, false), null, true, data); + if (ids != null && ids.length > 0) { + Property id = ids[0]; + id.getDynamicAttributes(); + Struct meta = id.getDynamicAttributes(); + if (meta != null) { + String type = CommonUtil.toString(meta.get(TYPE, null)); + + if (!Util.isEmpty(type) + && (!type.equalsIgnoreCase("any") && !type.equalsIgnoreCase("object"))) { + return type; + } + + String g = CommonUtil.toString(meta.get(GENERATOR, null)); + if (!Util.isEmpty(g)) { + return getDefaultTypeForGenerator(g, foreignCFC, data); + } + + } + } + } + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + return "string"; + } + + return "string"; + } + + public static String getDefaultTypeForGenerator(String generator, String defaultValue) { + if ("increment".equalsIgnoreCase(generator)) + return "integer"; + if ("identity".equalsIgnoreCase(generator)) + return "integer"; + if ("native".equalsIgnoreCase(generator)) + return "integer"; + if ("seqhilo".equalsIgnoreCase(generator)) + return "string"; + if ("uuid".equalsIgnoreCase(generator)) + return "string"; + if ("guid".equalsIgnoreCase(generator)) + return "string"; + if ("select".equalsIgnoreCase(generator)) + return "string"; + return defaultValue; + } + + private static String getType(ColumnInfo info, Component cfc, Property prop, Struct meta, String defaultValue, + SessionFactoryData data) throws PageException { + // ormType + String type = toString(cfc, prop, meta, "ormType", data); + // type=HibernateCaster.toHibernateType(info,type,null); + + // dataType + if (Util.isEmpty(type, true)) { + type = toString(cfc, prop, meta, "dataType", data); + // type=HibernateCaster.toHibernateType(info,type,null); + } + + // type + if (Util.isEmpty(type, true)) { + type = prop.getType(); + // type=HibernateCaster.toHibernateType(info,type,null); + } + + // type from db info + if (Util.isEmpty(type, true)) { + if (info != null) { + type = info.getTypeName(); + // type=HibernateCaster.toHibernateType(info,type,defaultValue); + } else + return defaultValue; + } + return HibernateCaster.toHibernateType(info, type, defaultValue); + } + + private static ColumnInfo getColumnInfo(Struct columnsInfo, String tableName, String columnName, + ColumnInfo defaultValue) { + if (columnsInfo != null) { + ColumnInfo info = (ColumnInfo) columnsInfo.get(CommonUtil.createKey(columnName), null); + if (info == null) + return defaultValue; + return info; + } + return defaultValue; + } + + private static String createXMLMappingGenerator(Element id, Component cfc, Property prop, StringBuilder foreignCFC, + SessionFactoryData data) throws PageException { + Struct meta = prop.getDynamicAttributes(); + + // generator + String className = toString(cfc, prop, meta, "generator", data); + if (Util.isEmpty(className, true)) + return null; + + Document doc = XMLUtil.getDocument(id); + Element generator = doc.createElement("generator"); + id.appendChild(generator); + + generator.setAttribute("class", className); + + // print.e("generator:"+className); + + // params + Object obj = meta.get(PARAMS, null); + // if(obj!=null){ + Struct sct = null; + if (obj == null) + obj = CommonUtil.createStruct(); + else if (obj instanceof String) + obj = CommonUtil.convertToSimpleMap((String) obj); + + if (CommonUtil.isStruct(obj)) + sct = CommonUtil.toStruct(obj); + else + throw ExceptionUtil.createException(data, cfc, "invalid value for attribute [params] of tag [property]", + null); + className = className.trim().toLowerCase(); + + // special classes + if ("foreign".equals(className)) { + if (!sct.containsKey(PROPERTY)) + sct.setEL(PROPERTY, toString(cfc, prop, meta, PROPERTY, true, data)); + + if (sct.containsKey(PROPERTY)) { + String p = CommonUtil.toString(sct.get(PROPERTY), null); + if (!Util.isEmpty(p)) + foreignCFC.append(p); + } + + } else if ("select".equals(className)) { + // print.e("select:"+toString(meta, "selectKey",true)); + if (!sct.containsKey(KEY)) + sct.setEL(KEY, toString(cfc, prop, meta, "selectKey", true, data)); + } else if ("sequence".equals(className)) { + if (!sct.containsKey(SEQUENCE)) + sct.setEL(SEQUENCE, toString(cfc, prop, meta, "sequence", true, data)); + } + + // Key[] keys = sct.keys(); + Iterator> it = sct.entryIterator(); + Entry e; + Element param; + while (it.hasNext()) { + e = it.next(); + param = doc.createElement("param"); + generator.appendChild(param); + + param.setAttribute("name", e.getKey().getLowerString()); + param.appendChild(doc.createTextNode(CommonUtil.toString(e.getValue()))); + + } + // } + return className; + } + + private static void createXMLMappingProperty(Element clazz, PageContext pc, Component cfc, Property prop, + Struct columnsInfo, String tableName, SessionFactoryData data) throws PageException { + Struct meta = prop.getDynamicAttributes(); + + // get table name + String columnName = toString(cfc, prop, meta, "column", data); + if (Util.isEmpty(columnName, true)) + columnName = prop.getName(); + + ColumnInfo info = getColumnInfo(columnsInfo, tableName, columnName, null); + + Document doc = XMLUtil.getDocument(clazz); + final Element property = doc.createElement("property"); + clazz.appendChild(property); + + // name + property.setAttribute("name", prop.getName()); + + // type + String str = getType(info, cfc, prop, meta, "string", data); + property.setAttribute("type", str); + + // formula or column + str = toString(cfc, prop, meta, "formula", data); + Boolean b; + if (!Util.isEmpty(str, true)) { + property.setAttribute("formula", "(" + str + ")"); + } else { + String length = null; + // property.setAttribute("column",columnName); + + Element column = doc.createElement("column"); + property.appendChild(column); + column.setAttribute("name", escape(HibernateUtil.convertColumnName(data, columnName))); + + // check + str = toString(cfc, prop, meta, "check", data); + if (!Util.isEmpty(str, true)) + column.setAttribute("check", str); + + // default + str = toString(cfc, prop, meta, "dbDefault", data); + if (!Util.isEmpty(str, true)) + column.setAttribute("default", str); + + // index + str = toString(cfc, prop, meta, "index", data); + if (!Util.isEmpty(str, true)) + column.setAttribute("index", str); + + // length + Integer i = toInteger(cfc, meta, "length", data); + if (i != null && i > 0) { + length = CommonUtil.toString(i.intValue()); + column.setAttribute("length", length); + } + + // not-null + b = toBoolean(cfc, meta, "notnull", data); + if (b != null && b.booleanValue()) + column.setAttribute("not-null", "true"); + + // precision + i = toInteger(cfc, meta, "precision", data); + if (i != null && i > -1) + column.setAttribute("precision", CommonUtil.toString(i.intValue())); + + // scale + i = toInteger(cfc, meta, "scale", data); + if (i != null && i > -1) + column.setAttribute("scale", CommonUtil.toString(i.intValue())); + + // sql-type + str = toString(cfc, prop, meta, "sqltype", data); + if (!Util.isEmpty(str, true)) { + if ((str == "varchar" || str == "nvarchar") && length != null) { + str += "(" + length + ")"; + } + column.setAttribute("sql-type", str); + } + + // unique + b = toBoolean(cfc, meta, "unique", data); + if (b != null && b.booleanValue()) + column.setAttribute("unique", "true"); + + // unique-key + str = toString(cfc, prop, meta, "uniqueKey", data); + if (Util.isEmpty(str)) + str = CommonUtil.toString(meta.get(UNIQUE_KEY_NAME, null), null); + if (!Util.isEmpty(str, true)) + column.setAttribute("unique-key", str); + + } + + // generated + str = toString(cfc, prop, meta, "generated", data); + if (!Util.isEmpty(str, true)) { + str = str.trim().toLowerCase(); + + if ("always".equals(str) || "insert".equals(str) || "never".equals(str)) + property.setAttribute("generated", str); + else + throw invalidValue(cfc, prop, "generated", str, "always,insert,never", data); + // throw new ORMException("invalid value ["+str+"] for attribute [generated] of column + // ["+columnName+"], valid values are [always,insert,never]"); + } + + // update + b = toBoolean(cfc, meta, "update", data); + if (b != null && !b.booleanValue()) + property.setAttribute("update", "false"); + + // insert + b = toBoolean(cfc, meta, "insert", data); + if (b != null && !b.booleanValue()) + property.setAttribute("insert", "false"); + + // lazy (dtd defintion:) + b = toBoolean(cfc, meta, "lazy", data); + if (b != null && b.booleanValue()) + property.setAttribute("lazy", "true"); + + // optimistic-lock + b = toBoolean(cfc, meta, "optimisticlock", data); + if (b != null && !b.booleanValue()) + property.setAttribute("optimistic-lock", "false"); + + } + + /* + * MUST dies kommt aber nicht hier sondern in verarbeitung in component + */ + private static void createXMLMappingOneToOne(Element clazz, PageContext pc, Component cfc, Property prop, + SessionFactoryData data) throws PageException { + Struct meta = prop.getDynamicAttributes(); + + Boolean b; + + Document doc = XMLUtil.getDocument(clazz); + Element x2o; + + // column + String fkcolumn = toString(cfc, prop, meta, "fkcolumn", data); + String linkTable = toString(cfc, prop, meta, "linkTable", data); + + if (!Util.isEmpty(linkTable, true) || !Util.isEmpty(fkcolumn, true)) { + clazz = getJoin(clazz); + + x2o = doc.createElement("many-to-one"); + // x2o.setAttribute("column", fkcolumn); + x2o.setAttribute("unique", "true"); + + if (!Util.isEmpty(linkTable, true)) { + setColumn(doc, x2o, linkTable, data); + } else { + setColumn(doc, x2o, fkcolumn, data); + } + + // update + b = toBoolean(cfc, meta, "update", data); + if (b != null) + x2o.setAttribute("update", CommonUtil.toString(b.booleanValue())); + + // insert + b = toBoolean(cfc, meta, "insert", data); + if (b != null) + x2o.setAttribute("insert", CommonUtil.toString(b.booleanValue())); + + // not-null + b = toBoolean(cfc, meta, "notNull", data); + if (b != null) + x2o.setAttribute("not-null", CommonUtil.toString(b.booleanValue())); + + // optimistic-lock + b = toBoolean(cfc, meta, "optimisticLock", data); + if (b != null) + x2o.setAttribute("optimistic-lock", CommonUtil.toString(b.booleanValue())); + + // not-found + b = toBoolean(cfc, meta, "missingRowIgnored", data); + if (b != null && b.booleanValue()) + x2o.setAttribute("not-found", "ignore"); + + /* + * / index str=toString(meta,"index"); if(!Util.isEmpty(str,true)) x2o.setAttribute("index", str); + */ + + } else { + x2o = doc.createElement("one-to-one"); + } + clazz.appendChild(x2o); + + // access + String str = toString(cfc, prop, meta, "access", data); + if (!Util.isEmpty(str, true)) + x2o.setAttribute("access", str); + + // constrained + b = toBoolean(cfc, meta, "constrained", data); + if (b != null && b.booleanValue()) + x2o.setAttribute("constrained", "true"); + + // formula + str = toString(cfc, prop, meta, "formula", data); + if (!Util.isEmpty(str, true)) + x2o.setAttribute("formula", str); + + // embed-xml + str = toString(cfc, prop, meta, "embedXml", data); + if (!Util.isEmpty(str, true)) + x2o.setAttribute("embed-xml", str); + + // property-ref + str = toString(cfc, prop, meta, "mappedBy", data); + if (!Util.isEmpty(str, true)) + x2o.setAttribute("property-ref", str); + + // foreign-key + str = toString(cfc, prop, meta, "foreignKeyName", data); + if (Util.isEmpty(str, true)) + str = toString(cfc, prop, meta, "foreignKey", data); + if (!Util.isEmpty(str, true)) + x2o.setAttribute("foreign-key", str); + + setForeignEntityName(cfc, prop, meta, x2o, true, data); + + createXMLMappingXToX(x2o, pc, cfc, prop, meta, data); + } + + private static Component loadForeignCFC(PageContext pc, Component cfc, Property prop, Struct meta, + SessionFactoryData data) throws PageException { + // entity + String str = toString(cfc, prop, meta, "entityName", data); + Component fcfc = null; + + if (!Util.isEmpty(str, true)) { + fcfc = data.getEntityByEntityName(str, false); + if (fcfc != null) + return fcfc; + } + + str = toString(cfc, prop, meta, "cfc", false, data); + if (!Util.isEmpty(str, true)) { + return data.getEntityByCFCName(str, false); + } + return null; + } + + private static void createXMLMappingCollection(Element clazz, PageContext pc, Component cfc, Property prop, + SessionFactoryData data) throws PageException { + Struct meta = prop.getDynamicAttributes(); + Document doc = XMLUtil.getDocument(clazz); + Element el = null; + + // collection type + String str = prop.getType(); + if (Util.isEmpty(str, true) || "any".equalsIgnoreCase(str) || "object".equalsIgnoreCase(str)) + str = "array"; + else + str = str.trim().toLowerCase(); + + // bag + if ("array".equals(str) || "bag".equals(str)) { + el = doc.createElement("bag"); + } + // map + else if ("struct".equals(str) || "map".equals(str)) { + el = doc.createElement("map"); + + // map-key + str = toString(cfc, prop, meta, "structKeyColumn", true, data); + if (!Util.isEmpty(str, true)) { + Element mapKey = doc.createElement("map-key"); + el.appendChild(mapKey); + mapKey.setAttribute("column", str); + + // type + str = toString(cfc, prop, meta, "structKeyType", data); + if (!Util.isEmpty(str, true)) + mapKey.setAttribute("type", str); + else + mapKey.setAttribute("type", "string"); + } + } else + throw invalidValue(cfc, prop, "collectiontype", str, "array,struct", data); + // throw new ORMException("invalid value ["+str+"] for attribute [collectiontype], valid values are + // [array,struct]"); + + setBeforeJoin(clazz, el); + + // name + el.setAttribute("name", prop.getName()); + + // table + str = toString(cfc, prop, meta, "table", true, data); + el.setAttribute("table", escape(HibernateUtil.convertTableName(data, str))); + + // catalog + str = toString(cfc, prop, meta, "catalog", data); + if (!Util.isEmpty(str, true)) + el.setAttribute("catalog", str); + + // schema + str = toString(cfc, prop, meta, "schema", data); + if (!Util.isEmpty(str, true)) + el.setAttribute("schema", str); + + // mutable + Boolean b = toBoolean(cfc, meta, "readonly", data); + if (b != null && b.booleanValue()) + el.setAttribute("mutable", "false"); + + // order-by + str = toString(cfc, prop, meta, "orderby", data); + if (!Util.isEmpty(str, true)) + el.setAttribute("order-by", str); + + // element-column + str = toString(cfc, prop, meta, "elementcolumn", data); + if (!Util.isEmpty(str, true)) { + Element element = doc.createElement("element"); + el.appendChild(element); + + // column + element.setAttribute("column", formatColumn(str, data)); + + // type + str = toString(cfc, prop, meta, "elementtype", data); + if (!Util.isEmpty(str, true)) + element.setAttribute("type", str); + } + + // batch-size + Integer i = toInteger(cfc, meta, "batchsize", data); + if (i != null && i.intValue() > 1) + el.setAttribute("batch-size", CommonUtil.toString(i.intValue())); + + // column + str = toString(cfc, prop, meta, "fkcolumn", data); + if (Util.isEmpty(str, true)) + str = toString(cfc, prop, meta, "column", data); + if (!Util.isEmpty(str, true)) { + Element key = doc.createElement("key"); + CommonUtil.setFirst(el, key); + // el.appendChild(key); + + // column + key.setAttribute("column", formatColumn(str, data)); + + // property-ref + str = toString(cfc, prop, meta, "mappedBy", data); + if (!Util.isEmpty(str, true)) + key.setAttribute("property-ref", str); + } + + // cache + setCacheStrategy(cfc, prop, doc, meta, el, data); + + // optimistic-lock + b = toBoolean(cfc, meta, "optimisticlock", data); + if (b != null && !b.booleanValue()) + el.setAttribute("optimistic-lock", "false"); + + } + + private static void setBeforeJoin(Element clazz, Element el) { + Element join; + if (clazz.getNodeName().equals("join")) { + join = clazz; + clazz = getClazz(clazz); + } else { + join = getJoin(clazz); + } + + if (join == clazz) + clazz.appendChild(el); + else + clazz.insertBefore(el, join); + + } + + private static Element getClazz(Element join) { + if (join.getNodeName().equals("join")) { + return (Element) join.getParentNode(); + } + return join; + } + + private static Element getJoin(Element clazz) { + if (clazz.getNodeName().equals("subclass")) { + NodeList joins = clazz.getElementsByTagName("join"); + if (joins != null && joins.getLength() > 0) + return (Element) joins.item(0); + } + return clazz; + } + + private static void createXMLMappingManyToMany(DatasourceConnection dc, Component cfc, PropertyCollection propColl, + Element clazz, PageContext pc, Property prop, SessionFactoryData data) throws PageException { + Element el = createXMLMappingXToMany(propColl, clazz, pc, cfc, prop, data); + Struct meta = prop.getDynamicAttributes(); + Document doc = XMLUtil.getDocument(clazz); + Element m2m = doc.createElement("many-to-many"); + el.appendChild(m2m); + + // link + setLink(dc, cfc, prop, el, meta, true, data); + + setForeignEntityName(cfc, prop, meta, m2m, true, data); + + // order-by + String str = toString(cfc, prop, meta, "orderby", data); + if (!Util.isEmpty(str, true)) + m2m.setAttribute("order-by", str); + + // column + str = toString(cfc, prop, meta, "inversejoincolumn", data); + + // build fkcolumn name + if (Util.isEmpty(str, true)) { + Component other = loadForeignCFC(pc, cfc, prop, meta, data); + if (other != null) { + boolean isClass = Util.isEmpty(other.getExtends()); + // MZ: Recursive search for persistent mappedSuperclass properties + Property[] _props = getProperties(pc, other, dc, meta, isClass, true, data); + PropertyCollection _propColl = splitJoins(cfc, new HashMap(), _props, data); + _props = _propColl.getProperties(); + + Struct m; + Property _prop = null; + for (int i = 0; i < _props.length; i++) { + m = _props[i].getDynamicAttributes(); + // fieldtype + String fieldtype = CommonUtil.toString(m.get(FIELDTYPE, null), null); + if ("many-to-many".equalsIgnoreCase(fieldtype)) { + // linktable + String currLinkTable = CommonUtil.toString(meta.get(LINK_TABLE, null), null); + String othLinkTable = CommonUtil.toString(m.get(LINK_TABLE, null), null); + if (currLinkTable.equals(othLinkTable)) { + // cfc name + String cfcName = CommonUtil.toString(m.get(CFC, null), null); + if (cfc.equalTo(cfcName)) { + _prop = _props[i]; + } + } + } + } + str = createM2MFKColumnName(other, _prop, _propColl, data); + } + } + setColumn(doc, m2m, str, data); + + // not-found + Boolean b = toBoolean(cfc, meta, "missingrowignored", data); + if (b != null && b.booleanValue()) + m2m.setAttribute("not-found", "ignore"); + + // property-ref + str = toString(cfc, prop, meta, "mappedby", data); + if (!Util.isEmpty(str, true)) + m2m.setAttribute("property-ref", str); + + // foreign-key + str = toString(cfc, prop, meta, "foreignKeyName", data); + if (Util.isEmpty(str, true)) + str = toString(cfc, prop, meta, "foreignKey", data); + if (!Util.isEmpty(str, true)) + m2m.setAttribute("foreign-key", str); + } + + private static boolean setLink(DatasourceConnection dc, Component cfc, Property prop, Element el, Struct meta, + boolean linkTableRequired, SessionFactoryData data) throws PageException { + String str = toString(cfc, prop, meta, "linktable", linkTableRequired, data); + + if (!Util.isEmpty(str, true)) { + + el.setAttribute("table", escape(HibernateUtil.convertTableName(data, str))); + + // schema + str = toString(cfc, prop, meta, "linkschema", data); + if (Util.isEmpty(str, true)) + str = ORMConfigurationUtil.getSchema(data.getORMConfiguration(), dc.getDatasource().getName()); + if (!Util.isEmpty(str, true)) + el.setAttribute("schema", str); + + // catalog + str = toString(cfc, prop, meta, "linkcatalog", data); + if (Util.isEmpty(str, true)) + str = ORMConfigurationUtil.getCatalog(data.getORMConfiguration(), dc.getDatasource().getName()); + if (!Util.isEmpty(str, true)) + el.setAttribute("catalog", str); + return true; + } + return false; + } + + private static void createXMLMappingOneToMany(DatasourceConnection dc, Component cfc, PropertyCollection propColl, + Element clazz, PageContext pc, Property prop, SessionFactoryData data) throws PageException { + Element el = createXMLMappingXToMany(propColl, clazz, pc, cfc, prop, data); + Struct meta = prop.getDynamicAttributes(); + Document doc = XMLUtil.getDocument(clazz); + Element x2m; + + // order-by + String str = toString(cfc, prop, meta, "orderby", data); + if (!Util.isEmpty(str, true)) + el.setAttribute("order-by", str); + + // link + if (setLink(dc, cfc, prop, el, meta, false, data)) { + x2m = doc.createElement("many-to-many"); + x2m.setAttribute("unique", "true"); + + str = toString(cfc, prop, meta, "inversejoincolumn", data); + setColumn(doc, x2m, str, data); + } else { + x2m = doc.createElement("one-to-many"); + } + el.appendChild(x2m); + + // entity-name + + setForeignEntityName(cfc, prop, meta, x2m, true, data); + + } + + private static Element createXMLMappingXToMany(PropertyCollection propColl, Element clazz, PageContext pc, + Component cfc, Property prop, SessionFactoryData data) throws PageException { + final Struct meta = prop.getDynamicAttributes(); + Document doc = XMLUtil.getDocument(clazz); + Element el = null; + + // collection type + String str = prop.getType(); + if (Util.isEmpty(str, true) || "any".equalsIgnoreCase(str) || "object".equalsIgnoreCase(str)) + str = "array"; + else + str = str.trim().toLowerCase(); + + Element mapKey = null; + // bag + if ("array".equals(str) || "bag".equals(str)) { + el = doc.createElement("bag"); + + } + // map + else if ("struct".equals(str) || "map".equals(str)) { + el = doc.createElement("map"); + + // map-key + mapKey = doc.createElement("map-key"); + // el.appendChild(mapKey); + + // column + str = toString(cfc, prop, meta, "structKeyColumn", true, data); + mapKey.setAttribute("column", formatColumn(str, data)); + + // type + str = toString(cfc, prop, meta, "structKeyType", data); + if (!Util.isEmpty(str, true)) + mapKey.setAttribute("type", str); + else + mapKey.setAttribute("type", "string");// MUST get type dynamicly + } else + throw invalidValue(cfc, prop, "collectiontype", str, "array,struct", data); + // throw new ORMException("invalid value ["+str+"] for attribute [collectiontype], valid values are + // [array,struct]"); + + setBeforeJoin(clazz, el); + + // batch-size + Integer i = toInteger(cfc, meta, "batchsize", data); + if (i != null) { + if (i.intValue() > 1) + el.setAttribute("batch-size", CommonUtil.toString(i.intValue())); + } + + // cacheUse + setCacheStrategy(cfc, prop, doc, meta, el, data); + + // column + str = createFKColumnName(cfc, prop, propColl, data); + + if (!Util.isEmpty(str, true)) { + Element key = doc.createElement("key"); + el.appendChild(key); + + // column + setColumn(doc, key, str, data); + + // property-ref + str = toString(cfc, prop, meta, "mappedBy", data); + if (!Util.isEmpty(str, true)) + key.setAttribute("property-ref", str); + } + + // inverse + Boolean b = toBoolean(cfc, meta, "inverse", data); + if (b != null && b.booleanValue()) + el.setAttribute("inverse", "true"); + + // mutable + b = toBoolean(cfc, meta, "readonly", data); + if (b != null && b.booleanValue()) + el.setAttribute("mutable", "false"); + + // optimistic-lock + b = toBoolean(cfc, meta, "optimisticlock", data); + if (b != null && !b.booleanValue()) + el.setAttribute("optimistic-lock", "false"); + + // where + str = toString(cfc, prop, meta, "where", data); + if (!Util.isEmpty(str, true)) + el.setAttribute("where", str); + + // add map key + if (mapKey != null) + el.appendChild(mapKey); + + createXMLMappingXToX(el, pc, cfc, prop, meta, data); + + return el; + } + + private static String createFKColumnName(Component cfc, Property prop, PropertyCollection propColl, + SessionFactoryData data) throws PageException { + + // fk column from local defintion + String str = prop == null ? null : toString(cfc, prop, prop.getDynamicAttributes(), "fkcolumn", data); + if (!Util.isEmpty(str)) + return str; + + // no local defintion, get from Foreign enity + Struct meta = prop.getDynamicAttributes(); + String type = toString(cfc, prop, meta, "fieldtype", false, data); + String otherType; + if ("many-to-one".equalsIgnoreCase(type)) + otherType = "one-to-many"; + else if ("one-to-many".equalsIgnoreCase(type)) + otherType = "many-to-one"; + else + return createM2MFKColumnName(cfc, prop, propColl, data); + + String feName = toString(cfc, prop, meta, "cfc", true, data); + Component feCFC = data.getEntityByCFCName(feName, false); + Property[] feProps = feCFC.getProperties(true, false, false, false); + + Property p; + Component _cfc; + for (int i = 0; i < feProps.length; i++) { + p = feProps[i]; + + // compare fieldType + str = toString(feCFC, p, p.getDynamicAttributes(), "fieldtype", false, data); + if (!otherType.equalsIgnoreCase(str)) + continue; + + // compare cfc + str = toString(feCFC, p, p.getDynamicAttributes(), "cfc", false, data); + if (Util.isEmpty(str)) + continue; + _cfc = data.getEntityByCFCName(str, false); + if (_cfc == null || !_cfc.equals(cfc)) + continue; + + // get fkcolumn + str = toString(_cfc, p, p.getDynamicAttributes(), "fkcolumn", data); + if (!Util.isEmpty(str)) + return str; + + } + throw ExceptionUtil.createException(data, null, + "cannot terminate foreign key column name for component " + cfc.getName(), null); + } + + private static String createM2MFKColumnName(Component cfc, Property prop, PropertyCollection propColl, + SessionFactoryData data) throws PageException { + + String str = prop == null ? null : toString(cfc, prop, prop.getDynamicAttributes(), "fkcolumn", data); + if (Util.isEmpty(str)) { + Property[] ids = getIds(cfc, propColl, data); + if (ids.length == 1) { + str = toString(cfc, ids[0], ids[0].getDynamicAttributes(), "column", data); + if (Util.isEmpty(str, true)) + str = ids[0].getName(); + } else if (prop != null) + str = toString(cfc, prop, prop.getDynamicAttributes(), "fkcolumn", true, data); + else + throw ExceptionUtil.createException(data, null, + "cannot terminate foreign key column name for component " + cfc.getName(), null); + + str = HibernateCaster.getEntityName(cfc) + "_" + str; + } + return str; + } + + private static void setForeignEntityName(Component cfc, Property prop, Struct meta, Element el, boolean cfcRequired, + SessionFactoryData data) throws PageException { + // entity + String str = cfcRequired ? null : toString(cfc, prop, meta, "entityName", data); + if (!Util.isEmpty(str, true)) { + el.setAttribute("entity-name", str); + } else { + // cfc + // createFKColumnName( cfc, prop, propColl); + + str = toString(cfc, prop, meta, "cfc", cfcRequired, data); + if (!Util.isEmpty(str, true)) { + Component _cfc = data.getEntityByCFCName(str, false); + str = HibernateCaster.getEntityName(_cfc); + el.setAttribute("entity-name", str); + } + } + } + + private static void setCacheStrategy(Component cfc, Property prop, Document doc, Struct meta, Element el, + SessionFactoryData data) throws PageException { + String strategy = toString(cfc, prop, meta, "cacheuse", data); + + if (!Util.isEmpty(strategy, true)) { + strategy = strategy.trim().toLowerCase(); + if ("read-only".equals(strategy) || "nonstrict-read-write".equals(strategy) || "read-write".equals(strategy) + || "transactional".equals(strategy)) { + Element cache = doc.createElement("cache"); + CommonUtil.setFirst(el, cache); + el.appendChild(cache); + cache.setAttribute("usage", strategy); + String name = toString(cfc, prop, meta, "cacheName", data); + if (!Util.isEmpty(name, true)) { + cache.setAttribute("region", name); + } + } else + throw ExceptionUtil.createException(data, cfc, "invalid value [" + strategy + + "] for attribute [cacheuse], valid values are [read-only,nonstrict-read-write,read-write,transactional]", + null); + } + + } + + private static void setColumn(Document doc, Element el, String columnValue, SessionFactoryData data) + throws PageException { + if (Util.isEmpty(columnValue, true)) + return; + + String[] arr = CommonUtil.toStringArray(columnValue, ","); + if (arr.length == 1) { + el.setAttribute("column", formatColumn(arr[0], data)); + } else { + Element column; + for (int i = 0; i < arr.length; i++) { + column = doc.createElement("column"); + el.appendChild(column); + column.setAttribute("name", formatColumn(arr[i], data)); + } + } + } + + private static void createXMLMappingManyToOne(Element clazz, PageContext pc, Component cfc, Property prop, + PropertyCollection propColl, SessionFactoryData data) throws PageException { + Struct meta = prop.getDynamicAttributes(); + Boolean b; + + Document doc = XMLUtil.getDocument(clazz); + clazz = getJoin(clazz); + + Element m2o = doc.createElement("many-to-one"); + clazz.appendChild(m2o); + + // columns + String linktable = toString(cfc, prop, meta, "linktable", data); + String _columns; + if (!Util.isEmpty(linktable, true)) + _columns = toString(cfc, prop, meta, "inversejoincolumn", data); + else + _columns = createFKColumnName(cfc, prop, propColl, data);// toString(cfc,prop,meta,"fkcolumn"); + setColumn(doc, m2o, _columns, data); + + // cfc + setForeignEntityName(cfc, prop, meta, m2o, true, data); + + // column + // String str=toString(prop,meta,"column",true); + // m2o.setAttribute("column", str); + + // insert + b = toBoolean(cfc, meta, "insert", data); + if (b != null && !b.booleanValue()) + m2o.setAttribute("insert", "false"); + + // update + b = toBoolean(cfc, meta, "update", data); + if (b != null && !b.booleanValue()) + m2o.setAttribute("update", "false"); + + // property-ref + String str = toString(cfc, prop, meta, "mappedBy", data); + if (!Util.isEmpty(str, true)) + m2o.setAttribute("property-ref", str); + + // update + b = toBoolean(cfc, meta, "unique", data); + if (b != null && b.booleanValue()) + m2o.setAttribute("unique", "true"); + + // not-null + b = toBoolean(cfc, meta, "notnull", data); + if (b != null && b.booleanValue()) + m2o.setAttribute("not-null", "true"); + + // optimistic-lock + b = toBoolean(cfc, meta, "optimisticLock", data); + if (b != null && !b.booleanValue()) + m2o.setAttribute("optimistic-lock", "false"); + + // not-found + b = toBoolean(cfc, meta, "missingRowIgnored", data); + if (b != null && b.booleanValue()) + m2o.setAttribute("not-found", "ignore"); + + // index + str = toString(cfc, prop, meta, "index", data); + if (!Util.isEmpty(str, true)) + m2o.setAttribute("index", str); + + // unique-key + str = toString(cfc, prop, meta, "uniqueKeyName", data); + if (Util.isEmpty(str, true)) + str = toString(cfc, prop, meta, "uniqueKey", data); + if (!Util.isEmpty(str, true)) + m2o.setAttribute("unique-key", str); + + // foreign-key + str = toString(cfc, prop, meta, "foreignKeyName", data); + if (Util.isEmpty(str, true)) + str = toString(cfc, prop, meta, "foreignKey", data); + if (!Util.isEmpty(str, true)) + m2o.setAttribute("foreign-key", str); + + // access + str = toString(cfc, prop, meta, "access", data); + if (!Util.isEmpty(str, true)) + m2o.setAttribute("access", str); + + createXMLMappingXToX(m2o, pc, cfc, prop, meta, data); + + } + + private static String formatColumn(String name, SessionFactoryData data) throws PageException { + name = name.trim(); + return escape(HibernateUtil.convertColumnName(data, name)); + } + + /* + * + * + * + * + */ + private static void createXMLMappingXToX(Element x2x, PageContext pc, Component cfc, Property prop, Struct meta, + SessionFactoryData data) throws PageException { + x2x.setAttribute("name", prop.getName()); + + // cascade + String str = toString(cfc, prop, meta, "cascade", data); + if (!Util.isEmpty(str, true)) + x2x.setAttribute("cascade", str); + + // fetch + str = toString(cfc, prop, meta, "fetch", data); + if (!Util.isEmpty(str, true)) { + str = str.trim().toLowerCase(); + if ("join".equals(str) || "select".equals(str)) + x2x.setAttribute("fetch", str); + else + throw invalidValue(cfc, prop, "fetch", str, "join,select", data); + // throw new ORMException("invalid value ["+str+"] for attribute [fetch], valid values are + // [join,select]"); + } + + // lazy + setLazy(cfc, prop, meta, x2x, data); + + } + + private static void setLazy(Component cfc, Property prop, Struct meta, Element x2x, SessionFactoryData data) + throws PageException { + String str = toString(cfc, prop, meta, "lazy", data); + if (!Util.isEmpty(str, true)) { + str = str.trim(); + String name = x2x.getNodeName(); + Boolean b = CommonUtil.toBoolean(str, null); + + // + // + if ("many-to-one".equals(name) || "one-to-one".equals(name)) { + if (b != null) + x2x.setAttribute("lazy", b.booleanValue() ? "proxy" : "false"); + else if ("proxy".equalsIgnoreCase(str)) + x2x.setAttribute("lazy", "proxy"); + else if ("no-proxy".equalsIgnoreCase(str)) + x2x.setAttribute("lazy", "no-proxy"); + else + throw invalidValue(cfc, prop, "lazy", str, "true,false,proxy,no-proxy", data); + } + + // + // + else if ("many-to-many".equals(name) || "key-many-to-one".equals(name)) { + if (b != null) + x2x.setAttribute("lazy", b.booleanValue() ? "proxy" : "false"); + else if ("proxy".equalsIgnoreCase(str)) + x2x.setAttribute("lazy", "proxy"); + throw invalidValue(cfc, prop, "lazy", str, "true,false,proxy", data); + + } + + else { + if (b != null) + x2x.setAttribute("lazy", b.booleanValue() ? "true" : "false"); + else if ("extra".equalsIgnoreCase(str)) + x2x.setAttribute("lazy", "extra"); + else + throw invalidValue(cfc, prop, "lazy", str, "true,false,extra", data); + } + } + } + + private static void createXMLMappingTimestamp(Element clazz, PageContext pc, Component cfc, Property prop, + SessionFactoryData data) throws PageException { + Struct meta = prop.getDynamicAttributes(); + String str; + Boolean b; + + Document doc = XMLUtil.getDocument(clazz); + Element timestamp = doc.createElement("timestamp"); + clazz.appendChild(timestamp); + + timestamp.setAttribute("name", prop.getName()); + + // access + str = toString(cfc, prop, meta, "access", data); + if (!Util.isEmpty(str, true)) + timestamp.setAttribute("access", str); + + // column + str = toString(cfc, prop, meta, "column", data); + if (Util.isEmpty(str, true)) + str = prop.getName(); + timestamp.setAttribute("column", formatColumn(str, data)); + + // generated + b = toBoolean(cfc, meta, "generated", data); + if (b != null) + timestamp.setAttribute("generated", b.booleanValue() ? "always" : "never"); + + // source + str = toString(cfc, prop, meta, "source", data); + if (!Util.isEmpty(str, true)) { + str = str.trim().toLowerCase(); + if ("db".equals(str) || "vm".equals(str)) + timestamp.setAttribute("source", str); + else + throw invalidValue(cfc, prop, "source", str, "db,vm", data); + } + + // unsavedValue + str = toString(cfc, prop, meta, "unsavedValue", data); + if (!Util.isEmpty(str, true)) { + str = str.trim().toLowerCase(); + if ("null".equals(str) || "undefined".equals(str)) + timestamp.setAttribute("unsaved-value", str); + else + throw invalidValue(cfc, prop, "unsavedValue", str, "null, undefined", data); + // throw new ORMException("invalid value ["+str+"] for attribute [unsavedValue], valid values are + // [null, undefined]"); + } + } + + private static PageException invalidValue(Component cfc, Property prop, String attrName, String invalid, + String valid, SessionFactoryData data) { + String owner = prop.getOwnerName(); + if (Util.isEmpty(owner)) + return ExceptionUtil.createException(data, cfc, "invalid value [" + invalid + "] for attribute [" + attrName + + "] of property [" + prop.getName() + "], valid values are [" + valid + "]", null); + return ExceptionUtil.createException(data, cfc, + "invalid value [" + invalid + "] for attribute [" + attrName + "] of property [" + prop.getName() + + "] of Component [" + CommonUtil.last(owner, ".") + "], valid values are [" + valid + "]", + null); + } + + private static void createXMLMappingVersion(Element clazz, PageContext pc, Component cfc, Property prop, + SessionFactoryData data) throws PageException { + Struct meta = prop.getDynamicAttributes(); + + Document doc = XMLUtil.getDocument(clazz); + Element version = doc.createElement("version"); + clazz.appendChild(version); + + version.setAttribute("name", prop.getName()); + + // column + String str = toString(cfc, prop, meta, "column", data); + if (Util.isEmpty(str, true)) + str = prop.getName(); + version.setAttribute("column", formatColumn(str, data)); + + // access + str = toString(cfc, prop, meta, "access", data); + if (!Util.isEmpty(str, true)) + version.setAttribute("access", str); + + // generated + Object o = meta.get(GENERATED, null); + if (o != null) { + Boolean b = CommonUtil.toBoolean(o, null); + str = null; + if (b != null) { + str = b.booleanValue() ? "always" : "never"; + } else { + str = CommonUtil.toString(o, null); + if ("always".equalsIgnoreCase(str)) + str = "always"; + else if ("never".equalsIgnoreCase(str)) + str = "never"; + else + throw invalidValue(cfc, prop, "generated", o.toString(), "true,false,always,never", data); + // throw new ORMException("invalid value ["+o+"] for attribute [generated] of property + // ["+prop.getName()+"], valid values are [true,false,always,never]"); + } + version.setAttribute("generated", str); + } + + // insert + Boolean b = toBoolean(cfc, meta, "insert", data); + if (b != null && !b.booleanValue()) + version.setAttribute("insert", "false"); + + // type + String typeName = "dataType"; + str = toString(cfc, prop, meta, typeName, data); + if (Util.isEmpty(str, true)) { + typeName = "ormType"; + str = toString(cfc, prop, meta, typeName, data); + } + if (!Util.isEmpty(str, true)) { + str = str.trim().toLowerCase(); + if ("int".equals(str) || "integer".equals(str)) + version.setAttribute("type", "integer"); + else if ("long".equals(str)) + version.setAttribute("type", "long"); + else if ("short".equals(str)) + version.setAttribute("type", "short"); + else + throw invalidValue(cfc, prop, typeName, str, "int,integer,long,short", data); + // throw new ORMException("invalid value ["+str+"] for attribute ["+typeName+"], valid values are + // [int,integer,long,short]"); + } else + version.setAttribute("type", "integer"); + + // unsavedValue + str = toString(cfc, prop, meta, "unsavedValue", data); + if (!Util.isEmpty(str, true)) { + str = str.trim().toLowerCase(); + if ("null".equals(str) || "negative".equals(str) || "undefined".equals(str)) + version.setAttribute("unsaved-value", str); + else + throw invalidValue(cfc, prop, "unsavedValue", str, "null, negative, undefined", data); + // throw new ORMException("invalid value ["+str+"] for attribute [unsavedValue], valid values are + // [null, negative, undefined]"); + } + } + + private static String toString(Component cfc, Property prop, Struct sct, String key, SessionFactoryData data) + throws PageException { + return toString(cfc, prop, sct, key, false, data); + } + + private static String toString(Component cfc, Property prop, Struct sct, String key, boolean throwErrorWhenNotExist, + SessionFactoryData data) throws PageException { + return toString(cfc, prop, sct, CommonUtil.createKey(key), throwErrorWhenNotExist, data); + } + + private static String toString(Component cfc, Property prop, Struct sct, Collection.Key key, + boolean throwErrorWhenNotExist, SessionFactoryData data) throws PageException { + Object value = sct.get(key, null); + if (value == null) { + if (throwErrorWhenNotExist) { + if (prop == null) + throw ExceptionUtil.createException(data, cfc, "attribute [" + key + "] is required", null); + throw ExceptionUtil.createException(data, cfc, "attribute [" + key + "] of property [" + prop.getName() + + "] of Component [" + _getCFCName(prop) + "] is required", null); + } + return null; + } + + String str = CommonUtil.toString(value, null); + if (str == null) { + if (prop == null) + throw ExceptionUtil.createException(data, cfc, "invalid type [" + CommonUtil.toTypeName(value) + + "] for attribute [" + key + "], value must be a string", null); + throw ExceptionUtil.createException(data, cfc, + "invalid type [" + CommonUtil.toTypeName(value) + "] for attribute [" + key + "] of property [" + + prop.getName() + "] of Component [" + _getCFCName(prop) + "], value must be a string", + null); + } + return str; + } + + private static String _getCFCName(Property prop) { + String owner = prop.getOwnerName(); + return CommonUtil.last(owner, "."); + } + + private static Boolean toBoolean(Component cfc, Struct sct, String key, SessionFactoryData data) + throws PageException { + Object value = sct.get(CommonUtil.createKey(key), null); + if (value == null) + return null; + + Boolean b = CommonUtil.toBoolean(value, null); + if (b == null) + throw ExceptionUtil.createException(data, cfc, "invalid type [" + CommonUtil.toTypeName(value) + + "] for attribute [" + key + "], value must be a boolean", null); + return b; + } + + private static Integer toInteger(Component cfc, Struct sct, String key, SessionFactoryData data) + throws PageException { + Object value = sct.get(CommonUtil.createKey(key), null); + if (value == null) + return null; + + Integer i = CommonUtil.toInteger(value, null); + if (i == null) + throw ExceptionUtil.createException(data, cfc, "invalid type [" + CommonUtil.toTypeName(value) + + "] for attribute [" + key + "], value must be a numeric value", null); + return i; + } + + /** + * Convert the document to a file-ready XML string. + *

+ * Will prepend the XML head tags. + * + * @param document + * The W3C document root element for converting to an XML string + * + * @return a fully-formed HBM XML document ready to save to a file. + * + * @throws PageException + */ + public static String toMappingString(Element document) throws PageException { + return getXMLOpen() + XMLUtil.toString(document); + } + + /** + * Save the XML dom to a hibernate mapping file (myEntity.hbm.xml) + * + * @param cfc + * Lucee Component (entity) that we're saving the mapping for + * @param xml + * Fully-formed hibernate mapping XML + */ + public static void saveMapping(Component cfc, String xml) { + Resource res = getMappingResource(cfc); + if (res != null) { + try { + CommonUtil.write(res, xml, CommonUtil.UTF8(), false); + } catch (Exception e) { + } + } + } + + /** + * Get the hibernate mapping XML as a string. + * + * @param cfc + * Lucee Component (entity) for which to load the HBM mapping xml file + * + * @return A giant XML string + */ + public static String loadMapping(Component cfc) throws PageException, IOException { + + Resource resource = getMappingResource(cfc); + if (resource == null) + throw ExceptionUtil.createException("Hibernate mapping not found for entity: " + cfc.getName()); + + String xml = CommonUtil.toString(resource, CommonUtil.UTF8()); + // return CommonUtil.toXML(xml).getOwnerDocument().getDocumentElement(); + return xml; + } + + /** + * Get the last modified time for this component's mapping. Will return 0 if no mapping found. + * + * @param cfc + * The Lucee component (persistent entity) we're pulling the modification date for + * + * @return A long value representing the time the file was last modified, measured in milliseconds + * since the epoch (00:00:00 GMT, January 1, 1970), or 0L if the file does not exist or if an + * I/O error occurs + * + * @see {lucee.commons.io.res.Resource#lastModified} + */ + public static long getMappingLastModified(Component cfc) { + Resource res = getMappingResource(cfc); + if (res == null) + return 0; + return res.lastModified(); + } + + /** + * Get the HBM mapping file ( i.e. `models/myEntity.hbm.xml`) for this persistent Component/entity. + * + * @param cfc + * Lucee Component + * + * @return Lucee Resource, i.e. a Lucee-fied File object + */ + public static Resource getMappingResource(Component cfc) { + Resource res = cfc.getPageSource().getResource(); + if (res == null) + return null; + return res.getParentResource().getRealResource(res.getName() + ".hbm.xml"); + } + + /** + * Get the opening of a Hibernate mapping XML file, including tag and DOCTYPE declaration + */ + public static String getXMLOpen() { + StringBuilder xml = new StringBuilder(); + xml.append("\n"); + xml.append(HIBERNATE_3_DOCTYPE_DEFINITION + "\n"); + // xml.append("\n"); + return xml.toString(); + } + + /** + * Strip the open/close tags (i.e. ``, ``, ``) from an hbm.xml file. + *

+ * Useful for assembling multiple entities into a single `` element for sending to Hibernate. + * + * @param xml + * XML string from which to strip open and close tags + * + * @return an XML string with the DOCTYPE, `` and `` elements removed + */ + public static String stripXMLOpenClose(String xml) { + return xml.replaceAll("<\\?xml[^>]+>", "").replaceAll("]+>", "").replaceAll("", + ""); + } } class PropertyCollection { - private Property[] properties; - private String tableName; - - public PropertyCollection(String tableName, Property[] properties) { - this.tableName = tableName; - this.properties = properties; - } - - public PropertyCollection(String tableName, java.util.List properties) { - this.tableName = tableName; - this.properties = properties.toArray(new Property[properties.size()]); - } - - public Property[] getProperties() { - return properties; - } - - public String getTableName() { - return tableName; - } + private Property[] properties; + private String tableName; + + public PropertyCollection(String tableName, Property[] properties) { + this.tableName = tableName; + this.properties = properties; + } + + public PropertyCollection(String tableName, java.util.List properties) { + this.tableName = tableName; + this.properties = properties.toArray(new Property[properties.size()]); + } + + public Property[] getProperties() { + return properties; + } + + public String getTableName() { + return tableName; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HibernateCaster.java b/source/java/src/org/lucee/extension/orm/hibernate/HibernateCaster.java index 208ba0c3..41720ce3 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/HibernateCaster.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/HibernateCaster.java @@ -12,6 +12,9 @@ import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.metadata.ClassMetadata; import org.hibernate.type.Type; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ExceptionUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; import lucee.commons.lang.types.RefBoolean; import lucee.loader.engine.CFMLEngineFactory; @@ -31,591 +34,676 @@ public class HibernateCaster { - private static final int NULL = -178696; - - public static Object toCFML(Object src) { - if (src == null) return null; - if (src instanceof Collection) return src; - - if (src instanceof List) { - return toCFML((List) src); - } - /* - * if(src instanceof Map){ return toCFML(pc,(Map) src); } - */ - return src; - } - - public static Array toCFML(List src) { - int size = src.size(); - - Array trg = CommonUtil.createArray(); - for (int i = 0; i < size; i++) { - trg.setEL(i + 1, toCFML(src.get(i))); - } - return trg; - } - - /* - * public static Object toCFML(PageContext pc,Map src) throws PageException { - * - * Object type =src.remove("$type$"); if(type instanceof String){ - * - * Component cfc = toComponent(pc, (String)type); return toCFML(pc,src, cfc); } - * - * - * Iterator> it = src.entrySet().iterator(); Struct - * trg=CommonUtil.createStruct(); Map.Entry entry; while(it.hasNext()){ - * entry=it.next(); trg.setEL(entry.getKey(),toCFML(pc,entry.getValue())); } return trg; } - */ - - public static String getEntityName(Component cfc) { - - String name = null; - try { - name = CommonUtil.toString(cfc.getMetaStructItem(CommonUtil.ENTITY_NAME), null); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - try { - Struct md = cfc.getMetaData(CommonUtil.pc()); - name = CommonUtil.toString(md.get(CommonUtil.ENTITY_NAME), null); - - } - catch (PageException e) {} - } - - if (!Util.isEmpty(name)) { - return name; - } - return getName(cfc); - - } - - private static String getName(Component cfc) { - String name = null; - // MUSTMUST cfc.getName() should return the real case, this should not be needed - name = cfc.getPageSource().getDisplayPath(); - name = CommonUtil.last(name, "\\/"); - int index = name.lastIndexOf('.'); - name = name.substring(0, index); - return name; - } - - public static int cascade(ORMSession session, String cascade) throws PageException { - int c = cascade(cascade, -1); - if (c != -1) return c; - throw ExceptionUtil.createException(session, null, - "invalid cascade defintion [" + cascade + "], valid values are [all,all-delete-orphan,delete,delete-orphan,refresh,save-update]", null); - } - - public static int cascade(String cascade, int defaultValue) { - cascade = cascade.trim().toLowerCase(); - if ("all".equals(cascade)) return HibernateConstants.CASCADE_ALL; - - if ("save-update".equals(cascade)) return HibernateConstants.CASCADE_SAVE_UPDATE; - if ("save_update".equals(cascade)) return HibernateConstants.CASCADE_SAVE_UPDATE; - if ("saveupdate".equals(cascade)) return HibernateConstants.CASCADE_SAVE_UPDATE; - - if ("delete".equals(cascade)) return HibernateConstants.CASCADE_DELETE; - - if ("delete-orphan".equals(cascade)) return HibernateConstants.CASCADE_DELETE_ORPHAN; - if ("delete_orphan".equals(cascade)) return HibernateConstants.CASCADE_DELETE_ORPHAN; - if ("deleteorphan".equals(cascade)) return HibernateConstants.CASCADE_DELETE_ORPHAN; - - if ("all-delete-orphan".equals(cascade)) return HibernateConstants.CASCADE_ALL_DELETE_ORPHAN; - if ("all_delete_orphan".equals(cascade)) return HibernateConstants.CASCADE_ALL_DELETE_ORPHAN; - if ("alldeleteorphan".equals(cascade)) return HibernateConstants.CASCADE_ALL_DELETE_ORPHAN; - - if ("refresh".equals(cascade)) return HibernateConstants.REFRESH; - - return defaultValue; - } - - public static int collectionType(ORMSession session, String strCollectionType) throws PageException { - int ct = collectionType(strCollectionType, -1); - if (ct != -1) return ct; - throw ExceptionUtil.createException(session, null, "invalid collectionType defintion [" + strCollectionType + "], valid values are [array,struct]", null); - } - - public static int collectionType(String strCollectionType, int defaultValue) { - strCollectionType = strCollectionType.trim().toLowerCase(); - if ("struct".equals(strCollectionType)) return HibernateConstants.COLLECTION_TYPE_STRUCT; - if ("array".equals(strCollectionType)) return HibernateConstants.COLLECTION_TYPE_ARRAY; - - return defaultValue; - } - - public static String toHibernateType(ColumnInfo info, String type, String defaultValue) { - - // no type defined - if (Util.isEmpty(type, true)) { - return HibernateCaster.toHibernateType(info, defaultValue); - } - - // type defined - String tmp = HibernateCaster.toHibernateType(type, null); - if (tmp != null) return tmp; - - if (info != null) { - tmp = HibernateCaster.toHibernateType(info, defaultValue); - return tmp; - } - return defaultValue; - - } - - public static int toSQLType(String type, int defaultValue) { - type = type.trim().toLowerCase(); - type = toHibernateType(type, type); - if ("long".equals(type)) return Types.BIGINT; - if ("binary".equals(type)) return Types.BINARY; - if ("boolean".equals(type)) return Types.BIT; - if ("blob".equals(type)) return Types.BLOB; - if ("boolean".equals(type)) return Types.BOOLEAN; - if ("character".equals(type)) return Types.CHAR; - if ("clob".equals(type)) return Types.CLOB; - if ("date".equals(type)) return Types.DATE; - if ("big_decimal".equals(type)) return Types.DECIMAL; - if ("big_integer".equals(type)) return Types.NUMERIC; - if ("double".equals(type)) return Types.DOUBLE; - if ("float".equals(type)) return Types.FLOAT; - if ("integer".equals(type)) return Types.INTEGER; - if ("binary".equals(type)) return Types.VARBINARY; - if ("string".equals(type)) return Types.VARCHAR; - if ("short".equals(type)) return Types.SMALLINT; - if ("time".equals(type)) return Types.TIME; - if ("timestamp".equals(type)) return Types.TIMESTAMP; - if ("byte".equals(type)) return Types.TINYINT; - - return defaultValue; - } - - public static String toHibernateType(ColumnInfo info, String defaultValue) { - if (info == null) return defaultValue; - - String rtn = toHibernateType(info.getType(), info.getSize(), null); - if (rtn != null) return rtn; - return toHibernateType(info.getTypeName(), defaultValue); - } - - public static String toHibernateType(int type, int size, String defaultValue) { - // MUST do better - switch (type) { - case Types.ARRAY: - return ""; - case Types.BIGINT: - return "long"; - case Types.BINARY: - return "binary"; - case Types.BIT: - return "boolean"; - case Types.BLOB: - return "blob"; - case Types.BOOLEAN: - return "boolean"; - case Types.CHAR: - return "string"; - // if(size>1) return "string"; - // return "character"; - case Types.CLOB: - return "clob"; - // case Types.DATALINK: return ""; - case Types.DATE: - return "date"; - case Types.DECIMAL: - return "big_decimal"; - // case Types.DISTINCT: return ""; - case Types.DOUBLE: - return "double"; - case Types.FLOAT: - return "float"; - case Types.INTEGER: - return "integer"; - // case Types.JAVA_OBJECT: return ""; - case Types.LONGVARBINARY: - return "binary"; - case Types.LONGVARCHAR: - return "string"; - // case Types.NULL: return ""; - case Types.NUMERIC: - return "big_decimal"; - // case Types.OTHER: return ""; - // case Types.REAL: return ""; - // case Types.REF: return ""; - case Types.SMALLINT: - return "short"; - // case Types.STRUCT: return ""; - case Types.TIME: - return "time"; - case Types.TIMESTAMP: - return "timestamp"; - case Types.TINYINT: - return "byte"; - case Types.VARBINARY: - return "binary"; - case Types.NVARCHAR: - return "string"; - case Types.VARCHAR: - return "string"; - } - return defaultValue; - } - - public static String toHibernateType(ORMSession session, String type) throws PageException { - String res = toHibernateType(type, null); - if (res == null) throw ExceptionUtil.createException(session, null, "the type [" + type + "] is not supported", null); - return res; - } - - // calendar_date: A type mapping for a Calendar object that represents a date - // calendar: A type mapping for a Calendar object that represents a datetime. - public static String toHibernateType(String type, String defaultValue) { - type = type.trim().toLowerCase(); - type = Util.replace(type, "java.lang.", "", true); - type = Util.replace(type, "java.util.", "", true); - type = Util.replace(type, "java.sql.", "", true); - - // return same value - if ("long".equals(type)) return type; - if ("binary".equals(type)) return type; - if ("boolean".equals(type)) return type; - if ("blob".equals(type)) return "binary"; - if ("boolean".equals(type)) return type; - if ("character".equals(type)) return type; - if ("clob".equals(type)) return "text"; - if ("date".equals(type)) return type; - if ("big_decimal".equals(type)) return type; - if ("double".equals(type)) return type; - if ("float".equals(type)) return type; - if ("integer".equals(type)) return type; - if ("binary".equals(type)) return type; - if ("string".equals(type)) return type; - if ("big_integer".equals(type)) return type; - if ("short".equals(type)) return type; - if ("time".equals(type)) return type; - if ("timestamp".equals(type)) return type; - if ("byte".equals(type)) return type; - if ("binary".equals(type)) return type; - if ("string".equals(type)) return type; - if ("text".equals(type)) return type; - if ("calendar".equals(type)) return type; - if ("calendar_date".equals(type)) return type; - if ("locale".equals(type)) return type; - if ("timezone".equals(type)) return type; - if ("currency".equals(type)) return type; - - if ("imm_date".equals(type)) return type; - if ("imm_time".equals(type)) return type; - if ("imm_timestamp".equals(type)) return type; - if ("imm_calendar".equals(type)) return type; - if ("imm_calendar_date".equals(type)) return type; - if ("imm_serializable".equals(type)) return type; - if ("imm_binary".equals(type)) return type; - - // return different value - if ("bigint".equals(type)) return "long"; - if ("bit".equals(type)) return "boolean"; - - if ("int".equals(type)) return "integer"; - if ("char".equals(type)) return "character"; - - if ("bool".equals(type)) return "boolean"; - if ("yes-no".equals(type)) return "yes_no"; - if ("yesno".equals(type)) return "yes_no"; - if ("yes_no".equals(type)) return "yes_no"; - if ("true-false".equals(type)) return "true_false"; - if ("truefalse".equals(type)) return "true_false"; - if ("true_false".equals(type)) return "true_false"; - if ("varchar".equals(type)) return "string"; - if ("big-decimal".equals(type)) return "big_decimal"; - if ("bigdecimal".equals(type)) return "big_decimal"; - if ("java.math.bigdecimal".equals(type)) return "big_decimal"; - if ("big-integer".equals(type)) return "big_integer"; - if ("biginteger".equals(type)) return "big_integer"; - if ("bigint".equals(type)) return "big_integer"; - if ("java.math.biginteger".equals(type)) return "big_integer"; - if ("byte[]".equals(type)) return "binary"; - if ("serializable".equals(type)) return "serializable"; - - if ("datetime".equals(type)) return "timestamp"; - if ("numeric".equals(type)) return "double"; - if ("number".equals(type)) return "double"; - if ("numeric".equals(type)) return "double"; - if ("char".equals(type)) return "character"; - if ("nchar".equals(type)) return "character"; - if ("decimal".equals(type)) return "double"; - if ("eurodate".equals(type)) return "timestamp"; - if ("usdate".equals(type)) return "timestamp"; - if ("int".equals(type)) return "integer"; - if ("varchar".equals(type)) return "string"; - if ("nvarchar".equals(type)) return "string"; - - return defaultValue; - - // FUTURE - /* - * - * add support for - any, object,other - * - * add support for custom types https://issues.jboss.org/browse/RAILO-1341 - array - base64 - guid - - * memory - node, xml - query - struct - uuid - variablename, variable_name - variablestring, - * variable_string - * - */ - - } - - public static Object toHibernateValue(PageContext pc, Object value, String type) throws PageException { - type = toHibernateType(type, null); - // return same value - if ("long".equals(type)) return CommonUtil.toLong(value); - if ("binary".equals(type) || "imm_binary".equals(type)) return CommonUtil.toBinary(value); - if ("boolean".equals(type) || "yes_no".equals(type) || "true_false".equals(type)) return CommonUtil.toBoolean(value); - if ("character".equals(type)) return CommonUtil.toCharacter(value); - if ("date".equals(type) || "imm_date".equals(type)) return CommonUtil.toDate(value, pc.getTimeZone()); - if ("big_decimal".equals(type)) return CommonUtil.toBigDecimal(value); - if ("double".equals(type)) return CommonUtil.toDouble(value); - if ("float".equals(type)) return CommonUtil.toFloat(value); - if ("integer".equals(type)) return CommonUtil.toInteger(value); - if ("string".equals(type)) return CommonUtil.toString(value); - if ("big_integer".equals(type)) return new BigInteger(CommonUtil.toString(value)); - if ("short".equals(type)) return CommonUtil.toShort(value); - if ("time".equals(type) || "imm_time".equals(type)) return new Time(CommonUtil.toDate(value, pc.getTimeZone()).getTime()); - if ("timestamp".equals(type) || "imm_timestamp".equals(type)) return new Timestamp(CommonUtil.toDate(value, pc.getTimeZone()).getTime()); - if ("byte".equals(type)) return CommonUtil.toBinary(value); - if ("text".equals(type)) return CommonUtil.toString(value); - if ("calendar".equals(type) || "calendar_date".equals(type) || "imm_calendar".equals(type) || "imm_calendar_date".equals(type)) - return CommonUtil.toCalendar(CommonUtil.toDate(value, pc.getTimeZone()), pc.getTimeZone(), pc.getLocale()); - if ("locale".equals(type)) return CommonUtil.toLocale(CommonUtil.toString(value)); - if ("timezone".equals(type)) return CommonUtil.toTimeZone(value, null); - if ("currency".equals(type)) return value; - - if ("imm_serializable".equals(type)) return value; - if ("serializable".equals(type)) return "serializable"; - - return value; - } - - /** - * translate CFMl specific types to Hibernate/SQL specific types - * - * @param engine - * @param ci - * @param value - * @return - * @throws PageException - */ - public static Object toSQL(ColumnInfo ci, Object value, RefBoolean isArray) throws PageException { - return toSQL(ci.getType(), value, isArray); - } - - /** - * translate CFMl specific types to Hibernate/SQL specific types - * - * @param engine - * @param type - * @param value - * @return - * @throws PageException - */ - public static Object toSQL(Type type, Object value, RefBoolean isArray) throws PageException { - int t = toSQLType(type.getName(), Types.OTHER); - // if(t==Types.OTHER) return value; - return toSQL(t, value, isArray); - } - - /** - * translate CFMl specific type to SQL specific types - * - * @param engine - * @param sqlType - * @param value - * @return - * @throws PageException - */ - private static Object toSQL(int sqlType, Object value, RefBoolean isArray) throws PageException { - if (sqlType == Types.OTHER && value instanceof PersistentCollection) { - return value; - } - - if (isArray != null) isArray.setValue(false); - - Boolean _isArray = null; - boolean hasType = sqlType != Types.OTHER; - - // first we try to convert without any checking - if (hasType) { - try { - return CommonUtil.toSqlType(CommonUtil.toSQLItem(value, sqlType)); - } - catch (PageException pe) { - _isArray = CommonUtil.isArray(value); - if (!_isArray.booleanValue()) throw pe; - } - } - - // already a hibernate type - - // can only be null if type is other - if (_isArray == null) { - if (!CommonUtil.isArray(value)) return value; - } - - // at this point it is for sure that the value is an array - if (isArray != null) isArray.setValue(true); - Array src = CommonUtil.toArray(value); - Iterator it = src.valueIterator(); - ArrayList trg = new ArrayList(); - Object v; - while (it.hasNext()) { - v = it.next(); - if (v == null) continue; - if (hasType) { - trg.add(CommonUtil.toSqlType(CommonUtil.toSQLItem(v, sqlType))); - } - else trg.add(v); - } - return trg; - } - - public static lucee.runtime.type.Query toQuery(PageContext pc, HibernateORMSession session, Object obj, String name) throws PageException { - Query qry = null; - // a single entity - if (!CommonUtil.isArray(obj)) { - qry = toQuery(pc, session, HibernateCaster.toComponent(obj), name, null, 1, 1); - } - - // a array of entities - else { - Array arr = CommonUtil.toArray(obj); - int len = arr.size(); - if (len > 0) { - Iterator it = arr.valueIterator(); - int row = 1; - while (it.hasNext()) { - qry = toQuery(pc, session, HibernateCaster.toComponent(it.next()), name, qry, len, row++); - } - } - else qry = CommonUtil.createQuery(new Collection.Key[0], 0, "orm"); - } - - if (qry == null) { - if (!Util.isEmpty(name)) throw ExceptionUtil.createException(session, null, "there is no entity inheritance that match the name [" + name + "]", null); - throw ExceptionUtil.createException(session, null, "cannot create query", null); - } - return qry; - } - - private static Query toQuery(PageContext pc, HibernateORMSession session, Component cfc, String entityName, Query qry, int rowcount, int row) throws PageException { - // inheritance mapping - if (!Util.isEmpty(entityName)) { - // String cfcName = toComponentName(HibernateCaster.toComponent(pc, entityName)); - return inheritance(pc, session, cfc, qry, entityName); - } - return populateQuery(pc, session, cfc, qry); - } - - private static Query populateQuery(PageContext pc, HibernateORMSession session, Component cfc, Query qry) throws PageException { - Property[] properties = CommonUtil.getProperties(cfc, true, true, false, false); - String dsn = CommonUtil.getDataSourceName(pc, cfc); - ComponentScope scope = cfc.getComponentScope(); - HibernateORMEngine engine = (HibernateORMEngine) session.getEngine(); - - // init - if (qry == null) { - SessionFactory factory = session.getRawSessionFactory(dsn); - ClassMetadata md = factory.getClassMetadata(getEntityName(cfc)); - Array names = CommonUtil.createArray(); - Array types = CommonUtil.createArray(); - String name; - // ColumnInfo ci; - int t; - Object obj; - Struct sct; - String fieldType; - for (int i = 0; i < properties.length; i++) { - obj = properties[i].getMetaData(); - if (obj instanceof Struct) { - sct = (Struct) obj; - fieldType = CommonUtil.toString(sct.get(CommonUtil.FIELDTYPE, null), null); - if ("one-to-many".equalsIgnoreCase(fieldType) || "many-to-many".equalsIgnoreCase(fieldType) || "many-to-one".equalsIgnoreCase(fieldType) - || "one-to-one".equalsIgnoreCase(fieldType)) - continue; - - } - - name = HibernateUtil.validateColumnName(md, properties[i].getName(), null); - // if(columnsInfo!=null)ci=(ColumnInfo) columnsInfo.get(name,null); - // else ci=null; - names.append(name); - if (name != null) { - - t = HibernateCaster.toSQLType(HibernateUtil.getPropertyType(md, name).getName(), NULL); - if (t == NULL) types.append("object"); - else types.append(CFMLEngineFactory.getInstance().getDBUtil().toStringType(t)); - } - else types.append("object"); - } - - qry = CommonUtil.createQuery(names, types, 0, getEntityName(cfc)); - - } - // check - else if (engine.getMode() == ORMEngine.MODE_STRICT) { - if (!qry.getName().equals(getEntityName(cfc))) throw ExceptionUtil.createException(session, null, "can only merge entities of the same kind to a query", null); - } - - // populate - Key[] names = CFMLEngineFactory.getInstance().getDBUtil().getColumnNames(qry); - - int row = qry.addRow(); - for (int i = 0; i < names.length; i++) { - qry.setAtEL(names[i], row, scope.get(names[i], null)); - } - return qry; - } - - private static Query inheritance(PageContext pc, HibernateORMSession session, Component cfc, Query qry, String entityName) throws PageException { - Property[] properties = cfc.getProperties(true, false, false, false); - ComponentScope scope = cfc.getComponentScope(); - Object value; - Array arr; - for (int i = 0; i < properties.length; i++) { - value = scope.get(CommonUtil.createKey(properties[i].getName()), null); - if (value instanceof Component) { - qry = inheritance(pc, session, qry, cfc, (Component) value, entityName); - } - else if (CommonUtil.isArray(value)) { - arr = CommonUtil.toArray(value); - Iterator it = arr.valueIterator(); - while (it.hasNext()) { - value = it.next(); - if (value instanceof Component) { - qry = inheritance(pc, session, qry, cfc, (Component) value, entityName); - } - } - } - } - return qry; - } - - private static Query inheritance(PageContext pc, HibernateORMSession session, Query qry, Component parent, Component child, String entityName) throws PageException { - if (getEntityName(child).equalsIgnoreCase(entityName)) return populateQuery(pc, session, child, qry); - return inheritance(pc, session, child, qry, entityName);// MUST geh ACF auch so tief? - } - - /** - * return the full name (package and name) of a component - * - * @param cfc - * @return - */ - public static String toComponentName(Component cfc) { - return cfc.getPageSource().getComponentName(); - } - - public static Component toComponent(Object obj) throws PageException { - return CommonUtil.toComponent(obj); - } + private static final int NULL = -178696; + + public static Object toCFML(Object src) { + if (src == null) + return null; + if (src instanceof Collection) + return src; + + if (src instanceof List) { + return toCFML((List) src); + } + /* + * if(src instanceof Map){ return toCFML(pc,(Map) src); } + */ + return src; + } + + public static Array toCFML(List src) { + int size = src.size(); + + Array trg = CommonUtil.createArray(); + for (int i = 0; i < size; i++) { + trg.setEL(i + 1, toCFML(src.get(i))); + } + return trg; + } + + /* + * public static Object toCFML(PageContext pc,Map src) throws PageException { + * + * Object type =src.remove("$type$"); if(type instanceof String){ + * + * Component cfc = toComponent(pc, (String)type); return toCFML(pc,src, cfc); } + * + * + * Iterator> it = src.entrySet().iterator(); Struct trg=CommonUtil.createStruct(); + * Map.Entry entry; while(it.hasNext()){ entry=it.next(); + * trg.setEL(entry.getKey(),toCFML(pc,entry.getValue())); } return trg; } + */ + + public static String getEntityName(Component cfc) { + + String name = null; + try { + name = CommonUtil.toString(cfc.getMetaStructItem(CommonUtil.ENTITY_NAME), null); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + try { + Struct md = cfc.getMetaData(CommonUtil.pc()); + name = CommonUtil.toString(md.get(CommonUtil.ENTITY_NAME), null); + + } catch (PageException e) { + } + } + + if (!Util.isEmpty(name)) { + return name; + } + return getName(cfc); + + } + + private static String getName(Component cfc) { + String name = null; + // MUSTMUST cfc.getName() should return the real case, this should not be needed + name = cfc.getPageSource().getDisplayPath(); + name = CommonUtil.last(name, "\\/"); + int index = name.lastIndexOf('.'); + name = name.substring(0, index); + return name; + } + + public static String toHibernateType(ColumnInfo info, String type, String defaultValue) { + + // no type defined + if (Util.isEmpty(type, true)) { + return HibernateCaster.toHibernateType(info, defaultValue); + } + + // type defined + String tmp = HibernateCaster.toHibernateType(type, null); + if (tmp != null) + return tmp; + + if (info != null) { + tmp = HibernateCaster.toHibernateType(info, defaultValue); + return tmp; + } + return defaultValue; + + } + + public static int toSQLType(String type, int defaultValue) { + type = type.trim().toLowerCase(); + type = toHibernateType(type, type); + if ("long".equals(type)) + return Types.BIGINT; + if ("binary".equals(type)) + return Types.BINARY; + if ("boolean".equals(type)) + return Types.BIT; + if ("blob".equals(type)) + return Types.BLOB; + if ("boolean".equals(type)) + return Types.BOOLEAN; + if ("character".equals(type)) + return Types.CHAR; + if ("clob".equals(type)) + return Types.CLOB; + if ("date".equals(type)) + return Types.DATE; + if ("big_decimal".equals(type)) + return Types.DECIMAL; + if ("big_integer".equals(type)) + return Types.NUMERIC; + if ("double".equals(type)) + return Types.DOUBLE; + if ("float".equals(type)) + return Types.FLOAT; + if ("integer".equals(type)) + return Types.INTEGER; + if ("binary".equals(type)) + return Types.VARBINARY; + if ("string".equals(type)) + return Types.VARCHAR; + if ("short".equals(type)) + return Types.SMALLINT; + if ("time".equals(type)) + return Types.TIME; + if ("timestamp".equals(type)) + return Types.TIMESTAMP; + if ("byte".equals(type)) + return Types.TINYINT; + + return defaultValue; + } + + public static String toHibernateType(ColumnInfo info, String defaultValue) { + if (info == null) + return defaultValue; + + String rtn = toHibernateType(info.getType(), info.getSize(), null); + if (rtn != null) + return rtn; + return toHibernateType(info.getTypeName(), defaultValue); + } + + public static String toHibernateType(int type, int size, String defaultValue) { + // MUST do better + switch (type) { + case Types.ARRAY: + return ""; + case Types.BIGINT: + return "long"; + case Types.BINARY: + return "binary"; + case Types.BIT: + return "boolean"; + case Types.BLOB: + return "blob"; + case Types.BOOLEAN: + return "boolean"; + case Types.CHAR: + return "string"; + // if(size>1) return "string"; + // return "character"; + case Types.CLOB: + return "clob"; + // case Types.DATALINK: return ""; + case Types.DATE: + return "date"; + case Types.DECIMAL: + return "big_decimal"; + // case Types.DISTINCT: return ""; + case Types.DOUBLE: + return "double"; + case Types.FLOAT: + return "float"; + case Types.INTEGER: + return "integer"; + // case Types.JAVA_OBJECT: return ""; + case Types.LONGVARBINARY: + return "binary"; + case Types.LONGVARCHAR: + return "string"; + // case Types.NULL: return ""; + case Types.NUMERIC: + return "big_decimal"; + // case Types.OTHER: return ""; + // case Types.REAL: return ""; + // case Types.REF: return ""; + case Types.SMALLINT: + return "short"; + // case Types.STRUCT: return ""; + case Types.TIME: + return "time"; + case Types.TIMESTAMP: + return "timestamp"; + case Types.TINYINT: + return "byte"; + case Types.VARBINARY: + return "binary"; + case Types.NVARCHAR: + return "string"; + case Types.VARCHAR: + return "string"; + } + return defaultValue; + } + + public static String toHibernateType(ORMSession session, String type) throws PageException { + String res = toHibernateType(type, null); + if (res == null) + throw ExceptionUtil.createException(session, null, "the type [" + type + "] is not supported", null); + return res; + } + + // calendar_date: A type mapping for a Calendar object that represents a date + // calendar: A type mapping for a Calendar object that represents a datetime. + public static String toHibernateType(String type, String defaultValue) { + type = type.trim().toLowerCase(); + type = Util.replace(type, "java.lang.", "", true); + type = Util.replace(type, "java.util.", "", true); + type = Util.replace(type, "java.sql.", "", true); + + // return same value + if ("long".equals(type)) + return type; + if ("binary".equals(type)) + return type; + if ("boolean".equals(type)) + return type; + if ("blob".equals(type)) + return "binary"; + if ("boolean".equals(type)) + return type; + if ("character".equals(type)) + return type; + if ("clob".equals(type)) + return "text"; + if ("date".equals(type)) + return type; + if ("big_decimal".equals(type)) + return type; + if ("double".equals(type)) + return type; + if ("float".equals(type)) + return type; + if ("integer".equals(type)) + return type; + if ("binary".equals(type)) + return type; + if ("string".equals(type)) + return type; + if ("big_integer".equals(type)) + return type; + if ("short".equals(type)) + return type; + if ("time".equals(type)) + return type; + if ("timestamp".equals(type)) + return type; + if ("byte".equals(type)) + return type; + if ("binary".equals(type)) + return type; + if ("string".equals(type)) + return type; + if ("text".equals(type)) + return type; + if ("calendar".equals(type)) + return type; + if ("calendar_date".equals(type)) + return type; + if ("locale".equals(type)) + return type; + if ("timezone".equals(type)) + return type; + if ("currency".equals(type)) + return type; + + if ("imm_date".equals(type)) + return type; + if ("imm_time".equals(type)) + return type; + if ("imm_timestamp".equals(type)) + return type; + if ("imm_calendar".equals(type)) + return type; + if ("imm_calendar_date".equals(type)) + return type; + if ("imm_serializable".equals(type)) + return type; + if ("imm_binary".equals(type)) + return type; + + // return different value + if ("bigint".equals(type)) + return "long"; + if ("bit".equals(type)) + return "boolean"; + + if ("int".equals(type)) + return "integer"; + if ("char".equals(type)) + return "character"; + + if ("bool".equals(type)) + return "boolean"; + if ("yes-no".equals(type)) + return "yes_no"; + if ("yesno".equals(type)) + return "yes_no"; + if ("yes_no".equals(type)) + return "yes_no"; + if ("true-false".equals(type)) + return "true_false"; + if ("truefalse".equals(type)) + return "true_false"; + if ("true_false".equals(type)) + return "true_false"; + if ("varchar".equals(type)) + return "string"; + if ("big-decimal".equals(type)) + return "big_decimal"; + if ("bigdecimal".equals(type)) + return "big_decimal"; + if ("java.math.bigdecimal".equals(type)) + return "big_decimal"; + if ("big-integer".equals(type)) + return "big_integer"; + if ("biginteger".equals(type)) + return "big_integer"; + if ("bigint".equals(type)) + return "big_integer"; + if ("java.math.biginteger".equals(type)) + return "big_integer"; + if ("byte[]".equals(type)) + return "binary"; + if ("serializable".equals(type)) + return "serializable"; + + if ("datetime".equals(type)) + return "timestamp"; + if ("numeric".equals(type)) + return "double"; + if ("number".equals(type)) + return "double"; + if ("numeric".equals(type)) + return "double"; + if ("char".equals(type)) + return "character"; + if ("nchar".equals(type)) + return "character"; + if ("decimal".equals(type)) + return "double"; + if ("eurodate".equals(type)) + return "timestamp"; + if ("usdate".equals(type)) + return "timestamp"; + if ("int".equals(type)) + return "integer"; + if ("varchar".equals(type)) + return "string"; + if ("nvarchar".equals(type)) + return "string"; + + return defaultValue; + + // FUTURE + /* + * + * add support for - any, object,other + * + * add support for custom types https://issues.jboss.org/browse/RAILO-1341 - array - base64 - guid - memory - + * node, xml - query - struct - uuid - variablename, variable_name - variablestring, variable_string + * + */ + + } + + public static Object toHibernateValue(PageContext pc, Object value, String type) throws PageException { + type = toHibernateType(type, null); + // return same value + if ("long".equals(type)) + return CommonUtil.toLong(value); + if ("binary".equals(type) || "imm_binary".equals(type)) + return CommonUtil.toBinary(value); + if ("boolean".equals(type) || "yes_no".equals(type) || "true_false".equals(type)) + return CommonUtil.toBoolean(value); + if ("character".equals(type)) + return CommonUtil.toCharacter(value); + if ("date".equals(type) || "imm_date".equals(type)) + return CommonUtil.toDate(value, pc.getTimeZone()); + if ("big_decimal".equals(type)) + return CommonUtil.toBigDecimal(value); + if ("double".equals(type)) + return CommonUtil.toDouble(value); + if ("float".equals(type)) + return CommonUtil.toFloat(value); + if ("integer".equals(type)) + return CommonUtil.toInteger(value); + if ("string".equals(type)) + return CommonUtil.toString(value); + if ("big_integer".equals(type)) + return new BigInteger(CommonUtil.toString(value)); + if ("short".equals(type)) + return CommonUtil.toShort(value); + if ("time".equals(type) || "imm_time".equals(type)) + return new Time(CommonUtil.toDate(value, pc.getTimeZone()).getTime()); + if ("timestamp".equals(type) || "imm_timestamp".equals(type)) + return new Timestamp(CommonUtil.toDate(value, pc.getTimeZone()).getTime()); + if ("byte".equals(type)) + return CommonUtil.toBinary(value); + if ("text".equals(type)) + return CommonUtil.toString(value); + if ("calendar".equals(type) || "calendar_date".equals(type) || "imm_calendar".equals(type) + || "imm_calendar_date".equals(type)) + return CommonUtil.toCalendar(CommonUtil.toDate(value, pc.getTimeZone()), pc.getTimeZone(), pc.getLocale()); + if ("locale".equals(type)) + return CommonUtil.toLocale(CommonUtil.toString(value)); + if ("timezone".equals(type)) + return CommonUtil.toTimeZone(value, null); + if ("currency".equals(type)) + return value; + + if ("imm_serializable".equals(type)) + return value; + if ("serializable".equals(type)) + return "serializable"; + + return value; + } + + /** + * translate CFMl specific types to Hibernate/SQL specific types + * + * @param ci + * @param value + * @param isArray + * + * @throws PageException + */ + public static Object toSQL(ColumnInfo ci, Object value, RefBoolean isArray) throws PageException { + return toSQL(ci.getType(), value, isArray); + } + + /** + * translate CFMl specific types to Hibernate/SQL specific types + * + * @param type + * @param value + * @param isArray + * + * @throws PageException + */ + public static Object toSQL(Type type, Object value, RefBoolean isArray) throws PageException { + int t = toSQLType(type.getName(), Types.OTHER); + // if(t==Types.OTHER) return value; + return toSQL(t, value, isArray); + } + + /** + * translate CFMl specific type to SQL specific types + * + * @param sqlType + * @param value + * @param isArray + * + * @throws PageException + */ + private static Object toSQL(int sqlType, Object value, RefBoolean isArray) throws PageException { + if (sqlType == Types.OTHER && value instanceof PersistentCollection) { + return value; + } + + if (isArray != null) + isArray.setValue(false); + + Boolean _isArray = null; + boolean hasType = sqlType != Types.OTHER; + + // first we try to convert without any checking + if (hasType) { + try { + return CommonUtil.toSqlType(CommonUtil.toSQLItem(value, sqlType)); + } catch (PageException pe) { + _isArray = CommonUtil.isArray(value); + if (!_isArray.booleanValue()) + throw pe; + } + } + + // already a hibernate type + + // can only be null if type is other + if (_isArray == null) { + if (!CommonUtil.isArray(value)) + return value; + } + + // at this point it is for sure that the value is an array + if (isArray != null) + isArray.setValue(true); + Array src = CommonUtil.toArray(value); + Iterator it = src.valueIterator(); + ArrayList trg = new ArrayList(); + Object v; + while (it.hasNext()) { + v = it.next(); + if (v == null) + continue; + if (hasType) { + trg.add(CommonUtil.toSqlType(CommonUtil.toSQLItem(v, sqlType))); + } else + trg.add(v); + } + return trg; + } + + public static lucee.runtime.type.Query toQuery(PageContext pc, HibernateORMSession session, Object obj, String name) + throws PageException { + Query qry = null; + // a single entity + if (!CommonUtil.isArray(obj)) { + qry = toQuery(pc, session, HibernateCaster.toComponent(obj), name, null, 1, 1); + } + + // a array of entities + else { + Array arr = CommonUtil.toArray(obj); + int len = arr.size(); + if (len > 0) { + Iterator it = arr.valueIterator(); + int row = 1; + while (it.hasNext()) { + qry = toQuery(pc, session, HibernateCaster.toComponent(it.next()), name, qry, len, row++); + } + } else + qry = CommonUtil.createQuery(new Collection.Key[0], 0, "orm"); + } + + if (qry == null) { + if (!Util.isEmpty(name)) + throw ExceptionUtil.createException(session, null, + "there is no entity inheritance that match the name [" + name + "]", null); + throw ExceptionUtil.createException(session, null, "cannot create query", null); + } + return qry; + } + + private static Query toQuery(PageContext pc, HibernateORMSession session, Component cfc, String entityName, + Query qry, int rowcount, int row) throws PageException { + // inheritance mapping + if (!Util.isEmpty(entityName)) { + // String cfcName = toComponentName(HibernateCaster.toComponent(pc, entityName)); + return inheritance(pc, session, cfc, qry, entityName); + } + return populateQuery(pc, session, cfc, qry); + } + + private static Query populateQuery(PageContext pc, HibernateORMSession session, Component cfc, Query qry) + throws PageException { + Property[] properties = CommonUtil.getProperties(cfc, true, true, false, false); + String dsn = CommonUtil.getDataSourceName(pc, cfc); + ComponentScope scope = cfc.getComponentScope(); + HibernateORMEngine engine = (HibernateORMEngine) session.getEngine(); + + // init + if (qry == null) { + SessionFactory factory = session.getRawSessionFactory(dsn); + ClassMetadata md = factory.getClassMetadata(getEntityName(cfc)); + Array names = CommonUtil.createArray(); + Array types = CommonUtil.createArray(); + String name; + // ColumnInfo ci; + int t; + Object obj; + Struct sct; + String fieldType; + for (int i = 0; i < properties.length; i++) { + obj = properties[i].getMetaData(); + if (obj instanceof Struct) { + sct = (Struct) obj; + fieldType = CommonUtil.toString(sct.get(CommonUtil.FIELDTYPE, null), null); + if ("one-to-many".equalsIgnoreCase(fieldType) || "many-to-many".equalsIgnoreCase(fieldType) + || "many-to-one".equalsIgnoreCase(fieldType) || "one-to-one".equalsIgnoreCase(fieldType)) + continue; + + } + + name = HibernateUtil.validateColumnName(md, properties[i].getName(), null); + // if(columnsInfo!=null)ci=(ColumnInfo) columnsInfo.get(name,null); + // else ci=null; + names.append(name); + if (name != null) { + + t = HibernateCaster.toSQLType(HibernateUtil.getPropertyType(md, name).getName(), NULL); + if (t == NULL) + types.append("object"); + else + types.append(CFMLEngineFactory.getInstance().getDBUtil().toStringType(t)); + } else + types.append("object"); + } + + qry = CommonUtil.createQuery(names, types, 0, getEntityName(cfc)); + + } + // check + else if (engine.getMode() == ORMEngine.MODE_STRICT) { + if (!qry.getName().equals(getEntityName(cfc))) + throw ExceptionUtil.createException(session, null, + "can only merge entities of the same kind to a query", null); + } + + // populate + Key[] names = CFMLEngineFactory.getInstance().getDBUtil().getColumnNames(qry); + + int row = qry.addRow(); + for (int i = 0; i < names.length; i++) { + qry.setAtEL(names[i], row, scope.get(names[i], null)); + } + return qry; + } + + private static Query inheritance(PageContext pc, HibernateORMSession session, Component cfc, Query qry, + String entityName) throws PageException { + Property[] properties = cfc.getProperties(true, false, false, false); + ComponentScope scope = cfc.getComponentScope(); + Object value; + Array arr; + for (int i = 0; i < properties.length; i++) { + value = scope.get(CommonUtil.createKey(properties[i].getName()), null); + if (value instanceof Component) { + qry = inheritance(pc, session, qry, cfc, (Component) value, entityName); + } else if (CommonUtil.isArray(value)) { + arr = CommonUtil.toArray(value); + Iterator it = arr.valueIterator(); + while (it.hasNext()) { + value = it.next(); + if (value instanceof Component) { + qry = inheritance(pc, session, qry, cfc, (Component) value, entityName); + } + } + } + } + return qry; + } + + private static Query inheritance(PageContext pc, HibernateORMSession session, Query qry, Component parent, + Component child, String entityName) throws PageException { + if (getEntityName(child).equalsIgnoreCase(entityName)) + return populateQuery(pc, session, child, qry); + return inheritance(pc, session, child, qry, entityName);// MUST geh ACF auch so tief? + } + + /** + * return the full name (package and name) of a component + * + * @param cfc + * + * @return Full name of a component. + */ + public static String toComponentName(Component cfc) { + return cfc.getPageSource().getComponentName(); + } + + public static Component toComponent(Object obj) throws PageException { + return CommonUtil.toComponent(obj); + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HibernateConstants.java b/source/java/src/org/lucee/extension/orm/hibernate/HibernateConstants.java deleted file mode 100755 index 03671943..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/HibernateConstants.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.lucee.extension.orm.hibernate; - -public class HibernateConstants { - - public static final int CASCADE_NONE = 0; - public static final int CASCADE_ALL = 1; - public static final int CASCADE_SAVE_UPDATE = 2; - public static final int CASCADE_DELETE = 4; - public static final int CASCADE_DELETE_ORPHAN = 8; - public static final int CASCADE_ALL_DELETE_ORPHAN = 16; - public static final int REFRESH = 32; - - public static final int COLLECTION_TYPE_ARRAY = 1; - public static final int COLLECTION_TYPE_STRUCT = 2; - -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMEngine.java b/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMEngine.java index 8909d874..eda93033 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMEngine.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMEngine.java @@ -1,6 +1,5 @@ package org.lucee.extension.orm.hibernate; -import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -8,21 +7,16 @@ import java.util.concurrent.ConcurrentHashMap; import org.hibernate.EntityMode; -import org.hibernate.SessionFactory; -import org.hibernate.cfg.Configuration; import org.hibernate.tuple.entity.EntityTuplizerFactory; import org.lucee.extension.orm.hibernate.event.EventListenerIntegrator; -import org.lucee.extension.orm.hibernate.event.InterceptorImpl; import org.lucee.extension.orm.hibernate.tuplizer.AbstractEntityTuplizerImpl; -import org.lucee.extension.orm.hibernate.util.XMLUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ExceptionUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; import lucee.commons.io.log.Log; import lucee.commons.io.res.Resource; -import lucee.loader.engine.CFMLEngine; import lucee.loader.engine.CFMLEngineFactory; -import lucee.loader.util.Util; import lucee.runtime.Component; import lucee.runtime.PageContext; import lucee.runtime.db.DataSource; @@ -36,441 +30,404 @@ public class HibernateORMEngine implements ORMEngine { - private static final int INIT_NOTHING = 1; - private static final int INIT_CFCS = 2; - private static final int INIT_ALL = 2; - - private Map factories = new ConcurrentHashMap(); - - static { - // Patch because commandbox otherwise uses com.sun.xml.internal.bind.v2.ContextFactory for unknown - // reason - // Class clazz = ContextFactory.class; - // System.setProperty("javax.xml.bind.context.factory", "com.sun.xml.bind.v2.ContextFactory"); - } - - public HibernateORMEngine() { - } - - @Override - public void init(PageContext pc) throws PageException { - SessionFactoryData data = getSessionFactoryData(pc, INIT_CFCS); - data.init();// init all factories - } - - @Override - public ORMSession createSession(PageContext pc) throws PageException { - try { - SessionFactoryData data = getSessionFactoryData(pc, INIT_NOTHING); - return new HibernateORMSession(pc, data); - } - catch (PageException pe) { - throw pe; - } - } - - /* - * QueryPlanCache getQueryPlanCache(PageContext pc) throws PageException { return - * getSessionFactoryData(pc,INIT_NOTHING).getQueryPlanCache(); } - */ - - /* - * public SessionFactory getSessionFactory(PageContext pc) throws PageException{ return - * getSessionFactory(pc,INIT_NOTHING); } - */ - - @Override - public boolean reload(PageContext pc, boolean force) throws PageException { - if (force) { - getSessionFactoryData(pc, INIT_ALL); - } - else { - if (factories.containsKey(hash(pc))) return false; - } - getSessionFactoryData(pc, INIT_CFCS); - return true; - } - - private SessionFactoryData getSessionFactoryData(PageContext pc, int initType) throws PageException { - ApplicationContext appContext = pc.getApplicationContext(); - if (!appContext.isORMEnabled()) throw ExceptionUtil.createException((ORMSession) null, null, "ORM is not enabled", ""); - - // datasource - ORMConfiguration ormConf = appContext.getORMConfiguration(); - - String key = hash(pc); - SessionFactoryData data = factories.get(key); - if (initType == INIT_ALL && data != null) { - data.reset(); - data = null; - } - if (data == null) { - data = new SessionFactoryData(this, ormConf); - factories.put(key, data); - } - - // config - try { - // arr=null; - if (initType != INIT_NOTHING) { - synchronized (data) { - - if (ormConf.autogenmap()) { - data.tmpList = HibernateSessionFactory.loadComponents(pc, this, ormConf); - - data.clearCFCs(); - } - else throw ExceptionUtil.createException(data, null, "orm setting autogenmap=false is not supported yet", null); - - // load entities - if (data.tmpList != null && data.tmpList.size() > 0) { - data.getNamingStrategy();// called here to make sure, it is called in the right context the - // first one - - // creates CFCInfo objects - { - Iterator it = data.tmpList.iterator(); - while (it.hasNext()) { - createMapping(pc, it.next(), ormConf, data); - } - } - if (data.tmpList.size() != data.sizeCFCs()) { - Component cfc; - String name, lcName; - Map names = new HashMap(); - Iterator it = data.tmpList.iterator(); - while (it.hasNext()) { - cfc = it.next(); - name = HibernateCaster.getEntityName(cfc); - lcName = name.toLowerCase(); - if (names.containsKey(lcName)) throw ExceptionUtil.createException(data, null, "Entity Name [" + name + "] is ambigous, [" + names.get(lcName) - + "] and [" + cfc.getPageSource().getDisplayPath() + "] use the same entity name.", ""); - names.put(lcName, cfc.getPageSource().getDisplayPath()); - } - } - } - } - } - } - finally { - data.tmpList = null; - } - - // already initialized for this application context - - // MUST - // cacheconfig - // cacheprovider - // ... - - Log log = pc.getConfig().getLog("orm"); - - Iterator> it = HibernateSessionFactory.createMappings(ormConf, data).entrySet().iterator(); - Entry e; - while (it.hasNext()) { - e = it.next(); - if (data.getConfiguration(e.getKey()) != null) continue; - - try { - data.setConfiguration(log, e.getValue(), data.getDataSource(e.getKey()), null, null, appContext == null ? "" : appContext.getName()); - } - catch (Exception ex) { - throw CommonUtil.toPageException(ex); - } - /* - * finally { CommonUtil.releaseDatasourceConnection(pc, dc); } - */ - addEventListeners(pc, data, e.getKey()); - - EntityTuplizerFactory tuplizerFactory = data.getConfiguration(e.getKey()).config.getEntityTuplizerFactory(); - tuplizerFactory.registerDefaultTuplizerClass(EntityMode.MAP, AbstractEntityTuplizerImpl.class); - tuplizerFactory.registerDefaultTuplizerClass(EntityMode.POJO, AbstractEntityTuplizerImpl.class); - - data.buildSessionFactory(e.getKey()); - } - - return data; - } - - private static void addEventListeners(PageContext pc, SessionFactoryData data, Key key) throws PageException { - if (!data.getORMConfiguration().eventHandling()) return; - String eventHandler = data.getORMConfiguration().eventHandler(); - - EventListenerIntegrator integrator = data.getEventListenerIntegrator(); - if (!Util.isEmpty(eventHandler, true)) { - // try { - Component c = pc.loadComponent(eventHandler.trim()); - if (c != null) { - integrator.setAllEventListener(c); - } - } - - Configuration conf = data.getConfiguration(key).config; - conf.setInterceptor(new InterceptorImpl(integrator != null ? integrator.getAllEventListener() : null)); - - Iterator it = data.getCFCs(key).values().iterator(); - while (it.hasNext()) { - CFCInfo info = it.next(); - integrator.setEventListene(info.getCFC()); - } - } - - public String hash(PageContext pc) { - ApplicationContext _ac = pc.getApplicationContext(); - Object ds = _ac.getORMDataSource(); - ORMConfiguration ormConf = _ac.getORMConfiguration(); - - StringBuilder data = new StringBuilder(ormConf.hash()).append(ormConf.autogenmap()).append(':').append(ormConf.getCatalog()).append(':') - .append(ormConf.isDefaultCfcLocation()).append(':').append(ormConf.getDbCreate()).append(':').append(ormConf.getDialect()).append(':') - .append(ormConf.eventHandling()).append(':').append(ormConf.namingStrategy()).append(':').append(ormConf.eventHandler()).append(':') - .append(ormConf.flushAtRequestEnd()).append(':').append(ormConf.logSQL()).append(':').append(ormConf.autoManageSession()).append(':') - .append(ormConf.skipCFCWithError()).append(':').append(ormConf.saveMapping()).append(':').append(ormConf.getSchema()).append(':') - .append(ormConf.secondaryCacheEnabled()).append(':').append(ormConf.useDBForMapping()).append(':').append(ormConf.getCacheProvider()).append(':').append(ds) - .append(':'); - - append(data, ormConf.getCfcLocations()); - append(data, ormConf.getSqlScript()); - append(data, ormConf.getCacheConfig()); - append(data, ormConf.getOrmConfig()); - - return CFMLEngineFactory.getInstance().getSystemUtil().hash64b(data.toString()); - } - - private void append(StringBuilder data, Resource[] reses) { - if (reses == null) return; - for (int i = 0; i < reses.length; i++) { - append(data, reses[i]); - } - } - - private void append(StringBuilder data, Resource res) { - if (res == null) return; - if (res.isFile()) { - CFMLEngine eng = CFMLEngineFactory.getInstance(); - try { - data.append(eng.getSystemUtil().hash64b(eng.getIOUtil().toString(res, null))); - return; - } - catch (IOException e) { - } - } - data.append(res.getAbsolutePath()).append(':'); - } - - public void createMapping(PageContext pc, Component cfc, ORMConfiguration ormConf, SessionFactoryData data) throws PageException { - String entityName = HibernateCaster.getEntityName(cfc); - CFCInfo info = data.getCFC(entityName, null); - String xml; - long cfcCompTime = HibernateUtil.getCompileTime(pc, cfc.getPageSource()); - if (info == null || (CommonUtil.equals(info.getCFC(), cfc))) {// && info.getModified()!=cfcCompTime - DataSource ds = CommonUtil.getDataSource(pc, cfc); - StringBuilder sb = new StringBuilder(); - - long xmlLastMod = loadMapping(sb, ormConf, cfc); - Element root; - // create mapping - if (true || xmlLastMod < cfcCompTime) {// MUSTMUST - data.reset(); - Document doc = null; - try { - doc = CommonUtil.newDocument(); - } - catch (Exception e) { - Log log = pc.getConfig().getLog("orm"); - log.error("hibernate", e); - } - - root = doc.createElement("hibernate-mapping"); - doc.appendChild(root); - pc.addPageSource(cfc.getPageSource(), true); - DatasourceConnection dc = CommonUtil.getDatasourceConnection(pc, ds, null, null, false); - try { - HBMCreator.createXMLMapping(pc, dc, cfc, root, data); - } - finally { - pc.removeLastPageSource(true); - CommonUtil.releaseDatasourceConnection(pc, dc, false); - } - try { - xml = XMLUtil.toString(root.getChildNodes(), true, true); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - saveMapping(ormConf, cfc, root); - } - // load - else { - xml = sb.toString(); - try { - root = CommonUtil.toXML(xml).getOwnerDocument().getDocumentElement(); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - /* - * print.o("1+++++++++++++++++++++++++++++++++++++++++"); print.o(xml); - * print.o("2+++++++++++++++++++++++++++++++++++++++++"); print.o(root); - * print.o("3+++++++++++++++++++++++++++++++++++++++++"); - */ - - } - data.addCFC(entityName, new CFCInfo(HibernateUtil.getCompileTime(pc, cfc.getPageSource()), xml, cfc, ds)); - } - - } - - private static void saveMapping(ORMConfiguration ormConf, Component cfc, Element hm) { - if (ormConf.saveMapping()) { - Resource res = cfc.getPageSource().getResource(); - if (res != null) { - res = res.getParentResource().getRealResource(res.getName() + ".hbm.xml"); - try { - CommonUtil.write(res, CommonUtil.toString(hm, false, true, HibernateSessionFactory.HIBERNATE_3_PUBLIC_ID, HibernateSessionFactory.HIBERNATE_3_SYSTEM_ID, - CommonUtil.UTF8().name()), CommonUtil.UTF8(), false); - } - catch (Exception e) { - } - } - } - } - - private static long loadMapping(StringBuilder sb, ORMConfiguration ormConf, Component cfc) { - - Resource res = cfc.getPageSource().getResource(); - if (res != null) { - res = res.getParentResource().getRealResource(res.getName() + ".hbm.xml"); - try { - sb.append(CommonUtil.toString(res, CommonUtil.UTF8())); - return res.lastModified(); - } - catch (Exception e) { - } - } - return 0; - } - - @Override - public int getMode() { - // MUST impl - return MODE_LAZY; - } - - @Override - public String getLabel() { - return "Hibernate"; - } - - @Override - public ORMConfiguration getConfiguration(PageContext pc) { - ApplicationContext ac = pc.getApplicationContext(); - if (!ac.isORMEnabled()) return null; - return ac.getORMConfiguration(); - } - - /** - * @param pc - * @param session - * @param entityName name of the entity to get - * @param unique create a unique version that can be manipulated - * @param init call the nit method of the cfc or not - * @return - * @throws PageException - */ - public Component create(PageContext pc, HibernateORMSession session, String entityName, boolean unique) throws PageException { - SessionFactoryData data = session.getSessionFactoryData(); - // get existing entity - Component cfc = _create(pc, entityName, unique, data); - if (cfc != null) return cfc; - - SessionFactoryData oldData = getSessionFactoryData(pc, INIT_NOTHING); - Map oldFactories = oldData.getFactories(); - SessionFactoryData newData = getSessionFactoryData(pc, INIT_CFCS); - Map newFactories = newData.getFactories(); - - Iterator> it = oldFactories.entrySet().iterator(); - Entry e; - SessionFactory newSF; - while (it.hasNext()) { - e = it.next(); - newSF = newFactories.get(e.getKey()); - if (e.getValue() != newSF) { - session.resetSession(pc, newSF, e.getKey(), oldData); - cfc = _create(pc, entityName, unique, data); - if (cfc != null) return cfc; - } - } - - ORMConfiguration ormConf = pc.getApplicationContext().getORMConfiguration(); - Resource[] locations = ormConf.getCfcLocations(); - - throw ExceptionUtil.createException(data, null, - "No entity (persistent component) with name [" + entityName + "] found, available entities are [" - + CFMLEngineFactory.getInstance().getListUtil().toList(data.getEntityNames(), ", ") + "] ", - "component are searched in the following directories [" + toString(locations) + "]"); - - } - - private String toString(Resource[] locations) { - if (locations == null) return ""; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < locations.length; i++) { - if (i > 0) sb.append(", "); - sb.append(locations[i].getAbsolutePath()); - } - return sb.toString(); - } - - private static Component _create(PageContext pc, String entityName, boolean unique, SessionFactoryData data) throws PageException { - CFCInfo info = data.getCFC(entityName, null); - if (info != null) { - Component cfc = info.getCFC(); - if (unique) { - cfc = (Component) cfc.duplicate(false); - if (cfc.contains(pc, CommonUtil.INIT)) cfc.call(pc, "init", new Object[] {}); - } - return cfc; - } - return null; - } + private Map factories = new ConcurrentHashMap(); + + static { + // Patch because commandbox otherwise uses com.sun.xml.internal.bind.v2.ContextFactory for unknown + // reason + // Class clazz = ContextFactory.class; + // System.setProperty("javax.xml.bind.context.factory", "com.sun.xml.bind.v2.ContextFactory"); + } + + public HibernateORMEngine() { + } + + /** + * Instantiate the Hibernate session and factory data. + * + * @param pc + * PageContext + */ + @Override + public void init(PageContext pc) throws PageException { + getOrBuildSessionFactoryData(pc); + } + + @Override + public ORMSession createSession(PageContext pc) throws PageException { + try { + return new HibernateORMSession(pc, getSessionFactory(pc.getApplicationContext().getName())); + } catch (PageException pe) { + throw pe; + } + } + + /** + * Reload the ORM session. + * + * Will NOT reload if force is false and the given pageContext already has a session factory. + * + * @param pc + * The current page context object + * @param force + * Force reload all session factory data. + */ + + @Override + public boolean reload(PageContext pc, boolean force) throws PageException { + if (force || !isInitializedForApplication(pc.getApplicationContext().getName())) { + buildSessionFactoryData(pc); + return false; + } + return false; + } + + private boolean isInitializedForApplication(String applicationName) { + return factories.containsKey(applicationName); + } + + /** + * Get the SessionFactoryData by application name. + * + * @param applicationName + * Lucee application name, retrieve from {@link lucee.runtime.listener.ApplicationContext#getName()} + */ + private SessionFactoryData getSessionFactory(String applicationName) { + return factories.get(applicationName); + } + + /** + * Retrieve a SessionFactoryData() if configured for this application. If not, build one and retrieve that. + * + * @param pc + * Lucee PageContext object. + * + * @return extension SessionFactoryData object. + * + * @throws PageException + */ + private SessionFactoryData getOrBuildSessionFactoryData(PageContext pc) throws PageException { + if (!isInitializedForApplication(pc.getApplicationContext().getName())) { + SessionFactoryData data = buildSessionFactoryData(pc); + data.init(); + } + return getSessionFactory(pc.getApplicationContext().getName()); + } + + /** + * Add a new session factory specific to this application. + * + * @param applicationName + * Lucee application name, retrieve from {@link lucee.runtime.listener.ApplicationContext#getName()} + * @param factory + * the SessionFactoryData object which houses the application-level Hibernate session factory + */ + private void setSessionFactory(String applicationName, SessionFactoryData factory) { + factories.put(applicationName, factory); + } + + /** + * Wipe the SessionFactoryData object for this Lucee application name from memory. + * + * @param applicationName + * The Lucee application name. + */ + private void clearSessionFactory(String applicationName) { + SessionFactoryData data = getSessionFactory(applicationName); + if (data != null) { + data.reset(); + factories.remove(applicationName); + } + } + + /** + * Reload all ORM configuration and entities and reload the HIbernate ORM session factory. + * + * @param pc + * Lucee PageContext + * + * @return SessionFactoryData + * + * @throws PageException + */ + private SessionFactoryData buildSessionFactoryData(PageContext pc) throws PageException { + ApplicationContext appContext = pc.getApplicationContext(); + if (!appContext.isORMEnabled()) + throw ExceptionUtil.createException((ORMSession) null, null, "ORM is not enabled", ""); + String applicationName = pc.getApplicationContext().getName(); + clearSessionFactory(applicationName); + + // datasource + ORMConfiguration ormConf = appContext.getORMConfiguration(); + SessionFactoryData data = new SessionFactoryData(this, ormConf); + setSessionFactory(applicationName, data); + + // config + try { + // arr=null; + synchronized (data) { + + data.tmpList = HibernateSessionFactory.loadComponents(pc, this, ormConf); + data.clearCFCs(); + + // load entities + if (data.hasTempCFCs()) { + data.getNamingStrategy();// called here to make sure, it is called in the right context the + // first one + + // creates CFCInfo objects + { + Iterator it = data.tmpList.iterator(); + while (it.hasNext()) { + createMapping(pc, it.next(), ormConf, data); + } + } + if (data.tmpList.size() != data.sizeCFCs()) { + Component cfc; + String name, lcName; + Map names = new HashMap(); + Iterator it = data.tmpList.iterator(); + while (it.hasNext()) { + cfc = it.next(); + name = HibernateCaster.getEntityName(cfc); + lcName = name.toLowerCase(); + if (names.containsKey(lcName)) + throw ExceptionUtil.createException(data, null, + "Entity Name [" + name + "] is ambigous, [" + names.get(lcName) + "] and [" + + cfc.getPageSource().getDisplayPath() + "] use the same entity name.", + ""); + names.put(lcName, cfc.getPageSource().getDisplayPath()); + } + } + } + } + } finally { + data.tmpList = null; + } + + // already initialized for this application context + + // MUST + // cacheconfig + // cacheprovider + // ... + + Log log = pc.getConfig().getLog("orm"); + + Iterator> it = HibernateSessionFactory.assembleMappingsByDatasource(data).entrySet() + .iterator(); + Entry e; + while (it.hasNext()) { + e = it.next(); + if (data.getConfiguration(e.getKey()) != null) + continue; + + try { + data.setConfiguration(log, e.getValue(), data.getDataSource(e.getKey()), null, null, + appContext == null ? "" : appContext.getName()); + } catch (Exception ex) { + throw CommonUtil.toPageException(ex); + } + /* + * finally { CommonUtil.releaseDatasourceConnection(pc, dc); } + */ + addEventListeners(pc, data, e.getKey()); + + EntityTuplizerFactory tuplizerFactory = data.getConfiguration(e.getKey()).config.getEntityTuplizerFactory(); + tuplizerFactory.registerDefaultTuplizerClass(EntityMode.MAP, AbstractEntityTuplizerImpl.class); + tuplizerFactory.registerDefaultTuplizerClass(EntityMode.POJO, AbstractEntityTuplizerImpl.class); + + data.buildSessionFactory(e.getKey()); + } + + return data; + } + + private static void addEventListeners(PageContext pc, SessionFactoryData data, Key key) throws PageException { + if (!data.getORMConfiguration().eventHandling()) + return; + String eventHandlerPath = data.getORMConfiguration().eventHandler(); + + EventListenerIntegrator integrator = data.getEventListenerIntegrator(); + if (eventHandlerPath != null && !eventHandlerPath.trim().isEmpty()) { + Component eventHandler = pc.loadComponent(eventHandlerPath.trim()); + if (eventHandler != null) { + integrator.setGlobalEventListener(eventHandler); + } + } + + Iterator it = data.getCFCs(key).values().iterator(); + while (it.hasNext()) { + CFCInfo info = it.next(); + integrator.appendEventListenerCFC(info.getCFC()); + } + } + + public void createMapping(PageContext pc, Component cfc, ORMConfiguration ormConf, SessionFactoryData data) + throws PageException { + String entityName = HibernateCaster.getEntityName(cfc); + CFCInfo info = data.getCFC(entityName, null); + String xml; + if (info == null || (CommonUtil.equals(info.getCFC(), cfc))) { + DataSource ds = CommonUtil.getDataSource(pc, cfc); + + if (ormConf.autogenmap()) { + data.reset(); + pc.addPageSource(cfc.getPageSource(), true); + // + /** + * TODO: Create a map of connections per datasource. + * Then we can grab and reuse existing connections based on the component's datasource annotation. + * This should save a good bit of time from opening and releasing connections hundreds of times for a single ORM reload. + */ + DatasourceConnection dc = CommonUtil.getDatasourceConnection(pc, ds, null, null, false); + try { + xml = HBMCreator.toMappingString(HBMCreator.createXMLMapping(pc, dc, cfc, data)); + if (ormConf.saveMapping()) { + HBMCreator.saveMapping(cfc, xml); + } + } catch (Exception e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } finally { + pc.removeLastPageSource(true); + CommonUtil.releaseDatasourceConnection(pc, dc, false); + } + } + // load + else { + try { + xml = HBMCreator.loadMapping(cfc); + } catch (Exception e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } + + } + data.addCFC(entityName, new CFCInfo(HibernateUtil.getCompileTime(pc, cfc.getPageSource()), xml, cfc, ds)); + } + + } + + @Override + public int getMode() { + // MUST impl + return MODE_LAZY; + } + + @Override + public String getLabel() { + return "Hibernate"; + } + + /** + * Get the ORM configuration for the given PageContext + * + * @param pc + * PageContext object + * + * @return ORMConfiguration + */ + @Override + public ORMConfiguration getConfiguration(PageContext pc) { + ApplicationContext ac = pc.getApplicationContext(); + if (!ac.isORMEnabled()) + return null; + return ac.getORMConfiguration(); + } + + /** + * @param pc + * @param session + * @param entityName + * name of the entity to get + * @param unique + * create a unique version that can be manipulated + * + * @return Lucee Component + * + * @throws PageException + */ + public Component create(PageContext pc, HibernateORMSession session, String entityName, boolean unique) + throws PageException { + SessionFactoryData data = session.getSessionFactoryData(); + // get existing entity + Component cfc = _create(pc, entityName, unique, data); + if (cfc != null) + return cfc; + + ORMConfiguration ormConf = pc.getApplicationContext().getORMConfiguration(); + Resource[] locations = ormConf.getCfcLocations(); + + throw ExceptionUtil.createException(data, null, + "No entity (persistent component) with name [" + entityName + "] found, available entities are [" + + CFMLEngineFactory.getInstance().getListUtil().toList(data.getEntityNames(), ", ") + "] ", + "component are searched in the following directories [" + toString(locations) + "]"); + + } + + private String toString(Resource[] locations) { + if (locations == null) + return ""; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < locations.length; i++) { + if (i > 0) + sb.append(", "); + sb.append(locations[i].getAbsolutePath()); + } + return sb.toString(); + } + + private static Component _create(PageContext pc, String entityName, boolean unique, SessionFactoryData data) + throws PageException { + CFCInfo info = data.getCFC(entityName, null); + if (info != null) { + Component cfc = info.getCFC(); + if (unique) { + cfc = (Component) cfc.duplicate(false); + if (cfc.contains(pc, CommonUtil.INIT)) + cfc.call(pc, "init", new Object[] {}); + } + return cfc; + } + return null; + } } class CFCInfo { - private String xml; - private long modified; - private Component cfc; - private DataSource ds; - - public CFCInfo(long modified, String xml, Component cfc, DataSource ds) { - this.modified = modified; - this.xml = xml; - this.cfc = cfc; - this.ds = ds; - } - - /** - * @return the cfc - */ - public Component getCFC() { - return cfc; - } - - /** - * @return the xml - */ - public String getXML() { - return xml; - } - - /** - * @return the modified - */ - public long getModified() { - return modified; - } - - public DataSource getDataSource() { - return ds; - } + private String xml; + private long modified; + private Component cfc; + private DataSource ds; + + public CFCInfo(long modified, String xml, Component cfc, DataSource ds) { + this.modified = modified; + this.xml = xml; + this.cfc = cfc; + this.ds = ds; + } + + /** + * @return the cfc + */ + public Component getCFC() { + return cfc; + } + + /** + * @return the xml + */ + public String getXML() { + return xml; + } + + /** + * @return the modified + */ + public long getModified() { + return modified; + } + + public DataSource getDataSource() { + return ds; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMSession.java b/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMSession.java index e0ff96a0..2350a7cd 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMSession.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMSession.java @@ -26,6 +26,9 @@ import org.hibernate.query.Query; import org.hibernate.query.internal.ParameterMetadataImpl; import org.hibernate.type.Type; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ExceptionUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; import lucee.commons.lang.types.RefBoolean; import lucee.loader.engine.CFMLEngineFactory; @@ -48,902 +51,1043 @@ public class HibernateORMSession implements ORMSession { - public class SessionAndConn { - - private Session s; - private DatasourceConnection dc; - private final DataSource d; - private SessionFactory factory; - - /* - * public SessionAndConn(Session session, DatasourceConnection dc) { this.session = session; this.dc - * = dc; this.d = dc.getDatasource(); } - * - * public SessionAndConn(Session session, DataSource d) { this.session = session; this.d = d; } - */ - - public SessionAndConn(PageContext pc, SessionFactory factory, DataSource ds) throws PageException { - this.d = ds; - this.factory = factory; - getSession(pc); - } - - public Session getSession(PageContext pc) throws PageException { - if (s == null || !s.isOpen()) s = factory.openSession(); - return s; - } - - public Connection getConnection(PageContext pc) throws PageException { - try { - if (dc == null || dc.isClosed()) { - connect(pc); - } - } - catch (SQLException e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - return dc.getConnection(); - } - - public void connect(PageContext pc) throws PageException { - if (dc != null) CommonUtil.releaseDatasourceConnection(pc, dc, true); - dc = CommonUtil.getDatasourceConnection(pc, d, null, null, true); - } - - public void close(PageContext pc) throws PageException { - if (s != null && s.isOpen()) { - s.close(); - s = null; - } - - if (dc != null) { - CommonUtil.releaseDatasourceConnection(pc, dc, true); - dc = null; - } - } - - public boolean isOpen() { - return s != null && s.isOpen(); - } - - public DataSource getDataSource() { - return d; - } - } - - private SessionFactoryData data; - private Map sessions = new HashMap(); - - public HibernateORMSession(PageContext pc, SessionFactoryData data) throws PageException { - this.data = data; - // this.dc=dc; - DataSource[] sources = data.getDataSources(); - - for (int i = 0; i < sources.length; i++) { - createSession(pc, data.getFactory(CommonUtil.toKey(sources[i].getName())), sources[i]); - } - } - - /* - * private Session session(){ return _session; } - */ - - private Session getSession(PageContext pc, Key datasSourceName) throws PageException { - return getSessionAndConn(pc, datasSourceName).getSession(pc); - } - - private SessionAndConn getSessionAndConn(PageContext pc, Key datasSourceName) throws PageException { - SessionAndConn sac = sessions.get(datasSourceName); - if (sac == null) { - CFMLEngineFactory.getInstance().getExceptionUtil().similarKeyMessage(sessions.keySet().toArray(new Key[sessions.size()]), datasSourceName.getString(), "datasource", - "datasources", null, true); - throw ExceptionUtil.createException(data, null, "there is no Session for the datasource [" + datasSourceName + "]", null); - } - Session s = sac.getSession(pc); - if (!s.isOpen() || !s.isConnected() || isClosed(s)) { - if (pc == null) pc = CFMLEngineFactory.getInstance().getThreadPageContext(); - - sac.connect(pc); - s.reconnect(sac.getConnection(pc)); - - } - return sac; - } - - private boolean isClosed(Session s) throws PageException { - return !s.isConnected(); - } - - public SessionFactoryData getSessionFactoryData() { - return data; - } - - SessionFactory getSessionFactory(Key datasSourceName) throws PageException { - Session s = getSession(null, datasSourceName); - return s.getSessionFactory(); - } - - void resetSession(PageContext pc, SessionFactory factory, Key dataSourceName, SessionFactoryData data) throws PageException { - - SessionAndConn sac = sessions.get(dataSourceName); - if (sac != null) { - sac.close(pc); - createSession(pc, factory, sac.getDataSource()); - return; - } - DataSource ds = data.getDataSource(dataSourceName); - createSession(pc, factory, ds); - } - - Session createSession(PageContext pc, SessionFactory factory, DataSource ds) throws PageException { - SessionAndConn sac = new SessionAndConn(pc, factory, ds); - - sessions.put(CommonUtil.toKey(ds.getName()), sac); - sac.getSession(pc).setFlushMode(FlushMode.MANUAL); - return sac.getSession(pc); - } - - @Override - public ORMEngine getEngine() { - return data.getEngine(); - } - - @Override - public void flushAll(PageContext pc) { - SessionAndConn sac; - Session s; - Iterator it = sessions.values().iterator(); - while (it.hasNext()) { - sac = it.next(); - if (sac.isOpen()) { - try { - s = sac.getSession(pc); - s.flush(); - } - catch (Exception e) { - } // we do this because of a Bug in Lucee that keeps session object in case of an exception for future - // request, this session then fail to flush, because the underlaying datasource is not defined in - // the current application.cfc. - } - } - } - - @Override - public void flush(PageContext pc) throws PageException { - flush(pc, null); - } - - @Override - public void flush(PageContext pc, String datasource) throws PageException { - _flush(pc, CommonUtil.getDataSource(pc, datasource)); - } - - private void _flush(PageContext pc, DataSource datasource) throws PageException { - Key dsn = CommonUtil.toKey(datasource.getName()); - - try { - getSession(pc, dsn).flush(); - } - catch (Throwable t) { - throw CommonUtil.toPageException(t); - } - - } - - @Override - public void delete(PageContext pc, Object obj) throws PageException { - if (CommonUtil.isArray(obj)) { - - // convert to a usable structure - Map> cfcs = new HashMap>(); - { - Array arr = CommonUtil.toArray(obj); - Iterator it = arr.valueIterator(); - Component cfc; - - Key dsn; - List list; - while (it.hasNext()) { - cfc = HibernateCaster.toComponent(it.next()); - dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); - list = cfcs.get(dsn); - if (list == null) cfcs.put(dsn, list = new ArrayList()); - list.add(cfc); - } - } - - Iterator>> it = cfcs.entrySet().iterator(); - while (it.hasNext()) { - Entry> e = it.next(); - Transaction trans = getSession(pc, e.getKey()).getTransaction(); - if (trans.isActive()) trans.begin(); - else trans = null; - - try { - Iterator _it = e.getValue().iterator(); - while (_it.hasNext()) { - _delete(pc, _it.next(), e.getKey()); - } - } - catch (Throwable t) { - if (trans != null) trans.rollback(); - throw CommonUtil.toPageException(t); - } - if (trans != null) trans.commit(); - } - } - else _delete(pc, HibernateCaster.toComponent(obj), null); - } - - public void _delete(PageContext pc, Component cfc, Key dsn) throws PageException { - if (dsn == null) dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); - data.checkExistent(pc, cfc); - try { - getSession(pc, dsn).delete(HibernateCaster.getEntityName(cfc), cfc); - } - catch (Throwable t) { - throw CommonUtil.toPageException(t); - } - } - - @Override - public void save(PageContext pc, Object obj, boolean forceInsert) throws PageException { - Component cfc = HibernateCaster.toComponent(obj); - String name = HibernateCaster.getEntityName(cfc); - Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); - /* - * just a test Property[] props = cfc.getProperties(true,true, false,true); Cast caster = - * CFMLEngineFactory.getInstance().getCastUtil(); ComponentScope cs = cfc.getComponentScope(); - * String type; Object val; for(Property p:props) { val=cs.get(p.getName(),null); if(val==null) - * continue; Object o = p.getMetaData(); if(!(o instanceof Struct)) continue; Struct meta = (Struct) - * o; - * - * type=caster.toString(meta.get("ormtype",null),null); if(Util.isEmpty(type)) - * type=caster.toString(meta.get("type",null)); if(!Util.isEmpty(type)) { - * val=HibernateCaster.toHibernateValue(pc,val,type); cs.setEL(p.getName(), val); } } - */ - try { - Session session = getSession(pc, dsn); - if (forceInsert) session.save(name, cfc); - else session.saveOrUpdate(name, cfc); - } - catch (Exception e) { - throw ExceptionUtil.createException(this, null, e); - } - } - - @Override - public void reload(PageContext pc, Object obj) throws PageException { - Component cfc = HibernateCaster.toComponent(obj); - Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); - data.checkExistent(pc, cfc); - getSession(pc, dsn).refresh(cfc); - } - - @Override - public Component create(PageContext pc, String entityName) throws PageException { - return data.getEngine().create(pc, this, entityName, true); - } - - @Override - public void clear(PageContext pc) throws PageException { - clear(pc, null); - } - - @Override - public void clear(PageContext pc, String datasource) throws PageException { - Key dsn = CommonUtil.toKey(CommonUtil.getDataSource(pc, datasource).getName()); - - getSession(pc, dsn).clear(); - /* - * Iterator it = _sessions.values().iterator(); while(it.hasNext()){ it.next().clear(); } - */ - } - - @Override - public void evictQueries(PageContext pc) throws PageException { - evictQueries(pc, null, null); - } - - @Override - public void evictQueries(PageContext pc, String cacheName) throws PageException { - evictQueries(pc, cacheName, null); - } - - @Override - public void evictQueries(PageContext pc, String cacheName, String datasource) throws PageException { - Key dsn = CommonUtil.toKey(CommonUtil.getDataSource(pc, datasource).getName()); - SessionFactory factory = getSession(pc, dsn).getSessionFactory(); - - if (Util.isEmpty(cacheName)) factory.getCache().evictDefaultQueryRegion(); - else factory.getCache().evictQueryRegion(cacheName); - - // String entityName = getEntityName(componentName); - // String datasource = this.config.getDataSource(entityName); - // this.config.getSessionFactory(datasource).getCache().evictEntityRegion(entityName); - - /* - * Iterator it = _sessions.values().iterator(); while(it.hasNext()){ SessionFactory f = - * it.next().getSessionFactory(); if(Util.isEmpty(cacheName))f.evictQueries(); else - * f.evictQueries(cacheName); } - */ - } - - @Override - public void evictEntity(PageContext pc, String entityName) throws PageException { - evictEntity(pc, entityName, null); - } - - @Override - public void evictEntity(PageContext pc, String entityName, String id) throws PageException { - entityName = correctCaseEntityName(entityName); - - Iterator it = sessions.values().iterator(); - SessionAndConn sac; - while (it.hasNext()) { - sac = it.next(); - SessionFactory f = sac.getSession(pc).getSessionFactory(); - if (id == null) f.getCache().evictEntityRegion(entityName); - else f.getCache().evictEntity(entityName, CommonUtil.toSerializable(id)); - } - } - - private String correctCaseEntityName(String entityName) { - Iterator it = data.getEntityNames().iterator(); - String n; - while (it.hasNext()) { - n = it.next(); - if (n.equalsIgnoreCase(entityName)) return n; - - } - return entityName; - } - - @Override - public void evictCollection(PageContext pc, String entityName, String collectionName) throws PageException { - evictCollection(pc, entityName, collectionName, null); - } - - @Override - public void evictCollection(PageContext pc, String entityName, String collectionName, String id) throws PageException { - String role = entityName + "." + collectionName; - - Iterator it = sessions.values().iterator(); - SessionAndConn sac; - while (it.hasNext()) { - sac = it.next(); - SessionFactory f = sac.getSession(pc).getSessionFactory(); - if (id == null) f.getCache().evictCollectionRegion(role); - else f.getCache().evictCollection(role, CommonUtil.toSerializable(id)); - } - } - - @Override - public Object executeQuery(PageContext pc, String dataSourceName, String hql, Array params, boolean unique, Struct queryOptions) throws PageException { - return _executeQuery(pc, dataSourceName, hql, params, unique, queryOptions); - } - - @Override - public Object executeQuery(PageContext pc, String dataSourceName, String hql, Struct params, boolean unique, Struct queryOptions) throws PageException { - return _executeQuery(pc, dataSourceName, hql, params, unique, queryOptions); - } - - private Object _executeQuery(PageContext pc, String dataSourceName, String hql, Object params, boolean unique, Struct queryOptions) throws PageException { - Key dsn; - if (dataSourceName == null) dsn = CommonUtil.toKey(CommonUtil.getDefaultDataSource(pc).getName()); - else dsn = CommonUtil.toKey(dataSourceName); - - Session s = getSession(pc, dsn); - try { - return __executeQuery(pc, s, dsn, hql, params, unique, queryOptions); - } - catch (QueryException qe) { - // argument scope is array and struct at the same time, by default it is handled - // as struct, if this - // fails try it as array - if (params instanceof Argument) { - try { - return __executeQuery(pc, s, dsn, hql, CommonUtil.toArray((Argument) params), unique, queryOptions); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } - throw qe; - } - - } - - private Object __executeQuery(PageContext pc, Session session, Key dsn, String hql, Object params, boolean unique, Struct options) throws PageException { - // Session session = getSession(pc,null); - hql = hql.trim(); - boolean isParamArray = params != null && CommonUtil.isArray(params); - if (isParamArray) hql = addIndexIfNecessary(hql); - Query query = session.createQuery(hql); - // options - if (options != null) { - // maxresults - Object obj = options.get("maxresults", null); - if (obj != null) { - int max = CommonUtil.toIntValue(obj, -1); - if (max < 0) - throw ExceptionUtil.createException(this, null, "option [maxresults] has an invalid value [" + obj + "], value should be a number bigger or equal to 0", null); - query.setMaxResults(max); - } - // offset - obj = options.get("offset", null); - if (obj != null) { - int off = CommonUtil.toIntValue(obj, -1); - if (off < 0) - throw ExceptionUtil.createException(this, null, "option [offset] has an invalid value [" + obj + "], value should be a number bigger or equal to 0", null); - query.setFirstResult(off); - } - // readonly - obj = options.get("readonly", null); - if (obj != null) { - Boolean ro = CommonUtil.toBoolean(obj, null); - if (ro == null) throw ExceptionUtil.createException(this, null, "option [readonly] has an invalid value [" + obj + "], value should be a boolean value", null); - query.setReadOnly(ro.booleanValue()); - } - // timeout - obj = options.get("timeout", null); - if (obj != null) { - int to; - if (obj instanceof TimeSpan) to = (int) ((TimeSpan) obj).getSeconds(); - else to = CommonUtil.toIntValue(obj, -1); - - if (to < 0) - throw ExceptionUtil.createException(this, null, "option [timeout] has an invalid value [" + obj + "], value should be a number bigger or equal to 0", null); - query.setTimeout(to); - } - } - - // params - if (params != null) { - HQLQueryPlan plan = ((SessionFactoryImpl) session.getSessionFactory()).getQueryPlanCache().getHQLQueryPlan(hql, false, java.util.Collections.EMPTY_MAP); - - ParameterMetadataImpl meta = plan.getParameterMetadata(); - Type type; - Object obj; - - // struct - if (CommonUtil.isStruct(params)) { - Struct sct = CommonUtil.toStruct(params); - String name; - // fix case-senstive - Struct names = CommonUtil.createStruct(); - if (meta != null) { - Iterator it = meta.getNamedParameterNames().iterator(); - while (it.hasNext()) { - name = it.next(); - names.setEL(name, name); - } - } - - RefBoolean isArray = CommonUtil.createRefBoolean(); - Iterator> it = sct.entryIterator(); - Entry e; - while (it.hasNext()) { - e = it.next(); - obj = sct.get(e.getKey(), null); - if (meta != null) { - name = (String) names.get(e.getKey(), null); - if (name == null) continue; // param not needed will be ignored - type = meta.getNamedParameterExpectedType(name); - - obj = HibernateCaster.toSQL(type, obj, isArray); - if (isArray.toBooleanValue()) { - if (obj instanceof Object[]) query.setParameterList(name, (Object[]) obj, type); - else if (obj instanceof List) query.setParameterList(name, (List) obj, type); - else query.setParameterList(name, CFMLEngineFactory.getInstance().getCastUtil().toList(obj), type); - } - else query.setParameter(name, obj, type); - - } - else query.setParameter(e.getKey().getString(), obj); - } - } - - // array - else if (isParamArray) { - Array arr = CommonUtil.toArray(params); - - if (meta.getOrdinalParameterCount() > arr.size()) throw ExceptionUtil.createException(this, null, - "parameter array is to small [" + arr.size() + "], need [" + meta.getOrdinalParameterCount() + "] elements", null); - - Iterator it = arr.valueIterator(); - int idx = 1; - SQLItem item; - RefBoolean isArray = null; - - while (it.hasNext()) { - type = null; - obj = it.next(); - if (obj instanceof SQLItem) { - item = (SQLItem) obj; - obj = item.getValue(); - } - if (meta != null) { - type = meta.getOrdinalParameterExpectedType(idx); - } - - if (type != null) query.setParameter(idx, HibernateCaster.toSQL(type, obj, isArray), type); - else query.setParameter(idx, obj); - idx++; - } - - } - } - - // select - String lcHQL = hql.toLowerCase(); - if (lcHQL.startsWith("select") || lcHQL.startsWith("from")) { - if (unique) { - return uniqueResult(query); - } - - return query.list(); - } - // update - return Double.valueOf(query.executeUpdate()); - } - - private Object uniqueResult(Query query) throws PageException { - try { - return query.uniqueResult(); - } - catch (NonUniqueResultException e) { - List list = query.list(); - if (list.size() > 0) return list.iterator().next(); - throw CommonUtil.toPageException(e); - } - catch (Throwable t) { - throw CommonUtil.toPageException(t); - } - } - - @Override - public lucee.runtime.type.Query toQuery(PageContext pc, Object obj, String name) throws PageException { - return HibernateCaster.toQuery(pc, this, obj, name); - } - - @Override - public void close(PageContext pc) throws PageException { - close(pc, null); - } - - @Override - public void close(PageContext pc, String datasource) throws PageException { - DataSource ds = CommonUtil.getDataSource(pc, datasource); - Key dsn = CommonUtil.toKey(ds.getName()); - - // close Session - SessionAndConn sac = sessions.remove(dsn); - if (sac != null && sac.isOpen()) sac.close(pc); - - } - - @Override - public void closeAll(PageContext pc) throws PageException { - Iterator it = sessions.values().iterator(); - SessionAndConn sac; - while (it.hasNext()) { - sac = it.next(); - if (sac.isOpen()) sac.close(pc); - } - } - - @Override - public Component merge(PageContext pc, Object obj) throws PageException { - Component cfc = HibernateCaster.toComponent(obj); - CFCInfo info = data.checkExistent(pc, cfc); - - String name = HibernateCaster.getEntityName(cfc); - - return CommonUtil.toComponent(getSession(pc, CommonUtil.toKey(info.getDataSource().getName())).merge(name, cfc)); - } - - @Override - public Component load(PageContext pc, String name, Struct filter) throws PageException { - return (Component) load(pc, name, filter, null, null, true); - } - - @Override - public Array loadAsArray(PageContext pc, String name, Struct filter) throws PageException { - return loadAsArray(pc, name, filter, null, null); - } - - @Override - public Array loadAsArray(PageContext pc, String name, String id, String order) throws PageException { - return loadAsArray(pc, name, id);// order is ignored in this case ACF compatibility - } - - @Override - public Array loadAsArray(PageContext pc, String name, String id) throws PageException { - Array arr = CommonUtil.createArray(); - Component c = load(pc, name, id); - if (c != null) arr.append(c); - return arr; - } - - @Override - public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options) throws PageException { - return loadAsArray(pc, name, filter, options, null); - } - - @Override - public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options, String order) throws PageException { - return CommonUtil.toArray(load(pc, name, filter, options, order, false)); - } - - @Override - public Component load(PageContext pc, String cfcName, String id) throws PageException { - return load(pc, cfcName, (Object) id); - } - - public Component load(PageContext pc, String cfcName, Object id) throws PageException { - // Component cfc = create(pc,cfcName); - Component cfc = data.getEngine().create(pc, this, cfcName, false); - Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); - Session sess = getSession(pc, dsn); - String name = HibernateCaster.getEntityName(cfc); - Object obj = null; - try { - ClassMetadata metaData = sess.getSessionFactory().getClassMetadata(name); - if (metaData == null) throw ExceptionUtil.createException(this, null, "could not load meta information for entity [" + name + "]", null); - Serializable oId = CommonUtil.toSerializable(CommonUtil.castTo(pc, metaData.getIdentifierType().getReturnedClass(), id)); - obj = sess.get(name, oId); - } - catch (Throwable t) { - throw CommonUtil.toPageException(t); - } - - return (Component) obj; - } - - @Override - public Component loadByExample(PageContext pc, Object obj) throws PageException { - Object res = loadByExample(pc, obj, true); - if (res == null) return null; - return CommonUtil.toComponent(res); - } - - @Override - public Array loadByExampleAsArray(PageContext pc, Object obj) throws PageException { - return CommonUtil.toArray(loadByExample(pc, obj, false)); - } - - private Object loadByExample(PageContext pc, Object obj, boolean unique) throws PageException { - Component cfc = HibernateCaster.toComponent(obj); - Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); - ComponentScope scope = cfc.getComponentScope(); - String name = HibernateCaster.getEntityName(cfc); - Session sess = getSession(pc, dsn); - Object rtn = null; - - try { - // trans.begin(); - - ClassMetadata metaData = sess.getSessionFactory().getClassMetadata(name); - String idName = metaData.getIdentifierPropertyName(); - Type idType = metaData.getIdentifierType(); - - Criteria criteria = sess.createCriteria(name); - if (!Util.isEmpty(idName)) { - Object idValue = scope.get(CommonUtil.createKey(idName), null); - if (idValue != null) { - criteria.add(Restrictions.eq(idName, HibernateCaster.toSQL(idType, idValue, null))); - } - } - criteria.add(Example.create(cfc)); - - // execute - - if (!unique) { - rtn = criteria.list(); - } - else { - // Map map=(Map) criteria.uniqueResult(); - rtn = criteria.uniqueResult(); - } - } - catch (Throwable t) { - // trans.rollback(); - throw CommonUtil.toPageException(t); - } - // trans.commit(); - - return rtn; - } - - private Object load(PageContext pc, String cfcName, Struct filter, Struct options, String order, boolean unique) throws PageException { - Component cfc = data.getEngine().create(pc, this, cfcName, false); - Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); - Session sess = getSession(pc, dsn); - - String name = HibernateCaster.getEntityName(cfc); - ClassMetadata metaData = null; - - Object rtn; - try { - Criteria criteria = sess.createCriteria(name); - - // filter - if (filter != null && !filter.isEmpty()) { - metaData = sess.getSessionFactory().getClassMetadata(name); - Object value; - Entry entry; - Iterator> it = filter.entryIterator(); - String colName; - while (it.hasNext()) { - entry = it.next(); - colName = HibernateUtil.validateColumnName(metaData, CommonUtil.toString(entry.getKey())); - Type type = HibernateUtil.getPropertyType(metaData, colName, null); - value = entry.getValue(); - if (!(value instanceof Component)) value = HibernateCaster.toSQL(type, value, null); - - if (value != null) criteria.add(Restrictions.eq(colName, value)); - else criteria.add(Restrictions.isNull(colName)); - } - } - - // options - boolean ignoreCase = false; - if (options != null && !options.isEmpty()) { - // ignorecase - Boolean ignorecase = CommonUtil.toBoolean(options.get("ignorecase", null), null); - if (ignorecase != null) ignoreCase = ignorecase.booleanValue(); - - // offset - int offset = CommonUtil.toIntValue(options.get("offset", null), 0); - if (offset > 0) criteria.setFirstResult(offset); - - // maxResults - int max = CommonUtil.toIntValue(options.get("maxresults", null), -1); - if (max > -1) criteria.setMaxResults(max); - - // cacheable - Boolean cacheable = CommonUtil.toBoolean(options.get("cacheable", null), null); - if (cacheable != null) criteria.setCacheable(cacheable.booleanValue()); - - // MUST cacheName ? - - // maxResults - int timeout = CommonUtil.toIntValue(options.get("timeout", null), -1); - if (timeout > -1) criteria.setTimeout(timeout); - } - - // order - if (!Util.isEmpty(order)) { - if (metaData == null) metaData = sess.getSessionFactory().getClassMetadata(name); - - String[] arr = CommonUtil.toStringArray(order, ","); - CommonUtil.trimItems(arr); - String[] parts; - String col; - boolean isDesc; - Order _order; - // ColumnInfo ci; - for (int i = 0; i < arr.length; i++) { - parts = CommonUtil.toStringArray(arr[i], " \t\n\b\r"); - CommonUtil.trimItems(parts); - col = parts[0]; - - col = HibernateUtil.validateColumnName(metaData, col); - isDesc = false; - if (parts.length > 1) { - if (parts[1].equalsIgnoreCase("desc")) isDesc = true; - else if (!parts[1].equalsIgnoreCase("asc")) { - throw ExceptionUtil.createException((ORMSession) null, null, "invalid order direction defintion [" + parts[1] + "]", "valid values are [asc, desc]"); - } - - } - _order = isDesc ? Order.desc(col) : Order.asc(col); - if (ignoreCase) _order.ignoreCase(); - - criteria.addOrder(_order); - - } - } - - // execute - if (!unique) { - rtn = HibernateCaster.toCFML(criteria.list()); - } - else { - rtn = HibernateCaster.toCFML(criteria.uniqueResult()); - } - - } - catch (Throwable t) { - throw CommonUtil.toPageException(t); - } - return rtn; - } - - @Override - public Session getRawSession(String dsn) throws PageException { - return getSession(null, CommonUtil.toKey(dsn)); - } - - @Override - public SessionFactory getRawSessionFactory(String dsn) throws PageException { - return getSession(null, CommonUtil.toKey(dsn)).getSessionFactory(); - } - - @Override - public boolean isValid(DataSource ds) { - SessionAndConn sac = sessions.get(CommonUtil.toKey(ds.getName())); - return sac != null && sac.isOpen(); - } - - @Override - public boolean isValid() { - if (sessions.size() == 0) return false; - Iterator it = sessions.values().iterator(); - - while (it.hasNext()) { - if (!it.next().isOpen()) return false; - } - return true; - } - - @Override - public ORMTransaction getTransaction(String dsn, boolean autoManage) throws PageException { - return new HibernateORMTransaction(getSession(null, CommonUtil.toKey(dsn)), autoManage); - } - - @Override - public String[] getEntityNames() { - List names = data.getEntityNames(); - return names.toArray(new String[names.size()]); - } - - @Override - public DataSource[] getDataSources() { - return data.getDataSources(); - } - - private static String addIndexIfNecessary(String sql) { - // if(namedParams.size()==0) return new Pair>(sql,params); - StringBuilder sb = new StringBuilder(); - int sqlLen = sql.length(); - char c, quoteType = 0; - boolean inQuotes = false; - int qm = 0, _qm = 0; - int index = 1; - for (int i = 0; i < sqlLen; i++) { - c = sql.charAt(i); - - if (c == '"' || c == '\'') { - if (inQuotes) { - if (c == quoteType) { - inQuotes = false; - } - } - else { - quoteType = c; - inQuotes = true; - } - } - - if (!inQuotes && c == '?') { - // is the next a number? - if (sqlLen > i + 1 && isInteger(sql.charAt(i + 1))) { - return sql; - } - - sb.append(c).append(index++); - } - else { - sb.append(c); - } - } - - return sb.toString(); - } - - private static final boolean isInteger(char c) { - return c >= '0' && c <= '9'; - } + public class SessionAndConn { + + private Session s; + private DatasourceConnection dc; + private final DataSource d; + private SessionFactory factory; + + /* + * public SessionAndConn(Session session, DatasourceConnection dc) { this.session = session; this.dc = dc; + * this.d = dc.getDatasource(); } + * + * public SessionAndConn(Session session, DataSource d) { this.session = session; this.d = d; } + */ + + public SessionAndConn(PageContext pc, SessionFactory factory, DataSource ds) throws PageException { + this.d = ds; + this.factory = factory; + getSession(pc); + } + + /** + * Retrieve the current session if found, or open a new session if necessary. + * + * @param pc + * PageContext object. (Unused.) + * + * @return The open and bound hibernate Session. + * + * @throws PageException + */ + public Session getSession(PageContext pc) throws PageException { + if (s == null || !s.isOpen()) + s = factory.openSession(); + return s; + } + + public Connection getConnection(PageContext pc) throws PageException { + try { + if (dc == null || dc.isClosed()) { + connect(pc); + } + } catch (SQLException e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } + return dc.getConnection(); + } + + public void connect(PageContext pc) throws PageException { + if (dc != null) + CommonUtil.releaseDatasourceConnection(pc, dc, true); + dc = CommonUtil.getDatasourceConnection(pc, d, null, null, true); + } + + public void close(PageContext pc) throws PageException { + if (s != null && s.isOpen()) { + s.close(); + s = null; + } + + if (dc != null) { + CommonUtil.releaseDatasourceConnection(pc, dc, true); + dc = null; + } + } + + public boolean isOpen() { + return s != null && s.isOpen(); + } + + public DataSource getDataSource() { + return d; + } + } + + private SessionFactoryData data; + private Map sessions = new HashMap(); + + public HibernateORMSession(PageContext pc, SessionFactoryData data) throws PageException { + this.data = data; + // this.dc=dc; + DataSource[] sources = data.getDataSources(); + + for (int i = 0; i < sources.length; i++) { + createSession(pc, data.getFactory(CommonUtil.toKey(sources[i].getName())), sources[i]); + } + } + + /* + * private Session session(){ return _session; } + */ + + private Session getSession(PageContext pc, Key datasSourceName) throws PageException { + return getSessionAndConn(pc, datasSourceName).getSession(pc); + } + + private SessionAndConn getSessionAndConn(PageContext pc, Key datasSourceName) throws PageException { + SessionAndConn sac = sessions.get(datasSourceName); + if (sac == null) { + CFMLEngineFactory.getInstance().getExceptionUtil().similarKeyMessage( + sessions.keySet().toArray(new Key[sessions.size()]), datasSourceName.getString(), "datasource", + "datasources", null, true); + throw ExceptionUtil.createException(data, null, + "there is no Session for the datasource [" + datasSourceName + "]", null); + } + Session s = sac.getSession(pc); + if (!s.isOpen() || !s.isConnected() || isClosed(s)) { + if (pc == null) + pc = CFMLEngineFactory.getInstance().getThreadPageContext(); + + sac.connect(pc); + s.reconnect(sac.getConnection(pc)); + + } + return sac; + } + + private boolean isClosed(Session s) throws PageException { + return !s.isConnected(); + } + + /** + * Get the configured SessionFactoryData for this HibernateORMSession object + * + * @return SessionFactoryData used to create this session + */ + public SessionFactoryData getSessionFactoryData() { + return data; + } + + SessionFactory getSessionFactory(Key datasSourceName) throws PageException { + Session s = getSession(null, datasSourceName); + return s.getSessionFactory(); + } + + void resetSession(PageContext pc, SessionFactory factory, Key dataSourceName, SessionFactoryData data) + throws PageException { + + SessionAndConn sac = sessions.get(dataSourceName); + if (sac != null) { + sac.close(pc); + createSession(pc, factory, sac.getDataSource()); + return; + } + DataSource ds = data.getDataSource(dataSourceName); + createSession(pc, factory, ds); + } + + /** + * Create a new {@link org.hibernate.Session} for the given Datasource + *

+ * Will set the Hibernate FlushMode on initialization. + * + * @param pc + * Lucee PageContext object. + * @param factory + * The SessionFactory to open the session with. + * @param ds + * A Lucee Datasource object + * + * @return The Hibernate Session. + * + * @throws PageException + */ + Session createSession(PageContext pc, SessionFactory factory, DataSource ds) throws PageException { + SessionAndConn sac = new SessionAndConn(pc, factory, ds); + + sessions.put(CommonUtil.toKey(ds.getName()), sac); + sac.getSession(pc).setHibernateFlushMode(FlushMode.MANUAL); + return sac.getSession(pc); + } + + @Override + public ORMEngine getEngine() { + return data.getEngine(); + } + + @Override + public void flushAll(PageContext pc) { + SessionAndConn sac; + Session s; + Iterator it = sessions.values().iterator(); + while (it.hasNext()) { + sac = it.next(); + if (sac.isOpen()) { + try { + s = sac.getSession(pc); + s.flush(); + } catch (Exception e) { + } // we do this because of a Bug in Lucee that keeps session object in case of an exception for future + // request, this session then fail to flush, because the underlaying datasource is not defined in + // the current application.cfc. + } + } + } + + /** + * Flush the session for the default datasource. + * + * @param pc + * Lucee PageContext object. + */ + @Override + public void flush(PageContext pc) throws PageException { + flush(pc, null); + } + + /** + * Flush the session for the given datasource + * + * @param pc + * Lucee PageContext object. + * @param datasource + * Datasource name + */ + @Override + public void flush(PageContext pc, String datasource) throws PageException { + _flush(pc, CommonUtil.getDataSource(pc, datasource)); + } + + private void _flush(PageContext pc, DataSource datasource) throws PageException { + Key dsn = CommonUtil.toKey(datasource.getName()); + + try { + getSession(pc, dsn).flush(); + } catch (Throwable t) { + throw CommonUtil.toPageException(t); + } + + } + + /** + * Delete an entity OR array of entities from the Hibernate session + * + * @param pc + * Lucee PageContext + * @param obj + * Hibernate Entity object OR an Array of objects + */ + @Override + public void delete(PageContext pc, Object obj) throws PageException { + if (CommonUtil.isArray(obj)) { + + // convert to a usable structure + Map> cfcs = new HashMap>(); + { + Array arr = CommonUtil.toArray(obj); + Iterator it = arr.valueIterator(); + Component cfc; + + Key dsn; + List list; + while (it.hasNext()) { + cfc = HibernateCaster.toComponent(it.next()); + dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); + list = cfcs.get(dsn); + if (list == null) + cfcs.put(dsn, list = new ArrayList()); + list.add(cfc); + } + } + + Iterator>> it = cfcs.entrySet().iterator(); + while (it.hasNext()) { + Entry> e = it.next(); + Transaction trans = getSession(pc, e.getKey()).getTransaction(); + if (trans.isActive()) + trans.begin(); + else + trans = null; + + try { + Iterator _it = e.getValue().iterator(); + while (_it.hasNext()) { + _delete(pc, _it.next(), e.getKey()); + } + } catch (Throwable t) { + if (trans != null) + trans.rollback(); + throw CommonUtil.toPageException(t); + } + if (trans != null) + trans.commit(); + } + } else + _delete(pc, HibernateCaster.toComponent(obj), null); + } + + private void _delete(PageContext pc, Component cfc, Key dsn) throws PageException { + if (dsn == null) + dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); + data.checkExistent(pc, cfc); + try { + getSession(pc, dsn).delete(HibernateCaster.getEntityName(cfc), cfc); + } catch (Throwable t) { + throw CommonUtil.toPageException(t); + } + } + + /** + * Persist this entity to the datasource. + * + * @param pc + * Lucee PageContext object + * @param obj + * Java entity object which maps to a persistent Component + * @param forceInsert + * force an INSERT. If false, will try a {@link org.hibernate.Session#saveOrUpdate(String, Object)} + */ + @Override + public void save(PageContext pc, Object obj, boolean forceInsert) throws PageException { + Component cfc = HibernateCaster.toComponent(obj); + String name = HibernateCaster.getEntityName(cfc); + Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); + /* + * just a test Property[] props = cfc.getProperties(true,true, false,true); Cast caster = + * CFMLEngineFactory.getInstance().getCastUtil(); ComponentScope cs = cfc.getComponentScope(); String type; + * Object val; for(Property p:props) { val=cs.get(p.getName(),null); if(val==null) continue; Object o = + * p.getMetaData(); if(!(o instanceof Struct)) continue; Struct meta = (Struct) o; + * + * type=caster.toString(meta.get("ormtype",null),null); if(Util.isEmpty(type)) + * type=caster.toString(meta.get("type",null)); if(!Util.isEmpty(type)) { + * val=HibernateCaster.toHibernateValue(pc,val,type); cs.setEL(p.getName(), val); } } + */ + try { + Session session = getSession(pc, dsn); + if (forceInsert) + session.save(name, cfc); + else + session.saveOrUpdate(name, cfc); + } catch (Exception e) { + throw ExceptionUtil.createException(this, null, e); + } + } + + /** + * Refresh (not reload) this entity in the (native) Hibernate session object. + * + * {@link org.hibernate.Session#refresh(Object) } + */ + @Override + public void reload(PageContext pc, Object obj) throws PageException { + Component cfc = HibernateCaster.toComponent(obj); + Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); + data.checkExistent(pc, cfc); + getSession(pc, dsn).refresh(cfc); + } + + @Override + public Component create(PageContext pc, String entityName) throws PageException { + return data.getEngine().create(pc, this, entityName, true); + } + + /** + * Clear the Hibernate session for the default datasource. + * + * @param pc + * Lucee PageContext object + */ + @Override + public void clear(PageContext pc) throws PageException { + clear(pc, null); + } + + /** + * Clear the Hibernate session for this datasource. + * + * @param pc + * Lucee PageContext object + * @param datasource + * Lucee Datasource by which to find the session to clear. + * + * @see org.hibernate.Session#clear() + */ + @Override + public void clear(PageContext pc, String datasource) throws PageException { + Key dsn = CommonUtil.toKey(CommonUtil.getDataSource(pc, datasource).getName()); + + getSession(pc, dsn).clear(); + /* + * Iterator it = _sessions.values().iterator(); while(it.hasNext()){ it.next().clear(); } + */ + } + + @Override + public void evictQueries(PageContext pc) throws PageException { + evictQueries(pc, null, null); + } + + @Override + public void evictQueries(PageContext pc, String cacheName) throws PageException { + evictQueries(pc, cacheName, null); + } + + @Override + public void evictQueries(PageContext pc, String cacheName, String datasource) throws PageException { + Key dsn = CommonUtil.toKey(CommonUtil.getDataSource(pc, datasource).getName()); + SessionFactory factory = getSession(pc, dsn).getSessionFactory(); + + if (Util.isEmpty(cacheName)) + factory.getCache().evictDefaultQueryRegion(); + else + factory.getCache().evictQueryRegion(cacheName); + + // String entityName = getEntityName(componentName); + // String datasource = this.config.getDataSource(entityName); + // this.config.getSessionFactory(datasource).getCache().evictEntityRegion(entityName); + + /* + * Iterator it = _sessions.values().iterator(); while(it.hasNext()){ SessionFactory f = + * it.next().getSessionFactory(); if(Util.isEmpty(cacheName))f.evictQueries(); else f.evictQueries(cacheName); } + */ + } + + @Override + public void evictEntity(PageContext pc, String entityName) throws PageException { + evictEntity(pc, entityName, null); + } + + @Override + public void evictEntity(PageContext pc, String entityName, String id) throws PageException { + entityName = correctCaseEntityName(entityName); + + Iterator it = sessions.values().iterator(); + SessionAndConn sac; + while (it.hasNext()) { + sac = it.next(); + SessionFactory f = sac.getSession(pc).getSessionFactory(); + if (id == null) + f.getCache().evictEntityRegion(entityName); + else + f.getCache().evictEntity(entityName, CommonUtil.toSerializable(id)); + } + } + + private String correctCaseEntityName(String entityName) { + Iterator it = data.getEntityNames().iterator(); + String n; + while (it.hasNext()) { + n = it.next(); + if (n.equalsIgnoreCase(entityName)) + return n; + + } + return entityName; + } + + @Override + public void evictCollection(PageContext pc, String entityName, String collectionName) throws PageException { + evictCollection(pc, entityName, collectionName, null); + } + + @Override + public void evictCollection(PageContext pc, String entityName, String collectionName, String id) + throws PageException { + String role = entityName + "." + collectionName; + + Iterator it = sessions.values().iterator(); + SessionAndConn sac; + while (it.hasNext()) { + sac = it.next(); + SessionFactory f = sac.getSession(pc).getSessionFactory(); + if (id == null) + f.getCache().evictCollectionRegion(role); + else + f.getCache().evictCollection(role, CommonUtil.toSerializable(id)); + } + } + + @Override + public Object executeQuery(PageContext pc, String dataSourceName, String hql, Array params, boolean unique, + Struct queryOptions) throws PageException { + return _executeQuery(pc, dataSourceName, hql, params, unique, queryOptions); + } + + @Override + public Object executeQuery(PageContext pc, String dataSourceName, String hql, Struct params, boolean unique, + Struct queryOptions) throws PageException { + return _executeQuery(pc, dataSourceName, hql, params, unique, queryOptions); + } + + private Object _executeQuery(PageContext pc, String dataSourceName, String hql, Object params, boolean unique, + Struct queryOptions) throws PageException { + Key dsn; + if (dataSourceName == null) + dsn = CommonUtil.toKey(CommonUtil.getDefaultDataSource(pc).getName()); + else + dsn = CommonUtil.toKey(dataSourceName); + + Session s = getSession(pc, dsn); + try { + return __executeQuery(pc, s, dsn, hql, params, unique, queryOptions); + } catch (QueryException qe) { + // argument scope is array and struct at the same time, by default it is handled + // as struct, if this + // fails try it as array + if (params instanceof Argument) { + try { + return __executeQuery(pc, s, dsn, hql, CommonUtil.toArray((Argument) params), unique, queryOptions); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + throw qe; + } + + } + + private Object __executeQuery(PageContext pc, Session session, Key dsn, String hql, Object params, boolean unique, + Struct options) throws PageException { + // Session session = getSession(pc,null); + hql = hql.trim(); + boolean isParamArray = params != null && CommonUtil.isArray(params); + if (isParamArray) + hql = addIndexIfNecessary(hql); + Query query = session.createQuery(hql); + // options + if (options != null) { + // maxresults + Object obj = options.get("maxresults", null); + if (obj != null) { + int max = CommonUtil.toIntValue(obj, -1); + if (max < 0) + throw ExceptionUtil.createException(this, null, "option [maxresults] has an invalid value [" + obj + + "], value should be a number bigger or equal to 0", null); + query.setMaxResults(max); + } + // offset + obj = options.get("offset", null); + if (obj != null) { + int off = CommonUtil.toIntValue(obj, -1); + if (off < 0) + throw ExceptionUtil.createException(this, null, "option [offset] has an invalid value [" + obj + + "], value should be a number bigger or equal to 0", null); + query.setFirstResult(off); + } + // readonly + obj = options.get("readonly", null); + if (obj != null) { + Boolean ro = CommonUtil.toBoolean(obj, null); + if (ro == null) + throw ExceptionUtil.createException(this, null, + "option [readonly] has an invalid value [" + obj + "], value should be a boolean value", + null); + query.setReadOnly(ro.booleanValue()); + } + // timeout + obj = options.get("timeout", null); + if (obj != null) { + int to; + if (obj instanceof TimeSpan) + to = (int) ((TimeSpan) obj).getSeconds(); + else + to = CommonUtil.toIntValue(obj, -1); + + if (to < 0) + throw ExceptionUtil.createException(this, null, "option [timeout] has an invalid value [" + obj + + "], value should be a number bigger or equal to 0", null); + query.setTimeout(to); + } + } + + // params + if (params != null) { + HQLQueryPlan plan = ((SessionFactoryImpl) session.getSessionFactory()).getQueryPlanCache() + .getHQLQueryPlan(hql, false, java.util.Collections.EMPTY_MAP); + + ParameterMetadataImpl meta = plan.getParameterMetadata(); + Type type; + Object obj; + + // struct + if (CommonUtil.isStruct(params)) { + Struct sct = CommonUtil.toStruct(params); + String name; + // fix case-senstive + Struct names = CommonUtil.createStruct(); + if (meta != null) { + Iterator it = meta.getNamedParameterNames().iterator(); + while (it.hasNext()) { + name = it.next(); + names.setEL(name, name); + } + } + + RefBoolean isArray = CommonUtil.createRefBoolean(); + Iterator> it = sct.entryIterator(); + Entry e; + while (it.hasNext()) { + e = it.next(); + obj = sct.get(e.getKey(), null); + if (meta != null) { + name = (String) names.get(e.getKey(), null); + if (name == null) + continue; // param not needed will be ignored + type = meta.getNamedParameterExpectedType(name); + + obj = HibernateCaster.toSQL(type, obj, isArray); + if (isArray.toBooleanValue()) { + if (obj instanceof Object[]) + query.setParameterList(name, (Object[]) obj, type); + else if (obj instanceof List) + query.setParameterList(name, (List) obj, type); + else + query.setParameterList(name, CFMLEngineFactory.getInstance().getCastUtil().toList(obj), + type); + } else + query.setParameter(name, obj, type); + + } else + query.setParameter(e.getKey().getString(), obj); + } + } + + // array + else if (isParamArray) { + Array arr = CommonUtil.toArray(params); + + if (meta.getOrdinalParameterCount() > arr.size()) + throw ExceptionUtil.createException(this, null, "parameter array is to small [" + arr.size() + + "], need [" + meta.getOrdinalParameterCount() + "] elements", null); + + Iterator it = arr.valueIterator(); + int idx = 1; + SQLItem item; + RefBoolean isArray = null; + + while (it.hasNext()) { + type = null; + obj = it.next(); + if (obj instanceof SQLItem) { + item = (SQLItem) obj; + obj = item.getValue(); + } + if (meta != null) { + type = meta.getOrdinalParameterExpectedType(idx); + } + + if (type != null) + query.setParameter(idx, HibernateCaster.toSQL(type, obj, isArray), type); + else + query.setParameter(idx, obj); + idx++; + } + + } + } + + // select + String lcHQL = hql.toLowerCase(); + if (lcHQL.startsWith("select") || lcHQL.startsWith("from")) { + if (unique) { + return uniqueResult(query); + } + + return query.list(); + } + // update + return Double.valueOf(query.executeUpdate()); + } + + private Object uniqueResult(Query query) throws PageException { + try { + return query.uniqueResult(); + } catch (NonUniqueResultException e) { + List list = query.list(); + if (list.size() > 0) + return list.iterator().next(); + throw CommonUtil.toPageException(e); + } catch (Throwable t) { + throw CommonUtil.toPageException(t); + } + } + + @Override + public lucee.runtime.type.Query toQuery(PageContext pc, Object obj, String name) throws PageException { + return HibernateCaster.toQuery(pc, this, obj, name); + } + + @Override + public void close(PageContext pc) throws PageException { + close(pc, null); + } + + @Override + public void close(PageContext pc, String datasource) throws PageException { + DataSource ds = CommonUtil.getDataSource(pc, datasource); + Key dsn = CommonUtil.toKey(ds.getName()); + + // close Session + SessionAndConn sac = sessions.remove(dsn); + if (sac != null && sac.isOpen()) + sac.close(pc); + + } + + @Override + public void closeAll(PageContext pc) throws PageException { + Iterator it = sessions.values().iterator(); + SessionAndConn sac; + while (it.hasNext()) { + sac = it.next(); + if (sac.isOpen()) + sac.close(pc); + } + } + + @Override + public Component merge(PageContext pc, Object obj) throws PageException { + Component cfc = HibernateCaster.toComponent(obj); + CFCInfo info = data.checkExistent(pc, cfc); + + String name = HibernateCaster.getEntityName(cfc); + + return CommonUtil + .toComponent( + getSession(pc, CommonUtil.toKey(info.getDataSource().getName())) + .merge(name, cfc) + ); + } + + @Override + public Component load(PageContext pc, String name, Struct filter) throws PageException { + return (Component) load(pc, name, filter, null, null, true); + } + + @Override + public Array loadAsArray(PageContext pc, String name, Struct filter) throws PageException { + return loadAsArray(pc, name, filter, null, null); + } + + @Override + public Array loadAsArray(PageContext pc, String name, String id, String order) throws PageException { + return loadAsArray(pc, name, id);// order is ignored in this case ACF compatibility + } + + @Override + public Array loadAsArray(PageContext pc, String name, String id) throws PageException { + Array arr = CommonUtil.createArray(); + Component c = load(pc, name, id); + if (c != null) + arr.append(c); + return arr; + } + + @Override + public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options) throws PageException { + return loadAsArray(pc, name, filter, options, null); + } + + @Override + public Array loadAsArray(PageContext pc, String name, Struct filter, Struct options, String order) + throws PageException { + return CommonUtil.toArray(load(pc, name, filter, options, order, false)); + } + + @Override + public Component load(PageContext pc, String cfcName, String id) throws PageException { + return load(pc, cfcName, (Object) id); + } + + public Component load(PageContext pc, String cfcName, Object id) throws PageException { + // Component cfc = create(pc,cfcName); + Component cfc = data.getEngine().create(pc, this, cfcName, false); + Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); + Session sess = getSession(pc, dsn); + String name = HibernateCaster.getEntityName(cfc); + Object obj = null; + try { + ClassMetadata metaData = sess.getSessionFactory().getClassMetadata(name); + if (metaData == null) + throw ExceptionUtil.createException(this, null, + "could not load meta information for entity [" + name + "]", null); + Serializable oId = CommonUtil + .toSerializable(CommonUtil.castTo(pc, metaData.getIdentifierType().getReturnedClass(), id)); + obj = sess.get(name, oId); + } catch (Throwable t) { + throw CommonUtil.toPageException(t); + } + + return (Component) obj; + } + + @Override + public Component loadByExample(PageContext pc, Object obj) throws PageException { + Object res = loadByExample(pc, obj, true); + if (res == null) + return null; + return CommonUtil.toComponent(res); + } + + @Override + public Array loadByExampleAsArray(PageContext pc, Object obj) throws PageException { + return CommonUtil.toArray(loadByExample(pc, obj, false)); + } + + private Object loadByExample(PageContext pc, Object obj, boolean unique) throws PageException { + Component cfc = HibernateCaster.toComponent(obj); + Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); + ComponentScope scope = cfc.getComponentScope(); + String name = HibernateCaster.getEntityName(cfc); + Session sess = getSession(pc, dsn); + Object rtn = null; + + try { + // trans.begin(); + + ClassMetadata metaData = sess.getSessionFactory().getClassMetadata(name); + String idName = metaData.getIdentifierPropertyName(); + Type idType = metaData.getIdentifierType(); + + Criteria criteria = sess.createCriteria(name); + if (!Util.isEmpty(idName)) { + Object idValue = scope.get(CommonUtil.createKey(idName), null); + if (idValue != null) { + criteria.add(Restrictions.eq(idName, HibernateCaster.toSQL(idType, idValue, null))); + } + } + criteria.add(Example.create(cfc)); + + // execute + + if (!unique) { + rtn = criteria.list(); + } else { + // Map map=(Map) criteria.uniqueResult(); + rtn = criteria.uniqueResult(); + } + } catch (Throwable t) { + // trans.rollback(); + throw CommonUtil.toPageException(t); + } + // trans.commit(); + + return rtn; + } + + private Object load(PageContext pc, String cfcName, Struct filter, Struct options, String order, boolean unique) + throws PageException { + Component cfc = data.getEngine().create(pc, this, cfcName, false); + Key dsn = CommonUtil.toKey(CommonUtil.getDataSourceName(pc, cfc)); + Session sess = getSession(pc, dsn); + + String name = HibernateCaster.getEntityName(cfc); + ClassMetadata metaData = null; + + Object rtn; + try { + Criteria criteria = sess.createCriteria(name); + + // filter + if (filter != null && !filter.isEmpty()) { + metaData = sess.getSessionFactory().getClassMetadata(name); + Object value; + Entry entry; + Iterator> it = filter.entryIterator(); + String colName; + while (it.hasNext()) { + entry = it.next(); + colName = HibernateUtil.validateColumnName(metaData, CommonUtil.toString(entry.getKey())); + Type type = HibernateUtil.getPropertyType(metaData, colName, null); + value = entry.getValue(); + if (!(value instanceof Component)) + value = HibernateCaster.toSQL(type, value, null); + + if (value != null) + criteria.add(Restrictions.eq(colName, value)); + else + criteria.add(Restrictions.isNull(colName)); + } + } + + // options + boolean ignoreCase = false; + if (options != null && !options.isEmpty()) { + // ignorecase + Boolean ignorecase = CommonUtil.toBoolean(options.get("ignorecase", null), null); + if (ignorecase != null) + ignoreCase = ignorecase.booleanValue(); + + // offset + int offset = CommonUtil.toIntValue(options.get("offset", null), 0); + if (offset > 0) + criteria.setFirstResult(offset); + + // maxResults + int max = CommonUtil.toIntValue(options.get("maxresults", null), -1); + if (max > -1) + criteria.setMaxResults(max); + + // cacheable + Boolean cacheable = CommonUtil.toBoolean(options.get("cacheable", null), null); + if (cacheable != null) + criteria.setCacheable(cacheable.booleanValue()); + + // MUST cacheName ? + + // maxResults + int timeout = CommonUtil.toIntValue(options.get("timeout", null), -1); + if (timeout > -1) + criteria.setTimeout(timeout); + } + + // order + if (!Util.isEmpty(order)) { + if (metaData == null) + metaData = sess.getSessionFactory().getClassMetadata(name); + + String[] arr = CommonUtil.toStringArray(order, ","); + CommonUtil.trimItems(arr); + String[] parts; + String col; + boolean isDesc; + Order _order; + // ColumnInfo ci; + for (int i = 0; i < arr.length; i++) { + parts = CommonUtil.toStringArray(arr[i], " \t\n\b\r"); + CommonUtil.trimItems(parts); + col = parts[0]; + + col = HibernateUtil.validateColumnName(metaData, col); + isDesc = false; + if (parts.length > 1) { + if (parts[1].equalsIgnoreCase("desc")) + isDesc = true; + else if (!parts[1].equalsIgnoreCase("asc")) { + throw ExceptionUtil.createException((ORMSession) null, null, + "invalid order direction defintion [" + parts[1] + "]", + "valid values are [asc, desc]"); + } + + } + _order = isDesc ? Order.desc(col) : Order.asc(col); + if (ignoreCase) + _order.ignoreCase(); + + criteria.addOrder(_order); + + } + } + + // execute + if (!unique) { + rtn = HibernateCaster.toCFML(criteria.list()); + } else { + rtn = HibernateCaster.toCFML(criteria.uniqueResult()); + } + + } catch (Throwable t) { + throw CommonUtil.toPageException(t); + } + return rtn; + } + + @Override + public Session getRawSession(String dsn) throws PageException { + return getSession(null, CommonUtil.toKey(dsn)); + } + + @Override + public SessionFactory getRawSessionFactory(String dsn) throws PageException { + return getSession(null, CommonUtil.toKey(dsn)).getSessionFactory(); + } + + @Override + public boolean isValid(DataSource ds) { + SessionAndConn sac = sessions.get(CommonUtil.toKey(ds.getName())); + return sac != null && sac.isOpen(); + } + + @Override + public boolean isValid() { + if (sessions.size() == 0) + return false; + Iterator it = sessions.values().iterator(); + + while (it.hasNext()) { + if (!it.next().isOpen()) + return false; + } + return true; + } + + @Override + public ORMTransaction getTransaction(String dsn, boolean autoManage) throws PageException { + return new HibernateORMTransaction(getSession(null, CommonUtil.toKey(dsn)), autoManage); + } + + @Override + public String[] getEntityNames() { + List names = data.getEntityNames(); + return names.toArray(new String[names.size()]); + } + + @Override + public DataSource[] getDataSources() { + return data.getDataSources(); + } + + private static String addIndexIfNecessary(String sql) { + // if(namedParams.size()==0) return new Pair>(sql,params); + StringBuilder sb = new StringBuilder(); + int sqlLen = sql.length(); + char c, quoteType = 0; + boolean inQuotes = false; + int qm = 0, _qm = 0; + int index = 1; + for (int i = 0; i < sqlLen; i++) { + c = sql.charAt(i); + + if (c == '"' || c == '\'') { + if (inQuotes) { + if (c == quoteType) { + inQuotes = false; + } + } else { + quoteType = c; + inQuotes = true; + } + } + + if (!inQuotes && c == '?') { + // is the next a number? + if (sqlLen > i + 1 && isInteger(sql.charAt(i + 1))) { + return sql; + } + + sb.append(c).append(index++); + } else { + sb.append(c); + } + } + + return sb.toString(); + } + + private static final boolean isInteger(char c) { + return c >= '0' && c <= '9'; + } } \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMTransaction.java b/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMTransaction.java index 09b2d2c5..e48817b6 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMTransaction.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/HibernateORMTransaction.java @@ -6,60 +6,106 @@ import lucee.runtime.orm.ORMTransaction; +/** + * Hibernate Transaction wrapper object. Useful for opening, closing, and general management of a single transaction. + */ public class HibernateORMTransaction implements ORMTransaction { - private Transaction trans; - private Session session; - private boolean doRollback; - private boolean autoManage; + private Transaction trans; + private Session session; + private boolean doRollback; + private boolean autoManage; - public HibernateORMTransaction(Session session, boolean autoManage) { - this.session = session; - this.autoManage = autoManage; - } + /** + * Constructor. Does NOT open a Hibernate transaction at this time. + *

+ * To open a Hibernate transaction, call begin() after this method: + * + *

+     * HibernateORMTransaction tx = new HibernateORMTransaction(session, true);
+     * tx.begin();
+     * 
+ * + * @param session + * Hibernate session to open a transaction on + * @param autoManage + * Should the Transaction be auto-managed + */ + public HibernateORMTransaction(Session session, boolean autoManage) { + this.session = session; + this.autoManage = autoManage; + } - @Override - public void begin() { - if (autoManage) { - // FlushM - // FlushModeType fm = session.getFlushMode(); - // FlushMode hfm = session.getHibernateFlushMode(); + /** + * Open or acquire a Transaction for the current session. + *

+ * Will flush the current session if autoManage is enabled. + * + * @see org.hibernate.SharedSessionContract#getTransaction() + */ + @Override + public void begin() { + if (autoManage) { + // FlushM + // FlushModeType fm = session.getFlushMode(); + // FlushMode hfm = session.getHibernateFlushMode(); - session.flush(); - } - trans = session.beginTransaction(); + session.flush(); + } + trans = session.getTransaction(); - } + } - @Override - public void commit() { - // do nothing - } + /** + * Commit the transaction. + * + * Just kidding... right now this method does nothing. + */ + @Override + public void commit() { + // do nothing + } - @Override - public void rollback() { - doRollback = true; - } + /** + * Mark the transaction for rollback. + * + * Will only execute a rollback on {@link #end()} + */ + @Override + public void rollback() { + doRollback = true; + } - @Override - public void end() { - try { - if (doRollback) { - trans.rollback(); - if (autoManage) { - session.clear(); - } - } - else { - if (trans.getStatus() == TransactionStatus.COMMITTED) { - trans.commit(); - } - session.flush(); - } - } - finally { - session.close(); - } + /** + * Wrap up the transaction. + *

    + *
  • Will roll back if rollback() called. + *
  • Will commit if transaction already committed. 🤯 + *
  • May flush the session or clear the session depending on transaction state and autoManage settings. + *
  • (currently) closes the session on execution. (See LDEV-4017) + *
+ */ + @Override + public void end() { + if (doRollback) { + trans.rollback(); + if (autoManage) { + session.clear(); + } + } else { + if (trans.getStatus() == TransactionStatus.COMMITTED) { + trans.commit(); + } + session.flush(); + } + } - } + /** + * Retrieve the internal Hibernate transaction + * + * @return a Hibernate {@link org.hibernate.Transaction} object. + */ + public Transaction getTransaction() { + return trans; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HibernatePageException.java b/source/java/src/org/lucee/extension/orm/hibernate/HibernatePageException.java index 4b09dc43..f5d83167 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/HibernatePageException.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/HibernatePageException.java @@ -1,6 +1,7 @@ package org.lucee.extension.orm.hibernate; import org.hibernate.HibernateException; +import org.lucee.extension.orm.hibernate.util.CommonUtil; import lucee.runtime.PageContext; import lucee.runtime.PageSource; @@ -16,122 +17,123 @@ public class HibernatePageException extends HibernateException implements IPageException, PageExceptionBox { - private static final long serialVersionUID = -7745292875775743390L; - - private PageException pe; - - /** - * constructor of the class - * - * @param pe page exception to hold - */ - public HibernatePageException(PageException pe) { - super(pe.getMessage()); - this.pe = pe; - } - - @Override - public String getDetail() { - return pe.getDetail(); - } - - @Override - public String getErrorCode() { - return pe.getErrorCode(); - } - - @Override - public String getExtendedInfo() { - return pe.getExtendedInfo(); - } - - @Override - public Struct getCatchBlock(PageContext pc) { - return getCatchBlock(pc.getConfig()); - } - - public Struct getCatchBlock() { - // TLPC - return pe.getCatchBlock(CommonUtil.config()); - } - - @Override - public CatchBlock getCatchBlock(Config config) { - return pe.getCatchBlock(config); - } - - @Override - public Struct getErrorBlock(PageContext pc, ErrorPage ep) { - return pe.getErrorBlock(pc, ep); - } - - @Override - public void addContext(PageSource template, int line, int column, StackTraceElement ste) { - pe.addContext(template, line, column, ste); - } - - @Override - public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { - return pe.toDumpData(pageContext, maxlevel, dp); - } - - @Override - public PageException getPageException() { - return pe; - } - - @Override - public void setDetail(String detail) { - pe.setDetail(detail); - } - - @Override - public void setErrorCode(String errorCode) { - pe.setErrorCode(errorCode); - } - - @Override - public void setExtendedInfo(String extendedInfo) { - pe.setExtendedInfo(extendedInfo); - } - - @Override - public boolean typeEqual(String type) { - return pe.typeEqual(type); - } - - @Override - public String getTypeAsString() { - return pe.getTypeAsString(); - } - - @Override - public String getCustomTypeAsString() { - return pe.getCustomTypeAsString(); - } - - @Override - public int getTracePointer() { - return pe.getTracePointer(); - } - - @Override - public void setTracePointer(int tracePointer) { - pe.setTracePointer(tracePointer); - } - - @Override - public Struct getAdditional() { - return pe.getAddional(); - } - - @Override - public Struct getAddional() { - return pe.getAddional(); - } - - @Override - public String getStackTraceAsString() { - return pe.getStackTraceAsString(); - } + private static final long serialVersionUID = -7745292875775743390L; + + private PageException pe; + + /** + * constructor of the class + * + * @param pe + * page exception to hold + */ + public HibernatePageException(PageException pe) { + super(pe.getMessage()); + this.pe = pe; + } + + @Override + public String getDetail() { + return pe.getDetail(); + } + + @Override + public String getErrorCode() { + return pe.getErrorCode(); + } + + @Override + public String getExtendedInfo() { + return pe.getExtendedInfo(); + } + + @Override + public Struct getCatchBlock(PageContext pc) { + return getCatchBlock(pc.getConfig()); + } + + public Struct getCatchBlock() { + // TLPC + return pe.getCatchBlock(CommonUtil.config()); + } + + @Override + public CatchBlock getCatchBlock(Config config) { + return pe.getCatchBlock(config); + } + + @Override + public Struct getErrorBlock(PageContext pc, ErrorPage ep) { + return pe.getErrorBlock(pc, ep); + } + + @Override + public void addContext(PageSource template, int line, int column, StackTraceElement ste) { + pe.addContext(template, line, column, ste); + } + + @Override + public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { + return pe.toDumpData(pageContext, maxlevel, dp); + } + + @Override + public PageException getPageException() { + return pe; + } + + @Override + public void setDetail(String detail) { + pe.setDetail(detail); + } + + @Override + public void setErrorCode(String errorCode) { + pe.setErrorCode(errorCode); + } + + @Override + public void setExtendedInfo(String extendedInfo) { + pe.setExtendedInfo(extendedInfo); + } + + @Override + public boolean typeEqual(String type) { + return pe.typeEqual(type); + } + + @Override + public String getTypeAsString() { + return pe.getTypeAsString(); + } + + @Override + public String getCustomTypeAsString() { + return pe.getCustomTypeAsString(); + } + + @Override + public int getTracePointer() { + return pe.getTracePointer(); + } + + @Override + public void setTracePointer(int tracePointer) { + pe.setTracePointer(tracePointer); + } + + @Override + public Struct getAdditional() { + return pe.getAdditional(); + } + + @Override + public Struct getAddional() { + return pe.getAdditional(); + } + + @Override + public String getStackTraceAsString() { + return pe.getStackTraceAsString(); + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HibernateSessionFactory.java b/source/java/src/org/lucee/extension/orm/hibernate/HibernateSessionFactory.java index ec45f083..882d471c 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/HibernateSessionFactory.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/HibernateSessionFactory.java @@ -1,8 +1,6 @@ package org.lucee.extension.orm.hibernate; import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.sql.SQLException; @@ -15,26 +13,21 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Properties; import java.util.Set; -import org.hibernate.MappingException; import org.hibernate.boot.MetadataSources; -import org.hibernate.boot.registry.BootstrapServiceRegistry; -import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.cache.ehcache.internal.EhcacheRegionFactory; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; import org.hibernate.service.ServiceRegistry; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.hibernate.tool.hbm2ddl.SchemaExport.Action; import org.hibernate.tool.hbm2ddl.SchemaUpdate; import org.hibernate.tool.schema.TargetType; -import org.lucee.extension.orm.hibernate.jdbc.ConnectionProviderImpl; -import org.w3c.dom.Document; -import org.w3c.dom.Element; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ExceptionUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; +import org.lucee.extension.orm.hibernate.util.ORMConfigurationUtil; import lucee.commons.io.log.Log; import lucee.commons.io.res.Resource; @@ -59,416 +52,340 @@ public class HibernateSessionFactory { - public static final String HIBERNATE_3_PUBLIC_ID = "-//Hibernate/Hibernate Mapping DTD 3.0//EN"; - public static final String HIBERNATE_3_SYSTEM_ID = "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"; - public static final String HIBERNATE_3_DOCTYPE_DEFINITION = ""; - - public static Configuration createConfiguration(Log log, String mappings, DataSource ds, String user, String pass, SessionFactoryData data, String applicationContextName) - throws SQLException, IOException, PageException { - ORMConfiguration ormConf = data.getORMConfiguration(); - - // dialect - String dialect = null; - String tmpDialect = ORMConfigurationUtil.getDialect(ormConf, ds.getName()); - if (!Util.isEmpty(tmpDialect)) dialect = Dialect.getDialect(tmpDialect); - if (dialect != null && Util.isEmpty(dialect)) dialect = null; - - // Cache Provider - String cacheProvider = ormConf.getCacheProvider(); - Class cacheProviderFactory = null; - - if (Util.isEmpty(cacheProvider) || "EHCache".equalsIgnoreCase(cacheProvider)) { - cacheProviderFactory = EhcacheRegionFactory.class; - } - // else if ("JBossCache".equalsIgnoreCase(cacheProvider)) cacheProvider = - // "org.hibernate.cache.TreeCacheProvider"; - // else if ("HashTable".equalsIgnoreCase(cacheProvider)) cacheProvider = - // "org.hibernate.cache.HashtableCacheProvider"; - // else if ("SwarmCache".equalsIgnoreCase(cacheProvider)) cacheProvider = - // "org.hibernate.cache.SwarmCacheProvider"; - // else if ("OSCache".equalsIgnoreCase(cacheProvider)) cacheProvider = - // "org.hibernate.cache.OSCacheProvider"; - - /// JBossCache -> https://mvnrepository.com/artifact/org.hibernate/hibernate-jbosscache - // OSCache -> https://mvnrepository.com/artifact/org.hibernate/hibernate-oscache - // SwarmCache -> https://mvnrepository.com/artifact/org.hibernate/hibernate-swarmcache - - Resource cc = ormConf.getCacheConfig(); - - BootstrapServiceRegistry bootstrapRegistry = new BootstrapServiceRegistryBuilder().applyIntegrator(data.getEventListenerIntegrator()).build(); - - Configuration configuration = new Configuration(bootstrapRegistry); - - // is ehcache - Resource cacheConfig = null; - if (cacheProvider != null && cacheProvider.toLowerCase().indexOf("ehcache") != -1) { - CFMLEngine eng = CFMLEngineFactory.getInstance(); - String varName = eng.getCastUtil().toVariableName(applicationContextName, applicationContextName); - String xml; - if (cc == null || !cc.isFile()) { - cacheConfig = eng.getResourceUtil().getTempDirectory().getRealResource("ehcache/" + varName + ".xml"); - xml = createEHConfigXML(varName); - } - // we need to change or set the name - else { - String b64 = varName + eng.getSystemUtil().hash64b(CommonUtil.toString(cc, (Charset) null)); - cacheConfig = eng.getResourceUtil().getTempDirectory().getRealResource("ehcache/" + b64 + ".xml"); - Document doc = CommonUtil.toDocument(cc, null); - Element root = doc.getDocumentElement(); - root.setAttribute("name", b64); - - xml = CommonUtil.toString(root, false, true, null, null, CommonUtil.UTF8().name()); - } - - if (!cacheConfig.isFile()) { - cacheConfig.getParentResource().mkdirs(); - eng.getIOUtil().write(cacheConfig, xml, false, null); - } - } - - // ormConfig - Resource conf = ormConf.getOrmConfig(); - if (conf != null) { - try { - Document doc = CommonUtil.toDocument(conf, null); - configuration.configure(doc); - } - catch (Exception e) { - log.log(Log.LEVEL_ERROR, "hibernate", e); - - } - } - - try { - configuration.addInputStream(new ByteArrayInputStream(mappings.getBytes("UTF-8"))); - } - catch (MappingException me) { - throw ExceptionUtil.createException(data, null, me); - } - - configuration.setProperty(AvailableSettings.FLUSH_BEFORE_COMPLETION, "false") - - .setProperty(AvailableSettings.ALLOW_UPDATE_OUTSIDE_TRANSACTION, "true") - - .setProperty(AvailableSettings.AUTO_CLOSE_SESSION, "false"); - - setProperty(configuration, Environment.CONNECTION_PROVIDER, new ConnectionProviderImpl(ds, user, pass)); - - // SQL dialect - if (dialect != null) configuration.setProperty(AvailableSettings.DIALECT, dialect); - // Enable Hibernate's current session context - configuration.setProperty(AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS, "thread") - - // Echo all executed SQL to stdout - .setProperty(AvailableSettings.SHOW_SQL, CommonUtil.toString(ormConf.logSQL())).setProperty("hibernate.format_sql", CommonUtil.toString(ormConf.logSQL())) - // formatting of SQL logged to the console - .setProperty(AvailableSettings.FORMAT_SQL, CommonUtil.toString(ormConf.logSQL())).setProperty("hibernate.format_sql", CommonUtil.toString(ormConf.logSQL())) - // Specifies whether secondary caching should be enabled - .setProperty(AvailableSettings.USE_SECOND_LEVEL_CACHE, CommonUtil.toString(ormConf.secondaryCacheEnabled())) - // Drop and re-create the database schema on startup - .setProperty("hibernate.exposeTransactionAwareSessionFactory", "false") - // .setProperty("hibernate.hbm2ddl.auto", "create") - .setProperty(AvailableSettings.DEFAULT_ENTITY_MODE, "dynamic-map"); - - String catalog = ORMConfigurationUtil.getCatalog(ormConf, ds.getName()); - String schema = ORMConfigurationUtil.getSchema(ormConf, ds.getName()); - - if (!Util.isEmpty(catalog)) configuration.setProperty("hibernate.default_catalog", catalog); - if (!Util.isEmpty(schema)) configuration.setProperty("hibernate.default_schema", schema); - - if (ormConf.secondaryCacheEnabled()) { - if (cacheConfig != null && cacheConfig.isFile()) { - configuration.setProperty("hibernate.cache.provider_configuration_file_resource_path", cacheConfig.getAbsolutePath()); - configuration.setProperty("cache.provider_configuration_file_resource_path", cacheConfig.getAbsolutePath()); - if (cacheConfig instanceof File) configuration.setProperty("net.sf.ehcache.configurationResourceName", ((File) cacheConfig).toURI().toURL().toExternalForm()); - else throw new IOException("only local configuration files are supported"); - - } - - if (cacheProviderFactory != null) { - setProperty(configuration, AvailableSettings.CACHE_REGION_FACTORY, cacheProviderFactory); - } - // AvailableSettings.CACHE_REGION_FACTORY - // hibernate.cache.region.factory_class - // hibernate.cache.use_second_level_cache - - // org.hibernate.cache.ehcache.EhCacheRegionFactory - // org.hibernate.cache.EhCacheProvider - - configuration.setProperty("hibernate.cache.use_query_cache", "true"); - // hibernate-ehcache.xml - - // hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider - } - - schemaExport(log, configuration, ds, user, pass, data); - - return configuration; - } - - private static void setProperty(Configuration configuration, String name, Object value) { - Properties props = new Properties(); - props.put(name, value); - configuration.addProperties(props); - } - - private static String createEHConfigXML(String cacheName) { - return new StringBuilder().append("").append("") - .append(" ").append(" ").append(" ").append(" ") - .append("").toString(); - } - - private static void schemaExport(Log log, Configuration configuration, DataSource ds, String user, String pass, SessionFactoryData data) - throws PageException, SQLException, IOException { - ORMConfiguration ormConf = data.getORMConfiguration(); - - ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); - - MetadataSources metadata = new MetadataSources(serviceRegistry); - EnumSet enumSet = EnumSet.of(TargetType.DATABASE); - - if (ORMConfiguration.DBCREATE_NONE == ormConf.getDbCreate()) { - configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "none"); - return; - } - else if (ORMConfiguration.DBCREATE_DROP_CREATE == ormConf.getDbCreate()) { - configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "create"); - SchemaExport export = new SchemaExport(); - export.setHaltOnError(true); - export.execute(enumSet, Action.BOTH, metadata.buildMetadata()); - printError(log, data, export.getExceptions(), false); - executeSQLScript(ormConf, ds, user, pass); - } - else if (/* ORMConfiguration.DBCREATE_CREATE */3 == ormConf.getDbCreate()) { - configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "create-only"); - SchemaExport export = new SchemaExport(); - export.setHaltOnError(true); - export.execute(enumSet, Action.CREATE, metadata.buildMetadata()); - printError(log, data, export.getExceptions(), false); - executeSQLScript(ormConf, ds, user, pass); - } - else if (/* ORMConfiguration.DBCREATE_CREATE_DROP */4 == ormConf.getDbCreate()) { - configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "create-drop"); - SchemaExport export = new SchemaExport(); - export.setHaltOnError(true); - export.execute(enumSet, Action.BOTH, metadata.buildMetadata()); - printError(log, data, export.getExceptions(), false); - executeSQLScript(ormConf, ds, user, pass); - } - else if (ORMConfiguration.DBCREATE_UPDATE == ormConf.getDbCreate()) { - configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "update"); - SchemaUpdate update = new SchemaUpdate(); - update.setHaltOnError(true); - update.execute(enumSet, metadata.buildMetadata()); - printError(log, data, update.getExceptions(), false); - } - } - - private static void printError(Log log, SessionFactoryData data, List exceptions, boolean throwException) throws PageException { - if (exceptions == null || exceptions.size() == 0) return; - Iterator it = exceptions.iterator(); - if (!throwException || exceptions.size() > 1) { - while (it.hasNext()) { - log.log(Log.LEVEL_ERROR, "hibernate", it.next()); - } - } - if (!throwException) return; - - it = exceptions.iterator(); - while (it.hasNext()) { - throw ExceptionUtil.createException(data, null, it.next()); - } - } - - private static void executeSQLScript(ORMConfiguration ormConf, DataSource ds, String user, String pass) throws SQLException, IOException, PageException { - Resource sqlScript = ORMConfigurationUtil.getSqlScript(ormConf, ds.getName()); - if (sqlScript != null && sqlScript.isFile()) { - BufferedReader br = CommonUtil.toBufferedReader(sqlScript, (Charset) null); - String line; - StringBuilder sql = new StringBuilder(); - String str; - Statement stat = null; - PageContext pc = CFMLEngineFactory.getInstance().getThreadPageContext(); - DatasourceConnection dc = CommonUtil.getDatasourceConnection(pc, ds, user, pass, true); - try { - - stat = dc.getConnection().createStatement(); - while ((line = br.readLine()) != null) { - line = line.trim(); - if (line.startsWith("//") || line.startsWith("--")) continue; - if (line.endsWith(";")) { - sql.append(line.substring(0, line.length() - 1)); - str = sql.toString().trim(); - if (str.length() > 0) stat.execute(str); - sql = new StringBuilder(); - } - else { - sql.append(line).append(" "); - } - } - str = sql.toString().trim(); - if (str.length() > 0) { - stat.execute(str); - } - } - finally { - CFMLEngineFactory.getInstance().getDBUtil().closeSilent(stat); - CommonUtil.releaseDatasourceConnection(pc, dc, true); - } - } - } - - public static Map createMappings(ORMConfiguration ormConf, SessionFactoryData data) { - Map mappings = new HashMap(); - Iterator>> it = data.getCFCs().entrySet().iterator(); - while (it.hasNext()) { - Entry> e = it.next(); - - Set done = new HashSet(); - StringBuilder mapping = new StringBuilder(); - mapping.append("\n"); - mapping.append(HIBERNATE_3_DOCTYPE_DEFINITION + "\n"); - mapping.append("\n"); - Iterator> _it = e.getValue().entrySet().iterator(); - Entry entry; - while (_it.hasNext()) { - entry = _it.next(); - createMappings(ormConf, entry.getKey(), entry.getValue(), done, mapping, data); - - } - mapping.append(""); - mappings.put(e.getKey(), mapping.toString()); - } - return mappings; - } - - private static void createMappings(ORMConfiguration ormConf, String key, CFCInfo value, Set done, StringBuilder mappings, SessionFactoryData data) { - if (done.contains(key)) return; - CFCInfo v; - String ext = value.getCFC().getExtends(); - if (!Util.isEmpty(ext)) { - try { - Component base = data.getEntityByCFCName(ext, false); - ext = HibernateCaster.getEntityName(base); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - - ext = HibernateUtil.id(CommonUtil.last(ext, ".").trim()); - if (!done.contains(ext)) { - v = data.getCFC(ext, null); - if (v != null) createMappings(ormConf, ext, v, done, mappings, data); - } - } - - mappings.append(value.getXML()); - done.add(key); - } - - public static List loadComponents(PageContext pc, HibernateORMEngine engine, ORMConfiguration ormConf) throws PageException { - CFMLEngine en = CFMLEngineFactory.getInstance(); - String[] ext = HibernateUtil.merge(en.getInfo().getCFMLComponentExtensions(), en.getInfo().getLuceeComponentExtensions()); - - ResourceFilter filter = en.getResourceUtil().getExtensionResourceFilter(ext, true); - List components = new ArrayList(); - loadComponents(pc, engine, components, ormConf.getCfcLocations(), filter, ormConf); - return components; - } - - private static void loadComponents(PageContext pc, HibernateORMEngine engine, List components, Resource[] reses, ResourceFilter filter, ORMConfiguration ormConf) - throws PageException { - Mapping[] mappings = createMappings(pc, reses); - ApplicationContext ac = pc.getApplicationContext(); - Mapping[] existing = ac.getComponentMappings(); - if (existing == null) existing = new Mapping[0]; - try { - Mapping[] tmp = new Mapping[existing.length + 1]; - for (int i = 1; i < tmp.length; i++) { - tmp[i] = existing[i - 1]; - } - ac.setComponentMappings(tmp); - for (int i = 0; i < reses.length; i++) { - if (reses[i] != null && reses[i].isDirectory()) { - tmp[0] = mappings[i]; - ac.setComponentMappings(tmp); - loadComponents(pc, engine, mappings[i], components, reses[i], filter, ormConf); - } - } - } - finally { - ac.setComponentMappings(existing); - } - } - - private static void loadComponents(PageContext pc, HibernateORMEngine engine, Mapping cfclocation, List components, Resource res, ResourceFilter filter, - ORMConfiguration ormConf) throws PageException { - if (res == null) return; - - if (res.isDirectory()) { - Resource[] children = res.listResources(filter); - - // first load all files - for (int i = 0; i < children.length; i++) { - if (children[i].isFile()) loadComponents(pc, engine, cfclocation, components, children[i], filter, ormConf); - } - - // and then invoke subfiles - for (int i = 0; i < children.length; i++) { - if (children[i].isDirectory()) loadComponents(pc, engine, cfclocation, components, children[i], filter, ormConf); - } - } - else if (res.isFile()) { - if (!HibernateUtil.isApplicationName(pc, res.getName())) { - try { - - // MUST still a bad solution - PageSource ps = pc.toPageSource(res, null); - if (ps == null || ps.getComponentName().indexOf("..") != -1) { - PageSource ps2 = null; - Resource root = cfclocation.getPhysical(); - String path = CFMLEngineFactory.getInstance().getResourceUtil().getPathToChild(res, root); - if (!Util.isEmpty(path, true)) { - ps2 = cfclocation.getPageSource(path); - } - if (ps2 != null) ps = ps2; - } - - // Page p = ps.loadPage(pc.getConfig()); - String name = res.getName(); - name = HibernateUtil.removeExtension(name, name); - - TemplateUtil tu = CFMLEngineFactory.getInstance().getTemplateUtil(); - - Page p = tu.loadPage(pc, ps, true); - if (!(p instanceof InterfacePage)) { - Component cfc = tu.loadComponent(pc, p, name, true, true, false, true); - if (cfc.isPersistent()) { - components.add(cfc); - } - } - } - catch (PageException e) { - if (!ormConf.skipCFCWithError()) throw e; - // e.printStackTrace(); - } - } - } - } - - public static Mapping[] createMappings(PageContext pc, Resource[] resources) { - - Mapping[] mappings = new Mapping[resources.length]; - Config config = pc.getConfig(); - for (int i = 0; i < mappings.length; i++) { - mappings[i] = CommonUtil.createMapping(config, "/", resources[i].getAbsolutePath()); - } - return mappings; - } + /** + * Generate the database schema based on the configured settings (dropcreate, update, etc.) + * + * @param log + * Lucee logger object + * @param configuration + * Hibernate configuration + * @param ds + * Datasource + * @param user + * Datasource username + * @param pass + * Datasource password + * @param data + * Session factory data container + * + * @throws PageException + * @throws SQLException + * @throws IOException + */ + public static void schemaExport(Log log, Configuration configuration, DataSource ds, String user, String pass, + SessionFactoryData data) throws PageException, SQLException, IOException { + ORMConfiguration ormConf = data.getORMConfiguration(); + + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() + .applySettings(configuration.getProperties()).build(); + + MetadataSources metadata = new MetadataSources(serviceRegistry); + EnumSet enumSet = EnumSet.of(TargetType.DATABASE); + + if (ORMConfiguration.DBCREATE_NONE == ormConf.getDbCreate()) { + configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "none"); + return; + } else if (ORMConfiguration.DBCREATE_DROP_CREATE == ormConf.getDbCreate()) { + configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "create"); + SchemaExport export = new SchemaExport(); + export.setHaltOnError(true); + export.execute(enumSet, Action.BOTH, metadata.buildMetadata()); + printError(log, data, export.getExceptions(), false); + executeSQLScript(ormConf, ds, user, pass); + } else if (/* ORMConfiguration.DBCREATE_CREATE */3 == ormConf.getDbCreate()) { + configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "create-only"); + SchemaExport export = new SchemaExport(); + export.setHaltOnError(true); + export.execute(enumSet, Action.CREATE, metadata.buildMetadata()); + printError(log, data, export.getExceptions(), false); + executeSQLScript(ormConf, ds, user, pass); + } else if (/* ORMConfiguration.DBCREATE_CREATE_DROP */4 == ormConf.getDbCreate()) { + configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "create-drop"); + SchemaExport export = new SchemaExport(); + export.setHaltOnError(true); + export.execute(enumSet, Action.BOTH, metadata.buildMetadata()); + printError(log, data, export.getExceptions(), false); + executeSQLScript(ormConf, ds, user, pass); + } else if (ORMConfiguration.DBCREATE_UPDATE == ormConf.getDbCreate()) { + configuration.setProperty(AvailableSettings.HBM2DDL_AUTO, "update"); + SchemaUpdate update = new SchemaUpdate(); + update.setHaltOnError(true); + update.execute(enumSet, metadata.buildMetadata()); + printError(log, data, update.getExceptions(), false); + } + } + + private static void printError(Log log, SessionFactoryData data, List exceptions, boolean throwException) + throws PageException { + if (exceptions == null || exceptions.size() == 0) + return; + Iterator it = exceptions.iterator(); + if (!throwException || exceptions.size() > 1) { + while (it.hasNext()) { + log.log(Log.LEVEL_ERROR, "hibernate", it.next()); + } + } + if (!throwException) + return; + + it = exceptions.iterator(); + while (it.hasNext()) { + throw ExceptionUtil.createException(data, null, it.next()); + } + } + + private static void executeSQLScript(ORMConfiguration ormConf, DataSource ds, String user, String pass) + throws SQLException, IOException, PageException { + Resource sqlScript = ORMConfigurationUtil.getSqlScript(ormConf, ds.getName()); + if (sqlScript != null && sqlScript.isFile()) { + BufferedReader br = CommonUtil.toBufferedReader(sqlScript, (Charset) null); + String line; + StringBuilder sql = new StringBuilder(); + String str; + Statement stat = null; + PageContext pc = CFMLEngineFactory.getInstance().getThreadPageContext(); + DatasourceConnection dc = CommonUtil.getDatasourceConnection(pc, ds, user, pass, true); + try { + + stat = dc.getConnection().createStatement(); + while ((line = br.readLine()) != null) { + line = line.trim(); + if (line.startsWith("//") || line.startsWith("--")) + continue; + if (line.endsWith(";")) { + sql.append(line.substring(0, line.length() - 1)); + str = sql.toString().trim(); + if (str.length() > 0) + stat.execute(str); + sql = new StringBuilder(); + } else { + sql.append(line).append(" "); + } + } + str = sql.toString().trim(); + if (str.length() > 0) { + stat.execute(str); + } + } finally { + CFMLEngineFactory.getInstance().getDBUtil().closeSilent(stat); + CommonUtil.releaseDatasourceConnection(pc, dc, true); + } + } + } + + public static Map assembleMappingsByDatasource(SessionFactoryData data) { + Map mappings = new HashMap(); + Iterator>> it = data.getCFCs().entrySet().iterator(); + while (it.hasNext()) { + Entry> e = it.next(); + + Set done = new HashSet(); + StringBuilder mapping = new StringBuilder(); + mapping.append(HBMCreator.getXMLOpen()); + mapping.append(""); + Iterator> _it = e.getValue().entrySet().iterator(); + _it.forEachRemaining(entry -> { + mapping.append(assembleMappingForCFC(entry.getKey(), entry.getValue(), done, data)); + }); + mapping.append(""); + mappings.put(e.getKey(), mapping.toString()); + } + return mappings; + } + + private static String assembleMappingForCFC(String key, CFCInfo value, Set done, SessionFactoryData data) { + if (done.contains(key)) + return ""; + CFCInfo v; + StringBuilder mappings = new StringBuilder(); + String ext = value.getCFC().getExtends(); + if (!Util.isEmpty(ext)) { + try { + Component parent = data.getEntityByCFCName(ext, false); + ext = HibernateCaster.getEntityName(parent); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + + ext = HibernateUtil.id(CommonUtil.last(ext, ".").trim()); + if (!done.contains(ext)) { + v = data.getCFC(ext, null); + if (v != null) { + mappings.append(HBMCreator.stripXMLOpenClose(assembleMappingForCFC(ext, v, done, data))); + } + } + } + + mappings.append(HBMCreator.stripXMLOpenClose(value.getXML())); + done.add(key); + return mappings.toString(); + } + + /** + * Load and return persistent entities using the ORM configuration + * + * @param pc + * Lucee PageContext object + * @param engine + * ORM engine + * @param ormConf + * ORM configuration object. + * + * @throws PageException + */ + public static List loadComponents(PageContext pc, HibernateORMEngine engine, ORMConfiguration ormConf) + throws PageException { + CFMLEngine en = CFMLEngineFactory.getInstance(); + + ResourceFilter filter = en.getResourceUtil().getExtensionResourceFilter("cfc", true); + List components = new ArrayList(); + loadComponents(pc, engine, components, ormConf.getCfcLocations(), filter, ormConf); + return components; + } + + /** + * Load persistent entities from the given directory + * + * @param pc + * Lucee PageContext object + * @param engine + * ORM engine + * @param components + * The current list of components. Any discovered components will be appended to this list. + * @param res + * The directory to search for Components. + * @param filter + * The file filter - probably just a Lucee-fied ".cfc" filter + * @param ormConf + * ORM configuration object. + * + * @throws PageException + */ + private static void loadComponents(PageContext pc, HibernateORMEngine engine, List components, + Resource[] reses, ResourceFilter filter, ORMConfiguration ormConf) throws PageException { + Mapping[] mappings = createFileMappings(pc, reses); + ApplicationContext ac = pc.getApplicationContext(); + Mapping[] existing = ac.getComponentMappings(); + if (existing == null) + existing = new Mapping[0]; + try { + Mapping[] tmp = new Mapping[existing.length + 1]; + for (int i = 1; i < tmp.length; i++) { + tmp[i] = existing[i - 1]; + } + ac.setComponentMappings(tmp); + for (int i = 0; i < reses.length; i++) { + if (reses[i] != null && reses[i].isDirectory()) { + tmp[0] = mappings[i]; + ac.setComponentMappings(tmp); + loadComponents(pc, engine, mappings[i], components, reses[i], filter, ormConf); + } + } + } finally { + ac.setComponentMappings(existing); + } + } + + /** + * Load persistent entities from the given cfclocation Mapping directory + * + * @param pc + * Lucee PageContext object + * @param engine + * ORM engine + * @param cfclocation + * Lucee {@link lucee.runtime.Mapping} pointing to a directory where .cfc Components are located. + * @param components + * The current list of components. Any discovered components will be appended to this list. + * @param res + * The directory to search for Components, OR the file to (potentially) import into the Hibernate + * configuration. + * @param filter + * The file filter - probably just a Lucee-fied ".cfc" filter + * @param ormConf + * ORM configuration object. + * + * @throws PageException + */ + private static void loadComponents(PageContext pc, HibernateORMEngine engine, Mapping cfclocation, + List components, Resource res, ResourceFilter filter, ORMConfiguration ormConf) + throws PageException { + if (res == null) + return; + + if (res.isDirectory()) { + Resource[] children = res.listResources(filter); + + // first load all files + for (int i = 0; i < children.length; i++) { + if (children[i].isFile()) + loadComponents(pc, engine, cfclocation, components, children[i], filter, ormConf); + } + + // and then invoke subfiles + for (int i = 0; i < children.length; i++) { + if (children[i].isDirectory()) + loadComponents(pc, engine, cfclocation, components, children[i], filter, ormConf); + } + } else if (res.isFile()) { + if (!HibernateUtil.isApplicationName(res.getName())) { + try { + + // MUST still a bad solution + PageSource ps = pc.toPageSource(res, null); + if (ps == null || ps.getComponentName().indexOf("..") != -1) { + PageSource ps2 = null; + Resource root = cfclocation.getPhysical(); + String path = CFMLEngineFactory.getInstance().getResourceUtil().getPathToChild(res, root); + if (!Util.isEmpty(path, true)) { + ps2 = cfclocation.getPageSource(path); + } + if (ps2 != null) + ps = ps2; + } + + // Page p = ps.loadPage(pc.getConfig()); + String name = res.getName(); + name = HibernateUtil.removeExtension(name, name); + + TemplateUtil tu = CFMLEngineFactory.getInstance().getTemplateUtil(); + + Page p = tu.loadPage(pc, ps, true); + if (!(p instanceof InterfacePage)) { + Component cfc = tu.loadComponent(pc, p, name, true, true, false, true); + if (cfc.isPersistent()) { + components.add(cfc); + } + } + } catch (PageException e) { + if (!ormConf.skipCFCWithError()) + throw e; + // e.printStackTrace(); + } + } + } + } + + /** + * Create CF mappings for locating persistent entities. + *

+ * Used when importing persistent entities from the configured this.ormsettings.cfclocation array. + * + * @param pc + * Lucee PageContext + * @param resources + * Array of Resource objects, i.e. a file path + * + * @return a Mapping object used to locate a file resource + */ + public static Mapping[] createFileMappings(PageContext pc, Resource[] resources) { + + Mapping[] mappings = new Mapping[resources.length]; + Config config = pc.getConfig(); + for (int i = 0; i < mappings.length; i++) { + mappings[i] = CommonUtil.createMapping(config, "/", resources[i].getAbsolutePath()); + } + return mappings; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/HibernateUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/HibernateUtil.java deleted file mode 100755 index b1648f50..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/HibernateUtil.java +++ /dev/null @@ -1,383 +0,0 @@ -package org.lucee.extension.orm.hibernate; - -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import org.hibernate.HibernateException; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.type.ComponentType; -import org.hibernate.type.Type; - -import lucee.Info; -import lucee.commons.io.res.Resource; -import lucee.loader.engine.CFMLEngine; -import lucee.loader.engine.CFMLEngineFactory; -import lucee.loader.util.Util; -import lucee.runtime.Component; -import lucee.runtime.PageContext; -import lucee.runtime.PageSource; -import lucee.runtime.component.Property; -import lucee.runtime.config.Config; -import lucee.runtime.db.DatasourceConnection; -import lucee.runtime.exp.PageException; -import lucee.runtime.orm.ORMConfiguration; -import lucee.runtime.orm.ORMSession; -import lucee.runtime.type.Collection; -import lucee.runtime.type.Struct; - -public class HibernateUtil { - - public static final short FIELDTYPE_ID = 0; - public static final short FIELDTYPE_COLUMN = 1; - public static final short FIELDTYPE_TIMESTAMP = 2; - public static final short FIELDTYPE_RELATION = 4; - public static final short FIELDTYPE_VERSION = 8; - public static final short FIELDTYPE_COLLECTION = 16; - - private static final String[] KEYWORDS = new String[] { "absolute", "access", "accessible", "action", "add", "after", "alias", "all", "allocate", "allow", "alter", "analyze", - "and", "any", "application", "are", "array", "as", "asc", "asensitive", "assertion", "associate", "asutime", "asymmetric", "at", "atomic", "audit", "authorization", - "aux", "auxiliary", "avg", "backup", "before", "begin", "between", "bigint", "binary", "bit", "bit_length", "blob", "boolean", "both", "breadth", "break", "browse", - "bufferpool", "bulk", "by", "cache", "call", "called", "capture", "cardinality", "cascade", "cascaded", "case", "cast", "catalog", "ccsid", "change", "char", - "char_length", "character", "character_length", "check", "checkpoint", "clob", "close", "cluster", "clustered", "coalesce", "collate", "collation", "collection", - "collid", "column", "comment", "commit", "compress", "compute", "concat", "condition", "connect", "connection", "constraint", "constraints", "constructor", "contains", - "containstable", "continue", "convert", "corresponding", "count", "count_big", "create", "cross", "cube", "current", "current_date", "current_default_transform_group", - "current_lc_ctype", "current_path", "current_role", "current_server", "current_time", "current_timestamp", "current_timezone", "current_transform_group_for_type", - "current_user", "cursor", "cycle", "data", "database", "databases", "date", "day", "day_hour", "day_microsecond", "day_minute", "day_second", "days", "db2general", - "db2genrl", "db2sql", "dbcc", "dbinfo", "deallocate", "dec", "decimal", "declare", "default", "defaults", "deferrable", "deferred", "delayed", "delete", "deny", - "depth", "deref", "desc", "describe", "descriptor", "deterministic", "diagnostics", "disallow", "disconnect", "disk", "distinct", "distinctrow", "distributed", "div", - "do", "domain", "double", "drop", "dsnhattr", "dssize", "dual", "dummy", "dump", "dynamic", "each", "editproc", "else", "elseif", "enclosed", "encoding", "end", - "end-exec", "end-exec1", "endexec", "equals", "erase", "errlvl", "escape", "escaped", "except", "exception", "excluding", "exclusive", "exec", "execute", "exists", - "exit", "explain", "external", "extract", "false", "fenced", "fetch", "fieldproc", "file", "fillfactor", "filter", "final", "first", "float", "float4", "float8", "for", - "force", "foreign", "found", "free", "freetext", "freetexttable", "from", "full", "fulltext", "function", "general", "generated", "get", "get_current_connection", - "global", "go", "goto", "grant", "graphic", "group", "grouping", "handler", "having", "high_priority", "hold", "holdlock", "hour", "hour_microsecond", "hour_minute", - "hour_second", "hours", "identified", "identity", "identity_insert", "identitycol", "if", "ignore", "immediate", "in", "including", "increment", "index", "indicator", - "infile", "inherit", "initial", "initially", "inner", "inout", "input", "insensitive", "insert", "int", "int1", "int2", "int3", "int4", "int8", "integer", "integrity", - "intersect", "interval", "into", "is", "isobid", "isolation", "iterate", "jar", "java", "join", "key", "keys", "kill", "language", "large", "last", "lateral", - "leading", "leave", "left", "level", "like", "limit", "linear", "lineno", "lines", "linktype", "load", "local", "locale", "localtime", "localtimestamp", "locator", - "locators", "lock", "lockmax", "locksize", "long", "longblob", "longint", "longtext", "loop", "low_priority", "lower", "ltrim", "map", "master_ssl_verify_server_cert", - "match", "max", "maxextents", "maxvalue", "mediumblob", "mediumint", "mediumtext", "method", "microsecond", "microseconds", "middleint", "min", "minus", "minute", - "minute_microsecond", "minute_second", "minutes", "minvalue", "mlslabel", "mod", "mode", "modifies", "modify", "module", "month", "months", "names", "national", - "natural", "nchar", "nclob", "new", "new_table", "next", "no", "no_write_to_binlog", "noaudit", "nocache", "nocheck", "nocompress", "nocycle", "nodename", "nodenumber", - "nomaxvalue", "nominvalue", "nonclustered", "none", "noorder", "not", "nowait", "null", "nullif", "nulls", "number", "numeric", "numparts", "nvarchar", "obid", - "object", "octet_length", "of", "off", "offline", "offsets", "old", "old_table", "on", "online", "only", "open", "opendatasource", "openquery", "openrowset", "openxml", - "optimization", "optimize", "option", "optionally", "or", "order", "ordinality", "out", "outer", "outfile", "output", "over", "overlaps", "overriding", "package", - "pad", "parameter", "part", "partial", "partition", "path", "pctfree", "percent", "piecesize", "plan", "position", "precision", "prepare", "preserve", "primary", - "print", "prior", "priqty", "privileges", "proc", "procedure", "program", "psid", "public", "purge", "queryno", "raiserror", "range", "raw", "read", "read_write", - "reads", "readtext", "real", "reconfigure", "recovery", "recursive", "ref", "references", "referencing", "regexp", "relative", "release", "rename", "repeat", "replace", - "replication", "require", "resignal", "resource", "restart", "restore", "restrict", "result", "result_set_locator", "return", "returns", "revoke", "right", "rlike", - "role", "rollback", "rollup", "routine", "row", "rowcount", "rowguidcol", "rowid", "rownum", "rows", "rrn", "rtrim", "rule", "run", "runtimestatistics", "save", - "savepoint", "schema", "schemas", "scope", "scratchpad", "scroll", "search", "second", "second_microsecond", "seconds", "secqty", "section", "security", "select", - "sensitive", "separator", "session", "session_user", "set", "sets", "setuser", "share", "show", "shutdown", "signal", "similar", "simple", "size", "smallint", "some", - "source", "space", "spatial", "specific", "specifictype", "sql", "sql_big_result", "sql_calc_found_rows", "sql_small_result", "sqlcode", "sqlerror", "sqlexception", - "sqlid", "sqlstate", "sqlwarning", "ssl", "standard", "start", "starting", "state", "static", "statistics", "stay", "stogroup", "stores", "straight_join", "style", - "subpages", "substr", "substring", "successful", "sum", "symmetric", "synonym", "sysdate", "sysfun", "sysibm", "sysproc", "system", "system_user", "table", - "tablespace", "temporary", "terminated", "textsize", "then", "time", "timestamp", "timezone_hour", "timezone_minute", "tinyblob", "tinyint", "tinytext", "to", "top", - "trailing", "tran", "transaction", "translate", "translation", "treat", "trigger", "trim", "true", "truncate", "tsequal", "type", "uid", "under", "undo", "union", - "unique", "unknown", "unlock", "unnest", "unsigned", "until", "update", "updatetext", "upper", "usage", "use", "user", "using", "utc_date", "utc_time", "utc_timestamp", - "validate", "validproc", "value", "values", "varbinary", "varchar", "varchar2", "varcharacter", "variable", "variant", "varying", "vcat", "view", "volumes", "waitfor", - "when", "whenever", "where", "while", "window", "with", "within", "without", "wlm", "work", "write", "writetext", "xor", "year", "year_month", "zerofill", "zone" }; - private static final Set keywords = new HashSet(); - static { - for (int i = 0; i < KEYWORDS.length; i++) { - keywords.add(KEYWORDS[i]); - } - } - - public static boolean isKeyword(String word) { - if (word == null) return false; - return keywords.contains(word.trim().toLowerCase()); - } - - public static Type getPropertyType(ClassMetadata metaData, String name) throws HibernateException { - try { - return metaData.getPropertyType(name); - } - catch (HibernateException he) { - if (name.equalsIgnoreCase(metaData.getIdentifierPropertyName())) return metaData.getIdentifierType(); - - String[] names = metaData.getPropertyNames(); - for (int i = 0; i < names.length; i++) { - if (names[i].equalsIgnoreCase(name)) return metaData.getPropertyType(names[i]); - } - throw he; - } - } - - public static Type getPropertyType(ClassMetadata metaData, String name, Type defaultValue) { - try { - return metaData.getPropertyType(name); - } - catch (HibernateException he) { - if (name.equalsIgnoreCase(metaData.getIdentifierPropertyName())) return metaData.getIdentifierType(); - - String[] names = metaData.getPropertyNames(); - for (int i = 0; i < names.length; i++) { - if (names[i].equalsIgnoreCase(name)) return metaData.getPropertyType(names[i]); - } - return defaultValue; - } - } - - public static String validateColumnName(ClassMetadata metaData, String name) throws PageException { - String res = validateColumnName(metaData, name, null); - if (res != null) return res; - throw ExceptionUtil.createException((ORMSession) null, null, "invalid name, there is no property with name [" + name + "] in the entity [" + metaData.getEntityName() + "]", - "valid properties names are [" + CommonUtil.toList(metaData.getPropertyNames(), ", ") + "]"); - - } - - public static String validateColumnName(ClassMetadata metaData, String name, String defaultValue) { - Type type = metaData.getIdentifierType(); - // composite id - if (type.isComponentType()) { - String res = _validateColumnName(((ComponentType) type).getPropertyNames(), name); - if (res != null) return res; - } - // regular id - String id = metaData.getIdentifierPropertyName(); - if (id != null && name.equalsIgnoreCase(id)) return metaData.getIdentifierPropertyName(); - - String res = _validateColumnName(metaData.getPropertyNames(), name); - if (res != null) return res; - return defaultValue; - } - - private static String _validateColumnName(String[] names, String name) { - if (names == null) return null; - for (int i = 0; i < names.length; i++) { - if (names[i].equalsIgnoreCase(name)) return names[i]; - } - return null; - } - - // - - public static Property[] createPropertiesFromTable(DatasourceConnection dc, String tableName) { - Struct properties = CommonUtil.createStruct(); - try { - DatabaseMetaData md = dc.getConnection().getMetaData(); - String dbName = CFMLEngineFactory.getInstance().getDBUtil().getDatabaseName(dc); - Collection.Key name; - - // get all columns - ResultSet res = md.getColumns(dbName, null, tableName, null); - while (res.next()) { - name = CommonUtil.createKey(res.getString("COLUMN_NAME")); - properties.setEL(name, CommonUtil.createProperty(name.getString(), res.getString("TYPE_NAME"))); - } - - // ids - res = md.getPrimaryKeys(null, null, tableName); - Property p; - while (res.next()) { - name = CommonUtil.createKey(res.getString("COLUMN_NAME")); - p = (Property) properties.get(name, null); - if (p != null) p.getDynamicAttributes().setEL(CommonUtil.FIELDTYPE, "id"); - } - - // MUST foreign-key relation - - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - return new Property[0]; - } - - Iterator it = properties.valueIterator(); - Property[] rtn = new Property[properties.size()]; - for (int i = 0; i < rtn.length; i++) { - rtn[i] = (Property) it.next(); - } - - return rtn; - } - - public static Property[] getProperties(Component component, int fieldType, Property[] defaultValue) { - Property[] props = component.getProperties(true, false, false, false); - java.util.List rtn = new ArrayList(); - - if (props != null) { - for (int i = 0; i < props.length; i++) { - if (fieldType == getFieldType(props[i], FIELDTYPE_COLUMN)) rtn.add(props[i]); - } - } - return rtn.toArray(new Property[rtn.size()]); - } - - private static int getFieldType(Property property, int defaultValue) { - return getFieldType(CommonUtil.toString(property.getDynamicAttributes().get(CommonUtil.FIELDTYPE, null), null), defaultValue); - - } - - private static int getFieldType(String fieldType, int defaultValue) { - if (Util.isEmpty(fieldType, true)) return defaultValue; - fieldType = fieldType.trim().toLowerCase(); - - if ("id".equals(fieldType)) return FIELDTYPE_ID; - if ("column".equals(fieldType)) return FIELDTYPE_COLUMN; - if ("timestamp".equals(fieldType)) return FIELDTYPE_TIMESTAMP; - if ("relation".equals(fieldType)) return FIELDTYPE_RELATION; - if ("version".equals(fieldType)) return FIELDTYPE_VERSION; - if ("collection".equals(fieldType)) return FIELDTYPE_COLLECTION; - return defaultValue; - } - - public static String convertTableName(SessionFactoryData data, String tableName) throws PageException { - if (tableName == null) return null; - return data.getNamingStrategy().convertTableName(tableName); - } - - public static String convertColumnName(SessionFactoryData data, String columnName) throws PageException { - if (columnName == null) return null; - return data.getNamingStrategy().convertColumnName(columnName); - } - - public static boolean isEntity(ORMConfiguration ormConf, Component cfc, String cfcName, String name) { - if (!Util.isEmpty(cfcName)) { - if (cfc.equalTo(cfcName)) return true; - - if (cfcName.indexOf('.') != -1) { - Info info = CFMLEngineFactory.getInstance().getInfo(); - String[] extensions = HibernateUtil.merge(info.getCFMLComponentExtensions(), info.getLuceeComponentExtensions()); - String prefix = cfcName.replace('.', '/') + "."; - Resource[] locations = ormConf.getCfcLocations(); - Resource res; - for (int i = 0; i < locations.length; i++) { - for (int y = 0; y < extensions.length; y++) { - res = locations[i].getRealResource(prefix + extensions[y]); - if (res.equals(cfc.getPageSource().getResource())) return true; - } - } - return false; - } - } - - if (cfc.equalTo(name)) return true; - return name.equalsIgnoreCase(HibernateCaster.getEntityName(cfc)); - } - - public static String id(String id) { - return id.toLowerCase().trim(); - } - - public static Struct checkTable(DatasourceConnection dc, String tableName, SessionFactoryData data) throws PageException { - - try { - String dbName = CFMLEngineFactory.getInstance().getDBUtil().getDatabaseName(dc); - DatabaseMetaData md = dc.getConnection().getMetaData(); - Struct rows = checkTableFill(md, dbName, tableName); - if (rows.size() == 0) { - String tableName2 = checkTableValidate(md, dbName, tableName); - if (tableName2 != null) rows = checkTableFill(md, dbName, tableName2); - } - - if (rows.size() == 0) { - return null; - } - return rows; - } - catch (SQLException e) { - throw CommonUtil.toPageException(e); - } - } - - private static Struct checkTableFill(DatabaseMetaData md, String dbName, String tableName) throws SQLException, PageException { - Struct rows = CFMLEngineFactory.getInstance().getCreationUtil().createCastableStruct(tableName, Struct.TYPE_LINKED); - ResultSet columns = md.getColumns(dbName, null, tableName, null); - try { - String name; - Object nullable; - while (columns.next()) { - name = columns.getString("COLUMN_NAME"); - - nullable = columns.getObject("IS_NULLABLE"); - rows.setEL(CommonUtil.createKey(name), - new ColumnInfo(name, columns.getInt("DATA_TYPE"), columns.getString("TYPE_NAME"), columns.getInt("COLUMN_SIZE"), CommonUtil.toBooleanValue(nullable))); - } - } - finally { - CommonUtil.closeEL(columns); - } // Table susid defined for cfc susid does not exist. - - return rows; - } - - private static String checkTableValidate(DatabaseMetaData md, String dbName, String tableName) { - - ResultSet tables = null; - try { - tables = md.getTables(dbName, null, null, null); - String name; - while (tables.next()) { - name = tables.getString("TABLE_NAME"); - if (name.equalsIgnoreCase(tableName) && tables.getString("TABLE_TYPE").toUpperCase().indexOf("SYSTEM") == -1) return name; - } - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - finally { - CommonUtil.closeEL(tables); - } - return null; - - } - - public static HibernateORMEngine getORMEngine(PageContext pc) throws PageException { - if (pc == null) pc = CommonUtil.pc(); - Config config = pc.getConfig(); - return (HibernateORMEngine) config.getORMEngine(pc);// TODO add this method to the public interface - } - - public static HibernateORMSession getORMSession(PageContext pc, boolean create) throws PageException { - return (HibernateORMSession) pc.getORMSession(create);// TODO add this method to the public interface - } - - public static Property[] getIDProperties(Component c, boolean onlyPeristent, boolean includeBaseProperties) { - Property[] props = CommonUtil.getProperties(c, onlyPeristent, includeBaseProperties, false, false); - java.util.List tmp = new ArrayList(); - for (int i = 0; i < props.length; i++) { - if ("id".equalsIgnoreCase(CommonUtil.toString(props[i].getDynamicAttributes().get(CommonUtil.FIELDTYPE, null), ""))) tmp.add(props[i]); - } - return tmp.toArray(new Property[tmp.size()]); - } - - public static long getCompileTime(PageContext pc, PageSource ps) throws PageException { - return CFMLEngineFactory.getInstance().getTemplateUtil().getCompileTime(pc, ps); - } - - public static String removeExtension(String filename, String defaultValue) { - int index = filename.lastIndexOf('.'); - if (index == -1) return defaultValue; - return filename.substring(0, index); - } - - public static String[] merge(String[] arr1, String[] arr2) { - String[] ret = new String[arr1.length + arr2.length]; - for (int i = 0; i < arr1.length; i++) { - ret[i] = arr1[i]; - } - for (int i = 0; i < arr2.length; i++) { - ret[arr1.length + i] = arr2[i]; - } - return ret; - } - - public static boolean isApplicationName(PageContext pc, String name) { - String lcn = name.toLowerCase(); - if (!lcn.startsWith("application.")) return false; - - Info info = CFMLEngineFactory.getInstance().getInfo(); - String[] extensions = pc.getRequestDialect() == CFMLEngine.DIALECT_CFML ? info.getCFMLComponentExtensions() : info.getLuceeComponentExtensions(); - - for (int i = 0; i < extensions.length; i++) { - if (lcn.equalsIgnoreCase("application." + extensions[i])) return true; - } - return false; - } -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/ORMConfigurationUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/ORMConfigurationUtil.java deleted file mode 100644 index de972af8..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/ORMConfigurationUtil.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.lucee.extension.orm.hibernate; - -import java.lang.reflect.Method; - -import lucee.commons.io.res.Resource; -import lucee.loader.engine.CFMLEngine; -import lucee.loader.engine.CFMLEngineFactory; -import lucee.loader.util.Util; -import lucee.runtime.exp.PageException; -import lucee.runtime.orm.ORMConfiguration; - -// FUTURE update ORMConfiguration interface -public class ORMConfigurationUtil { - - private static final Class[] CLASS_STRING = new Class[] { String.class }; - private static Method getDbCreate; - private static Method getCatalog; - private static Method getSchema; - private static Method getSqlScript; - private static Method getDialect; - - public static int getDbCreate(ORMConfiguration conf, String datasourceName) throws PageException { - if (!Util.isEmpty(datasourceName) && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { - CFMLEngine eng = CFMLEngineFactory.getInstance(); - // Lucee >= 5.3.2.16 - try { - if (getDbCreate == null || getDbCreate.getDeclaringClass() != conf.getClass()) { - getDbCreate = conf.getClass().getMethod("getDbCreate", CLASS_STRING); - } - return eng.getCastUtil().toIntValue(getDbCreate.invoke(conf, new Object[] { datasourceName })); - } - catch (NoSuchMethodException e) { - // older Lucee version - } - catch (Exception e) { - throw eng.getCastUtil().toPageException(e); - } - } - return conf.getDbCreate(); - } - - public static String getCatalog(ORMConfiguration conf, String datasourceName) throws PageException { - if (!Util.isEmpty(datasourceName) && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { - CFMLEngine eng = CFMLEngineFactory.getInstance(); - // Lucee >= 5.3.2.16 - try { - if (getCatalog == null || getCatalog.getDeclaringClass() != conf.getClass()) { - getCatalog = conf.getClass().getMethod("getCatalog", CLASS_STRING); - } - return eng.getCastUtil().toString(getCatalog.invoke(conf, new Object[] { datasourceName })); - } - catch (NoSuchMethodException e) { - // older Lucee version - } - catch (Exception e) { - throw eng.getCastUtil().toPageException(e); - } - } - return conf.getCatalog(); - } - - public static String getSchema(ORMConfiguration conf, String datasourceName) throws PageException { - if (!Util.isEmpty(datasourceName) && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { - CFMLEngine eng = CFMLEngineFactory.getInstance(); - // Lucee >= 5.3.2.16 - try { - if (getSchema == null || getSchema.getDeclaringClass() != conf.getClass()) { - getSchema = conf.getClass().getMethod("getSchema", CLASS_STRING); - } - return eng.getCastUtil().toString(getSchema.invoke(conf, new Object[] { datasourceName })); - } - catch (NoSuchMethodException e) { - // older Lucee version - } - catch (Exception e) { - throw eng.getCastUtil().toPageException(e); - } - } - return conf.getSchema(); - } - - public static String getDialect(ORMConfiguration conf, String datasourceName) throws PageException { - if (!Util.isEmpty(datasourceName) && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { - CFMLEngine eng = CFMLEngineFactory.getInstance(); - // Lucee >= 5.3.2.16 - try { - if (getDialect == null || getDialect.getDeclaringClass() != conf.getClass()) { - getDialect = conf.getClass().getMethod("getDialect", CLASS_STRING); - } - return eng.getCastUtil().toString(getDialect.invoke(conf, new Object[] { datasourceName })); - } - catch (NoSuchMethodException e) { - // older Lucee version - } - catch (Exception e) { - throw eng.getCastUtil().toPageException(e); - } - } - return conf.getDialect(); - } - - public static Resource getSqlScript(ORMConfiguration conf, String datasourceName) throws PageException { - if (!Util.isEmpty(datasourceName) && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { - CFMLEngine eng = CFMLEngineFactory.getInstance(); - // Lucee >= 5.3.2.16 - try { - if (getSqlScript == null || getSqlScript.getDeclaringClass() != conf.getClass()) { - getSqlScript = conf.getClass().getMethod("getSqlScript", CLASS_STRING); - } - return (Resource) getSqlScript.invoke(conf, new Object[] { datasourceName }); - } - catch (NoSuchMethodException e) { - // older Lucee version - } - catch (Exception e) { - throw eng.getCastUtil().toPageException(e); - } - } - return conf.getSqlScript(); - } - - public static void dump(ORMConfiguration ormConf, String name) throws PageException { - - System.err.println("---------------- " + name + " ---------------------"); - System.err.println("catalog: " + getCatalog(ormConf, name)); - System.err.println("dialect: " + getDialect(ormConf, name)); - System.err.println("schema: " + getSchema(ormConf, name)); - System.err.println("DbCreate: " + getDbCreate(ormConf, name)); - System.err.println("SqlScript: " + getSqlScript(ormConf, name)); - - name = "susi"; - - System.err.println("---------------- " + name + " ---------------------"); - System.err.println("catalog: " + getCatalog(ormConf, name)); - System.err.println("dialect: " + getDialect(ormConf, name)); - System.err.println("schema: " + getSchema(ormConf, name)); - System.err.println("DbCreate: " + getDbCreate(ormConf, name)); - System.err.println("SqlScript: " + getSqlScript(ormConf, name)); - - } - -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/SessionFactoryData.java b/source/java/src/org/lucee/extension/orm/hibernate/SessionFactoryData.java index fa6fd906..0f359a66 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/SessionFactoryData.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/SessionFactoryData.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; +import org.hibernate.cfg.Configuration; import org.hibernate.SessionFactory; import org.hibernate.engine.query.spi.QueryPlanCache; import org.hibernate.internal.SessionFactoryImpl; @@ -16,6 +17,10 @@ import org.lucee.extension.orm.hibernate.naming.CFCNamingStrategy; import org.lucee.extension.orm.hibernate.naming.DefaultNamingStrategy; import org.lucee.extension.orm.hibernate.naming.SmartNamingStrategy; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.ConfigurationBuilder; +import org.lucee.extension.orm.hibernate.util.ExceptionUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; import lucee.commons.io.log.Log; import lucee.loader.engine.CFMLEngineFactory; @@ -34,298 +39,347 @@ public class SessionFactoryData { - public List tmpList; - - private final Map sources = new HashMap(); - private final Map> cfcs = new HashMap>(); - private final Map configurations = new HashMap(); - private final Map factories = new HashMap(); - private final Map queryPlanCaches = new HashMap(); - - private final ORMConfiguration ormConf; - private NamingStrategy namingStrategy; - private final HibernateORMEngine engine; - private Struct tableInfo = CommonUtil.createStruct(); - private String cfcNamingStrategy; - - private EventListenerIntegrator eventListenerIntegrator = new EventListenerIntegrator(); - - public SessionFactoryData(HibernateORMEngine engine, ORMConfiguration ormConf) { - this.engine = engine; - this.ormConf = ormConf; - } - - public ORMConfiguration getORMConfiguration() { - return ormConf; - } - - public HibernateORMEngine getEngine() { - return engine; - } - - public QueryPlanCache getQueryPlanCache(Key datasSourceName) { - QueryPlanCache qpc = queryPlanCaches.get(datasSourceName); - if (qpc == null) { - qpc = ((SessionFactoryImpl) this.getFactory(datasSourceName)).getQueryPlanCache(); - queryPlanCaches.put(datasSourceName, qpc); - } - return qpc; - } - - public NamingStrategy getNamingStrategy() throws PageException { - if (namingStrategy == null) { - String strNamingStrategy = ormConf.namingStrategy(); - if (Util.isEmpty(strNamingStrategy, true)) { - namingStrategy = DefaultNamingStrategy.INSTANCE; - } - else { - strNamingStrategy = strNamingStrategy.trim(); - if ("default".equalsIgnoreCase(strNamingStrategy)) namingStrategy = DefaultNamingStrategy.INSTANCE; - else if ("smart".equalsIgnoreCase(strNamingStrategy)) namingStrategy = SmartNamingStrategy.INSTANCE; - else { - CFCNamingStrategy cfcNS = new CFCNamingStrategy(cfcNamingStrategy == null ? strNamingStrategy : cfcNamingStrategy); - cfcNamingStrategy = cfcNS.getComponent().getPageSource().getComponentName(); - namingStrategy = cfcNS; - - } - } - } - if (namingStrategy == null) return DefaultNamingStrategy.INSTANCE; - return namingStrategy; - } - - public CFCInfo checkExistent(PageContext pc, Component cfc) throws PageException { - CFCInfo info = getCFC(HibernateCaster.getEntityName(cfc), null); - if (info != null) return info; - - throw ExceptionUtil.createException(this, null, "there is no mapping definition for component [" + cfc.getAbsName() + "]", ""); - } - - public List getEntityNames() { - Iterator> it = cfcs.values().iterator(); - List names = new ArrayList(); - Iterator _it; - while (it.hasNext()) { - _it = it.next().values().iterator(); - while (_it.hasNext()) { - names.add(HibernateCaster.getEntityName(_it.next().getCFC())); - } - } - return names; - } - - public Component getEntityByEntityName(String entityName, boolean unique) throws PageException { - Component cfc; - - // first check cfcs for this entity - CFCInfo info = getCFC(entityName, null); - if (info != null) { - cfc = info.getCFC(); - return unique ? (Component) cfc.duplicate(false) : cfc; - } - - // if parsing is in progress, the cfc can be found here - if (tmpList != null) { - Iterator it = tmpList.iterator(); - while (it.hasNext()) { - cfc = it.next(); - if (HibernateCaster.getEntityName(cfc).equalsIgnoreCase(entityName)) return unique ? (Component) cfc.duplicate(false) : cfc; - } - } - throw ExceptionUtil.createException((ORMSession) null, null, "entity [" + entityName + "] does not exist", ""); - } - - public Component getEntityByCFCName(String cfcName, boolean unique) throws PageException { - String name = cfcName; - int pointIndex = cfcName.lastIndexOf('.'); - if (pointIndex != -1) { - name = cfcName.substring(pointIndex + 1); - } - else cfcName = null; - - Component cfc; - List names = new ArrayList(); - - List list = tmpList; - if (list != null) { - int index = 0; - Iterator it2 = list.iterator(); - while (it2.hasNext()) { - cfc = it2.next(); - names.add(cfc.getName()); - if (HibernateUtil.isEntity(ormConf, cfc, cfcName, name)) // if(cfc.equalTo(name)) - return unique ? (Component) cfc.duplicate(false) : cfc; - } - } - else { - // search cfcs - Iterator> it = cfcs.values().iterator(); - Map _cfcs; - while (it.hasNext()) { - _cfcs = it.next(); - Iterator _it = _cfcs.values().iterator(); - while (_it.hasNext()) { - cfc = _it.next().getCFC(); - names.add(cfc.getName()); - if (HibernateUtil.isEntity(ormConf, cfc, cfcName, name)) // if(cfc.instanceOf(name)) - return unique ? (Component) cfc.duplicate(false) : cfc; - } - } - } - - CFCInfo info = getCFC(name, null); - if (info != null) { - cfc = info.getCFC(); - return unique ? (Component) cfc.duplicate(false) : cfc; - } - - throw ExceptionUtil.createException((ORMSession) null, null, "entity [" + name + "] " + (Util.isEmpty(cfcName) ? "" : "with cfc name [" + cfcName + "] ") - + "does not exist, existing entities are [" + CFMLEngineFactory.getInstance().getListUtil().toList(names, ", ") + "]", ""); - - } - - // Datasource specific - public DataSourceConfig getConfiguration(DataSource ds) { - return configurations.get(CommonUtil.toKey(ds.getName())); - } - - public DataSourceConfig getConfiguration(Key key) { - return configurations.get(key); - } - - public void setConfiguration(Log log, String mappings, DataSource ds, String user, String pass, String applicationContextName) throws PageException, SQLException, IOException { - configurations.put(CommonUtil.toKey(ds.getName()), - new DataSourceConfig(ds, HibernateSessionFactory.createConfiguration(log, mappings, ds, user, pass, this, applicationContextName))); - } - - public SessionFactory buildSessionFactory(Key datasSourceName) { - // Key key=eng.getCreationUtil().createKey(ds.getName()); - DataSourceConfig dsc = getConfiguration(datasSourceName); - if (dsc == null) throw new RuntimeException("cannot build factory because there is no configuration"); // this should never - // happen - - Thread thread = Thread.currentThread(); - ClassLoader old = thread.getContextClassLoader(); - SessionFactory sf; - try { - // use the core classloader - thread.setContextClassLoader(CFMLEngineFactory.getInstance().getClass().getClassLoader()); - sf = dsc.config.buildSessionFactory(); - } - finally { - // reset - thread.setContextClassLoader(old); - } - - factories.put(datasSourceName, sf); - return sf; - } - - public SessionFactory getFactory(Key datasSourceName) { - SessionFactory factory = factories.get(datasSourceName); - if (factory != null && factory.isClosed()) factory = null; - if (factory == null && getConfiguration(datasSourceName) != null) factory = buildSessionFactory(datasSourceName);// this should never be happen - return factory; - } - - public void reset() { - configurations.clear(); - Iterator it = factories.values().iterator(); - while (it.hasNext()) { - it.next().close(); - } - factories.clear(); - // namingStrategy=null; because the ormconf not change, this has not to change - // as well - tableInfo = CommonUtil.createStruct(); - } - - public Struct getTableInfo(DatasourceConnection dc, String tableName) throws PageException { - Collection.Key keyTableName = CommonUtil.createKey(tableName); - Struct columnsInfo = (Struct) tableInfo.get(keyTableName, null); - if (columnsInfo != null) return columnsInfo; - - columnsInfo = HibernateUtil.checkTable(dc, tableName, this); - tableInfo.setEL(keyTableName, columnsInfo); - return columnsInfo; - } - - // CFC methods - public void addCFC(String entityName, CFCInfo info) { - DataSource ds = info.getDataSource(); - Key dsn = CommonUtil.toKey(ds.getName()); - - Map map = cfcs.get(dsn); - if (map == null) cfcs.put(dsn, map = new HashMap()); - map.put(HibernateUtil.id(entityName), info); - sources.put(dsn, ds); - } - - CFCInfo getCFC(String entityName, CFCInfo defaultValue) { - Iterator> it = cfcs.values().iterator(); - while (it.hasNext()) { - CFCInfo info = it.next().get(HibernateUtil.id(entityName)); - if (info != null) return info; - } - return defaultValue; - } - - public Map> getCFCs() { - return cfcs; - } - - /* - * public Map getCFCs(DataSource ds) { Key - * key=eng.getCreationUtil().createKey(ds.getName()); Map rtn = cfcs.get(key); - * if(rtn==null) return new HashMap(); return rtn; } - */ - - public Map getCFCs(Key datasSourceName) { - Map rtn = cfcs.get(datasSourceName); - if (rtn == null) return new HashMap(); - return rtn; - } - - public void clearCFCs() { - cfcs.clear(); - } - - public int sizeCFCs() { - Iterator> it = cfcs.values().iterator(); - int size = 0; - while (it.hasNext()) { - size += it.next().size(); - } - return size; - } - - public DataSource[] getDataSources() { - return sources.values().toArray(new DataSource[sources.size()]); - } - - public void init() { - Iterator it = cfcs.keySet().iterator(); - while (it.hasNext()) { - getFactory(it.next()); - } - } - - public Map getFactories() { - Iterator it = cfcs.keySet().iterator(); - Map map = new HashMap(); - Key key; - while (it.hasNext()) { - key = it.next(); - map.put(key, getFactory(key)); - } - return map; - } - - public DataSource getDataSource(Key datasSourceName) { - return sources.get(datasSourceName); - } - - public EventListenerIntegrator getEventListenerIntegrator() { - return eventListenerIntegrator; - } + /** + * Use during ORM initialization for tracking the in-progress list of Component entities. + */ + public List tmpList; + + private final Map sources = new HashMap(); + private final Map> cfcs = new HashMap>(); + private final Map configurations = new HashMap(); + private final Map factories = new HashMap(); + private final Map queryPlanCaches = new HashMap(); + + private final ORMConfiguration ormConf; + private NamingStrategy namingStrategy; + private final HibernateORMEngine engine; + private Struct tableInfo = CommonUtil.createStruct(); + private String cfcNamingStrategy; + + private EventListenerIntegrator eventListenerIntegrator = new EventListenerIntegrator(); + + public SessionFactoryData(HibernateORMEngine engine, ORMConfiguration ormConf) { + this.engine = engine; + this.ormConf = ormConf; + } + + public ORMConfiguration getORMConfiguration() { + return ormConf; + } + + public HibernateORMEngine getEngine() { + return engine; + } + + public QueryPlanCache getQueryPlanCache(Key datasSourceName) { + QueryPlanCache qpc = queryPlanCaches.get(datasSourceName); + if (qpc == null) { + qpc = ((SessionFactoryImpl) this.getFactory(datasSourceName)).getQueryPlanCache(); + queryPlanCaches.put(datasSourceName, qpc); + } + return qpc; + } + + public NamingStrategy getNamingStrategy() throws PageException { + if (namingStrategy == null) { + String strNamingStrategy = ormConf.namingStrategy(); + if (Util.isEmpty(strNamingStrategy, true)) { + namingStrategy = DefaultNamingStrategy.INSTANCE; + } else { + strNamingStrategy = strNamingStrategy.trim(); + if ("default".equalsIgnoreCase(strNamingStrategy)) + namingStrategy = DefaultNamingStrategy.INSTANCE; + else if ("smart".equalsIgnoreCase(strNamingStrategy)) + namingStrategy = SmartNamingStrategy.INSTANCE; + else { + CFCNamingStrategy cfcNS = new CFCNamingStrategy( + cfcNamingStrategy == null ? strNamingStrategy : cfcNamingStrategy); + cfcNamingStrategy = cfcNS.getComponent().getPageSource().getComponentName(); + namingStrategy = cfcNS; + + } + } + } + if (namingStrategy == null) + return DefaultNamingStrategy.INSTANCE; + return namingStrategy; + } + + public CFCInfo checkExistent(PageContext pc, Component cfc) throws PageException { + CFCInfo info = getCFC(HibernateCaster.getEntityName(cfc), null); + if (info != null) + return info; + + throw ExceptionUtil.createException(this, null, + "there is no mapping definition for component [" + cfc.getAbsName() + "]", ""); + } + + public List getEntityNames() { + Iterator> it = cfcs.values().iterator(); + List names = new ArrayList(); + Iterator _it; + while (it.hasNext()) { + _it = it.next().values().iterator(); + while (_it.hasNext()) { + names.add(HibernateCaster.getEntityName(_it.next().getCFC())); + } + } + return names; + } + + public Component getEntityByEntityName(String entityName, boolean unique) throws PageException { + Component cfc; + + // first check cfcs for this entity + CFCInfo info = getCFC(entityName, null); + if (info != null) { + cfc = info.getCFC(); + return unique ? (Component) cfc.duplicate(false) : cfc; + } + + // if parsing is in progress, the cfc can be found here + if (hasTempCFCs()) { + Iterator it = tmpList.iterator(); + while (it.hasNext()) { + cfc = it.next(); + if (HibernateCaster.getEntityName(cfc).equalsIgnoreCase(entityName)) + return unique ? (Component) cfc.duplicate(false) : cfc; + } + } + throw ExceptionUtil.createException((ORMSession) null, null, "entity [" + entityName + "] does not exist", ""); + } + + public Component getEntityByCFCName(String cfcName, boolean unique) throws PageException { + String name = cfcName; + int pointIndex = cfcName.lastIndexOf('.'); + if (pointIndex != -1) { + name = cfcName.substring(pointIndex + 1); + } else + cfcName = null; + + Component cfc; + List names = new ArrayList(); + + if (hasTempCFCs()) { + Iterator it2 = tmpList.iterator(); + while (it2.hasNext()) { + cfc = it2.next(); + names.add(cfc.getName()); + if (HibernateUtil.isEntity(ormConf, cfc, cfcName, name)) // if(cfc.equalTo(name)) + return unique ? (Component) cfc.duplicate(false) : cfc; + } + } else { + // search cfcs + Iterator> it = cfcs.values().iterator(); + Map _cfcs; + while (it.hasNext()) { + _cfcs = it.next(); + Iterator _it = _cfcs.values().iterator(); + while (_it.hasNext()) { + cfc = _it.next().getCFC(); + names.add(cfc.getName()); + if (HibernateUtil.isEntity(ormConf, cfc, cfcName, name)) // if(cfc.instanceOf(name)) + return unique ? (Component) cfc.duplicate(false) : cfc; + } + } + } + + CFCInfo info = getCFC(name, null); + if (info != null) { + cfc = info.getCFC(); + return unique ? (Component) cfc.duplicate(false) : cfc; + } + + throw ExceptionUtil.createException((ORMSession) null, null, + "entity [" + name + "] " + (Util.isEmpty(cfcName) ? "" : "with cfc name [" + cfcName + "] ") + + "does not exist, existing entities are [" + + CFMLEngineFactory.getInstance().getListUtil().toList(names, ", ") + "]", + ""); + + } + + /** + * Get the Hibernate configuration for the given datasource name. + * + * @param ds + * Datasource object + * + * @return an instance of the {@link org.lucee.extension.orm.hibernate.jdbc.DataSourceConfig} object + */ + public DataSourceConfig getConfiguration(DataSource ds) { + return configurations.get(CommonUtil.toKey(ds.getName())); + } + + /** + * Get the Hibernate configuration for the given datasource name. + * + * @param key + * Datasource name, as a Lucee collection key + * + * @return an instance of the {@link org.lucee.extension.orm.hibernate.jdbc.DataSourceConfig} object + */ + public DataSourceConfig getConfiguration(Key key) { + return configurations.get(key); + } + + public void setConfiguration(Log log, String mappings, DataSource ds, String user, String pass, + String applicationContextName) throws PageException, SQLException, IOException { + + Configuration configuration = new ConfigurationBuilder().withDatasource(ds).withDatasourceCreds(user, pass) + .withORMConfig(getORMConfiguration()).withEventListener(getEventListenerIntegrator()) + .withApplicationName(applicationContextName).withXMLMappings(mappings).withLog(log).build(); + configurations.put(CommonUtil.toKey(ds.getName()), new DataSourceConfig(ds, configuration)); + HibernateSessionFactory.schemaExport(log, configuration, ds, user, pass, this); + } + + public SessionFactory buildSessionFactory(Key datasSourceName) { + // Key key=eng.getCreationUtil().createKey(ds.getName()); + DataSourceConfig dsc = getConfiguration(datasSourceName); + if (dsc == null) + throw new RuntimeException("cannot build factory because there is no configuration"); // this should never + // happen + + Thread thread = Thread.currentThread(); + ClassLoader old = thread.getContextClassLoader(); + SessionFactory sf; + try { + // use the core classloader + thread.setContextClassLoader(CFMLEngineFactory.getInstance().getClass().getClassLoader()); + sf = dsc.config.buildSessionFactory(); + } finally { + // reset + thread.setContextClassLoader(old); + } + + factories.put(datasSourceName, sf); + return sf; + } + + public SessionFactory getFactory(Key datasSourceName) { + SessionFactory factory = factories.get(datasSourceName); + if (factory != null && factory.isClosed()) + factory = null; + if (factory == null && getConfiguration(datasSourceName) != null) + factory = buildSessionFactory(datasSourceName);// this should never be happen + return factory; + } + + /** + * Reset the session factory and clear all known configuration. + */ + public void reset() { + configurations.clear(); + Iterator it = factories.values().iterator(); + while (it.hasNext()) { + it.next().close(); + } + factories.clear(); + // namingStrategy=null; because the ormconf not change, this has not to change + // as well + tableInfo = CommonUtil.createStruct(); + } + + public Struct getTableInfo(DatasourceConnection dc, String tableName) throws PageException { + Collection.Key keyTableName = CommonUtil.createKey(tableName); + Struct columnsInfo = (Struct) tableInfo.get(keyTableName, null); + if (columnsInfo != null) + return columnsInfo; + + columnsInfo = HibernateUtil.checkTable(dc, tableName, this); + tableInfo.setEL(keyTableName, columnsInfo); + return columnsInfo; + } + + // CFC methods + public void addCFC(String entityName, CFCInfo info) { + DataSource ds = info.getDataSource(); + Key dsn = CommonUtil.toKey(ds.getName()); + + Map map = cfcs.get(dsn); + if (map == null) + cfcs.put(dsn, map = new HashMap()); + map.put(HibernateUtil.id(entityName), info); + sources.put(dsn, ds); + } + + CFCInfo getCFC(String entityName, CFCInfo defaultValue) { + Iterator> it = cfcs.values().iterator(); + while (it.hasNext()) { + CFCInfo info = it.next().get(HibernateUtil.id(entityName)); + if (info != null) + return info; + } + return defaultValue; + } + + public Map> getCFCs() { + return cfcs; + } + + /* + * public Map getCFCs(DataSource ds) { Key key=eng.getCreationUtil().createKey(ds.getName()); + * Map rtn = cfcs.get(key); if(rtn==null) return new HashMap(); return rtn; } + */ + + public Map getCFCs(Key datasSourceName) { + Map rtn = cfcs.get(datasSourceName); + if (rtn == null) + return new HashMap(); + return rtn; + } + + public void clearCFCs() { + cfcs.clear(); + } + + public int sizeCFCs() { + Iterator> it = cfcs.values().iterator(); + int size = 0; + while (it.hasNext()) { + size += it.next().size(); + } + return size; + } + + public DataSource[] getDataSources() { + return sources.values().toArray(new DataSource[sources.size()]); + } + + /** + * Call all SessionFactory objects to ensure they're all built + */ + public void init() { + Iterator it = cfcs.keySet().iterator(); + while (it.hasNext()) { + getFactory(it.next()); + } + } + + public Map getFactories() { + Iterator it = cfcs.keySet().iterator(); + Map map = new HashMap(); + Key key; + while (it.hasNext()) { + key = it.next(); + map.put(key, getFactory(key)); + } + return map; + } + + public DataSource getDataSource(Key datasSourceName) { + return sources.get(datasSourceName); + } + + public EventListenerIntegrator getEventListenerIntegrator() { + return eventListenerIntegrator; + } + + /** + * See if we have loaded entities. (ORM-ish CFML Components) + * + * @return True if entity list is not null and not empty. + */ + public boolean hasTempCFCs() { + return tmpList != null && !tmpList.isEmpty(); + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/event/EVComponent.java b/source/java/src/org/lucee/extension/orm/hibernate/event/EVComponent.java deleted file mode 100644 index a019e7b3..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/event/EVComponent.java +++ /dev/null @@ -1,209 +0,0 @@ -package org.lucee.extension.orm.hibernate.event; - -import org.hibernate.event.spi.AbstractEvent; -import org.hibernate.event.spi.AutoFlushEvent; -import org.hibernate.event.spi.ClearEvent; -import org.hibernate.event.spi.DeleteEvent; -import org.hibernate.event.spi.DirtyCheckEvent; -import org.hibernate.event.spi.EvictEvent; -import org.hibernate.event.spi.FlushEvent; -import org.hibernate.event.spi.PostDeleteEvent; -import org.hibernate.event.spi.PostInsertEvent; -import org.hibernate.event.spi.PostLoadEvent; -import org.hibernate.event.spi.PostUpdateEvent; -import org.hibernate.event.spi.PreDeleteEvent; -import org.hibernate.event.spi.PreInsertEvent; -import org.hibernate.event.spi.PreLoadEvent; -import org.hibernate.event.spi.PreUpdateEvent; -import org.lucee.extension.orm.hibernate.CommonUtil; - -import lucee.loader.engine.CFMLEngine; -import lucee.loader.engine.CFMLEngineFactory; -import lucee.runtime.Component; -import lucee.runtime.PageContext; -import lucee.runtime.exp.PageException; -import lucee.runtime.type.Collection; -import lucee.runtime.type.Collection.Key; -import lucee.runtime.type.Struct; -import lucee.runtime.type.UDF; - -public class EVComponent { - - final private Component comp; - final private boolean hasPreInsert; - final private boolean hasPostInsert; - final private boolean hasPreDelete; - final private boolean hasPostDelete; - final private boolean hasPreUpdate; - final private boolean hasPostUpdate; - final private boolean hasPreLoad; - final private boolean hasPostLoad; - final private boolean hasFlush; - final private boolean hasAutoFlush; - final private boolean hasClear; - final private boolean hasDelete; - final private boolean hasDirtyCheck; - final private boolean hasEvict; - - public static EVComponent newInstance(Component comp) { - boolean hasPreInsert = hasEventType(comp, CommonUtil.PRE_INSERT); - boolean hasPostInsert = hasEventType(comp, CommonUtil.POST_INSERT); - boolean hasPreDelete = hasEventType(comp, CommonUtil.PRE_DELETE); - boolean hasPostDelete = hasEventType(comp, CommonUtil.POST_DELETE); - boolean hasPreUpdate = hasEventType(comp, CommonUtil.PRE_UPDATE); - boolean hasPostUpdate = hasEventType(comp, CommonUtil.POST_UPDATE); - boolean hasPreLoad = hasEventType(comp, CommonUtil.PRE_LOAD); - boolean hasPostLoad = hasEventType(comp, CommonUtil.POST_LOAD); - boolean hasFlush = hasEventType(comp, CommonUtil.ON_FLUSH); - boolean hasAutoFlush = hasEventType(comp, CommonUtil.ON_AUTO_FLUSH); - boolean hasClear = hasEventType(comp, CommonUtil.ON_CLEAR); - boolean hasDelete = hasEventType(comp, CommonUtil.ON_DELETE); - boolean hasDirtyCheck = hasEventType(comp, CommonUtil.ON_DIRTY_CHECK); - boolean hasEvict = hasEventType(comp, CommonUtil.ON_EVICT); - - if (!hasPreInsert && !hasPostInsert && !hasPreDelete && !hasPostDelete && !hasPreUpdate && !hasPostUpdate && !hasPreLoad && !hasPostLoad && !hasFlush && !hasAutoFlush - && !hasClear && !hasDelete && !hasDirtyCheck && !hasEvict) - return null; - - return new EVComponent(comp, hasPreInsert, hasPostInsert, hasPreDelete, hasPostDelete, hasPreUpdate, hasPostUpdate, hasPreLoad, hasPostLoad, hasFlush, hasAutoFlush, - hasClear, hasDelete, hasDirtyCheck, hasEvict); - } - - private EVComponent(Component comp, boolean hasPreInsert, boolean hasPostInsert, boolean hasPreDelete, boolean hasPostDelete, boolean hasPreUpdate, boolean hasPostUpdate, - boolean hasPreLoad, boolean hasPostLoad, boolean hasFlush, boolean hasAutoFlush, boolean hasClear, boolean hasDelete, boolean hasDirtyCheck, boolean hasEvict) { - this.comp = comp; - this.hasPreInsert = hasPreInsert; - this.hasPostInsert = hasPostInsert; - this.hasPreDelete = hasPreDelete; - this.hasPostDelete = hasPostDelete; - this.hasPreUpdate = hasPreUpdate; - this.hasPostUpdate = hasPostUpdate; - this.hasPreLoad = hasPreLoad; - this.hasPostLoad = hasPostLoad; - this.hasFlush = hasFlush; - this.hasAutoFlush = hasAutoFlush; - this.hasClear = hasClear; - this.hasDelete = hasDelete; - this.hasDirtyCheck = hasDirtyCheck; - this.hasEvict = hasEvict; - } - - public void onPreInsert(Component caller, PreInsertEvent event) { - if (hasPreInsert) invoke(caller, CommonUtil.PRE_INSERT, event.getEntity(), event, null); - } - - public void onPostInsert(Component caller, PostInsertEvent event) { - if (hasPostInsert) invoke(caller, CommonUtil.POST_INSERT, event.getEntity(), event, null); - } - - public void onPreDelete(Component caller, PreDeleteEvent event) { - if (hasPreDelete) invoke(caller, CommonUtil.PRE_DELETE, event.getEntity(), event, null); - } - - public void onPostDelete(Component caller, PostDeleteEvent event) { - if (hasPostDelete) invoke(caller, CommonUtil.POST_DELETE, event.getEntity(), event, null); - } - - public void onPreUpdate(Component caller, PreUpdateEvent event) { - if (!hasPreUpdate) return; - - Struct oldData = CommonUtil.createStruct(); - String[] properties = event.getPersister().getPropertyNames(); - Object[] data = event.getOldState(); - - if (data != null && properties != null && data.length == properties.length) { - for (int i = 0; i < data.length; i++) { - oldData.setEL(CommonUtil.createKey(properties[i]), data[i]); - } - } - invoke(caller, CommonUtil.PRE_UPDATE, event.getEntity(), event, oldData); - - } - - public void onPostUpdate(Component caller, PostUpdateEvent event) { - if (hasPostUpdate) invoke(caller, CommonUtil.POST_UPDATE, event.getEntity(), event, null); - } - - public void onPreLoad(Component caller, PreLoadEvent event) { - if (hasPreLoad) invoke(caller, CommonUtil.PRE_LOAD, event.getEntity(), event, null); - - } - - public void onPostLoad(Component caller, PostLoadEvent event) { - if (hasPostLoad) invoke(caller, CommonUtil.POST_LOAD, event.getEntity(), event, null); - } - - public void onFlush(FlushEvent event) { - if (hasFlush) invoke(null, CommonUtil.ON_FLUSH, null, event, null); - } - - public void onAutoFlush(AutoFlushEvent event) { - if (hasAutoFlush) invoke(null, CommonUtil.ON_AUTO_FLUSH, null, event, null); - } - - public void onClear(ClearEvent event) { - if (hasClear) invoke(null, CommonUtil.ON_CLEAR, null, event, null); - } - - public void onDelete(DeleteEvent event) { - if (hasDelete) invoke(null, CommonUtil.ON_DELETE, null, event, null); - } - - public void onDirtyCheck(DirtyCheckEvent event) { - if (hasDirtyCheck) invoke(null, CommonUtil.ON_DIRTY_CHECK, null, event, null); - } - - public void onEvict(EvictEvent event) { - if (hasEvict) invoke(null, CommonUtil.ON_EVICT, null, event, null); - } - - public Component getComp() { - return comp; - } - - public void invoke(Component caller, Key name, Object obj, AbstractEvent event, Struct data) { - _invoke(caller == null ? comp : caller, name, data, caller == null ? obj : null, event); - } - - private static void _invoke(Component cfc, Key name, Struct data, Object arg, AbstractEvent event) { - if (cfc == null) return; - CFMLEngine engine = CFMLEngineFactory.getInstance(); - try { - PageContext pc = engine.getThreadPageContext(); - Object[] args; - if (data == null) { - args = arg != null ? new Object[] { arg, event } : new Object[] { event }; - } - else { - args = arg != null ? new Object[] { arg, data, event } : new Object[] { data, event }; - } - cfc.call(pc, name, args); - } - catch (PageException pe) { - throw engine.getCastUtil().toPageRuntimeException(pe); - } - } - - public static void invoke(Key name, Component cfc, Struct data, Object arg) { - if (cfc == null) return; - CFMLEngine engine = CFMLEngineFactory.getInstance(); - try { - PageContext pc = engine.getThreadPageContext(); - Object[] args; - if (data == null) { - args = arg != null ? new Object[] { arg } : new Object[] {}; - } - else { - args = arg != null ? new Object[] { arg, data } : new Object[] { data }; - } - cfc.call(pc, name, args); - } - catch (PageException pe) { - throw engine.getCastUtil().toPageRuntimeException(pe); - } - } - - public static boolean hasEventType(Component comp, Collection.Key eventType) { - return comp.get(eventType, null) instanceof UDF; - } -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/event/EventListenerIntegrator.java b/source/java/src/org/lucee/extension/orm/hibernate/event/EventListenerIntegrator.java index cfc9940d..3797bfbb 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/event/EventListenerIntegrator.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/event/EventListenerIntegrator.java @@ -8,6 +8,7 @@ import org.hibernate.boot.Metadata; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.AbstractEvent; import org.hibernate.event.spi.AutoFlushEvent; import org.hibernate.event.spi.AutoFlushEventListener; import org.hibernate.event.spi.ClearEvent; @@ -23,10 +24,14 @@ import org.hibernate.event.spi.FlushEventListener; import org.hibernate.event.spi.PostDeleteEvent; import org.hibernate.event.spi.PostDeleteEventListener; +import org.hibernate.event.spi.PreInsertEvent; +import org.hibernate.event.spi.PreInsertEventListener; import org.hibernate.event.spi.PostInsertEvent; import org.hibernate.event.spi.PostInsertEventListener; import org.hibernate.event.spi.PostLoadEvent; import org.hibernate.event.spi.PostLoadEventListener; +import org.hibernate.event.spi.PreUpdateEvent; +import org.hibernate.event.spi.PreUpdateEventListener; import org.hibernate.event.spi.PostUpdateEvent; import org.hibernate.event.spi.PostUpdateEventListener; import org.hibernate.event.spi.PreDeleteEvent; @@ -36,156 +41,347 @@ import org.hibernate.integrator.spi.Integrator; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.spi.SessionFactoryServiceRegistry; -import org.lucee.extension.orm.hibernate.CommonUtil; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import lucee.loader.engine.CFMLEngine; +import lucee.loader.engine.CFMLEngineFactory; import lucee.runtime.Component; - -public class EventListenerIntegrator implements Integrator, PostInsertEventListener, PreDeleteEventListener, PostDeleteEventListener, PostUpdateEventListener, PreLoadEventListener, - PostLoadEventListener, FlushEventListener, AutoFlushEventListener, ClearEventListener, DeleteEventListener, DirtyCheckEventListener, EvictEventListener { - - private static final long serialVersionUID = -5954121166467541422L; - - private EVComponent allEventListener; - private Map eventListeners = new ConcurrentHashMap<>(); - - @Override - public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { - EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); - - eventListenerRegistry.getEventListenerGroup(EventType.POST_INSERT).appendListener(this); - eventListenerRegistry.getEventListenerGroup(EventType.PRE_DELETE).appendListener(this); - eventListenerRegistry.getEventListenerGroup(EventType.POST_DELETE).appendListener(this); - eventListenerRegistry.getEventListenerGroup(EventType.POST_UPDATE).appendListener(this); - eventListenerRegistry.getEventListenerGroup(EventType.PRE_LOAD).appendListener(this); - eventListenerRegistry.getEventListenerGroup(EventType.POST_LOAD).appendListener(this); - - } - - @Override - public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { - - } - - public void setAllEventListener(Component allEventListener) { - this.allEventListener = EVComponent.newInstance(allEventListener); - } - - public void setEventListene(Component cfc) { - EVComponent evc = EVComponent.newInstance(cfc); - if (evc != null) this.eventListeners.put(cfc.getAbsName(), evc);// TODO correct string? - } - - @Override - public boolean requiresPostCommitHanding(EntityPersister arg0) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void onPostInsert(PostInsertEvent event) { - if (allEventListener != null) allEventListener.onPostInsert(null, event); - EVC2Caller evcc = getEventListener(event.getEntity()); - if (evcc != null) evcc.evc.onPostInsert(evcc.caller, event); - } - - // PreDeleteEventListener - @Override - public boolean onPreDelete(PreDeleteEvent event) { - if (allEventListener != null) allEventListener.onPreDelete(null, event); - EVC2Caller evcc = getEventListener(event.getEntity()); - if (evcc != null) evcc.evc.onPreDelete(evcc.caller, event); - return false; - } - - // PostDeleteEventListener - @Override - public void onPostDelete(PostDeleteEvent event) { - if (allEventListener != null) allEventListener.onPostDelete(null, event); - EVC2Caller evcc = getEventListener(event.getEntity()); - if (evcc != null) evcc.evc.onPostDelete(evcc.caller, event); - } - - // PostUpdateEventListener - @Override - public void onPostUpdate(PostUpdateEvent event) { - if (allEventListener != null) allEventListener.onPostUpdate(null, event); - EVC2Caller evcc = getEventListener(event.getEntity()); - if (evcc != null) evcc.evc.onPostUpdate(evcc.caller, event); - } - - // PreLoadEventListener - @Override - public void onPreLoad(PreLoadEvent event) { - if (allEventListener != null) allEventListener.onPreLoad(null, event); - EVC2Caller evcc = getEventListener(event.getEntity()); - if (evcc != null) evcc.evc.onPreLoad(evcc.caller, event); - } - - // PostLoadEventListener - @Override - public void onPostLoad(PostLoadEvent event) { - if (allEventListener != null) allEventListener.onPostLoad(null, event); - EVC2Caller evcc = getEventListener(event.getEntity()); - if (evcc != null) evcc.evc.onPostLoad(evcc.caller, event); - } - - @Override - public void onFlush(FlushEvent event) throws HibernateException { - if (allEventListener != null) allEventListener.onFlush(event); - } - - @Override - public void onAutoFlush(AutoFlushEvent event) throws HibernateException { - if (allEventListener != null) allEventListener.onAutoFlush(event); - } - - @Override - public void onClear(ClearEvent event) { - if (allEventListener != null) allEventListener.onClear(event); - } - - @Override - public void onDelete(DeleteEvent event) throws HibernateException { - if (allEventListener != null) allEventListener.onDelete(event); - } - - @Override - public void onDelete(DeleteEvent event, Set set) throws HibernateException { - if (allEventListener != null) allEventListener.onDelete(event); - } - - @Override - public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException { - if (allEventListener != null) allEventListener.onDirtyCheck(event); - } - - @Override - public void onEvict(EvictEvent event) throws HibernateException { - if (allEventListener != null) allEventListener.onEvict(event); - } - - private EVC2Caller getEventListener(Object entity) { - if (eventListeners.size() == 0) return null; - Component caller = CommonUtil.toComponent(entity, null); - if (caller != null) { - EVComponent evc = eventListeners.get(caller.getAbsName()); - if (evc != null) return new EVC2Caller(evc, caller); - } - return null; - } - - private static class EVC2Caller { - private EVComponent evc; - private Component caller; - - public EVC2Caller(EVComponent evc, Component caller) { - this.evc = evc; - this.caller = caller; - } - - } - - public EVComponent getAllEventListener() { - return allEventListener; - } +import lucee.runtime.PageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.type.Collection; +import lucee.runtime.type.Collection.Key; +import lucee.runtime.type.Struct; +import lucee.runtime.type.UDF; + +/** + * Integrate Hibernate events with the EventHandler and component listener UDFs. + * + * For example, a postInsert() method in a User entity will be invoked prior to the entity's + * insertion into the database. This same method will also be invoked on the EventHandler component, if configured. + */ +public class EventListenerIntegrator implements Integrator, PreInsertEventListener, PostInsertEventListener, + PreDeleteEventListener, PostDeleteEventListener, DeleteEventListener, PreUpdateEventListener, + PostUpdateEventListener, PreLoadEventListener, PostLoadEventListener, FlushEventListener, + AutoFlushEventListener, ClearEventListener, DirtyCheckEventListener, EvictEventListener { + + private static final long serialVersionUID = -5954121166467541422L; + + /** + * The EventHandler CFC defined in the application's `this.ormSettings.eventHandler`. + */ + private Component GlobalEventListener; + private Map eventListeners = new ConcurrentHashMap<>(); + + @Override + public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); + + eventListenerRegistry.prependListeners(EventType.PRE_INSERT, this); + eventListenerRegistry.prependListeners(EventType.POST_INSERT, this); + + eventListenerRegistry.prependListeners(EventType.PRE_DELETE, this); + eventListenerRegistry.prependListeners(EventType.POST_DELETE, this); + eventListenerRegistry.prependListeners(EventType.DELETE, this); + + eventListenerRegistry.prependListeners(EventType.PRE_UPDATE, this); + eventListenerRegistry.prependListeners(EventType.POST_UPDATE, this); + + eventListenerRegistry.prependListeners(EventType.PRE_LOAD, this); + eventListenerRegistry.prependListeners(EventType.POST_LOAD, this); + + eventListenerRegistry.prependListeners(EventType.AUTO_FLUSH, this); + eventListenerRegistry.prependListeners(EventType.FLUSH, this); + + eventListenerRegistry.prependListeners(EventType.EVICT, this); + eventListenerRegistry.prependListeners(EventType.CLEAR, this); + + eventListenerRegistry.prependListeners(EventType.DIRTY_CHECK, this); + } + + @Override + public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + + } + + /** + * Set the "Global" EventHandler to fire on all events in the application. + * + * @param GlobalEventListener + * Instantiated Lucee Component object. + */ + public void setGlobalEventListener(Component GlobalEventListener) { + this.GlobalEventListener = GlobalEventListener; + } + + /** + * Add this component to the list of listeners to be notified for an entity event. + *

+ * Note this listener will ONLY fire for events related to itself. i.e. Car.preInsert will be run for Car entity + * preInsert events - not for User entity preInsert events. + * + * @param cfc + * Instantiated Lucee Component object. + */ + public void appendEventListenerCFC(Component cfc) { + this.eventListeners.put(cfc.getAbsName(), cfc); + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister arg0) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean onPreInsert(PreInsertEvent event) { + Struct state = entityStateToStruct(event.getPersister().getPropertyNames(), event.getState()); + fireEventOnGlobalListener(CommonUtil.PRE_INSERT, event.getEntity(), event, state); + + // fire on entity + Component listener = getEventListener(event.getEntity()); + if (listener != null) { + fireEventOnEntityListener(listener, CommonUtil.PRE_INSERT, event, state); + } + + return false; + } + + @Override + public void onPostInsert(PostInsertEvent event) { + fireEventOnGlobalListener(CommonUtil.POST_INSERT, event.getEntity(), event, null); + + // fire on entity + Component listener = getEventListener(event.getEntity()); + if (listener != null) { + fireEventOnEntityListener(listener, CommonUtil.POST_INSERT, event, null); + } + } + + // PreDeleteEventListener + @Override + public boolean onPreDelete(PreDeleteEvent event) { + fireEventOnGlobalListener(CommonUtil.PRE_DELETE, event.getEntity(), event, null); + + Component listener = getEventListener(event.getEntity()); + if (listener != null) { + fireEventOnEntityListener(listener, CommonUtil.PRE_DELETE, event, null); + } + return false; + } + + // PostDeleteEventListener + @Override + public void onPostDelete(PostDeleteEvent event) { + fireEventOnGlobalListener(CommonUtil.POST_DELETE, event.getEntity(), event, null); + + Component listener = getEventListener(event.getEntity()); + if (listener != null) { + fireEventOnEntityListener(listener, CommonUtil.POST_DELETE, event, null); + } + } + + // PreUpdateEventListener + @Override + public boolean onPreUpdate(PreUpdateEvent event) { + Struct oldState = entityStateToStruct(event.getPersister().getPropertyNames(), event.getOldState()); + fireEventOnGlobalListener(CommonUtil.PRE_UPDATE, event.getEntity(), event, oldState); + + Component listener = getEventListener(event.getEntity()); + if (listener != null) { + fireEventOnEntityListener(listener, CommonUtil.PRE_UPDATE, event, oldState); + } + return false; + } + + // PostUpdateEventListener + @Override + public void onPostUpdate(PostUpdateEvent event) { + fireEventOnGlobalListener(CommonUtil.POST_UPDATE, event.getEntity(), event, null); + + Component listener = getEventListener(event.getEntity()); + if (listener != null) { + fireEventOnEntityListener(listener, CommonUtil.POST_UPDATE, event, null); + } + } + + // PreLoadEventListener + @Override + public void onPreLoad(PreLoadEvent event) { + fireEventOnGlobalListener(CommonUtil.PRE_LOAD, event.getEntity(), event, null); + + Component listener = getEventListener(event.getEntity()); + if (listener != null) { + fireEventOnEntityListener(listener, CommonUtil.PRE_LOAD, event, null); + } + } + + // PostLoadEventListener + @Override + public void onPostLoad(PostLoadEvent event) { + fireEventOnGlobalListener(CommonUtil.POST_LOAD, event.getEntity(), event, null); + + Component listener = getEventListener(event.getEntity()); + if (listener != null) { + fireEventOnEntityListener(listener, CommonUtil.POST_LOAD, event, null); + } + } + + @Override + public void onFlush(FlushEvent event) throws HibernateException { + // Sadly, the FlushEvent does not allow / provide a method to retrieve the entity. + Object entity = null; + fireEventOnGlobalListener(CommonUtil.ON_FLUSH, entity, event, null); + } + + @Override + public void onAutoFlush(AutoFlushEvent event) throws HibernateException { + // Sadly, the AutoFlushEvent does not allow / provide a method to retrieve the entity. + Object entity = null; + fireEventOnGlobalListener(CommonUtil.ON_AUTO_FLUSH, entity, event, null); + } + + @Override + public void onClear(ClearEvent event) { + // Sadly, the ClearEvent does not allow / provide a method to retrieve the entity. + Object entity = null; + fireEventOnGlobalListener(CommonUtil.ON_CLEAR, entity, event, null); + } + + @Override + public void onDelete(DeleteEvent event) throws HibernateException { + Object entity = event.getObject(); + fireEventOnGlobalListener(CommonUtil.ON_DELETE, entity, event, null); + } + + @Override + public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException { + Object entity = event.getObject(); + // TODO: handle transientEntities + fireEventOnGlobalListener(CommonUtil.ON_DELETE, entity, event, null); + } + + @Override + public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException { + // Sadly, the DirtyCheckEvent does not allow / provide a method to retrieve the entity. + Object entity = null; + fireEventOnGlobalListener(CommonUtil.ON_DIRTY_CHECK, entity, event, null); + } + + @Override + public void onEvict(EvictEvent event) throws HibernateException { + // Sadly, the EvictEvent does not allow / provide a method to retrieve the entity. + Object entity = null; + fireEventOnGlobalListener(CommonUtil.ON_EVICT, entity, event, null); + } + + /** + * Retrieve the configured "Global" event listener. + * + * i.e., the Component configured in `this.ormSettings.eventHandler`. + * + * @return The configured Component to use as this application's event handler. + */ + public Component getGlobalEventListener() { + return GlobalEventListener; + } + + /** + * Fire the event listener UDF on the configured global EventHandler listener. + *

+ * If no global event handler is configured, will exit. + * + * @param name + * event type name to fire, for example "preInsert" or "preDelete" + * @param entity + * the entity from event.getEntity() + * @param event + * the Hibernate event object. + * @param data + * A struct of data to pass to the event + */ + public void fireEventOnGlobalListener(Key name, Object entity, AbstractEvent event, Struct data) { + if (GlobalEventListener == null) { + return; + } + + _fireOnComponent(getGlobalEventListener(), name, entity, data, event); + } + + /** + * Fire the event listener UDF, if found, on the entity component + * + * @param listener + * the Lucee Component on which to fire this listener method + * @param name + * event type name to fire, for example "preInsert" or "preDelete" + * @param event + * the Hibernate event object. + * @param data + * A struct of data to pass to the event + */ + public void fireEventOnEntityListener(Component listener, Key name, AbstractEvent event, Struct data) { + _fireOnComponent(listener, name, data, event); + } + + /** + * See if the given component has a method matching the given name. + * + * @param comp + * Lucee Component to look on, for example events.EventHandler. + * @param methodName + * Method name to look for, for example "preInsert" + * + * @return true if method found + */ + public static boolean componentHasMethod(Component comp, Collection.Key methodName) { + return comp.get(methodName, null) instanceof UDF; + } + + private static void _fireOnComponent(Component cfc, Key name, Object... args) { + if (!componentHasMethod(cfc, name)) { + return; + } + CFMLEngine engine = CFMLEngineFactory.getInstance(); + try { + PageContext pc = engine.getThreadPageContext(); + cfc.call(pc, name, args); + } catch (PageException pe) { + throw engine.getCastUtil().toPageRuntimeException(pe); + } + } + + private Component getEventListener(Object entity) { + if (eventListeners.size() == 0) + return null; + Component caller = CommonUtil.toComponent(entity, null); + if (caller != null) { + Component eventListener = eventListeners.get(caller.getAbsName()); + if (eventListener != null) + return eventListener; + } + return null; + } + + /** + * Merge the provided arrays of properties and values into a CFML-friendly struct. + * + * @param properties + * Array of property names, usually retrieved from event.getPersister().getPropertyNames() + * @param values + * Array of property values, either retrieved from event.getPersister().getPropertyValues(), + * event.getState() or event.getOldState() + * + * @return A struct + */ + private static Struct entityStateToStruct(String[] properties, Object[] values) { + Struct entityState = CommonUtil.createStruct(); + + if (values != null && properties != null && values.length == properties.length) { + for (int i = 0; i < values.length; i++) { + entityState.setEL(CommonUtil.createKey(properties[i]), values[i]); + } + } + return entityState; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/event/InterceptorImpl.java b/source/java/src/org/lucee/extension/orm/hibernate/event/InterceptorImpl.java deleted file mode 100644 index 76784581..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/event/InterceptorImpl.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.lucee.extension.orm.hibernate.event; - -import java.io.Serializable; -import java.util.Iterator; - -import org.hibernate.CallbackException; -import org.hibernate.EmptyInterceptor; -import org.hibernate.EntityMode; -import org.hibernate.event.spi.AbstractEvent; -import org.hibernate.type.Type; -import org.lucee.extension.orm.hibernate.CommonUtil; -import org.lucee.extension.orm.hibernate.HibernateCaster; - -import lucee.runtime.Component; -import lucee.runtime.exp.PageException; -import lucee.runtime.type.Collection; -import lucee.runtime.type.Collection.Key; -import lucee.runtime.type.Struct; - -public class InterceptorImpl extends EmptyInterceptor { - - private static final long serialVersionUID = 7992972603422833660L; - - private final EVComponent listener; - private final boolean hasPreInsert; - private final boolean hasPreUpdate; - - public InterceptorImpl(EVComponent listener) { - this.listener = listener; - if (listener != null) { - Component cfc = listener.getComp(); - hasPreInsert = EVComponent.hasEventType(cfc, CommonUtil.PRE_INSERT); - hasPreUpdate = EVComponent.hasEventType(cfc, CommonUtil.PRE_UPDATE); - } - else { - hasPreInsert = false; - hasPreUpdate = false; - } - } - - @Override - public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { - ThreadLocalStatus.setit(true); - return on(entity, id, state, null, propertyNames, types, CommonUtil.PRE_INSERT, hasPreInsert); - // return super.onSave(entity, id, state, propertyNames, types); - } - - @Override - public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) { - if (ThreadLocalStatus.getit()) { - ThreadLocalStatus.setit(false); - return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types); - } - return on(entity, id, currentState, toStruct(propertyNames, previousState), propertyNames, types, CommonUtil.PRE_UPDATE, hasPreUpdate); - } - - public void invoke(Component caller, Key name, Object obj, AbstractEvent event, Struct data) { - } - - public static void _invoke(Component cfc, Key name, Struct data, Object arg, AbstractEvent event) { - } - - private boolean on(Object entity, Serializable id, Object[] state, Struct data, String[] propertyNames, Type[] types, Collection.Key eventType, boolean hasMethod) { - - Component cfc = CommonUtil.toComponent(entity, null); - if (cfc != null && EVComponent.hasEventType(cfc, eventType)) { - EVComponent.invoke(eventType, cfc, data, null); - // EVComponent.invoke(eventType, cfc, data, null); - } - if (hasMethod) EVComponent.invoke(eventType, listener.getComp(), data, entity); - - boolean rtn = false; - String prop; - Object before, current; - /* - * jira2049 ORMSession session = null; try { - * session=ORMUtil.getSession(ThreadLocalPageContext.get()); } catch (PageException pe) {} - */ - - for (int i = 0; i < propertyNames.length; i++) { - prop = propertyNames[i]; - before = state[i]; - current = CommonUtil.getPropertyValue(/* jira2049 session, */cfc, prop, null); - - if (before != current && (current == null || !CommonUtil.equalsComplexEL(before, current))) { - try { - state[i] = HibernateCaster.toSQL(types[i], current, null); - } - catch (PageException e) { - state[i] = current; - } - rtn = true; - } - } - return rtn; - } - - private static Struct toStruct(String propertyNames[], Object state[]) { - Struct sct = CommonUtil.createStruct(); - if (state != null && propertyNames != null) { - for (int i = 0; i < propertyNames.length; i++) { - sct.setEL(CommonUtil.createKey(propertyNames[i]), state[i]); - } - } - return sct; - } - - @Override - public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { - return super.onLoad(entity, id, state, propertyNames, types); - } - - @Override - public void preFlush(Iterator entities) { - super.preFlush(entities); - } - - @Override - public Object instantiate(String entityName, EntityMode entityMode, Serializable id) { - return super.instantiate(entityName, entityMode, id); - } - - @Override - public void onCollectionRecreate(Object collection, Serializable key) throws CallbackException { - super.onCollectionRecreate(collection, key); - } - - @Override - public void onCollectionRemove(Object collection, Serializable key) throws CallbackException { - super.onCollectionRemove(collection, key); - } - - @Override - public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException { - super.onCollectionUpdate(collection, key); - } - - @Override - public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { - super.onDelete(entity, id, state, propertyNames, types); - } - - @Override - public String onPrepareStatement(String sql) { - return super.onPrepareStatement(sql); - } - - private static class ThreadLocalStatus extends ThreadLocal { - - @Override - protected Object initialValue() { - return Boolean.FALSE; - } - - private static ThreadLocal insertDone = new ThreadLocal(); - - public static boolean getit() { - return insertDone.get(); - } - - public static void setit(boolean b) { - insertDone.set(b); - } - - /** - * release the pagecontext for the current thread - */ - public static void release() {// print.ds(Thread.currentThread().getName()); - insertDone.set(Boolean.FALSE); - } - - } -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/jdbc/ConnectionProviderImpl.java b/source/java/src/org/lucee/extension/orm/hibernate/jdbc/ConnectionProviderImpl.java index e2ec13ba..1e43a686 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/jdbc/ConnectionProviderImpl.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/jdbc/ConnectionProviderImpl.java @@ -4,7 +4,7 @@ import java.sql.SQLException; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; -import org.lucee.extension.orm.hibernate.CommonUtil; +import org.lucee.extension.orm.hibernate.util.CommonUtil; import lucee.loader.engine.CFMLEngine; import lucee.loader.engine.CFMLEngineFactory; @@ -15,67 +15,65 @@ public class ConnectionProviderImpl implements ConnectionProvider { - private static final long serialVersionUID = -4513189055112912809L; + private static final long serialVersionUID = -4513189055112912809L; - // private final DBUtil dbu; - private CFMLEngine engine; - private final DataSource ds; - private final String user; - private final String pass; + // private final DBUtil dbu; + private CFMLEngine engine; + private final DataSource ds; + private final String user; + private final String pass; - public ConnectionProviderImpl(DataSource ds, String user, String pass) { - engine = CFMLEngineFactory.getInstance(); - // dbu = engine.getDBUtil(); - this.ds = ds; - this.user = user; - this.pass = pass; - } + public ConnectionProviderImpl(DataSource ds, String user, String pass) { + engine = CFMLEngineFactory.getInstance(); + // dbu = engine.getDBUtil(); + this.ds = ds; + this.user = user; + this.pass = pass; + } - @Override - public Connection getConnection() throws SQLException { - PageContext pc = engine.getThreadPageContext(); + @Override + public Connection getConnection() throws SQLException { + PageContext pc = engine.getThreadPageContext(); - try { - return CommonUtil.getDatasourceConnection(pc, ds, user, pass, true); - // FUTURE we do not use because this is not managed the 4th argument is required return - // dbu.getDatasourceConnection(pc, ds, user, pass,true); - } - catch (PageException pe) { - throw engine.getExceptionUtil().createPageRuntimeException(pe); - } - } + try { + return CommonUtil.getDatasourceConnection(pc, ds, user, pass, true); + // FUTURE we do not use because this is not managed the 4th argument is required return + // dbu.getDatasourceConnection(pc, ds, user, pass,true); + } catch (PageException pe) { + throw engine.getExceptionUtil().createPageRuntimeException(pe); + } + } - @Override - public void closeConnection(Connection conn) throws SQLException { - PageContext pc = engine.getThreadPageContext(); - if (conn instanceof DatasourceConnection) { - try { - CommonUtil.releaseDatasourceConnection(pc, (DatasourceConnection) conn, true); - // FUTURE see comment above dbu.releaseDatasourceConnection(engine.getThreadConfig(), - // (DatasourceConnection) conn, false); - } - catch (PageException pe) { - throw engine.getExceptionUtil().createPageRuntimeException(pe); - } - } - } + @Override + public void closeConnection(Connection conn) throws SQLException { + PageContext pc = engine.getThreadPageContext(); + if (conn instanceof DatasourceConnection) { + try { + CommonUtil.releaseDatasourceConnection(pc, (DatasourceConnection) conn, true); + // FUTURE see comment above dbu.releaseDatasourceConnection(engine.getThreadConfig(), + // (DatasourceConnection) conn, false); + } catch (PageException pe) { + throw engine.getExceptionUtil().createPageRuntimeException(pe); + } + } + } - @Override - public boolean supportsAggressiveRelease() { - // nope - return false; - } + @Override + public boolean supportsAggressiveRelease() { + // nope + return false; + } - @Override - public boolean isUnwrappableAs(Class arg0) { - // TODO Auto-generated method stub - return false; - } + @Override + public boolean isUnwrappableAs(Class arg0) { + // TODO Auto-generated method stub + return false; + } - @Override - public T unwrap(Class arg0) { - // TODO Auto-generated method stub - return null; - } + @Override + public T unwrap(Class arg0) { + // TODO Auto-generated method stub + return null; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/jdbc/DataSourceConfig.java b/source/java/src/org/lucee/extension/orm/hibernate/jdbc/DataSourceConfig.java index 709331ff..a2ef8a22 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/jdbc/DataSourceConfig.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/jdbc/DataSourceConfig.java @@ -6,11 +6,11 @@ public class DataSourceConfig { - public final DataSource ds; - public final Configuration config; + public final DataSource ds; + public final Configuration config; - public DataSourceConfig(DataSource ds, Configuration config) { - this.ds = ds; - this.config = config; - } + public DataSourceConfig(DataSource ds, Configuration config) { + this.ds = ds; + this.config = config; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/naming/CFCNamingStrategy.java b/source/java/src/org/lucee/extension/orm/hibernate/naming/CFCNamingStrategy.java index 9d5c3c12..010fec22 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/naming/CFCNamingStrategy.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/naming/CFCNamingStrategy.java @@ -9,41 +9,42 @@ public class CFCNamingStrategy implements NamingStrategy { - Component cfc; - - public CFCNamingStrategy(String cfcName) throws PageException { - this.cfc = CFMLEngineFactory.getInstance().getThreadPageContext().loadComponent(cfcName); - } - - public Component getComponent() { - return cfc; - } - - @Override - public String convertTableName(String tableName) { - return call("getTableName", tableName); - } - - @Override - public String convertColumnName(String columnName) { - return call("getColumnName", columnName); - } - - private String call(String functionName, String name) { - Object res = cfc.get(functionName, null); - if (!(res instanceof UDF)) return name; - CFMLEngine engine = CFMLEngineFactory.getInstance(); - try { - return engine.getCastUtil().toString(cfc.call(engine.getThreadPageContext(), functionName, new Object[] { name })); - } - catch (PageException pe) { - throw engine.getCastUtil().toPageRuntimeException(pe); - } - } - - @Override - public String getType() { - return "cfc"; - } + Component cfc; + + public CFCNamingStrategy(String cfcName) throws PageException { + this.cfc = CFMLEngineFactory.getInstance().getThreadPageContext().loadComponent(cfcName); + } + + public Component getComponent() { + return cfc; + } + + @Override + public String convertTableName(String tableName) { + return call("getTableName", tableName); + } + + @Override + public String convertColumnName(String columnName) { + return call("getColumnName", columnName); + } + + private String call(String functionName, String name) { + Object res = cfc.get(functionName, null); + if (!(res instanceof UDF)) + return name; + CFMLEngine engine = CFMLEngineFactory.getInstance(); + try { + return engine.getCastUtil() + .toString(cfc.call(engine.getThreadPageContext(), functionName, new Object[] { name })); + } catch (PageException pe) { + throw engine.getCastUtil().toPageRuntimeException(pe); + } + } + + @Override + public String getType() { + return "cfc"; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/naming/DefaultNamingStrategy.java b/source/java/src/org/lucee/extension/orm/hibernate/naming/DefaultNamingStrategy.java index 3e8d9af0..79e08cfd 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/naming/DefaultNamingStrategy.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/naming/DefaultNamingStrategy.java @@ -4,21 +4,21 @@ public class DefaultNamingStrategy implements NamingStrategy { - public static final NamingStrategy INSTANCE = new DefaultNamingStrategy(); + public static final NamingStrategy INSTANCE = new DefaultNamingStrategy(); - @Override - public String convertTableName(String tableName) { - return tableName; - } + @Override + public String convertTableName(String tableName) { + return tableName; + } - @Override - public String convertColumnName(String columnName) { - return columnName; - } + @Override + public String convertColumnName(String columnName) { + return columnName; + } - @Override - public String getType() { - return "default"; - } + @Override + public String getType() { + return "default"; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/naming/SmartNamingStrategy.java b/source/java/src/org/lucee/extension/orm/hibernate/naming/SmartNamingStrategy.java index 1bad1e99..dd594e2e 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/naming/SmartNamingStrategy.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/naming/SmartNamingStrategy.java @@ -5,48 +5,49 @@ public class SmartNamingStrategy implements NamingStrategy { - public static final NamingStrategy INSTANCE = new SmartNamingStrategy(); - - @Override - public String convertTableName(String tableName) { - return translate(tableName); - } - - @Override - public String convertColumnName(String columnName) { - return translate(columnName); - } - - private static String translate(String name) { - if (Util.isEmpty(name)) return ""; - - int len = name.length(); - StringBuilder sb = new StringBuilder(); - char c, p, n; - for (int i = 0; i < len; i++) { - c = name.charAt(i); - if (i == 0 || i + 1 == len) { - sb.append(Character.toUpperCase(c)); - continue; - } - p = name.charAt(i - 1); - n = name.charAt(i + 1); - - // is Camel - if (Character.isLowerCase(p) && Character.isUpperCase(c) && Character.isLowerCase(n)) { - sb.append('_'); - sb.append(Character.toUpperCase(c)); - sb.append(Character.toUpperCase(n)); - i++; - } - else sb.append(Character.toUpperCase(c)); - } - return sb.toString(); - } - - @Override - public String getType() { - return "smart"; - } + public static final NamingStrategy INSTANCE = new SmartNamingStrategy(); + + @Override + public String convertTableName(String tableName) { + return translate(tableName); + } + + @Override + public String convertColumnName(String columnName) { + return translate(columnName); + } + + private static String translate(String name) { + if (Util.isEmpty(name)) + return ""; + + int len = name.length(); + StringBuilder sb = new StringBuilder(); + char c, p, n; + for (int i = 0; i < len; i++) { + c = name.charAt(i); + if (i == 0 || i + 1 == len) { + sb.append(Character.toUpperCase(c)); + continue; + } + p = name.charAt(i - 1); + n = name.charAt(i + 1); + + // is Camel + if (Character.isLowerCase(p) && Character.isUpperCase(c) && Character.isLowerCase(n)) { + sb.append('_'); + sb.append(Character.toUpperCase(c)); + sb.append(Character.toUpperCase(n)); + i++; + } else + sb.append(Character.toUpperCase(c)); + } + return sb.toString(); + } + + @Override + public String getType() { + return "smart"; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/AbstractEntityTuplizerImpl.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/AbstractEntityTuplizerImpl.java index b4a6e32f..e08601c8 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/AbstractEntityTuplizerImpl.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/AbstractEntityTuplizerImpl.java @@ -17,13 +17,13 @@ import org.hibernate.tuple.entity.AbstractEntityTuplizer; import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.type.Type; -import org.lucee.extension.orm.hibernate.CommonUtil; import org.lucee.extension.orm.hibernate.HBMCreator; import org.lucee.extension.orm.hibernate.HibernateCaster; -import org.lucee.extension.orm.hibernate.HibernateUtil; import org.lucee.extension.orm.hibernate.tuplizer.accessors.CFCGetter; import org.lucee.extension.orm.hibernate.tuplizer.accessors.CFCSetter; import org.lucee.extension.orm.hibernate.tuplizer.proxy.CFCHibernateProxyFactory; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; import lucee.loader.engine.CFMLEngineFactory; import lucee.loader.util.Util; @@ -32,123 +32,130 @@ import lucee.runtime.exp.PageException; import lucee.runtime.type.Struct; +/** + * Entity tuplizer for handling CFC getters, setters, identifiers, and such. + */ public class AbstractEntityTuplizerImpl extends AbstractEntityTuplizer { - // private static CFCAccessor accessor = new CFCAccessor(); - - public AbstractEntityTuplizerImpl(EntityMetamodel entityMetamodel, PersistentClass persistentClass) { - super(entityMetamodel, persistentClass); - } - - @Override - public Serializable getIdentifier(Object entity) throws HibernateException { - return toIdentifier(super.getIdentifier(entity)); - } - - @Override - public void setIdentifier(final Object entity, final Serializable id, final SharedSessionContractImplementor session) { - super.setIdentifier(entity, toIdentifier(id), session); - } - - private Serializable toIdentifier(Serializable id) { - if (id instanceof Component) { - HashMap map = new HashMap(); - Component cfc = (Component) id; - ComponentScope scope = cfc.getComponentScope(); - lucee.runtime.component.Property[] props = HibernateUtil.getIDProperties(cfc, true, true); - lucee.runtime.component.Property p; - String name; - Object value; - for (int i = 0; i < props.length; i++) { - p = props[i]; - name = p.getName(); - value = scope.get(CommonUtil.createKey(name), null); - String type = p.getType(); - Object o = p.getMetaData(); - Struct meta = o instanceof Struct ? (Struct) o : null; - // ormtype - if (meta != null) { - String tmp = CommonUtil.toString(meta.get("ormtype", null), null); - if (!Util.isEmpty(tmp)) type = tmp; - } - - // generator - if (meta != null && CommonUtil.isAnyType(type)) { - type = "string"; - try { - String gen = CommonUtil.toString(meta.get("generator", null), null); - if (!Util.isEmpty(gen)) { - type = HBMCreator.getDefaultTypeForGenerator(gen, "string"); - } - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - } - } - try { - value = HibernateCaster.toHibernateValue(CFMLEngineFactory.getInstance().getThreadPageContext(), value, type); - } - catch (PageException pe) { - } - - map.put(name, value); - } - return map; - } - return id; - } - - @Override - protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) { - return new CFCInstantiator(entityMetamodel, persistentClass); - } - - @Override - protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) { - Type type = null; - // Type type = null; - if (mappedProperty.getValue() != null) type = mappedProperty.getType(); - return new CFCGetter(mappedProperty.getName(), type, mappedEntity.getEntityName()); - } - - @Override - protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) { - Type type = null; - // Type type = null; - if (mappedProperty.getValue() != null) type = mappedProperty.getType(); - return new CFCSetter(mappedProperty.getName(), type, mappedEntity.getEntityName()); - } - - @Override - protected ProxyFactory buildProxyFactory(PersistentClass pc, Getter arg1, Setter arg2) { - CFCHibernateProxyFactory pf = new CFCHibernateProxyFactory(); - pf.postInstantiate(pc); - - return pf; - } - - @Override - public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) { - return CFCEntityNameResolver.INSTANCE.resolveEntityName(entityInstance); - } - - @Override - public EntityNameResolver[] getEntityNameResolvers() { - return new EntityNameResolver[] { CFCEntityNameResolver.INSTANCE }; - } - - @Override - public Class getConcreteProxyClass() { - return Component.class;// ???? - } - - @Override - public Class getMappedClass() { - return Component.class; // ???? - } - - @Override - public EntityMode getEntityMode() { - return EntityMode.MAP; - } + // private static CFCAccessor accessor = new CFCAccessor(); + + public AbstractEntityTuplizerImpl(EntityMetamodel entityMetamodel, PersistentClass persistentClass) { + super(entityMetamodel, persistentClass); + } + + @Override + public Serializable getIdentifier(Object entity) throws HibernateException { + return toIdentifier(super.getIdentifier(entity)); + } + + @Override + public void setIdentifier(final Object entity, final Serializable id, + final SharedSessionContractImplementor session) { + super.setIdentifier(entity, toIdentifier(id), session); + } + + private Serializable toIdentifier(Serializable id) { + if (id instanceof Component) { + HashMap map = new HashMap(); + Component cfc = (Component) id; + ComponentScope scope = cfc.getComponentScope(); + lucee.runtime.component.Property[] props = HibernateUtil.getIDProperties(cfc, true, true); + lucee.runtime.component.Property p; + String name; + Object value; + for (int i = 0; i < props.length; i++) { + p = props[i]; + name = p.getName(); + value = scope.get(CommonUtil.createKey(name), null); + String type = p.getType(); + Object o = p.getMetaData(); + Struct meta = o instanceof Struct ? (Struct) o : null; + // ormtype + if (meta != null) { + String tmp = CommonUtil.toString(meta.get("ormtype", null), null); + if (!Util.isEmpty(tmp)) + type = tmp; + } + + // generator + if (meta != null && CommonUtil.isAnyType(type)) { + type = "string"; + try { + String gen = CommonUtil.toString(meta.get("generator", null), null); + if (!Util.isEmpty(gen)) { + type = HBMCreator.getDefaultTypeForGenerator(gen, "string"); + } + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + try { + value = HibernateCaster.toHibernateValue(CFMLEngineFactory.getInstance().getThreadPageContext(), + value, type); + } catch (PageException pe) { + } + + map.put(name, value); + } + return map; + } + return id; + } + + @Override + protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) { + return new CFCInstantiator(entityMetamodel, persistentClass); + } + + @Override + protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) { + Type type = null; + // Type type = null; + if (mappedProperty.getValue() != null) + type = mappedProperty.getType(); + return new CFCGetter(mappedProperty.getName(), type, mappedEntity.getEntityName()); + } + + @Override + protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) { + Type type = null; + // Type type = null; + if (mappedProperty.getValue() != null) + type = mappedProperty.getType(); + return new CFCSetter(mappedProperty.getName(), type, mappedEntity.getEntityName()); + } + + @Override + protected ProxyFactory buildProxyFactory(PersistentClass pc, Getter arg1, Setter arg2) { + CFCHibernateProxyFactory pf = new CFCHibernateProxyFactory(); + pf.postInstantiate(pc); + + return pf; + } + + @Override + public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) { + return CFCEntityNameResolver.INSTANCE.resolveEntityName(entityInstance); + } + + @Override + public EntityNameResolver[] getEntityNameResolvers() { + return new EntityNameResolver[] { CFCEntityNameResolver.INSTANCE }; + } + + @Override + public Class getConcreteProxyClass() { + return Component.class;// ???? + } + + @Override + public Class getMappedClass() { + return Component.class; // ???? + } + + @Override + public EntityMode getEntityMode() { + return EntityMode.MAP; + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCEntityNameResolver.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCEntityNameResolver.java index 4dd31301..e3751bb9 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCEntityNameResolver.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCEntityNameResolver.java @@ -8,36 +8,35 @@ import lucee.runtime.exp.PageException; public class CFCEntityNameResolver implements EntityNameResolver { - public static final CFCEntityNameResolver INSTANCE = new CFCEntityNameResolver(); + public static final CFCEntityNameResolver INSTANCE = new CFCEntityNameResolver(); - /** - * {@inheritDoc} - */ - @Override - public String resolveEntityName(Object entity) { - try { - Component cfc = HibernateCaster.toComponent(entity); - return HibernateCaster.getEntityName(cfc); - } - catch (PageException pe) { - // print.printST(e); - throw new HibernatePageException(pe); - } - } + /** + * {@inheritDoc} + */ + @Override + public String resolveEntityName(Object entity) { + try { + Component cfc = HibernateCaster.toComponent(entity); + return HibernateCaster.getEntityName(cfc); + } catch (PageException pe) { + // print.printST(e); + throw new HibernatePageException(pe); + } + } - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object obj) { - return getClass().equals(obj.getClass()); - } + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + return getClass().equals(obj.getClass()); + } - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - return getClass().hashCode(); - } + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return getClass().hashCode(); + } } \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCEntityResolver.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCEntityResolver.java deleted file mode 100644 index bdef1235..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCEntityResolver.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.lucee.extension.orm.hibernate.tuplizer; - -import java.io.IOException; - -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -public class CFCEntityResolver implements EntityResolver { - - @Override - public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { - return null; - } - -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCInstantiator.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCInstantiator.java index 3b31ed25..d85ac918 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCInstantiator.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/CFCInstantiator.java @@ -8,12 +8,12 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.entity.EntityMetamodel; -import org.lucee.extension.orm.hibernate.CommonUtil; import org.lucee.extension.orm.hibernate.HibernateCaster; import org.lucee.extension.orm.hibernate.HibernateORMEngine; import org.lucee.extension.orm.hibernate.HibernateORMSession; import org.lucee.extension.orm.hibernate.HibernatePageException; -import org.lucee.extension.orm.hibernate.HibernateUtil; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; import lucee.runtime.Component; import lucee.runtime.PageContext; @@ -21,58 +21,59 @@ public class CFCInstantiator implements Instantiator { - private String entityName; - private Set isInstanceEntityNames = new HashSet(); - private EntityMetamodel entityMetamodel; + private String entityName; + private Set isInstanceEntityNames = new HashSet(); + private EntityMetamodel entityMetamodel; - public CFCInstantiator() { - this.entityName = null; - } + public CFCInstantiator() { + this.entityName = null; + } - /** - * Constructor of the class - * - * @param entityMetamodel - * - * @param mappingInfo - */ - public CFCInstantiator(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) { - this.entityName = mappingInfo.getEntityName(); - this.entityMetamodel = entityMetamodel; - isInstanceEntityNames.add(entityName); - if (mappingInfo.hasSubclasses()) { - Iterator itr = mappingInfo.getSubclassClosureIterator(); - while (itr.hasNext()) { - final PersistentClass subclassInfo = itr.next(); - isInstanceEntityNames.add(subclassInfo.getEntityName()); - } - } - } + /** + * Constructor of the class + * + * @param entityMetamodel + * Hibernate EntityMetamodel object + * @param mappingInfo + * Hibernate PersistentClass mapping info for this CFC + */ + public CFCInstantiator(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) { + this.entityName = mappingInfo.getEntityName(); + this.entityMetamodel = entityMetamodel; + isInstanceEntityNames.add(entityName); + if (mappingInfo.hasSubclasses()) { + Iterator itr = mappingInfo.getSubclassClosureIterator(); + while (itr.hasNext()) { + final PersistentClass subclassInfo = itr.next(); + isInstanceEntityNames.add(subclassInfo.getEntityName()); + } + } + } - @Override - public final Object instantiate(Serializable id) { - return instantiate(); - } + @Override + public final Object instantiate(Serializable id) { + return instantiate(); + } - @Override - public final Object instantiate() { - try { - PageContext pc = CommonUtil.pc(); - HibernateORMSession session = HibernateUtil.getORMSession(pc, true); - HibernateORMEngine engine = (HibernateORMEngine) session.getEngine(); - Component c = engine.create(pc, session, entityName, true); - c.setEntity(true); - return c;// new CFCProxy(c); - } catch (PageException pe) { - throw new HibernatePageException(pe); - } - } + @Override + public final Object instantiate() { + try { + PageContext pc = CommonUtil.pc(); + HibernateORMSession session = HibernateUtil.getORMSession(pc, true); + HibernateORMEngine engine = (HibernateORMEngine) session.getEngine(); + Component c = engine.create(pc, session, entityName, true); + c.setEntity(true); + return c; + } catch (PageException pe) { + throw new HibernatePageException(pe); + } + } - @Override - public final boolean isInstance(Object object) { - Component cfc = CommonUtil.toComponent(object, null); - if (cfc == null) - return false; - return isInstanceEntityNames.contains(HibernateCaster.getEntityName(cfc)); - } + @Override + public final boolean isInstance(Object object) { + Component cfc = CommonUtil.toComponent(object, null); + if (cfc == null) + return false; + return isInstanceEntityNames.contains(HibernateCaster.getEntityName(cfc)); + } } \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/accessors/CFCGetter.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/accessors/CFCGetter.java index 9db15d2d..4e9c14a7 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/accessors/CFCGetter.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/accessors/CFCGetter.java @@ -11,11 +11,11 @@ import org.hibernate.metadata.ClassMetadata; import org.hibernate.property.access.spi.Getter; import org.hibernate.type.Type; -import org.lucee.extension.orm.hibernate.CommonUtil; import org.lucee.extension.orm.hibernate.HibernateCaster; import org.lucee.extension.orm.hibernate.HibernateORMEngine; import org.lucee.extension.orm.hibernate.HibernatePageException; -import org.lucee.extension.orm.hibernate.HibernateUtil; +import org.lucee.extension.orm.hibernate.util.CommonUtil; +import org.lucee.extension.orm.hibernate.util.HibernateUtil; import lucee.loader.engine.CFMLEngineFactory; import lucee.runtime.Component; @@ -26,81 +26,84 @@ public class CFCGetter implements Getter { - private Key key; - private Type type; - private String entityName; - - /** - * Constructor of the class - * - * @param key - * @param string - * @param type - */ - public CFCGetter(String key, Type type, String entityName) { - this.key = CommonUtil.createKey(key); - this.type = type; - this.entityName = entityName; - } - - @Override - public Object get(Object trg) throws HibernateException { - try { - // MUST cache this, perhaps when building xml - PageContext pc = CommonUtil.pc(); - ORMSession session = pc.getORMSession(true); - Component cfc = CommonUtil.toComponent(trg); - String dsn = CFMLEngineFactory.getInstance().getORMUtil().getDataSourceName(pc, cfc); - String name = HibernateCaster.getEntityName(cfc); - SessionFactory sf = (SessionFactory) session.getRawSessionFactory(dsn); - ClassMetadata metaData = sf.getClassMetadata(name); - Type type = HibernateUtil.getPropertyType(metaData, key.getString()); - - Object rtn = cfc.getComponentScope().get(key, null); - return HibernateCaster.toSQL(type, rtn, null); - } catch (PageException pe) { - throw new HibernatePageException(pe); - } - } - - public HibernateORMEngine getHibernateORMEngine() { - try { - // TODO better impl - return HibernateUtil.getORMEngine(CommonUtil.pc()); - } catch (PageException e) { - } - - return null; - } - - // was used in previous versions, we keep it just in case - public Object getForInsert(Object trg, Map map, SessionImplementor si) throws HibernateException { - return get(trg);// MUST better solution? this is from MapGetter - } - - @Override - public Object getForInsert(Object trg, Map map, SharedSessionContractImplementor ssci) { - return get(trg);// MUST better solution? this is from MapGetter - } - - @Override - public Member getMember() { - return null; - } - - @Override - public Method getMethod() { - return null; - } - - @Override - public String getMethodName() { - return null;// MUST macht es sinn den namen zurueck zu geben? - } - - @Override - public Class getReturnType() { - return Object.class;// MUST more concrete? - } + private Key key; + private Type type; + private String entityName; + + /** + * Constructor of the class + * + * @param key + * Persistent property name + * @param type + * Persistent property type + * @param entityName + * Name of the Hibernate entity to retrieve the value from + */ + public CFCGetter(String key, Type type, String entityName) { + this.key = CommonUtil.createKey(key); + this.type = type; + this.entityName = entityName; + } + + @Override + public Object get(Object trg) throws HibernateException { + try { + // MUST cache this, perhaps when building xml + PageContext pc = CommonUtil.pc(); + ORMSession session = pc.getORMSession(true); + Component cfc = CommonUtil.toComponent(trg); + String dsn = CFMLEngineFactory.getInstance().getORMUtil().getDataSourceName(pc, cfc); + String name = HibernateCaster.getEntityName(cfc); + SessionFactory sf = (SessionFactory) session.getRawSessionFactory(dsn); + ClassMetadata metaData = sf.getClassMetadata(name); + Type type = HibernateUtil.getPropertyType(metaData, key.getString()); + + Object rtn = cfc.getComponentScope().get(key, null); + return HibernateCaster.toSQL(type, rtn, null); + } catch (PageException pe) { + throw new HibernatePageException(pe); + } + } + + public HibernateORMEngine getHibernateORMEngine() { + try { + // TODO better impl + return HibernateUtil.getORMEngine(CommonUtil.pc()); + } catch (PageException e) { + } + + return null; + } + + // was used in previous versions, we keep it just in case + public Object getForInsert(Object trg, Map map, SessionImplementor si) throws HibernateException { + return get(trg);// MUST better solution? this is from MapGetter + } + + @Override + public Object getForInsert(Object trg, Map map, SharedSessionContractImplementor ssci) { + return get(trg);// MUST better solution? this is from MapGetter + } + + @Override + public Member getMember() { + return null; + } + + @Override + public Method getMethod() { + return null; + } + + @Override + public String getMethodName() { + return null;// MUST macht es sinn den namen zurueck zu geben? + } + + @Override + public Class getReturnType() { + return Object.class;// MUST more concrete? + } } \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/accessors/CFCSetter.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/accessors/CFCSetter.java index 641a7fb0..84c4547d 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/accessors/CFCSetter.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/accessors/CFCSetter.java @@ -6,8 +6,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.property.access.spi.Setter; import org.hibernate.type.Type; -import org.lucee.extension.orm.hibernate.CommonUtil; import org.lucee.extension.orm.hibernate.HibernatePageException; +import org.lucee.extension.orm.hibernate.util.CommonUtil; import lucee.runtime.Component; import lucee.runtime.exp.PageException; @@ -15,43 +15,46 @@ public final class CFCSetter implements Setter { - private Key key; - private Type type; - private Object entityName; - - /** - * Constructor of the class - * - * @param key - * @param string - * @param type - */ - public CFCSetter(String key, Type type, String entityName) { - this.key = CommonUtil.createKey(key); - this.type = type; - this.entityName = entityName; - } - - @Override - public String getMethodName() { - return null; - } - - @Override - public Method getMethod() { - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public void set(Object trg, Object value, SessionFactoryImplementor factory) throws HibernateException { - try { - Component cfc = CommonUtil.toComponent(trg); - cfc.getComponentScope().set(key, value); - } catch (PageException pe) { - throw new HibernatePageException(pe); - } - } + private Key key; + private Type type; + private Object entityName; + + /** + * Constructor of the class + * + * @param key + * String name of the persistent property + * @param type + * Hibernate Type of this persistent property + * @param entityName + * String name of the Hibernate entity this property is defined on + */ + public CFCSetter(String key, Type type, String entityName) { + this.key = CommonUtil.createKey(key); + this.type = type; + this.entityName = entityName; + } + + @Override + public String getMethodName() { + return null; + } + + @Override + public Method getMethod() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public void set(Object trg, Object value, SessionFactoryImplementor factory) throws HibernateException { + try { + Component cfc = CommonUtil.toComponent(trg); + cfc.getComponentScope().set(key, value); + } catch (PageException pe) { + throw new HibernatePageException(pe); + } + } } \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCHibernateProxy.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCHibernateProxy.java index a4a03bbe..217cf7e6 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCHibernateProxy.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCHibernateProxy.java @@ -14,36 +14,36 @@ */ public class CFCHibernateProxy extends ComponentProxy implements HibernateProxy, Serializable, ObjectWrap { - private static final long serialVersionUID = 4115236247834562085L; - - private CFCLazyInitializer li; - - @Override - public Component getComponent() { - return li.getCFC(); - } - - public CFCHibernateProxy(CFCLazyInitializer li) { - this.li = li; - } - - @Override - public Object writeReplace() { - return this; - } - - @Override - public LazyInitializer getHibernateLazyInitializer() { - return li; - } - - @Override - public Object getEmbededObject(Object defaultValue) { - return getComponent(); - } - - @Override - public Object getEmbededObject() throws PageException { - return getComponent(); - } + private static final long serialVersionUID = 4115236247834562085L; + + private CFCLazyInitializer li; + + @Override + public Component getComponent() { + return li.getCFC(); + } + + public CFCHibernateProxy(CFCLazyInitializer li) { + this.li = li; + } + + @Override + public Object writeReplace() { + return this; + } + + @Override + public LazyInitializer getHibernateLazyInitializer() { + return li; + } + + @Override + public Object getEmbededObject(Object defaultValue) { + return getComponent(); + } + + @Override + public Object getEmbededObject() throws PageException { + return getComponent(); + } } \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCHibernateProxyFactory.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCHibernateProxyFactory.java index d89fadd6..c4934ed3 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCHibernateProxyFactory.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCHibernateProxyFactory.java @@ -12,30 +12,30 @@ import org.hibernate.type.CompositeType; public class CFCHibernateProxyFactory implements ProxyFactory { - private String entityName; - private String nodeName; + private String entityName; + private String nodeName; - @Override - public void postInstantiate(final String entityName, final Class persistentClass, final Set interfaces, final Method getIdentifierMethod, final Method setIdentifierMethod, - CompositeType componentIdType) { - int index = entityName.indexOf('.'); - this.nodeName = entityName; - this.entityName = entityName.substring(index + 1); - } + @Override + public void postInstantiate(final String entityName, final Class persistentClass, final Set interfaces, + final Method getIdentifierMethod, final Method setIdentifierMethod, CompositeType componentIdType) { + int index = entityName.indexOf('.'); + this.nodeName = entityName; + this.entityName = entityName.substring(index + 1); + } - public void postInstantiate(PersistentClass pc) { - this.nodeName = pc.getClassName(); - this.entityName = pc.getEntityName(); - } + public void postInstantiate(PersistentClass pc) { + this.nodeName = pc.getClassName(); + this.entityName = pc.getEntityName(); + } - @Override - public HibernateProxy getProxy(final Serializable id, final SharedSessionContractImplementor session) { - try { - return new CFCHibernateProxy(new CFCLazyInitializer(entityName, id, (SessionImplementor) session)); - } - catch (Throwable t) { - if (t instanceof ThreadDeath) throw (ThreadDeath) t; - return new CFCHibernateProxy(new CFCLazyInitializer(nodeName, id, (SessionImplementor) session)); - } - } + @Override + public HibernateProxy getProxy(final Serializable id, final SharedSessionContractImplementor session) { + try { + return new CFCHibernateProxy(new CFCLazyInitializer(entityName, id, (SessionImplementor) session)); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + return new CFCHibernateProxy(new CFCLazyInitializer(nodeName, id, (SessionImplementor) session)); + } + } } \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCLazyInitializer.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCLazyInitializer.java index b4f9f828..ea375f5a 100755 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCLazyInitializer.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCLazyInitializer.java @@ -4,8 +4,8 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.proxy.AbstractLazyInitializer; -import org.lucee.extension.orm.hibernate.CommonUtil; import org.lucee.extension.orm.hibernate.HibernatePageException; +import org.lucee.extension.orm.hibernate.util.CommonUtil; import lucee.runtime.Component; import lucee.runtime.exp.PageException; @@ -15,22 +15,21 @@ */ public class CFCLazyInitializer extends AbstractLazyInitializer implements Serializable { - CFCLazyInitializer(String entityName, Serializable id, SessionImplementor session) { - super(entityName, id, session); - } - - public Component getCFC() { - try { - return CommonUtil.toComponent(getImplementation()); - } - catch (PageException pe) { - throw new HibernatePageException(pe); - } - } - - @Override - public Class getPersistentClass() { - throw new UnsupportedOperationException("dynamic-map entity representation"); - } + CFCLazyInitializer(String entityName, Serializable id, SessionImplementor session) { + super(entityName, id, session); + } + + public Component getCFC() { + try { + return CommonUtil.toComponent(getImplementation()); + } catch (PageException pe) { + throw new HibernatePageException(pe); + } + } + + @Override + public Class getPersistentClass() { + throw new UnsupportedOperationException("dynamic-map entity representation"); + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCProxy.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCProxy.java deleted file mode 100644 index d345d7f3..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/CFCProxy.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.lucee.extension.orm.hibernate.tuplizer.proxy; - -import lucee.runtime.Component; - -public class CFCProxy extends ComponentProxy { - - private Component cfc; - - public CFCProxy(Component cfc) { - this.cfc = cfc; - } - - @Override - public Component getComponent() { - return cfc; - } - - @Override - public Object put(Object key, Object value) { - super.put(key, value); // writes to this scope - return getComponentScope().put(key, value); // writes to variables scope - } -} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/ComponentProxy.java b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/ComponentProxy.java index a81f1a9f..1aaa053d 100644 --- a/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/ComponentProxy.java +++ b/source/java/src/org/lucee/extension/orm/hibernate/tuplizer/proxy/ComponentProxy.java @@ -4,7 +4,7 @@ import java.util.Map; import java.util.Set; -import org.lucee.extension.orm.hibernate.CommonUtil; +import org.lucee.extension.orm.hibernate.util.CommonUtil; import lucee.commons.lang.types.RefBoolean; import lucee.runtime.Component; @@ -27,545 +27,549 @@ public abstract class ComponentProxy implements Component { - private static final long serialVersionUID = -8709126025976358501L; - - public abstract Component getComponent(); - - @Override - public Class getJavaAccessClass(RefBoolean isNew) throws PageException { - return getComponent().getJavaAccessClass(isNew); - } - - @Override - public Class getJavaAccessClass(PageContext pc, RefBoolean isNew, boolean writeLog, boolean takeTop, boolean create, boolean supressWSbeforeArg) throws PageException { - return getComponent().getJavaAccessClass(pc, isNew, writeLog, takeTop, create, supressWSbeforeArg); - } - - @Override - public Class getJavaAccessClass(PageContext pc, RefBoolean isNew, boolean writeLog, boolean takeTop, boolean create, boolean supressWSbeforeArg, boolean output, - boolean returnValue) throws PageException { - return getComponent().getJavaAccessClass(pc, isNew, writeLog, takeTop, create, supressWSbeforeArg, output, returnValue); - } - - @Override - public String getDisplayName() { - return getComponent().getDisplayName(); - } - - @Override - public String getExtends() { - return getComponent().getExtends(); - } - - @Override - public String getHint() { - return getComponent().getHint(); - } - - @Override - public String getName() { - return getComponent().getName(); - } - - @Override - public String getCallName() { - return getComponent().getCallName(); - } - - @Override - public String getAbsName() { - return getComponent().getAbsName(); - } - - @Override - public boolean getOutput() { - return getComponent().getOutput(); - } - - @Override - public int getModifier() { - return getComponent().getModifier(); - } - - @Override - public boolean instanceOf(String type) { - return getComponent().instanceOf(type); - } - - @Override - public boolean isValidAccess(int access) { - return getComponent().isValidAccess(access); - } - - @Override - public Struct getMetaData(PageContext pc) throws PageException { - return getComponent().getMetaData(pc); - } - - @Override - public Object call(PageContext pc, String key, Object[] args) throws PageException { - return getComponent().call(pc, key, args); - } - - @Override - public Object callWithNamedValues(PageContext pc, String key, Struct args) throws PageException { - return getComponent().callWithNamedValues(pc, key, args); - } - - @Override - public int size() { - return getComponent().size(); - } - - @Override - public Key[] keys() { - return getComponent().keys(); - } - - @Override - public Object remove(Key key) throws PageException { - return getComponent().remove(key); - } - - @Override - public Object removeEL(Key key) { - return getComponent().removeEL(key); - } - - @Override - public Object remove(Key key, Object defaultValue) { - return getComponent().remove(key, defaultValue); - } - - @Override - public void clear() { - getComponent().clear(); - } - - @Override - public Object get(String key) throws PageException { - return get(CommonUtil.toKey(key)); - } - - @Override - public Object get(Key key) throws PageException { - return getComponent().get(key); - } - - @Override - public Object get(String key, Object defaultValue) { - return getComponent().get(key, defaultValue); - } - - @Override - public Object get(Key key, Object defaultValue) { - return getComponent().get(key, defaultValue); - } - - @Override - public Object set(String key, Object value) throws PageException { - return getComponent().set(key, value); - } - - @Override - public Object set(Key key, Object value) throws PageException { - return getComponent().set(key, value); - } - - @Override - public Object setEL(String key, Object value) { - return getComponent().setEL(key, value); - } - - @Override - public Object setEL(Key key, Object value) { - return getComponent().setEL(key, value); - } - - @Override - public boolean containsKey(String key) { - return getComponent().containsKey(key); - } - - @Override - public boolean containsKey(Key key) { - return getComponent().containsKey(key); - } - - @Override - public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties properties) { - return getComponent().toDumpData(pageContext, maxlevel, properties); - } - - @Override - public Iterator keyIterator() { - return getComponent().keyIterator(); - } - - @Override - public Iterator keysAsStringIterator() { - return getComponent().keysAsStringIterator(); - } - - @Override - public Iterator> entryIterator() { - return getComponent().entryIterator(); - } - - @Override - public Iterator valueIterator() { - return getComponent().valueIterator(); - } - - @Override - public String castToString() throws PageException { - return getComponent().castToString(); - } - - @Override - public String castToString(String defaultValue) { - return getComponent().castToString(defaultValue); - } - - @Override - public boolean castToBooleanValue() throws PageException { - return getComponent().castToBooleanValue(); - } - - @Override - public Boolean castToBoolean(Boolean defaultValue) { - return getComponent().castToBoolean(defaultValue); - } - - @Override - public double castToDoubleValue() throws PageException { - return getComponent().castToDoubleValue(); - } - - @Override - public double castToDoubleValue(double defaultValue) { - return getComponent().castToDoubleValue(defaultValue); - } - - @Override - public DateTime castToDateTime() throws PageException { - return getComponent().castToDateTime(); - } - - @Override - public DateTime castToDateTime(DateTime defaultValue) { - return getComponent().castToDateTime(defaultValue); - } - - @Override - public int compareTo(String str) throws PageException { - return getComponent().compareTo(str); - } - - @Override - public int compareTo(boolean b) throws PageException { - return getComponent().compareTo(b); - } - - @Override - public int compareTo(double d) throws PageException { - return getComponent().compareTo(d); - } - - @Override - public int compareTo(DateTime dt) throws PageException { - return getComponent().compareTo(dt); - } - - @Override - public boolean containsKey(Object key) { - return getComponent().containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return getComponent().containsValue(value); - } - - @Override - public Set entrySet() { - return getComponent().entrySet(); - } - - @Override - public Object get(Object key) { - return getComponent().get(key); - } - - @Override - public boolean isEmpty() { - return getComponent().isEmpty(); - } - - @Override - public Set keySet() { - return getComponent().keySet(); - } - - @Override - public Object put(Object key, Object value) { - return getComponent().put(key, value); - } - - @Override - public void putAll(Map m) { - getComponent().putAll(m); - } - - @Override - public Object remove(Object key) { - return getComponent().remove(key); - } - - @Override - public java.util.Collection values() { - return getComponent().values(); - } - - @Override - public Object get(PageContext pc, Key key, Object defaultValue) { - return getComponent().get(pc, key, defaultValue); - } - - @Override - public Object get(PageContext pc, Key key) throws PageException { - return getComponent().get(pc, key); - } - - @Override - public Object set(PageContext pc, Key propertyName, Object value) throws PageException { - return getComponent().set(pc, propertyName, value); - } - - @Override - public Object setEL(PageContext pc, Key propertyName, Object value) { - return getComponent().setEL(pc, propertyName, value); - } - - @Override - public Object call(PageContext pc, Key methodName, Object[] arguments) throws PageException { - return getComponent().call(pc, methodName, arguments); - } - - @Override - public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException { - return getComponent().callWithNamedValues(pc, methodName, args); - } - - @Override - public Property[] getProperties(boolean onlyPeristent) { - return getComponent().getProperties(onlyPeristent); - } - - @Override - public void setProperty(Property property) throws PageException { - getComponent().setProperty(property); - } - - @Override - public ComponentScope getComponentScope() { - return getComponent().getComponentScope(); - } - - @Override - public boolean contains(PageContext pc, Key key) { - return getComponent().contains(pc, key); - } - - @Override - public PageSource getPageSource() { - return getComponent().getPageSource(); - } - - @Override - public String getBaseAbsName() { - return getComponent().getBaseAbsName(); - } - - @Override - public boolean isBasePeristent() { - return getComponent().isBasePeristent(); - } - - @Override - public boolean equalTo(String type) { - return getComponent().equalTo(type); - } - - @Override - public Object clone() { - return duplicate(true); - } - - @Override - public void registerUDF(Collection.Key key, UDF udf) throws PageException { - getComponent().registerUDF(key, udf); - } - - @Override - public void registerUDF(Collection.Key key, UDFProperties props) throws PageException { - getComponent().registerUDF(key, props); - } - - @Override - public java.util.Iterator getIterator() { - return keysAsStringIterator(); - } - - @Override - public String getWSDLFile() { - return getComponent().getWSDLFile(); - } - - @Override - public Collection duplicate(boolean deepCopy) { - return getComponent().duplicate(deepCopy); - } - - @Override - public Property[] getProperties(boolean onlyPeristent, boolean includeBaseProperties, boolean overrideProperties, boolean inheritedMappedSuperClassOnly) { - return getComponent().getProperties(onlyPeristent, includeBaseProperties, overrideProperties, inheritedMappedSuperClassOnly); - } - - @Override - public boolean isPersistent() { - return getComponent().isPersistent(); - } - - public static boolean isPersistent(Component c) { - return c.isPersistent(); - } - - @Override - public boolean isAccessors() { - return getComponent().isAccessors(); - } - - @Override - public Object getMetaStructItem(Key name) { - return getComponent().getMetaStructItem(name); - } - - public static Object getMetaStructItem(Component c, Key name) { - return c.getMetaStructItem(name); - } - - @Override - public Set keySet(int access) { - return getComponent().keySet(access); - } - - @Override - public Object call(PageContext pc, int access, Key name, Object[] args) throws PageException { - return getComponent().call(pc, access, name, args); - } - - @Override - public Object callWithNamedValues(PageContext pc, int access, Key name, Struct args) throws PageException { - return getComponent().callWithNamedValues(pc, access, name, args); - } - - @Override - public int size(int access) { - return getComponent().size(access); - } - - @Override - public Key[] keys(int access) { - return getComponent().keys(access); - } - - @Override - public Iterator> entryIterator(int access) { - return getComponent().entryIterator(access); - } - - @Override - public Iterator valueIterator(int access) { - return getComponent().valueIterator(access); - } - - @Override - public Object get(int access, Key key) throws PageException { - return getComponent().get(access, key); - } - - @Override - public Object get(int access, Key key, Object defaultValue) { - return getComponent().get(access, key, defaultValue); - } - - @Override - public Iterator keyIterator(int access) { - return getComponent().keyIterator(access); - } - - @Override - public Iterator keysAsStringIterator(int access) { - return getComponent().keysAsStringIterator(access); - } - - @Override - public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp, int access) { - return getComponent().toDumpData(pageContext, maxlevel, dp, access); - } - - @Override - public boolean contains(int access, Key name) { - return getComponent().contains(access, name); - } - - @Override - public Member getMember(int access, Key key, boolean dataMember, boolean superAccess) { - return getComponent().getMember(access, key, dataMember, superAccess); - } - - @Override - public void setEntity(boolean entity) { - getComponent().setEntity(entity); - } - - public static void setEntity(Component c, boolean entity) { - c.setEntity(entity); - } - - @Override - public boolean isEntity() { - return getComponent().isEntity(); - } - - @Override - public Component getBaseComponent() { - return getComponent().getBaseComponent(); - } - - @Override - public Scope staticScope() { - return getComponent().staticScope(); - } - - @Override - public Variables beforeStaticConstructor(PageContext pc) { - return getComponent().beforeStaticConstructor(pc); - } - - @Override - public void afterStaticConstructor(PageContext pc, Variables var) { - getComponent().afterStaticConstructor(pc, var); - } - - @Override - public Interface[] getInterfaces() { - return getComponent().getInterfaces(); - } - - @Override - public String id() { - return getComponent().id(); - } + private static final long serialVersionUID = -8709126025976358501L; + + public abstract Component getComponent(); + + @Override + public Class getJavaAccessClass(RefBoolean isNew) throws PageException { + return getComponent().getJavaAccessClass(isNew); + } + + @Override + public Class getJavaAccessClass(PageContext pc, RefBoolean isNew, boolean writeLog, boolean takeTop, boolean create, + boolean supressWSbeforeArg) throws PageException { + return getComponent().getJavaAccessClass(pc, isNew, writeLog, takeTop, create, supressWSbeforeArg); + } + + @Override + public Class getJavaAccessClass(PageContext pc, RefBoolean isNew, boolean writeLog, boolean takeTop, boolean create, + boolean supressWSbeforeArg, boolean output, boolean returnValue) throws PageException { + return getComponent().getJavaAccessClass(pc, isNew, writeLog, takeTop, create, supressWSbeforeArg, output, + returnValue); + } + + @Override + public String getDisplayName() { + return getComponent().getDisplayName(); + } + + @Override + public String getExtends() { + return getComponent().getExtends(); + } + + @Override + public String getHint() { + return getComponent().getHint(); + } + + @Override + public String getName() { + return getComponent().getName(); + } + + @Override + public String getCallName() { + return getComponent().getCallName(); + } + + @Override + public String getAbsName() { + return getComponent().getAbsName(); + } + + @Override + public boolean getOutput() { + return getComponent().getOutput(); + } + + @Override + public int getModifier() { + return getComponent().getModifier(); + } + + @Override + public boolean instanceOf(String type) { + return getComponent().instanceOf(type); + } + + @Override + public boolean isValidAccess(int access) { + return getComponent().isValidAccess(access); + } + + @Override + public Struct getMetaData(PageContext pc) throws PageException { + return getComponent().getMetaData(pc); + } + + @Override + public Object call(PageContext pc, String key, Object[] args) throws PageException { + return getComponent().call(pc, key, args); + } + + @Override + public Object callWithNamedValues(PageContext pc, String key, Struct args) throws PageException { + return getComponent().callWithNamedValues(pc, key, args); + } + + @Override + public int size() { + return getComponent().size(); + } + + @Override + public Key[] keys() { + return getComponent().keys(); + } + + @Override + public Object remove(Key key) throws PageException { + return getComponent().remove(key); + } + + @Override + public Object removeEL(Key key) { + return getComponent().removeEL(key); + } + + @Override + public Object remove(Key key, Object defaultValue) { + return getComponent().remove(key, defaultValue); + } + + @Override + public void clear() { + getComponent().clear(); + } + + @Override + public Object get(String key) throws PageException { + return get(CommonUtil.toKey(key)); + } + + @Override + public Object get(Key key) throws PageException { + return getComponent().get(key); + } + + @Override + public Object get(String key, Object defaultValue) { + return getComponent().get(key, defaultValue); + } + + @Override + public Object get(Key key, Object defaultValue) { + return getComponent().get(key, defaultValue); + } + + @Override + public Object set(String key, Object value) throws PageException { + return getComponent().set(key, value); + } + + @Override + public Object set(Key key, Object value) throws PageException { + return getComponent().set(key, value); + } + + @Override + public Object setEL(String key, Object value) { + return getComponent().setEL(key, value); + } + + @Override + public Object setEL(Key key, Object value) { + return getComponent().setEL(key, value); + } + + @Override + public boolean containsKey(String key) { + return getComponent().containsKey(key); + } + + @Override + public boolean containsKey(Key key) { + return getComponent().containsKey(key); + } + + @Override + public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties properties) { + return getComponent().toDumpData(pageContext, maxlevel, properties); + } + + @Override + public Iterator keyIterator() { + return getComponent().keyIterator(); + } + + @Override + public Iterator keysAsStringIterator() { + return getComponent().keysAsStringIterator(); + } + + @Override + public Iterator> entryIterator() { + return getComponent().entryIterator(); + } + + @Override + public Iterator valueIterator() { + return getComponent().valueIterator(); + } + + @Override + public String castToString() throws PageException { + return getComponent().castToString(); + } + + @Override + public String castToString(String defaultValue) { + return getComponent().castToString(defaultValue); + } + + @Override + public boolean castToBooleanValue() throws PageException { + return getComponent().castToBooleanValue(); + } + + @Override + public Boolean castToBoolean(Boolean defaultValue) { + return getComponent().castToBoolean(defaultValue); + } + + @Override + public double castToDoubleValue() throws PageException { + return getComponent().castToDoubleValue(); + } + + @Override + public double castToDoubleValue(double defaultValue) { + return getComponent().castToDoubleValue(defaultValue); + } + + @Override + public DateTime castToDateTime() throws PageException { + return getComponent().castToDateTime(); + } + + @Override + public DateTime castToDateTime(DateTime defaultValue) { + return getComponent().castToDateTime(defaultValue); + } + + @Override + public int compareTo(String str) throws PageException { + return getComponent().compareTo(str); + } + + @Override + public int compareTo(boolean b) throws PageException { + return getComponent().compareTo(b); + } + + @Override + public int compareTo(double d) throws PageException { + return getComponent().compareTo(d); + } + + @Override + public int compareTo(DateTime dt) throws PageException { + return getComponent().compareTo(dt); + } + + @Override + public boolean containsKey(Object key) { + return getComponent().containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return getComponent().containsValue(value); + } + + @Override + public Set entrySet() { + return getComponent().entrySet(); + } + + @Override + public Object get(Object key) { + return getComponent().get(key); + } + + @Override + public boolean isEmpty() { + return getComponent().isEmpty(); + } + + @Override + public Set keySet() { + return getComponent().keySet(); + } + + @Override + public Object put(Object key, Object value) { + return getComponent().put(key, value); + } + + @Override + public void putAll(Map m) { + getComponent().putAll(m); + } + + @Override + public Object remove(Object key) { + return getComponent().remove(key); + } + + @Override + public java.util.Collection values() { + return getComponent().values(); + } + + @Override + public Object get(PageContext pc, Key key, Object defaultValue) { + return getComponent().get(pc, key, defaultValue); + } + + @Override + public Object get(PageContext pc, Key key) throws PageException { + return getComponent().get(pc, key); + } + + @Override + public Object set(PageContext pc, Key propertyName, Object value) throws PageException { + return getComponent().set(pc, propertyName, value); + } + + @Override + public Object setEL(PageContext pc, Key propertyName, Object value) { + return getComponent().setEL(pc, propertyName, value); + } + + @Override + public Object call(PageContext pc, Key methodName, Object[] arguments) throws PageException { + return getComponent().call(pc, methodName, arguments); + } + + @Override + public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException { + return getComponent().callWithNamedValues(pc, methodName, args); + } + + @Override + public Property[] getProperties(boolean onlyPeristent) { + return getComponent().getProperties(onlyPeristent); + } + + @Override + public void setProperty(Property property) throws PageException { + getComponent().setProperty(property); + } + + @Override + public ComponentScope getComponentScope() { + return getComponent().getComponentScope(); + } + + @Override + public boolean contains(PageContext pc, Key key) { + return getComponent().contains(pc, key); + } + + @Override + public PageSource getPageSource() { + return getComponent().getPageSource(); + } + + @Override + public String getBaseAbsName() { + return getComponent().getBaseAbsName(); + } + + @Override + public boolean isBasePeristent() { + return getComponent().isBasePeristent(); + } + + @Override + public boolean equalTo(String type) { + return getComponent().equalTo(type); + } + + @Override + public Object clone() { + return duplicate(true); + } + + @Override + public void registerUDF(Collection.Key key, UDF udf) throws PageException { + getComponent().registerUDF(key, udf); + } + + @Override + public void registerUDF(Collection.Key key, UDFProperties props) throws PageException { + getComponent().registerUDF(key, props); + } + + @Override + public java.util.Iterator getIterator() { + return keysAsStringIterator(); + } + + @Override + public String getWSDLFile() { + return getComponent().getWSDLFile(); + } + + @Override + public Collection duplicate(boolean deepCopy) { + return getComponent().duplicate(deepCopy); + } + + @Override + public Property[] getProperties(boolean onlyPeristent, boolean includeBaseProperties, boolean overrideProperties, + boolean inheritedMappedSuperClassOnly) { + return getComponent().getProperties(onlyPeristent, includeBaseProperties, overrideProperties, + inheritedMappedSuperClassOnly); + } + + @Override + public boolean isPersistent() { + return getComponent().isPersistent(); + } + + public static boolean isPersistent(Component c) { + return c.isPersistent(); + } + + @Override + public boolean isAccessors() { + return getComponent().isAccessors(); + } + + @Override + public Object getMetaStructItem(Key name) { + return getComponent().getMetaStructItem(name); + } + + public static Object getMetaStructItem(Component c, Key name) { + return c.getMetaStructItem(name); + } + + @Override + public Set keySet(int access) { + return getComponent().keySet(access); + } + + @Override + public Object call(PageContext pc, int access, Key name, Object[] args) throws PageException { + return getComponent().call(pc, access, name, args); + } + + @Override + public Object callWithNamedValues(PageContext pc, int access, Key name, Struct args) throws PageException { + return getComponent().callWithNamedValues(pc, access, name, args); + } + + @Override + public int size(int access) { + return getComponent().size(access); + } + + @Override + public Key[] keys(int access) { + return getComponent().keys(access); + } + + @Override + public Iterator> entryIterator(int access) { + return getComponent().entryIterator(access); + } + + @Override + public Iterator valueIterator(int access) { + return getComponent().valueIterator(access); + } + + @Override + public Object get(int access, Key key) throws PageException { + return getComponent().get(access, key); + } + + @Override + public Object get(int access, Key key, Object defaultValue) { + return getComponent().get(access, key, defaultValue); + } + + @Override + public Iterator keyIterator(int access) { + return getComponent().keyIterator(access); + } + + @Override + public Iterator keysAsStringIterator(int access) { + return getComponent().keysAsStringIterator(access); + } + + @Override + public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp, int access) { + return getComponent().toDumpData(pageContext, maxlevel, dp, access); + } + + @Override + public boolean contains(int access, Key name) { + return getComponent().contains(access, name); + } + + @Override + public Member getMember(int access, Key key, boolean dataMember, boolean superAccess) { + return getComponent().getMember(access, key, dataMember, superAccess); + } + + @Override + public void setEntity(boolean entity) { + getComponent().setEntity(entity); + } + + public static void setEntity(Component c, boolean entity) { + c.setEntity(entity); + } + + @Override + public boolean isEntity() { + return getComponent().isEntity(); + } + + @Override + public Component getBaseComponent() { + return getComponent().getBaseComponent(); + } + + @Override + public Scope staticScope() { + return getComponent().staticScope(); + } + + @Override + public Variables beforeStaticConstructor(PageContext pc) { + return getComponent().beforeStaticConstructor(pc); + } + + @Override + public void afterStaticConstructor(PageContext pc, Variables var) { + getComponent().afterStaticConstructor(pc, var); + } + + @Override + public Interface[] getInterfaces() { + return getComponent().getInterfaces(); + } + + @Override + public String id() { + return getComponent().id(); + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/util/CommonUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/util/CommonUtil.java new file mode 100644 index 00000000..392b4b1b --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/hibernate/util/CommonUtil.java @@ -0,0 +1,1068 @@ +package org.lucee.extension.orm.hibernate.util; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.util.Date; +import java.nio.charset.Charset; +import java.sql.ResultSet; +import java.sql.Clob; +import java.util.Map; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; + +import org.hibernate.JDBCException; +import org.hibernate.exception.ConstraintViolationException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import lucee.commons.io.res.Resource; +import lucee.commons.lang.types.RefBoolean; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.util.Util; +import lucee.runtime.Component; +import lucee.runtime.Mapping; +import lucee.runtime.PageContext; +import lucee.runtime.component.Property; +import lucee.runtime.config.Config; +import lucee.runtime.db.DataSource; +import lucee.runtime.db.DatasourceConnection; +import lucee.runtime.db.SQL; +import lucee.runtime.db.SQLItem; +import lucee.runtime.exp.PageException; +import lucee.runtime.type.Array; +import lucee.runtime.type.Collection; +import lucee.runtime.type.Collection.Key; +import lucee.runtime.type.Query; +import lucee.runtime.type.Struct; +import lucee.runtime.type.dt.DateTime; +import lucee.runtime.type.scope.Argument; +import lucee.runtime.ext.function.Function; +import lucee.runtime.util.Cast; +import lucee.runtime.util.Creation; +import lucee.runtime.util.DBUtil; +import lucee.runtime.util.Decision; +import lucee.runtime.util.ORMUtil; +import lucee.runtime.util.Operation; +import lucee.runtime.op.Castable; +import lucee.runtime.type.ObjectWrap; + +public class CommonUtil { + + public static final Key ENTITY_NAME = CommonUtil.createKey("entityname"); + public static final Key FIELDTYPE = CommonUtil.createKey("fieldtype"); + public static final Key POST_INSERT = CommonUtil.createKey("postInsert"); + public static final Key POST_UPDATE = CommonUtil.createKey("postUpdate"); + public static final Key PRE_DELETE = CommonUtil.createKey("preDelete"); + public static final Key POST_DELETE = CommonUtil.createKey("postDelete"); + public static final Key PRE_LOAD = CommonUtil.createKey("preLoad"); + public static final Key POST_LOAD = CommonUtil.createKey("postLoad"); + public static final Key PRE_UPDATE = CommonUtil.createKey("preUpdate"); + public static final Key PRE_INSERT = CommonUtil.createKey("preInsert"); + public static final Key ON_FLUSH = CommonUtil.createKey("onFlush"); + public static final Key ON_AUTO_FLUSH = CommonUtil.createKey("onAutoFlush"); + public static final Key ON_CLEAR = CommonUtil.createKey("onClear"); + public static final Key ON_DELETE = CommonUtil.createKey("onDelete"); + public static final Key ON_DIRTY_CHECK = CommonUtil.createKey("onDirtyCheck"); + public static final Key ON_EVICT = CommonUtil.createKey("onEvict"); + + public static final Key INIT = CommonUtil.createKey("init"); + private static final short INSPECT_UNDEFINED = (short) 4; /* ConfigImpl.INSPECT_UNDEFINED */ + private static final Class[] ZEROC = new Class[] {}; + private static final Object[] ZEROO = new Object[] {}; + private static final Class[] GET_DSCONN = new Class[] { PageContext.class, DataSource.class, String.class, + String.class, boolean.class }; + private static final Class[] REL_DSCONN = new Class[] { PageContext.class, DatasourceConnection.class, + boolean.class }; + // private static final Class[] GET_CONN = new Class[] { PageContext.class, DataSource.class, + // String.class, String.class }; + // private static final Class[] REL_CONN = new Class[] { PageContext.class, + // DatasourceConnection.class }; + // releaseConnection(pageContext, dc); + private static Charset _charset; + + public static Charset _UTF8; + // public static Charset ISO88591; + public static Charset _UTF16BE; + public static Charset _UTF16LE; + + public static Charset getCharset() { + if (_charset == null) { + String strCharset = System.getProperty("file.encoding"); + if (strCharset == null || strCharset.equalsIgnoreCase("MacRoman")) + strCharset = "cp1252"; + + if (strCharset.equalsIgnoreCase("utf-8")) + _charset = UTF8(); + else + _charset = toCharset(strCharset); + } + return _charset; + } + + public static Charset UTF8() { + if (_UTF8 == null) + _UTF8 = toCharset("UTF-8"); + return _UTF8; + } + + private static Charset UTF16LE() { + if (_UTF16LE == null) + _UTF16LE = toCharset("UTF-16LE"); + return _UTF16LE; + } + + private static Charset UTF16BE() { + if (_UTF16BE == null) + _UTF16BE = toCharset("UTF-16BE"); + return _UTF16BE; + } + + private static Charset toCharset(String charset) { + try { + return CFMLEngineFactory.getInstance().getCastUtil().toCharset(charset); + } catch (PageException pe) { + throw CFMLEngineFactory.getInstance().getExceptionUtil().createPageRuntimeException(pe); + } + } + + private static Cast caster; + private static Decision decision; + private static Creation creator; + private static Operation op; + private static lucee.runtime.util.XMLUtil xml; + private static lucee.runtime.util.ListUtil list; + private static DBUtil db; + private static ORMUtil orm; + + private static Method mGetDatasourceConnection; + private static Method mReleaseDatasourceConnection; + + public static Object castTo(PageContext pc, Class trgClass, Object obj) throws PageException { + return caster().castTo(pc, trgClass, obj); + } + + public static Array toArray(Object obj) throws PageException { + return caster().toArray(obj); + } + + public static Array toArray(Object obj, Array defaultValue) { + return caster().toArray(obj, defaultValue); + } + + public static Boolean toBoolean(String str) throws PageException { + return caster().toBoolean(str); + } + + public static Boolean toBoolean(String str, Boolean defaultValue) { + return caster().toBoolean(str, defaultValue); + } + + public static Boolean toBoolean(Object obj) throws PageException { + return caster().toBoolean(obj); + } + + public static Boolean toBoolean(Object obj, Boolean defaultValue) { + return caster().toBoolean(obj, defaultValue); + } + + public static Boolean toBooleanValue(String str) throws PageException { + return caster().toBooleanValue(str); + } + + public static Boolean toBooleanValue(String str, Boolean defaultValue) { + return caster().toBooleanValue(str, defaultValue); + } + + public static boolean toBooleanValue(Object obj) throws PageException { + return caster().toBooleanValue(obj); + } + + public static boolean toBooleanValue(Object obj, boolean defaultValue) { + return caster().toBooleanValue(obj, defaultValue); + } + + public static Component toComponent(Object obj) throws PageException { + return caster().toComponent(obj); + } + + public static Component toComponent(Object obj, Component defaultValue) { + return caster().toComponent(obj, defaultValue); + } + + public static Object toList(String[] arr, String delimiter) { + return list().toList(arr, delimiter); + } + + public static String toString(Object obj, String defaultValue) { + return caster().toString(obj, defaultValue); + } + + public static String toString(Object obj) throws PageException { + return caster().toString(obj); + } + + public static String toString(boolean b) { + return caster().toString(b); + } + + public static String toString(double d) { + return caster().toString(d); + } + + public static String toString(int i) { + return caster().toString(i); + } + + public static String toString(long l) { + return caster().toString(l); + } + + /** + * reads String data from File + * + * @param file + * @param charset + * + * @return readed string + * + * @throws IOException + */ + public static String toString(Resource file, Charset charset) throws IOException { + Reader r = null; + try { + r = getReader(file, charset); + String str = toString(r); + return str; + } finally { + closeEL(r); + } + } + + public static String toString(Reader reader) throws IOException { + StringWriter sw = new StringWriter(512); + copy(toBufferedReader(reader), sw); + sw.close(); + return sw.toString(); + } + + public static BufferedReader toBufferedReader(Reader r) { + if (r instanceof BufferedReader) + return (BufferedReader) r; + return new BufferedReader(r); + } + + private static final void copy(Reader r, Writer w) throws IOException { + copy(r, w, 0xffff); + } + + private static final void copy(Reader r, Writer w, int blockSize) throws IOException { + char[] buffer = new char[blockSize]; + int len; + + while ((len = r.read(buffer)) != -1) + w.write(buffer, 0, len); + } + + public static Reader getReader(Resource res, Charset charset) throws IOException { + InputStream is = null; + try { + is = res.getInputStream(); + boolean markSupported = is.markSupported(); + if (markSupported) + is.mark(4); + int first = is.read(); + int second = is.read(); + // FE FF UTF-16, big-endian + if (first == 0xFE && second == 0xFF) { + return _getReader(is, UTF16BE()); + } + // FF FE UTF-16, little-endian + if (first == 0xFF && second == 0xFE) { + return _getReader(is, UTF16LE()); + } + + int third = is.read(); + // EF BB BF UTF-8 + if (first == 0xEF && second == 0xBB && third == 0xBF) { + // is.reset(); + return _getReader(is, UTF8()); + } + + if (markSupported) { + is.reset(); + return _getReader(is, charset); + } + } catch (IOException ioe) { + closeEL(is); + throw ioe; + } + + // when mark not supported return new reader + closeEL(is); + is = null; + try { + is = res.getInputStream(); + } catch (IOException ioe) { + closeEL(is); + throw ioe; + } + return _getReader(is, charset); + } + + private static Reader _getReader(InputStream is, Charset cs) { + if (cs == null) + cs = getCharset(); + return new BufferedReader(new InputStreamReader(is, cs)); + } + + public static String[] toStringArray(String list, String delimiter) { + return list().toStringArray(list().toArray(list, delimiter), ""); // TODO better + } + + public static Float toFloat(Object obj) throws PageException { + return caster().toFloat(obj); + } + + public static Float toFloat(Object obj, Float defaultValue) { + return caster().toFloat(obj, defaultValue); + } + + public static float toFloatValue(Object obj) throws PageException { + return caster().toFloatValue(obj); + } + + public static float toFloatValue(Object obj, float defaultValue) { + return caster().toFloatValue(obj, defaultValue); + } + + public static Double toDouble(Object obj) throws PageException { + return caster().toDouble(obj); + } + + public static Double toDouble(Object obj, Double defaultValue) { + return caster().toDouble(obj, defaultValue); + } + + public static double toDoubleValue(Object obj) throws PageException { + return caster().toDoubleValue(obj); + } + + public static double toDoubleValue(Object obj, double defaultValue) { + return caster().toDoubleValue(obj, defaultValue); + } + + public static BigDecimal toBigDecimal(Object obj) throws PageException { + return caster().toBigDecimal(obj); + } + + public static BigDecimal toBigDecimal(Object obj, BigDecimal defaultValue) { + return caster().toBigDecimal(obj, defaultValue); + } + + public static Short toShort(Object obj) throws PageException { + return caster().toShort(obj); + } + + public static Short toShort(Object obj, Short defaultValue) { + return caster().toShort(obj, defaultValue); + } + + public static double toShortValue(Object obj) throws PageException { + return caster().toShortValue(obj); + } + + public static double toShortValue(Object obj, short defaultValue) { + return caster().toShortValue(obj, defaultValue); + } + + public static Integer toInteger(Object obj) throws PageException { + return caster().toInteger(obj); + } + + public static Integer toInteger(Object obj, Integer defaultValue) { + return caster().toInteger(obj, defaultValue); + } + + public static Long toLong(Object obj) throws PageException { + return caster().toLong(obj); + } + + public static Long toLong(Object obj, Long defaultValue) { + return caster().toLong(obj, defaultValue); + } + + public static long toLongValue(Object obj) throws PageException { + return caster().toLongValue(obj); + } + + public static long toLongValue(Object obj, long defaultValue) { + return caster().toLongValue(obj, defaultValue); + } + + public static byte[] toBinary(Object obj) throws PageException { + return caster().toBinary(obj); + } + + public static byte[] toBinary(Object obj, byte[] defaultValue) { + return caster().toBinary(obj, defaultValue); + } + + public static int toIntValue(Object obj) throws PageException { + return caster().toIntValue(obj); + } + + public static int toIntValue(Object obj, int defaultValue) { + return caster().toIntValue(obj, defaultValue); + } + + public static Array toArray(Argument arg) { + Array trg = createArray(); + int[] keys = arg.intKeys(); + for (int i = 0; i < keys.length; i++) { + trg.setEL(keys[i], arg.get(keys[i], null)); + } + return trg; + } + + public static PageException toPageException(Throwable t) { + PageException pe = caster().toPageException(t); + if (t instanceof org.hibernate.HibernateException) { + org.hibernate.HibernateException he = (org.hibernate.HibernateException) t; + Throwable cause = he.getCause(); + if (cause != null) { + pe = caster().toPageException(cause); + ExceptionUtil.setAdditional(pe, CommonUtil.createKey("hibernate exception"), t); + } + } + if (t instanceof JDBCException) { + JDBCException je = (JDBCException) t; + ExceptionUtil.setAdditional(pe, CommonUtil.createKey("sql"), je.getSQL()); + } + if (t instanceof ConstraintViolationException) { + ConstraintViolationException cve = (ConstraintViolationException) t; + if (!Util.isEmpty(cve.getConstraintName())) { + ExceptionUtil.setAdditional(pe, CommonUtil.createKey("constraint name"), cve.getConstraintName()); + } + } + return pe; + } + + public static Serializable toSerializable(Object obj) throws PageException { + return caster().toSerializable(obj); + } + + public static Serializable toSerializable(Object obj, Serializable defaultValue) { + return caster().toSerializable(obj, defaultValue); + } + + public static Struct toStruct(Object obj) throws PageException { + return caster().toStruct(obj); + } + + public static Struct toStruct(Object obj, Struct defaultValue) { + return caster().toStruct(obj, defaultValue); + } + + // public static Struct toStruct(Object o, boolean caseSensitive) throws PageException { + // return caster().toStruct(o, caseSensitive); + // } + + public static SQLItem toSQLItem(Object value, int type) { + return db().toSQLItem(value, type); + } + + public static SQL toSQL(String sql, SQLItem[] items) { + return db().toSQL(sql, items); + } + + public static Object toSqlType(SQLItem item) throws PageException { + return db().toSqlType(item); + } + + public static Object[] toNativeArray(Object obj) throws PageException { + return caster().toNativeArray(obj); + } + + public static Key toKey(String str) { + return caster().toKey(str); + } + + public static String toTypeName(Object obj) { + return caster().toTypeName(obj); + } + + public static Node toXML(Object obj) throws PageException { + return XMLUtil.toNode(obj); + } + /* + * public static Node toXML(Object obj, Node defaultValue) { return caster().toXML(obj,defaultValue); } + */ + + public static Document toDocument(Resource res, Charset cs) throws PageException { + return XMLUtil.parse(XMLUtil.toInputSource(res, cs), null, false); + } + + public static boolean isArray(Object obj) { + return decision().isArray(obj); + } + + public static boolean isStruct(Object obj) { + return decision().isStruct(obj); + } + + /** + * See if a given value is coercable to a string. + *

+ * Blatantly copied from Lucee core because it's not in the Lucee loader, so we don't have access to run it without + * reflection. + * + * @link https://github.com/lucee/Lucee/blob/6.0/core/src/main/java/lucee/runtime/op/Decision.java#L964 + * + * @param o + * Value to compare + * + * @return Boolean, true if value is a String or castable to a String. + */ + public static boolean isString(Object o) { + if (o instanceof String) + return true; + else if (o instanceof Boolean) + return true; + else if (o instanceof Number) + return true; + else if (o instanceof Date) + return true; + else if (o instanceof Castable) { + return ((Castable) o).castToString("this is a unique string") != "this is a unique string"; + + } else if (o instanceof Clob) + return true; + else if (o instanceof Node) + return true; + else if (o instanceof Map || o instanceof List || o instanceof Function) + return false; + else if (o == null) + return true; + else if (o instanceof ObjectWrap) + return isString(((ObjectWrap) o).getEmbededObject("")); + return true; + } + + public static boolean isSimpleValue(Object obj) { + return decision().isSimpleValue(obj); + } + + public static boolean isCastableToBoolean(Object obj) { + return decision().isCastableToBoolean(obj); + } + + public static boolean isCastableToArray(Object o) { + return decision().isCastableToArray(o); + } + + public static boolean isCastableToStruct(Object o) { + return decision().isCastableToStruct(o); + } + + public static boolean isBinary(Object obj) { + return decision().isBinary(obj); + } + + public static boolean isBoolean(Object obj) { + return decision().isBoolean(obj); + } + + public static boolean isAnyType(String type) { + return decision().isAnyType(type); + } + + public static Array createArray() { + return creator().createArray(); + } + + public static DateTime createDateTime(long time) { + return creator().createDateTime(time); + } + + public static Property createProperty(String name, String type) { + return creator().createProperty(name, type); + } + + public static Struct createStruct() { + return creator().createStruct(); + } + + public static Collection.Key createKey(String key) { + return creator().createKey(key); + } + + public static Query createQuery(Collection.Key[] columns, int rows, String name) throws PageException { + return creator().createQuery(columns, rows, name); + } + + public static Query createQuery(Collection.Key[] columns, String[] types, int rows, String name) + throws PageException { + return creator().createQuery(columns, types, rows, name); + } + + public static Query createQuery(Array names, Array types, int rows, String name) throws PageException { + Collection.Key[] knames = new Collection.Key[names.size()]; + String[] ktypes = new String[types.size()]; + for (int i = names.size() - 1; i >= 0; i--) { + knames[i] = caster().toKey(names.getE(i + 1)); + ktypes[i] = caster().toString(types.getE(i + 1)); + } + return creator().createQuery(knames, ktypes, rows, name); + } + + public static RefBoolean createRefBoolean() { + return new RefBooleanImpl(); + } + + public static Key[] keys(Collection coll) { + if (coll == null) + return new Key[0]; + Iterator it = coll.keyIterator(); + List rtn = new ArrayList(); + if (it != null) + while (it.hasNext()) { + rtn.add(it.next()); + } + return rtn.toArray(new Key[rtn.size()]); + } + + private static Creation creator() { + if (creator == null) + creator = CFMLEngineFactory.getInstance().getCreationUtil(); + return creator; + } + + private static Decision decision() { + if (decision == null) + decision = CFMLEngineFactory.getInstance().getDecisionUtil(); + return decision; + } + + private static Cast caster() { + if (caster == null) + caster = CFMLEngineFactory.getInstance().getCastUtil(); + return caster; + } + + private static Operation op() { + if (op == null) + op = CFMLEngineFactory.getInstance().getOperatonUtil(); + return op; + } + + private static lucee.runtime.util.ListUtil list() { + if (list == null) + list = CFMLEngineFactory.getInstance().getListUtil(); + return list; + } + + private static ORMUtil orm() { + if (orm == null) + orm = CFMLEngineFactory.getInstance().getORMUtil(); + return orm; + } + + private static DBUtil db() { + if (db == null) + db = CFMLEngineFactory.getInstance().getDBUtil(); + return db; + } + + /** + * represents a SQL Statement with his defined arguments for a prepared statement + */ + static class SQLImpl implements SQL { + + private String strSQL; + + /** + * Constructor only with SQL String + * + * @param strSQL + * SQL String + */ + public SQLImpl(String strSQL) { + this.strSQL = strSQL; + } + + public void addItems(SQLItem item) { + + } + + @Override + public SQLItem[] getItems() { + return new SQLItem[0]; + } + + @Override + public int getPosition() { + return 0; + } + + @Override + public void setPosition(int position) { + } + + @Override + public String getSQLString() { + return strSQL; + } + + @Override + public void setSQLString(String strSQL) { + this.strSQL = strSQL; + } + + @Override + public String toString() { + return strSQL; + } + + @Override + public String toHashString() { + return strSQL; + } + } + + /** + * Integer Type that can be modified + */ + public static final class RefBooleanImpl implements RefBoolean {// MUST add interface Castable + + private boolean value; + + public RefBooleanImpl() { + } + + /** + * @param value + */ + public RefBooleanImpl(boolean value) { + this.value = value; + } + + /** + * @param value + */ + @Override + public void setValue(boolean value) { + this.value = value; + } + + /** + * @return returns value as Boolean Object + */ + @Override + public Boolean toBoolean() { + return value ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * @return returns value as boolean value + */ + @Override + public boolean toBooleanValue() { + return value; + } + + @Override + public String toString() { + return value ? "true" : "false"; + } + } + + /** + * Get the datasource defined for the provided name, or the default if name is null. + * + * @param pc + * Lucee's PageContext object. + * @param name + * Datasource name, or null to retrieve the default + * + * @return A Datasource object + * + * @throws PageException + */ + public static DataSource getDataSource(PageContext pc, String name) throws PageException { + if (Util.isEmpty(name, true)) + return orm().getDefaultDataSource(pc); + return pc.getDataSource(name); + } + + public static DatasourceConnection getDatasourceConnection(PageContext pc, DataSource ds, String user, String pass, + boolean transactionSensitive) throws PageException { + if (transactionSensitive) { + return pc.getDataSourceManager().getConnection(pc, ds, user, pass); + + } + + DBUtil dbutil = db(); + try { + if (mGetDatasourceConnection == null || dbutil.getClass() != mGetDatasourceConnection.getDeclaringClass()) { + mGetDatasourceConnection = dbutil.getClass().getMethod("getDatasourceConnection", GET_DSCONN); + } + return (DatasourceConnection) mGetDatasourceConnection.invoke(dbutil, + new Object[] { pc, ds, user, pass, false }); + } catch (Exception e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } + } + + public static void releaseDatasourceConnection(PageContext pc, DatasourceConnection dc, + boolean transactionSensitive) throws PageException { + // print.ds("rel:" + transactionSensitive); + if (transactionSensitive) { + pc.getDataSourceManager().releaseConnection(pc, dc); + return; + } + + DBUtil dbutil = db(); + try { + if (mReleaseDatasourceConnection == null + || dbutil.getClass() != mReleaseDatasourceConnection.getDeclaringClass()) { + mReleaseDatasourceConnection = dbutil.getClass().getMethod("releaseDatasourceConnection", REL_DSCONN); + } + mReleaseDatasourceConnection.invoke(dbutil, new Object[] { pc, dc, false }); + } catch (Exception e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } + } + + public static Mapping createMapping(Config config, String virtual, String physical) { + return creator().createMapping(config, virtual, physical, null, INSPECT_UNDEFINED, true, false, false, false, + true, true, null, -1, -1); + } + + public static String last(String list, String delimiter) { + return list().last(list, delimiter, true); + } + + public static int listFindNoCaseIgnoreEmpty(String list, String value, char delimiter) { + return list().findNoCaseIgnoreEmpty(list, value, delimiter); + } + + public static String[] trimItems(String[] arr) { + for (int i = 0; i < arr.length; i++) { + arr[i] = arr[i].trim(); + } + return arr; + } + + public static void setFirst(Node parent, Node node) { + XMLUtil.setFirst(parent, node); + } + + public static Property[] getProperties(Component c, boolean onlyPeristent, boolean includeBaseProperties, + boolean preferBaseProperties, boolean inheritedMappedSuperClassOnly) { + return c.getProperties(onlyPeristent, includeBaseProperties, preferBaseProperties, + inheritedMappedSuperClassOnly); + } + + public static void write(Resource res, String string, Charset cs, boolean append) throws IOException { + if (cs == null) + cs = getCharset(); + + Writer writer = null; + try { + writer = getWriter(res, cs, append); + writer.write(string); + } finally { + closeEL(writer); + } + } + + public static Writer getWriter(Resource res, Charset charset, boolean append) throws IOException { + OutputStream os = null; + try { + os = res.getOutputStream(append); + } catch (IOException ioe) { + closeEL(os); + throw ioe; + } + return getWriter(os, charset); + } + + public static Writer getWriter(OutputStream os, Charset cs) { + if (cs == null) + cs = getCharset(); + return new BufferedWriter(new OutputStreamWriter(os, getCharset())); + } + + public static BufferedReader toBufferedReader(Resource res, Charset charset) throws IOException { + return toBufferedReader(getReader(res, (Charset) null)); + } + + public static boolean equalsComplexEL(Object left, Object right) { + return op().equalsComplexEL(left, right, false, true); + } + + public static PageContext pc() { + return CFMLEngineFactory.getInstance().getThreadPageContext(); + } + + public static Config config() { + return pc().getConfig(); + } + + public static void closeEL(OutputStream os) { + if (os != null) { + try { + os.close(); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + } + + public static void closeEL(Writer w) { + if (w != null) { + try { + w.close(); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + } + + public static void closeEL(ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + } + + public static void closeEL(InputStream is) { + try { + if (is != null) + is.close(); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + + public static void closeEL(Reader r) { + try { + if (r != null) + r.close(); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + + public static boolean isRelated(Property property) { + return orm().isRelated(property); + } + + public static Object convertToSimpleMap(String paramsStr) { + return orm().convertToSimpleMap(paramsStr); + } + + public static String getDataSourceName(PageContext pc, Component cfc) throws PageException { + return orm().getDataSourceName(pc, cfc); + } + + public static DataSource getDataSource(PageContext pc, Component cfc) throws PageException { + return orm().getDataSource(pc, cfc); + } + + public static boolean equals(Component l, Component r) { + // TODO Auto-generated method stub + return orm().equals(l, r); + } + + public static DataSource getDefaultDataSource(PageContext pc) throws PageException { + return orm().getDefaultDataSource(pc); + } + + public static Object getPropertyValue(Component cfc, String name, Object defaultValue) { + return orm().getPropertyValue(cfc, name, defaultValue); + } + + public static String toBase64(Object o) throws PageException { + return caster().toBase64(o); + } + + public static Locale toLocale(String strLocale) throws PageException { + return caster().toLocale(strLocale); + } + + public static TimeZone toTimeZone(Object value, Object obj) throws PageException { + return caster().toTimeZone(obj); + } + + public static Character toCharacter(Object value) throws PageException { + return caster().toCharacter(value); + } + + public static DateTime toDate(Object value, TimeZone timeZone) throws PageException { + return caster().toDate(value, timeZone); + } + + public static Calendar toCalendar(DateTime date, TimeZone timeZone, Locale locale) { + return caster().toCalendar(date.getTime(), timeZone, locale); + } + + /** + * Tests if this string starts with the specified prefix. + *

+ * Blatantly copied from the Lucee core, since we don't have access to this method without reflection. + * + * @link https://github.com/lucee/Lucee/blob/6.0/core/src/main/java/lucee/commons/lang/StringUtil.java#L870 + * + * @param str + * string to check first char + * @param prefix + * the prefix. + * + * @return is first of given type + */ + public static boolean startsWith(String str, char prefix) { + return str != null && str.length() > 0 && str.charAt(0) == prefix; + } + + /** + * Tests if this string ends with the specified suffix. + *

+ * Blatantly copied from the Lucee core, since we don't have access to this method without reflection. + * + * @link https://github.com/lucee/Lucee/blob/6.0/core/src/main/java/lucee/commons/lang/StringUtil.java#L870 + * + * @param str + * string to check first char + * @param suffix + * the suffix. + * + * @return is last of given type + */ + public static boolean endsWith(String str, char suffix) { + return str != null && str.length() > 0 && str.charAt(str.length() - 1) == suffix; + } +} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/util/ConfigurationBuilder.java b/source/java/src/org/lucee/extension/orm/hibernate/util/ConfigurationBuilder.java new file mode 100644 index 00000000..9357151e --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/hibernate/util/ConfigurationBuilder.java @@ -0,0 +1,322 @@ +package org.lucee.extension.orm.hibernate.util; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Properties; + +import org.hibernate.MappingException; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.cache.ehcache.internal.EhcacheRegionFactory; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.lucee.extension.orm.hibernate.Dialect; +import org.lucee.extension.orm.hibernate.SessionFactoryData; +import org.lucee.extension.orm.hibernate.event.EventListenerIntegrator; +import org.lucee.extension.orm.hibernate.jdbc.ConnectionProviderImpl; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import lucee.commons.io.log.Log; +import lucee.commons.io.res.Resource; +import lucee.loader.engine.CFMLEngine; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.util.Util; +import lucee.runtime.db.DataSource; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMConfiguration; + +public class ConfigurationBuilder { + /** + * Store username and password for the configured datasource + */ + private HashMap datasourceCreds = new HashMap<>(); + + /** + * The event listener which will proxy Hibernate's Java events to the eventHandler CFC. + */ + private EventListenerIntegrator eventListener; + + /** + * The connection provider Hibernate should use if it needs to aquire its own database connections + */ + private ConnectionProvider connectionProvider; + + /** + * Hibernate Configuration object + */ + private Configuration configuration; + + /** + * Application ORM configuration set in the Application.cfc's this.ormSettings. + */ + private ORMConfiguration ormConf; + + /** + * The extension {@link org.lucee.extension.orm.hibernate.SessionFactoryData} + */ + private SessionFactoryData data; + + /** + * Application name, used as a unique key to identify a configuration set. + */ + private String applicationName; + + /** + * Datasource to operate on + */ + private DataSource datasource; + + /** + * Mapping XML document as a string + */ + private String xmlMappings; + + /** + * Lucee logger object, configured for the ORM log + */ + private Log log; + + /** + * Build out Hibernate configuration using the application's `this.ormSettings`, datasource, and generated mappings. + * + * @return Hibernate Configuration object + * @throws SQLException + * @throws IOException + * @throws PageException + */ + public Configuration build() throws SQLException, IOException, PageException { + BootstrapServiceRegistry bootstrapRegistry = new BootstrapServiceRegistryBuilder() + .applyIntegrator(this.eventListener).build(); + this.configuration = new Configuration(bootstrapRegistry); + + if (datasource != null) { + String dialect = null; + String tmpDialect = ORMConfigurationUtil.getDialect(ormConf, datasource.getName()); + if (!Util.isEmpty(tmpDialect)) + dialect = Dialect.getDialect(tmpDialect); + if (dialect != null && !Util.isEmpty(dialect)) { + configuration.setProperty(AvailableSettings.DIALECT, dialect); + } + + String catalog = ORMConfigurationUtil.getCatalog(ormConf, datasource.getName()); + String schema = ORMConfigurationUtil.getSchema(ormConf, datasource.getName()); + + if (!Util.isEmpty(catalog)) { + configuration.setProperty(AvailableSettings.DEFAULT_CATALOG, catalog); + } + if (!Util.isEmpty(schema)) { + configuration.setProperty(AvailableSettings.DEFAULT_SCHEMA, schema); + } + + if (this.connectionProvider == null) { + this.withConnectionProvider(new ConnectionProviderImpl(datasource, datasourceCreds.get("USERNAME"), + datasourceCreds.get("PASSWORD"))); + } + + addProperty(Environment.CONNECTION_PROVIDER, this.connectionProvider); + } + + // Cache Provider + String cacheProvider = ormConf.getCacheProvider(); + Class cacheProviderFactory = null; + + if (Util.isEmpty(cacheProvider) || "EHCache".equalsIgnoreCase(cacheProvider)) { + cacheProviderFactory = EhcacheRegionFactory.class; + } + // else if ("JBossCache".equalsIgnoreCase(cacheProvider)) cacheProvider = + // "org.hibernate.cache.TreeCacheProvider"; + // else if ("HashTable".equalsIgnoreCase(cacheProvider)) cacheProvider = + // "org.hibernate.cache.HashtableCacheProvider"; + // else if ("SwarmCache".equalsIgnoreCase(cacheProvider)) cacheProvider = + // "org.hibernate.cache.SwarmCacheProvider"; + // else if ("OSCache".equalsIgnoreCase(cacheProvider)) cacheProvider = + // "org.hibernate.cache.OSCacheProvider"; + + /// JBossCache -> https://mvnrepository.com/artifact/org.hibernate/hibernate-jbosscache + // OSCache -> https://mvnrepository.com/artifact/org.hibernate/hibernate-oscache + // SwarmCache -> https://mvnrepository.com/artifact/org.hibernate/hibernate-swarmcache + + Resource cc = ormConf.getCacheConfig(); + + // is ehcache + Resource cacheConfig = null; + if (cacheProvider != null && cacheProvider.toLowerCase().indexOf("ehcache") != -1) { + CFMLEngine eng = CFMLEngineFactory.getInstance(); + String varName = eng.getCastUtil().toVariableName(applicationName, applicationName); + String xml; + if (cc == null || !cc.isFile()) { + cacheConfig = eng.getResourceUtil().getTempDirectory().getRealResource("ehcache/" + varName + ".xml"); + xml = createEHConfigXML(varName); + } + // we need to change or set the name + else { + String b64 = varName + eng.getSystemUtil().hash64b(CommonUtil.toString(cc, (Charset) null)); + cacheConfig = eng.getResourceUtil().getTempDirectory().getRealResource("ehcache/" + b64 + ".xml"); + Document doc = CommonUtil.toDocument(cc, null); + Element root = doc.getDocumentElement(); + root.setAttribute("name", b64); + + xml = XMLUtil.toString(root); + } + + if (!cacheConfig.isFile()) { + cacheConfig.getParentResource().mkdirs(); + eng.getIOUtil().write(cacheConfig, xml, false, null); + } + } + + // ormConfig + Resource conf = ormConf.getOrmConfig(); + if (conf != null) { + try { + Document doc = CommonUtil.toDocument(conf, null); + configuration.configure(doc); + } catch (Exception e) { + log.log(Log.LEVEL_ERROR, "hibernate", e); + + } + } + + try { + configuration.addInputStream(new ByteArrayInputStream(xmlMappings.getBytes("UTF-8"))); + } catch (MappingException me) { + throw ExceptionUtil.createException(data, null, me); + } + + configuration.setProperty(AvailableSettings.FLUSH_BEFORE_COMPLETION, "false") + + .setProperty(AvailableSettings.ALLOW_UPDATE_OUTSIDE_TRANSACTION, "true") + + .setProperty(AvailableSettings.AUTO_CLOSE_SESSION, "false"); + + // Enable Hibernate's current session context + configuration.setProperty(AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS, "thread") + + // Echo all executed SQL to stdout + .setProperty(AvailableSettings.SHOW_SQL, ormConf.logSQL() ? "true" : "false") + // formatting of SQL logged to the console + .setProperty(AvailableSettings.FORMAT_SQL, ormConf.logSQL() ? "true" : "false") + // Specifies whether secondary caching should be enabled + .setProperty(AvailableSettings.USE_SECOND_LEVEL_CACHE, + ormConf.secondaryCacheEnabled() ? "true" : "false") + // Drop and re-create the database schema on startup + .setProperty("hibernate.exposeTransactionAwareSessionFactory", "false") + // .setProperty("hibernate.hbm2ddl.auto", "create") + .setProperty(AvailableSettings.DEFAULT_ENTITY_MODE, "dynamic-map"); + + if (ormConf.secondaryCacheEnabled()) { + if (cacheConfig != null && cacheConfig.isFile()) { + configuration.setProperty(AvailableSettings.CACHE_PROVIDER_CONFIG, cacheConfig.getAbsolutePath()); + if (cacheConfig instanceof File) + configuration.setProperty("net.sf.ehcache.configurationResourceName", + ((File) cacheConfig).toURI().toURL().toExternalForm()); + else + throw new IOException("only local configuration files are supported"); + + } + + if (cacheProviderFactory != null) { + addProperty(AvailableSettings.CACHE_REGION_FACTORY, cacheProviderFactory); + } + // org.hibernate.cache.EhCacheProvider + + configuration.setProperty(AvailableSettings.USE_QUERY_CACHE, "true"); + } + + return configuration; + } + + public ConfigurationBuilder withSessionFactoryData(SessionFactoryData data) { + this.data = data; + return this; + } + + public ConfigurationBuilder withEventListener(EventListenerIntegrator eventListener) { + this.eventListener = eventListener; + return this; + } + + public ConfigurationBuilder withORMConfig(ORMConfiguration ormConf) { + this.ormConf = ormConf; + return this; + } + + public ConfigurationBuilder withLog(Log log) { + this.log = log; + return this; + } + + public ConfigurationBuilder withDatasource(DataSource datasource) { + this.datasource = datasource; + return this; + } + + public ConfigurationBuilder withDatasourceCreds(String user, String pass) { + this.datasourceCreds.put("USERNAME", user); + this.datasourceCreds.put("PASSWORD", pass); + return this; + } + + public ConfigurationBuilder withXMLMappings(String xmlMappings) { + this.xmlMappings = xmlMappings; + return this; + } + + public ConfigurationBuilder withApplicationName(String applicationName) { + this.applicationName = applicationName; + return this; + } + + public ConfigurationBuilder withConnectionProvider(ConnectionProvider connectionProvider) { + this.connectionProvider = connectionProvider; + return this; + } + + /** + * Set a complex property on the provided Hibernate Configuration object. + * + * @param configuration + * Hibernate configuration on which to add a property + * @param name + * New setting / property name + * @param value + * Any value or object, like a {@link ConnectionProviderImpl} instance + */ + private void addProperty(String name, Object value) { + Properties props = new Properties(); + props.put(name, value); + configuration.addProperties(props); + } + + /** + * Generate an XML-format ehcache config file for the given cache name + *

+ * TODO: Add support for diskSpoolBufferSizeMB and clearOnFlush, added in ACF 9.0.1 + * + * @param cacheName + * Name of the cache + * + * @return XML string with formatting and line breaks + */ + private String createEHConfigXML(String cacheName) { + return new StringBuilder().append("").append("") + .append(" ").append(" ") + .append(" ").append(" ") + .append("").toString(); + } +} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/util/ExceptionUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/util/ExceptionUtil.java new file mode 100644 index 00000000..c17435a6 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/hibernate/util/ExceptionUtil.java @@ -0,0 +1,121 @@ +package org.lucee.extension.orm.hibernate.util; + +import java.lang.reflect.Method; + +import org.lucee.extension.orm.hibernate.SessionFactoryData; + +import lucee.loader.engine.CFMLEngineFactory; +import lucee.runtime.Component; +import lucee.runtime.db.DataSource; +// import lucee.runtime.exp.NativeException; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.type.Collection.Key; + +public class ExceptionUtil { + + private static Method setAdditional; + + /** + * Create a generic PageException with the given message. Utilizes Lucee's + * lucee.runtime.op.ExceptonImpl under the hood. + * + * @param message + * Exception message + * + * @return A PageException object + */ + public static PageException createException(String message) { + return CFMLEngineFactory.getInstance().getExceptionUtil().createApplicationException(message); + } + + /** + * Create a generic PageException with the given message and detail. Utilizes Lucee's + * lucee.runtime.op.ExceptonImpl under the hood. + * + * @param message + * Exception message + * @param detail + * Exception detail string + * + * @return A PageException object + */ + public static PageException createException(String message, String detail) { + return CFMLEngineFactory.getInstance().getExceptionUtil().createApplicationException(message, detail); + } + + public static PageException createException(SessionFactoryData data, Component cfc, String msg, String detail) { + + PageException pe = createException((ORMSession) null, cfc, msg, detail); + if (data != null) + setAddional(pe, data); + return pe; + } + + public static PageException createException(SessionFactoryData data, Component cfc, Throwable t) { + PageException pe = createException((ORMSession) null, cfc, t); + if (data != null) + setAddional(pe, data); + return pe; + } + + public static PageException createException(ORMSession session, Component cfc, Throwable t) { + return CFMLEngineFactory.getInstance().getORMUtil().createException(session, cfc, t); + } + + public static PageException createException(ORMSession session, Component cfc, String message, String detail) { + return CFMLEngineFactory.getInstance().getORMUtil().createException(session, cfc, message, detail); + } + + private static void setAddional(PageException pe, SessionFactoryData data) { + setAdditional(pe, CommonUtil.createKey("Entities"), + CFMLEngineFactory.getInstance().getListUtil().toListEL(data.getEntityNames(), ", ")); + setAddional(pe, data.getDataSources()); + } + + private static void setAddional(PageException pe, DataSource... sources) { + if (sources != null && sources.length > 0) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < sources.length; i++) { + if (i > 0) + sb.append(", "); + sb.append(sources[i].getName()); + } + setAdditional(pe, CommonUtil.createKey("_Datasource"), sb.toString()); + } + } + + public static void setAdditional(PageException pe, Key name, Object value) { + try { + if (setAdditional == null || setAdditional.getDeclaringClass() != pe.getClass()) { + setAdditional = pe.getClass().getMethod("setAdditional", new Class[] { Key.class, Object.class }); + } + setAdditional.invoke(pe, new Object[] { name, value }); + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + } + + /** + * A java.lang.ThreadDeath must never be caught, so any catch(Throwable t) must go through this method in order to + * ensure that the throwable is not of type ThreadDeath + * + * @param t + * the thrown Throwable + */ + public static void rethrowIfNecessary(Throwable t) { + if (unwrap(t) instanceof ThreadDeath) + throw (ThreadDeath) t; // never catch a ThreadDeath + } + + private static Throwable unwrap(Throwable t) { + if (t == null) + return t; + // if (t instanceof NativeException) return unwrap(((NativeException) t).getException()); + Throwable cause = t.getCause(); + if (cause != null && cause != t) + return unwrap(cause); + return t; + } +} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/util/HibernateUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/util/HibernateUtil.java new file mode 100755 index 00000000..1cc31b3e --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/hibernate/util/HibernateUtil.java @@ -0,0 +1,438 @@ +package org.lucee.extension.orm.hibernate.util; + +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.hibernate.HibernateException; +import org.hibernate.metadata.ClassMetadata; +import org.hibernate.type.ComponentType; +import org.hibernate.type.Type; +import org.lucee.extension.orm.hibernate.ColumnInfo; +import org.lucee.extension.orm.hibernate.HibernateCaster; +import org.lucee.extension.orm.hibernate.HibernateORMEngine; +import org.lucee.extension.orm.hibernate.HibernateORMSession; +import org.lucee.extension.orm.hibernate.SessionFactoryData; + +import lucee.commons.io.res.Resource; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.util.Util; +import lucee.runtime.Component; +import lucee.runtime.PageContext; +import lucee.runtime.PageSource; +import lucee.runtime.component.Property; +import lucee.runtime.config.Config; +import lucee.runtime.db.DatasourceConnection; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMConfiguration; +import lucee.runtime.orm.ORMSession; +import lucee.runtime.type.Collection; +import lucee.runtime.type.Struct; + +public class HibernateUtil { + + public static final short FIELDTYPE_ID = 0; + public static final short FIELDTYPE_COLUMN = 1; + public static final short FIELDTYPE_TIMESTAMP = 2; + public static final short FIELDTYPE_RELATION = 4; + public static final short FIELDTYPE_VERSION = 8; + public static final short FIELDTYPE_COLLECTION = 16; + + private static final String[] KEYWORDS = new String[] { "absolute", "access", "accessible", "action", "add", + "after", "alias", "all", "allocate", "allow", "alter", "analyze", "and", "any", "application", "are", + "array", "as", "asc", "asensitive", "assertion", "associate", "asutime", "asymmetric", "at", "atomic", + "audit", "authorization", "aux", "auxiliary", "avg", "backup", "before", "begin", "between", "bigint", + "binary", "bit", "bit_length", "blob", "boolean", "both", "breadth", "break", "browse", "bufferpool", + "bulk", "by", "cache", "call", "called", "capture", "cardinality", "cascade", "cascaded", "case", "cast", + "catalog", "ccsid", "change", "char", "char_length", "character", "character_length", "check", "checkpoint", + "clob", "close", "cluster", "clustered", "coalesce", "collate", "collation", "collection", "collid", + "column", "comment", "commit", "compress", "compute", "concat", "condition", "connect", "connection", + "constraint", "constraints", "constructor", "contains", "containstable", "continue", "convert", + "corresponding", "count", "count_big", "create", "cross", "cube", "current", "current_date", + "current_default_transform_group", "current_lc_ctype", "current_path", "current_role", "current_server", + "current_time", "current_timestamp", "current_timezone", "current_transform_group_for_type", "current_user", + "cursor", "cycle", "data", "database", "databases", "date", "day", "day_hour", "day_microsecond", + "day_minute", "day_second", "days", "db2general", "db2genrl", "db2sql", "dbcc", "dbinfo", "deallocate", + "dec", "decimal", "declare", "default", "defaults", "deferrable", "deferred", "delayed", "delete", "deny", + "depth", "deref", "desc", "describe", "descriptor", "deterministic", "diagnostics", "disallow", + "disconnect", "disk", "distinct", "distinctrow", "distributed", "div", "do", "domain", "double", "drop", + "dsnhattr", "dssize", "dual", "dummy", "dump", "dynamic", "each", "editproc", "else", "elseif", "enclosed", + "encoding", "end", "end-exec", "end-exec1", "endexec", "equals", "erase", "errlvl", "escape", "escaped", + "except", "exception", "excluding", "exclusive", "exec", "execute", "exists", "exit", "explain", "external", + "extract", "false", "fenced", "fetch", "fieldproc", "file", "fillfactor", "filter", "final", "first", + "float", "float4", "float8", "for", "force", "foreign", "found", "free", "freetext", "freetexttable", + "from", "full", "fulltext", "function", "general", "generated", "get", "get_current_connection", "global", + "go", "goto", "grant", "graphic", "group", "grouping", "handler", "having", "high_priority", "hold", + "holdlock", "hour", "hour_microsecond", "hour_minute", "hour_second", "hours", "identified", "identity", + "identity_insert", "identitycol", "if", "ignore", "immediate", "in", "including", "increment", "index", + "indicator", "infile", "inherit", "initial", "initially", "inner", "inout", "input", "insensitive", + "insert", "int", "int1", "int2", "int3", "int4", "int8", "integer", "integrity", "intersect", "interval", + "into", "is", "isobid", "isolation", "iterate", "jar", "java", "join", "key", "keys", "kill", "language", + "large", "last", "lateral", "leading", "leave", "left", "level", "like", "limit", "linear", "lineno", + "lines", "linktype", "load", "local", "locale", "localtime", "localtimestamp", "locator", "locators", + "lock", "lockmax", "locksize", "long", "longblob", "longint", "longtext", "loop", "low_priority", "lower", + "ltrim", "map", "master_ssl_verify_server_cert", "match", "max", "maxextents", "maxvalue", "mediumblob", + "mediumint", "mediumtext", "method", "microsecond", "microseconds", "middleint", "min", "minus", "minute", + "minute_microsecond", "minute_second", "minutes", "minvalue", "mlslabel", "mod", "mode", "modifies", + "modify", "module", "month", "months", "names", "national", "natural", "nchar", "nclob", "new", "new_table", + "next", "no", "no_write_to_binlog", "noaudit", "nocache", "nocheck", "nocompress", "nocycle", "nodename", + "nodenumber", "nomaxvalue", "nominvalue", "nonclustered", "none", "noorder", "not", "nowait", "null", + "nullif", "nulls", "number", "numeric", "numparts", "nvarchar", "obid", "object", "octet_length", "of", + "off", "offline", "offsets", "old", "old_table", "on", "online", "only", "open", "opendatasource", + "openquery", "openrowset", "openxml", "optimization", "optimize", "option", "optionally", "or", "order", + "ordinality", "out", "outer", "outfile", "output", "over", "overlaps", "overriding", "package", "pad", + "parameter", "part", "partial", "partition", "path", "pctfree", "percent", "piecesize", "plan", "position", + "precision", "prepare", "preserve", "primary", "print", "prior", "priqty", "privileges", "proc", + "procedure", "program", "psid", "public", "purge", "queryno", "raiserror", "range", "raw", "read", + "read_write", "reads", "readtext", "real", "reconfigure", "recovery", "recursive", "ref", "references", + "referencing", "regexp", "relative", "release", "rename", "repeat", "replace", "replication", "require", + "resignal", "resource", "restart", "restore", "restrict", "result", "result_set_locator", "return", + "returns", "revoke", "right", "rlike", "role", "rollback", "rollup", "routine", "row", "rowcount", + "rowguidcol", "rowid", "rownum", "rows", "rrn", "rtrim", "rule", "run", "runtimestatistics", "save", + "savepoint", "schema", "schemas", "scope", "scratchpad", "scroll", "search", "second", "second_microsecond", + "seconds", "secqty", "section", "security", "select", "sensitive", "separator", "session", "session_user", + "set", "sets", "setuser", "share", "show", "shutdown", "signal", "similar", "simple", "size", "smallint", + "some", "source", "space", "spatial", "specific", "specifictype", "sql", "sql_big_result", + "sql_calc_found_rows", "sql_small_result", "sqlcode", "sqlerror", "sqlexception", "sqlid", "sqlstate", + "sqlwarning", "ssl", "standard", "start", "starting", "state", "static", "statistics", "stay", "stogroup", + "stores", "straight_join", "style", "subpages", "substr", "substring", "successful", "sum", "symmetric", + "synonym", "sysdate", "sysfun", "sysibm", "sysproc", "system", "system_user", "table", "tablespace", + "temporary", "terminated", "textsize", "then", "time", "timestamp", "timezone_hour", "timezone_minute", + "tinyblob", "tinyint", "tinytext", "to", "top", "trailing", "tran", "transaction", "translate", + "translation", "treat", "trigger", "trim", "true", "truncate", "tsequal", "type", "uid", "under", "undo", + "union", "unique", "unknown", "unlock", "unnest", "unsigned", "until", "update", "updatetext", "upper", + "usage", "use", "user", "using", "utc_date", "utc_time", "utc_timestamp", "validate", "validproc", "value", + "values", "varbinary", "varchar", "varchar2", "varcharacter", "variable", "variant", "varying", "vcat", + "view", "volumes", "waitfor", "when", "whenever", "where", "while", "window", "with", "within", "without", + "wlm", "work", "write", "writetext", "xor", "year", "year_month", "zerofill", "zone" }; + private static final Set keywords = new HashSet(); + static { + for (int i = 0; i < KEYWORDS.length; i++) { + keywords.add(KEYWORDS[i]); + } + } + + public static boolean isKeyword(String word) { + if (word == null) + return false; + return keywords.contains(word.trim().toLowerCase()); + } + + public static Type getPropertyType(ClassMetadata metaData, String name) throws HibernateException { + try { + return metaData.getPropertyType(name); + } catch (HibernateException he) { + if (name.equalsIgnoreCase(metaData.getIdentifierPropertyName())) + return metaData.getIdentifierType(); + + String[] names = metaData.getPropertyNames(); + for (int i = 0; i < names.length; i++) { + if (names[i].equalsIgnoreCase(name)) + return metaData.getPropertyType(names[i]); + } + throw he; + } + } + + public static Type getPropertyType(ClassMetadata metaData, String name, Type defaultValue) { + try { + return metaData.getPropertyType(name); + } catch (HibernateException he) { + if (name.equalsIgnoreCase(metaData.getIdentifierPropertyName())) + return metaData.getIdentifierType(); + + String[] names = metaData.getPropertyNames(); + for (int i = 0; i < names.length; i++) { + if (names[i].equalsIgnoreCase(name)) + return metaData.getPropertyType(names[i]); + } + return defaultValue; + } + } + + public static String validateColumnName(ClassMetadata metaData, String name) throws PageException { + String res = validateColumnName(metaData, name, null); + if (res != null) + return res; + throw ExceptionUtil.createException((ORMSession) null, null, + "invalid name, there is no property with name [" + name + "] in the entity [" + metaData.getEntityName() + + "]", + "valid properties names are [" + CommonUtil.toList(metaData.getPropertyNames(), ", ") + "]"); + + } + + public static String validateColumnName(ClassMetadata metaData, String name, String defaultValue) { + Type type = metaData.getIdentifierType(); + // composite id + if (type.isComponentType()) { + String res = _validateColumnName(((ComponentType) type).getPropertyNames(), name); + if (res != null) + return res; + } + // regular id + String id = metaData.getIdentifierPropertyName(); + if (id != null && name.equalsIgnoreCase(id)) + return metaData.getIdentifierPropertyName(); + + String res = _validateColumnName(metaData.getPropertyNames(), name); + if (res != null) + return res; + return defaultValue; + } + + private static String _validateColumnName(String[] names, String name) { + if (names == null) + return null; + for (int i = 0; i < names.length; i++) { + if (names[i].equalsIgnoreCase(name)) + return names[i]; + } + return null; + } + + // + + public static Property[] createPropertiesFromTable(DatasourceConnection dc, String tableName) { + Struct properties = CommonUtil.createStruct(); + try { + DatabaseMetaData md = dc.getConnection().getMetaData(); + String dbName = CFMLEngineFactory.getInstance().getDBUtil().getDatabaseName(dc); + Collection.Key name; + + // get all columns + ResultSet res = md.getColumns(dbName, null, tableName, null); + while (res.next()) { + name = CommonUtil.createKey(res.getString("COLUMN_NAME")); + properties.setEL(name, CommonUtil.createProperty(name.getString(), res.getString("TYPE_NAME"))); + } + + // ids + res = md.getPrimaryKeys(null, null, tableName); + Property p; + while (res.next()) { + name = CommonUtil.createKey(res.getString("COLUMN_NAME")); + p = (Property) properties.get(name, null); + if (p != null) + p.getDynamicAttributes().setEL(CommonUtil.FIELDTYPE, "id"); + } + + // MUST foreign-key relation + + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + return new Property[0]; + } + + Iterator it = properties.valueIterator(); + Property[] rtn = new Property[properties.size()]; + for (int i = 0; i < rtn.length; i++) { + rtn[i] = (Property) it.next(); + } + + return rtn; + } + + public static Property[] getProperties(Component component, int fieldType, Property[] defaultValue) { + Property[] props = component.getProperties(true, false, false, false); + java.util.List rtn = new ArrayList(); + + if (props != null) { + for (int i = 0; i < props.length; i++) { + if (fieldType == getFieldType(props[i], FIELDTYPE_COLUMN)) + rtn.add(props[i]); + } + } + return rtn.toArray(new Property[rtn.size()]); + } + + private static int getFieldType(Property property, int defaultValue) { + return getFieldType(CommonUtil.toString(property.getDynamicAttributes().get(CommonUtil.FIELDTYPE, null), null), + defaultValue); + + } + + private static int getFieldType(String fieldType, int defaultValue) { + if (Util.isEmpty(fieldType, true)) + return defaultValue; + fieldType = fieldType.trim().toLowerCase(); + + if ("id".equals(fieldType)) + return FIELDTYPE_ID; + if ("column".equals(fieldType)) + return FIELDTYPE_COLUMN; + if ("timestamp".equals(fieldType)) + return FIELDTYPE_TIMESTAMP; + if ("relation".equals(fieldType)) + return FIELDTYPE_RELATION; + if ("version".equals(fieldType)) + return FIELDTYPE_VERSION; + if ("collection".equals(fieldType)) + return FIELDTYPE_COLLECTION; + return defaultValue; + } + + public static String convertTableName(SessionFactoryData data, String tableName) throws PageException { + if (tableName == null) + return null; + return data.getNamingStrategy().convertTableName(tableName); + } + + public static String convertColumnName(SessionFactoryData data, String columnName) throws PageException { + if (columnName == null) + return null; + return data.getNamingStrategy().convertColumnName(columnName); + } + + public static boolean isEntity(ORMConfiguration ormConf, Component cfc, String cfcName, String name) { + if (!Util.isEmpty(cfcName)) { + if (cfc.equalTo(cfcName)) + return true; + + if (cfcName.indexOf('.') != -1) { + String prefix = cfcName.replace('.', '/') + "."; + Resource[] locations = ormConf.getCfcLocations(); + Resource res; + for (int i = 0; i < locations.length; i++) { + res = locations[i].getRealResource(prefix + "cfc"); + if (res.equals(cfc.getPageSource().getResource())) + return true; + } + return false; + } + } + + if (cfc.equalTo(name)) + return true; + return name.equalsIgnoreCase(HibernateCaster.getEntityName(cfc)); + } + + public static String id(String id) { + return id.toLowerCase().trim(); + } + + public static Struct checkTable(DatasourceConnection dc, String tableName, SessionFactoryData data) + throws PageException { + + try { + String dbName = CFMLEngineFactory.getInstance().getDBUtil().getDatabaseName(dc); + DatabaseMetaData md = dc.getConnection().getMetaData(); + Struct rows = checkTableFill(md, dbName, tableName); + if (rows.size() == 0) { + String tableName2 = checkTableValidate(md, dbName, tableName); + if (tableName2 != null) + rows = checkTableFill(md, dbName, tableName2); + } + + if (rows.size() == 0) { + return null; + } + return rows; + } catch (SQLException e) { + throw CommonUtil.toPageException(e); + } + } + + private static Struct checkTableFill(DatabaseMetaData md, String dbName, String tableName) + throws SQLException, PageException { + Struct rows = CFMLEngineFactory.getInstance().getCreationUtil().createCastableStruct(tableName, + Struct.TYPE_LINKED); + ResultSet columns = md.getColumns(dbName, null, tableName, null); + try { + String name; + Object nullable; + while (columns.next()) { + name = columns.getString("COLUMN_NAME"); + + nullable = columns.getObject("IS_NULLABLE"); + rows.setEL(CommonUtil.createKey(name), + new ColumnInfo(name, columns.getInt("DATA_TYPE"), columns.getString("TYPE_NAME"), + columns.getInt("COLUMN_SIZE"), CommonUtil.toBooleanValue(nullable))); + } + } finally { + CommonUtil.closeEL(columns); + } // Table susid defined for cfc susid does not exist. + + return rows; + } + + private static String checkTableValidate(DatabaseMetaData md, String dbName, String tableName) { + + ResultSet tables = null; + try { + tables = md.getTables(dbName, null, null, null); + String name; + while (tables.next()) { + name = tables.getString("TABLE_NAME"); + if (name.equalsIgnoreCase(tableName) + && tables.getString("TABLE_TYPE").toUpperCase().indexOf("SYSTEM") == -1) + return name; + } + } catch (Throwable t) { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } finally { + CommonUtil.closeEL(tables); + } + return null; + + } + + public static HibernateORMEngine getORMEngine(PageContext pc) throws PageException { + if (pc == null) + pc = CommonUtil.pc(); + Config config = pc.getConfig(); + return (HibernateORMEngine) config.getORMEngine(pc);// TODO add this method to the public interface + } + + public static HibernateORMSession getORMSession(PageContext pc, boolean create) throws PageException { + return (HibernateORMSession) pc.getORMSession(create);// TODO add this method to the public interface + } + + public static Property[] getIDProperties(Component c, boolean onlyPeristent, boolean includeBaseProperties) { + Property[] props = CommonUtil.getProperties(c, onlyPeristent, includeBaseProperties, false, false); + java.util.List tmp = new ArrayList(); + for (int i = 0; i < props.length; i++) { + if ("id".equalsIgnoreCase( + CommonUtil.toString(props[i].getDynamicAttributes().get(CommonUtil.FIELDTYPE, null), ""))) + tmp.add(props[i]); + } + return tmp.toArray(new Property[tmp.size()]); + } + + public static long getCompileTime(PageContext pc, PageSource ps) throws PageException { + return CFMLEngineFactory.getInstance().getTemplateUtil().getCompileTime(pc, ps); + } + + public static String removeExtension(String filename, String defaultValue) { + int index = filename.lastIndexOf('.'); + if (index == -1) + return defaultValue; + return filename.substring(0, index); + } + + public static String[] merge(String[] arr1, String[] arr2) { + String[] ret = new String[arr1.length + arr2.length]; + for (int i = 0; i < arr1.length; i++) { + ret[i] = arr1[i]; + } + for (int i = 0; i < arr2.length; i++) { + ret[arr1.length + i] = arr2[i]; + } + return ret; + } + + /** + * Check filename string against known application.cfc name. + * + * @param name Filename to check + * @return True if string matches 'application.cfc'. + */ + public static boolean isApplicationName(String name) { + return name.toLowerCase().equalsIgnoreCase("application.cfc"); + } +} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/util/ORMConfigurationUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/util/ORMConfigurationUtil.java new file mode 100644 index 00000000..daad8a23 --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/hibernate/util/ORMConfigurationUtil.java @@ -0,0 +1,137 @@ +package org.lucee.extension.orm.hibernate.util; + +import java.lang.reflect.Method; + +import lucee.commons.io.res.Resource; +import lucee.loader.engine.CFMLEngine; +import lucee.loader.engine.CFMLEngineFactory; +import lucee.loader.util.Util; +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMConfiguration; + +// FUTURE update ORMConfiguration interface +public class ORMConfigurationUtil { + + private static final Class[] CLASS_STRING = new Class[] { String.class }; + private static Method getDbCreate; + private static Method getCatalog; + private static Method getSchema; + private static Method getSqlScript; + private static Method getDialect; + + public static int getDbCreate(ORMConfiguration conf, String datasourceName) throws PageException { + if (!Util.isEmpty(datasourceName) + && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { + CFMLEngine eng = CFMLEngineFactory.getInstance(); + // Lucee >= 5.3.2.16 + try { + if (getDbCreate == null || getDbCreate.getDeclaringClass() != conf.getClass()) { + getDbCreate = conf.getClass().getMethod("getDbCreate", CLASS_STRING); + } + return eng.getCastUtil().toIntValue(getDbCreate.invoke(conf, new Object[] { datasourceName })); + } catch (NoSuchMethodException e) { + // older Lucee version + } catch (Exception e) { + throw eng.getCastUtil().toPageException(e); + } + } + return conf.getDbCreate(); + } + + public static String getCatalog(ORMConfiguration conf, String datasourceName) throws PageException { + if (!Util.isEmpty(datasourceName) + && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { + CFMLEngine eng = CFMLEngineFactory.getInstance(); + // Lucee >= 5.3.2.16 + try { + if (getCatalog == null || getCatalog.getDeclaringClass() != conf.getClass()) { + getCatalog = conf.getClass().getMethod("getCatalog", CLASS_STRING); + } + return eng.getCastUtil().toString(getCatalog.invoke(conf, new Object[] { datasourceName })); + } catch (NoSuchMethodException e) { + // older Lucee version + } catch (Exception e) { + throw eng.getCastUtil().toPageException(e); + } + } + return conf.getCatalog(); + } + + public static String getSchema(ORMConfiguration conf, String datasourceName) throws PageException { + if (!Util.isEmpty(datasourceName) + && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { + CFMLEngine eng = CFMLEngineFactory.getInstance(); + // Lucee >= 5.3.2.16 + try { + if (getSchema == null || getSchema.getDeclaringClass() != conf.getClass()) { + getSchema = conf.getClass().getMethod("getSchema", CLASS_STRING); + } + return eng.getCastUtil().toString(getSchema.invoke(conf, new Object[] { datasourceName })); + } catch (NoSuchMethodException e) { + // older Lucee version + } catch (Exception e) { + throw eng.getCastUtil().toPageException(e); + } + } + return conf.getSchema(); + } + + public static String getDialect(ORMConfiguration conf, String datasourceName) throws PageException { + if (!Util.isEmpty(datasourceName) + && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { + CFMLEngine eng = CFMLEngineFactory.getInstance(); + // Lucee >= 5.3.2.16 + try { + if (getDialect == null || getDialect.getDeclaringClass() != conf.getClass()) { + getDialect = conf.getClass().getMethod("getDialect", CLASS_STRING); + } + return eng.getCastUtil().toString(getDialect.invoke(conf, new Object[] { datasourceName })); + } catch (NoSuchMethodException e) { + // older Lucee version + } catch (Exception e) { + throw eng.getCastUtil().toPageException(e); + } + } + return conf.getDialect(); + } + + public static Resource getSqlScript(ORMConfiguration conf, String datasourceName) throws PageException { + if (!Util.isEmpty(datasourceName) + && !(datasourceName = datasourceName.trim().toLowerCase()).equals("__default__")) { + CFMLEngine eng = CFMLEngineFactory.getInstance(); + // Lucee >= 5.3.2.16 + try { + if (getSqlScript == null || getSqlScript.getDeclaringClass() != conf.getClass()) { + getSqlScript = conf.getClass().getMethod("getSqlScript", CLASS_STRING); + } + return (Resource) getSqlScript.invoke(conf, new Object[] { datasourceName }); + } catch (NoSuchMethodException e) { + // older Lucee version + } catch (Exception e) { + throw eng.getCastUtil().toPageException(e); + } + } + return conf.getSqlScript(); + } + + public static void dump(ORMConfiguration ormConf, String name) throws PageException { + + System.err.println("---------------- " + name + " ---------------------"); + System.err.println("catalog: " + getCatalog(ormConf, name)); + System.err.println("dialect: " + getDialect(ormConf, name)); + System.err.println("schema: " + getSchema(ormConf, name)); + System.err.println("DbCreate: " + getDbCreate(ormConf, name)); + System.err.println("SqlScript: " + getSqlScript(ormConf, name)); + + name = "susi"; + + System.err.println("---------------- " + name + " ---------------------"); + System.err.println("catalog: " + getCatalog(ormConf, name)); + System.err.println("dialect: " + getDialect(ormConf, name)); + System.err.println("schema: " + getSchema(ormConf, name)); + System.err.println("DbCreate: " + getDbCreate(ormConf, name)); + System.err.println("SqlScript: " + getSqlScript(ormConf, name)); + + } + +} diff --git a/source/java/src/org/lucee/extension/orm/hibernate/util/ORMUtil.java b/source/java/src/org/lucee/extension/orm/hibernate/util/ORMUtil.java new file mode 100644 index 00000000..b3e75b8f --- /dev/null +++ b/source/java/src/org/lucee/extension/orm/hibernate/util/ORMUtil.java @@ -0,0 +1,401 @@ +/** + * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. + * Copyright (c) 2015, Lucee Assosication Switzerland + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + */ +package org.lucee.extension.orm.hibernate.util; + +import java.util.ArrayList; + +import lucee.runtime.orm.ORMSession; +import lucee.runtime.Component; +import lucee.runtime.PageContext; +// import lucee.runtime.PageContextImpl; +import lucee.runtime.component.Property; +import lucee.runtime.orm.ORMEngine; +import lucee.runtime.db.DataSource; +// import lucee.runtime.engine.ThreadLocalPageContext; +import lucee.runtime.exp.PageException; +import lucee.runtime.type.Collection.Key; +import lucee.runtime.type.Struct; +import lucee.loader.util.Util; + +public class ORMUtil { + + public static final Key PROPS_FIELDTYPE = CommonUtil.createKey("fieldtype"); + public static final Key PROPS_DATASOURCE = CommonUtil.createKey("datasource"); + + public static final String DELIMITER = new String("."); + + public static ORMSession getSession(PageContext pc) throws PageException { + return getSession(pc, true); + } + + public static ORMSession getSession(PageContext pc, boolean create) throws PageException { + return pc.getORMSession(create); + } + + // /** + // * Override's Lucee's {@link lucee.runtime.PageContext#getORMSession(boolean)} method to avoid stupidly creating a + // new session if one already exists. + // * + // * @param create Create a new session if none found. + // * @return A new or previously existing {@link lucee.runtime.orm.ORMSession} + // * @throws PageException + // */ + // public ORMSession getORMSession(boolean create) throws PageException { + // if (ormSession == null || !ormSession.isValid()) { + // if (!create) return null; + // ormSession = config.getORMEngine(this).createSession(this); + // } + // DatasourceManagerImpl manager = (DatasourceManagerImpl) getDataSourceManager(); + // manager.add(this, ormSession); + + // return ormSession; + // } + + public static ORMEngine getEngine(PageContext pc) throws PageException { + return pc.getConfig().getORMEngine(pc); + } + + /** + * + * @param pc + * @param force + * if set to false the engine is on loaded when the configuration has changed + * + * @throws PageException + */ + public static ORMEngine resetEngine(PageContext pc, boolean force) throws PageException { + ORMEngine e = getEngine(pc); + e.reload(pc, force); + return e; + } + + // public static boolean equals(Object left, Object right) { + // HashSet done = new HashSet(); + // return _equals(done, left, right); + // } + + // private static boolean _equals(HashSet done, Object left, Object right) { + + // if (left == right) return true; + // if (left == null || right == null) return false; + + // // components + // if (left instanceof Component && right instanceof Component) { + // return _equals(done, (Component) left, (Component) right); + // } + + // // arrays + // if (CommonUtil.isArray(left) && CommonUtil.isArray(right)) { + // return _equals(done, CommonUtil.toArray(left, null), CommonUtil.toArray(right, null)); + // } + + // // struct + // if (CommonUtil.isStruct(left) && CommonUtil.isStruct(right)) { + // return _equals(done, CommonUtil.toStruct(left, null), CommonUtil.toStruct(right, null)); + // } + + // try { + // return OpUtil.equals(ThreadLocalPageContext.get(), left, right, false); + // } + // catch (PageException e) { + // return false; + // } + // } + + // private static boolean _equals(HashSet done, Collection left, Collection right) { + // if (done.contains(left)) return done.contains(right); + // done.add(left); + // done.add(right); + + // if (left.size() != right.size()) return false; + // // Key[] keys = left.keys(); + // Iterator> it = left.entryIterator(); + // Entry e; + // Object l, r; + // while (it.hasNext()) { + // e = it.next(); + // l = e.getValue(); + // r = right.get(e.getKey(), null); + // if (r == null || !_equals(done, l, r)) return false; + // } + // return true; + // } + + // private static boolean _equals(HashSet done, Component left, Component right) { + // if (done.contains(left)) return done.contains(right); + // done.add(left); + // done.add(right); + + // if (left == null || right == null) return false; + // if (!left.getPageSource().equals(right.getPageSource())) return false; + // Property[] props = getProperties(left); + // Object l, r; + // props = getIds(props); + // for (int i = 0; i < props.length; i++) { + // l = left.getComponentScope().get(CommonUtil.createKey(props[i].getName()), null); + // r = right.getComponentScope().get(CommonUtil.createKey(props[i].getName()), null); + // if (!_equals(done, l, r)) return false; + // } + // return true; + // } + + public static Property[] getIds(Property[] props) { + ArrayList ids = new ArrayList(); + for (int y = 0; y < props.length; y++) { + String fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(PROPS_FIELDTYPE, null), null); + Character delimiterChar = Character.valueOf(DELIMITER.charAt(0)); + if ("id".equalsIgnoreCase(fieldType) + || CommonUtil.listFindNoCaseIgnoreEmpty(fieldType, "id", delimiterChar) != -1) + ids.add(props[y]); + } + + // no id field defined + if (ids.size() == 0) { + String fieldType; + for (int y = 0; y < props.length; y++) { + fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(PROPS_FIELDTYPE, null), null); + if (Util.isEmpty(fieldType, true) && props[y].getName().equalsIgnoreCase("id")) { + ids.add(props[y]); + props[y].getDynamicAttributes().setEL(PROPS_FIELDTYPE, "id"); + } + } + } + + // still no id field defined + if (ids.size() == 0 && props.length > 0) { + String owner = props[0].getOwnerName(); + if (!Util.isEmpty(owner)) + owner = CommonUtil.last(owner, DELIMITER).trim(); + + String fieldType; + if (!Util.isEmpty(owner)) { + String id = owner + "id"; + for (int y = 0; y < props.length; y++) { + fieldType = CommonUtil.toString(props[y].getDynamicAttributes().get(PROPS_FIELDTYPE, null), null); + if (Util.isEmpty(fieldType, true) && props[y].getName().equalsIgnoreCase(id)) { + ids.add(props[y]); + props[y].getDynamicAttributes().setEL(PROPS_FIELDTYPE, "id"); + } + } + } + } + return ids.toArray(new Property[ids.size()]); + } + + public static Object getPropertyValue(Component cfc, String name, Object defaultValue) { + Property[] props = getProperties(cfc); + + for (int i = 0; i < props.length; i++) { + if (!props[i].getName().equalsIgnoreCase(name)) + continue; + return cfc.getComponentScope().get(CommonUtil.createKey(name), null); + } + return defaultValue; + } + /* + * jira2049 public static Object getPropertyValue(ORMSession session,Component cfc, String name, Object + * defaultValue) { Property[] props=getProperties(cfc); Object raw=null; SessionImpl sess=null; if(session!=null){ + * raw=session.getRawSession(); if(raw instanceof SessionImpl) sess=(SessionImpl) raw; } Object val; for(int + * i=0;i clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLUtil"); - Method method = clazz.getMethod("toInputSource", new Class[] { Object.class }); - return (InputSource) method.invoke(null, new Object[] { obj }); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - } + public static InputSource toInputSource(Object obj) throws PageException { + // FUTURE use interface from loader + try { + Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLUtil"); + Method method = clazz.getMethod("toInputSource", new Class[] { Object.class }); + return (InputSource) method.invoke(null, new Object[] { obj }); + } catch (Exception e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } + } - public static InputSource toInputSource(Resource res, Charset cs) throws PageException { - // FUTURE use interface from loader - try { - Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLUtil"); - Method method = clazz.getMethod("toInputSource", new Class[] { Resource.class, Charset.class }); - return (InputSource) method.invoke(null, new Object[] { res, cs }); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - } + public static InputSource toInputSource(Resource res, Charset cs) throws PageException { + // FUTURE use interface from loader + try { + Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLUtil"); + Method method = clazz.getMethod("toInputSource", new Class[] { Resource.class, Charset.class }); + return (InputSource) method.invoke(null, new Object[] { res, cs }); + } catch (Exception e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } + } - public static final Document parse(InputSource xml, InputSource validator, boolean isHtml) throws PageException { - // FUTURE use interface from loader - try { - Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLUtil"); - Method method = clazz.getMethod("parse", new Class[] { InputSource.class, InputSource.class, boolean.class }); - return (Document) method.invoke(null, new Object[] { xml, validator, isHtml }); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - } + public static final Document parse(InputSource xml, InputSource validator, boolean isHtml) throws PageException { + // FUTURE use interface from loader + try { + Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLUtil"); + Method method = clazz.getMethod("parse", + new Class[] { InputSource.class, InputSource.class, boolean.class }); + return (Document) method.invoke(null, new Object[] { xml, validator, isHtml }); + } catch (Exception e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } + } - public static Document newDocument() throws PageException { - // FUTURE use interface from loader - try { - Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLUtil"); - Method method = clazz.getMethod("newDocument", new Class[] {}); - return (Document) method.invoke(null, new Object[] {}); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - } + public static Document newDocument() throws PageException { + // FUTURE use interface from loader + try { + Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLUtil"); + Method method = clazz.getMethod("newDocument", new Class[] {}); + return (Document) method.invoke(null, new Object[] {}); + } catch (Exception e) { + throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); + } + } - // toString(node, omitXMLDecl, indent, publicId, systemId, encoding); - public static String toString(NodeList nodeList, boolean omitXMLDecl, boolean indent) throws PageException { - // FUTURE use interface from loader - try { - Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLCaster"); - Method method = clazz.getMethod("toString", new Class[] { NodeList.class, boolean.class, boolean.class }); - return (String) method.invoke(null, new Object[] { nodeList, omitXMLDecl, indent }); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - } + /** + * Generate an XML string from the provided w3c Document Element. + * + * @param document + * The root element of an XML document. + * + * @return a fully-formed and formatted XML string. Does not append or prepend tags or DOCTYPE, etc. + * + * @throws PageException + */ + public static String toString(Element document) throws PageException { + try { + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(document), new StreamResult(writer)); + return writer.toString(); + } catch (Exception e) { + throw CommonUtil.toPageException(e); + } + } - // toString(node, omitXMLDecl, indent, publicId, systemId, encoding); - public static String toString(Node node, boolean omitXMLDecl, boolean indent, String publicId, String systemId, String encoding) throws PageException { - // FUTURE use interface from loader - try { - Class clazz = CFMLEngineFactory.getInstance().getClassUtil().loadClass("lucee.runtime.text.xml.XMLCaster"); - Method method = clazz.getMethod("toString", new Class[] { Node.class, boolean.class, boolean.class, String.class, String.class, String.class }); - return (String) method.invoke(null, new Object[] { node, omitXMLDecl, indent, publicId, systemId, encoding }); - } - catch (Exception e) { - throw CFMLEngineFactory.getInstance().getCastUtil().toPageException(e); - } - } + public static Node toNode(Object value) throws PageException { + if (value instanceof Node) + return (Node) value; + return parse(toInputSource(value), null, false); + } - public static Node toNode(Object value) throws PageException { - if (value instanceof Node) return (Node) value; - return parse(toInputSource(value), null, false); - } + public static Document getDocument(Node node) { + if (node instanceof Document) + return (Document) node; + return node.getOwnerDocument(); + } - public static Document getDocument(Node node) { - if (node instanceof Document) return (Document) node; - return node.getOwnerDocument(); - } - - public static void setFirst(Node parent, Node node) { - Node first = parent.getFirstChild(); - if (first != null) parent.insertBefore(node, first); - else parent.appendChild(node); - } + public static void setFirst(Node parent, Node node) { + Node first = parent.getFirstChild(); + if (first != null) + parent.insertBefore(node, first); + else + parent.appendChild(node); + } } diff --git a/source/java/src/org/lucee/extension/orm/hibernate/util/aprint.java b/source/java/src/org/lucee/extension/orm/hibernate/util/aprint.java deleted file mode 100644 index 910abce2..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/util/aprint.java +++ /dev/null @@ -1,432 +0,0 @@ -/** - * - * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - * - **/ -package org.lucee.extension.orm.hibernate.util; - -import java.io.PrintStream; -import java.lang.reflect.InvocationTargetException; -import java.util.Date; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Set; - -import javax.servlet.http.Cookie; - -import org.w3c.dom.Attr; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; - -import lucee.loader.engine.CFMLEngineFactory; - -/** - * - */ -public class aprint { - - public static void date(String value) { - long millis = System.currentTimeMillis(); - o(new Date(millis) + "-" + (millis - (millis / 1000 * 1000)) + " " + value); - } - - public static void ds(boolean useOutStream) { - new Exception("Stack trace").printStackTrace(useOutStream ? System.out : System.err); - } - - public static void ds(Object label, boolean useOutStream) { - _eo(useOutStream ? System.out : System.err, label); - ds(useOutStream); - } - - public static void ds() { - ds(false); - } - - public static void ds(Object label) { - ds(label, false); - } - - public static void dumpStack() { - ds(false); - } - - public static void dumpStack(boolean useOutStream) { - ds(useOutStream); - } - - public static void dumpStack(String label) { - ds(label, false); - } - - public static void dumpStack(String label, boolean useOutStream) { - ds(label, useOutStream); - } - - public static void err(boolean o) { - System.err.println(o); - } - - public static void err(double d) { - System.err.println(d); - } - - public static void err(long d) { - System.err.println(d); - } - - public static void err(float d) { - System.err.println(d); - } - - public static void err(int d) { - System.err.println(d); - } - - public static void err(short d) { - System.err.println(d); - } - - public static void out(Object o1, Object o2, Object o3) { - System.out.print(o1); - System.out.print(o2); - System.out.println(o3); - } - - public static void out(Object o1, Object o2) { - System.out.print(o1); - System.out.println(o2); - } - - public static void out(Object o, long l) { - System.out.print(o); - System.out.println(l); - } - - public static void out(Object o, double d) { - System.out.print(o); - System.out.println(d); - } - - public static void out(byte[] arr, int offset, int len) { - System.out.print("byte[]{"); - for (int i = offset; i < len + offset; i++) { - if (i > 0) System.out.print(','); - System.out.print(arr[i]); - } - System.out.println("}"); - } - - public static void out(double o) { - System.out.println(o); - } - - public static void out(float o) { - System.out.println(o); - } - - public static void out(long o) { - System.out.println(o); - } - - public static void out(int o) { - System.out.println(o); - } - - public static void out(char o) { - System.out.println(o); - } - - public static void out(boolean o) { - System.out.println(o); - } - - public static void out() { - System.out.println(); - } - - public static void printST(Throwable t) { - if (t instanceof InvocationTargetException) { - t = ((InvocationTargetException) t).getTargetException(); - } - err(t.getClass().getName()); - t.printStackTrace(); - - } - - public static void printST(Throwable t, PrintStream ps) { - if (t instanceof InvocationTargetException) { - t = ((InvocationTargetException) t).getTargetException(); - } - err(t.getClass().getName()); - t.printStackTrace(ps); - - } - - public static void out(Object o) { - _eo(System.out, o); - } - - public static void err(Object o) { - _eo(System.err, o); - } - - public static void o(Object o) { - _eo(System.out, o); - } - - public static void e(Object o) { - _eo(System.err, o); - } - - public static void oe(Object o, boolean valid) { - _eo(valid ? System.out : System.err, o); - } - - public static void dateO(String value) { - _date(System.out, value); - } - - public static void dateE(String value) { - _date(System.err, value); - } - - private static void _date(PrintStream ps, String value) { - long millis = System.currentTimeMillis(); - _eo(ps, new Date(millis) + "-" + (millis - (millis / 1000 * 1000)) + " " + value); - } - - private static void _eo(PrintStream ps, Object o) { - if (o instanceof Enumeration) _eo(ps, (Enumeration) o); - else if (o instanceof Object[]) _eo(ps, (Object[]) o); - else if (o instanceof boolean[]) _eo(ps, (boolean[]) o); - else if (o instanceof byte[]) _eo(ps, (byte[]) o); - else if (o instanceof int[]) _eo(ps, (int[]) o); - else if (o instanceof float[]) _eo(ps, (float[]) o); - else if (o instanceof long[]) _eo(ps, (long[]) o); - else if (o instanceof double[]) _eo(ps, (double[]) o); - else if (o instanceof char[]) _eo(ps, (char[]) o); - else if (o instanceof short[]) _eo(ps, (short[]) o); - else if (o instanceof Set) _eo(ps, (Set) o); - else if (o instanceof List) _eo(ps, (List) o); - else if (o instanceof Map) _eo(ps, (Map) o); - else if (o instanceof Iterator) _eo(ps, (Iterator) o); - else if (o instanceof NamedNodeMap) _eo(ps, (NamedNodeMap) o); - else if (o instanceof Node) _eo(ps, (Node) o); - else if (o instanceof Throwable) _eo(ps, (Throwable) o); - else if (o instanceof Cookie) { - Cookie c = (Cookie) o; - ps.println("Cookie(name:" + c.getName() + ";domain:" + c.getDomain() + ";maxage:" + c.getMaxAge() + ";path:" + c.getPath() + ";value:" + c.getValue() + ";version:" - + c.getVersion() + ";secure:" + c.getSecure() + ")"); - } - - else ps.println(o); - } - - private static void _eo(PrintStream ps, Object[] arr) { - if (arr == null) { - ps.println("null"); - return; - } - ps.print(arr.getClass().getComponentType().getName() + "[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) { - ps.print("\t,"); - } - _eo(ps, arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, int[] arr) { - ps.print("int[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) ps.print(','); - ps.print(arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, byte[] arr) { - ps.print("byte[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) ps.print(','); - ps.print(arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, boolean[] arr) { - ps.print("boolean[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) ps.print(','); - ps.print(arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, char[] arr) { - ps.print("char[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) ps.print(','); - ps.print(arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, short[] arr) { - ps.print("short[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) ps.print(','); - ps.print(arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, float[] arr) { - ps.print("float[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) ps.print(','); - ps.print(arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, long[] arr) { - ps.print("long[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) ps.print(','); - ps.print(arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, double[] arr) { - ps.print("double[]{"); - for (int i = 0; i < arr.length; i++) { - if (i > 0) ps.print(','); - ps.print(arr[i]); - } - ps.println("}"); - } - - private static void _eo(PrintStream ps, Node n) { - ps.print(CFMLEngineFactory.getInstance().getCastUtil().toString(n, null)); - } - - private static void _eo(PrintStream ps, Throwable t) { - t.printStackTrace(ps); - } - - private static void _eo(PrintStream ps, Enumeration en) { - - _eo(ps, en.getClass().getName() + " ["); - while (en.hasMoreElements()) { - ps.print(en.nextElement()); - ps.println(","); - } - _eo(ps, "]"); - } - - private static void _eo(PrintStream ps, List list) { - ListIterator it = list.listIterator(); - _eo(ps, list.getClass().getName() + " {"); - while (it.hasNext()) { - int index = it.nextIndex(); - it.next(); - ps.print(index); - ps.print(":"); - ps.print(list.get(index)); - ps.println(";"); - } - _eo(ps, "}"); - } - - private static void _eo(PrintStream ps, Iterator it) { - - _eo(ps, it.getClass().getName() + " {"); - while (it.hasNext()) { - ps.print(it.next()); - ps.println(";"); - } - _eo(ps, "}"); - } - - private static void _eo(PrintStream ps, Set set) { - Iterator it = set.iterator(); - ps.println(set.getClass().getName() + " {"); - while (it.hasNext()) { - _eo(ps, it.next()); - ps.println(","); - } - _eo(ps, "}"); - } - - private static void _eo(PrintStream ps, Map map) { - if (map == null) { - ps.println("null"); - return; - } - Iterator it = map.keySet().iterator(); - - if (map.size() < 2) { - ps.print(map.getClass().getName() + " {"); - while (it.hasNext()) { - Object key = it.next(); - - ps.print(key); - ps.print(":"); - ps.print(map.get(key)); - } - ps.println("}"); - } - else { - ps.println(map.getClass().getName() + " {"); - while (it.hasNext()) { - Object key = it.next(); - ps.print(" "); - ps.print(key); - ps.print(":"); - ps.print(map.get(key)); - ps.println(";"); - } - ps.println("}"); - } - } - - private static void _eo(PrintStream ps, NamedNodeMap map) { - if (map == null) { - ps.println("null"); - return; - } - int len = map.getLength(); - ps.print(map.getClass().getName() + " {"); - Attr attr; - for (int i = 0; i < len; i++) { - attr = (Attr) map.item(i); - - ps.print(attr.getName()); - ps.print(":"); - ps.print(attr.getValue()); - ps.println(";"); - } - ps.println("}"); - } - -} \ No newline at end of file diff --git a/source/java/src/org/lucee/extension/orm/hibernate/util/print.java b/source/java/src/org/lucee/extension/orm/hibernate/util/print.java deleted file mode 100644 index 721b1310..00000000 --- a/source/java/src/org/lucee/extension/orm/hibernate/util/print.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * - * Copyright (c) 2015, Lucee Association Switzerland. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - * - **/ -package org.lucee.extension.orm.hibernate.util; - -/** - * - */ -public final class print extends aprint { - -} \ No newline at end of file diff --git a/source/lex.xml b/source/lex.xml new file mode 100644 index 00000000..426078b5 --- /dev/null +++ b/source/lex.xml @@ -0,0 +1,56 @@ + + lex + false + + + zip + + + + ${project.build.directory}/META-INF/ + /META-INF/ + + + + ${project.basedir}/source/java/libs + /jars/ + + javax.servlet.jar + lucee.jar + + + + + + ${project.basedir}/source/images/logo.png + /META-INF/ + + + ${project.build.directory}/${project.artifactId}-${project.version}.jar + /jars + + + + \ No newline at end of file diff --git a/src/test/java/HibernateORMEngineTest.java b/src/test/java/HibernateORMEngineTest.java new file mode 100644 index 00000000..359a2303 --- /dev/null +++ b/src/test/java/HibernateORMEngineTest.java @@ -0,0 +1,28 @@ +package org.lucee.extension.orm.hibernate; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +// extension classes +import org.lucee.extension.orm.hibernate.HibernateORMEngine; + +// Lucee stuffs +import lucee.runtime.Component; +import lucee.runtime.orm.ORMConfiguration; +import lucee.commons.io.res.Resource; +// Testing and mocking +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import java.io.File; +import org.w3c.dom.Element; + +class HibernateORMEngineTest { + + HibernateORMEngine engine = new HibernateORMEngine(); + + @Test + void canInitialize() { + assertEquals(0, engine.getMode()); + } + +} \ No newline at end of file diff --git a/src/test/java/HibernateORMTransactionTest.java b/src/test/java/HibernateORMTransactionTest.java new file mode 100644 index 00000000..686c8c9d --- /dev/null +++ b/src/test/java/HibernateORMTransactionTest.java @@ -0,0 +1,28 @@ +package test.java; + +import org.hibernate.Session; +import org.hibernate.engine.spi.SessionDelegatorBaseImpl; +import org.lucee.extension.orm.hibernate.HibernateORMTransaction; + +// Testing and mocking +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class HibernateORMTransactionTest { + + @Mock + private Session MockSession; + + public HibernateORMTransactionTest() { + MockSession = Mockito.mock(org.hibernate.engine.spi.SessionDelegatorBaseImpl.class); + } + + @Test + public void canInitialize() { + Boolean autoManage = false; + new HibernateORMTransaction(MockSession, autoManage); + } +} \ No newline at end of file diff --git a/src/test/java/event/EventListenerIntegratorTest.java b/src/test/java/event/EventListenerIntegratorTest.java new file mode 100644 index 00000000..67f345c5 --- /dev/null +++ b/src/test/java/event/EventListenerIntegratorTest.java @@ -0,0 +1,19 @@ +import static org.junit.jupiter.api.Assertions.assertEquals; + +// extension classes +import org.lucee.extension.orm.hibernate.event.EventListenerIntegrator; + +// Lucee stuffs +import lucee.runtime.Component; + +// Testing and mocking +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; + +public class EventListenerIntegratorTest { + @Test + public void canInitialize() { + EventListenerIntegrator integrator = new EventListenerIntegrator(); + } +} diff --git a/src/test/java/util/ConfigurationBuilderTest.java b/src/test/java/util/ConfigurationBuilderTest.java new file mode 100644 index 00000000..3431f908 --- /dev/null +++ b/src/test/java/util/ConfigurationBuilderTest.java @@ -0,0 +1,47 @@ +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.IOException; +import java.sql.SQLException; + +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.AvailableSettings; +import org.junit.jupiter.api.Test; +import org.lucee.extension.orm.hibernate.event.EventListenerIntegrator; +import org.lucee.extension.orm.hibernate.jdbc.ConnectionProviderImpl; +import org.lucee.extension.orm.hibernate.util.ConfigurationBuilder; + +import org.mockito.Mock; +import org.mockito.Mockito; + +import lucee.runtime.exp.PageException; +import lucee.runtime.orm.ORMConfiguration; +import lucee.runtime.db.DataSource; + +public class ConfigurationBuilderTest { + @Test + public void canInitialize() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + } + + @Test + public void canBuildConfiguration() throws SQLException, IOException, PageException { + ConfigurationBuilder builder = new ConfigurationBuilder(); + + // @Mock + ORMConfiguration conf = Mockito.mock(ORMConfiguration.class); + Mockito.when(conf.logSQL()).thenReturn(true); + Mockito.when(conf.secondaryCacheEnabled()).thenReturn(true); + + // @Mock + DataSource datasource = Mockito.mock(DataSource.class); + ConnectionProviderImpl connProvider = Mockito.mock(ConnectionProviderImpl.class); + + Configuration config = builder.withEventListener(new EventListenerIntegrator()) + .withConnectionProvider(connProvider).withDatasource(datasource).withDatasourceCreds("foo", "myPass123") + .withORMConfig(conf).withXMLMappings("").build(); + + assertNotNull(config); + assertEquals("false", config.getProperty(AvailableSettings.AUTO_CLOSE_SESSION)); + } +} \ No newline at end of file diff --git a/src/test/java/util/HibernateUtilTest.java b/src/test/java/util/HibernateUtilTest.java new file mode 100644 index 00000000..8fb1b588 --- /dev/null +++ b/src/test/java/util/HibernateUtilTest.java @@ -0,0 +1,33 @@ +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Arrays; + +import org.junit.jupiter.api.Test; + +import org.mockito.Mock; +import org.mockito.Mockito; + +import org.lucee.extension.orm.hibernate.util.HibernateUtil; + +public class HibernateUtilTest { + + @Test + public void canInitialize() { + HibernateUtil util = new HibernateUtil(); + } + + @Test + public void canIdentifyReservedKeywords(){ + HibernateUtil util = new HibernateUtil(); + + assertEquals( true, util.isKeyword( "year" ) ); + assertEquals( true, util.isKeyword( "and" ) ); + assertEquals( true, util.isKeyword( "select" ) ); + assertEquals( false, util.isKeyword( "name" ) ); + assertEquals( false, util.isKeyword( "age" ) ); + assertEquals( false, util.isKeyword( "description" ) ); + } +} \ No newline at end of file diff --git a/test.sh b/test.sh new file mode 100755 index 00000000..09c2e668 --- /dev/null +++ b/test.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +### +# Lucee Extension Test script +# +# To run this script, you must: +# 1. Check out https://github.com/lucee/lucee to the parent directory: ../lucee/ +# 1. Check out https://github.com/lucee/script-runner to the parent directory: ../script-runner/ +### + +# Path to the checked out Lucee source +# Note that the tests run are pulled from this directory, +# so you'll have best luck (up to date tests) if you check out the tag that matches the LUCEE_VERSION variable. +LUCEE_PATH="$PWD/../lucee/" + +# Path to the checked out lucee/script-runner project, +# which is what sets up and runs the CFML-based tests +LUCEE_SCRIPT_RUNNER_PATH="$PWD/../script-runner/" + +# Lucee version to use to run tests on +# The tests themselves, however, will be sourced from `LUCEE_PATH/test`. +# +# Due to LDEV-3616, this must be AT LEAST 6.0.0.316 or the tests will fail with an NPE. +# @see https://luceeserver.atlassian.net/browse/LDEV-3616 +LUCEE_VERSION=6.0.0.316-SNAPSHOT + +# Filter by test label +export testLabels="orm" + +# Filter by test "filter" +# Highly recommend NOT using this, since it's just a filename/path-based filter... +# and you will end up running undesired tests like `imageFormat` simply because of the "orm" in the filename. +export testFilter="" + +# Run our local tests using the `testAdditional` environment variable. +export testAdditional="$PWD/tests" + +# Ensure the current extension is compiled for testing. +if [ ! -f `echo "dist/*.lex"` ]; then + echo "Extension file not found! Cannot run tests." + echo "Please run 'ant dist' to generate the .lex extension file in dist/" + exit 1; +fi + +# Import .env and export to environment +# Useful for testing MSSQL, MYSQL with secret credentials +# @see https://stackoverflow.com/a/30969768 +if [ -f "tests/.env" ]; then + set -o allexport + source tests/.env + set +o allexport +fi + +# Run the tests +ant \ + -buildfile "${LUCEE_SCRIPT_RUNNER_PATH}" \ + -DluceeVersion="$LUCEE_VERSION" \ + -Dwebroot="${LUCEE_PATH}test" \ + -Dexecute="/bootstrap-tests.cfm" \ + -DextensionDir="$PWD/dist" \ + -DtestAdditional="$PWD/tests" \ No newline at end of file diff --git a/tests/autogenmap.cfc b/tests/autogenmap.cfc new file mode 100644 index 00000000..35fd6f92 --- /dev/null +++ b/tests/autogenmap.cfc @@ -0,0 +1,22 @@ +component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { + + public void function testAutoGenMap(){ + + local.uri=createURI("autogenmap/index.cfm"); + local.result=_InternalRequest(uri); + expect( result.status ).toBe( 200 ); + // var res = deserializeJson(result.fileContent); + // if (len(res.errors)){ + // loop array=res.errors, item="local.err"{ + // systemOutput("ERROR: " & err.error, true, true); + // } + // } + } + + private string function createURI(string calledName){ + systemOutput("", true); + systemOutput("-------------- #calledName#----------------", true); + var baseURI = getDirectoryFromPath( contractPath( getCurrentTemplatePath() ) ); + return baseURI&""&calledName; + } +} \ No newline at end of file diff --git a/tests/autogenmap/Application.cfc b/tests/autogenmap/Application.cfc new file mode 100644 index 00000000..d52df072 --- /dev/null +++ b/tests/autogenmap/Application.cfc @@ -0,0 +1,40 @@ +component { + + this.name = "orm-autogenmap"; + this.datasources["h2"] = server.getDatasource("h2", "#getDirectoryFromPath(getCurrentTemplatePath())#/datasource/db" ); + this.datasources["h2_otherDB"] = server.getDatasource("h2", "#getDirectoryFromPath(getCurrentTemplatePath())#/datasource/otherDB" ); + this.ormEnabled = true; + this.ormSettings = { + dbcreate: "dropcreate", + dialect: "h2", + skipCFCWithError : false, + datasource : "h2", + autogenmap : false + }; + + function onApplicationStart() { + } + + public function onRequestStart() { + setting requesttimeout=10; + if ( url.keyExists( "flushcache" ) ){ + componentCacheClear(); + } + } + + function onRequestEnd() { + var javaIoFile=createObject("java","java.io.File"); + loop array = DirectoryList( + path = getDirectoryFromPath( getCurrentTemplatePath() ), + recurse = true, filter="*.db") item="local.path" { + fileDeleteOnExit(javaIoFile,path); + } + } + + private function fileDeleteOnExit(required javaIoFile, required string path) { + var file=javaIoFile.init(arguments.path); + if(!file.isFile())file=javaIoFile.init(expandPath(arguments.path)); + if(file.isFile()) file.deleteOnExit(); + } + +} \ No newline at end of file diff --git a/tests/autogenmap/Auto.cfc b/tests/autogenmap/Auto.cfc new file mode 100644 index 00000000..5f4e14e4 --- /dev/null +++ b/tests/autogenmap/Auto.cfc @@ -0,0 +1,8 @@ +component persistent="true" { + + property name="id" type="string" fieldtype="id" ormtype="string"; + property name="make" type="string"; + property name="model" type="string"; + + this.name = "Auto"; +} \ No newline at end of file diff --git a/tests/autogenmap/Auto.cfc.hbm.xml b/tests/autogenmap/Auto.cfc.hbm.xml new file mode 100644 index 00000000..e0269b95 --- /dev/null +++ b/tests/autogenmap/Auto.cfc.hbm.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tests/autogenmap/Dealership.cfc b/tests/autogenmap/Dealership.cfc new file mode 100644 index 00000000..6dd58e3a --- /dev/null +++ b/tests/autogenmap/Dealership.cfc @@ -0,0 +1,7 @@ +component persistent="true" datasource="h2_otherDB" { + + property name="id" type="string" fieldtype="id" ormtype="string"; + property name="name" type="string"; + + this.name = "Dealership"; +} \ No newline at end of file diff --git a/tests/autogenmap/Dealership.cfc.hbm.xml b/tests/autogenmap/Dealership.cfc.hbm.xml new file mode 100644 index 00000000..477a76f1 --- /dev/null +++ b/tests/autogenmap/Dealership.cfc.hbm.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/autogenmap/index.cfm b/tests/autogenmap/index.cfm new file mode 100644 index 00000000..5603f8d8 --- /dev/null +++ b/tests/autogenmap/index.cfm @@ -0,0 +1,26 @@ + + transaction{ + car = entityNew( "Auto" ); + car.setId( createUUID() ); + car.setMake( "Ford" ); + car.setModel( "F-150" ); + entitySave( car ); + + dealer = entityNew( "Dealership" ); + dealer.setId( createUUID() ); + dealer.setName( "Sedgewick Subaru" ); + entitySave( dealer ); + + ormFlush(); + } + + autoResults = queryExecute( "SELECT * FROM Auto WHERE id=:id", { id : car.getId() }, { datasource: "h2" } ); + if ( !autoResults.recordCount ){ + throw( "auto #car.getId()# not found in datasource table" ); + } + + dealerResults = queryExecute( "SELECT * FROM Dealership WHERE id=:id", { id : dealer.getId() }, { datasource: "h2_otherDB" } ); + if ( !dealerResults.recordCount ){ + throw( "Dealership #dealer.getId()# not found in datasource table" ); + } + \ No newline at end of file diff --git a/tests/datasources.cfc b/tests/datasources.cfc new file mode 100644 index 00000000..09f7c024 --- /dev/null +++ b/tests/datasources.cfc @@ -0,0 +1,22 @@ +component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { + + public void function testDatasources(){ + + local.uri=createURI("datasources/index.cfm"); + local.result=_InternalRequest(uri); + expect( result.status ).toBe( 200 ); + // var res = deserializeJson(result.fileContent); + // if (len(res.errors)){ + // loop array=res.errors, item="local.err"{ + // systemOutput("ERROR: " & err.error, true, true); + // } + // } + } + + private string function createURI(string calledName){ + systemOutput("", true); + systemOutput("-------------- #calledName#----------------", true); + var baseURI = getDirectoryFromPath( contractPath( getCurrentTemplatePath() ) ); + return baseURI&""&calledName; + } +} \ No newline at end of file diff --git a/tests/datasources/Application.cfc b/tests/datasources/Application.cfc new file mode 100644 index 00000000..8d749407 --- /dev/null +++ b/tests/datasources/Application.cfc @@ -0,0 +1,40 @@ +component { + + this.name = "orm-datasources"; + this.datasources["h2"] = server.getDatasource("h2", "#getDirectoryFromPath(getCurrentTemplatePath())#/datasource/db" ); + this.datasources["h2_otherDB"] = server.getDatasource("h2", "#getDirectoryFromPath(getCurrentTemplatePath())#/datasource/otherDB" ); + this.ormEnabled = true; + this.ormSettings = { + dbcreate: "dropcreate", + dialect: "h2", + skipCFCWithError : false, + datasource : "h2", + saveMapping : false + }; + + function onApplicationStart() { + } + + public function onRequestStart() { + setting requesttimeout=10; + if ( url.keyExists( "flushcache" ) ){ + componentCacheClear(); + } + } + + function onRequestEnd() { + var javaIoFile=createObject("java","java.io.File"); + loop array = DirectoryList( + path = getDirectoryFromPath( getCurrentTemplatePath() ), + recurse = true, filter="*.db") item="local.path" { + fileDeleteOnExit(javaIoFile,path); + } + } + + private function fileDeleteOnExit(required javaIoFile, required string path) { + var file=javaIoFile.init(arguments.path); + if(!file.isFile())file=javaIoFile.init(expandPath(arguments.path)); + if(file.isFile()) file.deleteOnExit(); + } + +} \ No newline at end of file diff --git a/tests/datasources/Auto.cfc b/tests/datasources/Auto.cfc new file mode 100644 index 00000000..5f4e14e4 --- /dev/null +++ b/tests/datasources/Auto.cfc @@ -0,0 +1,8 @@ +component persistent="true" { + + property name="id" type="string" fieldtype="id" ormtype="string"; + property name="make" type="string"; + property name="model" type="string"; + + this.name = "Auto"; +} \ No newline at end of file diff --git a/tests/datasources/Auto.cfc.hbm.xml b/tests/datasources/Auto.cfc.hbm.xml new file mode 100644 index 00000000..8c260280 --- /dev/null +++ b/tests/datasources/Auto.cfc.hbm.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + diff --git a/tests/datasources/Dealership.cfc b/tests/datasources/Dealership.cfc new file mode 100644 index 00000000..6dd58e3a --- /dev/null +++ b/tests/datasources/Dealership.cfc @@ -0,0 +1,7 @@ +component persistent="true" datasource="h2_otherDB" { + + property name="id" type="string" fieldtype="id" ormtype="string"; + property name="name" type="string"; + + this.name = "Dealership"; +} \ No newline at end of file diff --git a/tests/datasources/Dealership.cfc.hbm.xml b/tests/datasources/Dealership.cfc.hbm.xml new file mode 100644 index 00000000..e407d331 --- /dev/null +++ b/tests/datasources/Dealership.cfc.hbm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/tests/datasources/index.cfm b/tests/datasources/index.cfm new file mode 100644 index 00000000..5603f8d8 --- /dev/null +++ b/tests/datasources/index.cfm @@ -0,0 +1,26 @@ + + transaction{ + car = entityNew( "Auto" ); + car.setId( createUUID() ); + car.setMake( "Ford" ); + car.setModel( "F-150" ); + entitySave( car ); + + dealer = entityNew( "Dealership" ); + dealer.setId( createUUID() ); + dealer.setName( "Sedgewick Subaru" ); + entitySave( dealer ); + + ormFlush(); + } + + autoResults = queryExecute( "SELECT * FROM Auto WHERE id=:id", { id : car.getId() }, { datasource: "h2" } ); + if ( !autoResults.recordCount ){ + throw( "auto #car.getId()# not found in datasource table" ); + } + + dealerResults = queryExecute( "SELECT * FROM Dealership WHERE id=:id", { id : dealer.getId() }, { datasource: "h2_otherDB" } ); + if ( !dealerResults.recordCount ){ + throw( "Dealership #dealer.getId()# not found in datasource table" ); + } + \ No newline at end of file diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml new file mode 100644 index 00000000..1d212e3d --- /dev/null +++ b/tests/docker-compose.yml @@ -0,0 +1,46 @@ + +version: "3.9" +services: + + mysql: + platform: linux/x86_64 # Needed for Mac's on the M1 chip + image: mysql:5 + environment: + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD} + ports: + - "${MYSQL_PORT}:3306" + + postgres: + image: postgres:11.3 + environment: + POSTGRES_USER: ${POSTGRES_USERNAME} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: ${POSTGRES_DATABASE} + ports: + - "${POSTGRES_PORT}:5432" + + mssql: + image: mcr.microsoft.com/mssql/server:2017-latest + environment: + MSSQL_SA_PASSWORD: ${MSSQL_PASSWORD} + ACCEPT_EULA: "Y" + MSSQL_PID: "Developer" + volumes: + # Mounted entrypoint for initdb scripts + - ./docker/mssql:/docker-entrypoint-initdb.d + ports: + - "${MSSQL_PORT}:1433" + entrypoint: /docker-entrypoint-initdb.d/entrypoint.sh /opt/mssql/bin/sqlservr + + # TODO: Re-enable when MongoDB testing is fixed in Lucee 6 + # mongo: + # image: mongo + # environment: + # MONGO_INITDB_ROOT_USERNAME: ${MONGODB_USERNAME} + # MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_PASSWORD} + # MONGO_INITDB_DATABASE: ${MONGODB_DB} + # volumes: + # - ./docker/mongo:/docker-entrypoint-initdb.d + # ports: + # - "${MONGODB_PORT}:27017" \ No newline at end of file diff --git a/tests/docker/mssql/create.sql b/tests/docker/mssql/create.sql new file mode 100644 index 00000000..1193cadb --- /dev/null +++ b/tests/docker/mssql/create.sql @@ -0,0 +1,4 @@ +CREATE DATABASE hibernateDB; +GO +USE hibernateDB; +GO \ No newline at end of file diff --git a/tests/docker/mssql/entrypoint.sh b/tests/docker/mssql/entrypoint.sh new file mode 100755 index 00000000..4aee548f --- /dev/null +++ b/tests/docker/mssql/entrypoint.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +if [ "$1" = '/opt/mssql/bin/sqlservr' ]; then + # If this is the container's first run, initialize the application database + if [ ! -f /tmp/app-initialized ]; then + # Initialize the application database asynchronously in a background process. This allows a) the SQL Server process to be the main process in the container, which allows graceful shutdown and other goodies, and b) us to only start the SQL Server process once, as opposed to starting, stopping, then starting it again. + function initialize_app_database() { + # Wait a bit for SQL Server to start. SQL Server's process doesn't provide a clever way to check if it's up or not, and it needs to be up before we can import the application database + sleep 10s + + #run the setup script to create the DB and the schema in the DB + /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P hib3rnate_DB -d master -i /docker-entrypoint-initdb.d/create.sql + + # Note that the container has been initialized so future starts won't wipe changes to the data + touch /tmp/app-initialized + } + initialize_app_database & + fi +fi + +exec "$@" \ No newline at end of file diff --git a/tests/ehcache.cfc b/tests/ehcache.cfc new file mode 100644 index 00000000..dc42f70e --- /dev/null +++ b/tests/ehcache.cfc @@ -0,0 +1,22 @@ +component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { + + public void function testEHCache(){ + + local.uri=createURI("ehcache/index.cfm"); + local.result=_InternalRequest(uri); + expect( result.status ).toBe( 200 ); + // var res = deserializeJson(result.fileContent); + // if (len(res.errors)){ + // loop array=res.errors, item="local.err"{ + // systemOutput("ERROR: " & err.error, true, true); + // } + // } + } + + private string function createURI(string calledName){ + systemOutput("", true); + systemOutput("-------------- #calledName#----------------", true); + var baseURI = getDirectoryFromPath( contractPath( getCurrentTemplatePath() ) ); + return baseURI&""&calledName; + } +} \ No newline at end of file diff --git a/tests/ehcache/Application.cfc b/tests/ehcache/Application.cfc new file mode 100644 index 00000000..f56081fd --- /dev/null +++ b/tests/ehcache/Application.cfc @@ -0,0 +1,43 @@ +component { + + this.name = "orm-ehcache"; + this.datasources["h2"] = server.getDatasource("h2", "#getDirectoryFromPath(getCurrentTemplatePath())#/datasource/db" ); + this.ormEnabled = true; + this.ormSettings = { + dbcreate: "dropcreate", + dialect: "h2", + skipCFCWithError : false, + datasource : "h2", + + // ehcache setup + secondarycacheenabled : true, + cacheprovider : "ehcache", + cacheconfig : "ehcache.xml" + }; + + function onApplicationStart() { + } + + public function onRequestStart() { + setting requesttimeout=10; + if ( url.keyExists( "flushcache" ) ){ + componentCacheClear(); + } + } + + function onRequestEnd() { + var javaIoFile=createObject("java","java.io.File"); + loop array = DirectoryList( + path = getDirectoryFromPath( getCurrentTemplatePath() ), + recurse = true, filter="*.db") item="local.path" { + fileDeleteOnExit(javaIoFile,path); + } + } + + private function fileDeleteOnExit(required javaIoFile, required string path) { + var file=javaIoFile.init(arguments.path); + if(!file.isFile())file=javaIoFile.init(expandPath(arguments.path)); + if(file.isFile()) file.deleteOnExit(); + } + +} \ No newline at end of file diff --git a/tests/ehcache/Auto.cfc b/tests/ehcache/Auto.cfc new file mode 100644 index 00000000..b2fc47a8 --- /dev/null +++ b/tests/ehcache/Auto.cfc @@ -0,0 +1,8 @@ +component persistent="true" cachename="Autos" cacheuse="read-only" { + + property name="id" type="string" fieldtype="id" ormtype="string"; + property name="make" type="string"; + property name="model" type="string"; + + this.name = "Auto"; +} \ No newline at end of file diff --git a/tests/ehcache/ehcache.xml b/tests/ehcache/ehcache.xml new file mode 100644 index 00000000..08e8e0fd --- /dev/null +++ b/tests/ehcache/ehcache.xml @@ -0,0 +1,19 @@ + + + + + + + + + \ No newline at end of file diff --git a/tests/ehcache/index.cfm b/tests/ehcache/index.cfm new file mode 100644 index 00000000..4e012bb4 --- /dev/null +++ b/tests/ehcache/index.cfm @@ -0,0 +1,24 @@ + + /** + * TODO: Verify that the hibernate config is loaded and in effect. + */ + transaction{ + car = entityNew( "Auto" ); + car.setId( createUUID() ); + car.setMake( "Ford" ); + entitySave( car ); + ormFlush(); + } + + // Delete the item from the DB + queryExecute( "DELETE FROM Auto WHERE id=:id", { id : car.getId() }, { datasource : "h2" } ); + + // don't let Hibernate load from the first-level cache( the session ) + ormClearSession(); + + // test that it loads from the cache. + otherCar = entityLoad( "Auto", car.getId() ); + if ( isNull( otherCar ) ){ + throw( "Car #car.getId()# not found in 2nd-level cache!" ); + } + \ No newline at end of file diff --git a/tests/events.cfc b/tests/events.cfc index 39b17fbf..ffa56551 100644 --- a/tests/events.cfc +++ b/tests/events.cfc @@ -26,18 +26,14 @@ component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { local.result=_InternalRequest(uri); expect( result.status ).toBe( 200 ); local.res = deserializeJson(result.fileContent); - // systemOutput( res.events, true ); if (len(res.errors)){ loop array=res.errors, item="local.err"{ systemOutput("ERROR: " & err.error, true, true); } } + local.expectedEvents = [ "onFlush", "preLoad", "postLoad", "preLoad", "postLoad", "onDelete", "onFlush", "preInsert", "postInsert", "preUpdate", "postUpdate", "preDelete", "postDelete", "onClear" ]; + expect( res.events ).toBe( expectedEvents ); expect( res.errors.len() ).toBe( 0, "errors" ); - expect( res.events.len() ).toBe( 20, "events" ); // TBC - // expect( trim( result.fileContent ) ).toBe( arrExpectedEvents ); // TODO this should be an array of event names - /* - i.e. arrExpectedEvents to be something like this - ["preInsert","preInsert","postInsert","postInsert","preInsert","preInsert","preLoad","preLoad","postLoad","postLoad","postInsert","postInsert","postUpdate","postUpdate","preDelete","preDelete","postDelete","postDelete"] */ } public void function testEvents_createNew (){ @@ -52,10 +48,9 @@ component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { systemOutput("ERROR: " & err.error, true, true); } } - local.expectedEvents = [ "preInsert", "postInsert", "onFlush", "onClear" ]; // TBC + local.expectedEvents = [ "onFlush", "preInsert", "postInsert", "onClear" ]; expect( res.events ).toBe( expectedEvents ); expect( res.errors.len() ).toBe( 0, "errors" ); - expect( res.events.len() ).toBe( 4, "events" ); } public void function testEvents_load (){ @@ -70,10 +65,9 @@ component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { systemOutput("ERROR: " & err.error, true, true); } } - local.expectedEvents = [ "preLoad", "postLoad", "onFlush", "onClear" ]; // TBC + local.expectedEvents = [ "onFlush", "preInsert", "postInsert", "onClear", "preLoad", "postLoad" ]; expect( res.events ).toBe( expectedEvents ); expect( res.errors.len() ).toBe( 0, "errors" ); - expect( res.events.len() ).toBe( 4, "events" ); } private string function createURI(string calledName){ diff --git a/tests/events/Application.cfc b/tests/events/Application.cfc index c5614b76..a8b7a1bc 100644 --- a/tests/events/Application.cfc +++ b/tests/events/Application.cfc @@ -11,7 +11,8 @@ component { autoManageSession: false, flushAtRequestEnd: false, useDBForMapping: false, - dialect: "h2" + dialect: "h2", + skipCFCWithError : false }; function onApplicationStart() { diff --git a/tests/events/Code.cfc b/tests/events/Code.cfc index e8adb306..ff3efcdb 100644 --- a/tests/events/Code.cfc +++ b/tests/events/Code.cfc @@ -1,4 +1,4 @@ -component persistent="true" extends="eventHandler" { +component persistent="true" { property name="ID" type="numeric" fieldtype="id" ormtype="long";// generator="identity"; property name="code" type="string"; diff --git a/tests/events/eventHandler.cfc b/tests/events/eventHandler.cfc index 527a0265..417c0f63 100644 --- a/tests/events/eventHandler.cfc +++ b/tests/events/eventHandler.cfc @@ -5,17 +5,9 @@ component hint="logs out any orm events" { return this; } - // Currently not implemented - function preFlush( entity ){ // entities - eventLog( arguments ); - } function onFlush( entity ) { eventLog( arguments ); } - // Currently not implemented - function postFlush( entity ){ // entities - eventLog( arguments ); - } function postNew( any entity, any entityName ){ eventLog( arguments ); @@ -76,20 +68,6 @@ component hint="logs out any orm events" { systemOutput( "------- #eventName# #listLast(s.template,"/\")#: #s.lineNumber#", true ); systemOutput( "arguments: " & structKeyList(args), true); - if ( !isNull(args.2 ) ){ // only postNew, preUpdate should have two args - if ( isSimpleValue( args.2 ) ){ - systemOutput("simple arguments.2: " & args.2, true); - } else if ( isStruct( args.2) ) { - systemOutput("struct arguments.2: " & args.2.toJson(), true); - } else { - try { - systemOutput("arguments.2: " & args.2.toJson(), true); - } catch (e) { - systemOutput("arguments.2: " & e.message, true); - } - } - } - //if ( ! structKeyExists( application, "ormEventLog" ) ) // application.ormEventLog = []; application.ormEventLog.append( { @@ -99,8 +77,9 @@ component hint="logs out any orm events" { } ); try { + // Certain events like onFlush, onClear, onAutoFlush will not have an associated entity. if ( isNull(arguments.args.entity ) ) { - throw ("entity was null"); + return; } if (isObject( args.entity ) ){ diff --git a/tests/events/load.cfm b/tests/events/load.cfm index e865b1eb..8107049c 100644 --- a/tests/events/load.cfm +++ b/tests/events/load.cfm @@ -1,10 +1,15 @@ code = entityNew( 'Code' ); - arr = entityLoad("Code"); + code.setId( 100 ); + code.setCode( 'a' ); + // should trigger preInsert, postInsert, and onFlush + entitySave( code ); ormFlush(); - // trigger onClear + ormClearSession(); + arr = entityLoad( "Code", 100 ); + result = { events: [], errors: [] diff --git a/tests/ormconfig.cfc b/tests/ormconfig.cfc new file mode 100644 index 00000000..ce2266d8 --- /dev/null +++ b/tests/ormconfig.cfc @@ -0,0 +1,22 @@ +component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { + + public void function testORMConfig(){ + + local.uri=createURI("ormconfig/index.cfm"); + local.result=_InternalRequest(uri); + expect( result.status ).toBe( 200 ); + // var res = deserializeJson(result.fileContent); + // if (len(res.errors)){ + // loop array=res.errors, item="local.err"{ + // systemOutput("ERROR: " & err.error, true, true); + // } + // } + } + + private string function createURI(string calledName){ + systemOutput("", true); + systemOutput("-------------- #calledName#----------------", true); + var baseURI = getDirectoryFromPath( contractPath( getCurrentTemplatePath() ) ); + return baseURI&""&calledName; + } +} \ No newline at end of file diff --git a/tests/ormconfig/Application.cfc b/tests/ormconfig/Application.cfc new file mode 100644 index 00000000..b0c32247 --- /dev/null +++ b/tests/ormconfig/Application.cfc @@ -0,0 +1,39 @@ +component { + + this.name = "orm-ormconfig"; + this.datasources["h2"] = server.getDatasource("h2", "#getDirectoryFromPath(getCurrentTemplatePath())#/datasource/db" ); + this.ormEnabled = true; + this.ormSettings = { + dbcreate: "dropcreate", + dialect: "h2", + skipCFCWithError : false, + datasource : "h2", + ormConfig : "hibernate.cfg.xml" + }; + + function onApplicationStart() { + } + + public function onRequestStart() { + setting requesttimeout=10; + if ( url.keyExists( "flushcache" ) ){ + componentCacheClear(); + } + } + + function onRequestEnd() { + var javaIoFile=createObject("java","java.io.File"); + loop array = DirectoryList( + path = getDirectoryFromPath( getCurrentTemplatePath() ), + recurse = true, filter="*.db") item="local.path" { + fileDeleteOnExit(javaIoFile,path); + } + } + + private function fileDeleteOnExit(required javaIoFile, required string path) { + var file=javaIoFile.init(arguments.path); + if(!file.isFile())file=javaIoFile.init(expandPath(arguments.path)); + if(file.isFile()) file.deleteOnExit(); + } + +} \ No newline at end of file diff --git a/tests/ormconfig/Auto.cfc b/tests/ormconfig/Auto.cfc new file mode 100644 index 00000000..5f4e14e4 --- /dev/null +++ b/tests/ormconfig/Auto.cfc @@ -0,0 +1,8 @@ +component persistent="true" { + + property name="id" type="string" fieldtype="id" ormtype="string"; + property name="make" type="string"; + property name="model" type="string"; + + this.name = "Auto"; +} \ No newline at end of file diff --git a/tests/ormconfig/hibernate.cfg.xml b/tests/ormconfig/hibernate.cfg.xml new file mode 100644 index 00000000..27e853db --- /dev/null +++ b/tests/ormconfig/hibernate.cfg.xml @@ -0,0 +1,13 @@ + + + + + + + true + true + + + \ No newline at end of file diff --git a/tests/ormconfig/index.cfm b/tests/ormconfig/index.cfm new file mode 100644 index 00000000..4e618c66 --- /dev/null +++ b/tests/ormconfig/index.cfm @@ -0,0 +1,12 @@ + + /** + * TODO: Verify that the hibernate config is loaded and in effect. + */ + transaction{ + car = entityNew( "Auto" ); + car.setId( createUUID() ); + car.setMake( "Ford" ); + entitySave( car ); + ormFlush(); + } + \ No newline at end of file diff --git a/tests/savepoints.cfc b/tests/savepoints.cfc new file mode 100644 index 00000000..06e001ae --- /dev/null +++ b/tests/savepoints.cfc @@ -0,0 +1,19 @@ +component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { + + function run( testResults, testBox ) { + describe("ORM Savepoint Support", function() { + it( title="can use transaction savepoint", skip="true" body=function( currentSpec ) { + local.uri=createURI("savepoints/index.cfm"); + local.result=_InternalRequest(uri); + expect( result.status ).toBe( 200 ); + }); + }); + } + + private string function createURI(string calledName){ + systemOutput("", true); + systemOutput("-------------- #calledName#----------------", true); + var baseURI = getDirectoryFromPath( contractPath( getCurrentTemplatePath() ) ); + return baseURI&""&calledName; + } +} \ No newline at end of file diff --git a/tests/savepoints/Application.cfc b/tests/savepoints/Application.cfc new file mode 100644 index 00000000..c8b04ac6 --- /dev/null +++ b/tests/savepoints/Application.cfc @@ -0,0 +1,37 @@ +component { + + this.name = "orm-dialects"; + this.datasources["h2"] = server.getDatasource("h2", "#getDirectoryFromPath(getCurrentTemplatePath())#/datasource/db" ); + this.ormEnabled = true; + this.ormSettings = { + dbcreate: "dropcreate", + skipCFCWithError : false, + datasource : "h2", + }; + + function onApplicationStart() { + } + + public function onRequestStart() { + setting requesttimeout=10; + if ( url.keyExists( "flushcache" ) ){ + componentCacheClear(); + } + } + + function onRequestEnd() { + var javaIoFile=createObject("java","java.io.File"); + loop array = DirectoryList( + path = getDirectoryFromPath( getCurrentTemplatePath() ), + recurse = true, filter="*.db") item="local.path" { + fileDeleteOnExit(javaIoFile,path); + } + } + + private function fileDeleteOnExit(required javaIoFile, required string path) { + var file=javaIoFile.init(arguments.path); + if(!file.isFile())file=javaIoFile.init(expandPath(arguments.path)); + if(file.isFile()) file.deleteOnExit(); + } + +} \ No newline at end of file diff --git a/tests/savepoints/Auto.cfc b/tests/savepoints/Auto.cfc new file mode 100644 index 00000000..5f4e14e4 --- /dev/null +++ b/tests/savepoints/Auto.cfc @@ -0,0 +1,8 @@ +component persistent="true" { + + property name="id" type="string" fieldtype="id" ormtype="string"; + property name="make" type="string"; + property name="model" type="string"; + + this.name = "Auto"; +} \ No newline at end of file diff --git a/tests/savepoints/index.cfm b/tests/savepoints/index.cfm new file mode 100644 index 00000000..3646523c --- /dev/null +++ b/tests/savepoints/index.cfm @@ -0,0 +1,13 @@ + + ormReload(); + transaction{ + myEntity = entityNew( "Auto", { + "make" : "Hyundai", + "model" : "Accent", + "id" : createUUID() + } ); + + entitySave( myEntity ); + transactionSetSavepoint(); // throws "This feature not supported". + } + \ No newline at end of file diff --git a/tests/tickets/LDEV3907.cfc b/tests/tickets/LDEV3907.cfc new file mode 100644 index 00000000..9e5bab65 --- /dev/null +++ b/tests/tickets/LDEV3907.cfc @@ -0,0 +1,30 @@ +component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { + function beforeAll(){ + variables.uri = createURI("LDEV3907"); + } + + function run( testResults, testBox ) { + describe("Testcase for LDEV-3907", function() { + it( title="Setting the default value in the primary key in ORM entity", body=function( currentSpec ) { + try { + local.result = _InternalRequest( + template : "#uri#\LDEV3907.cfm" + ).filecontent; + } + catch(any e) { + result = e.message; + } + expect(trim(result)).toBe("LDEV3907"); + } skip="#notHasMssql()#"); + }); + } + + private function notHasMssql() { + return structCount(server.getDatasource("mssql")) == 0; + } + + private string function createURI(string calledName) { + var baseURI = "/testAdditional/#listLast(getDirectoryFromPath(getCurrenttemplatepath()),"\/")#/"; + return baseURI&""&calledName; + } +} \ No newline at end of file diff --git a/tests/tickets/LDEV3907/Application.cfc b/tests/tickets/LDEV3907/Application.cfc new file mode 100644 index 00000000..97820149 --- /dev/null +++ b/tests/tickets/LDEV3907/Application.cfc @@ -0,0 +1,11 @@ +component { + this.name = "LDEV-3907"; + this.ormenabled = true; + this.ormsettings = { + dbcreate="dropCreate" + ,dialect="MicrosoftSQLServer" + } + mssql = getDatasource(); + this.datasources["LDEV_3907"] = server.getDatasource("mssql"); + this.datasource = "LDEV_3907"; +} \ No newline at end of file diff --git a/tests/tickets/LDEV3907/Brand.cfc b/tests/tickets/LDEV3907/Brand.cfc new file mode 100644 index 00000000..9db1aef8 --- /dev/null +++ b/tests/tickets/LDEV3907/Brand.cfc @@ -0,0 +1,7 @@ +component displayname="brand" entityname="brand" table="brand" persistent=true output=false accessors=true { + // Persistent Properties + property name="brandID" ormtype="string" length="32" fieldtype="id" generator="uuid" unsavedvalue="" default="1"; + property name="activeFlag" ormtype="boolean"; + property name="urlTitle" ormtype="string"; + property name="brandName" ormtype="string"; +} \ No newline at end of file diff --git a/tests/tickets/LDEV3907/LDEV3907.cfm b/tests/tickets/LDEV3907/LDEV3907.cfm new file mode 100644 index 00000000..044c66bc --- /dev/null +++ b/tests/tickets/LDEV3907/LDEV3907.cfm @@ -0,0 +1,6 @@ + + + + + +#brand.getBrandName()# \ No newline at end of file diff --git a/tests/tickets/LDEV4150.cfc b/tests/tickets/LDEV4150.cfc new file mode 100644 index 00000000..d0bd0309 --- /dev/null +++ b/tests/tickets/LDEV4150.cfc @@ -0,0 +1,35 @@ +component extends="org.lucee.cfml.test.LuceeTestCase" labels="orm" { + + function beforeAll() { + variables.uri = createURI("LDEV4150"); + } + + function afterAll() { + if (!notHasMssql()) { + queryExecute( sql="DROP TABLE IF EXISTS test4150", options: { + datasource: server.getDatasource("mssql") + }); + } + } + + function run( testResults, testBox ) { + describe("Testcase for LDEV-4150", function() { + it( title="checking length property value to sqltype=varchar on ORM Entity", skip="#notHasMssql()#", body=function( currentSpec ) { + local.result = _InternalRequest( + template : "#uri#\LDEV4150.cfm" + ).filecontent; + expect(trim(result)).tobe("Success"); + }); + }); + } + + private function notHasMssql() { + return structCount(server.getDatasource("mssql")) == 0; + } + + private string function createURI(string calledName) { + var baseURI = "/testAdditional/#listLast(getDirectoryFromPath(getCurrenttemplatepath()),"\/")#/"; + return baseURI&""&calledName; + } + +} \ No newline at end of file diff --git a/tests/tickets/LDEV4150/Application.cfc b/tests/tickets/LDEV4150/Application.cfc new file mode 100644 index 00000000..066c7fe3 --- /dev/null +++ b/tests/tickets/LDEV4150/Application.cfc @@ -0,0 +1,9 @@ +component { + this.name = "LDEV4150" + this.ORMenabled = true; + this.datasource = server.getDatasource("mssql"); + this.ormSettings = { + dbcreate = "dropcreate", + dialect = "MicrosoftSQLServer" + }; +} \ No newline at end of file diff --git a/tests/tickets/LDEV4150/LDEV4150.cfm b/tests/tickets/LDEV4150/LDEV4150.cfm new file mode 100644 index 00000000..94f894c8 --- /dev/null +++ b/tests/tickets/LDEV4150/LDEV4150.cfm @@ -0,0 +1,15 @@ + + try { + test = entityNew( "test4150" ); + test.setName( "Steve" ); + test.setAddress( "116 Sunny Ave" ); + test.setId( createUUID() ); + entitySave( test ); + ormFlush(); + + writeOutput( "success" ); + } + catch(any e) { + writeoutput(e.message); + } + \ No newline at end of file diff --git a/tests/tickets/LDEV4150/test4150.cfc b/tests/tickets/LDEV4150/test4150.cfc new file mode 100644 index 00000000..f785f310 --- /dev/null +++ b/tests/tickets/LDEV4150/test4150.cfc @@ -0,0 +1,10 @@ + +component accessors="true" persistent="true" { + property name="id" type="string"; + property name="name" type="string" sqltype="varchar" length="100"; + property name="address" type="string" sqltype="nvarchar" length="150"; + + public component function init() { + return this; + } +} \ No newline at end of file