openjpa-2.2.2.orig/0000755000000000000000000000000012133330376010777 5ustar openjpa-2.2.2.orig/patchoj.py0000755000000000000000000001432112133327322013002 0ustar #!/usr/bin/python """ Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ from optparse import OptionParser from zipfile import ZipFile from subprocess import Popen,PIPE from glob import glob import os,re def main() : usage= "usage: %prog [optons]" description = "Generate a jar file which contains the OpenJPA class files which have been changed. The output from svn info and svn diff may also be included. A typical \ use is to run from the same directory as the parent pom. This will automatically include all changed files with a .java extension." version = "$prog 0.5" parser = OptionParser(usage=usage, version=version, description = description) parser.add_option("-f", "--files", dest="files", help="list of filenames to include") parser.add_option("-p", "--patchfile", dest="patchfile", help="patch file name", default="patch.jar") parser.add_option("-i", "--noinfo", action="store_false", dest="includeInfo", help="exclude output from svn info", default=True) parser.add_option("-d", "--nodiff", action="store_false", dest="includeDiff", help="exclude output from svn diff",default=True) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="print debug information",default=False) # parser.add_option("-p", "--pattern", dest="pattern", help="regex of filenames to match") global options (options,args) = parser.parse_args() genZip(options) def genZip(options): """ generate the zip file """ if options.files == None: files = getAllFiles() else : files = getFilesFromList(options.files) zip = ZipFile(options.patchfile, 'w') if options.includeInfo: writeInfo(zip, files) if options.includeDiff: writeDiff(zip, files) writeClasses(zip, files) zip.close() print 'Wrote patch to %s. ' % (options.patchfile) if options.verbose: print 'Files in patch: %s' % ("\n".join(files)) def getAllFiles(): """ get the list of all modified files. Only Added or Modified .java, .properties files will be considered """ if options.verbose: print ' > getAllFiles' files = [] commandOutput = Popen(['svn', 'stat'], stdout=PIPE).communicate()[0].splitlines() prog = re.compile('([A|M] *)(.*\.java)') for candidate in commandOutput: match = prog.match(candidate) if match : files.append(match.group(2)) prog = re.compile('([A|M] *)(.*\.properties)') for candidate in commandOutput: match = prog.match(candidate) if match : files.append(match.group(2)) if options.verbose: print 'Found modified files : ' + str(files) print ' < getAllFiles' return files def getFilesFromList(files) : """ get a list of modified files from a comma separated list usually from the command line """ if options.verbose : print ' > getFilesFromList' print ' returning ' + str(files.split(',')) print ' < getFilesFromList' return files.split(',') def writeInfo(zip, files=None): """ write the output of svn info to a temp file and store in a zip """ if options.verbose : print ' > writeInfo' patchFile = open('info.txt', 'w') args = ['svn', 'info'] if files: args.extend(files) Popen(args=args, stdout=patchFile).communicate()[0] zip.write(patchFile.name) patchFile.close() os.remove(patchFile.name) if options.verbose: print ' < writeInfo' def writeDiff(zip, files=None): """ Write the output of svn diff to a temp file and store in a zip """ if options.verbose: print ' > writeDiff' patchFile = open('patch.txt', 'w') args = ['svn', 'diff'] if files: args.extend(files) Popen(args=args, stdout=patchFile).communicate()[0] zip.write(patchFile.name) patchFile.close() os.remove(patchFile.name) if options.verbose: print ' < writeDiff' def javaToClass(file) : """ simple helper function, converts a string from svn stat (or command line) to its corresponding .class file """ rval = file.replace('src','target').replace('main','classes').replace('test','test-classes').replace('.java', '.class').replace('java','').replace('\\\\','\\') return rval; def javaToInnerClass(file): """ helper function, converts .java file to a glob pattern that matches inner classes """ return javaToClass(file).replace('.class', '$*.class') def writeClasses(zip, files=None): """ Write class files to a zip """ prog = re.compile('(.*classes.)(.*)') propertiesProg = re.compile('(.*resources.)(.*)') for file in files : if str(file).endswith('.java'): for globMatch in glob(javaToClass(file)) : if(prog.match(globMatch)): target = prog.match(globMatch).group(2) zip.write(os.path.realpath(globMatch), target) # match again on inner classes, not sure if glob supports optional matches. for globMatch in glob(javaToInnerClass(file)) : if(prog.match(globMatch)): target = prog.match(globMatch).group(2) zip.write(os.path.realpath(globMatch), target) elif str(file).endswith('.properties'): for globMatch in glob(file) : if(propertiesProg.match(globMatch)): target = propertiesProg.match(globMatch).group(2) zip.write(os.path.realpath(globMatch), target) if __name__ == "__main__": main() openjpa-2.2.2.orig/pom.xml0000644000000000000000000015103212133327322012313 0ustar 4.0.0 org.apache apache 7 org.apache.openjpa openjpa-parent pom OpenJPA Parent POM Apache OpenJPA implementation of JSR-317 JPA 2.0 2.2.2 ${project.version} DefaultLevel=INFO UTF-8 ${project.basedir}/../openjpa-project/checkstyle.xml scp://people.apache.org/home/${site.deploy.user.name}/public_html/openjpa/${project.version}/staging-site 512m 1024m -Xmx${test.jvm.maxheapsize} -XX:MaxPermSize=${test.jvm.maxpermsize} -XX:+HeapDumpOnOutOfMemoryError ${test.jvm.arguments} false 10 5 2 10000 MaxActive=${dbcp.maxActive},MaxIdle=${dbcp.maxIdle},MinIdle=${dbcp.minIdle},MaxWait=${dbcp.maxWait} 10 5 ignore none false 10.8.2.2 1.8.0.10 5.1.12 8.4-701.jdbc3 1.6.1 1.6 1.6 1.6 1.6 Apache Software License 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo Apache Software Foundation http://www.apache.org http://openjpa.apache.org jira http://issues.apache.org/jira/browse/OPENJPA Hudson https://hudson.apache.org/hudson/job/OpenJPA-trunk-deploy/ 2006 OpenJPA Developer List dev-subscribe@openjpa.apache.org dev-unsubscribe@openjpa.apache.org dev@openjpa.apache.org http://mail-archives.apache.org/mod_mbox/openjpa-dev/ OpenJPA Users List users-subscribe@openjpa.apache.org users-unsubscribe@openjpa.apache.org users@openjpa.apache.org http://mail-archives.apache.org/mod_mbox/openjpa-users/ OpenJPA Commits List commits-subscribe@openjpa.apache.org commits-unsubscribe@openjpa.apache.org commits@openjpa.apache.org http://mail-archives.apache.org/mod_mbox/openjpa-commits/ people.apache.org ${site.deploy.url} scm:svn:http://svn.apache.org/repos/asf/openjpa/tags/2.2.2 scm:svn:https://svn.apache.org/repos/asf/openjpa/tags/2.2.2 http://svn.apache.org/repos/asf/openjpa/tags/2.2.2 openjpa-lib openjpa-kernel openjpa-jdbc openjpa-persistence openjpa-persistence-jdbc openjpa-persistence-locking openjpa-xmlstore openjpa-slice openjpa-jest openjpa openjpa-project openjpa-examples openjpa-integration openjpa-all openjpa-tools apache-release performRelease verify true org.apache.rat apache-rat-plugin verify check false 0 **/javax.persistence.spi.PersistenceProvider **/javax.annotation.processing.Processor **/*.rsrc **/org.apache.openjpa.revision.properties scripts/*.list scripts/*.options scripts/*.dict **/.*/** **/target/**/* **/dependency-reduced-pom.xml **/*.log **/maven-eclipse.xml **/rat.txt release.properties DEPENDENCIES **/internal-repository/** sign-release sign-release org.apache.maven.plugins maven-gpg-plugin ydoc-profile -generic -umlautogen -tag param -tag return -tag see -ytag y.uml -license ${ydoc.license} -filter ydoc.filters.ExcludeFilter -filterpath ${ydoc.home}/lib/ydoc.jar -doclet ydoc.doclets.YStandard -docletpath ${ydoc.home}/lib/ydoc.jar${path.separator}${ydoc.home}/lib/class2svg.jar${path.separator}${ydoc.home}/resources ${ydoc.params} javadoc-profile org.apache.maven.plugins maven-javadoc-plugin builddocs true debug false -Xmx${test.jvm.maxheapsize} -XX:MaxPermSize=${test.jvm.maxpermsize} -agentlib:jdwp=transport=dt_socket,server=y,address=8000 enable-security false -Dtest.basedir=${basedir}/.. ${basedir}/../openjpa-persistence-jdbc/src/test/resources/j2.security.test.policy -Djava.security.manager -Djava.security.policy=${policy.file} ${test.env} ${test.jvm.arguments} test-dynamic-enhancer false -Dtest.basedir=${basedir}/.. ${basedir}/../openjpa-persistence-jdbc/src/test/resources/j2.security.test.policy -Djava.security.manager -Djava.security.policy=${policy.file} ${test.env} ${test.jvm.arguments} org.apache.maven.plugins maven-surefire-plugin ${surefire.jvm.args} test-derby true test-derby org.apache.derby derby ${derby.version} test org.apache.derby.jdbc.EmbeddedDriver jdbc:derby:target/database/openjpa-derby-database;create=true ShutdownOnClose=false derby test-derbymem test-derbymem org.apache.derby derby ${derby.version} test org.apache.derby.jdbc.EmbeddedDriver jdbc:derby:memory:openjpa-derby-inmem-database;create=true ShutdownOnClose=false test-derbynet test-derbynet org.apache.derby derbyclient ${derby.version} test jdbc:derby://localhost:1527/openjpa20;create=true;traceDirectory=target;traceFile=derby.log org.apache.derby.jdbc.ClientDriver uid pwd ${openjpa.derbynet.driver} ${openjpa.derbynet.url} ${openjpa.derbynet.username} ${openjpa.derbynet.password} commons-pool commons-pool 1.5.4 commons-logging commons-logging 1.0.4 commons-lang commons-lang 2.4 commons-collections commons-collections 3.2.1 net.sourceforge.serp serp 1.14.1 org.apache.geronimo.specs geronimo-jpa_2.0_spec 1.1 org.apache.geronimo.specs geronimo-jms_1.1_spec 1.1.1 org.apache.geronimo.specs geronimo-jta_1.1_spec 1.1.1 org.apache.geronimo.specs geronimo-validation_1.0_spec 1.1 org.apache.bval org.apache.bval.bundle 0.3-incubating commons-beanutils commons-beanutils 1.8.3 org.apache.derby derby ${derby.version} commons-dbcp commons-dbcp 1.4 javax.xml.bind jaxb-api 2.2.1 com.sun.xml.bind jaxb-impl 2.2.1 hsqldb hsqldb ${hsqldb.version} postgresql postgresql ${postgresql.version} provided jakarta-regexp jakarta-regexp 1.4 log4j log4j 1.2.13 org.slf4j slf4j-api ${slf4jVersion} org.apache.ant ant 1.7.1 org.jmock jmock 2.5.1 org.jmock jmock-junit3 2.5.1 junit junit 3.8.1 net.sourceforge.findbugs annotations 1.3.2 junit junit test commons-dbcp commons-dbcp test install src/main/resources src/test/resources org.apache.maven.plugins maven-compiler-plugin 2.3.2 ${compile.class.source} ${compile.class.target} ${project.build.sourceEncoding} org.apache.maven.plugins maven-surefire-plugin 2.5 ${surefire.jvm.args} false false true openjpa.Log ${openjpa.Log} openjpa.DynamicEnhancementAgent ${openjpa.DynamicEnhancementAgent} openjpa.ConnectionDriverName ${connection.driver.name} openjpa.ConnectionURL ${connection.url} openjpa.ConnectionUserName ${connection.username} openjpa.ConnectionPassword ${connection.password} openjpa.jdbc.DBDictionary ${jdbc.DBDictionary} derby.stream.error.file target/derby.log derby.locks.deadlockTimeout ${derby.locks.deadlockTimeout} derby.locks.waitTimeout ${derby.locks.waitTimeout} openjpa.ConnectionProperties ${dbcp.args} tests.openjpa.allowfailure ${tests.openjpa.allowfailure} org.apache.maven.plugins maven-surefire-report-plugin 2.6 org.codehaus.mojo findbugs-maven-plugin 2.3.1 org.codehaus.mojo buildnumber-maven-plugin 1.0-beta-4 true offline true {0,date,long} at {0,time,short} validate create org.apache.rat apache-rat-plugin 0.7 org.apache.maven.plugins maven-dependency-plugin 2.1 org.apache.maven.plugins maven-release-plugin 2.1 false deploy site site-deploy -Papache-release,docbook-profile,test-derby,bval -DskipTests true org.apache.maven.plugins maven-antrun-plugin 1.3 org.apache.ant ant-jsch 1.7.1 ant-contrib ant-contrib 1.0b3 ant ant org.codehaus.mojo taglist-maven-plugin 2.4 org.codehaus.mojo ianal-maven-plugin 1.0-alpha-1 verify-legal-files true org.apache.maven.plugins maven-shade-plugin 1.4 org.apache.maven.plugins maven-checkstyle-plugin 2.2 org.codehaus.plexus plexus-velocity 1.1.3 org.apache.maven.plugins maven-jar-plugin 2.3.1 default-jar jar true ${buildNumber} ${timestamp} attach-tests test-jar org.apache.felix maven-bundle-plugin 2.0.1 true ${project.name} ${project.version} ${project.url} org.apache.openjpa openjpa-maven-plugin ${project.version} org.apache.maven.plugins maven-javadoc-plugin 2.7 ${project.build.sourceEncoding} attach-javadoc package jar process-classes javadoc ${javadoc.additionalparam} true org.apache.openjpa false 512m http://download.oracle.com/javase/6/docs/api/ http://download.oracle.com/javaee/6/api/ http://commons.apache.org/collections/api-release/ org.codehaus.mojo findbugs-maven-plugin 2.3.1 com.agilejava.docbkx docbkx-maven-plugin 2.0.13 org.eclipse.m2e lifecycle-mapping 1.0.0 org.apache.maven.plugins maven-checkstyle-plugin [1.0.0,) checkstyle org.apache.maven.plugins maven-enforcer-plugin [1.0.0,) enforce org.apache.maven.plugins maven-javadoc-plugin [1.0.0,) javadoc org.codehaus.mojo buildnumber-maven-plugin [1.0.0,) create org.codehaus.mojo javacc-maven-plugin [1.0.0,) jjtree-javacc org.apache.maven.plugins maven-antrun-plugin [1.0.0,) run org.apache.openjpa openjpa-maven-plugin [1.0.0,) enhance org.apache.openjpa openjpa-maven-plugin [1.0.0,) test-enhance org.apache.maven.plugins maven-dependency-plugin [1.0.0,) unpack org.apache.maven.plugins maven-compiler-plugin test-source-compile process-test-sources testCompile ${compile.testclass.source} ${compile.testclass.target} org.codehaus.mojo ianal-maven-plugin org.codehaus.mojo buildnumber-maven-plugin org.apache.maven.plugins maven-checkstyle-plugin process-sources checkstyle ${checkstyle.config.location} true true true **/*_.java org.apache.maven.plugins maven-enforcer-plugin validate enforce [2.2.1,) [1.6,) org.apache.rat apache-rat-plugin verify check false 0 **/.*/** **/target/**/* **/src/**/*.bat **/src/**/*.css **/src/**/*.html **/src/**/*.java **/src/**/*.js **/src/**/*.jsp **/src/**/*.properties **/src/**/*.sh **/src/**/*.txt **/src/**/*.vm **/src/**/*.xml org.apache.maven.plugins maven-project-info-reports-plugin 2.1.1 org.apache.maven.plugins maven-javadoc-plugin 2.7 package true 1.6 http://download.oracle.com/javase/6/docs/api/ http://download.oracle.com/javaee/6/api/ http://commons.apache.org/collections/api-release/ javadoc openjpa-2.2.2.orig/CHANGES.txt0000644000000000000000000001515612133327262012620 0ustar Apache OpenJPA 2.2.2 Licensed under Apache License 2.0 - http://www.apache.org/licenses/LICENSE-2.0 -------------------------------------------------------------------------------- Content ------- * Overview * License * Notices * Prerequisites * Documentation * Getting Involved * Included Changes * Sub-tasks * Bugs * Improvements * New Features * Test Overview -------- The Apache OpenJPA community is proud to release a maintenance distribution of OpenJPA 2.2.2. This distribution is based on the final JSR 317 Java Persistence API, Version 2.0 specification and passes the JPA 2.0 TCK, while remaining backwards compatible with prior releases based on the Java Persistence API (JPA 1.0) part of Java Community Process JSR-220 (Enterprise JavaBeans 3.0). Additional information on the OpenJPA project may be found at the project web site: http://openjpa.apache.org License ------- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. The license may also be found in LICENSE.txt included in each assembly. Notices ------- Copyright 2006,2013 The Apache Software Foundation. Apache, the Apache feather logo and OpenJPA are trademarks of The Apache Software Foundation. This product includes software developed at The Apache Software Foundation (http://www.apache.org/). OpenJPA includes the persistence and orm schemas from the JPA specifications. Copyright 2005-2009 Sun Microsystems, Inc. All rights reserved. OpenJPA elects to include this software in this distribution under the CDDL license. You can obtain a copy of the License at: https://glassfish.dev.java.net/public/CDDL+GPL.html The source code is available at: http://java.net/projects/glassfish The complete list of notices can be found in NOTICE.txt included in each assembly. Prerequisites ------------- OpenJPA requires Java SE 6 or higher and a relational database of some sort. Documentation ------------- If you have questions about OpenJPA, a good source of information is the online product manual. You can find the manual for the current release as well as older releases of OpenJPA at http://openjpa.apache.org/documentation.html If you can't find what you are looking for in the manual or would like more clarification, please post to the OpenJPA development mailing list. Information on all of the OpenJPA mailing lists may be found here: http://openjpa.apache.org/mailing-lists.html Getting Involved ---------------- The Apache OpenJPA project is being built by the open source community for the open source community - we welcome your input and contributions! What we are looking for * Source code and fixes contributions * Documentation assistance * Product and feature suggestions * Detailed and constructive feedback * Articles and whitepapers How do I contribute? * To discuss Apache OpenJPA topics check out the mailing lists. * Informal discussion also occurs on the #openjpa IRC channel on freenode.net. * Bugs and other issues can be posted on the issue tracker at https://issues.apache.org/jira/browse/OPENJPA Included Changes in OpenJPA 2.2.2 --------------------------------- Bug [OPENJPA-2172] - openjpa-all jar is missing slf4j runtime dependency [OPENJPA-2196] - Create Sequence Postgres 9.1 [OPENJPA-2233] - Failed to invoke pcGetIDOwningClass method on embeddable entity with ID annotation [OPENJPA-2235] - "READ_UNCOMMITTED" setting for the fetch plan isolation level is ignored in DB2Dictionary [OPENJPA-2240] - JVMVRFY012 when using openjpa together with hyperjaxb3 [OPENJPA-2244] - Nested classpath ignored in mapping tool ant task [OPENJPA-2257] - Concurreny in org.apache.openjpa.persistence.EntityManagerImpl.getProperties leads to NullPointer and ConcurrentModificationException [OPENJPA-2284] - NPE occurs when is added to a in an orm. [OPENJPA-2285] - L2 cache doesn't store FK(s) back into the cache when lazy loading data. [OPENJPA-2288] - MetaDataRepository should be able to filter classes from other app ClassLoaders in JEE Env [OPENJPA-2289] - Additional SQL alias generated for query with subquery causes incorrect # of rows returned - Oracle only [OPENJPA-2298] - VerifyError/Stack underflow due to extra 'return' statements generated by PCEnhancer. [OPENJPA-2304] - Thread deadlock in CriteriaBuilder [OPENJPA-2320] - CriteriaBuilder predicate construction deadlocks in multi-core VM due to static initializer [OPENJPA-2321] - Synchronizing logging output stream causes deadlock when used some JDK LogManger derivative [OPENJPA-2326] - Updates in TCK execution configuration [OPENJPA-2334] - OpenJPA must support processing puRoot & jar-file URLs as jar-formatted InputStreams Improvement [OPENJPA-2264] - Upcast PreparedStatementManagerImpl.logSQLWarnings to take a Statement rather than a PreparedStatement [OPENJPA-2292] - Reduce object allocations [OPENJPA-2293] - Reduce LifecycleEventManager [OPENJPA-2324] - Option to express literal in query string directly into generate SQL [OPENJPA-2332] - Update message when unable to resolve datasource configuration [OPENJPA-2346] - Optimize MetaDataRepository.getMetaDataInternal [OPENJPA-2347] - Make StateManagerImpl more extensible [OPENJPA-2348] - Cache calculated hashCode in OpenJPAId [OPENJPA-2353] - Reduce object allocations [OPENJPA-2354] - Removed synchronized from enhancer added pcReplaceStateManager method [OPENJPA-2368] - Move www.apache.org/openjpa/ns/orm to openjpa.apache.org/ns/orm New Feature [OPENJPA-2295] - speed up query metadata lookup Question [OPENJPA-1532] - Should the element in a persistence unit definition automatically turn on the data cache? openjpa-2.2.2.orig/openjpa-xmlstore/0000755000000000000000000000000012133330002014270 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/pom.xml0000644000000000000000000001363112133327264015631 0ustar 4.0.0 org.apache.openjpa openjpa-parent 2.2.2 org.apache.openjpa openjpa-xmlstore jar OpenJPA XML Store OpenJPA XML Store org.apache.openjpa openjpa-kernel ${project.version} org.apache.openjpa openjpa-persistence-jdbc ${project.version} test org.apache.openjpa openjpa-persistence-jdbc ${project.version} test-jar test org.apache.maven.plugins maven-dependency-plugin unpack test-compile unpack org.apache.openjpa openjpa-persistence-jdbc ${project.version} test-jar ${project.build.testOutputDirectory} org/apache/openjpa/persistence/test/*.class org.apache.openjpa openjpa-maven-plugin org/apache/openjpa/xmlstore/**/Test*.class org/apache/openjpa/persistence/**/*.class true true enhancer process-test-classes test-enhance org.apache.openjpa openjpa-persistence-jdbc ${project.version} org.apache.maven.plugins maven-surefire-plugin ${test.jvm.arguments} openjpa.Log ${openjpa.Log} openjpa.DynamicEnhancementAgent false tests.openjpa.allowfailure ${tests.openjpa.allowfailure} openjpa-2.2.2.orig/openjpa-xmlstore/src/0000755000000000000000000000000012133327264015077 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/0000755000000000000000000000000012133327264016056 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/0000755000000000000000000000000012133327264016777 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/0000755000000000000000000000000012133327264017566 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/0000755000000000000000000000000012133327264021007 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/openjpa/0000755000000000000000000000000012133327264022443 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/openjpa/xmlstore/0000755000000000000000000000000012133327264024320 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/openjpa/xmlstore/simple/0000755000000000000000000000000012133327264025611 5ustar ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/openjpa/xmlstore/simple/TestPersistence.javaopenjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/openjpa/xmlstore/simple/TestPersistence0000644000000000000000000001115412133327264030662 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.xmlstore.simple; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import org.apache.openjpa.persistence.OpenJPAEntityManager; import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; import org.apache.openjpa.persistence.test.AbstractPersistenceTestCase; /** * Simple XMLStore test case to get an EntityManager and perform some basic operations. */ public class TestPersistence extends AbstractPersistenceTestCase { public void testCreateEntityManager() { OpenJPAEntityManagerFactorySPI emf = createNamedEMF("xmlstore-simple"); try { EntityManager em = emf.createEntityManager(); EntityTransaction t = em.getTransaction(); assertNotNull(t); t.begin(); t.setRollbackOnly(); t.rollback(); // openjpa-facade test assertTrue(em instanceof OpenJPAEntityManager); OpenJPAEntityManager ojem = (OpenJPAEntityManager) em; ojem.getFetchPlan().setMaxFetchDepth(1); assertEquals(1, ojem.getFetchPlan().getMaxFetchDepth()); em.close(); } finally { closeEMF(emf); } } public void testQuery() { OpenJPAEntityManagerFactorySPI emf = createNamedEMF("xmlstore-simple", CLEAR_TABLES, AllFieldTypes.class); try { EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); AllFieldTypes aft = new AllFieldTypes(); aft.setStringField("foo"); aft.setIntField(10); em.persist(aft); em.getTransaction().commit(); em.close(); em = emf.createEntityManager(); em.getTransaction().begin(); assertEquals(1, em.createQuery ("select x from AllFieldTypes x where x.stringField = 'foo'"). getResultList().size()); assertEquals(0, em.createQuery ("select x from AllFieldTypes x where x.stringField = 'bar'"). getResultList().size()); assertEquals(1, em.createQuery ("select x from AllFieldTypes x where x.intField >= 10"). getResultList().size()); em.getTransaction().rollback(); em.close(); } finally { closeEMF(emf); } } public void testNewDeleteNew() { OpenJPAEntityManagerFactorySPI emf = createNamedEMF("xmlstore-simple", CLEAR_TABLES, Place.class); try { EntityManager em = emf.createEntityManager(); // create new Place place = new Place(); place.setLocation("Lexington"); assertFalse(em.contains(place)); em.getTransaction().begin(); em.persist(place); em.getTransaction().commit(); assertTrue(em.contains(place)); // find and verify place = em.find(Place.class, "Lexington"); assertNotNull(place); assertEquals("Lexington", place.getLocation()); // delete em.getTransaction().begin(); em.remove(place); em.getTransaction().commit(); assertFalse(em.contains(place)); // recreate place = new Place(); place.setLocation("Lexington"); assertFalse(em.contains(place)); em.getTransaction().begin(); em.persist(place); em.getTransaction().commit(); assertTrue(em.contains(place)); // find and verify place = em.find(Place.class, "Lexington"); assertNotNull(place); assertEquals("Lexington", place.getLocation()); em.close(); } finally { closeEMF(emf); } } } openjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/openjpa/xmlstore/simple/Place.java0000644000000000000000000000234512133327264027504 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.xmlstore.simple; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Place implements Serializable { private static final long serialVersionUID = 1L; private String location; @Id public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/openjpa/xmlstore/simple/AllFieldTypes.javaopenjpa-2.2.2.orig/openjpa-xmlstore/src/test/java/org/apache/openjpa/xmlstore/simple/AllFieldTypes.j0000644000000000000000000002152312133327264030470 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.xmlstore.simple; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.Set; import java.util.List; import java.util.ArrayList; import javax.persistence.Entity; import javax.persistence.OneToOne; import javax.persistence.OneToMany; import org.apache.openjpa.persistence.PersistentCollection; @Entity public class AllFieldTypes implements Serializable { private static final long serialVersionUID = 1L; public static enum EnumType {Value1, Value2}; // @Basic types private short shortField; private int intField; private boolean booleanField; private long longField; private float floatField; private char charField; private double doubleField; private byte byteField; private Short wShortField; private Integer wIntegerField; private Boolean wBooleanField; private Long wLongField; private Float wFloatField; private Character wCharacterField; private Double wDoubleField; private Byte wByteField; private BigInteger bigIntegerField; private BigDecimal bigDecimalField; private String stringField; private Date dateField; private Calendar calendarField; private java.sql.Date sqlDateField; private java.sql.Time sqlTimeField; private java.sql.Timestamp sqlTimestampField; private byte[] byteLob; private Byte[] wByteLob; private char[] charLob; private Character[] wCharacterLob; private EnumType enumField; private Serializable serializableField; // Additional types private Set setOfStrings = new HashSet(); private String[] arrayOfStrings; @PersistentCollection private int[] arrayOfInts; // one-to-one and one-to-many relations to self @OneToOne private AllFieldTypes selfOneOne; @OneToMany private List selfOneMany = new ArrayList(); public void setShortField(short shortField) { this.shortField = shortField; } public short getShortField() { return this.shortField; } public void setIntField(int intField) { this.intField = intField; } public int getIntField() { return this.intField; } public void setBooleanField(boolean booleanField) { this.booleanField = booleanField; } public boolean getBooleanField() { return this.booleanField; } public void setLongField(long longField) { this.longField = longField; } public long getLongField() { return this.longField; } public void setFloatField(float floatField) { this.floatField = floatField; } public float getFloatField() { return this.floatField; } public void setCharField(char charField) { this.charField = charField; } public char getCharField() { return this.charField; } public void setDoubleField(double doubleField) { this.doubleField = doubleField; } public double getDoubleField() { return this.doubleField; } public void setByteField(byte byteField) { this.byteField = byteField; } public byte getByteField() { return this.byteField; } public void setStringField(String stringField) { this.stringField = stringField; } public String getStringField() { return this.stringField; } public void setDateField(Date dateField) { this.dateField = dateField; } public Date getDateField() { return this.dateField; } public void setSetOfStrings(Set setOfStrings) { this.setOfStrings = setOfStrings; } public Set getSetOfStrings() { return this.setOfStrings; } public void setArrayOfStrings(String[] arrayOfStrings) { this.arrayOfStrings = arrayOfStrings; } public String[] getArrayOfStrings() { return this.arrayOfStrings; } public void setArrayOfInts(int[] arrayOfInts) { this.arrayOfInts = arrayOfInts; } public int[] getArrayOfInts() { return arrayOfInts; } public BigDecimal getBigDecimalField() { return bigDecimalField; } public void setBigDecimalField(BigDecimal bigDecimalField) { this.bigDecimalField = bigDecimalField; } public BigInteger getBigIntegerField() { return bigIntegerField; } public void setBigIntegerField(BigInteger bigIntegerField) { this.bigIntegerField = bigIntegerField; } public byte[] getByteLob() { return byteLob; } public void setByteLob(byte[] byteLob) { this.byteLob = byteLob; } public Calendar getCalendarField() { return calendarField; } public void setCalendarField(Calendar calendarField) { this.calendarField = calendarField; } public char[] getCharLob() { return charLob; } public void setCharLob(char[] charLob) { this.charLob = charLob; } public EnumType getEnumField() { return enumField; } public void setEnumField(EnumType enumField) { this.enumField = enumField; } public Serializable getSerializableField() { return serializableField; } public void setSerializableField(Serializable serializableField) { this.serializableField = serializableField; } public java.sql.Date getSqlDateField() { return sqlDateField; } public void setSqlDateField(java.sql.Date sqlDateField) { this.sqlDateField = sqlDateField; } public java.sql.Time getSqlTimeField() { return sqlTimeField; } public void setSqlTimeField(java.sql.Time sqlTimeField) { this.sqlTimeField = sqlTimeField; } public java.sql.Timestamp getSqlTimestampField() { return sqlTimestampField; } public void setSqlTimestampField(java.sql.Timestamp sqlTimestampField) { this.sqlTimestampField = sqlTimestampField; } public Boolean getWBooleanField() { return wBooleanField; } public void setWBooleanField(Boolean booleanField) { wBooleanField = booleanField; } public Byte getWByteField() { return wByteField; } public void setWByteField(Byte byteField) { wByteField = byteField; } public Byte[] getWByteLob() { return wByteLob; } public void setWByteLob(Byte[] byteLob) { wByteLob = byteLob; } public Character getWCharacterField() { return wCharacterField; } public void setWCharacterField(Character characterField) { wCharacterField = characterField; } public Character[] getWCharacterLob() { return wCharacterLob; } public void setWCharacterLob(Character[] characterLob) { wCharacterLob = characterLob; } public Double getWDoubleField() { return wDoubleField; } public void setWDoubleField(Double doubleField) { wDoubleField = doubleField; } public Float getWFloatField() { return wFloatField; } public void setWFloatField(Float floatField) { wFloatField = floatField; } public Integer getWIntegerField() { return wIntegerField; } public void setWIntegerField(Integer integerField) { wIntegerField = integerField; } public Long getWLongField() { return wLongField; } public void setWLongField(Long longField) { wLongField = longField; } public Short getWShortField() { return wShortField; } public void setWShortField(Short shortField) { wShortField = shortField; } public AllFieldTypes getSelfOneOne() { return selfOneOne; } public void setSelfOneOne(AllFieldTypes selfOneOne) { this.selfOneOne = selfOneOne; } public List getSelfOneMany() { return selfOneMany; } public void setSelfOneMany(List selfOneMany) { this.selfOneMany = selfOneMany; } } openjpa-2.2.2.orig/openjpa-xmlstore/src/test/resources/0000755000000000000000000000000012133327264020070 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/resources/META-INF/0000755000000000000000000000000012133327264021230 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/test/resources/META-INF/persistence.xml0000644000000000000000000000372312133327264024303 0ustar org.apache.openjpa.xmlstore.simple.AllFieldTypes org.apache.openjpa.xmlstore.simple.Place openjpa-2.2.2.orig/openjpa-xmlstore/src/main/0000755000000000000000000000000012133327264016023 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/0000755000000000000000000000000012133327264016744 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/0000755000000000000000000000000012133327264017533 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/0000755000000000000000000000000012133327264020754 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/openjpa/0000755000000000000000000000000012133327264022410 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/0000755000000000000000000000000012133327264024265 5ustar openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/package.html0000644000000000000000000000164412133327264026553 0ustar

XML Store

Simple XML store using the common OpenJPA runtime system as a front end.

openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLStore.java0000644000000000000000000001223012133327264026603 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.xmlstore; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.openjpa.meta.ClassMetaData; /** * Represents a store of object data encoded in XML. This store only allows * one datastore transaction to proceed at a time. File I/O errors can put * this store into an invalid state. */ public class XMLStore { private final XMLConfiguration _conf; // each key in the map is a least-derived class metadata object, and each // value is a map of oids to object datas representing the instances of // that class, including subclasses private final Map _metaOidMaps = new HashMap(); // store gets locked during transactions private boolean _locked; /** * Constructor; supply configuration. */ public XMLStore(XMLConfiguration conf) { _conf = conf; } /** * Return the data for the given oid, or null if it does not exist. */ public synchronized ObjectData getData(ClassMetaData meta, Object oid) { meta = getLeastDerived(meta); return (ObjectData) getMap(meta).get(oid); } /** * Return all datas for the base class of the given type. */ public synchronized ObjectData[] getData(ClassMetaData meta) { meta = getLeastDerived(meta); Collection vals = getMap(meta).values(); return (ObjectData[]) vals.toArray(new ObjectData[vals.size()]); } /** * Returns the map of oids to object datas for the given least-derived type. */ private Map getMap(ClassMetaData meta) { Map m = (Map) _metaOidMaps.get(meta); if (m != null) return m; // load datas from file and cache them Collection datas = _conf.getFileHandler().load(meta); m = new HashMap(datas.size()); for (Iterator itr = datas.iterator(); itr.hasNext();) { ObjectData data = (ObjectData) itr.next(); m.put(data.getId(), data); } _metaOidMaps.put(meta, m); return m; } /** * Return the least-derived metadata in the inheritance chain * above meta, or meta if it is a * least-derived metadata. */ private static ClassMetaData getLeastDerived(ClassMetaData meta) { while (meta.getPCSuperclass() != null) meta = meta.getPCSuperclassMetaData(); return meta; } /** * Begin a datastore transaction. Obtains an exclusive write lock on the * store. */ public synchronized void beginTransaction() { // lock store while (_locked) try { wait(); } catch (InterruptedException ie) { } _locked = true; } /** * End the datastore transaction. * * @param updates {@link ObjectData} instances to insert or update * @param deletes {@link ObjectData} instances to delete */ public synchronized void endTransaction(Collection updates, Collection deletes) { // track dirty types Set dirty = new HashSet(); try { // commit updates if (updates != null) { for (Iterator itr = updates.iterator(); itr.hasNext();) { ObjectData data = (ObjectData) itr.next(); ClassMetaData meta = getLeastDerived(data.getMetaData()); getMap(meta).put(data.getId(), data); dirty.add(meta); } } // commit deletes if (deletes != null) { for (Iterator itr = deletes.iterator(); itr.hasNext();) { ObjectData data = (ObjectData) itr.next(); ClassMetaData meta = getLeastDerived(data.getMetaData()); getMap(meta).remove(data.getId()); dirty.add(meta); } } // write changes to dirty extents back to file XMLFileHandler fh = _conf.getFileHandler(); for (Iterator itr = dirty.iterator(); itr.hasNext();) { ClassMetaData meta = (ClassMetaData) itr.next(); fh.store(meta, getMap(meta).values()); } } finally { // unlock store notify(); _locked = false; } } } openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLFileHandler.java0000644000000000000000000006014712133327264027676 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.xmlstore; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.io.Writer; import java.lang.reflect.Constructor; import java.math.BigDecimal; import java.math.BigInteger; import java.security.AccessController; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import javax.xml.parsers.SAXParser; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.lib.util.Base16Encoder; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.xml.XMLFactory; import org.apache.openjpa.lib.xml.XMLWriter; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.Id; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.StoreException; import org.apache.openjpa.util.UnsupportedException; /** * Stores {@link ObjectData} objects by serializing a collection * of them into and out of an XML file. */ public class XMLFileHandler { private final XMLConfiguration _conf; /** * Constructor; supply configuration. */ public XMLFileHandler(XMLConfiguration conf) { _conf = conf; } /** * Loads all instances of meta into a list of objects. * The given meta must represent a least-derived * persistence-capable type. */ public Collection load(ClassMetaData meta) { File f = getFile(meta); if (!(AccessController.doPrivileged( J2DoPrivHelper.existsAction(f))).booleanValue() || (AccessController.doPrivileged( J2DoPrivHelper.lengthAction(f))).longValue() == 0) return Collections.EMPTY_SET; try { return read(f); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new StoreException(e); } } /** * Read a collection of {@link ObjectData}s from the contents of the * given file. */ private Collection read(File f) throws Exception { // parse the file and return the objects it contains SAXParser parser = XMLFactory.getSAXParser(false, false); ObjectDataHandler handler = new ObjectDataHandler(_conf); parser.parse(f, handler); return handler.getExtent(); } /** * Returns a {@link File} object that meta lives * in. This implementation creates a filename from the full class * name of the type identified by meta, and returns * a {@link File} object that has this filename and whose base * directory is the URL identified by the ConnectionURL * configuration property. */ private File getFile(ClassMetaData meta) { if (_conf.getConnectionURL() == null) { throw new InternalException("Invalid ConnectionURL"); } File baseDir = new File(_conf.getConnectionURL()); return new File(baseDir, meta.getDescribedType().getName()); } /** * Stores all instances in datas into the appropriate file, * as dictated by meta. * * @param meta the least-derived type of the instances being stored * @param datas a collection of {@link ObjectData} instances, each * of which represents an object of type meta */ public void store(ClassMetaData meta, Collection datas) { if (meta.getPCSuperclass() != null) throw new InternalException(); File f = getFile(meta); if (!(AccessController.doPrivileged( J2DoPrivHelper.existsAction(f.getParentFile()))).booleanValue()) AccessController.doPrivileged( J2DoPrivHelper.mkdirsAction(f.getParentFile())); FileWriter fw = null; try { fw = new FileWriter(f); write(datas, fw); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new StoreException(e); } finally { if (fw != null) try { fw.close(); } catch (IOException ioe) { } } } /** * Write the given collection of {@link ObjectData}s to the given file. */ private void write(Collection datas, FileWriter fw) throws Exception { // create an XML pretty printer to write out the objects Writer out = new XMLWriter(fw); // start the file; the root node is an "extent" out.write(""); out.write(""); // run through each object in the collection for (Iterator itr = datas.iterator(); itr.hasNext();) { ObjectData obj = (ObjectData) itr.next(); ClassMetaData meta = obj.getMetaData(); // write out the "object" element start out.write(""); // run through each field writing out the value FieldMetaData[] fmds = meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].getManagement() != fmds[i].MANAGE_PERSISTENT) continue; out.write(""); // write out the field data depending upon type switch (fmds[i].getTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.ARRAY: Collection c = (Collection) obj.getField(i); if (c == null) break; // write out each of the elements int elemType = fmds[i].getElement().getTypeCode(); for (Iterator ci = c.iterator(); ci.hasNext();) { out.write(""); writeDataValue(out, elemType, ci.next()); out.write(""); } break; case JavaTypes.MAP: Map m = (Map) obj.getField(i); if (m == null) break; // write out each of the map entries Collection entries = m.entrySet(); int keyType = fmds[i].getKey().getTypeCode(); int valueType = fmds[i].getElement().getTypeCode(); for (Iterator ei = entries.iterator(); ei.hasNext();) { Map.Entry e = (Map.Entry) ei.next(); out.write(""); writeDataValue(out, keyType, e.getKey()); out.write(""); out.write(""); writeDataValue(out, valueType, e.getValue()); out.write(""); } break; default: writeDataValue(out, fmds[i].getTypeCode(), obj.getField(i)); } out.write(""); } out.write(""); } out.write(""); } /** * Write out the data value. This method writes nulls as "null", * serializes (using Java serialization and base16 encoding) out non- * primitives/boxed primitives and non-persistent types, and writes * primitives/boxed primitives and oids using their toString. */ public void writeDataValue(Writer out, int type, Object val) throws IOException { // write nulls as "null" if (val == null) { out.write("null"); return; } switch (type) { case JavaTypes.OBJECT: case JavaTypes.OID: if (!(val instanceof Serializable)) throw new UnsupportedException( "Cannot store non-serializable," + " non-persistence-capable value: " + val); // serialize out the object and encode the result with base16 ByteArrayOutputStream baos = new ByteArrayOutputStream(8192); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(val); oos.close(); out.write(Base16Encoder.encode(baos.toByteArray())); break; case JavaTypes.CHAR: case JavaTypes.CHAR_OBJ: // quote chars so we can distinguish whitespace chars; special // case for \0 char c = ((Character) val).charValue(); out.write("'"); if (c == '\0') out.write("0x0"); else out.write(XMLEncoder.encode(val.toString())); out.write("'"); break; case JavaTypes.STRING: // quote strings so we can distinguish leading and trailing // whitespace out.write("\""); out.write(XMLEncoder.encode(val.toString())); out.write("\""); break; case JavaTypes.PC: case JavaTypes.PC_UNTYPED: // write the type of oid object + ':' + oid string out.write(val.getClass().getName()); out.write(':'); out.write(XMLEncoder.encode(val.toString())); break; default: // must be a number of simple type; no need to encode out.write(val.toString()); } } /** * Used to reconstruct {@link ObjectData} instances from SAX events. */ private static class ObjectDataHandler extends DefaultHandler { private static final Class[] ARGS = new Class[]{ String.class }; private final XMLConfiguration _conf; private final Collection _extent = new ArrayList(); // parse state private ObjectData _object; private FieldMetaData _fmd; private Object _fieldVal; private Object _keyVal; private StringBuffer _buf; /** * Constructor; supply configuration. */ public ObjectDataHandler(XMLConfiguration conf) { _conf = conf; } /** * Return the results of the parsing. */ public Collection getExtent() { return _extent; } public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { try { startElement(qName, attrs); } catch (RuntimeException re) { throw re; } catch (SAXException se) { throw se; } catch (Exception e) { throw new SAXException(e); } } private void startElement(String qName, Attributes attrs) throws Exception { switch (qName.charAt(0)) { case 'o': // object // get the metadata for the type we're reading String type = attrs.getValue("class"); ClassMetaData meta = _conf.getMetaDataRepositoryInstance(). getMetaData(classForName(type), null, true); // construct the oid object Object oid; if (meta.getIdentityType() == meta.ID_DATASTORE) oid = new Id(attrs.getValue("oid"), _conf, null); else oid = PCRegistry.newObjectId(meta.getDescribedType(), attrs.getValue("oid")); // create an ObjectData that will contain the information // for this instance, and set the version _object = new ObjectData(oid, meta); _object.setVersion(new Long(attrs.getValue("version"))); break; case 'f': // field // start parsing a field element: for container types, // initialize the container; for other types, initialize a // buffer _fmd = _object.getMetaData().getField(attrs.getValue("name")); switch (_fmd.getTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.ARRAY: _fieldVal = new ArrayList(); break; case JavaTypes.MAP: _fieldVal = new HashMap(); break; default: _buf = new StringBuffer(); } break; case 'e': // element case 'k': // key case 'v': // value // initialize a buffer for the element value _buf = new StringBuffer(); break; } } public void endElement(String uri, String localName, String qName) throws SAXException { try { endElement(qName); } catch (RuntimeException re) { throw re; } catch (SAXException se) { throw se; } catch (Exception e) { throw new SAXException(e); } } private void endElement(String qName) throws Exception { Object val; switch (qName.charAt(0)) { case 'o': // object // add the object to our results _extent.add(_object); case 'f': // field switch (_fmd.getTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.ARRAY: case JavaTypes.MAP: // field value already constructed break; default: // construct the field value from text within the // element _fieldVal = fromXMLString(_fmd.getTypeCode(), _fmd.getTypeMetaData(), _buf.toString()); } // set the field value into the object being parsed _object.setField(_fmd.getIndex(), _fieldVal); break; case 'e': // element // cache element value val = fromXMLString(_fmd.getElement().getTypeCode(), _fmd.getElement().getTypeMetaData(), _buf.toString()); ((Collection) _fieldVal).add(val); break; case 'k': // key // cache key value _keyVal = fromXMLString(_fmd.getKey().getTypeCode(), _fmd.getKey().getTypeMetaData(), _buf.toString()); break; case 'v': // value // create value and put cached key and value into map val = fromXMLString(_fmd.getElement().getTypeCode(), _fmd.getElement().getTypeMetaData(), _buf.toString()); Map map = (Map) _fieldVal; map.put(_keyVal, val); break; } // don't cache text between elements _buf = null; } public void characters(char[] ch, int start, int length) { if (_buf != null) _buf.append(ch, start, length); } /** * Recreate a field value from its XML string. */ public Object fromXMLString(int type, ClassMetaData rel, String str) throws Exception { str = str.trim(); if (str.equals("null")) return null; switch (type) { case JavaTypes.BOOLEAN: case JavaTypes.BOOLEAN_OBJ: return Boolean.valueOf(str); case JavaTypes.BYTE: case JavaTypes.BYTE_OBJ: return new Byte(str); case JavaTypes.CHAR: case JavaTypes.CHAR_OBJ: // strip quotes; special case for 0x0 str = str.substring(1, str.length() - 1); if (str.equals("0x0")) return new Character('\0'); return new Character(XMLEncoder.decode(str).charAt(0)); case JavaTypes.DOUBLE: case JavaTypes.DOUBLE_OBJ: return new Double(str); case JavaTypes.FLOAT: case JavaTypes.FLOAT_OBJ: return new Float(str); case JavaTypes.INT: case JavaTypes.INT_OBJ: return new Integer(str); case JavaTypes.LONG: case JavaTypes.LONG_OBJ: return new Long(str); case JavaTypes.SHORT: case JavaTypes.SHORT_OBJ: return new Short(str); case JavaTypes.NUMBER: case JavaTypes.BIGDECIMAL: return new BigDecimal(str); case JavaTypes.BIGINTEGER: return new BigInteger(str); case JavaTypes.STRING: // strip quotes str = str.substring(1, str.length() - 1); return XMLEncoder.decode(str); case JavaTypes.OBJECT: case JavaTypes.OID: // convert the chars into bytes, and run them through an // ObjectInputStream in order to get the serialized object byte[] bytes = Base16Encoder.decode(str); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); Object data = ois.readObject(); ois.close(); return data; case JavaTypes.DATE: return new Date(str); case JavaTypes.PC: case JavaTypes.PC_UNTYPED: // parse out oid class name and value int idx = str.indexOf(':'); Class idClass = classForName(str.substring(0, idx)); String idStr = XMLEncoder.decode(str.substring(idx + 1)); Constructor cons = idClass.getConstructor(ARGS); return cons.newInstance(new Object[]{ idStr }); case JavaTypes.LOCALE: int under1 = str.indexOf('_'); if (under1 == -1) return (new Locale(str, "")); int under2 = str.indexOf('_', under1 + 1); if (under2 == -1) return new Locale(str.substring(0, under1), str.substring(under1 + 1)); String lang = str.substring(0, under1); String country = str.substring(under1 + 1, under2); String variant = str.substring(under2 + 1); return new Locale(lang, country, variant); default: throw new InternalException(); } } /** * Return the class for the specified name. */ private Class classForName(String name) throws Exception { ClassLoader loader = _conf.getClassResolverInstance(). getClassLoader(getClass(), null); return Class.forName(name, true, loader); } } /** * Utility methods for encoding and decoding XML strings. */ private static class XMLEncoder { /** * Encode the given string as XML text. */ public static String encode(String s) { StringBuffer buf = null; for (int i = 0; i < s.length(); i++) { switch (s.charAt(i)) { case '<': buf = initializeBuffer(buf, s, i); buf.append("<"); break; case '>': buf = initializeBuffer(buf, s, i); buf.append(">"); break; case '&': buf = initializeBuffer(buf, s, i); buf.append("&"); break; default: if (buf != null) buf.append(s.charAt(i)); } } if (buf != null) return buf.toString(); return s; } /** * Decode the given XML string. */ public static String decode(String s) { StringBuffer buf = null; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '&' && s.length() > i + 3) { if ((s.charAt(i + 1) == 'l' || s.charAt(i + 1) == 'g') && s.charAt(i + 2) == 't' && s.charAt(i + 3) == ';') { // < or > buf = initializeBuffer(buf, s, i); c = (s.charAt(i) == 'l') ? '<' : '>'; i += 3; } else if (s.length() > i + 4 && s.charAt(i + 1) == 'a' && s.charAt(i + 2) == 'm' && s.charAt(i + 3) == 'p' && s.charAt(i + 4) == ';') { // & buf = initializeBuffer(buf, s, i); c = '&'; i += 4; } } if (buf != null) buf.append(c); } if (buf != null) return buf.toString(); return s; } /** * Create and initialize a buffer for the encoded/decoded string if * needed. */ private static StringBuffer initializeBuffer(StringBuffer buf, String s, int i) { if (buf == null) { buf = new StringBuffer(); if (i > 0) buf.append (s.substring (0, i)); } return buf; } } } openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLConfiguration.java0000644000000000000000000000475312133327264030331 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.xmlstore; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.lib.conf.ProductDerivations; /** * Configuration implementation for the XML file store. Each unique * {@link BrokerFactory} has a distinct configuration instance. * Thus this configuration is shared by all {@link Broker}s * associated with the owning factory, and is a good place to provide access * to shared resources. Note that each broker has its own * {@link org.apache.openjpa.abstractstore.AbstractStoreManager}. */ public class XMLConfiguration extends OpenJPAConfigurationImpl { // shared resources private XMLStore _store; private XMLFileHandler _handler; /** * Default constructor. */ public XMLConfiguration() { super(false, false); // override the default and the current value of lock manager plugin // from our superclass to use the single-jvm lock manager lockManagerPlugin.setDefault("version"); lockManagerPlugin.setString("version"); ProductDerivations.beforeConfigurationLoad(this); loadGlobals(); } /** * Return the {@link XMLFileHandler} associated with this configuration. */ public synchronized XMLFileHandler getFileHandler() { if (_handler == null) _handler = new XMLFileHandler(this); return _handler; } /** * Return the {@link XMLStore} associated with this configuration. */ public synchronized XMLStore getStore() { if (_store == null) _store = new XMLStore(this); return _store; } } openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLStoreManager.java0000644000000000000000000002537312133327264030112 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.xmlstore; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.apache.openjpa.abstractstore.AbstractStoreManager; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.PCState; import org.apache.openjpa.lib.rop.ListResultObjectProvider; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.util.OptimisticException; import org.apache.openjpa.util.StoreException; /** * Store manager to a back-end consisting of XML files. This * implementation accesses data through the {@link XMLStore} associated with * its {@link XMLConfiguration}. Configuration instances are shared by all * store managers owned by all brokers created with the same factory. * * @see AbstractStoreManager */ public class XMLStoreManager extends AbstractStoreManager { private XMLConfiguration _conf; private XMLStore _store; // changed data within the current transaction private Collection _updates; private Collection _deletes; protected Collection getUnsupportedOptions() { Collection c = super.getUnsupportedOptions(); // remove options we do support but the abstract store doesn't c.remove(OpenJPAConfiguration.OPTION_ID_DATASTORE); c.remove(OpenJPAConfiguration.OPTION_OPTIMISTIC); // and add some that we don't support but the abstract store does c.add(OpenJPAConfiguration.OPTION_EMBEDDED_RELATION); c.add(OpenJPAConfiguration.OPTION_EMBEDDED_COLLECTION_RELATION); c.add(OpenJPAConfiguration.OPTION_EMBEDDED_MAP_RELATION); return c; } protected OpenJPAConfiguration newConfiguration() { // override to use our configuration type return new XMLConfiguration(); } protected void open() { // cache operational state _conf = (XMLConfiguration) ctx.getConfiguration(); _store = _conf.getStore(); } public boolean exists(OpenJPAStateManager sm, Object context) { // see if the given object exists in the store return _store.getData(sm.getMetaData(), sm.getObjectId()) != null; } /** * Increment the version indicator in the given state manager. */ private static void incrementVersion(OpenJPAStateManager sm) { long version = 0; if (sm.getVersion() != null) version = ((Long) sm.getVersion()).longValue() + 1; sm.setNextVersion(version); } public boolean initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch, Object context) { // we may already have looked up the backing ObjectData (see our extent // implementation below), and passed it through as the context; if // not, then look it up in the store ObjectData data; if (context != null) data = (ObjectData) context; else data = _store.getData(sm.getMetaData(), sm.getObjectId()); // no matching record? if (data == null) return false; // initialize the state manager with a new instance of the right // type and lifecycle state sm.initialize(data.getMetaData().getDescribedType(), state); // load the data from the ObjectData into the state mgr; note that // this store manager doesn't do any locking -- it relies on the // system's lock manager to lock after the load is complete data.load(sm, fetch); return true; } public boolean load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch, int lockLevel, Object context) { // we may already have looked up the backing ObjectData (see our extent // implementation below), and passed it through as the context; if // not, then look it up in the store ObjectData data; if (context != null) data = (ObjectData) context; else data = _store.getData(sm.getMetaData(), sm.getObjectId()); // no matching record? if (data == null) return false; // load the data from the ObjectData into the state mgr; note that // this store manager doesn't do any locking -- it relies on the // system's lock manager to lock after the load is complete data.load(sm, fields, fetch); return true; } public boolean syncVersion(OpenJPAStateManager sm, Object context) { if (sm.getVersion() == null) return false; // we may already have looked up the backing ObjectData (see our extent // implementation below), and passed it through as the context; if // not, then look it up in the store ObjectData data; if (context != null) data = (ObjectData) context; else data = _store.getData(sm.getMetaData(), sm.getObjectId()); // no record? if (data == null) return false; // if the version of data held by the state mgr is the same as the // version in the datastore, return true, letting the broker know that // it doesn't need to load any more data if (sm.getVersion().equals(data.getVersion())) return true; // set the version to be up-to-date, and return false letting // the broker know that it needs to load up-to-date data sm.setVersion(data.getVersion()); return false; } public void begin() { _store.beginTransaction(); } public void commit() { try { _store.endTransaction(_updates, _deletes); } finally { _updates = null; _deletes = null; } } public void rollback() { _updates = null; _deletes = null; _store.endTransaction(null, null); } protected Collection flush(Collection pNew, Collection pNewUpdated, Collection pNewFlushedDeleted, Collection pDirty, Collection pDeleted) { // we don't support incremental flushing, so pNewUpdated and // pNewFlushedDeleted should be empty; we ignore them here // track optimistic violations Collection exceps = new LinkedList(); // convert instances to ObjectDatas _updates = new ArrayList(pNew.size() + pDirty.size()); _deletes = new ArrayList(pDeleted.size()); // convert additions for (Iterator itr = pNew.iterator(); itr.hasNext();) { // create new object data for instance OpenJPAStateManager sm = (OpenJPAStateManager) itr.next(); Object oid = sm.getObjectId(); ObjectData data = _store.getData(sm.getMetaData(), oid); if (data != null) throw new StoreException("Attempt to insert " + "new object " + sm.getManagedInstance() + "with the same oid as an existing instance: " + oid). setFatal(true); data = new ObjectData(oid, sm.getMetaData()); incrementVersion(sm); data.store(sm); _updates.add(data); } // convert updates for (Iterator itr = pDirty.iterator(); itr.hasNext();) { OpenJPAStateManager sm = (OpenJPAStateManager) itr.next(); ObjectData data = _store.getData(sm.getMetaData(), sm.getObjectId()); // if data has been deleted or has the wrong version, record // opt lock violation if (data == null || !data.getVersion().equals(sm.getVersion())) { exceps.add(new OptimisticException (sm.getManagedInstance())); continue; } // store changes incrementVersion(sm); data = (ObjectData) data.clone(); data.store(sm); _updates.add(data); } // convert deletes for (Iterator itr = pDeleted.iterator(); itr.hasNext();) { OpenJPAStateManager sm = (OpenJPAStateManager) itr.next(); ObjectData data = _store.getData(sm.getMetaData(), sm.getObjectId()); // record delete if (data != null) _deletes.add(data); } return exceps; } public ResultObjectProvider executeExtent(ClassMetaData meta, boolean subclasses, FetchConfiguration fetch) { // ask the store for all ObjectDatas for the given type; this // actually gives us all instances of the base class of the type ObjectData[] datas = _store.getData(meta); Class candidate = meta.getDescribedType(); // create a list of the corresponding persistent objects that // match the type and subclasses criteria List pcs = new ArrayList(datas.length); for (int i = 0; i < datas.length; i++) { // does this instance belong in the extent? Class c = datas[i].getMetaData().getDescribedType(); if (c != candidate && (!subclasses || !candidate.isAssignableFrom(c))) continue; // look up the pc instance for the data, passing in the data // as well so that we can take advantage of the fact that we've // already looked it up. note that in the store manager's // initialize(), load(), etc methods we check for this data // being passed through and save ourselves a trip to the store // if it is present; this is particularly important in systems // where a trip to the store can be expensive. pcs.add(ctx.find(datas[i].getId(), fetch, null, datas[i], 0)); } return new ListResultObjectProvider(pcs); } public boolean isCached(List oids, BitSet edata) { // XMLStoreManager does not cache oids. return false; } } openjpa-2.2.2.orig/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/ObjectData.java0000644000000000000000000003314312133327264027134 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.xmlstore; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.apache.openjpa.event.OrphanedKeyAction; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.Proxy; import org.apache.openjpa.util.UnsupportedException; /** * In-memory form of data in datastore backing a single persistent object. */ public final class ObjectData implements Cloneable { private Object _oid; private Object[] _data; private Long _version; private ClassMetaData _meta; /** * Create the object without underlying data. Just pass in type specific * metadata and the oid. */ public ObjectData(Object oid, ClassMetaData meta) { _oid = oid; _meta = meta; _data = new Object[meta.getFields().length]; } /** * Getter for oid. */ public Object getId() { return _oid; } /** * Get the data for the field with the given index. */ public Object getField(int num) { return _data[num]; } /** * Set the data for the field with the given index. */ public void setField(int num, Object val) { _data[num] = val; } /** * Set the version number of the object. */ public void setVersion(Long version) { _version = version; } /** * Get the version number of the object. */ public Long getVersion() { return _version; } /** * Get the metadata associated with the type of persistent object for * which this data applies. */ public ClassMetaData getMetaData() { return _meta; } /** * Load the data and version information for this object into the * given state manager. Only fields in the given fetch configuration are * loaded. */ public void load(OpenJPAStateManager sm, FetchConfiguration fetch) { if (sm.getVersion() == null) sm.setVersion(_version); FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) if (!sm.getLoaded().get(i) && fetch.requiresFetch(fmds[i]) != FetchConfiguration.FETCH_NONE) sm.store(i, toLoadable(sm, fmds[i], _data[i], fetch)); } /** * Load the data and version information for this object into the * given state manager. Only fields in the given bit set will be loaded. */ public void load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch) { if (sm.getVersion() == null) sm.setVersion(_version); FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) if (fields.get(i)) sm.store(i, toLoadable(sm, fmds[i], _data[i], fetch)); } /** * Convert the stored value val into a value for loading * into a state manager. */ private static Object toLoadable(OpenJPAStateManager sm, FieldMetaData fmd, Object val, FetchConfiguration fetch) { if (val == null) return null; Collection c; switch (fmd.getTypeCode()) { case JavaTypes.COLLECTION: // the stored value must be a collection c = (Collection) val; // the state manager will create a proxy collection of the // needed type depending on the declared type of the user's // field; the proxy will perform dirty tracking, etc Collection c2 = (Collection) sm.newFieldProxy(fmd.getIndex()); // populate the proxy collection with our stored data, // converting it to the right type from its stored form for (Iterator itr = c.iterator(); itr.hasNext();) c2.add(toNestedLoadable(sm, fmd.getElement(), itr.next(), fetch)); return c2; case JavaTypes.ARRAY: // the stored value must be a collection; we put arrays into // collections for storage c = (Collection) val; // create a new array of the right type; unlike collections in // the case above, arrays cannot be proxied Object a = Array.newInstance(fmd.getElement().getType(), c.size()); // populate the array with our stored data, converting it to the // right type from its stored form int idx = 0; for (Iterator itr = c.iterator(); itr.hasNext(); idx++) Array.set(a, idx, toNestedLoadable(sm, fmd.getElement(), itr.next(), fetch)); return a; case JavaTypes.MAP: // the stored value must be a map Map m = (Map) val; // the state manager will create a proxy map of the needed // type depending on the declared type of the user's field; the // proxy will perform dirty tracking, etc Map m2 = (Map) sm.newFieldProxy(fmd.getIndex()); // populate the proxy map with our stored data, converting // it to the right type from its stored form for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) { Map.Entry e = (Map.Entry) itr.next(); m2.put(toNestedLoadable(sm, fmd.getKey(), e.getKey(),fetch), toNestedLoadable(sm, fmd.getElement(), e.getValue(), fetch)); } return m2; default: // just convert the stored value into its loadable equivalent. return toNestedLoadable(sm, fmd, val, fetch); } } /** * Convert the given stored value val to a value for loading * into a state manager. The value val must be a singular * value; it cannot be a container. */ private static Object toNestedLoadable(OpenJPAStateManager sm, ValueMetaData vmd, Object val, FetchConfiguration fetch) { if (val == null) return null; switch (vmd.getTypeCode()) { // clone the date to prevent direct modification of our stored value case JavaTypes.DATE: return ((Date) val).clone(); case JavaTypes.PC: case JavaTypes.PC_UNTYPED: // for relations to other persistent objects, we store the // related object's oid -- convert it back into a persistent // instance StoreContext ctx = sm.getContext(); Object pc = ctx.find(val, fetch, null, null, 0); if (pc != null) return pc; OrphanedKeyAction action = ctx.getConfiguration(). getOrphanedKeyActionInstance(); return action.orphan(val, sm, vmd); default: return val; } } /** * Store the data and version information for this object from the * given state manager. Only dirty fields will be stored. */ public void store(OpenJPAStateManager sm) { _version = (Long) sm.getVersion(); // if the version has not been set in the state manager (only true // when the object is new), set the version number to 0 if (_version == null) _version = 0L; // run through each persistent field in the state manager and store it FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (sm.getDirty().get(i) && fmds[i].getManagement() == fmds[i].MANAGE_PERSISTENT) _data[i] = toStorable(fmds[i], sm.fetch(i), sm.getContext()); } } /** * Convert the given field value val to a form we can store. */ private static Object toStorable(FieldMetaData fmd, Object val, StoreContext ctx) { if (val == null) return null; Collection c; switch (fmd.getTypeCode()) { case JavaTypes.COLLECTION: c = (Collection) val; // create a collection to copy the elements into for storage, // and populate it with converted element values Collection c2 = new ArrayList(); for (Iterator itr = c.iterator(); itr.hasNext();) c2.add(toNestedStorable(fmd.getElement(), itr.next(), ctx)); return c2; case JavaTypes.ARRAY: // create a collection to copy the elements into for storage, // and populate it with converted element values c = new ArrayList(); for (int i = 0, len = Array.getLength(val); i < len; i++) c.add(toNestedStorable(fmd.getElement(), Array.get(val, i), ctx)); return c; case JavaTypes.MAP: Map m = (Map) val; // create a map to copy the entries into for storage, and // populate it with converted entry values Map m2 = new HashMap(); for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) { Map.Entry e = (Map.Entry) itr.next(); m2.put(toNestedStorable(fmd.getKey(), e.getKey(), ctx), toNestedStorable(fmd.getElement(), e.getValue(), ctx)); } return m2; default: // just convert the loaded value into its storable equivalent return toNestedStorable(fmd, val, ctx); } } /** * Convert the given loaded value val to a value for storing. * The value val must be a singular value; it cannot be a * container. */ private static Object toNestedStorable(ValueMetaData vmd, Object val, StoreContext ctx) { if (val == null) return null; switch (vmd.getTypeCode()) { case JavaTypes.DATE: // if the date is a proxy (since Dates are second class // objects (SCOs) they can be proxied for dirty tracking, // etc) then copy the value out of it for storage if (val instanceof Proxy) return ((Proxy) val).copy(val); return ((Date) val).clone(); case JavaTypes.PC: case JavaTypes.PC_UNTYPED: return ctx.getObjectId(val); case JavaTypes.COLLECTION: case JavaTypes.ARRAY: case JavaTypes.MAP: // nested relation types (e.g. collections of collections) // are not currently supported throw new UnsupportedException("This store does not support " + "nested containers (e.g. collections of collections)."); default: return val; } } /** * Clone this data. */ public Object clone() { ObjectData data = new ObjectData(_oid, _meta); data.setVersion(_version); // copy each field FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { Object val = _data[i]; if (val == null) { data.setField(i, null); continue; } switch (fmds[i].getTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.ARRAY: data.setField(i, new ArrayList((Collection) val)); break; case JavaTypes.MAP: data.setField(i, new HashMap((Map) val)); break; default: data.setField(i, val); } } return data; } public String toString() { StringBuilder buf = new StringBuilder(); buf.append("Class: (" + _meta.getDescribedType().getName() + ")\n"); buf.append("Object Id: (" + _oid + ")\n"); buf.append("Version: (" + _version + ")\n"); FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { buf.append(" Field: (" + i + ")\n"); buf.append(" Name: (" + fmds[i].getName() + ")\n"); buf.append(" Value: (" + _data[i] + ")\n"); } return buf.toString (); } } openjpa-2.2.2.orig/openjpa/0000755000000000000000000000000012133332044012425 5ustar openjpa-2.2.2.orig/openjpa/pom.xml0000644000000000000000000002506612133327252013760 0ustar 4.0.0 org.apache.openjpa openjpa-parent 2.2.2 openjpa bundle OpenJPA Aggregate Jar org.apache.maven.plugins maven-javadoc-plugin true org.apache.maven.plugins maven-source-plugin false org.apache.maven.plugins maven-shade-plugin package shade true ${createSources} true true org.apache.openjpa:openjpa-lib org.apache.openjpa:openjpa-kernel org.apache.openjpa:openjpa-jdbc org.apache.openjpa:openjpa-persistence org.apache.openjpa:openjpa-persistence-jdbc org.apache.openjpa:openjpa-xmlstore org.apache.openjpa:openjpa-slice org.apache.openjpa:openjpa-jest org.apache.felix maven-bundle-plugin true org.apache.openjpa.conf.OpenJPAVersion org.apache.openjpa.enhance.PCEnhancerAgent org.apache.openjpa.enhance.InstrumentationFactory true true JSR-317 Java Persistence Sun Microsystems, Inc. 2.0 ${project.url} org.apache.openjpa.persistence.osgi.PersistenceActivator org.apache.openjpa.*;version=${project.version} com.ibm.*;resolution:=optional,org.postgresql.*;resolution:=optional,org.apache.tools.ant.*;resolution:=optional,org.apache.log4j.*;resolution:=optional,org.slf4j.*;resolution:=optional,org.apache.commons.logging.*;resolution:=optional,javax.activation.xa*;resolution:=optional,javax.jms.*;version="[1.1.0,1.2)";resolution:=optional,javax.transaction.*;version="[1.1.0,1.2)";resolution:=optional,javax.validation.*;version="[1.0.0,1.1)";resolution:=optional,javax.xml.bind.*;resolution:=optional,serp.*;resolution:=optional,javax.persistence.*;version="[1.1.0,2.1)",* org.apache.openjpa openjpa-lib ${project.version} org.apache.openjpa openjpa-kernel ${project.version} org.apache.openjpa openjpa-jdbc ${project.version} javax.xml.bind jaxb-api com.sun.xml.bind jaxb-impl javax.xml.bind jaxb-api compile true javax.xml.bind jsr173_api javax.activation activation com.sun.xml.bind jaxb-impl compile true javax.xml.bind jsr173_api javax.activation activation org.apache.openjpa openjpa-persistence ${project.version} org.apache.openjpa openjpa-persistence-jdbc ${project.version} org.apache.openjpa openjpa-xmlstore ${project.version} org.apache.openjpa openjpa-slice ${project.version} org.apache.openjpa openjpa-jest ${project.version} openjpa-2.2.2.orig/openjpa/src/0000755000000000000000000000000012133327252013221 5ustar openjpa-2.2.2.orig/openjpa/src/main/0000755000000000000000000000000012133327252014145 5ustar openjpa-2.2.2.orig/openjpa/src/main/appended-resources/0000755000000000000000000000000012133327252017735 5ustar openjpa-2.2.2.orig/openjpa/src/main/appended-resources/META-INF/0000755000000000000000000000000012133327252021075 5ustar openjpa-2.2.2.orig/openjpa/src/main/appended-resources/META-INF/LICENSE.vm0000644000000000000000000011217512133327252022532 0ustar ## ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. ## ====================================== LICENSES FOR INCLUDED DEPENDENCIES ====================================== All the source code for the OpenJPA project is released under the license above. Additionally, the OpenJPA binary distribution includes a number of third-party files that are required in order to the software to function. Unless noted below, these jars and resource files are also released under the ASF license above. The exceptions are as follows: =========================== openjpa-persistence - orm-xsd.rsrc - CDDL 1.0 - included in the openjpa jar, taken from: http://java.sun.com/xml/ns/persistence/orm_1_0.xsd) orm_2_0-xsd.rsrc - CDDL 1.0 - included in the openjpa jar, taken from: http://java.sun.com/xml/ns/persistence/orm_2_0.xsd) persistence-xsd.rsrc - CDDL 1.0 - included in the openjpa jar, taken from: http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd) persistence_2_0-xsd.rsrc - CDDL 1.0 - included in the openjpa jar, taken from: http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd). =========================== COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 1. Definitions. 1.1. Contributor. means each individual or entity that creates or contributes to the creation of Modifications. 1.2. Contributor Version. means the combination of the Original Software, prior Modifications used by a Contributor (if any), and the Modifications made by that particular Contributor. 1.3. Covered Software. means (a) the Original Software, or (b) Modifications, or (c) the combination of files containing Original Software with files containing Modifications, in each case including portions thereof. 1.4. Executable. means the Covered Software in any form other than Source Code. 1.5. Initial Developer. means the individual or entity that first makes Original Software available under this License. 1.6. Larger Work. means a work which combines Covered Software or portions thereof with code not governed by the terms of this License. 1.7. License. means this document. 1.8. Licensable. means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. Modifications. means the Source Code and Executable form of any of the following: A. Any file that results from an addition to, deletion from or modification of the contents of a file containing Original Software or previous Modifications; B. Any new file that contains any part of the Original Software or previous Modification; or C. Any new file that is contributed or otherwise made available under the terms of this License. 1.10. Original Software. means the Source Code and Executable form of computer software code that is originally released under this License. 1.11. Patent Claims. means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.12. Source Code. means (a) the common form of computer software code in which modifications are made and (b) associated documentation included in or with such code. 1.13. You. (or .Your.) means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, .You. includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, .control. means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants. 2.1. The Initial Developer Grant. Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer, to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions thereof), with or without Modifications, and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof). (c) The licenses granted in Sections 2.1(a) and (b) are effective on the date Initial Developer first distributes or otherwise makes the Original Software available to a third party under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: (1) for code that You delete from the Original Software, or (2) for infringements caused by: (i) the modification of the Original Software, or (ii) the combination of the Original Software with other software or devices. 2.2. Contributor Grant. Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: (1) Modifications made by that Contributor (or portions thereof); and (2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first distributes or otherwise makes the Modifications available to a third party. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: (1) for any code that Contributor has deleted from the Contributor Version; (2) for infringements caused by: (i) third party modifications of Contributor Version, or (ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or (3) under Patent Claims infringed by Covered Software in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Availability of Source Code. Any Covered Software that You distribute or otherwise make available in Executable form must also be made available in Source Code form and that Source Code form must be distributed only under the terms of this License. You must include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used for software exchange. 3.2. Modifications. The Modifications that You create or to which You contribute are governed by the terms of this License. You represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to grant the rights conveyed by this License. 3.3. Required Notices. You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification. You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer. 3.4. Application of Additional Terms. You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the applicable version of this License or the recipients. rights hereunder. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.5. Distribution of Executable Versions. You may distribute the Executable form of the Covered Software under the terms of this License or under the terms of a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable form does not attempt to limit or alter the recipient.s rights in the Source Code form from the rights set forth in this License. If You distribute the Covered Software in Executable form under a different license, You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.6. Larger Works. You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Software. 4. Versions of the License. 4.1. New Versions. Sun Microsystems, Inc. is the initial license steward and may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3, no one other than the license steward has the right to modify this License. 4.2. Effect of New Versions. You may always continue to use, distribute or otherwise make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. If the Initial Developer includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under any subsequent version of the License, You must distribute and make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. Otherwise, You may also choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version of the License published by the license steward. 4.3. Modified Versions. When You are an Initial Developer and You want to create a new license for Your Original Software, You may create and use a modified version of this License if You: (a) rename the license and remove any references to the name of the license steward (except to note that the license differs from this License); and (b) otherwise make it clear that the license contains terms which differ from this License. 5. DISCLAIMER OF WARRANTY. COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN .AS IS. BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 6. TERMINATION. 6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as .Participant.) alleging that the Participant Software (meaning the Contributor Version where the Participant is a Contributor or the Original Software where the Participant is the Initial Developer) directly or indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant, the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement with Participant. 6.3. In the event of termination under Sections 6.1 or 6.2 above, all end user licenses that have been validly granted by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor) shall survive termination. 7. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY.S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 8. U.S. GOVERNMENT END USERS. The Covered Software is a .commercial item,. as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of .commercial computer software. (as that term is defined at 48 C.F.R. ? 252.227-7014(a)(1)) and .commercial computer software documentation. as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License. 9. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any, provides otherwise), excluding such jurisdiction.s conflict-of-law provisions. Any litigation relating to this License shall be subject to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the losing party responsible for costs, including, without limitation, court costs and reasonable attorneys. fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use, distribute or otherwise make available any Covered Software. 10. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) The code released under the CDDL shall be governed by the laws of the State of California (excluding conflict-of-law provisions). Any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California and the state courts of the State of California, with venue lying in Santa Clara County, California. The GNU General Public License (GPL) Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. One line to give the program's name and a brief idea of what it does. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. "CLASSPATH" EXCEPTION TO THE GPL VERSION 2 Certain source files distributed by Sun Microsystems, Inc. are subject to the following clarification and special exception to the GPL Version 2, but only where Sun has expressly included in the particular source file's header the words "Sun designates this particular file as subject to the "Classpath" exception as provided by Sun in the License file that accompanied this code." Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License Version 2 cover the whole combination. As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module.? An independent module is a module which is not derived from or based on this library.? If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so.? If you do not wish to do so, delete this exception statement from your version. openjpa-2.2.2.orig/openjpa/src/main/appended-resources/META-INF/NOTICE.vm0000644000000000000000000000265412133327252022431 0ustar ## ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. ## OpenJPA includes software developed by the SERP project Copyright (c) 2002-2006, A. Abram White. All rights reserved. OpenJPA includes the persistence and orm schemas from the JPA specifications. Copyright 2005-2007 Sun Microsystems, Inc. All rights reserved. OpenJPA elects to include this software in this distribution under the CDDL license. You can obtain a copy of the License at: https://glassfish.dev.java.net/public/CDDL+GPL.html The source code is available at: https://glassfish.dev.java.net/source/browse/glassfish/ OpenJPA includes software written by Miroslav Nachev OpenJPA uses test code written by Charles Tillman. openjpa-2.2.2.orig/openjpa/src/main/resources/0000755000000000000000000000000012133327252016157 5ustar openjpa-2.2.2.orig/openjpa/src/main/resources/META-INF/0000755000000000000000000000000012133327252017317 5ustar openjpa-2.2.2.orig/openjpa/src/main/resources/META-INF/services/0000755000000000000000000000000012133327252021142 5ustar ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa/src/main/resources/META-INF/services/javax.annotation.processing.Processoropenjpa-2.2.2.orig/openjpa/src/main/resources/META-INF/services/javax.annotation.processing.Processo0000644000000000000000000000007112133327252030314 0ustar org.apache.openjpa.persistence.meta.AnnotationProcessor6 openjpa-2.2.2.orig/openjpa/dependency-reduced-pom.xml0000644000000000000000000001763512133332044017503 0ustar openjpa-parent org.apache.openjpa 2.2.2 4.0.0 openjpa bundle OpenJPA Aggregate Jar maven-javadoc-plugin true maven-source-plugin false maven-shade-plugin package shade true ${createSources} true true org.apache.openjpa:openjpa-lib org.apache.openjpa:openjpa-kernel org.apache.openjpa:openjpa-jdbc org.apache.openjpa:openjpa-persistence org.apache.openjpa:openjpa-persistence-jdbc org.apache.openjpa:openjpa-xmlstore org.apache.openjpa:openjpa-slice org.apache.openjpa:openjpa-jest org.apache.felix maven-bundle-plugin true org.apache.openjpa.conf.OpenJPAVersion org.apache.openjpa.enhance.PCEnhancerAgent org.apache.openjpa.enhance.InstrumentationFactory true true JSR-317 Java Persistence Sun Microsystems, Inc. 2.0 ${project.url} org.apache.openjpa.persistence.osgi.PersistenceActivator org.apache.openjpa.*;version=${project.version} com.ibm.*;resolution:=optional,org.postgresql.*;resolution:=optional,org.apache.tools.ant.*;resolution:=optional,org.apache.log4j.*;resolution:=optional,org.slf4j.*;resolution:=optional,org.apache.commons.logging.*;resolution:=optional,javax.activation.xa*;resolution:=optional,javax.jms.*;version="[1.1.0,1.2)";resolution:=optional,javax.transaction.*;version="[1.1.0,1.2)";resolution:=optional,javax.validation.*;version="[1.0.0,1.1)";resolution:=optional,javax.xml.bind.*;resolution:=optional,serp.*;resolution:=optional,javax.persistence.*;version="[1.1.0,2.1)",* org.apache.openjpa openjpa-lib 2.2.2 provided commons-lang commons-lang 2.4 compile commons-collections commons-collections 3.2.1 compile net.sourceforge.serp serp 1.14.1 compile org.apache.openjpa openjpa-kernel 2.2.2 provided org.apache.geronimo.specs geronimo-jms_1.1_spec 1.1.1 compile org.apache.geronimo.specs geronimo-jta_1.1_spec 1.1.1 compile commons-pool commons-pool 1.5.4 compile asm asm 3.2 compile org.apache.openjpa openjpa-jdbc 2.2.2 provided javax.xml.bind jaxb-api 2.2.1 compile activation javax.activation true javax.xml.stream stax-api 1.0-2 compile com.sun.xml.bind jaxb-impl 2.2.1 compile true org.apache.openjpa openjpa-persistence 2.2.2 provided org.apache.geronimo.specs geronimo-jpa_2.0_spec 1.1 compile org.apache.openjpa openjpa-persistence-jdbc 2.2.2 provided org.apache.openjpa openjpa-xmlstore 2.2.2 provided org.apache.openjpa openjpa-slice 2.2.2 provided org.apache.openjpa openjpa-jest 2.2.2 provided openjpa-2.2.2.orig/openjpa-kernel/0000755000000000000000000000000012133327574013717 5ustar openjpa-2.2.2.orig/openjpa-kernel/pom.xml0000644000000000000000000001563712133327274015245 0ustar 4.0.0 org.apache.openjpa openjpa-parent 2.2.2 org.apache.openjpa openjpa-kernel jar OpenJPA Kernel OpenJPA Kernel org.apache.openjpa openjpa-lib ${project.version} org.apache.geronimo.specs geronimo-jms_1.1_spec org.apache.geronimo.specs geronimo-jta_1.1_spec commons-pool commons-pool com.ibm.websphere websphere_uow_api 0.0.1 provided org.apache.ant ant provided org.osgi org.osgi.core 4.2.0 provided asm asm 3.2 org.codehaus.mojo javacc-maven-plugin 2.4 jjtree-javacc-jpql generate-sources false 1.6 jjtree-javacc org.apache.maven.plugins maven-antrun-plugin add-was-interfaces process-classes run generate-standard-sco-proxies process-classes run org.apache.maven.plugins maven-jar-plugin default-jar jar true ${buildNumber} org.apache.openjpa.enhance.InstrumentationFactory attach-tests test-jar openjpa-internal Internal repository file://${basedir}/internal-repository openjpa-2.2.2.orig/openjpa-kernel/src/0000755000000000000000000000000012133327270014477 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/0000755000000000000000000000000012133327270015456 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/0000755000000000000000000000000012133327270016377 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/0000755000000000000000000000000012133327270017166 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/0000755000000000000000000000000012133327270020407 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/0000755000000000000000000000000012133327270022043 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/util/0000755000000000000000000000000012133327270023020 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/util/TestProxyManager.java0000644000000000000000000010223212133327270027137 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.InputStream; import java.sql.Time; import java.sql.Timestamp; import java.util.AbstractMap; import java.util.AbstractSequentialList; import java.util.AbstractSet; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TimeZone; import java.util.TreeSet; import java.util.TreeMap; import java.util.Vector; import org.apache.openjpa.util.Proxy; import junit.framework.TestCase; import junit.textui.TestRunner; /** * Test proxies generated by the proxy manager. * * @author Abe White */ public class TestProxyManager extends TestCase { private ProxyManagerImpl _mgr; public void setUp() { _mgr = new ProxyManagerImpl(); } public void testCopyLists() { List orig = new ArrayList(); populate(orig); assertListsEqual(orig, (List) _mgr.copyCollection(orig)); orig = new LinkedList(); populate(orig); assertListsEqual(orig, (List) _mgr.copyCollection(orig)); orig = new CustomList(); populate(orig); assertListsEqual(orig, (List) _mgr.copyCollection(orig)); } /** * Populate the given list with arbitrary data. */ private static void populate(Collection coll) { coll.add(new Integer(1)); coll.add("foo"); coll.add(new Long(99)); coll.add("bar"); coll.add(new Short((short) 50)); } /** * Assert that the given lists are exactly the same. */ private static void assertListsEqual(List l1, List l2) { assertTrue(l1.getClass() == l2.getClass()); assertEquals(l1.size(), l2.size()); for (int i = 0; i < l1.size(); i++) assertTrue(l1.get(i) + " != " + l2.get(i), l1.get(i) == l2.get(i)); } public void testCopySets() { Set orig = new HashSet(); populate(orig); assertSetsEqual(orig, (Set) _mgr.copyCollection(orig)); orig = new CustomSet(); populate(orig); assertSetsEqual(orig, (Set) _mgr.copyCollection(orig)); } /** * Assert that the given sets are exactly the same. */ private static void assertSetsEqual(Set s1, Set s2) { assertTrue(s1.getClass() == s2.getClass()); assertEquals(s1.size(), s2.size()); assertEquals(s1, s2); } public void testCopySortedSets() { SortedSet orig = new TreeSet(); populate(orig); assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig)); orig = new TreeSet(new CustomComparator()); populate(orig); assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig)); orig = new CustomSortedSet(); populate(orig); assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig)); orig = new CustomComparatorSortedSet(new CustomComparator()); populate(orig); assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig)); } /** * Populate the given sorted set with arbitrary data. */ private static void populate(SortedSet coll) { coll.add(new Integer(1)); coll.add(new Integer(99)); coll.add(new Integer(50)); coll.add(new Integer(-5)); coll.add(new Integer(10)); } /** * Assert that the given sets are exactly the same. */ private static void assertSortedSetsEqual(SortedSet s1, SortedSet s2) { assertTrue(s1.getClass() == s2.getClass()); assertSortedSetsEquals(s1, s2); } /** * Assert that the given sets are exactly the same (minus the class). */ private static void assertSortedSetsEquals(SortedSet s1, SortedSet s2) { assertEquals(s1.comparator(), s2.comparator()); assertEquals(s1.size(), s2.size()); Iterator itr1 = s1.iterator(); Iterator itr2 = s2.iterator(); while (itr1.hasNext()) assertTrue(itr1.next() == itr2.next()); assertTrue(s1.equals(s2)); } public void testCopyNullCollection() { assertNull(_mgr.copyCollection(null)); } public void testCopyProxyCollection() { List orig = (List) _mgr.newCollectionProxy(ArrayList.class, null, null,true); populate(orig); assertListsEqual(new ArrayList(orig), (List) _mgr.copyCollection(orig)); TreeSet torig = (TreeSet) _mgr.newCollectionProxy(TreeSet.class, null, new CustomComparator(),true); assertTrue(torig.comparator() instanceof CustomComparator); populate(torig); assertSortedSetsEqual(new TreeSet(torig), (SortedSet) _mgr.copyCollection(torig)); } public void testCloneProxyCollection() { // List doesn't support clone() TreeSet torig = (TreeSet) _mgr.newCollectionProxy(TreeSet.class, null, new CustomComparator(),true); assertTrue(torig.comparator() instanceof CustomComparator); populate(torig); assertSortedSetsEquals(new TreeSet(torig), (SortedSet) torig.clone()); } public void testListMethodsProxied() throws Exception { Class proxy = _mgr.newCollectionProxy(ArrayList.class, null, null,true). getClass(); assertListMethodsProxied(proxy); proxy = _mgr.newCollectionProxy(CustomList.class, null, null,true). getClass(); assertListMethodsProxied(proxy); } /** * Assert that the methods we need to override to dirty the collection are * proxied appropriately. */ private void assertCollectionMethodsProxied(Class cls) throws Exception { assertNotNull(cls.getDeclaredMethod("add", new Class[] {Object.class})); assertNotNull(cls.getDeclaredMethod("addAll", new Class[] {Collection.class})); assertNotNull(cls.getDeclaredMethod("clear", (Class[]) null)); assertNotNull(cls.getDeclaredMethod("iterator", (Class[]) null)); assertNotNull(cls.getDeclaredMethod("remove", new Class[] {Object.class})); assertNotNull(cls.getDeclaredMethod("removeAll", new Class[] {Collection.class})); assertNotNull(cls.getDeclaredMethod("retainAll", new Class[] {Collection.class})); // check a non-mutating method to make sure we're not just proxying // everything try { cls.getDeclaredMethod("contains", new Class[] {Object.class}); fail("Proxied non-mutating method."); } catch (NoSuchMethodException nsme) { // expected } } /** * Assert that the methods we need to override to dirty the list are * proxied appropriately. */ private void assertListMethodsProxied(Class cls) throws Exception { assertCollectionMethodsProxied(cls); assertNotNull(cls.getDeclaredMethod("add", new Class[] {int.class, Object.class})); assertNotNull(cls.getDeclaredMethod("addAll", new Class[] {int.class, Collection.class})); assertNotNull(cls.getDeclaredMethod("listIterator", (Class[]) null)); assertNotNull(cls.getDeclaredMethod("listIterator", new Class[] {int.class})); assertNotNull(cls.getDeclaredMethod("remove", new Class[] {int.class})); assertNotNull(cls.getDeclaredMethod("set", new Class[] {int.class, Object.class})); } public void testSetMethodsProxied() throws Exception { Class proxy = _mgr.newCollectionProxy(HashSet.class, null, null,true). getClass(); assertCollectionMethodsProxied(proxy); proxy = _mgr.newCollectionProxy(CustomSet.class, null, null,true).getClass(); assertCollectionMethodsProxied(proxy); proxy = _mgr.newCollectionProxy(CustomSortedSet.class, null, null,true). getClass(); assertCollectionMethodsProxied(proxy); proxy = _mgr.newCollectionProxy(CustomComparatorSortedSet.class, null, new CustomComparator(),true).getClass(); assertCollectionMethodsProxied(proxy); } public void testQueueMethodsProxied() throws Exception { Class queue = getQueueClass(); if (queue == null) return; Class proxy = _mgr.newCollectionProxy(LinkedList.class, null, null,true). getClass(); assertTrue(queue.isAssignableFrom(proxy)); assertCollectionMethodsProxied(proxy); assertNotNull(proxy.getDeclaredMethod("offer", new Class[] {Object.class})); assertNotNull(proxy.getDeclaredMethod("poll", (Class[]) null)); assertNotNull(proxy.getDeclaredMethod("remove", (Class[]) null)); try { proxy.getDeclaredMethod("peek", (Class[]) null); fail("Proxied non-mutating method."); } catch (NoSuchMethodException nsme) { // expected } } public void testLinkedListMethodsProxied() throws Exception { Class proxy = _mgr.newCollectionProxy(LinkedList.class, null, null,true). getClass(); assertListMethodsProxied(proxy); assertNotNull(proxy.getDeclaredMethod("addFirst", new Class[] {Object.class})); assertNotNull(proxy.getDeclaredMethod("addLast", new Class[] {Object.class})); assertNotNull(proxy.getDeclaredMethod("removeFirst", (Class[]) null)); assertNotNull(proxy.getDeclaredMethod("removeLast", (Class[]) null)); } public void testVectorMethodsProxied() throws Exception { Class proxy = _mgr.newCollectionProxy(Vector.class, null, null,true). getClass(); assertListMethodsProxied(proxy); assertNotNull(proxy.getDeclaredMethod("addElement", new Class[] {Object.class})); assertNotNull(proxy.getDeclaredMethod("insertElementAt", new Class[] {Object.class, int.class})); assertNotNull(proxy.getDeclaredMethod("removeAllElements", (Class[]) null)); assertNotNull(proxy.getDeclaredMethod("removeElement", new Class[] {Object.class})); assertNotNull(proxy.getDeclaredMethod("removeElementAt", new Class[] {int.class})); assertNotNull(proxy.getDeclaredMethod("setElementAt", new Class[] {Object.class, int.class})); } public void testListChangeTracker() { Proxy coll = _mgr.newCollectionProxy(ArrayList.class, null, null,true); assertNotNull(coll); assertNotNull(coll.getChangeTracker()); assertTrue(coll.getChangeTracker() instanceof CollectionChangeTrackerImpl); CollectionChangeTrackerImpl ct = (CollectionChangeTrackerImpl) coll.getChangeTracker(); assertTrue(ct.allowsDuplicates()); assertTrue(ct.isOrdered()); } public void testSetChangeTracker() { Proxy coll = _mgr.newCollectionProxy(HashSet.class, null, null,true); assertNotNull(coll); assertNotNull(coll.getChangeTracker()); assertTrue(coll.getChangeTracker() instanceof CollectionChangeTrackerImpl); CollectionChangeTrackerImpl ct = (CollectionChangeTrackerImpl) coll.getChangeTracker(); assertFalse(ct.allowsDuplicates()); assertFalse(ct.isOrdered()); } public void testCollectionInterfaceProxy() { Proxy coll = _mgr.newCollectionProxy(Collection.class, null, null,true); assertNotNull(coll); } public void testListInterfaceProxy() { Proxy coll = _mgr.newCollectionProxy(List.class, null, null,true); assertNotNull(coll); assertTrue(coll instanceof List); } public void testSetInterfaceProxy() { Proxy coll = _mgr.newCollectionProxy(Set.class, null, null,true); assertNotNull(coll); assertTrue(coll instanceof Set); assertFalse(coll instanceof SortedSet); } public void testSortedSetInterfaceProxy() { Proxy coll = _mgr.newCollectionProxy(SortedSet.class, null, null,true); assertNotNull(coll); assertTrue(coll instanceof SortedSet); } public void testQueueInterfaceProxy() { Class queue = getQueueClass(); if (queue == null) return; Proxy coll = _mgr.newCollectionProxy(queue, null, null,true); assertNotNull(coll); assertTrue(queue.isInstance(coll)); } /** * Return the {@link java.util.Queue} class if avaialble. */ private static Class getQueueClass() { try { return Class.forName("java.util.Queue"); } catch (Throwable t) { return null; } } public void testCopyMaps() { Map orig = new HashMap(); populate(orig); assertMapsEqual(orig, (Map) _mgr.copyMap(orig)); orig = new CustomMap(); populate(orig); assertMapsEqual(orig, (Map) _mgr.copyMap(orig)); Properties porig = new Properties(); porig.setProperty("foo", "bar"); porig.setProperty("bar", "biz"); porig.setProperty("biz", "baz"); assertMapsEqual(orig, (Map) _mgr.copyMap(orig)); } /** * Populate the given map with arbitrary data. */ private static void populate(Map map) { map.put(new Integer(1), "1"); map.put(new Integer(99), "99"); map.put(new Integer(-2), "-2"); map.put(new Integer(50), "50"); } /** * Assert that the given maps are exactly the same. */ private static void assertMapsEqual(Map m1, Map m2) { assertTrue(m1.getClass() == m2.getClass()); assertEquals(m1.size(), m2.size()); assertEquals(m1, m2); } public void testCopySortedMaps() { SortedMap orig = new TreeMap(); populate(orig); assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig)); orig = new TreeMap(new CustomComparator()); populate(orig); assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig)); orig = new CustomSortedMap(); populate(orig); assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig)); orig = new CustomComparatorSortedMap(new CustomComparator()); populate(orig); assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig)); } /** * Assert that the given maps are exactly the same. */ private static void assertSortedMapsEqual(SortedMap m1, SortedMap m2) { assertTrue(m1.getClass() == m2.getClass()); assertSortedMapsEquals(m1, m2); } /** * Assert that the given maps are exactly the same (minus the class). */ private static void assertSortedMapsEquals(SortedMap m1, SortedMap m2) { assertEquals(m1.comparator(), m2.comparator()); assertEquals(m1.size(), m2.size()); Map.Entry entry1; Map.Entry entry2; Iterator itr1 = m1.entrySet().iterator(); Iterator itr2 = m2.entrySet().iterator(); while (itr1.hasNext()) { entry1 = (Map.Entry) itr1.next(); entry2 = (Map.Entry) itr2.next(); assertTrue(entry1.getKey() == entry2.getKey()); assertTrue(entry1.getValue() == entry2.getValue()); } assertTrue(m1.equals(m2)); } public void testCopyNullMap() { assertNull(_mgr.copyMap(null)); } public void testCopyProxyMap() { Map orig = (Map) _mgr.newMapProxy(HashMap.class, null, null, null,true); populate(orig); assertMapsEqual(new HashMap(orig), (Map) _mgr.copyMap(orig)); TreeMap torig = (TreeMap) _mgr.newMapProxy(TreeMap.class, null, null, new CustomComparator(),true); assertTrue(torig.comparator() instanceof CustomComparator); populate(torig); assertSortedMapsEqual(new TreeMap(torig), (SortedMap) _mgr.copyMap(torig)); } public void testCloneProxyMap() { // Map does not support clone() TreeMap torig = (TreeMap) _mgr.newMapProxy(TreeMap.class, null, null, new CustomComparator(),true); assertTrue(torig.comparator() instanceof CustomComparator); populate(torig); assertSortedMapsEquals(new TreeMap(torig), (SortedMap) torig.clone()); } public void testMapMethodsProxied() throws Exception { Class proxy = _mgr.newMapProxy(HashMap.class, null, null, null,true). getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(TreeMap.class, null, null, null,true).getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(TreeMap.class, null, null, new CustomComparator(),true).getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(CustomMap.class, null, null, null,true).getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(CustomSortedMap.class, null, null, null,true). getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(CustomComparatorSortedMap.class, null, null, new CustomComparator(),true).getClass(); assertMapMethodsProxied(proxy); } /** * Assert that the methods we need to override to dirty the collection are * proxied appropriately. */ private void assertMapMethodsProxied(Class cls) throws Exception { assertNotNull(cls.getDeclaredMethod("put", new Class[] {Object.class, Object.class})); assertNotNull(cls.getDeclaredMethod("putAll", new Class[] {Map.class})); assertNotNull(cls.getDeclaredMethod("clear", (Class[]) null)); assertNotNull(cls.getDeclaredMethod("remove", new Class[] {Object.class})); assertNotNull(cls.getDeclaredMethod("keySet", (Class[]) null)); assertNotNull(cls.getDeclaredMethod("values", (Class[]) null)); assertNotNull(cls.getDeclaredMethod("entrySet", (Class[]) null)); // check a non-mutating method to make sure we're not just proxying // everything try { cls.getDeclaredMethod("containsKey", new Class[] {Object.class}); fail("Proxied non-mutating method."); } catch (NoSuchMethodException nsme) { // expected } } public void testPropertiesMethodsProxied() throws Exception { Class proxy = _mgr.newMapProxy(Properties.class, null, null, null,true). getClass(); assertMapMethodsProxied(proxy); assertNotNull(proxy.getDeclaredMethod("setProperty", new Class[] {String.class, String.class})); assertNotNull(proxy.getDeclaredMethod("load", new Class[] {InputStream.class})); assertNotNull(proxy.getDeclaredMethod("loadFromXML", new Class[] {InputStream.class})); } public void testCopyDates() { Date orig = new Date(1999); assertDatesEqual(orig, (Date) _mgr.copyDate(orig)); orig = new java.sql.Date(1999); assertDatesEqual(orig, (Date) _mgr.copyDate(orig)); orig = new Time(1999); assertDatesEqual(orig, (Date) _mgr.copyDate(orig)); Timestamp torig = new Timestamp(1999); torig.setNanos(2001); assertDatesEqual(torig, (Date) _mgr.copyDate(torig)); torig = new CustomDate(1999); torig.setNanos(2001); assertDatesEqual(torig, (Date) _mgr.copyDate(torig)); } /** * Assert that the given dates are exactly the same. */ private static void assertDatesEqual(Date d1, Date d2) { assertTrue(d1.getClass() == d2.getClass()); assertDatesEquals(d1, d2); } /** * Assert that the given dates are exactly the same (minus the class). */ private static void assertDatesEquals(Date d1, Date d2) { assertTrue(d1.equals(d2)); } public void testCopyNullDate() { assertNull(_mgr.copyDate(null)); } public void testCopyProxyDate() { Date orig = (Date) _mgr.newDateProxy(Time.class); orig.setTime(1999); assertDatesEqual(new Time(orig.getTime()), (Date) _mgr.copyDate(orig)); } public void testCloneProxyDate() { Date orig = (Date) _mgr.newDateProxy(Time.class); orig.setTime(1999); assertDatesEquals(new Time(orig.getTime()), (Date) orig.clone()); } public void testDateMethodsProxied() throws Exception { Class proxy = _mgr.newDateProxy(Date.class).getClass(); assertDateMethodsProxied(proxy); proxy = _mgr.newDateProxy(java.sql.Date.class).getClass(); assertDateMethodsProxied(proxy); proxy = _mgr.newDateProxy(Time.class).getClass(); assertDateMethodsProxied(proxy); proxy = _mgr.newDateProxy(Timestamp.class).getClass(); assertTimestampMethodsProxied(proxy); proxy = _mgr.newDateProxy(CustomDate.class).getClass(); assertTimestampMethodsProxied(proxy); } /** * Assert that the methods we need to override to dirty the date are * proxied appropriately. */ private void assertDateMethodsProxied(Class cls) throws Exception { assertNotNull(cls.getDeclaredMethod("setDate", new Class[] {int.class})); assertNotNull(cls.getDeclaredMethod("setHours", new Class[] {int.class})); assertNotNull(cls.getDeclaredMethod("setMinutes", new Class[] {int.class})); assertNotNull(cls.getDeclaredMethod("setMonth", new Class[] {int.class})); assertNotNull(cls.getDeclaredMethod("setSeconds", new Class[] {int.class})); assertNotNull(cls.getDeclaredMethod("setTime", new Class[] {long.class})); assertNotNull(cls.getDeclaredMethod("setYear", new Class[] {int.class})); // check a non-mutating method to make sure we're not just proxying // everything try { cls.getDeclaredMethod("getTime", (Class[]) null); fail("Proxied non-mutating method."); } catch (NoSuchMethodException nsme) { // expected } } /** * Assert that the methods we need to override to dirty the timestamp are * proxied appropriately. */ private void assertTimestampMethodsProxied(Class cls) throws Exception { assertDateMethodsProxied(cls); assertNotNull(cls.getDeclaredMethod("setNanos", new Class[] {int.class})); } public void testCopyCalendars() { Calendar orig = new GregorianCalendar(); populate(orig); assertCalendarsEqual(orig, _mgr.copyCalendar(orig)); orig = new CustomCalendar(); populate(orig); assertCalendarsEqual(orig, _mgr.copyCalendar(orig)); } /** * Populate calendar with arbitrary data. */ private static void populate(Calendar cal) { cal.setTimeInMillis(1999); cal.setTimeZone(TimeZone.getTimeZone("CST")); } /** * Assert that the given dates are exactly the same. */ private static void assertCalendarsEqual(Calendar c1, Calendar c2) { assertTrue(c1.getClass() == c2.getClass()); assertCalendarsEquals(c1, c2); } /** * Assert that the given dates are exactly the same (minus the class). */ private static void assertCalendarsEquals(Calendar c1, Calendar c2) { assertTrue(c1.equals(c2)); } public void testCopyNullCalendar() { assertNull(_mgr.copyCalendar(null)); } public void testCopyProxyCalendar() { Calendar orig = (Calendar) _mgr.newCalendarProxy (GregorianCalendar.class, TimeZone.getTimeZone("CST")); populate(orig); Calendar cal = new GregorianCalendar(); populate(cal); assertCalendarsEqual(cal, _mgr.copyCalendar(orig)); } public void testCloneProxyCalendar() { Calendar orig = (Calendar) _mgr.newCalendarProxy (GregorianCalendar.class, TimeZone.getTimeZone("CST")); populate(orig); Calendar cal = new GregorianCalendar(); populate(cal); assertCalendarsEquals(cal, (Calendar)orig.clone()); } public void testCalendarAbstractClassProxy() { Proxy cal = _mgr.newCalendarProxy(Calendar.class, null); assertNotNull(cal); } public void testCalendarMethodsProxied() throws Exception { Class proxy = _mgr.newCalendarProxy(GregorianCalendar.class, TimeZone.getDefault()).getClass(); assertCalendarMethodsProxied(proxy); proxy = _mgr.newCalendarProxy(CustomCalendar.class, TimeZone.getDefault()).getClass(); assertCalendarMethodsProxied(proxy); proxy = _mgr.newCalendarProxy(Calendar.class, TimeZone.getDefault()).getClass(); assertCalendarMethodsProxied(proxy); } /** * Assert that the methods we need to override to dirty the calendar are * proxied appropriately. */ private void assertCalendarMethodsProxied(Class cls) throws Exception { assertNotNull(cls.getDeclaredMethod("set", new Class[] {int.class, int.class})); assertNotNull(cls.getDeclaredMethod("roll", new Class[] {int.class, int.class})); assertNotNull(cls.getDeclaredMethod("setTimeInMillis", new Class[] {long.class})); assertNotNull(cls.getDeclaredMethod("setTimeZone", new Class[] {TimeZone.class})); assertNotNull(cls.getDeclaredMethod("computeFields", (Class[]) null)); // check a non-mutating method to make sure we're not just proxying // everything try { cls.getDeclaredMethod("getTimeInMillis", (Class[]) null); fail("Proxied non-mutating method."); } catch (NoSuchMethodException nsme) { // expected } } public void testCopyBeans() { CustomBean orig = new CustomBean(); populate(orig); assertBeansEqual(orig, (CustomBean) _mgr.copyCustom(orig)); orig = new CustomCopyConstructorBean(orig); assertBeansEqual(orig, (CustomBean) _mgr.copyCustom(orig)); } /** * Populate the given bean with arbitrary data. */ private void populate(CustomBean bean) { bean.setString("foo"); bean.setNumber(99); } public void testNonproxyableBean() { NonproxyableBean orig = new NonproxyableBean(1); populate(orig); assertNull(_mgr.copyCustom(orig)); assertNull(_mgr.newCustomProxy(orig,true)); } /** * Assert that the given beans are exactly the same. */ private static void assertBeansEqual(CustomBean b1, CustomBean b2) { assertTrue(b1.getClass() == b2.getClass()); assertTrue(b1.getString() == b2.getString()); assertTrue(b1.getNumber() == b2.getNumber()); } public void testCopyNullBean() { assertNull(_mgr.copyCustom(null)); } public void testCopyProxyBean() { CustomBean orig = (CustomBean) _mgr.newCustomProxy(new CustomBean(),true); populate(orig); CustomBean comp = new CustomBean(); populate(comp); assertBeansEqual(comp, (CustomBean) _mgr.copyCustom(orig)); } public void testBeanMethodsProxied() throws Exception { Class proxy = _mgr.newCustomProxy(new CustomBean(),true).getClass(); assertBeanMethodsProxied(proxy); proxy = _mgr.newCustomProxy(new CustomCopyConstructorBean (new CustomBean()),true).getClass(); assertBeanMethodsProxied(proxy); } /** * Assert that the methods we need to override to dirty the bean are * proxied appropriately. */ private void assertBeanMethodsProxied(Class cls) throws Exception { assertNotNull(cls.getDeclaredMethod("setString", new Class[] {String.class})); assertNotNull(cls.getDeclaredMethod("setNumber", new Class[] {int.class})); // check a non-mutating method to make sure we're not just proxying // everything try { cls.getDeclaredMethod("getString", (Class[]) null); fail("Proxied non-mutating method."); } catch (NoSuchMethodException nsme) { // expected } } public static void main(String[] args) { TestRunner.run(TestProxyManager.class); } /** * Used to test custom list handling. Copy constructor intentionally * ommitted. */ public static class CustomList extends AbstractSequentialList { private final List _delegate = new ArrayList(); public int size() { return _delegate.size(); } public ListIterator listIterator(int idx) { return _delegate.listIterator(idx); } } /** * Used to test custom set handling. Copy constructor intentionally * ommitted. */ public static class CustomSet extends AbstractSet { private final Set _delegate = new HashSet(); public int size() { return _delegate.size(); } public Iterator iterator() { return _delegate.iterator(); } public boolean add(Object o) { return _delegate.add(o); } } /** * Used to test custom set handling. Copy constructor intentionally * ommitted. */ public static class CustomSortedSet extends TreeSet { } /** * Used to test custom set handling. Copy constructor intentionally * ommitted. */ public static class CustomComparatorSortedSet extends TreeSet { public CustomComparatorSortedSet() { } public CustomComparatorSortedSet(Comparator comp) { super(comp); } } /** * Used to test custom map handling. Copy constructor intentionally * ommitted. */ public static class CustomMap extends AbstractMap { private final Map _delegate = new HashMap(); public Object put(Object key, Object value) { return _delegate.put(key, value); } public Set entrySet() { return _delegate.entrySet(); } } /** * Used to test custom map handling. Copy constructor intentionally * ommitted. */ public static class CustomSortedMap extends TreeMap { } /** * Used to test custom map handling. Copy constructor intentionally * ommitted. */ public static class CustomComparatorSortedMap extends TreeMap { public CustomComparatorSortedMap() { } public CustomComparatorSortedMap(Comparator comp) { super(comp); } } /** * Used to test transfer of comparators to proxies. */ private static class CustomComparator implements Comparator { public int compare(Object o1, Object o2) { return ((Comparable) o1).compareTo(o2); } } /** * Used to test custom date handling. */ public static class CustomDate extends Timestamp { public CustomDate(long time) { super(time); } } /** * Used to test custom bean handling. */ public static class CustomBean { private String _string; private int _number; public String getString() { return _string; } public void setString(String str) { _string = str; } public int getNumber() { return _number; } public void setNumber(int number) { _number = number; } } /** * Used to test custom bean handling. */ public static class CustomCopyConstructorBean extends CustomBean { public CustomCopyConstructorBean(CustomBean bean) { setString(bean.getString()); setNumber(bean.getNumber()); } } /** * Used to non-proxyable custom bean handling. */ public static class NonproxyableBean extends CustomBean { public NonproxyableBean(long x) { // single non-default, non-copy constructor } } /** * Used to test custom calendar handling. */ public static class CustomCalendar extends GregorianCalendar { } } openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/util/TestResultShape.java0000644000000000000000000002457612133327270027000 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import org.apache.openjpa.kernel.FillStrategy; import org.apache.openjpa.kernel.ResultShape; import junit.framework.TestCase; public class TestResultShape extends TestCase { public void testPrimitiveShapeIsImmutable() { ResultShape shape = new ResultShape(Object.class, true); assertCategory(shape, true, false, false); assertEquals(FillStrategy.Assign.class, shape.getStrategy().getClass()); try { shape.add(int.class); fail(shape + " should not allow adding other shapes"); } catch (UnsupportedOperationException e) { } try { shape.nest(Object[].class, new FillStrategy.Array(Object[].class), int.class, double.class); fail(shape + " should not allow nesting other shapes"); } catch (UnsupportedOperationException e) { } } public void testArrayIsMutable() { ResultShape shape = new ResultShape(Object[].class); assertCategory(shape, false, true, false); assertEquals(FillStrategy.Array.class, shape.getStrategy().getClass()); shape.add(int.class, double.class); // will add primitive shapes assertCategory(shape, false, true, false); ResultShape primitiveShape = new ResultShape(Object.class, true); shape.nest(primitiveShape); assertCategory(shape, false, true, false); ResultShape nonPrimitiveShape = new ResultShape(Object[].class); nonPrimitiveShape.add(int.class, double.class); assertCategory(nonPrimitiveShape, false, true, false); shape.nest(nonPrimitiveShape); assertCategory(shape, false, true, true); } public void testMethodImpliesMapStrategy() { FillStrategy strategy = new FillStrategy.Map(method(Map.class, "put", Object.class, Object.class)); ResultShape mapShape = new ResultShape(Map.class, strategy, true); assertCategory(mapShape, true, false, false); assertEquals(FillStrategy.Map.class, mapShape.getStrategy().getClass()); } public void testShapeWithConstrcutorStrategy() { FillStrategy strategy = new FillStrategy.NewInstance(constructor(ArrayList.class, int.class)); ResultShape listShape = new ResultShape(List.class, strategy); assertCategory(listShape, false, true, false); assertEquals(FillStrategy.NewInstance.class, listShape.getStrategy().getClass()); } public void testGetCompositeTypes() { ResultShape root = new ResultShape(Object[].class); FillStrategy strategy1 = new FillStrategy.NewInstance(Bar.class); ResultShape bar1 = new ResultShape(Bar.class, strategy1, false); bar1.add(int.class); FillStrategy strategy2 = new FillStrategy.NewInstance(constructor(Foo.class, short.class, Bar.class)); ResultShape fooBarConstructor = new ResultShape(Foo.class, strategy2); fooBarConstructor.add(short.class); fooBarConstructor.nest(bar1); root.add(Foo.class, Object.class); root.nest(fooBarConstructor); ResultShape bar2 = new ResultShape(Bar.class, new FillStrategy.NewInstance(Bar.class), false); root.nest(bar2); assertEquals("Object[]{Foo, Object, Foo{short, Bar{int}}, Bar}", root.toString()); assertEquals(Arrays.asList(Foo.class, Object.class, short.class, int.class, Bar.class), root.getCompositeTypes()); assertEquals(Arrays.asList(Foo.class, Object.class, Foo.class, Bar.class), root.getTypes()); assertEquals(5, root.argLength()); assertEquals(4, root.length()); } public void testRecursiveNestingIsNotAllowed() { ResultShape root = new ResultShape(Object[].class); ResultShape bar1 = new ResultShape(Bar.class, new FillStrategy.NewInstance(Bar.class), false); bar1.add(int.class); ResultShape fooBarConstructor = new ResultShape(Foo.class, new FillStrategy.NewInstance(constructor(Foo.class, short.class, Bar.class))); fooBarConstructor.add(short.class); fooBarConstructor.nest(bar1); root.add(Foo.class, Object.class); root.nest(fooBarConstructor); ResultShape bar2 = new ResultShape(Bar.class, new FillStrategy.NewInstance(Bar.class), false); root.nest(bar2); try { bar1.nest(fooBarConstructor); fail("Expecetd recursive nesting error in nest " + fooBarConstructor + " in " + bar1); } catch (IllegalArgumentException e) { } } public void testFill() { //Fill this shape: Foo{short, Bar{String, Double}}; ResultShape foo = new ResultShape(Foo.class, new FillStrategy.NewInstance(Foo.class), false); ResultShape bar = new ResultShape(Bar.class, new FillStrategy.NewInstance(Bar.class), false); bar.add(String.class, Double.class); foo.add(short.class); foo.nest(bar); assertEquals("Foo{short, Bar{String, Double}}", foo.toString()); //from this array: 200s, "bar1", 12.3d) Object[] values = {(short)200, "bar1", 12.3d}; Class[] types = {short.class, String.class, Double.class}; String[] aliases = {"foo-short", "foo-bar-string", "foo-bar-Double"}; Foo result = foo.pack(values, types, aliases); assertEquals(200, result.shrt); assertEquals("bar1", result.b.string); assertEquals(12.3, result.b.Dbl); } public void testFill2() { //Fill this shape: Object[]{Foo, Object, Foo{short, Bar{String, Double}}, Bar{double}}; ResultShape root = new ResultShape(Object[].class); ResultShape bar1 = new ResultShape(Bar.class, new FillStrategy.NewInstance(Bar.class)); bar1.add(String.class, Double.class); ResultShape fooBarConstr = new ResultShape(Foo.class, new FillStrategy.NewInstance(Foo.class)); fooBarConstr.add(short.class); fooBarConstr.nest(bar1); ResultShape bar2 = new ResultShape(Bar.class, new FillStrategy.NewInstance(Bar.class)); bar2.add(double.class); root.add(Foo.class, Object.class); root.nest(fooBarConstr); root.nest(bar2); assertEquals("Object[]{Foo, Object, Foo{short, Bar{String, Double}}, Bar{double}}", root.toString()); //from this array: new Foo(), new Object(), 200s, "bar1", 12.3d, 45.6d) Object[] values = {new Foo(), new Object(), 200, "bar1", 12.3d, 45.6d}; Class[] types = {Foo.class, Object.class, short.class, String.class, Double.class, double.class}; String[] aliases = {"Foo", "Object", "foo-short", "foo-bar-string", "foo-bar-Double", "bar-double"}; Object[] result = root.pack(values, types, aliases); assertEquals(4, result.length); assertEquals(Foo.class, result[0].getClass()); assertEquals(Object.class, result[1].getClass()); assertEquals(Foo.class, result[2].getClass()); assertEquals(Bar.class, result[3].getClass()); assertEquals(200, ((Foo)result[2]).shrt); assertEquals("bar1", ((Foo)result[2]).b.string); assertEquals(12.3, ((Foo)result[2]).b.Dbl); assertEquals(45.6, ((Bar)result[3]).dbl); } void assertCategory(ResultShape s, boolean primitive, boolean compound, boolean nesting) { if (primitive) assertTrue(s + " is not primitive", s.isPrimitive()); else assertFalse(s + " is primitive", s.isPrimitive()); if (compound) assertTrue(s + " is not compound", s.isCompound()); else assertFalse(s + " is compound", s.isCompound()); if (nesting) assertTrue(s + " is not nesting", s.isNesting()); else assertFalse(s + " is nesting", s.isNesting()); } void arrayEquals(Object[] a, Object[] b) { assertEquals(a.length, b.length); for (int i = 0; i < a.length; i++) { assertEquals(i+"-th element not equal", a[i], b[i]); } } Constructor constructor(Class t, Class...args) { try { return t.getConstructor(args); } catch (Exception e) { throw new RuntimeException(e); } } Method method(Class t, String name, Class...args) { try { return t.getMethod(name, args); } catch (Exception e) { throw new RuntimeException(e); } } public static class Foo { private String string; private int i; private short shrt; private Bar b; public Foo() {} public Foo(String s, int i) {this.string = s; this.i = i;} public Foo(short s, Bar b){this.shrt = s; this.b = b;} public String toString() { return "Foo(string='"+string+"' i="+i+" short="+shrt+" bar="+b+"";} } public static class Bar { private String string; private Double Dbl; private double dbl; public Bar() {} public Bar(double d) {this.dbl = d;} public Bar(String s, Double i) {this.string = s; this.Dbl = i;} public String toString() {return "Bar(string='"+string+"' Dbl="+Dbl+" dbl="+dbl+"";} } } openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/enhance/0000755000000000000000000000000012133327270023444 5ustar ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/enhance/TestGetDeclaredMethod.javaopenjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/enhance/TestGetDeclaredMethod.jav0000644000000000000000000000604312133327270030315 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.lang.reflect.Method; import java.util.List; import java.util.ArrayList; import junit.framework.TestCase; /** * Tests that {@link Reflection#getDeclaredMethod(Class, String, Class)} * returns the most-derived class's method when called from a type hierarchy. * See OPENJPA-251. */ public class TestGetDeclaredMethod extends TestCase { public void testGetDeclaredMethod() { Method meth = Reflection.getDeclaredMethod(Impl.class, "getObject", null); assertEquals(Impl.class, meth.getDeclaringClass()); assertEquals(String.class, meth.getReturnType()); } public void testMostDerived() throws NoSuchMethodException { Method impl = Impl.class.getDeclaredMethod("getObject", null); Method iface = Iface.class.getDeclaredMethod("getObject", null); Method other = Other.class.getDeclaredMethod("getObject", null); assertEquals(Impl.class, Reflection.mostDerived(impl, iface) .getDeclaringClass()); assertEquals(Impl.class, Reflection.mostDerived(iface, impl) .getDeclaringClass()); try { Reflection.mostDerived(iface, other); fail("'iface' and 'other' are not from related types"); } catch (IllegalArgumentException e) { // expected } } public void testGenerics() throws NoSuchMethodException { List meths = new ArrayList(); for (Method meth : GenericsImpl.class.getDeclaredMethods()) { if ("getObject".equals(meth.getName())) meths.add(meth); } assertEquals(2, meths.size()); assertEquals(String.class, Reflection.mostDerived(meths.get(0), meths.get(1)).getReturnType()); } interface Iface { Object getObject(); } static class Impl implements Iface { public String getObject() { return "string"; } } static class Other { public String getObject() { return "other"; } } interface GenericsIface { public T getObject(); } static class GenericsImpl implements GenericsIface { public String getObject() { return null; } } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/enhance/TestPCSubclassNameConversion.javaopenjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/enhance/TestPCSubclassNameConvers0000644000000000000000000000227612133327270030401 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import junit.framework.TestCase; public class TestPCSubclassNameConversion extends TestCase { public void testPCSubclassNameConversion() { String name = PCEnhancer.toPCSubclassName(Object.class); assertTrue(PCEnhancer.isPCSubclassName(name)); assertEquals(Object.class.getName(), PCEnhancer.toManagedTypeName(name)); } } openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/ee/0000755000000000000000000000000012133327270022434 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/ee/TestWASManagedRuntime.java0000644000000000000000000000372412133327270027420 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import junit.framework.TestCase; import serp.util.Strings; /** * Test class for build transformation performed by WASManagedRuntime. * */ public class TestWASManagedRuntime extends TestCase { /** * This test will verify that the WASManagedRuntime$WASSynchronization * class was properly modified by the maven build process (reference * the top level pom.xml). This testcase will not execute properly * within Eclipse since the Eclipse target directory (probably) hasn't * been modified via the maven build. * * @throws ClassNotFoundException */ public void testInterfaceAdded() throws ClassNotFoundException { String msg = null; try { Class.forName(WASManagedRuntime.CLASS); fail("expected an exception to be thrown"); } catch (NoClassDefFoundError e) { msg = e.getMessage(); } String interfaceName = Strings. getClassName(WASManagedRuntime.INTERFACE); assertTrue("message should have contained " + interfaceName + ", but was '" + msg + "'", msg.indexOf(interfaceName) != -1); } } openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/ee/TestOSGiManagedRuntime.java0000644000000000000000000003750212133327270027570 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.Dictionary; import java.util.List; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.InvalidTransactionException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.openjpa.util.InternalException; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.BundleListener; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkListener; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; /** * Test javax.transaction.TransactionManager OSGi service discovery. */ public class TestOSGiManagedRuntime extends TestCase { private static final String TXN_MANAGER_CLASS_NAME = "javax.transaction.TransactionManager"; /** * A transaction manager instance an nothing more. */ private static final TransactionManager TXN_MANAGER = new TransactionManager() { public void begin() throws NotSupportedException, SystemException { } public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException, RollbackException, SecurityException, SystemException { } public int getStatus() throws SystemException { return 0; } public Transaction getTransaction() throws SystemException { return null; } public void resume(Transaction tobj) throws IllegalStateException, InvalidTransactionException, SystemException { } public void rollback() throws IllegalStateException, SecurityException, SystemException { } public void setRollbackOnly() throws IllegalStateException, SystemException { } public void setTransactionTimeout(int seconds) throws SystemException { } public Transaction suspend() throws SystemException { return null; } public String toString() { return TestOSGiManagedRuntime.class.getName()+"::TXN_MANAGER"; } }; /** * A service reference instance an nothing more. */ private static final ServiceReference TXN_SVC_REFERENCE = new ServiceReference() { @Override public boolean isAssignableTo(Bundle bundle, String className) { return false; } @Override public Bundle[] getUsingBundles() { return null; } @Override public String[] getPropertyKeys() { return null; } @Override public Object getProperty(String key) { return null; } @Override public Bundle getBundle() { return null; } @Override public int compareTo(Object reference) { return reference == TXN_SVC_REFERENCE ? 0 : 1; } public String toString() { return TestOSGiManagedRuntime.class.getName()+"::TXN_SVC_REFERENCE"; } }; /** * A fake bundle context with a reference counter for a javax.transaction.TRansactionManager */ private static final class TestBundleContext implements BundleContext { private List serviceListeners; private TransactionManager transactionManager; private int txnRefCount; public void setTransactionManager(TransactionManager transactionManager) { if (transactionManager == null) { if (this.serviceListeners != null) { for (ServiceListener listener :this.serviceListeners) { listener.serviceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING,TXN_SVC_REFERENCE)); } } } // test for properly calling ungetReference(). assertEquals(0,this.txnRefCount); this.transactionManager = transactionManager; if (transactionManager != null) { if (this.serviceListeners != null) { for (ServiceListener listener :this.serviceListeners) { listener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED,TXN_SVC_REFERENCE)); } } } } public int getServiceListenerCount() { if (this.serviceListeners == null) { return 0; } else { return this.serviceListeners.size(); } } public int getTxnRefCount() { return this.txnRefCount; } public String getProperty(String key) { throw new UnsupportedOperationException(); } public Bundle getBundle() { throw new UnsupportedOperationException(); } public Bundle installBundle(String location, InputStream input) throws BundleException { throw new UnsupportedOperationException(); } public Bundle installBundle(String location) throws BundleException { throw new UnsupportedOperationException(); } public Bundle getBundle(long id) { throw new UnsupportedOperationException(); } public Bundle[] getBundles() { throw new UnsupportedOperationException(); } public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException { assertEquals("(objectClass="+TXN_MANAGER_CLASS_NAME+")",filter); if (this.serviceListeners == null) this.serviceListeners = new ArrayList(); this.serviceListeners.add(listener); } public void addServiceListener(ServiceListener listener) { throw new AssertionFailedError("service listener must be added using an objectClass filter."); } public void removeServiceListener(ServiceListener listener) { if (this.serviceListeners == null || ! this.serviceListeners.remove(listener)) { throw new AssertionFailedError("Try to remove service listener, which has not been added before."); } assertEquals(0,this.txnRefCount); } public void addBundleListener(BundleListener listener) { throw new UnsupportedOperationException(); } public void removeBundleListener(BundleListener listener) { throw new UnsupportedOperationException(); } public void addFrameworkListener(FrameworkListener listener) { throw new UnsupportedOperationException(); } public void removeFrameworkListener(FrameworkListener listener) { throw new UnsupportedOperationException(); } @SuppressWarnings("rawtypes") public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) { throw new UnsupportedOperationException(); } @SuppressWarnings("rawtypes") public ServiceRegistration registerService(String clazz, Object service, Dictionary properties) { throw new UnsupportedOperationException(); } public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException { throw new UnsupportedOperationException(); } public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException { throw new UnsupportedOperationException(); } public ServiceReference getServiceReference(String clazz) { assertEquals(TXN_MANAGER_CLASS_NAME,clazz); if (this.transactionManager == null) { return null; } assertEquals(TXN_MANAGER_CLASS_NAME,clazz); return TXN_SVC_REFERENCE; } @Override public Object getService(ServiceReference reference) { assertSame(TXN_SVC_REFERENCE,reference); ++this.txnRefCount; return this.transactionManager; } @Override public boolean ungetService(ServiceReference reference) { assertSame(TXN_SVC_REFERENCE,reference); --this.txnRefCount; return true; } public File getDataFile(String filename) { throw new UnsupportedOperationException(); } public Filter createFilter(String filter) throws InvalidSyntaxException { throw new UnsupportedOperationException(); } } private static void assertTxnManagerAvailable(TestBundleContext context, ManagedRuntime mr) throws Exception { assertSame(TXN_MANAGER,mr.getTransactionManager()); assertEquals(1,context.getTxnRefCount()); } private static void assertTxnManagerUnavailable(TestBundleContext context, ManagedRuntime mr) throws Exception { InternalException ie = null; try { mr.getTransactionManager(); } catch (InternalException e) { ie = e; } assertNotNull(ie); assertEquals(0,context.getTxnRefCount()); } /** * Test the discovery, when transaction manager is available before starting * OSGiManagedRuntime and disappears after stopping the managed runtime. * * @throws Throwable */ public void testTxnServiceDiscoveryPreStartPostStop() throws Throwable { TestBundleContext context = new TestBundleContext(); context.setTransactionManager(TXN_MANAGER); OSGiManagedRuntime.registerServiceListener(context); ManagedRuntime mr = new OSGiManagedRuntime(); try { assertEquals(1,context.getServiceListenerCount()); assertTxnManagerAvailable(context, mr); context.setTransactionManager(null); assertTxnManagerUnavailable(context, mr); OSGiManagedRuntime.deregisterServiceListener(context); } catch(Throwable e) { // this is her in order to make test repeatable in one JVM, because // OSGiManagerRuntime has static properties. OSGiManagedRuntime.deregisterServiceListener(context); throw e; } assertEquals(0,context.getServiceListenerCount()); assertTxnManagerUnavailable(context, mr); } /** * Test the discovery, when transaction manager is available before starting * OSGiManagedRuntime and disappears before stopping the managed runtime. * * @throws Throwable */ public void testTxnServiceDiscoveryPreStartPreStop() throws Throwable { TestBundleContext context = new TestBundleContext(); context.setTransactionManager(TXN_MANAGER); OSGiManagedRuntime.registerServiceListener(context); ManagedRuntime mr = new OSGiManagedRuntime(); try { assertEquals(1,context.getServiceListenerCount()); assertTxnManagerAvailable(context, mr); OSGiManagedRuntime.deregisterServiceListener(context); } catch(Throwable e) { // this is her in order to make test repeatable in one JVM, because // OSGiManagerRuntime has static properties. OSGiManagedRuntime.deregisterServiceListener(context); throw e; } assertEquals(0,context.getServiceListenerCount()); assertTxnManagerUnavailable(context, mr); } /** * Test the discovery, when transaction manager becomes available after starting * OSGiManagedRuntime and disappears after stopping the managed runtime. * * @throws Throwable */ public void testTxnServiceDiscoveryPostStartPostStop() throws Throwable { TestBundleContext context = new TestBundleContext(); OSGiManagedRuntime.registerServiceListener(context); ManagedRuntime mr = new OSGiManagedRuntime(); try{ assertEquals(1,context.getServiceListenerCount()); assertTxnManagerUnavailable(context, mr); context.setTransactionManager(TXN_MANAGER); assertTxnManagerAvailable(context, mr); OSGiManagedRuntime.deregisterServiceListener(context); } catch(Throwable e) { // this is her in order to make test repeatable in one JVM, because // OSGiManagerRuntime has static proeprties. OSGiManagedRuntime.deregisterServiceListener(context); throw e; } assertEquals(0,context.getServiceListenerCount()); assertTxnManagerUnavailable(context, mr); } /** * Test the discovery, when transaction manager becomes available after starting * OSGiManagedRuntime and disappears before stopping the managed runtime. * * @throws Throwable */ public void testTxnServiceDiscoveryPostStartPreStop() throws Throwable { TestBundleContext context = new TestBundleContext(); OSGiManagedRuntime.registerServiceListener(context); ManagedRuntime mr = new OSGiManagedRuntime(); try { assertEquals(1,context.getServiceListenerCount()); assertTxnManagerUnavailable(context, mr); context.setTransactionManager(TXN_MANAGER); assertTxnManagerAvailable(context, mr); context.setTransactionManager(null); assertTxnManagerUnavailable(context, mr); OSGiManagedRuntime.deregisterServiceListener(context); } catch(Throwable e) { // this is her in order to make test repeatable in one JVM, because // OSGiManagerRuntime has static proeprties. OSGiManagedRuntime.deregisterServiceListener(context); throw e; } assertEquals(0,context.getServiceListenerCount()); assertTxnManagerUnavailable(context, mr); } } openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/conf/0000755000000000000000000000000012133327270022770 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/conf/TestSpecification.java0000644000000000000000000000512212133327270027253 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import junit.framework.TestCase; /** * Test basics of Specification object. * * @author Pinaki Poddar * */ public class TestSpecification extends TestCase { public void testStaticConstruction() { Specification spec1 = new Specification("JPA 2.3"); assertEquals("JPA", spec1.getName()); assertEquals(2, spec1.getVersion()); assertEquals("3", spec1.getMinorVersion()); Specification spec2 = new Specification("JPA 1.1"); assertEquals("JPA", spec2.getName()); assertEquals(1, spec2.getVersion()); assertEquals("1", spec2.getMinorVersion()); Specification spec3 = new Specification("JDO 3.ED"); assertEquals("JDO", spec3.getName()); assertEquals(3, spec3.getVersion()); assertEquals("ED", spec3.getMinorVersion()); Specification spec4 = new Specification("JDO 3.5"); assertEquals("JDO", spec4.getName()); assertEquals(3, spec4.getVersion()); assertEquals("5", spec4.getMinorVersion()); } public void testEqualityByName() { Specification spec1 = new Specification("JPA 2.3"); Specification spec2 = new Specification("JPA 1.0"); Specification spec3 = new Specification("JDO 3.1"); assertTrue(spec1.isSame(spec2)); assertTrue(spec1.isSame("jpa")); assertTrue(spec1.isSame("JPA")); assertFalse(spec1.isSame(spec3)); } public void testVersionCompare() { Specification spec1 = new Specification("JPA 1.1"); Specification spec2 = new Specification("JPA 2.2"); assertTrue(spec1.compareVersion(spec2) < 0); assertTrue(spec2.compareVersion(spec1) > 0); assertTrue(spec1.compareVersion(spec1) == 0); } } openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/meta/0000755000000000000000000000000012133327270022771 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestMemberProvider.java0000644000000000000000000000434412133327270027423 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.IOException; import junit.framework.TestCase; import org.apache.openjpa.meta.FieldMetaData.MemberProvider; public class TestMemberProvider extends TestCase { private String field; public void testField() throws NoSuchFieldException, IOException, ClassNotFoundException { MemberProvider b = new MemberProvider( getClass().getDeclaredField("field")); MemberProvider b2 = roundtrip(b); assertEquals(b.getMember(), b2.getMember()); } public void testMethod() throws NoSuchMethodException, IOException, ClassNotFoundException { MemberProvider b = new MemberProvider( getClass().getDeclaredMethod("testMethod", null)); MemberProvider b2 = roundtrip(b); assertEquals(b.getMember(), b2.getMember()); } private MemberProvider roundtrip(MemberProvider other) throws IOException, ClassNotFoundException { ByteArrayOutputStream out = new ByteArrayOutputStream(); new ObjectOutputStream(out).writeObject(other); out.flush(); byte[] bytes = out.toByteArray(); out.close(); ByteArrayInputStream in = new ByteArrayInputStream(bytes); return (MemberProvider) new ObjectInputStream(in).readObject(); } } openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestAccessCode.java0000644000000000000000000002001412133327270026465 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import junit.framework.TestCase; /** * Access code is a 5-bit integer. * * @author Pinaki Poddar * */ public class TestAccessCode extends TestCase { public static final int UNKNOWN = AccessCode.UNKNOWN; public static final int FIELD = AccessCode.FIELD; public static final int PROPERTY = AccessCode.PROPERTY; public static final int EXPLICIT = AccessCode.EXPLICIT; public static final int MIXED = AccessCode.MIXED; // Valid class codes are 0 2 4 10 12 26 28 public void testValidClassCodes() { isValidClassCode(true, 0, UNKNOWN); isValidClassCode(true, 2, FIELD); isValidClassCode(true, 4, PROPERTY); isValidClassCode(false, 6, FIELD | PROPERTY); isValidClassCode(false, 8, EXPLICIT); isValidClassCode(true, 10, EXPLICIT | FIELD); isValidClassCode(true, 12, EXPLICIT | PROPERTY); isValidClassCode(false, 14, EXPLICIT | FIELD | PROPERTY); isValidClassCode(false, 16, MIXED); isValidClassCode(false, 18, MIXED | FIELD); isValidClassCode(false, 20, MIXED | PROPERTY); isValidClassCode(false, 22, MIXED | FIELD | PROPERTY); isValidClassCode(false, 24, MIXED | EXPLICIT | UNKNOWN); isValidClassCode(true, 26, MIXED | EXPLICIT | FIELD); isValidClassCode(true, 28, MIXED | EXPLICIT | PROPERTY); isValidClassCode(false, 30, MIXED | EXPLICIT | FIELD | PROPERTY); // All odd codes other than 1 are invalid for (int i = 3; i < 32; i += 2) assertFalse("Not a valid Class Code: " + AccessCode.toClassString(i), AccessCode.isValidClassCode(i)); } // Valid field codes are 0 2 4 10 12 public void testValidFieldCodes() { isValidClassCode(true, 0, UNKNOWN); isValidClassCode(true, 2, FIELD); isValidClassCode(true, 4, PROPERTY); isValidClassCode(false, 6, FIELD | PROPERTY); isValidClassCode(false, 8, EXPLICIT); isValidClassCode(true, 10, EXPLICIT | FIELD); isValidClassCode(true, 12, EXPLICIT | PROPERTY); isValidClassCode(false, 14, EXPLICIT | FIELD | PROPERTY); // any even code with MIXED bit set is invalid for (int i = MIXED; i < 32; i += 2) { assertFalse("Not a valid field code: " + AccessCode.toFieldString(i), AccessCode.isValidFieldCode(i)); } } public void testProperty() { isProperty(false, 0, UNKNOWN); isProperty(false, 2, FIELD); isProperty(true, 4, PROPERTY); isProperty(false, 10, EXPLICIT | FIELD); isProperty(true, 12, EXPLICIT | PROPERTY); isProperty(false, 26, MIXED | EXPLICIT | FIELD); isProperty(true, 28, MIXED | EXPLICIT | PROPERTY); } public void testField() { isField(false, 0, UNKNOWN); isField(true, 2, FIELD); isField(false, 4, PROPERTY); isField(true, 10, EXPLICIT | FIELD); isField(false, 12, EXPLICIT | PROPERTY); isField(true, 14, EXPLICIT | FIELD | PROPERTY); isField(true, 26, MIXED | EXPLICIT | FIELD); isField(false, 28, MIXED | EXPLICIT | PROPERTY); } public void testExplicit() { isExplicit(false, 0, UNKNOWN); isExplicit(false, 2, FIELD); isExplicit(false, 4, PROPERTY); isExplicit(true, 10, EXPLICIT | FIELD); isExplicit(true, 12, EXPLICIT | PROPERTY); isExplicit(true, 14, EXPLICIT | FIELD | PROPERTY); isExplicit(true, 26, MIXED | EXPLICIT | FIELD); isExplicit(true, 28, MIXED | EXPLICIT | PROPERTY); } public void testMixed() { isMixed(false, 0, UNKNOWN); isMixed(false, 2, FIELD); isMixed(false, 4, PROPERTY); isMixed(false, 10, EXPLICIT | FIELD); isMixed(false, 12, EXPLICIT | PROPERTY); isMixed(false, 14, EXPLICIT | FIELD | PROPERTY); isMixed(true, 26, MIXED | EXPLICIT | FIELD); isMixed(true, 28, MIXED | EXPLICIT | PROPERTY); } public void testCompatibleField() { assertCompatible(EXPLICIT|FIELD, PROPERTY, MIXED|EXPLICIT|FIELD); assertCompatible(EXPLICIT|FIELD, FIELD, EXPLICIT|FIELD); assertCompatible(EXPLICIT|PROPERTY, PROPERTY, EXPLICIT|PROPERTY); assertCompatible(EXPLICIT|PROPERTY, FIELD, MIXED|EXPLICIT|PROPERTY); assertNotCompatible(FIELD, PROPERTY); assertCompatible(FIELD, FIELD, FIELD); assertCompatible(PROPERTY, PROPERTY, PROPERTY); assertNotCompatible(PROPERTY, FIELD); } void assertCompatible(int cCode, int fCode) { assertCompatibility(true, cCode, fCode, cCode); } void assertNotCompatible(int cCode, int fCode) { assertCompatibility(false, cCode, fCode, cCode); } void assertCompatible(int cCode, int fCode, int tCode) { assertCompatibility(true, cCode, fCode, tCode); } void assertCompatibility(boolean flag, int cCode, int fCode, int tCode) { if (flag) { assertEquals(tCode, AccessCode.mergeFieldCode(cCode, fCode)); } else { try { AccessCode.mergeFieldCode(cCode, fCode); fail(); } catch (IllegalStateException e) { } } } public void testToString() { assertEquals("explicit property access", AccessCode.toClassString(12)); } void isValidClassCode(boolean flag, int v, int valid) { assertEquals(v, valid); if (flag) assertTrue("Invalid Class Code: " + AccessCode.toClassString(valid), AccessCode.isValidClassCode(valid)); else assertFalse("Wrong Valid Class Code: " + AccessCode.toClassString(valid), AccessCode.isValidClassCode(valid)); } void isValidFieldCode(boolean flag, int v, int valid) { assertEquals(v, valid); if (flag) assertTrue("Invalid Field Code: " + AccessCode.toFieldString(valid), AccessCode.isValidFieldCode(valid)); else assertFalse("Wrong Field Class Code: " + AccessCode.toFieldString(valid), AccessCode.isValidFieldCode(valid)); } void isProperty(boolean flag, int v, int valid) { assertEquals(v, valid); if (flag) assertTrue(AccessCode.isProperty(valid)); else assertFalse(AccessCode.isProperty(valid)); } void isField(boolean flag, int v, int valid) { assertEquals(v, valid); if (flag) assertTrue(AccessCode.isField(valid)); else assertFalse(AccessCode.isField(valid)); } void isExplicit(boolean flag, int v, int valid) { assertEquals(v, valid); if (flag) assertTrue(AccessCode.isExplicit(valid)); else assertFalse(AccessCode.isExplicit(valid)); } void isMixed(boolean flag, int v, int valid) { assertEquals(v, valid); if (flag) assertTrue(AccessCode.isMixed(valid)); else assertFalse(AccessCode.isMixed(valid)); } } openjpa-2.2.2.orig/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestJavaTypes.java0000644000000000000000000000415112133327270026403 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import junit.framework.TestCase; public class TestJavaTypes extends TestCase { TypesHolder _types = new TypesHolder(); public void testIsPrimitiveDefault() { assertTrue(JavaTypes.isPrimitiveDefault(_types.getBoolean(), JavaTypes.BOOLEAN)); assertTrue(JavaTypes.isPrimitiveDefault(_types.getChar(), JavaTypes.CHAR)); assertTrue(JavaTypes.isPrimitiveDefault(_types.getDouble(), JavaTypes.DOUBLE)); assertTrue(JavaTypes.isPrimitiveDefault(_types.getInt(), JavaTypes.INT)); assertTrue(JavaTypes.isPrimitiveDefault(_types.getLong(), JavaTypes.LONG)); assertTrue(JavaTypes.isPrimitiveDefault(_types.getShort(), JavaTypes.SHORT)); } class TypesHolder { boolean _boolean; short _short; int _int; long _long; float _float; double _double; char _char; public Object getBoolean() { return _boolean; } public Object getShort() { return _short; } public Object getInt() { return _int; } public Object getLong() { return _long; } public Object getDouble() { return _double; } public Object getChar() { return _char; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/0000755000000000000000000000000012133327272015425 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/0000755000000000000000000000000012133327270016344 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/0000755000000000000000000000000012133327270017133 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/0000755000000000000000000000000012133327270020354 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/0000755000000000000000000000000012133327272022012 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/0000755000000000000000000000000012133327272022767 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/Proxy.java0000644000000000000000000000374012133327272024757 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * Interface implemented by all proxy types to allow setting and nulling * of their owning instance. * All concrete proxy classes should be public and have publc no-args * constructors so that tools that work via reflection on persistent instances * can manipulate them. * * @author Abe White */ public interface Proxy { /** * Reset the state of the proxy, and set the owning instance of the * proxy and the name of the field it is assigned to. Set to null to * indicate that the proxy is no longer managed. */ public void setOwner(OpenJPAStateManager sm, int field); /** * Return the owning object. */ public OpenJPAStateManager getOwner(); /** * Return the owning field index. */ public int getOwnerField(); /** * Return the change tracker for this proxy, or null if none. */ public ChangeTracker getChangeTracker(); /** * Return an unproxied copy of the given instance. This method is used * by proxy managers to create backup values for use in rollback. */ public Object copy(Object orig); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/StoreFacadeTypeRegistry.java0000644000000000000000000001005312133327272030404 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Map; import org.apache.openjpa.kernel.StoreManager; import java.util.concurrent.ConcurrentHashMap; /** * Repository of store-specific facade classes. This is used by facade * implementations to wrap store-specific components without knowing * about all possible back-ends. */ public class StoreFacadeTypeRegistry { private Map _impls = new ConcurrentHashMap(); /** * Register a facade implementation. * * @param facadeType the facade interface * @param storeType the store's * {@link org.apache.openjpa.kernel.StoreManager} type, or null for generic * @param implType the class implementing the facade */ public void registerImplementation(Class facadeType, Class storeType, Class implType) { Object key = (storeType == null) ? (Object) facadeType : new Key(facadeType, storeType); _impls.put(key, implType); } /** * Return the implementation for the given facade and store. * * @param facadeType the facade interface * @param storeType the store's * {@link org.apache.openjpa.kernel.StoreManager} type, or null for generic * @param implType the registered implementor */ public Class getImplementation(Class facadeType, Class storeType) { // traverse store type hierarchy to store manager to find most specific // store avaialble Class impl; for (; storeType != null && storeType != StoreManager.class; storeType = storeType.getSuperclass()) { impl = (Class) _impls.get(new Key(facadeType, storeType)); if (impl != null) return impl; } return (Class) _impls.get(facadeType); } /** * Return the implementation for the given facade and store. If no * registered implementation is found then returns the given default type * provided it the facade type is assignable from the deafult type. * * @param facadeType the facade interface * @param storeType the store's * {@link org.apache.openjpa.kernel.StoreManager} type, or null for generic * @param implType the registered implementor * @param defaultType class if no registered implementation is available. */ public Class getImplementation(Class facadeType, Class storeType, Class defaultType) { Class result = getImplementation(facadeType, storeType); if (result == null) result = defaultType; if (facadeType == null || !facadeType.isAssignableFrom(result)) throw new InternalException(); return result; } /** * Lookup key for facade+store hash. */ private static class Key { public final Class _facadeType; public final Class _storeType; public Key(Class facadeType, Class storeType) { _facadeType = facadeType; _storeType = storeType; } public int hashCode() { return _facadeType.hashCode() ^ _storeType.hashCode(); } public boolean equals(Object other) { if (other == this) return true; Key k = (Key) other; return _facadeType == k._facadeType && _storeType == k._storeType; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/UserException.java0000644000000000000000000000342012133327272026426 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Base exception type for user errors. * * @author Marc Prud'hommeaux * @since 0.2.5 */ public class UserException extends OpenJPAException { public static final int METADATA = 1; public static final int INVALID_STATE = 2; public static final int NO_TRANSACTION = 3; public static final int CALLBACK = 4; public static final int NO_RESULT = 5; public static final int NON_UNIQUE_RESULT = 6; public UserException() { } public UserException(String msg) { super(msg); } public UserException(Message msg) { super(msg); } public UserException(Throwable cause) { super(cause); } public UserException(String msg, Throwable cause) { super(msg, cause); } public UserException(Message msg, Throwable cause) { super(msg, cause); } public int getType() { return USER; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java0000644000000000000000000006613312133327272026546 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.Date; import org.apache.openjpa.enhance.FieldManager; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.Reflection; import org.apache.openjpa.kernel.ObjectIdStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StateManagerImpl; import org.apache.openjpa.kernel.StoreManager; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueStrategies; /** * Utility class for manipulating application object ids. * * @author Abe White * @nojavadoc */ public class ApplicationIds { private static final Localizer _loc = Localizer.forPackage (ApplicationIds.class); private static final Localizer _loc2 = Localizer.forPackage (StateManagerImpl.class); /** * Return the primary key values for the given object id. The values * will be returned in the same order as the metadata primary key fields. * Values for PC primary key fields will be the primary key value or * oid value of the related instance (depending on * {@link FieldMetaData#isObjectIdFieldIdOfPC}). */ public static Object[] toPKValues(Object oid, ClassMetaData meta) { if (meta == null) return null; Object[] pks; if (meta.isOpenJPAIdentity()) { pks = new Object[1]; if (oid != null) pks[0] = ((OpenJPAId) oid).getIdObject(); return pks; } // reset owning 'meta' to the owner of the primary key fields, because // the one passed in might be a proxy, like for embedded mappings; // since getPrimaryKeyFields is guaranteed to return the primary // keys in the order of inheritance, we are guaranteed that // the last element will be the most-derived class. FieldMetaData[] fmds = meta.getPrimaryKeyFields(); meta = fmds[fmds.length - 1].getDeclaringMetaData(); pks = new Object[fmds.length]; if (oid == null) return pks; if (!Modifier.isAbstract(meta.getDescribedType().getModifiers())) { // copy fields from the oid PrimaryKeyFieldManager consumer = new PrimaryKeyFieldManager(); consumer.setStore(pks); oid = wrap(meta, oid); PCRegistry.copyKeyFieldsFromObjectId(meta.getDescribedType(), consumer, oid); return consumer.getStore(); } // default to reflection if (meta.isObjectIdTypeShared()) oid = ((ObjectId) oid).getId(); Class oidType = oid.getClass(); for (int i = 0; i < fmds.length; i++) { if (AccessCode.isField(meta.getAccessType())) pks[i] = Reflection.get(oid, Reflection.findField(oidType, fmds[i].getName(), true)); else pks[i] = Reflection.get(oid, Reflection.findGetter(oidType, fmds[i].getName(), true)); } return pks; } /** * Wraps the given object for the given type into a OpenJPA specific * application identity object wrapper instance (i.e. ObjectId) if all of * the following is true: * the given type is not using built-in OpenJPA identity types * the given type is using a shared OpenJPA identity type * the given object is not already a wrapper identity type */ public static Object wrap(ClassMetaData meta, Object oid) { if (!meta.isOpenJPAIdentity() && meta.isObjectIdTypeShared() && !(oid instanceof ObjectId)) { return new ObjectId(meta.getDescribedType(), oid); } return oid; } /** * Return a new object id constructed from the given primary key values. * Values for PC primary key fields should be the primary key value or * oid value of the related instance (depending on * {@link FieldMetaData#isObjectIdFieldIdOfPC}). */ public static Object fromPKValues(Object[] pks, ClassMetaData meta) { if (meta == null || pks == null) return null; boolean convert = !meta.getRepository().getConfiguration(). getCompatibilityInstance().getStrictIdentityValues(); if (meta.isOpenJPAIdentity()) { int type = meta.getPrimaryKeyFields()[0].getObjectIdFieldTypeCode(); Object val = (convert) ? JavaTypes.convert(pks[0], type) : pks[0]; switch (type) { case JavaTypes.BYTE: case JavaTypes.BYTE_OBJ: if (!convert && !(val instanceof Byte)) throw new ClassCastException("!(x instanceof Byte)"); return new ByteId(meta.getDescribedType(), val == null ? 0 : ((Number) val).byteValue()); case JavaTypes.CHAR: case JavaTypes.CHAR_OBJ: return new CharId(meta.getDescribedType(), val == null ? 0 : ((Character) val).charValue()); case JavaTypes.DOUBLE: case JavaTypes.DOUBLE_OBJ: if (!convert && !(val instanceof Double)) throw new ClassCastException("!(x instanceof Double)"); return new DoubleId(meta.getDescribedType(), val == null ? 0 : ((Number) val).doubleValue()); case JavaTypes.FLOAT: case JavaTypes.FLOAT_OBJ: if (!convert && !(val instanceof Float)) throw new ClassCastException("!(x instanceof Float)"); return new FloatId(meta.getDescribedType(), val == null ? 0 : ((Number) val).floatValue()); case JavaTypes.INT: case JavaTypes.INT_OBJ: if (!convert && !(val instanceof Integer)) throw new ClassCastException("!(x instanceof Integer)"); return new IntId(meta.getDescribedType(), val == null ? 0 : ((Number) val).intValue()); case JavaTypes.LONG: case JavaTypes.LONG_OBJ: if (!convert && !(val instanceof Long)) throw new ClassCastException("!(x instanceof Long)"); return new LongId(meta.getDescribedType(), val == null ? 0 : ((Number) val).longValue()); case JavaTypes.SHORT: case JavaTypes.SHORT_OBJ: if (!convert && !(val instanceof Short)) throw new ClassCastException("!(x instanceof Short)"); return new ShortId(meta.getDescribedType(), val == null ? 0 : ((Number) val).shortValue()); case JavaTypes.STRING: return new StringId(meta.getDescribedType(), (String) val); case JavaTypes.DATE: return new DateId(meta.getDescribedType(), (Date) val); case JavaTypes.OID: case JavaTypes.OBJECT: return new ObjectId(meta.getDescribedType(), val); case JavaTypes.BIGDECIMAL: if (!convert && !(val instanceof BigDecimal)) throw new ClassCastException( "!(x instanceof BigDecimal)"); return new BigDecimalId(meta.getDescribedType(), (BigDecimal)val); case JavaTypes.BIGINTEGER: if (!convert && !(val instanceof BigInteger)) throw new ClassCastException( "!(x instanceof BigInteger)"); return new BigIntegerId(meta.getDescribedType(), (BigInteger)val); case JavaTypes.BOOLEAN: case JavaTypes.BOOLEAN_OBJ: if (!convert && !(val instanceof Boolean)) throw new ClassCastException("!(x instanceof Boolean)"); return new BooleanId(meta.getDescribedType(), val == null ? false : (Boolean)val); default: throw new InternalException(); } } // copy pks to oid if (!Modifier.isAbstract(meta.getDescribedType().getModifiers())) { Object oid = PCRegistry.newObjectId(meta.getDescribedType()); PrimaryKeyFieldManager producer = new PrimaryKeyFieldManager(); producer.setStore(pks); if (convert) producer.setMetaData(meta); PCRegistry.copyKeyFieldsToObjectId(meta.getDescribedType(), producer, oid); return ApplicationIds.wrap(meta, oid); } // default to reflection Class oidType = meta.getObjectIdType(); if (Modifier.isAbstract(oidType.getModifiers())) throw new UserException(_loc.get("objectid-abstract", meta)); Object copy = null; try { copy = AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(oidType)); } catch (Throwable t) { if (t instanceof PrivilegedActionException) t = ((PrivilegedActionException) t).getException(); throw new GeneralException(t); } FieldMetaData[] fmds = meta.getPrimaryKeyFields(); Object val; for (int i = 0; i < fmds.length; i++) { val = (convert) ? JavaTypes.convert(pks[i], fmds[i].getObjectIdFieldTypeCode()) : pks[i]; if (AccessCode.isField(meta.getAccessType())) Reflection.set(copy, Reflection.findField(oidType, fmds[i].getName(), true), val); else Reflection.set(copy, Reflection.findSetter(oidType, fmds[i].getName(), fmds[i].getDeclaredType(), true), val); } if (meta.isObjectIdTypeShared()) copy = new ObjectId(meta.getDescribedType(), copy); return copy; } /** * Copy the given oid value. */ public static Object copy(Object oid, ClassMetaData meta) { if (meta == null || oid == null) return null; if (meta.isOpenJPAIdentity()) { // use meta type instead of oid type in case it's a subclass Class cls = meta.getDescribedType(); OpenJPAId koid = (OpenJPAId) oid; FieldMetaData pk = meta.getPrimaryKeyFields()[0]; switch (pk.getObjectIdFieldTypeCode()) { case JavaTypes.BYTE: case JavaTypes.BYTE_OBJ: return new ByteId(cls, ((ByteId) oid).getId(), koid.hasSubclasses()); case JavaTypes.CHAR: case JavaTypes.CHAR_OBJ: return new CharId(cls, ((CharId) oid).getId(), koid.hasSubclasses()); case JavaTypes.DOUBLE: case JavaTypes.DOUBLE_OBJ: return new DoubleId(cls, ((DoubleId) oid).getId(), koid.hasSubclasses()); case JavaTypes.FLOAT: case JavaTypes.FLOAT_OBJ: return new FloatId(cls, ((FloatId) oid).getId(), koid.hasSubclasses()); case JavaTypes.INT: case JavaTypes.INT_OBJ: return new IntId(cls, ((IntId) oid).getId(), koid.hasSubclasses()); case JavaTypes.LONG: case JavaTypes.LONG_OBJ: return new LongId(cls, ((LongId) oid).getId(), koid.hasSubclasses()); case JavaTypes.SHORT: case JavaTypes.SHORT_OBJ: return new ShortId(cls, ((ShortId) oid).getId(), koid.hasSubclasses()); case JavaTypes.STRING: return new StringId(cls, oid.toString(), koid.hasSubclasses()); case JavaTypes.OID: ClassMetaData embed = pk.getEmbeddedMetaData(); Object inner = koid.getIdObject(); if (embed != null) inner = copy(inner, embed, embed.getFields()); return new ObjectId(cls, inner, koid.hasSubclasses()); case JavaTypes.OBJECT: return new ObjectId(cls, koid.getIdObject(), koid.hasSubclasses()); case JavaTypes.DATE: return new DateId(cls, ((DateId) oid).getId(), koid.hasSubclasses()); case JavaTypes.BIGDECIMAL: return new BigDecimalId(cls, ((BigDecimalId) oid).getId(), koid.hasSubclasses()); case JavaTypes.BIGINTEGER: return new BigIntegerId(cls, ((BigIntegerId) oid).getId(), koid.hasSubclasses()); default: throw new InternalException(); } } // create a new pc instance of the right type, set its key fields // to the original oid values, then copy its key fields to a new // oid instance if (!Modifier.isAbstract(meta.getDescribedType().getModifiers()) && !hasPCPrimaryKeyFields(meta)) { Class type = meta.getDescribedType(); PersistenceCapable pc = PCRegistry.newInstance(type, null, oid, false); Object copy = pc.pcNewObjectIdInstance(); pc.pcCopyKeyFieldsToObjectId(copy); return copy; } Object copy = (!meta.isObjectIdTypeShared()) ? oid : ((ObjectId) oid).getId(); copy = copy(copy, meta, meta.getPrimaryKeyFields()); if (meta.isObjectIdTypeShared()) copy = new ObjectId(meta.getDescribedType(), copy, ((OpenJPAId) oid).hasSubclasses()); return copy; } /** * Return true if any of the given type's primary key fields are * persistent objects. */ private static boolean hasPCPrimaryKeyFields(ClassMetaData meta) { FieldMetaData[] fmds = meta.getPrimaryKeyFields(); for (int i = 0; i < fmds.length; i++) if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) return true; return false; } /** * Copy the given identity object using reflection. */ private static Object copy(Object oid, ClassMetaData meta, FieldMetaData[] fmds) { if (oid == null) return null; Class oidType = oid.getClass(); Object copy = null; try { copy = AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(oidType)); } catch (Throwable t) { if (t instanceof PrivilegedActionException) t = ((PrivilegedActionException) t).getException(); throw new GeneralException(t); } Field field; Object val; for (int i = 0; i < fmds.length; i++) { if (fmds[i].getManagement() != FieldMetaData.MANAGE_PERSISTENT) continue; if (AccessCode.isField(meta.getAccessType())) { field = Reflection.findField(oidType, fmds[i].getName(), true); Reflection.set(copy, field, Reflection.get(oid, field)); } else { // property val = Reflection.get(oid, Reflection.findGetter(oidType, fmds[i].getName(), true)); Reflection.set(copy, Reflection.findSetter(oidType, fmds[i]. getName(), fmds[i].getObjectIdFieldType(), true), val); } } return copy; } /** * Return the given primary key field value from the given oid. */ public static Object get(Object oid, FieldMetaData fmd) { if (oid == null) return null; if (oid instanceof OpenJPAId) return ((OpenJPAId) oid).getIdObject(); ClassMetaData meta = fmd.getDefiningMetaData(); Class oidType = oid.getClass(); if (AccessCode.isField(meta.getAccessType())) return Reflection.get(oid, Reflection.findField(oidType, fmd.getName(), true)); return Reflection.get(oid, Reflection.findGetter(oidType, fmd.getName(), true)); } /** * Generate an application id based on the current primary key field state * of the given instance. */ public static Object create(PersistenceCapable pc, ClassMetaData meta) { if (pc == null) return null; Object oid = pc.pcNewObjectIdInstance(); if (oid == null) return null; if (!meta.isOpenJPAIdentity()) { pc.pcCopyKeyFieldsToObjectId(oid); return oid; } FieldMetaData pk = meta.getPrimaryKeyFields()[0]; if (pk.getDeclaredTypeCode() != JavaTypes.OID) return oid; // always copy oid object in case field value mutates or becomes // managed ObjectId objid = (ObjectId) oid; ClassMetaData embed = pk.getEmbeddedMetaData(); objid.setId(copy(objid.getId(), embed, embed.getFields())); return objid; } /** * Assign an application identity object to the given state, or return * false if determining the application identity requires a flush. */ public static boolean assign(OpenJPAStateManager sm, StoreManager store, boolean preFlush) { ClassMetaData meta = sm.getMetaData(); if (meta.getIdentityType() != ClassMetaData.ID_APPLICATION) throw new InternalException(); boolean ret; FieldMetaData[] pks = meta.getPrimaryKeyFields(); if (meta.isOpenJPAIdentity() && pks[0].getDeclaredTypeCode() == JavaTypes.OID) { OpenJPAStateManager oidsm = new ObjectIdStateManager (sm.fetchObjectField(pks[0].getIndex()), sm, pks[0]); ret = assign(oidsm, store, pks[0].getEmbeddedMetaData(). getFields(), preFlush); sm.storeObjectField(pks[0].getIndex(), oidsm.getManagedInstance()); } else ret = assign(sm, store, meta.getPrimaryKeyFields(), preFlush); if (!ret) return false; // base oid on field values sm.setObjectId(create(sm.getPersistenceCapable(), meta)); return true; } /** * Assign generated values to given primary key fields. */ private static boolean assign(OpenJPAStateManager sm, StoreManager store, FieldMetaData[] pks, boolean preFlush) { for (int i = 0; i < pks.length; i++) // If we are generating values... if (pks[i].getValueStrategy() != ValueStrategies.NONE) { // If a value already exists on this field, throw exception. // This is considered an application coding error. if (!sm.isDefaultValue(pks[i].getIndex())) throw new InvalidStateException(_loc2.get("existing-value-override-excep", pks[i].getFullName(false), Exceptions.toString(sm.getPersistenceCapable()), sm.getPCState().getClass().getSimpleName())); // Assign the generated value if (store.assignField(sm, pks[i].getIndex(), preFlush)) pks[i].setValueGenerated(true); else return false; } return true; } /** * Check if object id is set or not. */ public static boolean isIdSet(Object id, ClassMetaData meta, String mappedByIdFieldName) { Object key = null; if (meta.isOpenJPAIdentity()) key = ApplicationIds.getKey(id, meta); else key = ((ObjectId)id).getId(); Object val = null; if (mappedByIdFieldName.length() != 0) { if (((ObjectId)id).getId() == null) return false; Class idClass = ((ObjectId)id).getId().getClass(); val = Reflection.get(key, Reflection.findField(idClass, mappedByIdFieldName, true)); } else val = key; boolean notSet = (val == null || (val instanceof String && ((String)val).length() == 0) || (val instanceof Number && ((Number)val).longValue() == 0)); return !notSet; } /** * Return the key from the given id. */ public static Object getKey(Object id, ClassMetaData meta) { if (meta == null || id == null) return null; if (meta.isOpenJPAIdentity()) { int type = meta.getPrimaryKeyFields()[0].getObjectIdFieldTypeCode(); switch (type) { case JavaTypes.BYTE: case JavaTypes.BYTE_OBJ: return ((ByteId)id).getId(); case JavaTypes.CHAR: case JavaTypes.CHAR_OBJ: return ((CharId)id).getId(); case JavaTypes.DOUBLE: case JavaTypes.DOUBLE_OBJ: return ((DoubleId)id).getId(); case JavaTypes.FLOAT: case JavaTypes.FLOAT_OBJ: return ((FloatId)id).getId(); case JavaTypes.INT: case JavaTypes.INT_OBJ: return ((IntId)id).getId(); case JavaTypes.LONG: case JavaTypes.LONG_OBJ: return ((LongId)id).getId(); case JavaTypes.SHORT: case JavaTypes.SHORT_OBJ: return ((ShortId)id).getId(); case JavaTypes.STRING: return ((StringId)id).getId(); case JavaTypes.DATE: return ((DateId)id).getId(); case JavaTypes.OID: case JavaTypes.OBJECT: return ((ObjectId)id).getId(); case JavaTypes.BIGDECIMAL: return ((BigDecimalId)id).getId(); case JavaTypes.BIGINTEGER: return ((BigIntegerId)id).getId(); default: throw new InternalException(); } } else { // IdClass return ((ObjectId)id).getId(); } } /** * Sets the underlying id of an ObjectId. Should only * be used with simple (idclass) types. */ public static void setAppId(ObjectId id, Object newId) { id.setId(newId); } /** * Helper class used to transfer pk values to/from application oids. */ private static class PrimaryKeyFieldManager implements FieldManager { private Object[] _store = null; private int _index = 0; private ClassMetaData _meta = null; public void setMetaData(ClassMetaData meta) { _meta = meta; } public Object[] getStore() { return _store; } public void setStore(Object[] store) { _store = store; } public void storeBooleanField(int field, boolean val) { store((val) ? Boolean.TRUE : Boolean.FALSE); } public void storeByteField(int field, byte val) { store(Byte.valueOf(val)); } public void storeCharField(int field, char val) { store(Character.valueOf(val)); } public void storeShortField(int field, short val) { store(Short.valueOf(val)); } public void storeIntField(int field, int val) { store(val); } public void storeLongField(int field, long val) { store(val); } public void storeFloatField(int field, float val) { store(Float.valueOf(val)); } public void storeDoubleField(int field, double val) { store(Double.valueOf(val)); } public void storeStringField(int field, String val) { store(val); } public void storeObjectField(int field, Object val) { store(val); } public boolean fetchBooleanField(int field) { return (retrieve(field) == Boolean.TRUE) ? true : false; } public char fetchCharField(int field) { return ((Character) retrieve(field)).charValue(); } public byte fetchByteField(int field) { return ((Number) retrieve(field)).byteValue(); } public short fetchShortField(int field) { return ((Number) retrieve(field)).shortValue(); } public int fetchIntField(int field) { return ((Number) retrieve(field)).intValue(); } public long fetchLongField(int field) { return ((Number) retrieve(field)).longValue(); } public float fetchFloatField(int field) { return ((Number) retrieve(field)).floatValue(); } public double fetchDoubleField(int field) { return ((Number) retrieve(field)).doubleValue(); } public String fetchStringField(int field) { return (String) retrieve(field); } public Object fetchObjectField(int field) { return retrieve(field); } private void store(Object val) { _store[_index++] = val; } private Object retrieve(int field) { Object val = _store[_index++]; if (_meta != null) { FieldMetaData fmd = _meta.getField(field); if (fmd.getDeclaredTypeCode() != JavaTypes.PC) val = JavaTypes.convert(val, fmd.getDeclaredTypeCode()); else val = JavaTypes.convert(val, JavaTypes.getTypeCode(fmd. getObjectIdFieldType())); } return val; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/package.html0000644000000000000000000000172212133327272025252 0ustar

OpenJPA Utilities

This package provides utilities to facilitate the handling of second class objects and OpenJPA object ids.

openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java0000644000000000000000000017500212133327272027075 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.File; import java.io.IOException; import java.io.ObjectStreamException; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet; import java.util.Queue; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.enhance.AsmAdaptor; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.lib.util.concurrent.NullSafeConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import serp.bytecode.BCClass; import serp.bytecode.BCField; import serp.bytecode.BCMethod; import serp.bytecode.Code; import serp.bytecode.JumpInstruction; import serp.bytecode.Project; import serp.util.Strings; /** * Default implementation of the {@link ProxyManager} interface. * * @author Abe White */ public class ProxyManagerImpl implements ProxyManager { private static final String PROXY_SUFFIX = "$proxy"; private static final Localizer _loc = Localizer.forPackage (ProxyManagerImpl.class); private static long _proxyId = 0L; private static final Map _stdCollections = new HashMap(); private static final Map _stdMaps = new HashMap(); static { _stdCollections.put(Collection.class, ArrayList.class); _stdCollections.put(Set.class, HashSet.class); _stdCollections.put(SortedSet.class, TreeSet.class); _stdCollections.put(List.class, ArrayList.class); _stdCollections.put(Queue.class, LinkedList.class); _stdMaps.put(Map.class, HashMap.class); _stdMaps.put(SortedMap.class, TreeMap.class); } private final Set _unproxyable = new HashSet(); private final Map _proxies = new NullSafeConcurrentHashMap(); private boolean _trackChanges = true; private boolean _assertType = false; private boolean _delayedCollectionLoading = false; public ProxyManagerImpl() { _unproxyable.add(TimeZone.class.getName()); } /** * Whether proxies produced by this factory will use {@link ChangeTracker}s * to try to cut down on data store operations at the cost of some extra * bookkeeping overhead. Defaults to true. */ public boolean getTrackChanges() { return _trackChanges; } /** * Whether proxies produced by this factory will use {@link ChangeTracker}s * to try to cut down on data store operations at the cost of some extra * bookkeeping overhead. Defaults to true. */ public void setTrackChanges(boolean track) { _trackChanges = track; } /** * Whether to perform runtime checks to ensure that all elements * added to collection and map proxies are the proper element/key/value * type as defined by the metadata. Defaults to false. */ public boolean getAssertAllowedType() { return _assertType; } /** * Whether to perform runtime checks to ensure that all elements * added to collection and map proxies are the proper element/key/value * type as defined by the metadata. Defaults to false. */ public void setAssertAllowedType(boolean assertType) { _assertType = assertType; } /** * Whether loading of collections should be delayed until an operation * is performed that requires them to be loaded. This property only * applies to proxies that implement java.util.Collection (ie. not arrays * or maps). Defaults to false. * @return */ public boolean getDelayCollectionLoading() { return _delayedCollectionLoading; } /** * Whether loading of collections should be delayed until an operation * is performed that requires them to be loaded. Defaults to false. */ public void setDelayCollectionLoading(boolean delay) { _delayedCollectionLoading = delay; } /** * Return a mutable view of class names we know cannot be proxied * correctly by this manager. */ public Collection getUnproxyable() { return _unproxyable; } /** * Provided for auto-configuration. Add the given semicolon-separated * class names to the set of class names we know cannot be proxied correctly * by this manager. */ public void setUnproxyable(String clsNames) { if (clsNames != null) _unproxyable.addAll(Arrays.asList(Strings.split(clsNames, ";", 0))); } public Object copyArray(Object orig) { if (orig == null) return null; try { int length = Array.getLength(orig); Object array = Array.newInstance(orig.getClass(). getComponentType(), length); System.arraycopy(orig, 0, array, 0, length); return array; } catch (Exception e) { throw new UnsupportedException(_loc.get("bad-array", e.getMessage()), e); } } public Collection copyCollection(Collection orig) { if (orig == null) return null; if (orig instanceof Proxy) return (Collection) ((Proxy) orig).copy(orig); ProxyCollection proxy = getFactoryProxyCollection(orig.getClass()); return (Collection) proxy.copy(orig); } public Proxy newCollectionProxy(Class type, Class elementType, Comparator compare, boolean autoOff) { type = toProxyableCollectionType(type); ProxyCollection proxy = getFactoryProxyCollection(type); return proxy.newInstance((_assertType) ? elementType : null, compare, _trackChanges, autoOff); } public Map copyMap(Map orig) { if (orig == null) return null; if (orig instanceof Proxy) return (Map) ((Proxy) orig).copy(orig); ProxyMap proxy = getFactoryProxyMap(orig.getClass()); return (Map) proxy.copy(orig); } public Proxy newMapProxy(Class type, Class keyType, Class elementType, Comparator compare,boolean autoOff) { type = toProxyableMapType(type); ProxyMap proxy = getFactoryProxyMap(type); return proxy.newInstance((_assertType) ? keyType : null, (_assertType) ? elementType : null, compare, _trackChanges, autoOff); } public Date copyDate(Date orig) { if (orig == null) return null; if (orig instanceof Proxy) return (Date) ((Proxy) orig).copy(orig); ProxyDate proxy = getFactoryProxyDate(orig.getClass()); return (Date) proxy.copy(orig); } public Proxy newDateProxy(Class type) { ProxyDate proxy = getFactoryProxyDate(type); return proxy.newInstance(); } public Calendar copyCalendar(Calendar orig) { if (orig == null) return null; if (orig instanceof Proxy) return (Calendar) ((Proxy) orig).copy(orig); ProxyCalendar proxy = getFactoryProxyCalendar(orig.getClass()); return (Calendar) proxy.copy(orig); } public Proxy newCalendarProxy(Class type, TimeZone zone) { if (type == Calendar.class) type = GregorianCalendar.class; ProxyCalendar proxy = getFactoryProxyCalendar(type); ProxyCalendar cal = proxy.newInstance(); if (zone != null) ((Calendar) cal).setTimeZone(zone); return cal; } public Object copyCustom(Object orig) { if (orig == null) return null; if (orig instanceof Proxy) return ((Proxy) orig).copy(orig); if (ImplHelper.isManageable(orig)) return null; if (orig instanceof Collection) return copyCollection((Collection) orig); if (orig instanceof Map) return copyMap((Map) orig); if (orig instanceof Date) return copyDate((Date) orig); if (orig instanceof Calendar) return copyCalendar((Calendar) orig); ProxyBean proxy = getFactoryProxyBean(orig); return (proxy == null) ? null : proxy.copy(orig); } public Proxy newCustomProxy(Object orig, boolean autoOff) { if (orig == null) return null; if (orig instanceof Proxy) return (Proxy) orig; if (ImplHelper.isManageable(orig)) return null; if (orig instanceof Collection) { Comparator comp = (orig instanceof SortedSet) ? ((SortedSet) orig).comparator() : null; Collection c = (Collection) newCollectionProxy(orig.getClass(), null, comp, autoOff); c.addAll((Collection) orig); return (Proxy) c; } if (orig instanceof Map) { Comparator comp = (orig instanceof SortedMap) ? ((SortedMap) orig).comparator() : null; Map m = (Map) newMapProxy(orig.getClass(), null, null, comp, autoOff); m.putAll((Map) orig); return (Proxy) m; } if (orig instanceof Date) { Date d = (Date) newDateProxy(orig.getClass()); d.setTime(((Date) orig).getTime()); if (orig instanceof Timestamp) ((Timestamp) d).setNanos(((Timestamp) orig).getNanos()); return (Proxy) d; } if (orig instanceof Calendar) { Calendar c = (Calendar) newCalendarProxy(orig.getClass(), ((Calendar) orig).getTimeZone()); c.setTimeInMillis(((Calendar) orig).getTimeInMillis()); return (Proxy) c; } ProxyBean proxy = getFactoryProxyBean(orig); return (proxy == null) ? null : proxy.newInstance(orig); } /** * Return the concrete type for proxying. */ protected Class toProxyableCollectionType(Class type) { if (type.getName().endsWith(PROXY_SUFFIX)) type = type.getSuperclass(); else if (type.isInterface()) { type = toConcreteType(type, _stdCollections); if (type == null) throw new UnsupportedException(_loc.get("no-proxy-intf", type)); } else if (Modifier.isAbstract(type.getModifiers())) throw new UnsupportedException(_loc.get("no-proxy-abstract", type)); return type; } /** * Return the concrete type for proxying. */ protected Class toProxyableMapType(Class type) { if (type.getName().endsWith(PROXY_SUFFIX)) type = type.getSuperclass(); else if (type.isInterface()) { type = toConcreteType(type, _stdMaps); if (type == null) throw new UnsupportedException(_loc.get("no-proxy-intf", type)); } else if (Modifier.isAbstract(type.getModifiers())) throw new UnsupportedException(_loc.get("no-proxy-abstract", type)); return type; } /** * Locate a concrete type to proxy for the given collection interface. */ private static Class toConcreteType(Class intf, Map concretes) { Class concrete = (Class) concretes.get(intf); if (concrete != null) return concrete; Class[] intfs = intf.getInterfaces(); for (int i = 0; i < intfs.length; i++) { concrete = toConcreteType(intfs[i], concretes); if (concrete != null) return concrete; } return null; } /** * Return the cached factory proxy for the given collection type. */ private ProxyCollection getFactoryProxyCollection(Class type) { // we don't lock here; ok if two proxies get generated for same type ProxyCollection proxy = (ProxyCollection) _proxies.get(type); if (proxy == null) { ClassLoader l = GeneratedClasses.getMostDerivedLoader(type, ProxyCollection.class); Class pcls = loadBuildTimeProxy(type, l); if (pcls == null) pcls = GeneratedClasses.loadBCClass( generateProxyCollectionBytecode(type, true), l); proxy = (ProxyCollection) instantiateProxy(pcls, null, null); _proxies.put(type, proxy); } return proxy; } /** * Return the cached factory proxy for the given map type. */ private ProxyMap getFactoryProxyMap(Class type) { // we don't lock here; ok if two proxies get generated for same type ProxyMap proxy = (ProxyMap) _proxies.get(type); if (proxy == null) { ClassLoader l = GeneratedClasses.getMostDerivedLoader(type, ProxyMap.class); Class pcls = loadBuildTimeProxy(type, l); if (pcls == null) pcls = GeneratedClasses.loadBCClass( generateProxyMapBytecode(type, true), l); proxy = (ProxyMap) instantiateProxy(pcls, null, null); _proxies.put(type, proxy); } return proxy; } /** * Return the cached factory proxy for the given date type. */ private ProxyDate getFactoryProxyDate(Class type) { // we don't lock here; ok if two proxies get generated for same type ProxyDate proxy = (ProxyDate) _proxies.get(type); if (proxy == null) { ClassLoader l = GeneratedClasses.getMostDerivedLoader(type, ProxyDate.class); Class pcls = loadBuildTimeProxy(type, l); if (pcls == null) pcls = GeneratedClasses.loadBCClass( generateProxyDateBytecode(type, true), l); proxy = (ProxyDate) instantiateProxy(pcls, null, null); _proxies.put(type, proxy); } return proxy; } /** * Return the cached factory proxy for the given calendar type. */ private ProxyCalendar getFactoryProxyCalendar(Class type) { // we don't lock here; ok if two proxies get generated for same type ProxyCalendar proxy = (ProxyCalendar) _proxies.get(type); if (proxy == null) { ClassLoader l = GeneratedClasses.getMostDerivedLoader(type, ProxyCalendar.class); Class pcls = loadBuildTimeProxy(type, l); if (pcls == null) pcls = GeneratedClasses.loadBCClass( generateProxyCalendarBytecode(type, true), l); proxy = (ProxyCalendar) instantiateProxy(pcls, null, null); _proxies.put(type, proxy); } return proxy; } /** * Return the cached factory proxy for the given bean type. */ private ProxyBean getFactoryProxyBean(Object orig) { final Class type = orig.getClass(); if (isUnproxyable(type)) return null; // we don't lock here; ok if two proxies get generated for same type ProxyBean proxy = (ProxyBean) _proxies.get(type); if (proxy == null && !_proxies.containsKey(type)) { ClassLoader l = GeneratedClasses.getMostDerivedLoader(type, ProxyBean.class); Class pcls = loadBuildTimeProxy(type, l); if (pcls == null) { // TODO Move this to J2DOPrivHelper? BCClass bc = AccessController .doPrivileged(new PrivilegedAction() { public BCClass run() { return generateProxyBeanBytecode(type, true); } }); if (bc != null) pcls = GeneratedClasses.loadBCClass(bc, l); } if (pcls != null) proxy = (ProxyBean) instantiateProxy(pcls, findCopyConstructor(type), new Object[] {orig}); _proxies.put(type, proxy); } return proxy; } /** * Return whether the given type is known to be unproxyable. */ protected boolean isUnproxyable(Class type) { for (; type != null && type != Object.class; type = type.getSuperclass()) { if (_unproxyable.contains(type.getName())) return true; } return false; } /** * Load the proxy class generated at build time for the given type, * returning null if none exists. */ protected Class loadBuildTimeProxy(Class type, ClassLoader loader) { try { Class proxyClass = null; if (_delayedCollectionLoading) { proxyClass = loadDelayedProxy(type); if (proxyClass != null) { return proxyClass; } } return Class.forName(getProxyClassName(type, false), true, loader); } catch (Throwable t) { return null; } } protected Class loadDelayedProxy(Class type) { if (type.equals(java.util.ArrayList.class)) { return org.apache.openjpa.util.DelayedArrayListProxy.class; } if (type.equals(java.util.HashSet.class)) { return org.apache.openjpa.util.DelayedHashSetProxy.class; } if (type.equals(java.util.LinkedList.class)) { return org.apache.openjpa.util.DelayedLinkedListProxy.class; } if (type.equals(java.util.Vector.class)) { return org.apache.openjpa.util.DelayedVectorProxy.class; } if (type.equals(java.util.LinkedHashSet.class)) { return org.apache.openjpa.util.DelayedLinkedHashSetProxy.class; } if (type.equals(java.util.SortedSet.class) || type.equals(java.util.TreeSet.class)) { return org.apache.openjpa.util.DelayedTreeSetProxy.class; } if (type.equals(java.util.PriorityQueue.class)) { return org.apache.openjpa.util.DelayedPriorityQueueProxy.class; } return null; } /** * Instantiate the given proxy class. */ private Proxy instantiateProxy(Class cls, Constructor cons, Object[] args) { try { if (cons != null) return (Proxy) cls.getConstructor(cons.getParameterTypes()). newInstance(args); return (Proxy) AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(cls)); } catch (InstantiationException ie) { throw new UnsupportedException(_loc.get("cant-newinstance", cls.getSuperclass().getName())); } catch (PrivilegedActionException pae) { Exception e = pae.getException(); if (e instanceof InstantiationException) throw new UnsupportedException(_loc.get("cant-newinstance", cls.getSuperclass().getName())); else throw new GeneralException(cls.getName()).setCause(e); } catch (Throwable t) { throw new GeneralException(cls.getName()).setCause(t); } } /** * Generate the bytecode for a collection proxy for the given type. */ protected BCClass generateProxyCollectionBytecode(Class type, boolean runtime) { assertNotFinal(type); Project project = new Project(); BCClass bc = AccessController.doPrivileged(J2DoPrivHelper .loadProjectClassAction(project, getProxyClassName(type, runtime))); bc.setSuperclass(type); bc.declareInterface(ProxyCollection.class); delegateConstructors(bc, type); addProxyMethods(bc, false); addProxyCollectionMethods(bc, type); proxyRecognizedMethods(bc, type, ProxyCollections.class, ProxyCollection.class); proxySetters(bc, type); addWriteReplaceMethod(bc, runtime); return bc; } /** * Return the name of the proxy class to generate for the given type. */ private static String getProxyClassName(Class type, boolean runtime) { String id = (runtime) ? "$" + nextProxyId() : ""; return Strings.getPackageName(ProxyManagerImpl.class) + "." + type.getName().replace('.', '$') + id + PROXY_SUFFIX; } /** * Throw appropriate exception if the given type is final. */ private static void assertNotFinal(Class type) { if (Modifier.isFinal(type.getModifiers())) throw new UnsupportedException(_loc.get("no-proxy-final", type)); } /** * Generate the bytecode for a map proxy for the given type. */ protected BCClass generateProxyMapBytecode(Class type, boolean runtime) { assertNotFinal(type); Project project = new Project(); BCClass bc = AccessController.doPrivileged(J2DoPrivHelper .loadProjectClassAction(project, getProxyClassName(type, runtime))); bc.setSuperclass(type); bc.declareInterface(ProxyMap.class); delegateConstructors(bc, type); addProxyMethods(bc, false); addProxyMapMethods(bc, type); Class mapProxyClassType = ConcurrentMap.class.isAssignableFrom(type) ? ProxyConcurrentMaps.class : ProxyMaps.class; proxyRecognizedMethods(bc, type, mapProxyClassType, ProxyMap.class); proxySetters(bc, type); addWriteReplaceMethod(bc, runtime); return bc; } /** * Generate the bytecode for a date proxy for the given type. */ protected BCClass generateProxyDateBytecode(Class type, boolean runtime) { assertNotFinal(type); Project project = new Project(); BCClass bc = AccessController.doPrivileged(J2DoPrivHelper .loadProjectClassAction(project, getProxyClassName(type, runtime))); bc.setSuperclass(type); bc.declareInterface(ProxyDate.class); delegateConstructors(bc, type); addProxyMethods(bc, true); addProxyDateMethods(bc, type); proxySetters(bc, type); addWriteReplaceMethod(bc, runtime); return bc; } /** * Generate the bytecode for a calendar proxy for the given type. */ protected BCClass generateProxyCalendarBytecode(Class type, boolean runtime) { assertNotFinal(type); Project project = new Project(); BCClass bc = AccessController.doPrivileged(J2DoPrivHelper .loadProjectClassAction(project, getProxyClassName(type, runtime))); bc.setSuperclass(type); bc.declareInterface(ProxyCalendar.class); delegateConstructors(bc, type); addProxyMethods(bc, true); addProxyCalendarMethods(bc, type); proxySetters(bc, type); addWriteReplaceMethod(bc, runtime); return bc; } /** * Generate the bytecode for a bean proxy for the given type. */ protected BCClass generateProxyBeanBytecode(Class type, boolean runtime) { if (Modifier.isFinal(type.getModifiers())) return null; if (ImplHelper.isManagedType(null, type)) return null; // we can only generate a valid proxy if there is a copy constructor // or a default constructor Constructor cons = findCopyConstructor(type); if (cons == null) { Constructor[] cs = type.getConstructors(); for (int i = 0; cons == null && i < cs.length; i++) if (cs[i].getParameterTypes().length == 0) cons = cs[i]; if (cons == null) return null; } Project project = new Project(); BCClass bc = AccessController.doPrivileged(J2DoPrivHelper .loadProjectClassAction(project, getProxyClassName(type, runtime))); bc.setSuperclass(type); bc.declareInterface(ProxyBean.class); delegateConstructors(bc, type); addProxyMethods(bc, true); addProxyBeanMethods(bc, type, cons); if (!proxySetters(bc, type)) return null; addWriteReplaceMethod(bc, runtime); return bc; } /** * Create pass-through constructors to base type. */ private void delegateConstructors(BCClass bc, Class type) { Constructor[] cons = type.getConstructors(); Class[] params; BCMethod m; Code code; for (int i = 0; i < cons.length; i++) { params = cons[i].getParameterTypes(); m = bc.declareMethod("", void.class, params); m.makePublic(); code = m.getCode(true); code.aload().setThis(); for (int j = 0; j < params.length; j++) code.xload().setParam(j).setType(params[j]); code.invokespecial().setMethod(cons[i]); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } } /** * Implement the methods in the {@link Proxy} interface, with the exception * of {@link Proxy#copy}. * * @param changeTracker whether to implement a null change tracker; if false * the change tracker method is left unimplemented */ private void addProxyMethods(BCClass bc, boolean changeTracker) { BCField sm = bc.declareField("sm", OpenJPAStateManager.class); sm.setTransient(true); BCField field = bc.declareField("field", int.class); field.setTransient(true); BCMethod m = bc.declareMethod("setOwner", void.class, new Class[] { OpenJPAStateManager.class, int.class }); m.makePublic(); Code code = m.getCode(true); code.aload().setThis(); code.aload().setParam(0); code.putfield().setField(sm); code.aload().setThis(); code.iload().setParam(1); code.putfield().setField(field); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); m = bc.declareMethod("getOwner", OpenJPAStateManager.class, null); m.makePublic(); code = m.getCode(true); code.aload().setThis(); code.getfield().setField(sm); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); m = bc.declareMethod("getOwnerField", int.class, null); m.makePublic(); code = m.getCode(true); code.aload().setThis(); code.getfield().setField(field); code.ireturn(); code.calculateMaxStack(); code.calculateMaxLocals(); /* * clone (return detached proxy object) * Note: This method is only being provided to satisfy a quirk with * the IBM JDK -- while comparing Calendar objects, the clone() method * was invoked. So, we are now overriding the clone() method so as to * provide a detached proxy object (null out the StateManager). */ m = bc.declareMethod("clone", Object.class, null); m.makePublic(); code = m.getCode(true); code.aload().setThis(); code.invokespecial().setMethod(bc.getSuperclassType(), "clone", Object.class, null); code.checkcast().setType(Proxy.class); int other = code.getNextLocalsIndex(); code.astore().setLocal(other); code.aload().setLocal(other); code.constant().setNull(); code.constant().setValue(0); code.invokeinterface().setMethod(Proxy.class, "setOwner", void.class, new Class[] { OpenJPAStateManager.class, int.class }); code.aload().setLocal(other); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); if (changeTracker) { m = bc.declareMethod("getChangeTracker", ChangeTracker.class, null); m.makePublic(); code = m.getCode(true); code.constant().setNull(); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } } /** * Implement the methods in the {@link ProxyCollection} interface. */ private void addProxyCollectionMethods(BCClass bc, Class type) { // change tracker BCField changeTracker = bc.declareField("changeTracker", CollectionChangeTracker.class); changeTracker.setTransient(true); BCMethod m = bc.declareMethod("getChangeTracker", ChangeTracker.class, null); m.makePublic(); Code code = m.getCode(true); code.aload().setThis(); code.getfield().setField(changeTracker); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // collection copy Constructor cons = findCopyConstructor(type); if (cons == null && SortedSet.class.isAssignableFrom(type)) cons = findComparatorConstructor(type); Class[] params = (cons == null) ? new Class[0] : cons.getParameterTypes(); m = bc.declareMethod("copy", Object.class, new Class[] {Object.class}); m.makePublic(); code = m.getCode(true); code.anew().setType(type); code.dup(); if (params.length == 1) { code.aload().setParam(0); if (params[0] == Comparator.class) { code.checkcast().setType(SortedSet.class); code.invokeinterface().setMethod(SortedSet.class, "comparator", Comparator.class, null); } else code.checkcast().setType(params[0]); } code.invokespecial().setMethod(type, "", void.class, params); if (params.length == 0 || params[0] == Comparator.class) { code.dup(); code.aload().setParam(0); code.checkcast().setType(Collection.class); code.invokevirtual().setMethod(type, "addAll", boolean.class, new Class[] { Collection.class }); code.pop(); } code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // element type BCField elementType = bc.declareField("elementType", Class.class); elementType.setTransient(true); m = bc.declareMethod("getElementType", Class.class, null); m.makePublic(); code = m.getCode(true); code.aload().setThis(); code.getfield().setField(elementType); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // new instance factory m = bc.declareMethod("newInstance", ProxyCollection.class, new Class[] { Class.class, Comparator.class, boolean.class, boolean.class }); m.makePublic(); code = m.getCode(true); code.anew().setType(bc); code.dup(); cons = findComparatorConstructor(type); params = (cons == null) ? new Class[0] : cons.getParameterTypes(); if (params.length == 1) code.aload().setParam(1); code.invokespecial().setMethod("", void.class, params); int ret = code.getNextLocalsIndex(); code.astore().setLocal(ret); // set element type code.aload().setLocal(ret); code.aload().setParam(0); code.putfield().setField(elementType); // create change tracker and set it code.iload().setParam(2); JumpInstruction ifins = code.ifeq(); code.aload().setLocal(ret); code.anew().setType(CollectionChangeTrackerImpl.class); code.dup(); code.aload().setLocal(ret); code.constant().setValue(allowsDuplicates(type)); code.constant().setValue(isOrdered(type)); code.aload().setParam(3); code.invokespecial().setMethod(CollectionChangeTrackerImpl.class, "", void.class, new Class[] { Collection.class, boolean.class, boolean.class, boolean.class }); code.putfield().setField(changeTracker); ifins.setTarget(code.aload().setLocal(ret)); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Return whether the given collection type allows duplicates. */ protected boolean allowsDuplicates(Class type) { return !Set.class.isAssignableFrom(type); } /** * Return whether the given collection type maintains an artificial * ordering. */ protected boolean isOrdered(Class type) { return List.class.isAssignableFrom(type) || "java.util.LinkedHashSet".equals(type.getName()); } /** * Implement the methods in the {@link ProxyMap} interface. */ private void addProxyMapMethods(BCClass bc, Class type) { // change tracker BCField changeTracker = bc.declareField("changeTracker", MapChangeTracker.class); changeTracker.setTransient(true); BCMethod m = bc.declareMethod("getChangeTracker", ChangeTracker.class, null); m.makePublic(); Code code = m.getCode(true); code.aload().setThis(); code.getfield().setField(changeTracker); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // map copy Constructor cons = findCopyConstructor(type); if (cons == null && SortedMap.class.isAssignableFrom(type)) cons = findComparatorConstructor(type); Class[] params = (cons == null) ? new Class[0] : cons.getParameterTypes(); m = bc.declareMethod("copy", Object.class, new Class[] {Object.class}); m.makePublic(); code = m.getCode(true); code.anew().setType(type); code.dup(); if (params.length == 1) { code.aload().setParam(0); if (params[0] == Comparator.class) { code.checkcast().setType(SortedMap.class); code.invokeinterface().setMethod(SortedMap.class, "comparator", Comparator.class, null); } else code.checkcast().setType(params[0]); } code.invokespecial().setMethod(type, "", void.class, params); if (params.length == 0 || params[0] == Comparator.class) { code.dup(); code.aload().setParam(0); code.checkcast().setType(Map.class); code.invokevirtual().setMethod(type, "putAll", void.class, new Class[] { Map.class }); } code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // key type BCField keyType = bc.declareField("keyType", Class.class); keyType.setTransient(true); m = bc.declareMethod("getKeyType", Class.class, null); m.makePublic(); code = m.getCode(true); code.aload().setThis(); code.getfield().setField(keyType); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // value type BCField valueType = bc.declareField("valueType", Class.class); valueType.setTransient(true); m = bc.declareMethod("getValueType", Class.class, null); m.makePublic(); code = m.getCode(true); code.aload().setThis(); code.getfield().setField(valueType); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // new instance factory m = bc.declareMethod("newInstance", ProxyMap.class, new Class[] { Class.class, Class.class, Comparator.class, boolean.class,boolean.class }); m.makePublic(); code = m.getCode(true); code.anew().setType(bc); code.dup(); cons = findComparatorConstructor(type); params = (cons == null) ? new Class[0] : cons.getParameterTypes(); if (params.length == 1) code.aload().setParam(2); code.invokespecial().setMethod("", void.class, params); int ret = code.getNextLocalsIndex(); code.astore().setLocal(ret); // set key and value types code.aload().setLocal(ret); code.aload().setParam(0); code.putfield().setField(keyType); code.aload().setLocal(ret); code.aload().setParam(1); code.putfield().setField(valueType); // create change tracker and set it code.iload().setParam(3); JumpInstruction ifins = code.ifeq(); code.aload().setLocal(ret); code.anew().setType(MapChangeTrackerImpl.class); code.dup(); code.aload().setLocal(ret); code.aload().setParam(4); code.invokespecial().setMethod(MapChangeTrackerImpl.class, "", void.class, new Class[] { Map.class, boolean.class }); code.putfield().setField(changeTracker); ifins.setTarget(code.aload().setLocal(ret)); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Implement the methods in the {@link ProxyDate} interface. */ private void addProxyDateMethods(BCClass bc, Class type) { boolean hasDefaultCons = bc.getDeclaredMethod("", (Class[]) null) != null; boolean hasMillisCons = bc.getDeclaredMethod("", new Class[] { long.class }) != null; if (!hasDefaultCons && !hasMillisCons) throw new UnsupportedException(_loc.get("no-date-cons", type)); // add a default constructor that delegates to the millis constructor BCMethod m; Code code; if (!hasDefaultCons) { m = bc.declareMethod("", void.class, null); m.makePublic(); code = m.getCode(true); code.aload().setThis(); code.invokestatic().setMethod(System.class, "currentTimeMillis", long.class, null); code.invokespecial().setMethod(type, "", void.class, new Class[] { long.class }); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } // date copy Constructor cons = findCopyConstructor(type); Class[] params; if (cons != null) params = cons.getParameterTypes(); else if (hasMillisCons) params = new Class[] { long.class }; else params = new Class[0]; m = bc.declareMethod("copy", Object.class, new Class[] {Object.class}); m.makePublic(); code = m.getCode(true); code.anew().setType(type); code.dup(); if (params.length == 1) { if (params[0] == long.class) { code.aload().setParam(0); code.checkcast().setType(Date.class); code.invokevirtual().setMethod(Date.class, "getTime", long.class, null); } else { code.aload().setParam(0); code.checkcast().setType(params[0]); } } code.invokespecial().setMethod(type, "", void.class, params); if (params.length == 0) { code.dup(); code.aload().setParam(0); code.checkcast().setType(Date.class); code.invokevirtual().setMethod(Date.class, "getTime", long.class, null); code.invokevirtual().setMethod(type, "setTime", void.class, new Class[] { long.class }); } if ((params.length == 0 || params[0] == long.class) && Timestamp.class.isAssignableFrom(type)) { code.dup(); code.aload().setParam(0); code.checkcast().setType(Timestamp.class); code.invokevirtual().setMethod(Timestamp.class, "getNanos", int.class, null); code.invokevirtual().setMethod(type, "setNanos", void.class, new Class[] { int.class }); } code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // new instance factory m = bc.declareMethod("newInstance", ProxyDate.class, null); m.makePublic(); code = m.getCode(true); code.anew().setType(bc); code.dup(); code.invokespecial().setMethod("", void.class, null); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Implement the methods in the {@link ProxyCalendar} interface. */ private void addProxyCalendarMethods(BCClass bc, Class type) { // calendar copy Constructor cons = findCopyConstructor(type); Class[] params = (cons == null) ? new Class[0] : cons.getParameterTypes(); BCMethod m = bc.declareMethod("copy", Object.class, new Class[] {Object.class}); m.makePublic(); Code code = m.getCode(true); code.anew().setType(type); code.dup(); if (params.length == 1) { code.aload().setParam(0); code.checkcast().setType(params[0]); } code.invokespecial().setMethod(type, "", void.class, params); if (params.length == 0) { code.dup(); code.aload().setParam(0); code.checkcast().setType(Calendar.class); code.invokevirtual().setMethod(Calendar.class, "getTimeInMillis", long.class, null); code.invokevirtual().setMethod(type, "setTimeInMillis", void.class, new Class[] { long.class }); code.dup(); code.aload().setParam(0); code.checkcast().setType(Calendar.class); code.invokevirtual().setMethod(Calendar.class, "isLenient", boolean.class, null); code.invokevirtual().setMethod(type, "setLenient", void.class, new Class[] { boolean.class }); code.dup(); code.aload().setParam(0); code.checkcast().setType(Calendar.class); code.invokevirtual().setMethod(Calendar.class, "getFirstDayOfWeek", int.class, null); code.invokevirtual().setMethod(type, "setFirstDayOfWeek", void.class, new Class[] { int.class }); code.dup(); code.aload().setParam(0); code.checkcast().setType(Calendar.class); code.invokevirtual().setMethod(Calendar.class, "getMinimalDaysInFirstWeek", int.class, null); code.invokevirtual().setMethod(type, "setMinimalDaysInFirstWeek", void.class, new Class[] { int.class }); code.dup(); code.aload().setParam(0); code.checkcast().setType(Calendar.class); code.invokevirtual().setMethod(Calendar.class, "getTimeZone", TimeZone.class, null); code.invokevirtual().setMethod(type, "setTimeZone", void.class, new Class[] { TimeZone.class }); } code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // new instance factory m = bc.declareMethod("newInstance", ProxyCalendar.class, null); m.makePublic(); code = m.getCode(true); code.anew().setType(bc); code.dup(); code.invokespecial().setMethod("", void.class, null); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // proxy the protected computeFields method b/c it is called on // mutate, and some setters are final and therefore not proxyable m = bc.declareMethod("computeFields", void.class, null); m.makeProtected(); code = m.getCode(true); code.aload().setThis(); code.constant().setValue(true); code.invokestatic().setMethod(Proxies.class, "dirty", void.class, new Class[] { Proxy.class, boolean.class }); code.aload().setThis(); code.invokespecial().setMethod(type, "computeFields", void.class, null); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Implement the methods in the {@link ProxyBean} interface. */ private void addProxyBeanMethods(BCClass bc, Class type, Constructor cons) { // bean copy BCMethod m = bc.declareMethod("copy", Object.class, new Class[] { Object.class }); m.makePublic(); Code code = m.getCode(true); code.anew().setType(type); code.dup(); Class[] params = cons.getParameterTypes(); if (params.length == 1) { code.aload().setParam(0); code.checkcast().setType(params[0]); } code.invokespecial().setMethod(cons); if (params.length == 0) copyProperties(type, code); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // new instance factory m = bc.declareMethod("newInstance", ProxyBean.class, new Class[] { Object.class }); m.makePublic(); code = m.getCode(true); code.anew().setType(bc); code.dup(); if (params.length == 1) { code.aload().setParam(0); code.checkcast().setType(params[0]); } code.invokespecial().setMethod("", void.class, params); if (params.length == 0) copyProperties(type, code); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Copy bean properties. Called with the copy object on the stack. Must * return with the copy object on the stack. */ private void copyProperties(Class type, Code code) { int copy = code.getNextLocalsIndex(); code.astore().setLocal(copy); Method[] meths = type.getMethods(); Method getter; int mods; for (int i = 0; i < meths.length; i++) { mods = meths[i].getModifiers(); if (!Modifier.isPublic(mods) || Modifier.isStatic(mods)) continue; if (!startsWith(meths[i].getName(), "set") || meths[i].getParameterTypes().length != 1) continue; getter = findGetter(type, meths[i]); if (getter == null) continue; // copy.setXXX(orig.getXXX()); code.aload().setLocal(copy); code.aload().setParam(0); code.checkcast().setType(type); code.invokevirtual().setMethod(getter); code.invokevirtual().setMethod(meths[i]); } code.aload().setLocal(copy); } /** * Proxy recognized methods to invoke helpers in given helper class. */ private void proxyRecognizedMethods(BCClass bc, Class type, Class helper, Class proxyType) { Method[] meths = type.getMethods(); Class[] params; Class[] afterParams; Method match; Method after; for (int i = 0; i < meths.length; i++) { params = toHelperParameters(meths[i].getParameterTypes(), proxyType); // first check for overriding method try { match = helper.getMethod(meths[i].getName(), params); proxyOverrideMethod(bc, meths[i], match, params); continue; } catch (NoSuchMethodException nsme) { } catch (Exception e) { throw new GeneralException(e); } // check for before and after methods, either of which may not // exist match = null; try { match = helper.getMethod("before" + StringUtils.capitalize(meths[i].getName()), params); } catch (NoSuchMethodException nsme) { } catch (Exception e) { throw new GeneralException(e); } after = null; afterParams = null; try { afterParams = toHelperAfterParameters(params, meths[i].getReturnType(), (match == null) ? void.class : match.getReturnType()); after = helper.getMethod("after" + StringUtils.capitalize(meths[i].getName()), afterParams); } catch (NoSuchMethodException nsme) { } catch (Exception e) { throw new GeneralException(e); } if (match != null || after != null) proxyBeforeAfterMethod(bc, type, meths[i], match, params, after, afterParams); } } /** * Return the parameter types to the corresponding helper class method. */ private static Class[] toHelperParameters(Class[] cls, Class helper) { Class[] params = new Class[cls.length + 1]; params[0] = helper; System.arraycopy(cls, 0, params, 1, cls.length); return params; } /** * Return the parameter types to the corresponding helper class "after" * method. */ private static Class[] toHelperAfterParameters(Class[] cls, Class ret, Class beforeRet) { if (ret == void.class && beforeRet == void.class) return cls; int len = cls.length; if (ret != void.class) len++; if (beforeRet != void.class) len++; Class[] params = new Class[len]; System.arraycopy(cls, 0, params, 0, cls.length); int pos = cls.length; if (ret != void.class) params[pos++] = ret; if (beforeRet != void.class) params[pos++] = beforeRet; return params; } /** * Proxy setter methods of the given type. * * @return true if we find any setters, false otherwise */ private boolean proxySetters(BCClass bc, Class type) { Method[] meths = type.getMethods(); int setters = 0; for (int i = 0; i < meths.length; i++) { if (isSetter(meths[i]) && !Modifier.isFinal(meths[i].getModifiers()) && bc.getDeclaredMethod(meths[i].getName(), meths[i].getParameterTypes()) == null) { setters++; proxySetter(bc, type, meths[i]); } } return setters > 0; } /** * Proxy the given method with one that overrides it by calling into the * given helper. */ private void proxyOverrideMethod(BCClass bc, Method meth, Method helper, Class[] params) { BCMethod m = bc.declareMethod(meth.getName(), meth.getReturnType(), meth.getParameterTypes()); m.makePublic(); Code code = m.getCode(true); code.aload().setThis(); for (int i = 1; i < params.length; i++) code.xload().setParam(i - 1).setType(params[i]); code.invokestatic().setMethod(helper); code.xreturn().setType(meth.getReturnType()); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Proxy the given method with one that overrides it by calling into the * given helper. */ private void proxyBeforeAfterMethod(BCClass bc, Class type, Method meth, Method before, Class[] params, Method after, Class[] afterParams) { BCMethod m = bc.declareMethod(meth.getName(), meth.getReturnType(), meth.getParameterTypes()); m.makePublic(); Code code = m.getCode(true); // invoke before int beforeRet = -1; if (before != null) { code.aload().setThis(); for (int i = 1; i < params.length; i++) code.xload().setParam(i - 1).setType(params[i]); code.invokestatic().setMethod(before); if (after != null && before.getReturnType() != void.class) { beforeRet = code.getNextLocalsIndex(); code.xstore().setLocal(beforeRet). setType(before.getReturnType()); } } // invoke super code.aload().setThis(); for (int i = 1; i < params.length; i++) code.xload().setParam(i - 1).setType(params[i]); code.invokespecial().setMethod(type, meth.getName(), meth.getReturnType(), meth.getParameterTypes()); // invoke after if (after != null) { int ret = -1; if (meth.getReturnType() != void.class) { ret = code.getNextLocalsIndex(); code.xstore().setLocal(ret).setType(meth.getReturnType()); } code.aload().setThis(); for (int i = 1; i < params.length; i++) code.xload().setParam(i - 1).setType(params[i]); if (ret != -1) code.xload().setLocal(ret).setType(meth.getReturnType()); if (beforeRet != -1) code.xload().setLocal(beforeRet). setType(before.getReturnType()); code.invokestatic().setMethod(after); } code.xreturn().setType(meth.getReturnType()); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Return whether the given method is a setter. */ protected boolean isSetter(Method meth) { return startsWith(meth.getName(), "set") || startsWith(meth.getName(), "add") || startsWith(meth.getName(), "remove") || startsWith(meth.getName(), "insert") || startsWith(meth.getName(), "clear") || startsWith(meth.getName(), "roll"); // used by Calendar } /** * Return the getter corresponding to the given setter, or null. */ protected Method findGetter(Class type, Method setter) { String name = setter.getName().substring(3); Class param = setter.getParameterTypes()[0]; Method getter; try { getter = type.getMethod("get" + name, (Class[]) null); if (getter.getReturnType().isAssignableFrom(param) || param.isAssignableFrom(getter.getReturnType())) return getter; } catch (NoSuchMethodException nsme) { } catch (Exception e) { throw new GeneralException(e); } if (param == boolean.class || param == Boolean.class) { try { getter = type.getMethod("is" + name, (Class[]) null); if (getter.getReturnType().isAssignableFrom(param) || param.isAssignableFrom(getter.getReturnType())) return getter; } catch (NoSuchMethodException nsme) { } catch (Exception e) { throw new GeneralException(e); } } return null; } /** * Return whether the target string stars with the given token. */ private static boolean startsWith(String str, String token) { return str.startsWith(token) && (str.length() == token.length() || Character.isUpperCase(str.charAt(token.length()))); } /** * Proxy the given setter method to dirty the proxy owner. */ private void proxySetter(BCClass bc, Class type, Method meth) { Class[] params = meth.getParameterTypes(); Class ret = meth.getReturnType(); BCMethod m = bc.declareMethod(meth.getName(), ret, params); m.makePublic(); Code code = m.getCode(true); code.aload().setThis(); code.constant().setValue(true); code.invokestatic().setMethod(Proxies.class, "dirty", void.class, new Class[] { Proxy.class, boolean.class }); code.aload().setThis(); for (int i = 0; i < params.length; i++) code.xload().setParam(i).setType(params[i]); code.invokespecial().setMethod(type, meth.getName(), ret, params); code.xreturn().setType(ret); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Add a writeReplace implementation that serializes to a non-proxy type * unless detached and this is a build-time generated class. */ private void addWriteReplaceMethod(BCClass bc, boolean runtime) { BCMethod m = bc.declareMethod("writeReplace", Object.class, null); m.makeProtected(); m.getExceptions(true).addException(ObjectStreamException.class); Code code = m.getCode(true); code.aload().setThis(); code.constant().setValue(!runtime); code.invokestatic().setMethod(Proxies.class, "writeReplace", Object.class, new Class[] { Proxy.class, boolean.class }); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Create a unique id to avoid proxy class name conflicts. */ private static synchronized long nextProxyId() { return _proxyId++; } /** * Find an appropriate copy constructor for the given type, or return null * if none. */ protected Constructor findCopyConstructor(Class cls) { Constructor[] cons = cls.getConstructors(); Constructor match = null; Class matchParam = null; Class[] params; for (int i = 0; i < cons.length; i++) { params = cons[i].getParameterTypes(); if (params.length != 1) continue; // quit immediately on exact match if (params[0] == cls) return cons[i]; if (params[0].isAssignableFrom(cls) && (matchParam == null || matchParam.isAssignableFrom(params[0]))) { // track most derived collection constructor match = cons[i]; matchParam = params[0]; } } return match; } /** * Return the constructor that takes a comparator for the given type, or * null if none. */ private static Constructor findComparatorConstructor(Class cls) { try { return cls.getConstructor(new Class[] { Comparator.class }); } catch (NoSuchMethodException nsme) { return null; } catch (Exception e) { throw new GeneralException(e); } } /** * Usage: java org.apache.openjpa.util.proxy.ProxyManagerImpl [option]* * <class name>+
* Where the following options are recognized: *
    *
  • -utils/-u <number>: Generate proxies for the standard * java.util collection, map, date, and calendar classes of the given Java * version. Use 4 for Java 1.4, 5 for Java 5, etc.
  • *
* * The main method generates .class files for the proxies to the classes * given on the command line. It writes the generated classes to beside the * ProxyManagerImpl.class file if possible; otherwise it writes to the * current directory. The proxy manager looks for these classes * before generating its own proxies at runtime. */ public static void main(String[] args) throws ClassNotFoundException, IOException { File dir = Files.getClassFile(ProxyManagerImpl.class); dir = (dir == null) ? new File(AccessController.doPrivileged( J2DoPrivHelper.getPropertyAction("user.dir"))) : dir.getParentFile(); Options opts = new Options(); args = opts.setFromCmdLine(args); List types = new ArrayList(); types.addAll(Arrays.asList(args)); int utils = opts.removeIntProperty("utils", "u", 0); if (utils >= 4) { types.addAll(Arrays.asList(new String[] { java.sql.Date.class.getName(), java.sql.Time.class.getName(), java.sql.Timestamp.class.getName(), java.util.ArrayList.class.getName(), java.util.Date.class.getName(), java.util.GregorianCalendar.class.getName(), java.util.HashMap.class.getName(), java.util.HashSet.class.getName(), java.util.Hashtable.class.getName(), java.util.LinkedList.class.getName(), java.util.Properties.class.getName(), java.util.TreeMap.class.getName(), java.util.TreeSet.class.getName(), java.util.Vector.class.getName(), })); } if (utils >= 5) { types.addAll(Arrays.asList(new String[] { "java.util.EnumMap", "java.util.IdentityHashMap", "java.util.LinkedHashMap", "java.util.LinkedHashSet", "java.util.PriorityQueue", })); } final ProxyManagerImpl mgr = new ProxyManagerImpl(); Class cls; BCClass bc; for (int i = 0; i < types.size(); i++) { cls = Class.forName((String) types.get(i)); try { if (Class.forName(getProxyClassName(cls, false), true, GeneratedClasses.getMostDerivedLoader(cls, Proxy.class)) != null) continue; } catch (Throwable t) { // expected if the class hasn't been generated } if (Collection.class.isAssignableFrom(cls)) bc = mgr.generateProxyCollectionBytecode(cls, false); else if (Map.class.isAssignableFrom(cls)) bc = mgr.generateProxyMapBytecode(cls, false); else if (Date.class.isAssignableFrom(cls)) bc = mgr.generateProxyDateBytecode(cls, false); else if (Calendar.class.isAssignableFrom(cls)) bc = mgr.generateProxyCalendarBytecode(cls, false); else { final Class fCls = cls; // TODO Move this to J2DOPrivHelper bc = AccessController .doPrivileged(new PrivilegedAction() { public BCClass run() { return mgr.generateProxyBeanBytecode(fCls, false); } }); } System.out.println(bc.getName()); AsmAdaptor.write(bc, new File(dir, bc.getClassName() + ".class")); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/Serialization.java0000644000000000000000000001533012133327272026451 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.OutputStream; import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.MultiClassLoader; /** * Helper class to serialize and deserialize persistent objects, * subtituting oids into the serialized stream and subtituting the persistent * objects back during deserialization. * * @author Abe White * @since 0.3.3 * @nojavadoc */ public class Serialization { private static final Localizer _loc = Localizer.forPackage (Serialization.class); /** * Serialize a value that might contain persistent objects. Replaces * persistent objects with their oids. */ public static byte[] serialize(Object val, StoreContext ctx) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); try { ObjectOutputStream objs = new PersistentObjectOutputStream(bytes, ctx); objs.writeObject(val); objs.flush(); return bytes.toByteArray(); } catch (Exception e) { throw new StoreException(e); } } /** * Deserialize an object value from the given bytes. */ public static Object deserialize(byte[] bytes, StoreContext ctx) { ByteArrayInputStream in = new ByteArrayInputStream(bytes); return deserialize(in, ctx); } /** * Deserialize an object value from the given stream. */ public static Object deserialize(InputStream in, StoreContext ctx) { try { if (ctx == null) return new ClassResolvingObjectInputStream(in).readObject(); return new PersistentObjectInputStream(in, ctx).readObject(); } catch (Exception e) { throw new StoreException(e); } } /** * Object output stream that replaces persistent objects with their oids. */ public static class PersistentObjectOutputStream extends ObjectOutputStream { private StoreContext _ctx; /** * Constructor; supply underlying stream. */ public PersistentObjectOutputStream(OutputStream delegate, StoreContext ctx) throws IOException { super(delegate); _ctx = ctx; AccessController.doPrivileged(new PrivilegedAction() { public Object run() { enableReplaceObject(true); return null; } }); } protected Object replaceObject(Object obj) { Object oid = _ctx.getObjectId(obj); return (oid == null) ? obj : new ObjectIdMarker(oid); } } public static class ClassResolvingObjectInputStream extends ObjectInputStream { public ClassResolvingObjectInputStream(InputStream delegate) throws IOException { super(delegate); } protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { MultiClassLoader loader = AccessController .doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction()); addContextClassLoaders(loader); loader.addClassLoader(getClass().getClassLoader()); loader.addClassLoader(MultiClassLoader.SYSTEM_LOADER); return Class.forName(desc.getName(), true, loader); } protected void addContextClassLoaders(MultiClassLoader loader) { loader.addClassLoader(AccessController.doPrivileged( J2DoPrivHelper.getContextClassLoaderAction())); } } /** * Object input stream that replaces oids with their objects. */ public static class PersistentObjectInputStream extends ClassResolvingObjectInputStream { private final StoreContext _ctx; /** * Constructor; supply source stream and broker to * use for persistent object lookups. */ public PersistentObjectInputStream(InputStream delegate, StoreContext ctx) throws IOException { super(delegate); _ctx = ctx; AccessController.doPrivileged(new PrivilegedAction() { public Object run() { enableResolveObject(true); return null; } }); } protected void addContextClassLoaders(MultiClassLoader loader) { super.addContextClassLoaders(loader); loader.addClassLoader(_ctx.getClassLoader()); } protected Object resolveObject(Object obj) { if (!(obj instanceof ObjectIdMarker)) return obj; Object oid = ((ObjectIdMarker) obj).oid; if (oid == null) return null; Object pc = _ctx.find(oid, null, null, null, 0); if (pc == null) { Log log = _ctx.getConfiguration().getLog (OpenJPAConfiguration.LOG_RUNTIME); if (log.isWarnEnabled()) log.warn(_loc.get("bad-ser-oid", oid)); if (log.isTraceEnabled()) log.trace(new ObjectNotFoundException(oid)); } return pc; } } /** * Marker for oids. */ private static class ObjectIdMarker implements Serializable { public Object oid; public ObjectIdMarker(Object oid) { this.oid = oid; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ShortId.java0000644000000000000000000000342512133327272025212 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * {@link OpenJPAId} subclass appropriate for short fields. * * @author Steve Kim */ public final class ShortId extends OpenJPAId { private final short key; public ShortId(Class cls, Short key) { this(cls, (key == null) ? (short) 0 : key.shortValue()); } public ShortId(Class cls, String key) { this(cls, (key == null) ? (short) 0 : Short.parseShort(key)); } public ShortId(Class cls, short key) { super(cls); this.key = key; } public ShortId(Class cls, short key, boolean subs) { super(cls, subs); this.key = key; } public short getId() { return key; } public Object getIdObject() { return Short.valueOf(key); } public String toString() { return Short.toString(key); } protected int idHash() { return key; } protected boolean idEquals(OpenJPAId o) { return key == ((ShortId) o).key; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyMaps.java0000644000000000000000000002260412133327272025600 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.InputStream; import java.io.ObjectStreamException; import java.util.AbstractSet; import java.util.Collection; import java.util.Map; import java.util.Iterator; import java.util.Set; /** * Utility methods used by map proxies. * * @author Abe White * @nojavadoc */ public class ProxyMaps extends Proxies { /** * Call before invoking {@link Map#clear} on super. */ public static void beforeClear(ProxyMap map) { dirty(map, true); Map.Entry entry; for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); removed(map, entry.getKey(), true); removed(map, entry.getValue(), false); } } /** * Override for {@link Map#keySet}. */ public static Set keySet(ProxyMap map) { ProxyEntrySet entries = (ProxyEntrySet) map.entrySet(); entries.setView(ProxyEntrySet.VIEW_KEYS); return entries; } /** * Override for {@link Map#values}. */ public static Collection values(ProxyMap map) { ProxyEntrySet entries = (ProxyEntrySet) map.entrySet(); entries.setView(ProxyEntrySet.VIEW_VALUES); return entries; } /** * Wrap the given entry set in a proxy. */ public static Set afterEntrySet(ProxyMap map, Set entries) { return new ProxyEntrySetImpl(map, entries); } /** * Call before invoking {@link Map#get} on super. */ public static boolean beforeGet(ProxyMap map, Object key) { assertAllowedType(key, map.getKeyType()); return map.containsKey(key); } /** * Call after invoking {@link Map#get} on super. * The potential change is tracked when the get method is called. This change * will not translated to an update statement if the retrieved value * is not dirty. * * @param ret the return value from the super's method * @param before the return value from {@link #beforeGet} * @return the value to return from {@link Map#get} */ public static Object afterGet(ProxyMap map, Object key, Object ret, boolean before) { if (before) { if (map.getChangeTracker() != null) ((MapChangeTracker) map.getChangeTracker()).changed(key, ret, ret); } return ret; } /** * Call before invoking {@link Map#put} on super. */ public static boolean beforePut(ProxyMap map, Object key, Object value) { assertAllowedType(key, map.getKeyType()); assertAllowedType(value, map.getValueType()); dirty(map, false); return map.containsKey(key); } /** * Call after invoking {@link Map#put} on super. * * @param ret the return value from the super's method * @param before the return value from {@link #beforePut} * @return the value to return from {@link Map#put} */ public static Object afterPut(ProxyMap map, Object key, Object value, Object ret, boolean before) { if (before) { if (map.getChangeTracker() != null) ((MapChangeTracker) map.getChangeTracker()).changed(key, ret, value); removed(map, ret, false); } else if (map.getChangeTracker() != null) ((MapChangeTracker) map.getChangeTracker()).added(key, value); return ret; } /** * Call before invoking {@link Properties#setProperty} on super. */ public static boolean beforeSetProperty(ProxyMap map, String key, String value) { return beforePut(map, key, value); } /** * Call after invoking {@link Properties#setProperty} on super. * * @param ret the return value from the super's method * @param before the return value from {@link #beforeSetProperty} * @return the value to return from {@link Properties#setProperty} */ public static Object afterSetProperty(ProxyMap map, String key, String value, Object ret, boolean before) { return afterPut(map, key, value, ret, before); } /** * Call before invoking {@link Properties#load} on super. */ public static void beforeLoad(ProxyMap map, InputStream in) { dirty(map, true); } /** * Call before invoking {@link Properties#loadXML} on super. */ public static void beforeLoadFromXML(ProxyMap map, InputStream in) { dirty(map, true); } /** * Overload for {@link Map#putAll}. */ public static void putAll(ProxyMap map, Map values) { Map.Entry entry; for (Iterator itr = values.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); map.put(entry.getKey(), entry.getValue()); } } /** * Call before invoking {@link Map#remove} on super. */ public static boolean beforeRemove(ProxyMap map, Object key) { dirty(map, false); return map.containsKey(key); } /** * Call after invoking {@link Map#remove} on super. * * @param ret the return value from the super's method * @param before the return value from {@link #beforeRemove} * @return the value to return from {@link Map#remove} */ public static Object afterRemove(ProxyMap map, Object key, Object ret, boolean before) { if (before) { if (map.getChangeTracker() != null) ((MapChangeTracker) map.getChangeTracker()).removed(key, ret); removed(map, key, true); removed(map, ret, false); } return ret; } /** * Marker interface for a proxy entry set. */ public static interface ProxyEntrySet extends Set { public static final int VIEW_KEYS = 0; public static final int VIEW_VALUES = 1; public static final int VIEW_ENTRIES = 2; /** * Set what entry view this set exposes. */ public void setView(int view); } /** * Dirtying proxy for map entry set. */ private static class ProxyEntrySetImpl extends AbstractSet implements ProxyEntrySet { private final ProxyMap _map; private final Set _entries; private int _view = VIEW_ENTRIES; /** * Supply owning map and delegate entry set on construction. */ public ProxyEntrySetImpl(ProxyMap map, Set entries) { _map = map; _entries = entries; } /** * View mode. */ public int getView() { return _view; } /** * View mode. */ public void setView(int view) { _view = view; } public int size() { return _entries.size(); } public boolean remove(Object o) { if (_view != VIEW_KEYS) throw new UnsupportedOperationException(); if (!_map.containsKey(o)) return false; _map.remove(o); return true; } public Iterator iterator() { final Iterator itr = _entries.iterator(); return new Iterator() { private Map.Entry _last = null; public boolean hasNext() { return itr.hasNext(); } public Object next() { _last = (Map.Entry) itr.next(); switch (_view) { case VIEW_KEYS: return _last.getKey(); case VIEW_VALUES: return _last.getValue(); default: return _last; } } public void remove() { dirty(_map, false); itr.remove(); if (_map.getChangeTracker() != null) ((MapChangeTracker) _map.getChangeTracker()). removed(_last.getKey(), _last.getValue()); Proxies.removed(_map, _last.getKey(), true); Proxies.removed(_map, _last.getValue(), false); } }; } protected Object writeReplace() throws ObjectStreamException { switch (_view) { case VIEW_KEYS: return ((Map) _map).keySet(); case VIEW_VALUES: return ((Map) _map).values(); default: return ((Map) _map).entrySet(); } } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectId.java0000644000000000000000000000330612133327272025317 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * Identity type appropriate for object primary key fields and shared * id classes. * * @author Abe White */ public final class ObjectId extends OpenJPAId { private Object _key; public ObjectId(Class cls, Object key) { super(cls); _key = key; } public ObjectId(Class cls, Object key, boolean subs) { super(cls, subs); _key = key; } public Object getId() { return _key; } /** * Allow utilities in this package to mutate id. */ void setId(Object id) { _key = id; } public Object getIdObject() { return _key; } protected int idHash() { return (_key == null) ? 0 : _key.hashCode(); } protected boolean idEquals(OpenJPAId o) { Object key = ((ObjectId) o)._key; return (_key == null) ? key == null : _key.equals(key); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/AbstractLRSProxyMap.java0000644000000000000000000003645612133327272027474 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.AbstractCollection; import java.util.AbstractSet; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import org.apache.commons.collections.Predicate; import org.apache.commons.collections.iterators.FilterIterator; import org.apache.commons.collections.iterators.IteratorChain; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.Localizer; /** * A map proxy designed for maps backed by extremely large result sets in * which each call to {@link #get} or {@link #containsKey} may perform a * database query. Changes to the map are tracked through a * {@link ChangeTracker}. This map has the following limitations: *
    *
  • The size method may return {@link Integer#MAX_VALUE}.
  • *
  • Null keys and values are not supported.
  • *
* * @author Abe White */ public abstract class AbstractLRSProxyMap implements Map, LRSProxy, MapChangeTracker, Predicate { private static final int MODE_KEY = 0; private static final int MODE_VALUE = 1; private static final int MODE_ENTRY = 2; private static final Localizer _loc = Localizer.forPackage (AbstractLRSProxyMap.class); private Class _keyType = null; private Class _valueType = null; private MapChangeTrackerImpl _ct = null; private OpenJPAStateManager _sm = null; private int _field = -1; private OpenJPAStateManager _origOwner = null; private int _origField = -1; private Map _map = null; private int _count = -1; private boolean _iterated = false; public AbstractLRSProxyMap(Class keyType, Class valueType) { _keyType = keyType; _valueType = valueType; _ct = new MapChangeTrackerImpl(this,false); _ct.setAutoOff(false); } public void setOwner(OpenJPAStateManager sm, int field) { // can't transfer ownership of an lrs proxy if (sm != null && _origOwner != null && (_origOwner != sm || _origField != field)) { throw new InvalidStateException(_loc.get("transfer-lrs", _origOwner.getMetaData().getField(_origField))); } _sm = sm; _field = field; // keep track of original owner so we can detect transfer attempts if (sm != null) { _origOwner = sm; _origField = field; } } public OpenJPAStateManager getOwner() { return _sm; } public int getOwnerField() { return _field; } public ChangeTracker getChangeTracker() { return this; } public Object copy(Object orig) { // used to store fields for rollbac; we don't store lrs fields return null; } /** * used in testing; we need to be able to make sure that OpenJPA does not * iterate lrs fields during standard crud operations */ boolean isIterated() { return _iterated; } /** * used in testing; we need to be able to make sure that OpenJPA does not * iterate lrs fields during standard crud operations */ void setIterated(boolean it) { _iterated = it; } public int size() { if (_count == -1) _count = count(); if (_count == Integer.MAX_VALUE) return _count; return _count + _ct.getAdded().size() - _ct.getRemoved().size(); } public boolean isEmpty() { return size() == 0; } public boolean containsKey(Object key) { if (_keyType != null && !_keyType.isInstance(key)) return false; if (_map != null && _map.containsKey(key)) return true; if (_ct.getTrackKeys()) { if (_ct.getRemoved().contains(key)) return false; return hasKey(key); } // value tracking: // if we've removed values, we need to see if this key represents // a removed instance. otherwise we can rely on the 1-1 between // keys and values when using value tracking if (_ct.getRemoved().isEmpty()) return hasKey(key); return get(key) != null; } public boolean containsValue(Object val) { if (_valueType != null && !_valueType.isInstance(val)) return false; if (_map != null && _map.containsValue(val)) return true; if (!_ct.getTrackKeys()) { if (_ct.getRemoved().contains(val)) return false; return hasValue(val); } // key tracking Collection keys = keys(val); if (keys == null || keys.isEmpty()) return false; keys.removeAll(_ct.getRemoved()); keys.removeAll(_ct.getChanged()); return keys.size() > 0; } public V get(Object key) { if (_keyType != null && !_keyType.isInstance(key)) return null; V ret = (_map == null) ? null : _map.get(key); if (ret != null) return ret; if (_ct.getTrackKeys() && _ct.getRemoved().contains(key)) return null; V val = value(key); if (!_ct.getTrackKeys() && _ct.getRemoved().contains(val)) return null; return val; } public V put(K key, V value) { Proxies.assertAllowedType(key, _keyType); Proxies.assertAllowedType(value, _valueType); Proxies.dirty(this, false); if (_map == null) _map = new HashMap(); V old = _map.put(key, value); if (old == null && (!_ct.getTrackKeys() || !_ct.getRemoved().contains(key))) old = value(key); if (old != null) { _ct.changed(key, old, value); Proxies.removed(this, old, false); } else _ct.added(key, value); return old; } public void putAll(Map m) { for (Map.Entry entry : m.entrySet()) { put(entry.getKey(), entry.getValue()); } } public V remove(Object key) { Proxies.dirty(this, false); V old = (_map == null) ? null : _map.remove(key); if (old == null && (!_ct.getTrackKeys() || !_ct.getRemoved().contains(key))) old = value(key); if (old != null) { _ct.removed(key, old); Proxies.removed(this, key, true); Proxies.removed(this, old, false); } return old; } public void clear() { Proxies.dirty(this, false); Itr itr = iterator(MODE_ENTRY); try { Map.Entry entry; while (itr.hasNext()) { entry = (Map.Entry) itr.next(); Proxies.removed(this, entry.getKey(), true); Proxies.removed(this, entry.getValue(), false); _ct.removed(entry.getKey(), entry.getValue()); } } finally { itr.close(); } } public Set keySet() { return new AbstractSet() { public int size() { return AbstractLRSProxyMap.this.size(); } public boolean remove(Object o) { return AbstractLRSProxyMap.this.remove(o) != null; } public Iterator iterator() { return AbstractLRSProxyMap.this.iterator(MODE_KEY); } }; } public Collection values() { return new AbstractCollection() { public int size() { return AbstractLRSProxyMap.this.size(); } public Iterator iterator() { return AbstractLRSProxyMap.this.iterator(MODE_VALUE); } }; } public Set> entrySet() { return new AbstractSet>() { public int size() { return AbstractLRSProxyMap.this.size(); } public Iterator> iterator() { return AbstractLRSProxyMap.this.iterator(MODE_ENTRY); } }; } protected Object writeReplace() throws ObjectStreamException { Itr itr = iterator(MODE_ENTRY); try { Map map = new HashMap(); Map.Entry entry; while (itr.hasNext()) { entry = (Map.Entry) itr.next(); map.put(entry.getKey(), entry.getValue()); } return map; } finally { itr.close(); } } /** * Return whether the given key exists in the map. */ protected abstract boolean hasKey(Object key); /** * Return whether the given value exists in the map. */ protected abstract boolean hasValue(Object value); /** * Return all keys for the given value. */ protected abstract Collection keys(Object value); /** * Return the value of the given key. */ protected abstract V value(Object key); /** * Implement this method to return an iterator over the entries * in the map. Each returned object must implement the * Map.Entry interface. This method may be invoked multiple * times. The iterator does not have to support the * {@link Iterator#remove} method, and may implement * {@link org.apache.openjpa.lib.util.Closeable}. */ protected abstract Iterator itr(); /** * Return the number of entries in the map, or {@link Integer#MAX_VALUE}. */ protected abstract int count(); private Itr iterator(int mode) { _iterated = true; // have to copy the entry set of _map to prevent concurrent mod errors IteratorChain chain = new IteratorChain(); if (_map != null) chain.addIterator(new ArrayList(_map.entrySet()).iterator()); chain.addIterator(new FilterIterator(itr(), this)); return new Itr(mode, chain); } //////////////////////////// // Predicate Implementation //////////////////////////// public boolean evaluate(Object obj) { Map.Entry entry = (Map.Entry) obj; return (_ct.getTrackKeys() && !_ct.getRemoved().contains(entry.getKey()) || (!_ct.getTrackKeys() && !_ct.getRemoved().contains(entry.getValue()))) && (_map == null || !_map.containsKey(entry.getKey())); } /////////////////////////////////// // MapChangeTracker Implementation /////////////////////////////////// public boolean isTracking() { return _ct.isTracking(); } public void startTracking() { _ct.startTracking(); reset(); } public void stopTracking() { _ct.stopTracking(); reset(); } private void reset() { if (_map != null) _map.clear(); if (_count != Integer.MAX_VALUE) _count = -1; } public boolean getTrackKeys() { return _ct.getTrackKeys(); } public void setTrackKeys(boolean keys) { _ct.setTrackKeys(keys); } public Collection getAdded() { return _ct.getAdded(); } public Collection getRemoved() { return _ct.getRemoved(); } public Collection getChanged() { return _ct.getChanged(); } public void added(Object key, Object val) { _ct.added(key, val); } public void removed(Object key, Object val) { _ct.removed(key, val); } public void changed(Object key, Object orig, Object val) { _ct.changed(key, orig, val); } public int getNextSequence() { return _ct.getNextSequence(); } public void setNextSequence(int seq) { _ct.setNextSequence(seq); } /** * Wrapper around our filtering iterator chain. */ private class Itr implements Iterator, Closeable { private static final int OPEN = 0; private static final int LAST_ELEM = 1; private static final int CLOSED = 2; private final int _mode; private final IteratorChain _itr; private Map.Entry _last = null; private int _state = OPEN; public Itr(int mode, IteratorChain itr) { _mode = mode; _itr = itr; } public boolean hasNext() { if (_state != OPEN) return false; // close automatically if no more elements if (!_itr.hasNext()) { free(); _state = LAST_ELEM; return false; } return true; } public Object next() { if (_state != OPEN) throw new NoSuchElementException(); _last = (Map.Entry) _itr.next(); switch (_mode) { case MODE_KEY: return _last.getKey(); case MODE_VALUE: return _last.getValue(); default: return _last; } } public void remove() { if (_state == CLOSED || _last == null) throw new NoSuchElementException(); Proxies.dirty(AbstractLRSProxyMap.this, false); Proxies.removed(AbstractLRSProxyMap.this, _last.getKey(), true); Proxies.removed(AbstractLRSProxyMap.this, _last.getValue(), false); // need to get a reference to the key before we remove it // from the map, since in JDK 1.3-, the act of removing an entry // from the map will also null the entry's value, which would // result in incorrectly passing a null to the change tracker Object key = _last.getKey(); Object value = _last.getValue(); if (_map != null) _map.remove(key); _ct.removed(key, value); _last = null; } public void close() { free(); _state = CLOSED; } private void free() { if (_state != OPEN) return; List itrs = _itr.getIterators(); Iterator itr; for (int i = 0; i < itrs.size(); i++) { itr = (Iterator) itrs.get(i); if (itr instanceof FilterIterator) itr = ((FilterIterator) itr).getIterator(); ImplHelper.close(itr); } } protected void finalize() { close (); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/StringId.java0000644000000000000000000000327012133327272025357 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.commons.lang.StringUtils; /** * {@link OpenJPAId} subclass appropriate for String fields. * * @author Steve Kim */ public final class StringId extends OpenJPAId { private final String key; public StringId(Class cls, String key) { super(cls); this.key = (key == null) ? "" : StringUtils.stripEnd(key, null); } public StringId(Class cls, String key, boolean subs) { super(cls, subs); this.key = (key == null) ? "" : StringUtils.stripEnd(key, null); } public String getId() { return key; } public Object getIdObject() { return key; } public String toString() { return key; } protected int idHash() { return key.hashCode(); } protected boolean idEquals(OpenJPAId o) { return key.equals(((StringId) o).key); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedProxy.java0000644000000000000000000000500712133327272026245 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * Implemented by proxy classes which are delay-load capable. Delay-load * proxies are lazily loaded and provide some operations * which allow manipulation of proxy without necessarily needing to * load the proxied object. */ public interface DelayedProxy { /** * Load the proxy if it was delay-loaded. */ void load(); /** * Returns whether the caller has direct-call access to the proxied * object. Direct access allows calls to be made on the object * without triggering a load or proxy state tracking callbacks. */ boolean isDirectAccess(); /** * Sets whether the caller has direct-call access to the proxied * object. Direct access allows calls to be made on the object * without triggering a load or proxy state tracking callbacks. */ void setDirectAccess(boolean direct); /** * Get the broker that is used to service this proxy. */ Broker getBroker(); /** * Close the broker that is used to service this proxy. */ void closeBroker(); /** * Returns the state manager of the owning instance. */ OpenJPAStateManager getOwnerStateManager(); /** * Returns a state manager that can service this proxy even if * the collection was detached. */ OpenJPAStateManager getDelayedOwner(); /** * Returns the expected field index even if this collection * was detached. * @return */ int getDelayedField(); /** * Returns whether the proxy is detached. * @return */ boolean isDetached(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/InvalidStateException.java0000644000000000000000000000255312133327272030105 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type thrown when attempting to execute an operation that * is not allowed by the current state. * * @since 0.4.0 * @author Abe White */ public class InvalidStateException extends UserException { public InvalidStateException(Message msg) { super(msg); } public InvalidStateException(Message msg, Object failed) { super(msg); setFailedObject(failed); } public int getSubtype() { return INVALID_STATE; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/CollectionChangeTracker.java0000644000000000000000000000260712133327272030354 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * Change tracker that can be used for collections. If the user calls * any mutating methods on the collection that do not have an equivalent in * this change tracker, then you must call {@link #stopTracking} after * applying the operation to the collection. * * @author Abe White */ public interface CollectionChangeTracker extends ChangeTracker { /** * Record that the given element was added. */ public void added(Object elem); /** * Record that the given element was removed. */ public void removed(Object elem); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedHashSetProxy.java0000644000000000000000000002376712133327272027542 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.DetachedStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * HashSet proxy with delay loading capability. Allows non-indexed add and * remove operations to occur on an unloaded collection. Operations that require * a load will trigger a load. */ @SuppressWarnings({ "rawtypes", "unchecked" }) public class DelayedHashSetProxy extends HashSet implements DelayedProxy, ProxyCollection { private transient OpenJPAStateManager sm; private transient int field; private transient CollectionChangeTracker changeTracker; private transient Class elementType; private transient OpenJPAStateManager _ownerSm; private transient boolean _directAccess = false; private transient BrokerFactory _brokerFactory = null; private transient Broker _broker = null; private transient OpenJPAStateManager _delayedSm; private transient int _delayedField; private transient boolean _detached = false; public DelayedHashSetProxy(Collection paramCollection) { super(paramCollection); } public DelayedHashSetProxy(int paramInt, float paramFloat) { super(paramInt, paramFloat); } public DelayedHashSetProxy(int paramInt) { super(paramInt); } public DelayedHashSetProxy() { } public void setOwner(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { // If clearing the owner of this proxy, store away what is necessary for // delayed loading if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) { _detached = true; _delayedSm = sm; _delayedField = field; } else { _detached = false; } this.sm = paramOpenJPAStateManager; if (sm != null && sm.getPersistenceCapable() != null) { _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable() .pcGetStateManager(); } this.field = paramInt; if (sm != null && sm.getContext() != null) { _brokerFactory = sm.getContext().getBroker().getBrokerFactory(); } } private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { if ((paramOpenJPAStateManager == null && paramInt == -1) || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) { return true; } return false; } public OpenJPAStateManager getOwner() { return this.sm; } public int getOwnerField() { return this.field; } public ChangeTracker getChangeTracker() { return this.changeTracker; } protected void setChangeTracker(CollectionChangeTracker ct) { changeTracker = ct; } @Override public Object copy(Object paramObject) { return new HashSet((Collection) paramObject); } public Class getElementType() { return this.elementType; } protected void setElementType(Class elemType) { elementType = elemType; } public ProxyCollection newInstance(Class paramClass, Comparator paramComparator, boolean paramBoolean1, boolean paramBoolean2) { DelayedHashSetProxy localproxy = new DelayedHashSetProxy(); localproxy.elementType = paramClass; if (paramBoolean1) localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl( localproxy, false, false, paramBoolean2); return localproxy; } @Override public Object clone() { if (isDirectAccess()) { return super.clone(); } if (isDelayLoad()) { load(); } Proxy localProxy = (Proxy) super.clone(); localProxy.setOwner(null, 0); return localProxy; } @Override public boolean add(Object paramObject) { if (_directAccess) { return super.add(paramObject); } ProxyCollections.beforeAdd(this, paramObject); boolean bool = super.add(paramObject); return ProxyCollections.afterAdd(this, paramObject, bool); } @Override public void clear() { if (!_directAccess) { if (isDelayLoad()) { load(); } ProxyCollections.beforeClear(this); } super.clear(); } @Override public Iterator iterator() { if (_directAccess) { return super.iterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.iterator(); return ProxyCollections.afterIterator(this, localIterator); } @Override public boolean remove(Object paramObject) { if (_directAccess) { return super.remove(paramObject); } ProxyCollections.beforeRemove(this, paramObject); setDirectAccess(true); boolean bool = super.remove(paramObject); setDirectAccess(false); return ProxyCollections.afterRemove(this, paramObject, bool); } @Override public boolean removeAll(Collection paramCollection) { if (_directAccess) { return super.removeAll(paramCollection); } return ProxyCollections.removeAll(this, paramCollection); } @Override public boolean addAll(Collection paramCollection) { if (_directAccess) { return super.addAll(paramCollection); } return ProxyCollections.addAll(this, paramCollection); } @Override public boolean retainAll(Collection paramCollection) { if (_directAccess) { return super.retainAll(paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.retainAll(this, paramCollection); } protected Object writeReplace() throws ObjectStreamException { if (isDelayLoad()) { load(); } return Proxies.writeReplace(this, true); } @Override public int size() { if (!_directAccess && isDelayLoad()) { load(); } return super.size(); } @Override public boolean isEmpty() { if (!_directAccess && isDelayLoad()) { load(); } return super.isEmpty(); } @Override public boolean contains(Object o) { if (!_directAccess && isDelayLoad()) { load(); } return super.contains(o); } @Override public Object[] toArray() { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(); } @Override public Object[] toArray(Object[] a) { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(a); } @Override public boolean containsAll(Collection c) { if (!_directAccess && isDelayLoad()) { load(); } return super.containsAll(c); } @Override public String toString() { if (!_directAccess && isDelayLoad()) { load(); } return super.toString(); } public boolean equals(Object paramObject) { if (!_directAccess && isDelayLoad()) { load(); } return super.equals(paramObject); } public int hashCode() { if (!_directAccess && isDelayLoad()) { load(); } return super.hashCode(); } // ////////////////////////////////////// // DelayedProxy methods // ////////////////////////////////////// public int getDelayedField() { if (field == -1 || _detached) { return _delayedField; } return field; } public OpenJPAStateManager getDelayedOwner() { if (sm == null || _detached) { return _delayedSm; } return sm; } public boolean isDirectAccess() { return _directAccess; } public void setDirectAccess(boolean direct) { _directAccess = direct; } public BrokerFactory getBrokerFactory() { return _brokerFactory; } @Override public void load() { ProxyCollections.loadCollection(this); } @Override public Broker getBroker() { if (_broker == null || _broker.isClosed()) { if (_brokerFactory != null) { _broker = _brokerFactory.newBroker(); } } return _broker; } @Override public void closeBroker() { if (_broker != null && !_broker.isClosed()) { _broker.setAutoDetach(AutoDetach.DETACH_CLOSE); _broker.close(); _broker = null; } } @Override public OpenJPAStateManager getOwnerStateManager() { return _ownerSm; } @Override public boolean isDetached() { return _detached; } public boolean isDelayLoad() { return ProxyCollections.isDelayed(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAId.java0000644000000000000000000001056612133327272025353 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.Serializable; import org.apache.openjpa.lib.util.ReferenceMap; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap; /** * Identity class extended by built-in OpenJPA identity objects. * * @author Steve Kim */ @SuppressWarnings("serial") public abstract class OpenJPAId implements Comparable, Serializable { public static final char TYPE_VALUE_SEP = '-'; // cache the types' generated hash codes private static ConcurrentReferenceHashMap _typeCache = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD); protected Class type; protected boolean subs = true; // type hash is based on the least-derived non-object class so that // user-given ids with non-exact types match ids with exact types private int _typeHash = 0; protected OpenJPAId() { } protected OpenJPAId(Class type) { this.type = type; } protected OpenJPAId(Class type, boolean subs) { this.type = type; this.subs = subs; } /** * Return the persistent class which this id instance represents. */ public Class getType() { return type; } /** * Whether this oid might be for a subclass of the given type. * Defaults to true. */ public boolean hasSubclasses() { return subs; } /** * Set the exact type of the described instance once it is known. */ public void setManagedInstanceType(Class type) { setManagedInstanceType(type, false); } /** * Set the exact type of the described instance once it is known. */ public void setManagedInstanceType(Class type, boolean subs) { this.type = type; this.subs = subs; } /** * Return the identity value as an object. */ public abstract Object getIdObject(); /** * Return the id's hash code. */ protected abstract int idHash(); /** * Compare the id to the id of the given instance. */ protected abstract boolean idEquals(OpenJPAId other); /** * Generate the hash code for this Id. Cache the type's generated hash code * so that it doesn't have to be generated each time. */ public int hashCode() { if (_typeHash == 0) { Integer typeHashInt = (Integer) _typeCache.get(type); if (typeHashInt == null) { Class base = type; Class superclass = base.getSuperclass(); while (superclass != null && superclass != Object.class) { base = base.getSuperclass(); superclass = base.getSuperclass(); } _typeHash = base.getName().hashCode(); _typeCache.put(type, Integer.valueOf(_typeHash)); } else { _typeHash = typeHashInt.intValue(); } } return _typeHash ^ idHash(); } public boolean equals(Object o) { if (o == this) return true; if (o == null || getClass() != o.getClass()) return false; OpenJPAId id = (OpenJPAId) o; return idEquals(id) && (id.type.isAssignableFrom(type) || (subs && type.isAssignableFrom(id.type))); } public String toString() { return type.getName() + TYPE_VALUE_SEP + getIdObject(); } public int compareTo(Object other) { if (other == this) return 0; if (other == null) return 1; return ((Comparable) getIdObject()).compareTo(((OpenJPAId) other).getIdObject ()); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedArrayListProxy.java0000644000000000000000000003040412133327272030077 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.DetachedStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * ArrayList proxy with delay loading capability. Allows non-indexed * add and remove operations to occur on an unloaded collection. Operations * that require a load will trigger a load. */ @SuppressWarnings({"rawtypes","unchecked"}) public class DelayedArrayListProxy extends ArrayList implements ProxyCollection, DelayedProxy { private transient OpenJPAStateManager sm; private transient int field; private transient CollectionChangeTracker changeTracker; private transient Class elementType; private transient OpenJPAStateManager _ownerSm; private transient boolean _directAccess = false; private transient BrokerFactory _brokerFactory = null; private transient Broker _broker = null; private transient OpenJPAStateManager _delayedSm; private transient int _delayedField; private transient boolean _detached = false; public DelayedArrayListProxy() { } public DelayedArrayListProxy(Collection paramCollection) { super(paramCollection); } public DelayedArrayListProxy(int paramInt) { super(paramInt); } public void setOwner(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { // If clearing the owner of this proxy, store away what is necessary for // delayed loading if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) { _detached = true; _delayedSm = sm; _delayedField = field; } else { _detached = false; } this.sm = paramOpenJPAStateManager; if (sm != null && sm.getPersistenceCapable() != null) { _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable() .pcGetStateManager(); } this.field = paramInt; if (sm != null && sm.getContext() != null) { _brokerFactory = sm.getContext().getBroker().getBrokerFactory(); } } private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { if ((paramOpenJPAStateManager == null && paramInt == -1) || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) { return true; } return false; } public int getDelayedField() { if (field == -1 || _detached) { return _delayedField; } return field; } public OpenJPAStateManager getDelayedOwner() { if (sm == null || _detached) { return _delayedSm; } return sm; } public OpenJPAStateManager getOwner() { return sm; } public int getOwnerField() { return field; } public Object clone() { if (isDirectAccess()) { return super.clone(); } if (isDelayLoad()) { load(); } Proxy localProxy = (Proxy) super.clone(); localProxy.setOwner(null, 0); return localProxy; } public ChangeTracker getChangeTracker() { return this.changeTracker; } protected void setChangeTracker(CollectionChangeTracker ct) { changeTracker = ct; } public Object copy(Object paramObject) { if (isDelayLoad()) { load(); } return new ArrayList((Collection) paramObject); } public Class getElementType() { return this.elementType; } protected void setElementType(Class elemType) { elementType = elemType; } @Override public ProxyCollection newInstance(Class paramClass, Comparator paramComparator, boolean paramBoolean1, boolean paramBoolean2) { DelayedArrayListProxy proxy = new DelayedArrayListProxy(); proxy.elementType = paramClass; proxy.changeTracker = new DelayedCollectionChangeTrackerImpl(proxy, true, true, paramBoolean2); return proxy; } public boolean add(Object paramObject) { if (_directAccess) { return super.add(paramObject); } ProxyCollections.beforeAdd(this, paramObject); boolean bool = super.add(paramObject); return ProxyCollections.afterAdd(this, paramObject, bool); } public void add(int paramInt, Object paramObject) { if (!_directAccess) { if (isDelayLoad()) { load(); } } ProxyCollections.beforeAdd(this, paramInt, paramObject); super.add(paramInt, paramObject); } public void clear() { if (!_directAccess) { if (isDelayLoad()) { load(); } ProxyCollections.beforeClear(this); } super.clear(); } public boolean addAll(int paramInt, Collection paramCollection) { if (isDelayLoad()) { load(); } return ProxyCollections.addAll(this, paramInt, paramCollection); } public boolean addAll(Collection paramCollection) { if (_directAccess) { return super.addAll(paramCollection); } return ProxyCollections.addAll(this, paramCollection); } public boolean remove(Object paramObject) { if (_directAccess) { return super.remove(paramObject); } ProxyCollections.beforeRemove(this, paramObject); setDirectAccess(true); boolean bool = super.remove(paramObject); setDirectAccess(false); return ProxyCollections.afterRemove(this, paramObject, bool); } public Object remove(int paramInt) { if (_directAccess) { return super.remove(paramInt); } if (isDelayLoad()) { load(); } ProxyCollections.beforeRemove(this, paramInt); Object localObject = super.remove(paramInt); return ProxyCollections.afterRemove(this, paramInt, localObject); } public Object set(int paramInt, Object paramObject) { if (_directAccess) { return super.set(paramInt, paramObject); } if (isDelayLoad()) { load(); } ProxyCollections.beforeSet(this, paramInt, paramObject); Object localObject = super.set(paramInt, paramObject); return ProxyCollections.afterSet(this, paramInt, paramObject, localObject); } public Iterator iterator() { if (_directAccess) { return super.iterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.iterator(); return ProxyCollections.afterIterator(this, localIterator); } public ListIterator listIterator(int paramInt) { if (_directAccess) { return super.listIterator(paramInt); } if (isDelayLoad()) { load(); } ListIterator localListIterator = super.listIterator(paramInt); return ProxyCollections.afterListIterator(this, paramInt, localListIterator); } public ListIterator listIterator() { if (_directAccess) { return super.listIterator(); } if (isDelayLoad()) { load(); } ListIterator localListIterator = super.listIterator(); return ProxyCollections.afterListIterator(this, localListIterator); } public boolean removeAll(Collection paramCollection) { if (_directAccess) { return super.removeAll(paramCollection); } return ProxyCollections.removeAll(this, paramCollection); } public boolean retainAll(Collection paramCollection) { if (_directAccess) { return super.retainAll(paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.retainAll(this, paramCollection); } protected Object writeReplace() throws ObjectStreamException { if (isDelayLoad()) { load(); } return Proxies.writeReplace(this, true); } public boolean isDelayLoad() { return ProxyCollections.isDelayed(this); } @Override public Object get(int location) { if (!_directAccess && isDelayLoad()) { load(); } return super.get(location); } @Override public int indexOf(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.indexOf(object); } @Override public int lastIndexOf(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.lastIndexOf(object); } @Override public List subList(int start, int end) { if (!_directAccess && isDelayLoad()) { load(); } return super.subList(start, end); } @Override public boolean contains(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.contains(object); } @Override public boolean containsAll(Collection collection) { if (!_directAccess && isDelayLoad()) { load(); } return super.containsAll(collection); } @Override public boolean isEmpty() { if (!_directAccess && isDelayLoad()) { load(); } return super.isEmpty(); } @Override public int size() { if (!_directAccess && isDelayLoad()) { load(); } return super.size(); } @Override public Object[] toArray() { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(); } @Override public Object[] toArray(Object[] array) { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(array); } public boolean equals(Object paramObject) { if (!_directAccess && isDelayLoad()) { load(); } return super.equals(paramObject); } public int hashCode() { if (!_directAccess && isDelayLoad()) { load(); } return super.hashCode(); } public boolean isDirectAccess() { return _directAccess; } public void setDirectAccess(boolean direct) { _directAccess = direct; } public BrokerFactory getBrokerFactory() { return _brokerFactory; } @Override public void load() { ProxyCollections.loadCollection(this); } @Override public Broker getBroker() { if (_broker == null || _broker.isClosed()) { if (_brokerFactory != null) { _broker = _brokerFactory.newBroker(); } } return _broker; } @Override public void closeBroker() { if (_broker != null && !_broker.isClosed()) { _broker.setAutoDetach(AutoDetach.DETACH_CLOSE); _broker.close(); _broker = null; } } @Override public OpenJPAStateManager getOwnerStateManager() { return _ownerSm; } @Override public boolean isDetached() { return _detached; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/GeneratedClasses.java0000644000000000000000000000576212133327272027060 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.security.AccessController; import java.security.PrivilegedActionException; import java.lang.reflect.Constructor; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import serp.bytecode.BCClass; import serp.bytecode.BCClassLoader; /** * Utility methods when generating classes, including at runtime. * * @since 1.0.0 */ public class GeneratedClasses { /** * Return the more derived loader of the class laoders for the given * classes. */ public static ClassLoader getMostDerivedLoader(Class c1, Class c2) { ClassLoader l1 = AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(c1)); ClassLoader l2 = AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(c2)); if (l1 == l2) return l1; if (l1 == null) return l2; if (l2 == null) return l1; if(canLoad(l1, c2)) { return l1; } return l2; } /** * Load the class represented by the given bytecode. */ public static Class loadBCClass(BCClass bc, ClassLoader loader) { BCClassLoader bcloader = AccessController .doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(bc .getProject(), loader)); try { Class c = Class.forName(bc.getName(), true, bcloader); bc.getProject().clear(); return c; } catch (Throwable t) { throw new GeneralException(bc.getName()).setCause(t); } } /** * Return true if the given loader will load the same version of a given * class. * * @param loader Classloader to use. * @param clazz Expected class. * @return true if loader.load(clazz.getName()) == clazz. Otherwise false. */ private static boolean canLoad(ClassLoader loader, Class clazz) { Class loaded = null; try { loaded = loader.loadClass(clazz.getName()); } catch (ClassNotFoundException e) { // Rely on caller to handle return value = false. } return clazz == loaded; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/BooleanId.java0000644000000000000000000000356212133327272025474 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * {@link OpenJPAId} subclass appropriate for boolean fields. * * @author Dianne Richards * @since 2.1.0 */ public class BooleanId extends OpenJPAId { private final boolean key; public BooleanId(Class cls, Boolean key) { this(cls, key.booleanValue()); } public BooleanId(Class cls, String key) { this(cls, Boolean.parseBoolean(key)); } public BooleanId(Class cls, boolean key) { super(cls); this.key = key; } public BooleanId(Class cls, boolean key, boolean subs) { super(cls, subs); this.key = key; } public boolean getId() { return key; } @Override public Object getIdObject() { return Boolean.valueOf(key); } public String toString() { return Boolean.toString(key); } @Override protected boolean idEquals(OpenJPAId other) { return key == ((BooleanId) other).key; } @Override protected int idHash() { return Boolean.valueOf(key).hashCode(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyDate.java0000644000000000000000000000213012133327272025545 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * Interface implemented by all generated proxies on {@link java.util.Date} * types. * * @author Abe White */ public interface ProxyDate extends Proxy { /** * Return a new instance of this date type. */ public ProxyDate newInstance(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/MetaDataException.java0000644000000000000000000000274012133327272027174 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type reserved for missing or invalid metadata. * * @since 0.3.0 * @author Abe White */ public class MetaDataException extends UserException { public MetaDataException() { setFatal(true); } public MetaDataException(String msg) { super(msg); setFatal(true); } public MetaDataException(Message msg) { super(msg); setFatal(true); } public MetaDataException(Message msg, Throwable nested) { super(msg, nested); setFatal(true); } public int getSubtype() { return METADATA; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/Id.java0000644000000000000000000001053612133327272024173 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.security.AccessController; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; /** * Datastore identity type. Implementations may choose to use this type, * or choose to use their own datastore identity values. * * @author Abe White */ public final class Id extends OpenJPAId { private static final Localizer _loc = Localizer.forPackage(Id.class); private final long _id; /** * Create an id from the given type and value; the value might be an * id instance, a stringified id, or a primary key value. */ public static Id newInstance(Class cls, Object val) { if (val instanceof Id) return (Id) val; if (val instanceof String) return new Id(cls, (String) val); if (val instanceof Number) return new Id(cls, ((Number) val).longValue()); if (val == null) return new Id(cls, 0L); throw new UserException(_loc.get("unknown-oid", cls, val, val.getClass())); } /** * Create an id from the result of a {@link #toString} call on another * instance. */ public Id(String str) { this(str, (ClassLoader) null); } /** * Create an id from the result of an {@link #toString} call on another * instance. */ public Id(String str, OpenJPAConfiguration conf, ClassLoader brokerLoader) { this(str, (conf == null) ? brokerLoader : conf. getClassResolverInstance().getClassLoader(Id.class, brokerLoader)); } /** * Create an id from the result of an {@link #toString} call on another * instance. */ public Id(String str, ClassLoader loader) { if (loader == null) loader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction()); if (str == null) _id = 0L; else { int dash = str.indexOf(TYPE_VALUE_SEP); try { type = Class.forName(str.substring(0, dash), true, loader); } catch (Throwable t) { throw new UserException(_loc.get("string-id", str), t); } _id = Long.parseLong(str.substring(dash + 1)); } } /** * Construct from the result of a {@link #toString} call on another * instance. */ public Id(Class cls, String key) { super(cls); if (key == null) _id = 0L; else { // allow either stringified long or result of Id.toString int dash = key.indexOf(TYPE_VALUE_SEP); if (dash > 0) // don't check for -1; might be negative number key = key.substring(dash + 1); _id = Long.parseLong(key); } } /** * Construct from key value. */ public Id(Class cls, Long key) { this(cls, (key == null) ? 0L : key.longValue()); } /** * Construct from key value. */ public Id(Class cls, long key) { super(cls); _id = key; } /** * Construct from key value. */ public Id(Class cls, long key, boolean subs) { super(cls, subs); _id = key; } /** * Primary key. */ public long getId() { return _id; } public Object getIdObject() { return _id; } protected int idHash() { return (int) (_id ^ (_id >>> 32)); } protected boolean idEquals(OpenJPAId other) { return _id == ((Id) other)._id; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyMap.java0000644000000000000000000000255312133327272025416 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Comparator; import java.util.Map; /** * Interface implemented by proxies on {@link Map} types. * * @author Abe White */ public interface ProxyMap extends Proxy, Map { /** * The map key type. */ public Class getKeyType(); /** * The map value type. */ public Class getValueType(); /** * Create a new instance of this proxy type. */ public ProxyMap newInstance(Class keyType, Class valueType, Comparator compare, boolean trackChanges, boolean autoOff); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ChangeTracker.java0000644000000000000000000000623612133327272026342 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Collection; /** * Interface for components that track changes to containers at a * fine-grained level. Proxies that use change trackers might have better * update performance than non-tracking proxies. * * @author Abe White */ public interface ChangeTracker { /** * Return true if this tracker has an up-to-date view of all the changes * to the container it is managing. */ public boolean isTracking(); /** * Reset the state of the change tracker, and turn change tracking back * on if it has been disabled. */ public void startTracking(); /** * Tell the tracker to stop tracking changes for its container. */ public void stopTracking(); /** * Return the collection of values that need to be added to the managed * container. */ public Collection getAdded(); /** * Return the set of values that need to be removed from the managed * container. */ public Collection getRemoved(); /** * Return the set of elements that have changed. In maps, this marks a * possible change in value for a key. In collections, this marks an * element that has been removed and re-added. */ public Collection getChanged(); /** * The next element sequence value for this proxy at load time. * If the data store keeps this proxy's data in sequence order but allows * holes for removed objects, the implementation can set the next * sequence at load time, then retrieve it and start from there for * added objects at flush time. This value is set back to 0 if the * proxy stops tracking changes. For ordered proxies, it is set to the * proxy's size when the proxy starts tracking changes again. */ public int getNextSequence(); /** * The maximum element sequence value for this proxy at load time. * If the data store keeps this proxy's data in sequence order but allows * holes for removed objects, the implementation can set the next * sequence at load time, then retrieve it and start from there for * added objects at flush time. This value is set back to 0 if the * proxy stops tracking changes. For ordered proxies, it is set to the * proxy's size when the proxy starts tracking changes again. */ public void setNextSequence (int seq); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java0000644000000000000000000000562212133327272026406 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.apache.openjpa.lib.util.Localizer; /** * Exception indicating that locks on one or more objects could not be acquired. * * @author Marc Prud'hommeaux * @since 0.3.1 */ @SuppressWarnings("serial") public class LockException extends StoreException { private static final transient Localizer _loc = Localizer.forPackage(LockException.class); private int timeout = -1; private int lockLevel = -1; public LockException(Object failed) { super(_loc.get("lock-failed", Exceptions.toString(failed))); setFailedObject(failed); } public LockException(Object failed, int timeout) { this(failed, timeout, -1); } public LockException(Object failed, int timeout, int lockLevel) { super(_loc.get("lock-timeout", Exceptions.toString(failed), String.valueOf(timeout))); setFailedObject(failed); setTimeout(timeout); setLockLevel(lockLevel); } public int getSubtype() { return LOCK; } /** * The number of milliseconds to wait for a lock. */ public int getTimeout() { return timeout; } /** * The number of milliseconds to wait for a lock. */ public LockException setTimeout(int timeout) { this.timeout = timeout; return this; } public void setLockLevel(int lockLevel) { this.lockLevel = lockLevel; } public int getLockLevel() { return lockLevel; } public String toString() { String str = super.toString(); if (timeout < 0) return str; return str + Exceptions.SEP + "Timeout: " + timeout + ", LockLevel" + lockLevel; } private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(timeout); out.writeInt(lockLevel); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { timeout = in.readInt(); lockLevel = in.readInt(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyCollections.java0000644000000000000000000004651712133327272027167 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerImpl; import org.apache.openjpa.kernel.DetachedValueStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StateManagerImpl; /** * Utility methods used by collection proxies. * * @author Abe White * @nojavadoc */ public class ProxyCollections extends Proxies { /** * Call before invoking {@link List#add(int,Object)} on super. */ public static void beforeAdd(ProxyCollection coll, int index, Object value){ assertAllowedType(value, coll.getElementType()); dirty(coll, true); } /** * Call before invoking {@link Vector#insertElementAt(Object,int)} on super. */ public static void beforeInsertElementAt(ProxyCollection coll, Object value, int index) { beforeAdd(coll, index, value); } /** * Call before invoking {@link Collection#add(Object)} on super. */ public static void beforeAdd(ProxyCollection coll, Object value) { assertAllowedType(value, coll.getElementType()); // Must only dirty the collection outside of a delayed load if (!isDirectAccess(coll)) { dirty(coll, false); } } /** * Call after invoking {@link Collection#add(Object)} on super. * * @param added whether the object was added * @return added, for convenience */ public static boolean afterAdd(ProxyCollection coll, Object value, boolean added) { if (!isDirectAccess(coll) && added && coll.getChangeTracker() != null) { setDirectAccess(coll,true); ((CollectionChangeTracker) coll.getChangeTracker()).added(value); setDirectAccess(coll,false); } return added; } /** * Call before invoking {@link Vector#addElement(Object)} on super. */ public static void beforeAddElement(ProxyCollection coll, Object value) { beforeAdd(coll, value); } /** * Call after invoking {@link Vector#addElement(Object)} on super. */ public static void afterAddElement(ProxyCollection coll, Object value) { afterAdd(coll, value, true); } /** * Call before invoking {@link LinkedList#addFirst(Object)} on super. */ public static void beforeAddFirst(ProxyCollection coll, Object value) { beforeAdd(coll, 0, value); } /** * Call before invoking {@link LinkedList#addLast(Object)} on super. */ public static void beforeAddLast(ProxyCollection coll, Object value) { beforeAdd(coll, value); } /** * Call after invoking {@link LinkedList#addLast(Object)} on super. */ public static void afterAddLast(ProxyCollection coll, Object value) { afterAdd(coll, value, true); } /** * Call before invoking {@link Queue#offer(Object)} on super. */ public static void beforeOffer(ProxyCollection coll, Object value) { beforeAdd(coll, value); } /** * Call after invoking {@link Queue#offer(Object)} on super. * * @param added whether the object was added * @return added, for convenience */ public static boolean afterOffer(ProxyCollection coll, Object value, boolean added) { return afterAdd(coll, value, added); } /** * Override for {@link List#addAll(int, Collection)}. */ public static boolean addAll(ProxyCollection coll, int index, Collection values) { List list = (List) coll; for (Iterator itr = values.iterator(); itr.hasNext(); index++) list.add(index, itr.next()); return values.size() > 0; } /** * Override for {@link Collection#addAll}. */ public static boolean addAll(ProxyCollection coll, Collection values) { boolean added = false; for (Iterator itr = values.iterator(); itr.hasNext();) added |= coll.add(itr.next()); return added; } /** * Call before clearing collection. */ public static void beforeClear(ProxyCollection coll) { dirty(coll, true); for (Iterator itr = coll.iterator(); itr.hasNext();) removed(coll, itr.next(), false); } /** * Call before clearing vector. */ public static void beforeRemoveAllElements(ProxyCollection coll) { beforeClear(coll); } /** * Wrap given iterator in a proxy. */ public static Iterator afterIterator(final ProxyCollection coll, final Iterator itr) { // check for proxied; some coll impls delegate iterator methods if (itr instanceof ProxyIterator) return itr; return new ProxyIterator() { private Object _last = null; public boolean hasNext() { return itr.hasNext(); } public Object next() { _last = itr.next(); return _last; } public void remove() { dirty(coll, false); itr.remove(); if (coll.getChangeTracker() != null) ((CollectionChangeTracker) coll.getChangeTracker()). removed(_last); Proxies.removed(coll, _last, false); } }; } /** * Wrap given iterator in a proxy. */ public static ListIterator afterListIterator(final ProxyCollection coll, int idx, final ListIterator itr) { return afterListIterator(coll, itr); } /** * Wrap given iterator in a proxy. */ public static ListIterator afterListIterator(final ProxyCollection coll, final ListIterator itr) { // check for proxied; some coll impls delegate iterator methods if (itr instanceof ProxyListIterator) return itr; return new ProxyListIterator() { private Object _last = null; public boolean hasNext() { return itr.hasNext(); } public int nextIndex() { return itr.nextIndex(); } public Object next() { _last = itr.next(); return _last; } public boolean hasPrevious() { return itr.hasPrevious(); } public int previousIndex() { return itr.previousIndex(); } public Object previous() { _last = itr.previous(); return _last; } public void set(Object o) { assertAllowedType(o, coll.getElementType()); dirty(coll, false); itr.set(o); if (coll.getChangeTracker() != null) coll.getChangeTracker().stopTracking(); Proxies.removed(coll, _last, false); _last = o; } public void add(Object o) { assertAllowedType(o, coll.getElementType()); dirty(coll, false); itr.add(o); if (coll.getChangeTracker() != null) { if (hasNext()) coll.getChangeTracker().stopTracking(); else ((CollectionChangeTracker) coll.getChangeTracker()). added(o); } _last = o; } public void remove() { dirty(coll, false); itr.remove(); if (coll.getChangeTracker() != null) ((CollectionChangeTracker) coll.getChangeTracker()). removed(_last); Proxies.removed(coll, _last, false); } }; } /** * Call before invoking {@link List#remove(int)} on super. */ public static void beforeRemove(ProxyCollection coll, int index) { dirty(coll, false); } /** * Call after invoking {@link List#remove(int)} on super. * * @param removed the removed object * @return the removed object, for convenience */ public static Object afterRemove(ProxyCollection coll, int index, Object removed) { if (coll.getChangeTracker() != null) ((CollectionChangeTracker) coll.getChangeTracker()). removed(removed); removed(coll, removed, false); return removed; } /** * Call before invoking {@link Vector#removeElementAt(int)} on super. */ public static void beforeRemoveElementAt(ProxyCollection coll, int index) { beforeRemove(coll, index); } /** * Call before invoking {@link Collection#remove} on super. */ public static void beforeRemove(ProxyCollection coll, Object o) { // Must only dirty the collection outside of a delayed load if (!isDirectAccess(coll)) { dirty(coll, false); } } /** * Call after invoking {@link Collection#remove} on super. * * @param removed whether the object was removed * @return whether the object was removed, for convenience */ public static boolean afterRemove(ProxyCollection coll, Object o, boolean removed){ boolean isDelayed = isDelayed(coll); boolean direct = isDirectAccess(coll); if (!isDelayed) { if (!removed) return false; } if (!direct && coll.getChangeTracker() != null) { // switch on direct access to prevent the removed op from // inadvertently loading the collection setDirectAccess(coll, true); ((CollectionChangeTracker) coll.getChangeTracker()).removed(o); setDirectAccess(coll, false); } if (!isDelayed) { removed(coll, o, false); } return true; } private static boolean isDirectAccess(ProxyCollection coll) { if (coll instanceof DelayedProxy) { DelayedProxy dpxy = (DelayedProxy)coll; return dpxy.isDirectAccess(); } return false; } private static void setDirectAccess(ProxyCollection coll, boolean direct) { if (coll instanceof DelayedProxy) { DelayedProxy dpxy = (DelayedProxy)coll; dpxy.setDirectAccess(direct); } } /** * Call before invoking {@link Vector#removeElement} on super. */ public static void beforeRemoveElement(ProxyCollection coll, Object o) { beforeRemove(coll, o); } /** * Call after invoking {@link Vector#removeElement} on super. */ public static boolean afterRemoveElement(ProxyCollection coll, Object o, boolean removed) { return afterRemove(coll, o, removed); } /** * Call before invoking {@link LinkedList#removeFirst} on super. */ public static void beforeRemoveFirst(ProxyCollection coll) { beforeRemove(coll, 0); } /** * Call after invoking {@link LinkedList#removeFirst} on super. */ public static Object afterRemoveFirst(ProxyCollection coll, Object removed){ return afterRemove(coll, 0, removed); } /** * Call after invoking {@link LinkedList#removeLast} on super. */ public static void beforeRemoveLast(ProxyCollection coll) { beforeRemove(coll, coll.size() - 1); } /** * Call after invoking {@link LinkedList#removeLast} on super. */ public static Object afterRemoveLast(ProxyCollection coll, Object removed) { return afterRemove(coll, coll.size(), removed); } /** * Call before invoking {@link Queue#remove} on super. */ public static void beforeRemove(ProxyCollection coll) { beforeRemove(coll, 0); } /** * Call after invoking {@link Queue#remove} on super. */ public static Object afterRemove(ProxyCollection coll, Object removed){ return afterRemove(coll, 0, removed); } /** * Call before invoking {@link Queue#poll} on super. */ public static void beforePoll(ProxyCollection coll) { if (!coll.isEmpty()) beforeRemove(coll, 0); } /** * Call after invoking {@link Queue#poll} on super. */ public static Object afterPoll(ProxyCollection coll, Object removed) { if (removed != null) afterRemove(coll, 0, removed); return removed; } /** * Override for {@link Collection#removeAll}. */ public static boolean removeAll(ProxyCollection coll, Collection vals) { boolean removed = false; for (Iterator itr = vals.iterator(); itr.hasNext();) removed |= coll.remove(itr.next()); return removed; } /** * Override for {@link Collection#retainAll}. */ public static boolean retainAll(ProxyCollection coll, Collection vals) { int size = coll.size(); for (Iterator itr = coll.iterator(); itr.hasNext();) if (!vals.contains(itr.next())) itr.remove(); return coll.size() < size; } /** * Call before invoking {@link List#set} on super. */ public static void beforeSet(ProxyCollection coll, int index, Object element) { assertAllowedType(element, coll.getElementType()); dirty(coll, true); } /** * Call after invoking {@link List#set} on super. * * @param replaced the replaced object * @return the replaced object, for convenience */ public static Object afterSet(ProxyCollection coll, int index, Object element, Object replaced) { if (replaced != element) removed(coll, replaced, false); return replaced; } /** * Call before invoking {@link Vector#setElementAt} on super. */ public static void beforeSetElementAt(ProxyCollection coll, Object element, int index) { beforeSet(coll, index, element); } /** * Call after invoking {@link Vector#setElementAt} on super. */ public static Object afterSetElementAt(ProxyCollection coll, Object element, int index, Object replaced) { return afterSet(coll, index, element, replaced); } /** * Marker interface for a proxied iterator. */ public static interface ProxyIterator extends Iterator { } /** * Marker interface for a proxied list iterator. */ public static interface ProxyListIterator extends ProxyIterator, ListIterator { } public static void loadCollection(ProxyCollection proxy) { loadCollection(proxy, false); } public static void loadCollection(ProxyCollection proxy, boolean detaching) { if (!isDelayed(proxy)) { return; } DelayedProxy dProxy = (DelayedProxy)proxy; if (dProxy.isDirectAccess()) { return; } boolean state[] = new boolean[2]; try { dProxy.setDirectAccess(true); state = checkState(proxy); boolean tracking = false; ChangeTracker ct = proxy.getChangeTracker(); Collection added = null; Collection removed = null; if (ct != null && ct.isTracking() ) { if (!ct.getAdded().isEmpty()) { added = new ArrayList(ct.getAdded()); } if (!ct.getRemoved().isEmpty()) { removed = new ArrayList(ct.getRemoved()); } tracking = true; ct.stopTracking(); } if (proxy.size() > 0) { proxy.clear(); } dProxy.getDelayedOwner().loadDelayedField(dProxy.getDelayedField()); if (!detaching && tracking && !ct.isTracking()) { ct.startTracking(); } // add new elements if (added != null && added.size() > 0) { dProxy.setDirectAccess(false); proxy.addAll(added); added.clear(); } // purge removed elements if (removed != null && removed.size() > 0) { dProxy.setDirectAccess(false); proxy.removeAll(removed); removed.clear(); } } finally { dProxy.setDirectAccess(false); if (state[0]) { dProxy.closeBroker(); } if (state[1]) { clearStateManager(proxy); } } } public static boolean isDelayed(ProxyCollection proxy) { if (proxy instanceof DelayedProxy) { DelayedProxy dProxy = (DelayedProxy)proxy; OpenJPAStateManager sm = dProxy.getDelayedOwner(); return (sm != null && sm.isDelayed(dProxy.getDelayedField())); } return false; } private static boolean[] checkState(ProxyCollection proxy) { boolean[] state = new boolean[2]; DelayedProxy dProxy = (DelayedProxy)proxy; OpenJPAStateManager sm = dProxy.getDelayedOwner(); if (sm != null) { // If the broker assigned to this proxy is null, closed or no longer // manages the pc, produce a new one Broker broker = sm.getContext().getBroker(); if (dProxy.isDetached() || broker == null || broker.isClosed() || (!broker.isClosed() && !broker.isPersistent(sm.getPersistenceCapable()))) { state[0] = true; broker = dProxy.getBroker(); ((StateManagerImpl)sm).setBroker((BrokerImpl)broker); } if (dProxy.isDetached() || sm.getPersistenceCapable().pcGetStateManager() == null) { state[1] = true; if (dProxy.getOwnerStateManager() != null) { sm.getPersistenceCapable().pcReplaceStateManager(dProxy.getOwnerStateManager()); ((StateManagerImpl)dProxy.getOwnerStateManager()).setBroker((BrokerImpl)broker); } else { sm.getPersistenceCapable().pcReplaceStateManager( new DetachedValueStateManager(sm.getPersistenceCapable(), sm.getContext())); } } } return state; } private static void clearStateManager(ProxyCollection proxy) { OpenJPAStateManager sm = proxy.getOwner(); if (sm != null) { sm.getPersistenceCapable().pcReplaceStateManager(null); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedLinkedHashSetProxy.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedLinkedHashSetProxy.ja0000644000000000000000000002413712133327272030332 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.DetachedStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * LinkedHashSet proxy with delay loading capability. Allows non-indexed * add and remove operations to occur on an unloaded collection. Operations * that require a load will trigger a load. */ @SuppressWarnings({"rawtypes","unchecked"}) public class DelayedLinkedHashSetProxy extends LinkedHashSet implements DelayedProxy, ProxyCollection { private transient OpenJPAStateManager sm; private transient int field; private transient CollectionChangeTracker changeTracker; private transient Class elementType; private transient OpenJPAStateManager _ownerSm; private transient boolean _directAccess = false; private transient BrokerFactory _brokerFactory = null; private transient Broker _broker = null; private transient OpenJPAStateManager _delayedSm; private transient int _delayedField; private transient boolean _detached = false; public DelayedLinkedHashSetProxy(Collection paramCollection) { super(paramCollection); } public DelayedLinkedHashSetProxy(int paramInt, float paramFloat) { super(paramInt, paramFloat); } public DelayedLinkedHashSetProxy(int paramInt) { super(paramInt); } public DelayedLinkedHashSetProxy() { } public void setOwner(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { // If clearing the owner of this proxy, store away what is necessary for // delayed loading if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) { _detached = true; _delayedSm = sm; _delayedField = field; } else { _detached = false; } this.sm = paramOpenJPAStateManager; if (sm != null && sm.getPersistenceCapable() != null) { _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable() .pcGetStateManager(); } this.field = paramInt; if (sm != null && sm.getContext() != null) { _brokerFactory = sm.getContext().getBroker().getBrokerFactory(); } } private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { if ((paramOpenJPAStateManager == null && paramInt == -1) || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) { return true; } return false; } public OpenJPAStateManager getOwner() { return this.sm; } public int getOwnerField() { return this.field; } public ChangeTracker getChangeTracker() { return this.changeTracker; } protected void setChangeTracker(CollectionChangeTracker ct) { changeTracker = ct; } @Override public Object copy(Object paramObject) { return new LinkedHashSet((Collection) paramObject); } public Class getElementType() { return this.elementType; } protected void setElementType(Class elemType) { elementType = elemType; } public ProxyCollection newInstance(Class paramClass, Comparator paramComparator, boolean paramBoolean1, boolean paramBoolean2) { DelayedLinkedHashSetProxy localproxy = new DelayedLinkedHashSetProxy(); localproxy.elementType = paramClass; if (paramBoolean1) localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl( localproxy, false, false, paramBoolean2); return localproxy; } @Override public Object clone() { if (isDirectAccess()) { return super.clone(); } if (isDelayLoad()) { load(); } Proxy localProxy = (Proxy) super.clone(); localProxy.setOwner(null, 0); return localProxy; } @Override public boolean add(Object paramObject) { if (_directAccess) { return super.add(paramObject); } ProxyCollections.beforeAdd(this, paramObject); boolean bool = super.add(paramObject); return ProxyCollections.afterAdd(this, paramObject, bool); } @Override public void clear() { if (!_directAccess) { if (isDelayLoad()) { load(); } ProxyCollections.beforeClear(this); } super.clear(); } @Override public Iterator iterator() { if (_directAccess) { return super.iterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.iterator(); return ProxyCollections.afterIterator(this, localIterator); } @Override public boolean remove(Object paramObject) { if (_directAccess) { return super.remove(paramObject); } ProxyCollections.beforeRemove(this, paramObject); setDirectAccess(true); boolean bool = super.remove(paramObject); setDirectAccess(false); return ProxyCollections.afterRemove(this, paramObject, bool); } @Override public boolean removeAll(Collection paramCollection) { if (_directAccess) { return super.removeAll(paramCollection); } return ProxyCollections.removeAll(this, paramCollection); } @Override public boolean addAll(Collection paramCollection) { if (_directAccess) { return super.addAll(paramCollection); } return ProxyCollections.addAll(this, paramCollection); } @Override public boolean retainAll(Collection paramCollection) { if (_directAccess) { return super.retainAll(paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.retainAll(this, paramCollection); } protected Object writeReplace() throws ObjectStreamException { if (isDelayLoad()) { load(); } return Proxies.writeReplace(this, true); } @Override public int size() { if (!_directAccess && isDelayLoad()) { load(); } return super.size(); } @Override public boolean isEmpty() { if (!_directAccess && isDelayLoad()) { load(); } return super.isEmpty(); } @Override public boolean contains(Object o) { if (!_directAccess && isDelayLoad()) { load(); } return super.contains(o); } @Override public Object[] toArray() { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(); } @Override public Object[] toArray(Object[] a) { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(a); } @Override public boolean containsAll(Collection c) { if (!_directAccess && isDelayLoad()) { load(); } return super.containsAll(c); } @Override public String toString() { if (!_directAccess && isDelayLoad()) { load(); } return super.toString(); } public boolean equals(Object paramObject) { if (!_directAccess && isDelayLoad()) { load(); } return super.equals(paramObject); } public int hashCode() { if (!_directAccess && isDelayLoad()) { load(); } return super.hashCode(); } // ////////////////////////////////////// // DelayedProxy methods // ////////////////////////////////////// public int getDelayedField() { if (field == -1 || _detached) { return _delayedField; } return field; } public OpenJPAStateManager getDelayedOwner() { if (sm == null || _detached) { return _delayedSm; } return sm; } public boolean isDirectAccess() { return _directAccess; } public void setDirectAccess(boolean direct) { _directAccess = direct; } public BrokerFactory getBrokerFactory() { return _brokerFactory; } @Override public void load() { ProxyCollections.loadCollection(this); } @Override public Broker getBroker() { if (_broker == null || _broker.isClosed()) { if (_brokerFactory != null) { _broker = _brokerFactory.newBroker(); } } return _broker; } @Override public void closeBroker() { if (_broker != null && !_broker.isClosed()) { _broker.setAutoDetach(AutoDetach.DETACH_CLOSE); _broker.close(); _broker = null; } } @Override public OpenJPAStateManager getOwnerStateManager() { return _ownerSm; } @Override public boolean isDetached() { return _detached; } protected boolean isDelayLoad() { return ProxyCollections.isDelayed(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/InternalException.java0000644000000000000000000000324412133327272027270 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type for internal errors. * * @author Abe White * @since 0.3.2 */ public class InternalException extends OpenJPAException { public InternalException() { setFatal(true); } public InternalException(String msg) { super(msg); setFatal(true); } public InternalException(Message msg) { super(msg); setFatal(true); } public InternalException(Throwable cause) { super(cause); setFatal(true); } public InternalException(String msg, Throwable cause) { super(msg, cause); setFatal(true); } public InternalException(Message msg, Throwable cause) { super(msg, cause); setFatal(true); } public int getType() { return INTERNAL; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java0000644000000000000000000000237112133327272030122 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type reserved for conflicts with existing objects. * * @author Abe White */ public class ObjectExistsException extends StoreException { public ObjectExistsException(String msg) { super(msg); } public ObjectExistsException(Message msg) { super(msg); } public int getSubtype() { return OBJECT_EXISTS; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/IntId.java0000644000000000000000000000334112133327272024642 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * {@link OpenJPAId} subclass appropriate for int fields. * * @author Steve Kim */ public final class IntId extends OpenJPAId { private final int key; public IntId(Class cls, Integer key) { this(cls, (key == null) ? 0 : key.intValue()); } public IntId(Class cls, String key) { this(cls, (key == null) ? 0 : Integer.parseInt(key)); } public IntId(Class cls, int key) { super(cls); this.key = key; } public IntId(Class cls, int key, boolean subs) { super(cls, subs); this.key = key; } public int getId() { return key; } public Object getIdObject() { return key; } public String toString() { return String.valueOf(key); } protected int idHash() { return key; } protected boolean idEquals(OpenJPAId o) { return key == ((IntId) o).key; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/BigIntegerId.java0000644000000000000000000000374712133327272026141 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.math.BigInteger; /** * @author Miroslav Nachev * @since 1.1.0 */ public class BigIntegerId extends OpenJPAId { private final BigInteger key; public BigIntegerId(Class cls, String key) { this(cls, (key == null) ? null : new BigInteger(key)); } public BigIntegerId(Class cls, BigInteger key) { super(cls); this.key = key; } public BigIntegerId(Class cls, BigInteger key, boolean subs) { super(cls, subs); this.key = key; } public BigInteger getId() { return key; } public Object getIdObject() { return key; } public String toString() { if (key == null) { return "NULL"; } return key.toString(); } protected int idHash() { if (key != null) { return key.hashCode(); } return 0; } protected boolean idEquals(OpenJPAId other) { if ((key == null) || (!BigIntegerId.class.isAssignableFrom(other.getClass()))) { return false; } return key.equals(((BigIntegerId)other).key); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyConcurrentMaps.java0000644000000000000000000000351312133327272027641 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Map; /** * Utility methods used by concurrent map proxies. * */ public class ProxyConcurrentMaps extends ProxyMaps { /** * Call before invoking {@link Map#remove} on super. */ public static boolean beforeRemove(ProxyMap map, Object key, Object value) { dirty(map, false); return map.containsKey(key); } /** * Call after invoking {@link Map#remove} on super. * * @param ret the return value from the super's method * @param before the return value from {@link #beforeRemove} * @return the value to return from {@link Map#remove} */ public static boolean afterRemove(ProxyMap map, Object key, Object value, boolean ret, boolean before) { if (before) { if (map.getChangeTracker() != null) { ((MapChangeTracker) map.getChangeTracker()).removed(key, ret); } removed(map, key, true); removed(map, ret, false); } return ret; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java0000644000000000000000000001172212133327272026750 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintStream; import java.io.PrintWriter; import java.io.Serializable; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type for all OpenJPA exceptions. Meant to be easily * transformed into an appropriate exception at the API layer, since most APIs * define their own exception types. * * @author Abe White * @since 0.4.0 */ @SuppressWarnings("serial") public abstract class OpenJPAException extends RuntimeException implements Serializable, ExceptionInfo { private transient boolean _fatal = false; private transient Object _failed = null; private transient Throwable[] _nested = null; /** * Default constructor. */ public OpenJPAException() { } /** * Constructor; supply message. */ public OpenJPAException(String msg) { super(msg); } /** * Constructor; supply message. */ public OpenJPAException(Message msg) { super(msg.getMessage()); } /** * Construct with cause. */ public OpenJPAException(Throwable cause) { this(cause.getMessage(), cause); } /** * Construct with message and cause. */ public OpenJPAException(String msg, Throwable cause) { super(msg); setCause(cause); } /** * Construct with message and cause. */ public OpenJPAException(Message msg, Throwable cause) { super(msg.getMessage()); setCause(cause); } /** * Exception type. */ public abstract int getType(); /** * Exception subtype. */ public int getSubtype() { return 0; } /** * Whether this error is fatal. */ public boolean isFatal() { return _fatal; } /** * Whether this error is fatal. */ public OpenJPAException setFatal(boolean fatal) { _fatal = fatal; return this; } /** * Returns the first {@link Throwable} from {@link #getNestedThrowables} * in order to conform to {@link Throwable#getCause} in Java 1.4+. * * @see Throwable#getCause */ public Throwable getCause() { if (_nested == null || _nested.length == 0) return null; else return _nested[0]; } /** * The first nested throwable. */ public OpenJPAException setCause(Throwable nested) { if (_nested != null) throw new IllegalStateException(); if (nested != null) _nested = new Throwable[]{ nested }; return this; } /** * The nested throwables. */ public Throwable[] getNestedThrowables() { return (_nested == null) ? Exceptions.EMPTY_THROWABLES : _nested; } /** * The nested throwables. */ public OpenJPAException setNestedThrowables(Throwable[] nested) { _nested = nested; return this; } /** * The failed object. */ public Object getFailedObject() { return _failed; } /** * The failed object. */ public OpenJPAException setFailedObject(Object failed) { _failed = failed; return this; } public String toString() { return Exceptions.toString(this); } public void printStackTrace() { printStackTrace(System.err); } public void printStackTrace(PrintStream out) { super.printStackTrace(out); Exceptions.printNestedThrowables(this, out); } public void printStackTrace(PrintWriter out) { super.printStackTrace(out); Exceptions.printNestedThrowables(this, out); } private void writeObject(ObjectOutputStream out) throws IOException { out.writeBoolean(_fatal); out.writeObject(Exceptions.replaceFailedObject(_failed)); out.writeObject(Exceptions.replaceNestedThrowables(_nested)); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { _fatal = in.readBoolean(); _failed = in.readObject(); _nested = (Throwable[]) in.readObject (); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ByteId.java0000644000000000000000000000340212133327272025011 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * {@link OpenJPAId} subclass appropriate for byte fields. * * @author Steve Kim */ public final class ByteId extends OpenJPAId { private final byte key; public ByteId(Class cls, Byte key) { this(cls, (key == null) ? (byte) 0 : key.byteValue()); } public ByteId(Class cls, String key) { this(cls, (key == null) ? (byte) 0 : Byte.parseByte(key)); } public ByteId(Class cls, byte key) { super(cls); this.key = key; } public ByteId(Class cls, byte key, boolean subs) { super(cls, subs); this.key = key; } public byte getId() { return key; } public Object getIdObject() { return Byte.valueOf(key); } public String toString() { return Byte.toString(key); } protected int idHash() { return key; } protected boolean idEquals(OpenJPAId o) { return key == ((ByteId) o).key; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/AbstractLRSProxyCollection.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/AbstractLRSProxyCollection.j0000644000000000000000000002713512133327272030354 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import org.apache.commons.collections.Predicate; import org.apache.commons.collections.iterators.FilterIterator; import org.apache.commons.collections.iterators.IteratorChain; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.Localizer; /** * A collection proxy designed for collections backed by extremely large * result sets in which each call to {@link #iterator} may perform a database * query. Changes to the collection are tracked through a * {@link ChangeTracker}. This collection has the following limitations: *
    *
  • The size method may return {@link Integer#MAX_VALUE}.
  • *
  • The collection cannot contain duplicate elements.
  • *
* * @author Abe White */ public abstract class AbstractLRSProxyCollection implements Set, LRSProxy, Predicate, CollectionChangeTracker { private static final Localizer _loc = Localizer.forPackage (AbstractLRSProxyCollection.class); private Class _elementType = null; private CollectionChangeTrackerImpl _ct = null; private OpenJPAStateManager _sm = null; private int _field = -1; private OpenJPAStateManager _origOwner = null; private int _origField = -1; private int _count = -1; private boolean _iterated = false; /** * Constructor. * * @param elementType the allowed type of elements, or null for no * restrictions * @param ordered true if this collection is ordered */ public AbstractLRSProxyCollection(Class elementType, boolean ordered) { _elementType = elementType; _ct = new CollectionChangeTrackerImpl(this, false, ordered,false); _ct.setAutoOff(false); } public void setOwner(OpenJPAStateManager sm, int field) { // can't transfer ownership of an lrs proxy if (sm != null && _origOwner != null && (_origOwner != sm || _origField != field)) { throw new InvalidStateException(_loc.get("transfer-lrs", _origOwner.getMetaData().getField(_origField))); } _sm = sm; _field = field; // keep track of original owner so we can detect transfer attempts if (sm != null) { _origOwner = sm; _origField = field; } } public OpenJPAStateManager getOwner() { return _sm; } public int getOwnerField() { return _field; } public ChangeTracker getChangeTracker() { return this; } public Object copy(Object orig) { // used to store fields for rollback; we don't store lrs fields return null; } public boolean add(Object o) { Proxies.assertAllowedType(o, _elementType); Proxies.dirty(this, false); _ct.added(o); return true; } public boolean addAll(Collection all) { Proxies.dirty(this, false); boolean added = false; Object add; for (Iterator itr = all.iterator(); itr.hasNext();) { add = itr.next(); Proxies.assertAllowedType(add, _elementType); _ct.added(add); added = true; } return added; } public boolean remove(Object o) { if (!contains(o)) return false; Proxies.dirty(this, false); Proxies.removed(this, o, false); _ct.removed(o); return true; } public boolean removeAll(Collection all) { Proxies.dirty(this, false); boolean removed = false; Object rem; for (Iterator itr = all.iterator(); itr.hasNext();) { rem = itr.next(); if (remove(rem)) { Proxies.removed(this, rem, false); _ct.removed(rem); removed = true; } } return removed; } public boolean retainAll(Collection all) { if (all.isEmpty()) { clear(); return true; } Proxies.dirty(this, false); Itr itr = (Itr) iterator(); try { boolean removed = false; Object rem; while (itr.hasNext()) { rem = itr.next(); if (!all.contains(rem)) { Proxies.removed(this, rem, false); _ct.removed(rem); removed = true; } } return removed; } finally { itr.close(); } } public void clear() { Proxies.dirty(this, false); Itr itr = (Itr) iterator(); try { Object rem; while (itr.hasNext()) { rem = itr.next(); Proxies.removed(this, rem, false); _ct.removed(rem); } } finally { itr.close(); } } public boolean contains(Object o) { if (_elementType != null && !_elementType.isInstance(o)) return false; if (_ct.getAdded().contains(o)) return true; if (_ct.getRemoved().contains(o)) return false; if (!has(o)) return false; return true; } public boolean containsAll(Collection all) { for (Iterator itr = all.iterator(); itr.hasNext();) if (!contains(itr.next())) return false; return true; } public Object[] toArray() { return asList().toArray(); } public Object[] toArray(Object[] a) { return asList().toArray(a); } private List asList() { Itr itr = (Itr) iterator(); try { List list = new ArrayList(); while (itr.hasNext()) list.add(itr.next()); return list; } finally { itr.close(); } } public int size() { if (_count == -1) _count = count(); if (_count == Integer.MAX_VALUE) return _count; return _count + _ct.getAdded().size() - _ct.getRemoved().size(); } public boolean isEmpty() { return size() == 0; } public Iterator iterator() { _iterated = true; IteratorChain chain = new IteratorChain(); chain.addIterator(new FilterIterator(itr(), this)); // note have to copy _ct.getAdded to prevent concurrent mod errors chain.addIterator(new ArrayList(_ct.getAdded()).iterator()); return new Itr(chain); } /** * used in testing; we need to be able to make sure that OpenJPA does not * iterate lrs fields during standard crud operations */ boolean isIterated() { return _iterated; } /** * used in testing; we need to be able to make sure that OpenJPA does not * iterate lrs fields during standard crud operations */ void setIterated(boolean it) { _iterated = it; } protected Object writeReplace() throws ObjectStreamException { return asList(); } /** * Implement this method to return an iterator over the contents of the * collection. This method may be invoked multiple times. The returned * iterator does not have to support the {@link Iterator#remove} method, * and may implement {@link org.apache.openjpa.lib.util.Closeable}. */ protected abstract Iterator itr(); /** * Return whether the collection contains the given element. */ protected abstract boolean has(Object o); /** * Return the number of elements in the collection, or * {@link Integer#MAX_VALUE}. */ protected abstract int count(); //////////////////////////// // Predicate Implementation //////////////////////////// public boolean evaluate(Object o) { return !_ct.getRemoved().contains(o); } ////////////////////////////////////////// // CollectionChangeTracker Implementation ////////////////////////////////////////// public boolean isTracking() { return _ct.isTracking(); } public void startTracking() { _ct.startTracking(); reset(); } public void stopTracking() { _ct.stopTracking(); reset(); } private void reset() { if (_count != Integer.MAX_VALUE) _count = -1; } public Collection getAdded() { return _ct.getAdded(); } public Collection getRemoved() { return _ct.getRemoved(); } public Collection getChanged() { return _ct.getChanged(); } public void added(Object val) { _ct.added(val); } public void removed(Object val) { _ct.removed(val); } public int getNextSequence() { return _ct.getNextSequence(); } public void setNextSequence(int seq) { _ct.setNextSequence(seq); } /** * Wrapper around our filtering iterator chain. */ private class Itr implements Iterator, Closeable { private static final int OPEN = 0; private static final int LAST_ELEM = 1; private static final int CLOSED = 2; private final IteratorChain _itr; private Object _last = null; private int _state = OPEN; public Itr(IteratorChain itr) { _itr = itr; } public boolean hasNext() { if (_state == CLOSED) return false; // close automatically if no more elements if (!_itr.hasNext()) { free(); _state = LAST_ELEM; return false; } return true; } public Object next() { if (_state != OPEN) throw new NoSuchElementException(); _last = _itr.next(); return _last; } public void remove() { if (_state == CLOSED || _last == null) throw new NoSuchElementException(); Proxies.dirty(AbstractLRSProxyCollection.this, false); _ct.removed(_last); Proxies.removed(AbstractLRSProxyCollection.this, _last, false); _last = null; } public void close() { free(); _state = CLOSED; } private void free() { if (_state != OPEN) return; List itrs = _itr.getIterators(); Iterator itr; for (int i = 0; i < itrs.size(); i++) { itr = (Iterator) itrs.get(i); if (itr instanceof FilterIterator) itr = ((FilterIterator) itr).getIterator(); ImplHelper.close(itr); } } protected void finalize() { close(); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/LongId.java0000644000000000000000000000340512133327272025010 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * {@link OpenJPAId} subclass appropriate for long fields. * * @author Steve Kim */ public final class LongId extends OpenJPAId { private final long key; public LongId(Class cls, Long key) { this(cls, (key == null) ? 0L : key.longValue()); } public LongId(Class cls, String key) { this(cls, (key == null) ? 0L : Long.parseLong(key)); } public LongId(Class cls, long key) { super(cls); this.key = key; } public LongId(Class cls, long key, boolean subs) { super(cls, subs); this.key = key; } public long getId() { return key; } public Object getIdObject() { return key; } public String toString() { return String.valueOf(key); } protected int idHash() { return (int) (key ^ (key >>> 32)); } protected boolean idEquals(OpenJPAId o) { return key == ((LongId) o).key; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedVectorProxy.java0000644000000000000000000004341612133327272027436 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.Collection; import java.util.Comparator; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Vector; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.DetachedStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * Vector proxy with delay loading capability. Allows non-indexed * add and remove operations to occur on an unloaded collection. Operations * that require a load will trigger a load. */ @SuppressWarnings({"rawtypes","unchecked"}) public class DelayedVectorProxy extends Vector implements ProxyCollection, DelayedProxy { private transient OpenJPAStateManager sm; private transient int field; private transient CollectionChangeTracker changeTracker; private transient Class elementType; private transient OpenJPAStateManager _ownerSm; private transient boolean _directAccess = false; private transient BrokerFactory _brokerFactory = null; private transient Broker _broker = null; private transient OpenJPAStateManager _delayedSm; private transient int _delayedField; private transient boolean _detached = false; public DelayedVectorProxy(int paramInt) { super(paramInt); } public DelayedVectorProxy() { } public DelayedVectorProxy(Collection paramCollection) { super(paramCollection); } public DelayedVectorProxy(int paramInt1, int paramInt2) { super(paramInt1, paramInt2); } @Override public void setOwner(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { // If clearing the owner of this proxy, store away what is necessary for // delayed loading if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) { _detached = true; _delayedSm = sm; _delayedField = field; } else { _detached = false; } this.sm = paramOpenJPAStateManager; if (sm != null && sm.getPersistenceCapable() != null) { _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable() .pcGetStateManager(); } this.field = paramInt; if (sm != null && sm.getContext() != null) { _brokerFactory = sm.getContext().getBroker().getBrokerFactory(); } } private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { if ((paramOpenJPAStateManager == null && paramInt == -1) || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) { return true; } return false; } @Override public int getDelayedField() { if (field == -1 || _detached) { return _delayedField; } return field; } @Override public OpenJPAStateManager getDelayedOwner() { if (sm == null || _detached) { return _delayedSm; } return sm; } @Override public OpenJPAStateManager getOwner() { return this.sm; } @Override public int getOwnerField() { return this.field; } @Override public boolean isDirectAccess() { return _directAccess; } @Override public void setDirectAccess(boolean direct) { _directAccess = direct; } public BrokerFactory getBrokerFactory() { return _brokerFactory; } @Override public void load() { ProxyCollections.loadCollection(this); } @Override public Broker getBroker() { if (_broker == null || _broker.isClosed()) { if (_brokerFactory != null) { _broker = _brokerFactory.newBroker(); } } return _broker; } @Override public void closeBroker() { if (_broker != null && !_broker.isClosed()) { _broker.setAutoDetach(AutoDetach.DETACH_CLOSE); _broker.close(); _broker = null; } } @Override public OpenJPAStateManager getOwnerStateManager() { return _ownerSm; } @Override public boolean isDetached() { return _detached; } public boolean isDelayLoad() { return ProxyCollections.isDelayed(this); } @Override public synchronized Object clone() { if (isDirectAccess()) { return super.clone(); } if (isDelayLoad()) { load(); } Proxy localProxy = (Proxy) super.clone(); localProxy.setOwner(null, 0); return localProxy; } @Override public ChangeTracker getChangeTracker() { return this.changeTracker; } protected void setChangeTracker(CollectionChangeTracker ct) { changeTracker = ct; } @Override public Object copy(Object paramObject) { if (isDelayLoad()) { load(); } return new Vector((Collection) paramObject); } @Override public Class getElementType() { return this.elementType; } protected void setElementType(Class elemType) { elementType = elemType; } @Override public ProxyCollection newInstance(Class paramClass, Comparator paramComparator, boolean paramBoolean1, boolean paramBoolean2) { DelayedVectorProxy localproxy = new DelayedVectorProxy(); localproxy.elementType = paramClass; if (paramBoolean1) { localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl( localproxy, true, true, paramBoolean2); } return localproxy; } @Override public synchronized boolean add(Object paramObject) { if (_directAccess) { return super.add(paramObject); } ProxyCollections.beforeAdd(this, paramObject); boolean bool = super.add(paramObject); return ProxyCollections.afterAdd(this, paramObject, bool); } @Override public synchronized void add(int paramInt, Object paramObject) { if (!_directAccess) { if (isDelayLoad()) { load(); } } ProxyCollections.beforeAdd(this, paramInt, paramObject); super.add(paramInt, paramObject); } @Override public void clear() { if (!_directAccess) { if (isDelayLoad()) { load(); } ProxyCollections.beforeClear(this); } super.clear(); } @Override public synchronized boolean addAll(int paramInt, Collection paramCollection) { if (_directAccess) { return super.addAll(paramInt, paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.addAll(this, paramInt, paramCollection); } @Override public synchronized boolean addAll(Collection paramCollection) { if (_directAccess) { return super.addAll(paramCollection); } return ProxyCollections.addAll(this, paramCollection); } @Override public synchronized void addElement(Object paramObject) { if (_directAccess) { super.addElement(paramObject); return; } ProxyCollections.beforeAddElement(this, paramObject); super.addElement(paramObject); ProxyCollections.afterAddElement(this, paramObject); } @Override public synchronized Object remove(int paramInt) { if (_directAccess) { return super.remove(paramInt); } if (isDelayLoad()) { load(); } ProxyCollections.beforeRemove(this, paramInt); Object localObject = super.remove(paramInt); return ProxyCollections.afterRemove(this, paramInt, localObject); } @Override public synchronized boolean remove(Object paramObject) { if (_directAccess) { return super.remove(paramObject); } ProxyCollections.beforeRemove(this, paramObject); setDirectAccess(true); boolean bool = super.remove(paramObject); setDirectAccess(false); return ProxyCollections.afterRemove(this, paramObject, bool); } @Override public synchronized Object set(int paramInt, Object paramObject) { if (_directAccess) { return super.set(paramInt, paramObject); } if (isDelayLoad()) { load(); } ProxyCollections.beforeSet(this, paramInt, paramObject); Object localObject = super.set(paramInt, paramObject); return ProxyCollections.afterSet(this, paramInt, paramObject, localObject); } @Override public synchronized boolean removeAll(Collection paramCollection) { if (_directAccess) { return super.removeAll(paramCollection); } return ProxyCollections.removeAll(this, paramCollection); } @Override public synchronized boolean retainAll(Collection paramCollection) { if (_directAccess) { return super.retainAll(paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.retainAll(this, paramCollection); } @Override public synchronized void insertElementAt(Object paramObject, int paramInt) { if (_directAccess) { super.insertElementAt(paramObject, paramInt); return; } if (isDelayLoad()) { load(); } ProxyCollections.beforeInsertElementAt(this, paramObject, paramInt); super.insertElementAt(paramObject, paramInt); } @Override public synchronized void removeAllElements() { if (_directAccess) { super.removeAllElements(); return; } if (isDelayLoad()) { load(); } ProxyCollections.beforeRemoveAllElements(this); super.removeAllElements(); } @Override public synchronized boolean removeElement(Object paramObject) { if (_directAccess) { return super.removeElement(paramObject); } ProxyCollections.beforeRemoveElement(this, paramObject); setDirectAccess(true); boolean bool = super.removeElement(paramObject); setDirectAccess(false); return ProxyCollections.afterRemoveElement(this, paramObject, bool); } @Override public synchronized void removeElementAt(int paramInt) { if (_directAccess) { super.removeElementAt(paramInt); return; } if (isDelayLoad()) { load(); } ProxyCollections.beforeRemoveElementAt(this, paramInt); super.removeElementAt(paramInt); } @Override public synchronized void setElementAt(Object paramObject, int paramInt) { if (_directAccess) { super.setElementAt(paramObject, paramInt); return; } if (isDelayLoad()) { load(); } ProxyCollections.beforeSetElementAt(this, paramObject, paramInt); super.setElementAt(paramObject, paramInt); } @Override public Iterator iterator() { if (_directAccess) { return super.iterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.iterator(); return ProxyCollections.afterIterator(this, localIterator); } @Override public ListIterator listIterator(int paramInt) { if (_directAccess) { return super.listIterator(paramInt); } if (isDelayLoad()) { load(); } ListIterator localListIterator = super.listIterator(paramInt); return ProxyCollections.afterListIterator(this, paramInt, localListIterator); } @Override public ListIterator listIterator() { if (_directAccess) { return super.listIterator(); } if (isDelayLoad()) { load(); } ListIterator localListIterator = super.listIterator(); return ProxyCollections.afterListIterator(this, localListIterator); } @Override public synchronized void setSize(int paramInt) { if (_directAccess) { super.setSize(paramInt); return; } if (isDelayLoad()) { load(); } Proxies.dirty(this, true); super.setSize(paramInt); } protected synchronized Object writeReplace() throws ObjectStreamException { if (isDelayLoad()) { load(); } return Proxies.writeReplace(this, true); } @Override public synchronized boolean contains(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.contains(object); } @Override public synchronized boolean containsAll(Collection collection) { if (!_directAccess && isDelayLoad()) { load(); } return super.containsAll(collection); } @Override public synchronized boolean isEmpty() { if (!_directAccess && isDelayLoad()) { load(); } return super.isEmpty(); } @Override public synchronized int size() { if (!_directAccess && isDelayLoad()) { load(); } return super.size(); } @Override public synchronized Object[] toArray() { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(); } @Override public synchronized Object[] toArray(Object[] array) { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(array); } @Override public synchronized boolean equals(Object paramObject) { if (!_directAccess && isDelayLoad()) { load(); } return super.equals(paramObject); } @Override public synchronized int hashCode() { if (!_directAccess && isDelayLoad()) { load(); } return super.hashCode(); } @Override public synchronized int lastIndexOf(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.lastIndexOf(object); } @Override public synchronized List subList(int start, int end) { if (!_directAccess && isDelayLoad()) { load(); } return super.subList(start, end); } @Override public synchronized Object get(int location) { if (!_directAccess && isDelayLoad()) { load(); } return super.get(location); } @Override public synchronized int indexOf(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.indexOf(object); } @Override public synchronized int indexOf(Object object, int index) { if (!_directAccess && isDelayLoad()) { load(); } return super.indexOf(object, index); } @Override public synchronized void copyInto(Object[] anArray) { if (!_directAccess && isDelayLoad()) { load(); } super.copyInto(anArray); } public synchronized void trimToSize() { if (!_directAccess && isDelayLoad()) { load(); } super.trimToSize(); } public synchronized void ensureCapacity(int minCapacity) { if (!_directAccess && isDelayLoad()) { load(); } super.ensureCapacity(minCapacity); } public synchronized int capacity() { if (!_directAccess && isDelayLoad()) { load(); } return super.capacity(); } public Enumeration elements() { if (!_directAccess && isDelayLoad()) { load(); } return super.elements(); } public synchronized int lastIndexOf(Object o, int index) { if (!_directAccess && isDelayLoad()) { load(); } return super.lastIndexOf(o, index); } public synchronized Object elementAt(int index) { if (!_directAccess && isDelayLoad()) { load(); } return super.elementAt(index); } public synchronized Object firstElement() { if (!_directAccess && isDelayLoad()) { load(); } return super.firstElement(); } public synchronized Object lastElement() { if (!_directAccess && isDelayLoad()) { load(); } return super.lastElement(); } public synchronized String toString() { if (!_directAccess && isDelayLoad()) { load(); } return super.toString(); } protected synchronized void removeRange(int fromIndex, int toIndex) { if (!_directAccess && isDelayLoad()) { load(); } super.removeRange(fromIndex, toIndex); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/FloatId.java0000644000000000000000000000344212133327272025157 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * {@link OpenJPAId} subclass appropriate for float fields. * * @author Abe White */ public final class FloatId extends OpenJPAId { private final float key; public FloatId(Class cls, Float key) { this(cls, (key == null) ? 0F : key.floatValue()); } public FloatId(Class cls, String key) { this(cls, (key == null) ? 0F : Float.parseFloat(key)); } public FloatId(Class cls, float key) { super(cls); this.key = key; } public FloatId(Class cls, float key, boolean subs) { super(cls, subs); this.key = key; } public float getId() { return key; } public Object getIdObject() { return Float.valueOf(key); } public String toString() { return Float.toString(key); } protected int idHash() { return Float.floatToIntBits(key); } protected boolean idEquals(OpenJPAId o) { return key == ((FloatId) o).key; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectNotFoundException.java0000644000000000000000000000332012133327272030372 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Collection; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type reserved for failed object lookups. * * @author Abe White */ public class ObjectNotFoundException extends StoreException { private static final transient Localizer _loc = Localizer.forPackage (ObjectNotFoundException.class); public ObjectNotFoundException(Message msg) { super(msg); } public ObjectNotFoundException(Object failed) { super(_loc.get("not-found", Exceptions.toString(failed))); setFailedObject(failed); } public ObjectNotFoundException(Collection failed, Throwable[] nested) { super(_loc.get("not-found-multi", Exceptions.toString(failed))); setNestedThrowables(nested); } public int getSubtype() { return OBJECT_NOT_FOUND; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyBean.java0000644000000000000000000000225512133327272025545 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * Interface implemented by all generated custom types, which use JavaBean * conventions for copying state. * * @author Abe White */ public interface ProxyBean extends Proxy { /** * Create a new instance of this proxy type with the same state as the * given instance. */ public ProxyBean newInstance(Object orig); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/CollectionChangeTrackerImpl.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/CollectionChangeTrackerImpl.0000644000000000000000000000730712133327272030336 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.ArrayList; import java.util.Collection; /** * Default {@link CollectionChangeTracker}. * * @author Abe White * @nojavadoc */ public class CollectionChangeTrackerImpl extends AbstractChangeTracker implements CollectionChangeTracker { protected final Collection _coll; protected final boolean _dups; protected final boolean _order; /** * Constructor. * * @param coll the collection to delegate to * @param dups true if the collection allows duplicates, false otherwise * @param order true if the collection is ordered, false otherwise */ public CollectionChangeTrackerImpl(Collection coll, boolean dups, boolean order,boolean autoOff) { _coll = coll; _dups = dups; _order = order; this.setAutoOff(autoOff); } /** * Whether the underlying collection allows duplicates. */ public boolean allowsDuplicates() { return _dups; } /** * Whether the underlying collection is ordered. */ public boolean isOrdered() { return _order; } public void added(Object elem) { super.added(elem); } public void removed(Object elem) { super.removed(elem); } protected int initialSequence() { if (_order) return _coll.size(); return super.initialSequence(); } protected void add(Object elem) { if (rem == null || !rem.remove(elem)) { // after a point it's inefficient to keep tracking if (getAutoOff() && getAdded().size() + getRemoved().size() >= _coll.size()) stopTracking(); else { if (add == null) { if (_dups || _order) add = new ArrayList(); else add = newSet(); } add.add(elem); } } else if (_order) stopTracking(); else { if (change == null) change = newSet(); change.add(elem); } } protected void remove(Object elem) { // if the collection contains multiple copies of the elem, we can't // use change tracking because some back-ends can't just delete a // single copy of a elem if (_dups && getAutoOff() && _coll.contains(elem)) stopTracking(); else if (add == null || !add.remove(elem)) { // after a point it's inefficient to keep tracking if (getAutoOff() && getRemoved().size() + getAdded().size() >= _coll.size()) stopTracking(); else { if (rem == null) rem = newSet(); rem.add(elem); } } } protected void change(Object elem) { throw new InternalException(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/OptimisticException.java0000644000000000000000000000354712133327272027646 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Collection; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type for optimistic concurrency violations. * * @author Marc Prud'hommeaux * @since 0.2.5 * @nojavadoc */ public class OptimisticException extends StoreException { private static final transient Localizer _loc = Localizer.forPackage (OptimisticException.class); public OptimisticException(Message msg) { super(msg); } public OptimisticException(Object failed) { this(_loc.get("opt-lock", Exceptions.toString(failed))); setFailedObject(failed); } public OptimisticException(Throwable[] nested) { this(_loc.get("opt-lock-nested")); setNestedThrowables(nested); } public OptimisticException(Collection failed, Throwable[] nested) { this(_loc.get("opt-lock-multi", Exceptions.toString(failed))); setNestedThrowables(nested); } public int getSubtype() { return OPTIMISTIC; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/GeneralException.java0000644000000000000000000000276012133327272027073 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * General exception type. * * @author Abe White */ public class GeneralException extends OpenJPAException { public GeneralException() { } public GeneralException(String msg) { super(msg); } public GeneralException(Message msg) { super(msg); } public GeneralException(Throwable cause) { super(cause); } public GeneralException(Message msg, Throwable cause) { super(msg, cause); } public GeneralException(String msg, Throwable cause) { super(msg, cause); } public int getType() { return GENERAL; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedCollectionChangeTrackerImpl.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedCollectionChangeTrack0000644000000000000000000000365312133327272030377 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.ArrayList; import java.util.Collection; /** * A collection change tracker used by delay loaded collections. * * @nojavadoc */ public class DelayedCollectionChangeTrackerImpl extends CollectionChangeTrackerImpl { public DelayedCollectionChangeTrackerImpl(Collection coll, boolean dups, boolean order,boolean autoOff) { super(coll, dups, order, autoOff); } protected void add(Object elem) { if (rem == null || !rem.remove(elem)) { if (add == null) { if (_dups || _order) add = new ArrayList(); else add = newSet(); } add.add(elem); } else { if (change == null) change = newSet(); change.add(elem); } } protected void remove(Object elem) { if (add == null || !add.remove(elem)) { if (rem == null) rem = newSet(); rem.add(elem); } } protected void change(Object elem) { throw new InternalException(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ExceptionInfo.java0000644000000000000000000000421212133327272026403 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * Interface supplying additional exception information. All OpenJPA * exceptions implement this interface. * * @author Abe White * @since 0.4.0 */ public interface ExceptionInfo { public static final int GENERAL = 0; public static final int INTERNAL = 1; public static final int STORE = 2; public static final int UNSUPPORTED = 3; public static final int USER = 4; public static final int WRAPPED = 5; public static final int UNAVAILABLE = 6; /** * Exception message. * * @see Throwable#getMessage */ public String getMessage(); /** * Returns the first {@link Throwable} from {@link #getNestedThrowables} * in order to conform to {@link Throwable#getCause} in Java 1.4+. * * @see Throwable#getCause */ public Throwable getCause(); /** * Stack. * * @see Throwable#printStackTrace */ public void printStackTrace(); /** * Exception type. */ public int getType(); /** * Exception subtype. */ public int getSubtype(); /** * Whether this error is fatal. */ public boolean isFatal(); /** * The nested throwables. */ public Throwable[] getNestedThrowables(); /** * The failed object. */ public Object getFailedObject(); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/MultiLoaderClassResolver.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/MultiLoaderClassResolver.jav0000644000000000000000000000330712133327272030425 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.security.AccessController; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.MultiClassLoader; /** * A simple {@link ClassResolver} that uses multiple class loaders to * resolve classes. * * @author Steve Kim */ public class MultiLoaderClassResolver implements ClassResolver { final private MultiClassLoader _loader = AccessController .doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction()); public MultiLoaderClassResolver() { } public MultiLoaderClassResolver(ClassLoader[] loaders) { for (int i = 0; i < loaders.length; i++) _loader.addClassLoader(loaders[i]); } public boolean addClassLoader(ClassLoader loader) { return _loader.addClassLoader(loader); } public ClassLoader getClassLoader(Class ctx, ClassLoader envLoader) { return _loader; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/BigDecimalId.java0000644000000000000000000000374612133327272026101 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.math.BigDecimal; /** * @author Miroslav Nachev * @since 1.1.0 */ public class BigDecimalId extends OpenJPAId { private final BigDecimal key; public BigDecimalId(Class cls, String key) { this(cls, (key == null) ? null : new BigDecimal(key)); } public BigDecimalId(Class cls, BigDecimal key) { super(cls); this.key = key; } public BigDecimalId(Class cls, BigDecimal key, boolean subs) { super(cls, subs); this.key = key; } public BigDecimal getId() { return key; } public Object getIdObject() { return key; } public String toString() { if (key == null) { return "NULL"; } return key.toString(); } protected int idHash() { if (key != null) { return key.hashCode(); } return 0; } protected boolean idEquals(OpenJPAId other) { if ((key == null) || (!BigDecimalId.class.isAssignableFrom(other.getClass()))) { return false; } return key.equals(((BigDecimalId)other).key); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/NoTransactionException.java0000644000000000000000000000236212133327272030276 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type thrown when attempting a transactional operation without * an active transaction. * * @since 0.4.0 * @author Abe White */ public class NoTransactionException extends InvalidStateException { public NoTransactionException(Message msg) { super(msg); } public int getSubtype() { return NO_TRANSACTION; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedTreeSetProxy.java0000644000000000000000000003244112133327272027543 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.NavigableSet; import java.util.SortedSet; import java.util.TreeSet; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.DetachedStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * TreeSet proxy with delay loading capability. Allows non-indexed * add and remove operations to occur on an unloaded collection. Operations * that require a load will trigger a load. */ @SuppressWarnings({"rawtypes","unchecked"}) public class DelayedTreeSetProxy extends TreeSet implements ProxyCollection, DelayedProxy { private transient OpenJPAStateManager sm; private transient int field; private transient CollectionChangeTracker changeTracker; private transient Class elementType; private transient OpenJPAStateManager _ownerSm; private transient boolean _directAccess = false; private transient BrokerFactory _brokerFactory = null; private transient Broker _broker = null; private transient OpenJPAStateManager _delayedSm; private transient int _delayedField; private transient boolean _detached = false; public DelayedTreeSetProxy() { } public DelayedTreeSetProxy(Comparator paramComparator) { super(paramComparator); } public DelayedTreeSetProxy(Collection paramCollection) { super(paramCollection); } public DelayedTreeSetProxy(SortedSet paramSortedSet) { super(paramSortedSet); } public void setOwner(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { // If clearing the owner of this proxy, store away what is necessary for // delayed loading if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) { _detached = true; _delayedSm = sm; _delayedField = field; } else { _detached = false; } this.sm = paramOpenJPAStateManager; if (sm != null && sm.getPersistenceCapable() != null) { _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable().pcGetStateManager(); } this.field = paramInt; if (sm != null && sm.getContext() != null) { _brokerFactory = sm.getContext().getBroker().getBrokerFactory(); } } private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { if ((paramOpenJPAStateManager == null && paramInt == -1) || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) { return true; } return false; } public OpenJPAStateManager getOwner() { return this.sm; } public int getOwnerField() { return this.field; } public ChangeTracker getChangeTracker() { return this.changeTracker; } protected void setChangeTracker(CollectionChangeTracker ct) { changeTracker = ct; } public Object copy(Object paramObject) { return new TreeSet((SortedSet) paramObject); } public Class getElementType() { return this.elementType; } protected void setElementType(Class elemType) { elementType = elemType; } public ProxyCollection newInstance(Class paramClass, Comparator paramComparator, boolean paramBoolean1, boolean paramBoolean2) { DelayedTreeSetProxy localproxy = new DelayedTreeSetProxy( paramComparator); localproxy.elementType = paramClass; if (paramBoolean1) localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl( localproxy, false, false, paramBoolean2); return localproxy; } @Override public Object clone() { if (_directAccess) { return super.clone(); } if (isDelayLoad()) { load(); } Proxy localProxy = (Proxy) super.clone(); localProxy.setOwner(null, 0); return localProxy; } protected Object writeReplace() throws ObjectStreamException { if (isDelayLoad()) { load(); } return Proxies.writeReplace(this, true); } //////////////////////////////////////// // DelayedProxy methods //////////////////////////////////////// public int getDelayedField() { if (field == -1 || _detached) { return _delayedField; } return field; } public OpenJPAStateManager getDelayedOwner() { if (sm == null || _detached) { return _delayedSm; } return sm; } public boolean isDirectAccess() { return _directAccess; } public void setDirectAccess(boolean direct) { _directAccess = direct; } public BrokerFactory getBrokerFactory() { return _brokerFactory; } @Override public void load() { ProxyCollections.loadCollection(this); } @Override public Broker getBroker() { if (_broker == null || _broker.isClosed()) { if (_brokerFactory != null) { _broker = _brokerFactory.newBroker(); } } return _broker; } @Override public void closeBroker() { if (_broker != null && !_broker.isClosed()) { _broker.setAutoDetach(AutoDetach.DETACH_CLOSE); _broker.close(); _broker = null; } } @Override public OpenJPAStateManager getOwnerStateManager() { return _ownerSm; } @Override public boolean isDetached() { return _detached; } public boolean isDelayLoad() { return ProxyCollections.isDelayed(this); } //////////////////////////////////////// // TreeSet methods //////////////////////////////////////// @Override public void clear() { if (!_directAccess) { if (isDelayLoad()) { load(); } ProxyCollections.beforeClear(this); } super.clear(); } @Override public Iterator iterator() { if (_directAccess) { return super.iterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.iterator(); return ProxyCollections.afterIterator(this, localIterator); } @Override public boolean remove(Object paramObject) { if (_directAccess) { return super.remove(paramObject); } ProxyCollections.beforeRemove(this, paramObject); setDirectAccess(true); boolean bool = super.remove(paramObject); setDirectAccess(false); return ProxyCollections.afterRemove(this, paramObject, bool); } @Override public int size() { if (!_directAccess && isDelayLoad()) { load(); } return super.size(); } @Override public boolean isEmpty() { if (!_directAccess && isDelayLoad()) { load(); } return super.isEmpty(); } @Override public boolean contains(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.contains(object); } @Override public Object[] toArray() { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(); } @Override public Object[] toArray(Object[] array) { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(array); } @Override public Comparator comparator() { if (!_directAccess && isDelayLoad()) { load(); } return super.comparator(); } @Override public Object first() { if (!_directAccess && isDelayLoad()) { load(); } return super.first(); } @Override public Object last() { if (!_directAccess && isDelayLoad()) { load(); } return super.last(); } @Override public boolean add(Object paramObject) { if (_directAccess) { return super.add(paramObject); } ProxyCollections.beforeAdd(this, paramObject); boolean bool = super.add(paramObject); return ProxyCollections.afterAdd(this, paramObject, bool); } @Override public boolean containsAll(Collection c) { if (!_directAccess && isDelayLoad()) { load(); } return super.containsAll(c); } @Override public boolean addAll(Collection paramCollection) { if (_directAccess) { return super.addAll(paramCollection); } return ProxyCollections.addAll(this, paramCollection); } @Override public boolean retainAll(Collection paramCollection) { if (_directAccess) { return super.retainAll(paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.retainAll(this, paramCollection); } @Override public boolean removeAll(Collection paramCollection) { if (_directAccess) { return super.removeAll(paramCollection); } return ProxyCollections.removeAll(this, paramCollection); } @Override public Object lower(Object e) { if (!_directAccess && isDelayLoad()) { load(); } return super.lower(e); } @Override public Object floor(Object e) { if (!_directAccess && isDelayLoad()) { load(); } return super.floor(e); } @Override public Object ceiling(Object e) { if (!_directAccess && isDelayLoad()) { load(); } return super.ceiling(e); } @Override public Object higher(Object e) { if (!_directAccess && isDelayLoad()) { load(); } return super.higher(e); } @Override public Object pollFirst() { if (!_directAccess && isDelayLoad()) { load(); } return super.pollFirst(); } @Override public Object pollLast() { if (!_directAccess && isDelayLoad()) { load(); } return super.pollLast(); } @Override public NavigableSet descendingSet() { if (!_directAccess && isDelayLoad()) { load(); } return super.descendingSet(); } @Override public Iterator descendingIterator() { if (_directAccess) { return super.descendingIterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.descendingIterator(); return ProxyCollections.afterIterator(this, localIterator); } @Override public NavigableSet subSet(Object fromElement, boolean fromInclusive, Object toElement, boolean toInclusive) { if (!_directAccess && isDelayLoad()) { load(); } return super.subSet(fromElement, fromInclusive, toElement, toInclusive); } @Override public NavigableSet headSet(Object toElement, boolean inclusive) { if (!_directAccess && isDelayLoad()) { load(); } return super.headSet(toElement, inclusive); } @Override public NavigableSet tailSet(Object fromElement, boolean inclusive) { if (!_directAccess && isDelayLoad()) { load(); } return super.tailSet(fromElement, inclusive); } @Override public SortedSet subSet(Object fromElement, Object toElement) { if (!_directAccess && isDelayLoad()) { load(); } return super.subSet(fromElement, toElement); } @Override public SortedSet headSet(Object toElement) { if (!_directAccess && isDelayLoad()) { load(); } return super.headSet(toElement); } @Override public SortedSet tailSet(Object fromElement) { if (!_directAccess && isDelayLoad()) { load(); } return super.tailSet(fromElement); } @Override public boolean equals(Object paramObject) { if (!_directAccess && isDelayLoad()) { load(); } return super.equals(paramObject); } @Override public int hashCode() { if (!_directAccess && isDelayLoad()) { load(); } return super.hashCode(); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/NonUniqueResultException.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/NonUniqueResultException.jav0000644000000000000000000000262012133327272030470 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type thrown when a query was configured to return * a single result, and multiple results were found. * * @since 0.9.7 * @author Marc Prud'hommeaux */ public class NonUniqueResultException extends InvalidStateException { public NonUniqueResultException(Message msg) { super(msg); } public NonUniqueResultException(Message msg, Object failed) { super(msg); setFailedObject(failed); } public int getSubtype() { return NON_UNIQUE_RESULT; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManager.java0000644000000000000000000001067412133327272026256 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Calendar; import java.util.Collection; import java.util.Comparator; import java.util.Date; import java.util.Map; import java.util.TimeZone; /** * Manager for copying and proxying second class objects. Second class * objects are those that are often used as fields of persistent or * transactional instances, and which can themselves be modified without * resetting the owning class' field. Because these types can change without * an explicit call to the owning persistence capable instance, special care * must be taken to ensure that their state is managed correctly. * Specifically, they must be copied when saving state for rollback, and they * must be proxied for any instance whose state is managed by a state manager, * where proxying involves creating a second class object that automaticlly * notifies its owning instance whenever it is modified. Generally, this * factory is only used by the implementation; second class object handling * is transparent to client code. * * @author Abe White */ public interface ProxyManager { /** * Return a new array of the same component type as the given array * and containing the same elements. Works for both primitive and * object array types. */ public Object copyArray(Object orig); /** * Return a copy of the given date with the same information. */ public Date copyDate(Date orig); /** * Return a new date proxy. */ public Proxy newDateProxy(Class type); /** * Return a copy of the given calendar with the same information. */ public Calendar copyCalendar(Calendar orig); /** * Return a new calendar proxy. */ public Proxy newCalendarProxy(Class type, TimeZone timeZone); /** * Return a new collection of the same type as the given one * with a copy of all contained elements. */ public Collection copyCollection(Collection orig); /** * Return a proxy for the given collection type. The returned collection * will allow only addition of elements assignable from the given * element type and will use the given comparator, if it is not null. */ public Proxy newCollectionProxy(Class type, Class elementType, Comparator compare, boolean autoOff); /** * Return a new map of the same type as the given one * with a copy of all contained key/value pairs. */ public Map copyMap(Map orig); /** * Return a proxy for the given map type. The returned map will * allow only addition of keys/values assignable from the given * keyType/valueType, and will use the given comparator, if it is not null. */ public Proxy newMapProxy(Class type, Class keyType, Class valueType, Comparator compare, boolean autoOff); /** * Return a copy of the given object with the same information, or null if * this manager cannot copy the object. * * @since 0.2.5 */ public Object copyCustom(Object orig); /** * Return a proxy for the given object, or null if this manager cannot * proxy the object. * * @since 0.2.5 */ public Proxy newCustomProxy (Object obj, boolean autoOff); /** * Returns whether this proxy manager is enabled for delayed collection * loading. Delayed collection loading provides the ability to do simple, * non-indexed add or remove operations on a lazy collection without * loading the collection. The collection is loaded when necessary, such * as iteration, indexed operations, isEmpty, or size. * * @since 2.2.1 */ public boolean getDelayCollectionLoading(); } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/RuntimeExceptionTranslator.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/RuntimeExceptionTranslator.j0000644000000000000000000000222612133327272030520 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.Serializable; /** * Interface used by many facade helpers to translate exceptions. * * @author Abe White * @nojavadoc */ public interface RuntimeExceptionTranslator extends Serializable { /** * Translate the given exception. */ public RuntimeException translate(RuntimeException re); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/UnsupportedException.java0000644000000000000000000000277712133327272030056 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type for attempts to perform unsupported operations. * * @author Marc Prud'hommeaux * @since 0.2.5 */ public class UnsupportedException extends OpenJPAException { public UnsupportedException() { setFatal(true); } public UnsupportedException(String msg) { super(msg); setFatal(true); } public UnsupportedException(Message msg) { super(msg); setFatal(true); } public UnsupportedException(Message msg, Throwable cause) { super(msg, cause); setFatal(true); } public int getType() { return UNSUPPORTED; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DateId.java0000644000000000000000000000364512133327272024774 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Date; /** * {@link OpenJPAId} subclass appropriate for Date fields. * * @author Marc Prud'hommeaux */ public final class DateId extends OpenJPAId { private final Date key; public DateId(Class cls, String key) { this(cls, new Date(Long.parseLong(key))); } public DateId(Class cls, Date key) { super(cls); this.key = key == null ? new Date(0) : key; } public DateId(Class cls, java.sql.Date key) { this(cls, (Date) key); } public DateId(Class cls, java.sql.Timestamp key) { this(cls, (Date) key); } public DateId(Class cls, Date key, boolean subs) { super(cls, subs); this.key = key == null ? new Date(0) : key; } public Date getId() { return key; } public Object getIdObject() { return getId(); } public String toString() { return Long.toString(key.getTime()); } protected int idHash() { return key.hashCode(); } protected boolean idEquals(OpenJPAId o) { return key.equals(((DateId) o).key); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedLinkedListProxy.java0000644000000000000000000004506712133327272030242 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.DetachedStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * LinkedList proxy with delay loading capability. Allows non-indexed * add and remove operations to occur on an unloaded collection. Operations * that require a load will trigger a load. */ @SuppressWarnings({"rawtypes","unchecked"}) public class DelayedLinkedListProxy extends LinkedList implements ProxyCollection, DelayedProxy { private transient OpenJPAStateManager sm; private transient int field; private transient CollectionChangeTracker changeTracker; private transient Class elementType; private transient OpenJPAStateManager _ownerSm; private transient boolean _directAccess = false; private transient BrokerFactory _brokerFactory = null; private transient Broker _broker = null; private transient OpenJPAStateManager _delayedSm; private transient int _delayedField; private transient boolean _detached = false; public DelayedLinkedListProxy(Collection paramCollection) { super(paramCollection); } public DelayedLinkedListProxy() { } @Override public void setOwner(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { // If clearing the owner of this proxy, store away what is necessary for // delayed loading if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) { _detached = true; _delayedSm = sm; _delayedField = field; } else { _detached = false; } this.sm = paramOpenJPAStateManager; if (sm != null && sm.getPersistenceCapable() != null) { _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable() .pcGetStateManager(); } this.field = paramInt; if (sm != null && sm.getContext() != null) { _brokerFactory = sm.getContext().getBroker().getBrokerFactory(); } } private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { if ((paramOpenJPAStateManager == null && paramInt == -1) || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) { return true; } return false; } @Override public OpenJPAStateManager getOwner() { return this.sm; } @Override public int getOwnerField() { return this.field; } @Override public ChangeTracker getChangeTracker() { return this.changeTracker; } protected void setChangeTracker(CollectionChangeTracker ct) { changeTracker = ct; } @Override public Object copy(Object paramObject) { return new LinkedList((Collection) paramObject); } @Override public Class getElementType() { return this.elementType; } protected void setElementType(Class elemType) { elementType = elemType; } @Override public ProxyCollection newInstance(Class paramClass, Comparator paramComparator, boolean paramBoolean1, boolean paramBoolean2) { DelayedLinkedListProxy localproxy = new DelayedLinkedListProxy(); localproxy.elementType = paramClass; if (paramBoolean1) localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl( localproxy, true, true, paramBoolean2); return localproxy; } // ////////////////////////////////////// // DelayedProxy methods // ////////////////////////////////////// @Override public int getDelayedField() { if (field == -1 || _detached) { return _delayedField; } return field; } @Override public OpenJPAStateManager getDelayedOwner() { if (sm == null || _detached) { return _delayedSm; } return sm; } @Override public boolean isDirectAccess() { return _directAccess; } @Override public void setDirectAccess(boolean direct) { _directAccess = direct; } public BrokerFactory getBrokerFactory() { return _brokerFactory; } @Override public void load() { ProxyCollections.loadCollection(this); } @Override public Broker getBroker() { if (_broker == null || _broker.isClosed()) { if (_brokerFactory != null) { _broker = _brokerFactory.newBroker(); } } return _broker; } @Override public void closeBroker() { if (_broker != null && !_broker.isClosed()) { _broker.setAutoDetach(AutoDetach.DETACH_CLOSE); _broker.close(); _broker = null; } } @Override public OpenJPAStateManager getOwnerStateManager() { return _ownerSm; } @Override public boolean isDetached() { return _detached; } public boolean isDelayLoad() { return ProxyCollections.isDelayed(this); } // ////////////////////////////////////// // Implementation method wrappers // ////////////////////////////////////// @Override public Object clone() { if (_directAccess) { return super.clone(); } if (isDelayLoad()) { load(); } Proxy localProxy = (Proxy) super.clone(); localProxy.setOwner(null, 0); return localProxy; } @Override public void add(int paramInt, Object paramObject) { if (!_directAccess) { if (isDelayLoad()) { load(); } } ProxyCollections.beforeAdd(this, paramInt, paramObject); super.add(paramInt, paramObject); } @Override public boolean add(Object paramObject) { if (_directAccess) { return super.add(paramObject); } ProxyCollections.beforeAdd(this, paramObject); boolean bool = super.add(paramObject); return ProxyCollections.afterAdd(this, paramObject, bool); } @Override public void clear() { if (!_directAccess) { if (isDelayLoad()) { load(); } ProxyCollections.beforeClear(this); } super.clear(); } @Override public boolean addAll(Collection paramCollection) { if (_directAccess) { return super.addAll(paramCollection); } return ProxyCollections.addAll(this, paramCollection); } @Override public boolean addAll(int paramInt, Collection paramCollection) { if (_directAccess) { return super.addAll(paramInt, paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.addAll(this, paramInt, paramCollection); } @Override public boolean remove(Object paramObject) { if (_directAccess) { return super.remove(paramObject); } ProxyCollections.beforeRemove(this, paramObject); setDirectAccess(true); boolean bool = super.remove(paramObject); setDirectAccess(false); return ProxyCollections.afterRemove(this, paramObject, bool); } @Override public Object remove(int paramInt) { if (_directAccess) { return super.remove(paramInt); } if (isDelayLoad()) { load(); } ProxyCollections.beforeRemove(this, paramInt); Object localObject = super.remove(paramInt); return ProxyCollections.afterRemove(this, paramInt, localObject); } @Override public Object remove() { if (_directAccess) { return super.remove(); } // queue operations require proper ordering. the collection // must be loaded in order to ensure order. if (isDelayLoad()) { load(); } ProxyCollections.beforeRemove(this); Object localObject = super.remove(); return ProxyCollections.afterRemove(this, localObject); } @Override public Object set(int paramInt, Object paramObject) { if (_directAccess) { return super.set(paramInt, paramObject); } if (isDelayLoad()) { load(); } ProxyCollections.beforeSet(this, paramInt, paramObject); Object localObject = super.set(paramInt, paramObject); return ProxyCollections.afterSet(this, paramInt, paramObject, localObject); } @Override public Object poll() { if (_directAccess) { return super.poll(); } // queue operations require proper ordering. the collection // must be loaded in order to ensure order. if (isDelayLoad()) { load(); } ProxyCollections.beforePoll(this); Object localObject = super.poll(); return ProxyCollections.afterPoll(this, localObject); } @Override public ListIterator listIterator(int paramInt) { if (_directAccess) { return super.listIterator(paramInt); } if (isDelayLoad()) { load(); } ListIterator localListIterator = super.listIterator(paramInt); return ProxyCollections.afterListIterator(this, paramInt, localListIterator); } @Override public void addFirst(Object paramObject) { if (_directAccess) { super.addFirst(paramObject); return; } if (isDelayLoad()) { load(); } ProxyCollections.beforeAddFirst(this, paramObject); super.addFirst(paramObject); } @Override public void addLast(Object paramObject) { if (_directAccess) { super.addLast(paramObject); return; } if (isDelayLoad()) { load(); } ProxyCollections.beforeAddLast(this, paramObject); super.addLast(paramObject); ProxyCollections.afterAddLast(this, paramObject); } @Override public boolean offer(Object paramObject) { if (_directAccess) { return super.offer(paramObject); } ProxyCollections.beforeOffer(this, paramObject); boolean bool = super.offer(paramObject); return ProxyCollections.afterOffer(this, paramObject, bool); } @Override public Object removeFirst() { if (_directAccess) { return super.removeFirst(); } if (isDelayLoad()) { load(); } ProxyCollections.beforeRemoveFirst(this); Object localObject = super.removeFirst(); return ProxyCollections.afterRemoveFirst(this, localObject); } @Override public Object removeLast() { if (_directAccess) { return super.removeLast(); } if (isDelayLoad()) { load(); } ProxyCollections.beforeRemoveLast(this); Object localObject = super.removeLast(); return ProxyCollections.afterRemoveLast(this, localObject); } @Override public Iterator iterator() { if (_directAccess) { return super.iterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.iterator(); return ProxyCollections.afterIterator(this, localIterator); } @Override public ListIterator listIterator() { if (_directAccess) { return super.listIterator(); } if (isDelayLoad()) { load(); } ListIterator localListIterator = super.listIterator(); return ProxyCollections.afterListIterator(this, localListIterator); } @Override public boolean removeAll(Collection paramCollection) { if (_directAccess) { return super.removeAll(paramCollection); } return ProxyCollections.removeAll(this, paramCollection); } @Override public boolean retainAll(Collection paramCollection) { if (_directAccess) { return super.retainAll(paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.retainAll(this, paramCollection); } @Override public boolean removeFirstOccurrence(Object paramObject) { if (_directAccess) { return super.removeFirstOccurrence(paramObject); } if (isDelayLoad()) { load(); } Proxies.dirty(this, true); return super.removeFirstOccurrence(paramObject); } @Override public boolean removeLastOccurrence(Object paramObject) { if (_directAccess) { return super.removeLastOccurrence(paramObject); } if (isDelayLoad()) { load(); } Proxies.dirty(this, true); return super.removeLastOccurrence(paramObject); } protected Object writeReplace() throws ObjectStreamException { if (isDelayLoad()) { load(); } return Proxies.writeReplace(this, true); } @Override public boolean equals(Object paramObject) { if (!_directAccess && isDelayLoad()) { load(); } return super.equals(paramObject); } @Override public int hashCode() { if (!_directAccess && isDelayLoad()) { load(); } return super.hashCode(); } @Override public List subList(int fromIndex, int toIndex) { if (!_directAccess && isDelayLoad()) { load(); } return super.subList(fromIndex, toIndex); } @Override public int lastIndexOf(Object o) { if (!_directAccess && isDelayLoad()) { load(); } return super.lastIndexOf(o); } @Override public int indexOf(Object o) { if (!_directAccess && isDelayLoad()) { load(); } return super.indexOf(o); } @Override public Object get(int index) { if (!_directAccess && isDelayLoad()) { load(); } return super.get(index); } @Override public boolean containsAll(Collection c) { if (!_directAccess && isDelayLoad()) { load(); } return super.containsAll(c); } @Override public Object[] toArray() { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(); } @Override public Object[] toArray(Object[] array) { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(array); } @Override public boolean contains(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.contains(object); } @Override public boolean isEmpty() { if (!_directAccess && isDelayLoad()) { load(); } return super.isEmpty(); } @Override public int size() { if (!_directAccess && isDelayLoad()) { load(); } return super.size(); } @Override public boolean offerFirst(Object paramObject) { if (_directAccess) { return super.offerFirst(paramObject); } if (isDelayLoad()) { load(); } return super.offerFirst(paramObject); } @Override public boolean offerLast(Object paramObject) { if (_directAccess) { return super.offerLast(paramObject); } if (isDelayLoad()) { load(); } return super.offerLast(paramObject); } @Override public Object pollFirst() { if (!_directAccess && isDelayLoad()) { load(); } return super.pollFirst(); } @Override public Object pollLast() { if (!_directAccess && isDelayLoad()) { load(); } return super.pollLast(); } @Override public Object getFirst() { if (!_directAccess && isDelayLoad()) { load(); } return super.getFirst(); } @Override public Object getLast() { if (!_directAccess && isDelayLoad()) { load(); } return super.getLast(); } @Override public Object peekFirst() { if (!_directAccess && isDelayLoad()) { load(); } return super.peekFirst(); } @Override public Object peekLast() { if (!_directAccess && isDelayLoad()) { load(); } return super.peekLast(); } @Override public Object element() { if (!_directAccess && isDelayLoad()) { load(); } return super.element(); } @Override public Object peek() { if (!_directAccess && isDelayLoad()) { load(); } return super.peek(); } @Override public void push(Object o) { if (!_directAccess && isDelayLoad()) { load(); } super.push(o); } @Override public Object pop() { if (!_directAccess && isDelayLoad()) { load(); } return super.pop(); } @Override public Iterator descendingIterator() { if (_directAccess) { return super.descendingIterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.descendingIterator(); return ProxyCollections.afterIterator(this, localIterator); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedPriorityQueueProxy.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedPriorityQueueProxy.ja0000644000000000000000000002767012133327272030477 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectStreamException; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.PriorityQueue; import java.util.SortedSet; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.DetachedStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; /** * PriorityQueue proxy with delay loading capability. Allows non-indexed * add and remove operations to occur on an unloaded collection. Operations * that require a load will trigger a load. */ @SuppressWarnings({"rawtypes","unchecked"}) public class DelayedPriorityQueueProxy extends PriorityQueue implements ProxyCollection, DelayedProxy { private transient OpenJPAStateManager sm; private transient int field; private transient CollectionChangeTracker changeTracker; private transient Class elementType; private transient OpenJPAStateManager _ownerSm; private transient boolean _directAccess = false; private transient BrokerFactory _brokerFactory = null; private transient Broker _broker = null; private transient OpenJPAStateManager _delayedSm; private transient int _delayedField; private transient boolean _detached = false; public DelayedPriorityQueueProxy(int paramInt) { super(paramInt); } public DelayedPriorityQueueProxy(int paramInt, Comparator paramComparator) { super(paramInt, paramComparator); } public DelayedPriorityQueueProxy(Collection paramCollection) { super(paramCollection); } public DelayedPriorityQueueProxy(PriorityQueue paramPriorityQueue) { super(paramPriorityQueue); } public DelayedPriorityQueueProxy(SortedSet paramSortedSet) { super(paramSortedSet); } public DelayedPriorityQueueProxy() { } @Override public void setOwner(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { // If clearing the owner of this proxy, store away what is necessary for // delayed loading if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) { _detached = true; _delayedSm = sm; _delayedField = field; } else { _detached = false; } this.sm = paramOpenJPAStateManager; if (sm != null && sm.getPersistenceCapable() != null) { _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable() .pcGetStateManager(); } this.field = paramInt; if (sm != null && sm.getContext() != null) { _brokerFactory = sm.getContext().getBroker().getBrokerFactory(); } } private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) { if ((paramOpenJPAStateManager == null && paramInt == -1) || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) { return true; } return false; } public OpenJPAStateManager getOwner() { return this.sm; } public int getOwnerField() { return this.field; } @Override public Object clone() throws CloneNotSupportedException { if (_directAccess) { return super.clone(); } if (isDelayLoad()) { load(); } Proxy localProxy = (Proxy) super.clone(); localProxy.setOwner(null, 0); return localProxy; } public ChangeTracker getChangeTracker() { return this.changeTracker; } protected void setChangeTracker(CollectionChangeTracker ct) { changeTracker = ct; } public Object copy(Object paramObject) { return new PriorityQueue((PriorityQueue) paramObject); } public Class getElementType() { return this.elementType; } protected void setElementType(Class elemType) { elementType = elemType; } public ProxyCollection newInstance(Class paramClass, Comparator paramComparator, boolean paramBoolean1, boolean paramBoolean2) { DelayedPriorityQueueProxy localproxy = new DelayedPriorityQueueProxy(); localproxy.elementType = paramClass; if (paramBoolean1) localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl( localproxy, true, false, paramBoolean2); return localproxy; } @Override public boolean add(Object paramObject) { if (_directAccess) { return super.add(paramObject); } ProxyCollections.beforeAdd(this, paramObject); boolean bool = false; try { setDirectAccess(true); bool = super.add(paramObject); } finally { setDirectAccess(false); } return ProxyCollections.afterAdd(this, paramObject, bool); } @Override public void clear() { if (!_directAccess) { if (isDelayLoad()) { load(); } ProxyCollections.beforeClear(this); } super.clear(); } @Override public Iterator iterator() { if (_directAccess) { return super.iterator(); } if (isDelayLoad()) { load(); } Iterator localIterator = super.iterator(); return ProxyCollections.afterIterator(this, localIterator); } @Override public boolean remove(Object paramObject) { if (_directAccess) { return super.remove(paramObject); } ProxyCollections.beforeRemove(this, paramObject); setDirectAccess(true); boolean bool = super.remove(paramObject); setDirectAccess(false); return ProxyCollections.afterRemove(this, paramObject, bool); } @Override public Object poll() { if (_directAccess) { return super.poll(); } // queue operations require proper ordering. the collection // must be loaded in order to ensure order. if (isDelayLoad()) { load(); } ProxyCollections.beforePoll(this); Object localObject = super.poll(); return ProxyCollections.afterPoll(this, localObject); } @Override public boolean offer(Object paramObject) { if (_directAccess) { return super.offer(paramObject); } ProxyCollections.beforeOffer(this, paramObject); boolean bool = super.offer(paramObject); return ProxyCollections.afterOffer(this, paramObject, bool); } @Override public boolean addAll(Collection paramCollection) { if (_directAccess) { return super.addAll(paramCollection); } return ProxyCollections.addAll(this, paramCollection); } @Override public Object remove() { if (_directAccess) { return super.remove(); } // queue operations require proper ordering. the collection // must be loaded in order to ensure order. if (isDelayLoad()) { load(); } ProxyCollections.beforeRemove(this); Object localObject = super.remove(); return ProxyCollections.afterRemove(this, localObject); } @Override public boolean removeAll(Collection paramCollection) { if (_directAccess) { return super.removeAll(paramCollection); } return ProxyCollections.removeAll(this, paramCollection); } @Override public boolean retainAll(Collection paramCollection) { if (_directAccess) { return super.retainAll(paramCollection); } if (isDelayLoad()) { load(); } return ProxyCollections.retainAll(this, paramCollection); } protected Object writeReplace() throws ObjectStreamException { if (isDelayLoad()) { load(); } return Proxies.writeReplace(this, true); } @Override public int size() { if (!_directAccess && isDelayLoad()) { load(); } return super.size(); } @Override public boolean isEmpty() { if (!_directAccess && isDelayLoad()) { load(); } return super.isEmpty(); } @Override public boolean contains(Object object) { if (!_directAccess && isDelayLoad()) { load(); } return super.contains(object); } @Override public Object[] toArray() { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(); } @Override public Object[] toArray(Object[] array) { if (!_directAccess && isDelayLoad()) { load(); } return super.toArray(array); } @Override public boolean containsAll(Collection c) { if (!_directAccess && isDelayLoad()) { load(); } return super.containsAll(c); } @Override public Object element() { if (!_directAccess && isDelayLoad()) { load(); } return super.element(); } @Override public Object peek() { if (!_directAccess && isDelayLoad()) { load(); } return super.peek(); } @Override public boolean equals(Object paramObject) { if (!_directAccess && isDelayLoad()) { load(); } return super.equals(paramObject); } @Override public int hashCode() { if (!_directAccess && isDelayLoad()) { load(); } return super.hashCode(); } // ////////////////////////////////////// // DelayedProxy methods // ////////////////////////////////////// @Override public int getDelayedField() { if (field == -1 || _detached) { return _delayedField; } return field; } @Override public OpenJPAStateManager getDelayedOwner() { if (sm == null || _detached) { return _delayedSm; } return sm; } @Override public boolean isDirectAccess() { return _directAccess; } @Override public void setDirectAccess(boolean direct) { _directAccess = direct; } public BrokerFactory getBrokerFactory() { return _brokerFactory; } @Override public void load() { ProxyCollections.loadCollection(this); } @Override public Broker getBroker() { if (_broker == null || _broker.isClosed()) { if (_brokerFactory != null) { _broker = _brokerFactory.newBroker(); } } return _broker; } @Override public void closeBroker() { if (_broker != null && !_broker.isClosed()) { _broker.setAutoDetach(AutoDetach.DETACH_CLOSE); _broker.close(); _broker = null; } } @Override public OpenJPAStateManager getOwnerStateManager() { return _ownerSm; } @Override public boolean isDetached() { return _detached; } public boolean isDelayLoad() { return ProxyCollections.isDelayed(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/AbstractChangeTracker.java0000644000000000000000000001405612133327272030025 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Set; import org.apache.commons.collections.set.MapBackedSet; /** * Base class that provides utilities to change trackers. * * @author Abe White * @nojavadoc */ public abstract class AbstractChangeTracker implements ChangeTracker { /** * Collection of added items. May be null. */ protected Collection add = null; /** * Collection of removed items. May be null. */ protected Collection rem = null; /** * Collection of changed items. May be null. */ protected Collection change = null; private boolean _autoOff = true; private boolean _track = false; private Boolean _identity = null; private int _seq = -1; /** * Constructor; supply configuration. */ public AbstractChangeTracker() { } /** * Whether to automatically stop tracking when the number of changes * exceeds the container size. Defaults to true. */ public boolean getAutoOff() { return _autoOff; } /** * Whether to automatically stop tracking when the number of changes * exceeds the container size. Defaults to true. */ public void setAutoOff(boolean autoOff) { _autoOff = autoOff; } public boolean isTracking() { return _track; } public void startTracking() { _track = true; if (_seq == -1) _seq = initialSequence(); reset(); } /** * Return the initial sequence value for this proxy. Typically this is * the container size. Assumes an unordered collection by default, * returning 0. */ protected int initialSequence() { return 0; } public void stopTracking() { _track = false; _seq = -1; reset(); } /** * Reset the state of the tracker. */ protected void reset() { if (add != null) add.clear(); if (rem != null) rem.clear(); if (change != null) change.clear(); _identity = null; } public Collection getAdded() { return (add == null) ? Collections.EMPTY_LIST : add; } public Collection getRemoved() { return (rem == null) ? Collections.EMPTY_LIST : rem; } public Collection getChanged() { return (change == null) ? Collections.EMPTY_LIST : change; } /** * Notify the tracker that the given object was added. */ protected void added(Object val) { if (!_track) return; setIdentity(val); add(val); } /** * Mark the given value as added. */ protected abstract void add(Object val); /** * Notify the tracker that the given object was removed. */ protected void removed(Object val) { if (!_track) return; setIdentity(val); remove(val); } /** * Mark the given value as removed. */ protected abstract void remove(Object val); /** * Notify the tracker that the given object was changed. */ protected void changed(Object val) { if (!_track) return; setIdentity(val); change(val); } /** * Mark the given value as changed. */ protected abstract void change(Object val); public int getNextSequence() { return _seq; } public void setNextSequence(int seq) { _seq = seq; } /** * Create a new set for storing adds/removes/changes. Takes into account * whether we need to use an identity set or standard set. */ protected Set newSet() { if (_identity == Boolean.TRUE) return MapBackedSet.decorate(new IdentityHashMap()); return new HashSet(); } /** * Set whether to use identity-based datastructures, and switch our current * datastructures appropriately if needed. We use identity structures for * PC types in case the user has coded them such that two objects with * different identities can compare equals(). */ private void setIdentity(Object val) { if (val == null || _identity != null) return; if (ImplHelper.isManagedType(null, val.getClass())) _identity = Boolean.TRUE; else _identity = Boolean.FALSE; add = switchStructure(add, _identity.booleanValue()); rem = switchStructure(rem, _identity.booleanValue()); change = switchStructure(change, _identity.booleanValue()); } /** * Switch from an identity structure to a standard one, or vice versa. */ private static Collection switchStructure(Collection cur, boolean identity) { if (cur == null) return null; if (identity && cur instanceof HashSet) { if (cur.isEmpty()) return null; Set replace = MapBackedSet.decorate(new IdentityHashMap()); replace.addAll(cur); return replace; } if (!identity && !(cur instanceof HashSet) && cur instanceof Set) { if (cur.isEmpty()) return null; return new HashSet(cur); } return cur; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/NoResultException.java0000644000000000000000000000255312133327272027271 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type thrown when a query was configured to return * a single result, and no result was found. * * @since 0.9.7 * @author Marc Prud'hommeaux */ public class NoResultException extends InvalidStateException { public NoResultException(Message msg) { super(msg); } public NoResultException(Message msg, Object failed) { super(msg); setFailedObject(failed); } public int getSubtype() { return NO_RESULT; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/CacheMap.java0000644000000000000000000004257212133327272025305 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.AbstractCollection; import java.util.AbstractSet; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.commons.collections.Predicate; import org.apache.commons.collections.iterators.FilterIterator; import org.apache.commons.collections.iterators.IteratorChain; import org.apache.openjpa.lib.util.LRUMap; import org.apache.openjpa.lib.util.ReferenceMap; import org.apache.openjpa.lib.util.SizedMap; import org.apache.openjpa.lib.util.concurrent.ConcurrentHashMap; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap; import java.util.concurrent.locks.ReentrantLock; /** * Fixed-size map that has ability to pin/unpin entries and move overflow to * a backing soft map. * * @author Patrick Linskey * @author Abe White */ public class CacheMap implements Map { /** * The map for non-expired and non-pinned references. */ protected final SizedMap cacheMap; /** * The map for expired references. */ protected final SizedMap softMap; /** * The set of objects pinned into the cache. */ protected final Map pinnedMap; // number of pinned values (not including keys not mapped to values) private int _pinnedSize = 0; private final ReentrantLock _writeLock = new ReentrantLock(); private final ReentrantLock _readLock; /** * Create a non-LRU (and therefore highly concurrent) cache map with a * size of 1000. */ public CacheMap() { this(false, 1000); } /** * Create a cache map with a size of 1000. * * @param lru if true, create a LRU cache map otherwise a non-LRU map will be created. */ public CacheMap(boolean lru) { this(lru, 1000); } /** * Create a cache map with the given properties. */ public CacheMap(boolean lru, int max) { this(lru, max, max / 2, .75F); } /** * @deprecated use {@link CacheMap#CacheMap(boolean, int, int, float, int)} * instead. */ public CacheMap(boolean lru, int max, int size, float load) { this(lru, max, size, load, 16); } /** * Create a cache map with the given properties. * * @since 1.1.0 */ public CacheMap(boolean lru, int max, int size, float load, int concurrencyLevel) { if (size < 0) size = 500; softMap = new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.SOFT, size, load) { public void overflowRemoved(Object key, Object value) { softMapOverflowRemoved(key, value); } public void valueExpired(Object key) { softMapValueExpired(key); } }; pinnedMap = new ConcurrentHashMap(); if (!lru) { cacheMap = new ConcurrentHashMap(size, load) { public void overflowRemoved(Object key, Object value) { cacheMapOverflowRemoved(key, value); } }; _readLock = null; } else { cacheMap = new LRUMap(size, load) { public void overflowRemoved(Object key, Object value) { cacheMapOverflowRemoved(key, value); } }; _readLock = _writeLock; } if (max < 0) max = Integer.MAX_VALUE; cacheMap.setMaxSize(max); } /** * Called from {@link SizedMap#overflowRemoved} in the cache map. */ protected void cacheMapOverflowRemoved(Object key, Object value) { if (softMap.size() < softMap.getMaxSize()) put(softMap, key, value); else entryRemoved(key, value, true); } /** * Called from {@link SizedMap#overflowRemoved} in the soft map. */ protected void softMapOverflowRemoved(Object key, Object value) { entryRemoved(key, value, true); } /** * Called when a value expires from the soft map. */ protected void softMapValueExpired(Object key) { entryRemoved(key, null, true); } /** * Put the given entry into the given map. Allows subclasses to * take additional actions. */ protected Object put(Map map, Object key, Object value) { return map.put(key, value); } /** * Remove the given key from the given map. Allows subclasses to * take additional actions. */ protected Object remove(Map map, Object key) { return map.remove(key); } /** * Acquire read lock. */ public void readLock() { if (_readLock != null) _readLock.lock(); } /** * Release read lock. */ public void readUnlock() { if (_readLock != null) _readLock.unlock(); } /** * Acquire write lock. */ public void writeLock() { _writeLock.lock(); } /** * Release write lock. */ public void writeUnlock() { _writeLock.unlock(); } /** * Whether this cache map uses LRU eviction. */ public boolean isLRU() { return _readLock != null; } /** * The maximum number of hard references to maintain, or -1 for no limit. */ public void setCacheSize(int size) { writeLock(); try { cacheMap.setMaxSize((size < 0) ? Integer.MAX_VALUE : size); } finally { writeUnlock(); } } /** * The maximum number of hard references to maintain, or -1 for no limit. */ public int getCacheSize() { int max = cacheMap.getMaxSize(); return (max == Integer.MAX_VALUE) ? -1 : max; } /** * The maximum number of soft references to maintain, or -1 for no limit. */ public void setSoftReferenceSize(int size) { writeLock(); try { softMap.setMaxSize((size < 0) ? Integer.MAX_VALUE : size); } finally { writeUnlock(); } } /** * The maximum number of soft references to maintain, or -1 for no limit. */ public int getSoftReferenceSize() { int max = softMap.getMaxSize(); return (max == Integer.MAX_VALUE) ? -1 : max; } /** * The keys pinned into the map. */ public Set getPinnedKeys() { readLock(); try { return Collections.unmodifiableSet(pinnedMap.keySet()); } finally { readUnlock(); } } /** * Locks the given key and its value into the map. Objects pinned into * the map are not counted towards the maximum cache size, and are never * evicted implicitly. You may pin keys for which no value is in the map. * * @return true if the givne key's value was pinned; false if no value * for the given key is cached */ public boolean pin(Object key) { writeLock(); try { // if we don't have a pinned map we need to create one; else if the // pinned map already contains the key, nothing to do if (pinnedMap.containsKey(key)) return pinnedMap.get(key) != null; // check other maps for key Object val = remove(cacheMap, key); if (val == null) val = remove(softMap, key); // pin key put(pinnedMap, key, val); if (val != null) { _pinnedSize++; return true; } return false; } finally { writeUnlock(); } } /** * Undo a pinning. */ public boolean unpin(Object key) { writeLock(); try { Object val = remove(pinnedMap, key); if (val != null) { // put back into unpinned cache put(key, val); _pinnedSize--; return true; } return false; } finally { writeUnlock(); } } /** * Invoked when a key-value pair is evicted from this data * structure. This is invoked with expired set to * true when an object is dropped because of space * requirements or through garbage collection of soft references. * It is invoked with expired set to false * when an object is explicitly removed via the {@link #remove} or * {@link #clear} methods. This may be invoked more than once for a * given entry. * * @param value may be null if the value was a soft reference that has * been GCd * @since 0.2.5.0 */ protected void entryRemoved(Object key, Object value, boolean expired) { } /** * Invoked when an entry is added to the cache. This may be invoked * more than once for an entry. */ protected void entryAdded(Object key, Object value) { } public Object get(Object key) { readLock(); try { // Check the main map first Object val = cacheMap.get(key); if (val == null) { // if we find the key in the soft map, move it back into // the primary map val = softMap.get(key); if (val != null){ put(key, val); }else{ val = pinnedMap.get(key); } } return val; } finally { readUnlock(); } } public Object put(Object key, Object value) { writeLock(); try { // if the key is pinned, just interact directly with the pinned map Object val; if (pinnedMap.containsKey(key)) { val = put(pinnedMap, key, value); if (val == null) { _pinnedSize++; entryAdded(key, value); } else { entryRemoved(key, val, false); entryAdded(key, value); } return val; } // if no hard refs, don't put anything if (cacheMap.getMaxSize() == 0) return null; // otherwise, put the value into the map and clear it from the // soft map val = put(cacheMap, key, value); if (val == null) { val = remove(softMap, key); if (val == null) entryAdded(key, value); else { entryRemoved(key, val, false); entryAdded(key, value); } } else { entryRemoved(key, val, false); entryAdded(key, value); } return val; } finally { writeUnlock(); } } public void putAll(Map map) { putAll(map, true); } public void putAll(Map map, boolean replaceExisting) { Map.Entry entry; for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); if(replaceExisting || !containsKey(entry.getKey())) { put(entry.getKey(), entry.getValue()); } } } /** * If key is pinned into the cache, the pin is * cleared and the object is removed. */ public Object remove(Object key) { writeLock(); try { // if the key is pinned, just interact directly with the // pinned map Object val; if (pinnedMap.containsKey(key)) { // re-put with null value; we still want key pinned val = put(pinnedMap, key, null); if (val != null) { _pinnedSize--; entryRemoved(key, val, false); } return val; } val = remove(cacheMap, key); if (val == null) val = softMap.remove(key); if (val != null) entryRemoved(key, val, false); return val; } finally { writeUnlock(); } } /** * Removes pinned objects as well as unpinned ones. */ public void clear() { writeLock(); try { notifyEntryRemovals(pinnedMap.entrySet()); pinnedMap.clear(); _pinnedSize = 0; notifyEntryRemovals(cacheMap.entrySet()); cacheMap.clear(); notifyEntryRemovals(softMap.entrySet()); softMap.clear(); } finally { writeUnlock(); } } private void notifyEntryRemovals(Set set) { Map.Entry entry; for (Iterator itr = set.iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); if (entry.getValue() != null) entryRemoved(entry.getKey(), entry.getValue(), false); } } public int size() { readLock(); try { return _pinnedSize + cacheMap.size() + softMap.size(); } finally { readUnlock(); } } public boolean isEmpty() { return size() == 0; } public boolean containsKey(Object key) { readLock(); try { return cacheMap.containsKey(key) || pinnedMap.get(key) != null || softMap.containsKey(key); } finally { readUnlock(); } } public boolean containsValue(Object val) { readLock(); try { return cacheMap.containsValue(val) || pinnedMap.containsValue(val) || softMap.containsValue(val); } finally { readUnlock(); } } public Set keySet() { return new KeySet(); } public Collection values() { return new ValueCollection(); } public Set entrySet() { return new EntrySet(); } public String toString() { readLock(); try { return "CacheMap:" + cacheMap.toString() + "::" + softMap.toString(); } finally { readUnlock(); } } /** * View of the entry set. */ private class EntrySet extends AbstractSet { public int size() { return CacheMap.this.size(); } public boolean add(Object o) { Map.Entry entry = (Map.Entry) o; put(entry.getKey(), entry.getValue()); return true; } public Iterator iterator() { return new EntryIterator(EntryIterator.ENTRY); } } /** * View of the key set. */ private class KeySet extends AbstractSet { public int size() { return CacheMap.this.size(); } public Iterator iterator() { return new EntryIterator(EntryIterator.KEY); } } /** * View of the value collection. */ private class ValueCollection extends AbstractCollection { public int size() { return CacheMap.this.size(); } public Iterator iterator() { return new EntryIterator(EntryIterator.VALUE); } } /** * Iterator over all entries. */ private class EntryIterator implements Iterator, Predicate { public static final int ENTRY = 0; public static final int KEY = 1; public static final int VALUE = 2; private final IteratorChain _itr = new IteratorChain(); private final int _type; public EntryIterator(int type) { _type = type; _itr.addIterator(new FilterIterator(getView(pinnedMap), this)); _itr.addIterator(getView(cacheMap)); _itr.addIterator(getView(softMap)); } /** * Return an iterator over the appropriate view of the given map. */ private Iterator getView(Map m) { if (m == null) return null; switch (_type) { case KEY: return m.keySet().iterator(); case VALUE: return m.values().iterator(); default: return m.entrySet().iterator(); } } public boolean hasNext() { return _itr.hasNext(); } public Object next() { return _itr.next(); } public void remove() { _itr.remove(); } public boolean evaluate(Object obj) { switch (_type) { case ENTRY: return ((Map.Entry) obj).getValue() != null; case VALUE: return obj != null; default: return true; } } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/WrappedException.java0000644000000000000000000000322112133327272027111 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; @SuppressWarnings("serial") /** * Identifiable exception type which wraps an internal runtime exception. */ public class WrappedException extends OpenJPAException { /* * Methods extending OpenJPAException * See StoreException for similar behavior */ public WrappedException(String msg) { super(msg); } public WrappedException(Message msg) { super(msg.getMessage()); } public WrappedException(Throwable cause) { super(cause); } public WrappedException(String msg, Throwable cause) { super(msg, cause); } public WrappedException(Message msg, Throwable cause) { super(msg.getMessage(), cause); } @Override public int getType() { return WRAPPED; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/LRSProxy.java0000644000000000000000000000174112133327272025337 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * Marker interface for large result set proxies. * * @author Abe White * @since 0.3.0.3 */ public interface LRSProxy extends Proxy { } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/DoubleId.java0000644000000000000000000000356312133327272025330 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * {@link OpenJPAId} subclass appropriate for double fields. * * @author Abe White */ public final class DoubleId extends OpenJPAId { private final double key; public DoubleId(Class cls, Double key) { this(cls, (key == null) ? 0D : key.doubleValue()); } public DoubleId(Class cls, String key) { this(cls, (key == null) ? 0D : Double.parseDouble(key)); } public DoubleId(Class cls, double key) { super(cls); this.key = key; } public DoubleId(Class cls, double key, boolean subs) { super(cls, subs); this.key = key; } public double getId() { return key; } public Object getIdObject() { return Double.valueOf(key); } public String toString() { return Double.toString(key); } protected int idHash() { return (int) (Double.doubleToLongBits(key) ^ (Double.doubleToLongBits(key) >>> 32)); } protected boolean idEquals(OpenJPAId o) { return key == ((DoubleId) o).key; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/MapChangeTracker.java0000644000000000000000000000420212133327272026767 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * Change tracker that can be used for maps. If the user calls * any mutating methods on the map that do not have an equivalent in * this change tracker, then you must call {@link ChangeTracker#stopTracking} * after applying the operation to the map. The collections returned from * {@link ChangeTracker#getAdded} and {@link ChangeTracker#getRemoved} will * be collections of keys to add/remove. * * @author Abe White */ public interface MapChangeTracker extends ChangeTracker { /** * Whether to track keys or values. Defaults to keys. * If you set to values, it is assumed there is a 1-1 correlation * between keys and values in this map. */ public boolean getTrackKeys(); /** * Whether to track keys or values. Defaults to keys. * If you set to values, it is assumed there is a 1-1 correlation * between keys and values in this map. */ public void setTrackKeys(boolean keys); /** * Record that the given entry was added to the map. */ public void added(Object key, Object val); /** * Record that the given entry was removed from the map. */ public void removed(Object key, Object val); /** * Record that the given entry was altered. */ public void changed(Object key, Object oldVal, Object newVal); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/MapChangeTrackerImpl.java0000644000000000000000000000756512133327272027630 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Map; /** * Default {@link MapChangeTracker}. * * @author Abe White * @nojavadoc */ public class MapChangeTrackerImpl extends AbstractChangeTracker implements MapChangeTracker { private final Map _map; private boolean _keys = true; /** * Constructor; supply delegate map. */ public MapChangeTrackerImpl(Map map, boolean autoOff) { _map = map; this.setAutoOff(autoOff); } public boolean getTrackKeys() { return _keys; } public void setTrackKeys(boolean keys) { _keys = keys; } public void added(Object key, Object val) { if (_keys) super.added(key); else super.added(val); } public void removed(Object key, Object val) { if (_keys) super.removed(key); else super.removed(val); } public void changed(Object key, Object oldVal, Object newVal) { if (_keys) super.changed(key); else { super.removed(oldVal); super.added(newVal); } } protected void add(Object obj) { // if the key was previously removed and now added back, mark // it as a change; otherwise it's a new addition if (rem != null && rem.remove(obj)) { if (change == null) change = newSet(); change.add(obj); } else { // after a point it becomes inefficient to track changes if (getAutoOff() && getAdded().size() + getChanged().size() + getRemoved().size() >= _map.size()) stopTracking(); else { if (add == null) add = newSet(); add.add(obj); } } } protected void remove(Object obj) { // no longer a change, if it was before if (change != null) change.remove(obj); // if it was a new addition, just forget it; otherwise remember // that it was removed if (add == null || !add.remove(obj)) { // after a point it becomes inefficient to track changes if (getAutoOff() && getAdded().size() + getChanged().size() + getRemoved().size() >= _map.size()) stopTracking(); else { if (rem == null) rem = newSet(); rem.add(obj); } } } protected void change(Object key) { // if the key is already changed or the key is newly added, nothing // to do if ((change != null && change.contains(key)) || (add != null && add.contains(key))) return; // after a point it becomes inefficient to track changes if (getAutoOff() && getAdded().size() + getChanged().size() + getRemoved().size() >= _map.size()) stopTracking(); else { // record the change if (change == null) change = newSet(); change.add(key); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/QueryException.java0000644000000000000000000000461312133327272026622 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.apache.openjpa.lib.util.Localizer; /** * Exception indicating that a query timeout occurred. * * @since 2.0.0 */ public class QueryException extends StoreException { private static final transient Localizer _loc = Localizer.forPackage(QueryException.class); private int timeout = -1; public QueryException(Object failed) { super(_loc.get("query-failed")); setFailedObject(failed); } public QueryException(Object failed, int timeout) { super(_loc.get("query-timeout", String.valueOf(timeout))); setFailedObject(failed); setTimeout(timeout); } public int getSubtype() { return QUERY; } /** * The number of milliseconds to wait for a query to complete. */ public int getTimeout() { return timeout; } /** * The number of milliseconds to wait for a query to complete. */ public QueryException setTimeout(int timeout) { this.timeout = timeout; return this; } public String toString() { String str = super.toString(); if (timeout < 0) return str; return str + Exceptions.SEP + "Query Timeout: " + timeout; } private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(timeout); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { timeout = in.readInt(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java0000644000000000000000000003012612133327272025675 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Map; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.enhance.ManagedInstanceProvider; import org.apache.openjpa.enhance.ReflectingPersistenceCapable; import org.apache.openjpa.enhance.RuntimeUnenhancedClassesModes; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.LockManager; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.PCState; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.kernel.StoreManager; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.ReferenceMap; import org.apache.openjpa.lib.util.UUIDGenerator; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.SequenceMetaData; import org.apache.openjpa.meta.ValueStrategies; import org.apache.openjpa.conf.OpenJPAConfiguration; /** * Helper for OpenJPA back-ends. * * @since 0.3.0 * @author Abe White * @nojavadoc */ public class ImplHelper { // Cache for from/to type assignments private static final Map _assignableTypes = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD); // map of all new unenhanced instances active in this classloader public static final Map _unenhancedInstanceMap = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD) { protected boolean eq(Object x, Object y) { // the Entries in ConcurrentReferenceHashMap delegate back to // eq() in their equals() impls if (x instanceof Map.Entry) return super.eq(x, y); else return x == y; } protected int hc(Object o) { // the Entries in ConcurrentReferenceHashMap delegate back to // hc() in their hashCode() impls if (o instanceof Map.Entry) return super.hc(o); else return System.identityHashCode(o); } }; /** * Helper for store manager implementations. This method simply delegates * to the proper singular method for each state manager. * * @see StoreManager#loadAll * @since 0.4.0 */ public static Collection loadAll(Collection sms, StoreManager store, PCState state, int load, FetchConfiguration fetch, Object context) { Collection failed = null; OpenJPAStateManager sm; LockManager lm; for (Iterator itr = sms.iterator(); itr.hasNext();) { sm = (OpenJPAStateManager) itr.next(); if (sm.getManagedInstance() == null) { if (!store.initialize(sm, state, fetch, context)) failed = addFailedId(sm, failed); } else if (load != StoreManager.FORCE_LOAD_NONE || sm.getPCState() == PCState.HOLLOW) { lm = sm.getContext().getLockManager(); if (!store.load(sm, sm.getUnloaded(fetch), fetch, lm.getLockLevel(sm), context)) failed = addFailedId(sm, failed); } else if (!store.exists(sm, context)) failed = addFailedId(sm, failed); } return (failed == null) ? Collections.EMPTY_LIST : failed; } /** * Add identity of given instance to collection. */ private static Collection addFailedId(OpenJPAStateManager sm, Collection failed) { if (failed == null) failed = new ArrayList(); failed.add(sm.getId()); return failed; } /** * Generate a value for the given metadata, or return null. Generates * values for hte following strategies: {@link ValueStrategies#SEQUENCE}, * {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX} */ public static Object generateIdentityValue(StoreContext ctx, ClassMetaData meta, int typeCode) { return generateValue(ctx, meta, null, typeCode); } /** * Generate a value for the given metadata, or return null. Generates * values for hte following strategies: {@link ValueStrategies#SEQUENCE}, * {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX} */ public static Object generateFieldValue(StoreContext ctx, FieldMetaData fmd) { return generateValue(ctx, fmd.getDefiningMetaData(), fmd, fmd.getDeclaredTypeCode()); } /** * Generate a value for the given metadaa. */ private static Object generateValue(StoreContext ctx, ClassMetaData meta, FieldMetaData fmd, int typeCode) { int strategy = (fmd == null) ? meta.getIdentityStrategy() : fmd.getValueStrategy(); switch (strategy) { case ValueStrategies.SEQUENCE: SequenceMetaData smd = (fmd == null) ? meta.getIdentitySequenceMetaData() : fmd.getValueSequenceMetaData(); return JavaTypes.convert(smd.getInstance(ctx.getClassLoader()). next(ctx, meta), typeCode); case ValueStrategies.UUID_STRING: return UUIDGenerator.nextString(UUIDGenerator.TYPE1); case ValueStrategies.UUID_HEX: return UUIDGenerator.nextHex(UUIDGenerator.TYPE1); case ValueStrategies.UUID_TYPE4_STRING: return UUIDGenerator.nextString(UUIDGenerator.TYPE4); case ValueStrategies.UUID_TYPE4_HEX: return UUIDGenerator.nextHex(UUIDGenerator.TYPE4); default: return null; } } /** * Returns the fields of the state that require an update. * * @param sm the state to check * @return the BitSet of fields that need update, or null if none */ public static BitSet getUpdateFields(OpenJPAStateManager sm) { if ((sm.getPCState() == PCState.PDIRTY && (!sm.isFlushed() || sm.isFlushedDirty())) || (sm.getPCState() == PCState.PNEW && sm.isFlushedDirty())) { BitSet dirty = sm.getDirty(); if (sm.isFlushed()) { dirty = (BitSet) dirty.clone(); dirty.andNot(sm.getFlushed()); } if (dirty.length() > 0) return dirty; } return null; } /** * Close the given resource. The resource can be an extent iterator, * query result, large result set relation, or any closeable OpenJPA * component. */ public static void close(Object o) { try { if (o instanceof Closeable) ((Closeable) o).close(); } catch (RuntimeException re) { throw re; } catch (Exception e) { throw new GeneralException(e); } } /** * Returns true if the specified class is a type that can be managed by * OpenJPA. * * @param type the class to test * @return true if the class is manageable. * * @since 1.0.0 */ public static boolean isManagedType(OpenJPAConfiguration conf, Class type) { return (PersistenceCapable.class.isAssignableFrom(type) || (type != null && (conf == null || conf.getRuntimeUnenhancedClassesConstant() == RuntimeUnenhancedClassesModes.SUPPORTED) && PCRegistry.isRegistered(type))); } /** * Returns true if the specified instance is manageable. * * @param instance the object to check * @return true if the instance is a persistent type, false otherwise */ public static boolean isManageable(Object instance) { return instance instanceof PersistenceCapable || instance != null && PCRegistry.isRegistered(instance.getClass()); } /** * Returns true if the referenced "to" class is assignable to the "from" * class. This helper method utilizes a cache to help avoid the overhead * of the Class.isAssignableFrom() method. * * @param from target class instance to be checked for assignability * @param to second class instance to be checked for assignability * @return true if the "to" class is assignable to the "from" class */ public static boolean isAssignable(Class from, Class to) { if (from == null || to == null) return false; Boolean isAssignable = null; Map assignableTo = (Map) _assignableTypes.get(from); if (assignableTo == null) { // "to" cache doesn't exist, so create it... assignableTo = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD); _assignableTypes.put(from, assignableTo); } else { // "to" cache exists... isAssignable = (Boolean) assignableTo.get(to); } if (isAssignable == null) {// we don't have a record of this pair... isAssignable = Boolean.valueOf(from.isAssignableFrom(to)); assignableTo.put(to, isAssignable); } return isAssignable.booleanValue(); } /** * @return the persistence-capable instance responsible for managing * o, or null if o is not manageable. * @since 1.0.0 */ public static PersistenceCapable toPersistenceCapable(Object o, Object ctx){ if (o instanceof PersistenceCapable) return (PersistenceCapable) o; OpenJPAConfiguration conf = null; if (ctx instanceof OpenJPAConfiguration) conf = (OpenJPAConfiguration) ctx; else if (ctx instanceof StateManager && ((StateManager) ctx).getGenericContext() instanceof StoreContext) conf = ((StoreContext) ((StateManager) ctx).getGenericContext()) .getConfiguration(); if (!isManageable(o)) return null; // if we had a putIfAbsent() method, we wouldn't need to sync here synchronized (o) { PersistenceCapable pc = (PersistenceCapable) _unenhancedInstanceMap.get(o); if (pc != null) return pc; // if we don't have a conf passed in, then we can't create a new // ReflectingPC; this will only be the case when invoked from a // context outside of OpenJPA. if (conf == null) return null; pc = new ReflectingPersistenceCapable(o, conf); _unenhancedInstanceMap.put(o, pc); return pc; } } public static void registerPersistenceCapable( ReflectingPersistenceCapable pc) { _unenhancedInstanceMap.put(pc.getManagedInstance(), pc); } /** * @return the user-visible representation of o. * @since 1.0.0 */ public static Object getManagedInstance(Object o) { if (o instanceof ManagedInstanceProvider) return ((ManagedInstanceProvider) o).getManagedInstance(); else return o; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyCalendar.java0000644000000000000000000000216112133327272026405 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * Interface implemented by all generated proxies on {@link java.util.Calendar} * types. * * @author Marc Prud'hommeaux */ public interface ProxyCalendar extends Proxy { /** * Return a new instance of this calendar type. */ public ProxyCalendar newInstance(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/Proxies.java0000644000000000000000000001660512133327272025273 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.security.AccessController; import org.apache.openjpa.conf.Compatibility; import org.apache.openjpa.kernel.DetachedStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; /** * Utility methods for managing proxies. * * @author Abe White */ public class Proxies { private static final Localizer _loc = Localizer.forPackage(Proxies.class); /** * Used by proxy types to check if the given owners and field names * are equivalent. */ public static boolean isOwner(Proxy proxy, OpenJPAStateManager sm, int field) { return proxy.getOwner() == sm && proxy.getOwnerField() == field; } /** * Used by proxy types to check that an attempt to add a new value is legal. */ public static void assertAllowedType(Object value, Class allowed) { if (value != null && allowed != null && !allowed.isInstance(value)) { throw new UserException(_loc.get("bad-elem-type", new Object[]{ AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(allowed)), allowed, AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(value.getClass())), value.getClass() })); } } /** * Used by proxy types to dirty their owner. */ public static void dirty(Proxy proxy, boolean stopTracking) { if (proxy.getOwner() != null) proxy.getOwner().dirty(proxy.getOwnerField()); if (stopTracking && proxy.getChangeTracker() != null) proxy.getChangeTracker().stopTracking(); } /** * Used by proxy types to notify collection owner on element removal. */ public static void removed(Proxy proxy, Object removed, boolean key) { if (proxy.getOwner() != null && removed != null) proxy.getOwner().removed(proxy.getOwnerField(), removed, key); } /** * Used by proxy types to serialize non-proxy versions. */ public static Object writeReplace(Proxy proxy, boolean detachable) { /* OPENJPA-1097 Remove $proxy classes during serialization based on: * 1) No Proxy, then return as-is * 2) Runtime created proxy (!detachable), then unproxy * 3) No StateManager (DetachedStateField==false), then return as-is * Get the new IgnoreDetachedStateFieldForProxySerialization * Compatibility flag from either the metadata/configuration if * this is a normal StateManager, otherwise use the new flag * added to the DetachedStateManager * 4) If new 2.0 behavior * 4a) If ClassMetaData exists and DetachedStateField == TRUE * then do not remove the proxy and return as-is * 4b) Else, using DetachedStateField of transient(default) or * false, so unproxy * 5) If 1.0 app or requested old 1.0 behavior * 5a) If detached, then do not unproxy and return as-is * 5b) Else, unproxy * * Original code - * 1) Runtime created proxy (!detachable), then unproxy * 2) No Proxy, then return as-is * 3) No StateManager (DetachedStateField==false), then return as-is * 4) If detached, then return as-is <--- ERROR as EM.clear() marks * entity as detached but doesn't remove any $proxy usage * 5) Else, unproxy * * if (detachable && (proxy == null || proxy.getOwner() == null * || proxy.getOwner().isDetached())) * return proxy; * */ if (proxy == null) { return proxy; } else if (!detachable) { // OPENJPA-1571 - using our runtime generated proxies, so remove any $proxy return proxy.copy(proxy); } else if (proxy.getOwner() == null) { // no StateManager (DetachedStateField==false), so no $proxy to remove return proxy; } else { // using a StateManager, so determine what DetachedState is being used OpenJPAStateManager sm = proxy.getOwner(); // null checked for above ClassMetaData meta = null; // if null, no proxies? boolean useDSFForUnproxy = false; // default to false for old 1.0 behavior // Don't rely on sm.isDetached() method because if we are serializing an attached Entity // the sm will still be a StateManagerImpl, but isDetached() will return true. // Using a DetachedStateManager, so use the new flag since there is no context or // metadata if (sm instanceof DetachedStateManager) { useDSFForUnproxy = ((DetachedStateManager) sm).getUseDSFForUnproxy(); } else{ // DetachedStateManager has no context or metadata, so we can't get configuration settings Compatibility compat = null; meta = sm.getMetaData(); if (meta != null) { compat = meta.getRepository().getConfiguration().getCompatibilityInstance(); } else if (sm.getContext() != null && sm.getContext().getConfiguration() != null) { compat = sm.getContext().getConfiguration().getCompatibilityInstance(); } else { // no-op - using a StateManager, but no Compatibility settings available } if (compat != null) { // new 2.0 behavior of using DetachedStateField to determine unproxy during serialization useDSFForUnproxy = !compat.getIgnoreDetachedStateFieldForProxySerialization(); } } if (useDSFForUnproxy) { // use new 2.0 behavior if ((meta != null) && (Boolean.TRUE.equals(meta.usesDetachedState()))) { // configured to always use and serialize a StateManger, so keep any $proxy return proxy; } else { // already detached or using DetachedStateField==false or transient, so remove any $proxy return proxy.copy(proxy); } } else { // use old 1.0 behavior if (proxy.getOwner().isDetached()) return proxy; else return proxy.copy(proxy); } } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/CallbackException.java0000644000000000000000000000241012133327272027202 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Exception type thrown when an error occurs in a callback. * * @since 0.4.0 * @author Marc Prud'hommeaux */ public class CallbackException extends UserException { public CallbackException(Message msg) { super(msg); } public CallbackException(Throwable cause) { super(cause); } public int getSubtype() { return CALLBACK; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/Exceptions.java0000644000000000000000000002431612133327272025761 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.PrintStream; import java.io.PrintWriter; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import org.apache.openjpa.conf.OpenJPAVersion; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.JavaVersions; /** * Utility methods for externalizing and handling exceptions. * * @author Marc Prud'hommeaux * @since 0.2.5 * @nojavadoc */ public class Exceptions { public static final Throwable[] EMPTY_THROWABLES = new Throwable[0]; static final String SEP = J2DoPrivHelper.getLineSeparator(); private static final OutputStream DEV_NULL = new OutputStream() { public void write(int b) { } }; /** * Test to see if the specified object will be able to be serialized. This * will check if the object implements {@link Serializable}, and if so, * will try to perform an actual serialization. This is in case the object * has fields which, in turn, are not serializable. * * @param ob the object to test * @return true if the object will be able to be serialized */ private static boolean isSerializable(Object ob) { if (!(ob instanceof Serializable)) return false; // don't serialize persistent objects exceptions to prevent // reading in all the state if (!ImplHelper.isManagedType(null, ob.getClass())) return false; // now do an actual test to see if we will be // able to perform the serialization try { new ObjectOutputStream(DEV_NULL).writeObject(ob); return true; } catch (Throwable t) { return false; } } /** * Safely stringify the given object. */ public static String toString(Object ob) { if (ob == null) return "null"; // don't take oid of new objects since it can cause a flush if auto-inc // and the id is meaningless anyway Object oid = getObjectId(ob); if (oid != null) { if (oid instanceof Id) return oid.toString(); String oidString = oid.toString(); // some oids stringify their class names. Some do not. if (oidString.indexOf(ob.getClass().getName()) == -1) { return ob.getClass().getName() + "-" + oidString; } else { return oidString; } } if (ImplHelper.isManagedType(null, ob.getClass())) { // never call toString() on a PersistenceCapable, since // it may access persistent fields; fall-back to using // the standard object stringification mechanism. New // instances that use proxying (property-access instances, // for example) that were created with the 'new' keyword // will not end up in this code, which is ok since they // don't do lazy loading anyways, so they will stringify // safely. return ob.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(ob)); } try { String s = ob.toString(); if (s.indexOf(ob.getClass().getName()) == -1) s += " [" + ob.getClass().getName() + "]"; return s; } catch (Throwable t) { return ob.getClass().getName(); } } /** * Safely stringify the given objects. */ public static String toString(Collection failed) { StringBuilder buf = new StringBuilder(); buf.append("["); for (Iterator itr = failed.iterator(); itr.hasNext();) { buf.append(Exceptions.toString(itr.next())); if (itr.hasNext()) buf.append(", "); } buf.append("]"); return buf.toString(); } /** * Stringify the given exception. */ public static String toString(ExceptionInfo e) { int type = e.getType(); StringBuilder buf = new StringBuilder(); buf.append("<"). append(OpenJPAVersion.VERSION_ID). append(' '). append(e.isFatal() ? "fatal " : "nonfatal "). append (type == ExceptionInfo.GENERAL ? "general error" : type == ExceptionInfo.INTERNAL ? "internal error" : type == ExceptionInfo.STORE ? "store error" : type == ExceptionInfo.UNSUPPORTED ? "unsupported error" : type == ExceptionInfo.USER ? "user error" : (type + " error")). append("> "); buf.append(e.getClass().getName()).append(": "). append(e.getMessage()); Object failed = e.getFailedObject(); if (failed != null) buf.append(SEP).append("FailedObject: "). append(toString(failed)); return buf.toString(); } /** * Print the stack trace of the exception's nested throwables. */ public static void printNestedThrowables(ExceptionInfo e, PrintStream out) { // if this is Java 1.4 and there is exactly a single // exception, then defer to 1.4's behavior of printing // out the result of getCause(). This deferral happens in // the calling code. Throwable[] nested = e.getNestedThrowables(); int i = (JavaVersions.VERSION >= 4) ? 1 : 0; if (i < nested.length) { out.println("NestedThrowables:"); for (; i < nested.length; i++) // guard against a nasty null in the array if (nested[i] != null) nested[i].printStackTrace(out); } } /** * Print the stack trace of the exception's nested throwables. */ public static void printNestedThrowables(ExceptionInfo e, PrintWriter out) { // if this is Java 1.4 and there is exactly a single // exception, then defer to 1.4's behavior of printing // out the result of getCause(). This deferral happens in // the calling code. Throwable[] nested = e.getNestedThrowables(); int i = (JavaVersions.VERSION >= 4) ? 1 : 0; if (i < nested.length) { out.println("NestedThrowables:"); for (; i < nested.length; i++) // guard against a nasty null in the array if (nested[i] != null) nested[i].printStackTrace(out); } } /** * Convert the specified failed object into a serializable * object for when we are serializing an Exception. It will * try the following: *
    *
  • if the object can be serialized, return the object itself
  • *
  • if the object has a serializable oid, return the oid
  • *
  • if the object has a non-serializable oid, return the oid's * toString and the object class
  • *
  • return the object's toString
  • *
* * @param ob the object to convert * @return some serialized representation of the object */ public static Object replaceFailedObject(Object ob) { if (ob == null) return null; if (isSerializable(ob)) return ob; // don't take oid of new objects since it can cause a flush if auto-inc // and the id is meaningless anyway Object oid = getObjectId(ob); if (oid != null && isSerializable(oid)) return oid; // last ditch: stringify the object return toString(ob); } /** * Convert the specified throwables into a serialzable array. If * any of the nested throwables cannot be serialized, they will * be converted into a Exception with the original message. */ public static Throwable[] replaceNestedThrowables(Throwable[] nested) { if (nested == null || nested.length == 0) return nested; if (isSerializable(nested)) return nested; Throwable[] newNested = new Throwable[nested.length]; for (int i = 0; i < nested.length; i++) { if (isSerializable(nested[i])) newNested[i] = nested[i]; else // guard against a nasty null in the array by using valueOf // instead of toString to prevent throwing yet another // exception newNested[i] = new Exception(String.valueOf(nested[i])); } return newNested; } /** * Return the object id for ob if it has one, or * null otherwise. */ private static Object getObjectId(Object ob) { if (!ImplHelper.isManageable(ob)) return null; PersistenceCapable pc = ImplHelper.toPersistenceCapable(ob, null); if (pc == null || pc.pcIsNew()) return null; else return pc.pcFetchObjectId(); } public static String toClassName(Class cls) { if (cls == null) return ""; if (cls.isArray()) return toClassName(cls.getComponentType())+"[]"; return cls.getName(); } public static String toClassNames(Collection> classes) { if (classes == null) return ""; StringBuilder buffer = new StringBuilder(); for (Class cls : classes) { buffer.append("\r\n").append(toClassName(cls)); } return buffer.toString(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ArrayStateImage.java0000644000000000000000000000671612133327272026666 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.BitSet; import org.apache.commons.lang.ObjectUtils; /** * Utilities for dealing with a simple state image consisting of an * Object[] of field values with one extra index containing a * {@link BitSet} of loaded fields. This simplistic state image might be used * for optimistic versioning. * * @author Abe White * @nojavadoc */ public class ArrayStateImage { /** * Create a new state image for the given number of fields. */ public static Object[] newImage(int numFields) { Object[] state = new Object[numFields + 1]; state[numFields] = new BitSet(numFields); return state; } /** * Return true if the given version object appears to be an array state * image. */ public static boolean isImage(Object obj) { if (!(obj instanceof Object[])) return false; Object[] arr = (Object[]) obj; return arr.length > 0 && arr[arr.length - 1] instanceof BitSet; } /** * Get the loaded mask from a state image. */ public static BitSet getLoaded(Object[] state) { return (BitSet) state[state.length - 1]; } /** * Set the loaded mask into a state image. */ public static void setLoaded(Object[] state, BitSet loaded) { state[state.length - 1] = loaded; } /** * Clone a state array. */ public static Object[] clone(Object[] state) { Object[] copy = new Object[state.length]; System.arraycopy(state, 0, copy, 0, state.length - 1); BitSet loaded = (BitSet) state[state.length - 1]; copy[copy.length - 1] = loaded.clone(); return copy; } /** * Return whether the given images are equivalent from an optimistic * locking perspective. */ public static boolean sameVersion(Object[] state1, Object[] state2) { if (state1 == state2) return true; // if either state is null, then we report that it is the // same: this is because a null version will indicate that // there are no loaded fields in the version at all, which // indicates that there is nothing to compare if (state1 == null || state2 == null) return true; // check only the fields that are in the loaded set for the // first version BitSet loaded1 = getLoaded(state1); BitSet loaded2 = getLoaded(state2); for (int i = 0, max = loaded1.length(); i < max; i++) { if (loaded1.get(i) && loaded2.get(i) && !ObjectUtils.equals(state1[i], state2[i])) return false; } return true; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyCollection.java0000644000000000000000000000247012133327272026772 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.util.Collection; import java.util.Comparator; /** * Interface implemented by all proxy collection types. * * @author Abe White */ public interface ProxyCollection extends Proxy, Collection { /** * The collection element type. */ public Class getElementType(); /** * Create a new instance of this proxy type. */ public ProxyCollection newInstance(Class elementType, Comparator comp, boolean trackChanges, boolean autoOff); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ClassResolver.java0000644000000000000000000000317512133327272026427 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.MultiClassLoader; /** * Interface to customize the loading of classes under OpenJPA. * * @since 0.3.0 * @author Marc Prud'hommeaux * @author Abe White */ public interface ClassResolver { /** * Return a class loader that can be used to load classes and resources. * This can be a standard class loader, or a customized loader such * as a {@link MultiClassLoader}. * * @param contextClass the context class; may be null if no context class * @param envLoader the thread's context class loader when the * persistence environment (i.e. broker) * was obtained; may be null if operating outside * the context of persistence environment */ public ClassLoader getClassLoader(Class contextClass, ClassLoader envLoader); } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ReferentialIntegrityException.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ReferentialIntegrityExceptio0000644000000000000000000000530312133327272030553 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.apache.openjpa.lib.util.Localizer; /** * Exception type reserved for violations of integrity constraints. * * @author Patrick Linskey */ public class ReferentialIntegrityException extends StoreException { public static final int IV_UNKNOWN = 0; public static final int IV_DUPLICATE_OID = 1; public static final int IV_UNIQUE = 2; public static final int IV_REFERENCE = 3; public static final int IV_MIXED = 4; private static final transient Localizer _loc = Localizer.forPackage (ReferentialIntegrityException.class); private int _iv = IV_UNKNOWN; public ReferentialIntegrityException(String msg) { super(msg); } public ReferentialIntegrityException(int iv) { this(getMessage(iv)); setIntegrityViolation(iv); } private static String getMessage(int iv) { switch (iv) { case IV_DUPLICATE_OID: return _loc.get("dup-oid").getMessage(); case IV_UNIQUE: return _loc.get("unique").getMessage(); default: return _loc.get("ref-integrity").getMessage(); } } public int getSubtype() { return REFERENTIAL_INTEGRITY; } /** * The type of integrity violation that occurred. */ public int getIntegrityViolation() { return _iv; } /** * The type of integrity violation that occurred. */ public ReferentialIntegrityException setIntegrityViolation(int iv) { _iv = iv; return this; } private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(_iv); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { _iv = in.readInt(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/CharId.java0000644000000000000000000000340712133327272024770 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; /** * {@link OpenJPAId} subclass appropriate for char fields. * * @author Steve Kim */ public final class CharId extends OpenJPAId { private final char key; public CharId(Class cls, Character key) { this(cls, (key == null) ? (char) 0 : key.charValue()); } public CharId(Class cls, String key) { this(cls, (key == null) ? (char) 0 : key.charAt(0)); } public CharId(Class cls, char key) { super(cls); this.key = key; } public CharId(Class cls, char key, boolean subs) { super(cls, subs); this.key = key; } public char getId() { return key; } public Object getIdObject() { return Character.valueOf(key); } public String toString() { return String.valueOf(key); } protected int idHash() { return key; } protected boolean idEquals(OpenJPAId o) { return key == ((CharId) o).key; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/ClassResolverImpl.java0000644000000000000000000000530012133327272027241 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.security.AccessController; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.MultiClassLoader; /** * Default class resolver implementation. * * @since 0.3.0 * @author Abe White */ public class ClassResolverImpl implements ClassResolver { public ClassLoader getClassLoader(Class contextClass, ClassLoader envLoader) { // get the context class' loader; if the class was loaded by the // bootstrap loader, use the system classloader in the hopes that // class.forName calls on it will find the bootstrap loader's cached // class (the bootstrap loader is the parent of the system loader) ClassLoader contextLoader = null; if (contextClass != null) { contextLoader = AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(contextClass)); if (contextLoader == null) contextLoader = AccessController.doPrivileged( J2DoPrivHelper.getSystemClassLoaderAction()); } // if there is only one unique loader, just return it ClassLoader threadLoader = AccessController.doPrivileged( J2DoPrivHelper.getContextClassLoaderAction()); if ((contextLoader == null || contextLoader == threadLoader) && (envLoader == null || envLoader == threadLoader)) return threadLoader; // construct a multi class loader that will delegate in the order // described in section 12.5 of the spec MultiClassLoader loader = AccessController .doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction()); if (contextLoader != null) loader.addClassLoader(contextLoader); loader.addClassLoader(threadLoader); if (envLoader != null) loader.addClassLoader(envLoader); return loader; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/util/StoreException.java0000644000000000000000000000345612133327272026615 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import org.apache.openjpa.lib.util.Localizer.Message; /** * Base exception for data store errors. * * @author Marc Prud'hommeaux * @since 0.2.5 */ @SuppressWarnings("serial") public class StoreException extends OpenJPAException { public static final int LOCK = 1; public static final int OBJECT_NOT_FOUND = 2; public static final int OPTIMISTIC = 3; public static final int REFERENTIAL_INTEGRITY = 4; public static final int OBJECT_EXISTS = 5; public static final int QUERY = 6; public StoreException(String msg) { super(msg); } public StoreException(Message msg) { super(msg.getMessage()); } public StoreException(Throwable cause) { super(cause); } public StoreException(String msg, Throwable cause) { super(msg, cause); } public StoreException(Message msg, Throwable cause) { super(msg.getMessage(), cause); } public int getType() { return STORE; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/0000755000000000000000000000000012133327272023413 5ustar ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.j0000644000000000000000000004322512133327272030354 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.lang.reflect.Constructor; import java.security.AccessController; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.InternalException; import serp.bytecode.BCClass; import serp.bytecode.BCClassLoader; import serp.bytecode.BCField; import serp.bytecode.BCMethod; import serp.bytecode.Code; import serp.bytecode.Constants; import serp.bytecode.Instruction; import serp.bytecode.JumpInstruction; import serp.bytecode.LoadInstruction; import serp.bytecode.Project; import serp.bytecode.TableSwitchInstruction; /** * Factory for creating new {@link DynamicStorage} classes. Can be * extended to decorate/modify the generated instances behavior. * * @author Steve Kim * @nojavadoc * @since 0.3.2.0 */ public class DynamicStorageGenerator { // prefix for generic generated classes. private static final String PREFIX = "openjpastorage$"; /** * Constant to throw an exception on invalid index passed to type set/get * methods */ protected static final int POLICY_EXCEPTION = 0; /** * Constant to not generate type set/get methods. */ protected static final int POLICY_EMPTY = 1; /** * Constant to be as silent as possible during invalid index passed * to set/get type methods. On getting an Object, for example, * null will be returned. * However, on primitive gets, an exception will be thrown. */ protected static final int POLICY_SILENT = 2; // wrappers for primitive types private static final Class[][] WRAPPERS = new Class[][]{ { boolean.class, Boolean.class }, { byte.class, Byte.class }, { char.class, Character.class }, { int.class, Integer.class }, { short.class, Short.class }, { long.class, Long.class }, { float.class, Float.class }, { double.class, Double.class }, }; // primitive types private static final int[] TYPES = new int[]{ JavaTypes.BOOLEAN, JavaTypes.BYTE, JavaTypes.CHAR, JavaTypes.INT, JavaTypes.SHORT, JavaTypes.LONG, JavaTypes.FLOAT, JavaTypes.DOUBLE, JavaTypes.OBJECT }; // the project/classloader for the classes. private final Project _project = new Project(); private final BCClassLoader _loader = AccessController.doPrivileged(J2DoPrivHelper.newBCClassLoaderAction( _project, AccessController.doPrivileged(J2DoPrivHelper .getClassLoaderAction(DynamicStorage.class)))); /** * Generate a generic {@link DynamicStorage} instance with the given * array of {@link JavaTypes} constants and the given object as * the user key for generation. */ public DynamicStorage generateStorage(int[] types, Object obj) { if (obj == null) return null; String name = getClassName(obj); BCClass bc = _project.loadClass(name); declareClasses(bc); bc.addDefaultConstructor().makePublic(); int objectCount = declareFields(types, bc); addFactoryMethod(bc); addFieldCount(bc, types, objectCount); addSetMethods(bc, types, objectCount); addGetMethods(bc, types); addInitialize(bc, objectCount); decorate(obj, bc, types); return createFactory(bc); } /** * Return a class name to use for the given user key. By default, * returns the stringified key prefixed by PREFIX. */ protected String getClassName(Object obj) { return PREFIX + obj.toString(); } /** * Return the default field ACCESS constant for generated fields from * {@link Constants}. */ protected int getFieldAccess() { return Constants.ACCESS_PRIVATE; } /** * Return the name for the generated field at the given index. Returns * "field" + i by default. */ protected String getFieldName(int index) { return "field" + index; } /** * Return the policy constant for how to create type methods. */ protected int getCreateFieldMethods(int type) { return POLICY_EXCEPTION; } /** * Decorate the generated class. */ protected void decorate(Object obj, BCClass cls, int[] types) { } /** * Create a stub factory instance for the given class. */ protected DynamicStorage createFactory(BCClass bc) { try { Class cls = Class.forName(bc.getName(), false, _loader); Constructor cons = cls.getConstructor((Class[]) null); DynamicStorage data = (DynamicStorage) cons.newInstance ((Object[]) null); _project.clear(); // remove old refs return data; } catch (Throwable t) { throw new InternalException("cons-access", t).setFatal(true); } } /** * Add interface or superclass declarations to the generated class. */ protected void declareClasses(BCClass bc) { bc.declareInterface(DynamicStorage.class); } /** * Implement the newInstance method. */ private void addFactoryMethod(BCClass bc) { BCMethod method = bc.declareMethod("newInstance", DynamicStorage.class, null); Code code = method.getCode(true); code.anew().setType(bc); code.dup(); code.invokespecial().setMethod(bc.getName(), "", "void", null); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Implement getFieldCount/getObjectCount. */ private void addFieldCount(BCClass bc, int[] types, int objectCount) { BCMethod method = bc.declareMethod("getFieldCount", int.class, null); Code code = method.getCode(true); code.constant().setValue(types.length); code.ireturn(); code.calculateMaxLocals(); code.calculateMaxStack(); method = bc.declareMethod("getObjectCount", int.class, null); code = method.getCode(true); code.constant().setValue(objectCount); code.ireturn(); code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Implement initialize. */ private void addInitialize(BCClass bc, int objectCount) { BCMethod meth = bc.declareMethod("initialize", void.class, null); Code code = meth.getCode(true); JumpInstruction ifins = null; if (objectCount > 0) { // if (objects == null) // objects = new Object[objectCount]; code.aload().setThis(); code.getfield().setField("objects", Object[].class); ifins = code.ifnonnull(); code.aload().setThis(); code.constant().setValue(objectCount); code.anewarray().setType(Object.class); code.putfield().setField("objects", Object[].class); } Instruction ins = code.vreturn(); if (ifins != null) ifins.setTarget(ins); code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Declare the primitive fields and the object field. */ private int declareFields(int[] types, BCClass bc) { bc.declareField("objects", Object[].class).makePrivate(); int objectCount = 0; Class type; for (int i = 0; i < types.length; i++) { type = forType(types[i]); if (type == Object.class) objectCount++; else { BCField field = bc.declareField(getFieldName(i), type); field.setAccessFlags(getFieldAccess()); } } return objectCount; } /** * Add all the typed set by index method. */ private void addSetMethods(BCClass bc, int[] types, int totalObjects) { for (int i = 0; i < TYPES.length; i++) addSetMethod(TYPES[i], bc, types, totalObjects); } /** * Add the typed set by index method. */ private void addSetMethod(int typeCode, BCClass bc, int[] types, int totalObjects) { int handle = getCreateFieldMethods(typeCode); if (handle == POLICY_EMPTY) return; Class type = forType(typeCode); // public void set (int field, val) String name = Object.class.equals(type) ? "Object" : StringUtils.capitalize(type.getName()); name = "set" + name; BCMethod method = bc.declareMethod(name, void.class, new Class[]{ int.class, type }); method.makePublic(); Code code = method.getCode(true); // switch (field) code.aload().setParam(0); TableSwitchInstruction tabins = code.tableswitch(); tabins.setLow(0); tabins.setHigh(types.length - 1); Instruction defaultIns; if (handle == POLICY_SILENT) defaultIns = code.vreturn(); else defaultIns = throwException (code, IllegalArgumentException.class); tabins.setDefaultTarget(defaultIns); int objectCount = 0; for (int i = 0; i < types.length; i++) { // default: throw new IllegalArgumentException if (!isCompatible(types[i], typeCode)) { tabins.addTarget(tabins.getDefaultTarget()); continue; } tabins.addTarget(code.aload().setThis()); if (typeCode >= JavaTypes.OBJECT) { // if (objects == null) // objects = new Object[totalObjects]; code.aload().setThis(); code.getfield().setField("objects", Object[].class); JumpInstruction ifins = code.ifnonnull(); code.aload().setThis(); code.constant().setValue(totalObjects); code.anewarray().setType(Object.class); code.putfield().setField("objects", Object[].class); // objects[objectCount] = val; ifins.setTarget(code.aload().setThis()); code.getfield().setField("objects", Object[].class); code.constant().setValue(objectCount); code.aload().setParam(1); code.aastore(); objectCount++; } else { // case i: fieldi = val; LoadInstruction load = code.xload(); load.setType(type); load.setParam(1); code.putfield().setField("field" + i, type); } // return code.vreturn(); } code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Add all typed get by index method for the given fields. */ private void addGetMethods(BCClass bc, int[] types) { for (int i = 0; i < TYPES.length; i++) addGetMethod(TYPES[i], bc, types); } /** * Add typed get by index method. */ private void addGetMethod(int typeCode, BCClass bc, int[] types) { int handle = getCreateFieldMethods(typeCode); if (handle == POLICY_EMPTY) return; Class type = forType(typeCode); // public getField (int field) String name = Object.class.equals(type) ? "Object" : StringUtils.capitalize(type.getName()); name = "get" + name; BCMethod method = bc.declareMethod(name, type, new Class[]{ int.class }); method.makePublic(); Code code = method.getCode(true); // switch (field) code.aload().setParam(0); TableSwitchInstruction tabins = code.tableswitch(); tabins.setLow(0); tabins.setHigh(types.length - 1); Instruction defaultIns = null; if (typeCode == JavaTypes.OBJECT && handle == POLICY_SILENT) { defaultIns = code.constant().setNull(); code.areturn(); } else defaultIns = throwException (code, IllegalArgumentException.class); tabins.setDefaultTarget(defaultIns); int objectCount = 0; for (int i = 0; i < types.length; i++) { // default: throw new IllegalArgumentException if (!isCompatible(types[i], typeCode)) { tabins.addTarget(tabins.getDefaultTarget()); continue; } tabins.addTarget(code.aload().setThis()); if (typeCode >= JavaTypes.OBJECT) { // if (objects == null) // return null; // return objects[objectCount]; code.aload().setThis(); code.getfield().setField("objects", Object[].class); JumpInstruction ifins = code.ifnonnull(); code.constant().setNull(); code.areturn(); ifins.setTarget(code.aload().setThis()); code.getfield().setField("objects", Object[].class); code.constant().setValue(objectCount); code.aaload(); code.areturn(); objectCount++; } else { // case i: return fieldi; code.getfield().setField("field" + i, type); code.xreturn().setType(type); } } code.calculateMaxLocals(); code.calculateMaxStack(); } ///////////// // Utilities ///////////// /** * Clear code associated with the given method signature, and return * the empty code. Will return null if the method should be empty. */ protected Code replaceMethod(BCClass bc, String name, Class retType, Class[] args, boolean remove) { bc.removeDeclaredMethod(name, args); BCMethod meth = bc.declareMethod(name, retType, args); Code code = meth.getCode(true); if (!remove) return code; code.xreturn().setType(retType); code.calculateMaxStack(); code.calculateMaxLocals(); return null; } /** * Add a bean field of the given name and type. */ protected BCField addBeanField(BCClass bc, String name, Class type) { if (name == null) throw new IllegalArgumentException("name == null"); // private BCField field = bc.declareField(name, type); field.setAccessFlags(getFieldAccess()); name = StringUtils.capitalize(name); // getter String prefix = (type == boolean.class) ? "is" : "get"; BCMethod method = bc.declareMethod(prefix + name, type, null); method.makePublic(); Code code = method.getCode(true); code.aload().setThis(); code.getfield().setField(field); code.xreturn().setType(type); code.calculateMaxStack(); code.calculateMaxLocals(); // setter method = bc.declareMethod("set" + name, void.class, new Class[]{ type }); method.makePublic(); code = method.getCode(true); code.aload().setThis(); code.xload().setParam(0).setType(type); code.putfield().setField(field); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); return field; } /** * Return true if the given field type and storage type are compatible. */ protected boolean isCompatible(int fieldType, int storageType) { if (storageType == JavaTypes.OBJECT) return fieldType >= JavaTypes.OBJECT; return fieldType == storageType; } /** * Throw an exception of the given type. */ protected Instruction throwException(Code code, Class type) { Instruction ins = code.anew().setType(type); code.dup(); code.invokespecial().setMethod(type, "", void.class, null); code.athrow(); return ins; } /** * Return the proper type for the given {@link JavaTypes} constant. */ protected Class forType(int type) { switch (type) { case JavaTypes.BOOLEAN: return boolean.class; case JavaTypes.BYTE: return byte.class; case JavaTypes.CHAR: return char.class; case JavaTypes.INT: return int.class; case JavaTypes.SHORT: return short.class; case JavaTypes.LONG: return long.class; case JavaTypes.FLOAT: return float.class; case JavaTypes.DOUBLE: return double.class; } return Object.class; } /** * get the wrapper for the given {@link JavaTypes} constant. */ protected Class getWrapper(int type) { return getWrapper(forType(type)); } /** * Get the wrapper for the given type. */ protected Class getWrapper(Class c) { for (int i = 0; i < WRAPPERS.length; i++) { if (WRAPPERS[i][0].equals (c)) return WRAPPERS[i][1]; } return c; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/RedefinitionHelper.java0000644000000000000000000001776012133327272030050 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.lang.reflect.Method; import java.lang.reflect.Field; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StateManagerImpl; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.ImplHelper; /** * Helper methods for managed types that use method redefinition for field * tracking. * * @since 1.0.0 */ public class RedefinitionHelper { /** * Call {@link StateManagerImpl#dirtyCheck} if the argument is a * {@link StateManagerImpl}. */ public static void dirtyCheck(StateManager sm) { if (sm instanceof StateManagerImpl) ((StateManagerImpl) sm).dirtyCheck(); } /** * Notify the state manager for o (if any) that a field * is about to be accessed. */ public static void accessingField(Object o, int absoluteIndex) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.accessingField(absoluteIndex); } /** * Setting state callback. */ public static void settingField(Object o, int idx, boolean cur, boolean next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingBooleanField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, char cur, char next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingCharField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, byte cur, byte next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingByteField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, short cur, short next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingShortField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, int cur, int next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingIntField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, long cur, long next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingLongField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, float cur, float next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingFloatField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, double cur, double next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingDoubleField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, String cur, String next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingStringField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Setting state callback. */ public static void settingField(Object o, int idx, Object cur, Object next) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(o, null); if (pc == null) return; StateManager sm = pc.pcGetStateManager(); if (sm != null) sm.settingObjectField(pc, idx, cur, next, OpenJPAStateManager.SET_USER); } /** * Create a container instance that will delegate back to the state * manager to emulate lazy loading. This is used by PC subclasses for * unenhanced types that could not be redefined, and thus do not have * field-interception capabilities. Do this for all collection and * map field types, even if they are in the dfg, in case the fetch * groups are reset at runtime. * * @since 1.1.0 */ public static void assignLazyLoadProxies(StateManagerImpl sm) { FieldMetaData[] fmds = sm.getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) { switch (fmds[i].getTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.MAP: PersistenceCapable pc = sm.getPersistenceCapable(); Field field = (Field) fmds[i].getBackingMember(); Reflection.set(pc, field, newLazyLoadingProxy(fmds[i].getDeclaredType(), i, sm)); break; } } } private static Object newLazyLoadingProxy(Class type, final int idx, final StateManagerImpl sm) { InvocationHandler handler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // this will replace the field in the instance, so the dynamic // proxy should only be called the first time a // lazy-load-proxied field is used in normal usage. Object delegate = sm.fetch(idx); return method.invoke(delegate, args); } }; return Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, handler); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ApplicationIdTool.java0000644000000000000000000016033512133327272027644 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.lang.reflect.Modifier; import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.meta.ClassArgParser; import org.apache.openjpa.lib.util.CodeFormat; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.JavaVersions; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.DelegatingMetaDataFactory; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.MetaDataFactory; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.UserException; import serp.bytecode.BCClass; import serp.bytecode.BCClassLoader; import serp.bytecode.Project; import serp.util.Strings; /** * Generates a class appropriate for use as an application identity class. * * @author Patrick Linskey * @author Abe White */ public class ApplicationIdTool { public static final String TOKEN_DEFAULT = "::"; private static final String TOKENIZER_CUSTOM = "Tokenizer"; private static final String TOKENIZER_STD = "StringTokenizer"; private static final Localizer _loc = Localizer.forPackage (ApplicationIdTool.class); private final Log _log; private final Class _type; private final ClassMetaData _meta; private boolean _abstract = false; private FieldMetaData[] _fields = null; private boolean _ignore = true; private File _dir = null; private Writer _writer = null; private String _code = null; private String _token = TOKEN_DEFAULT; private CodeFormat _format = null; /** * Constructs a new ApplicationIdTool capable of generating an * object id class for type. */ public ApplicationIdTool(OpenJPAConfiguration conf, Class type) { _log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE); _type = type; MetaDataRepository repos = conf.newMetaDataRepositoryInstance(); repos.setValidate(repos.VALIDATE_NONE); repos.setSourceMode(repos.MODE_MAPPING, false); loadObjectIds(repos, true); _meta = repos.getMetaData(type, null, false); if (_meta != null) { _abstract = Modifier.isAbstract(_meta.getDescribedType(). getModifiers()); _fields = getDeclaredPrimaryKeyFields(_meta); } } /** * Constructs a new tool instance capable of generating an * object id class for meta. */ public ApplicationIdTool(OpenJPAConfiguration conf, Class type, ClassMetaData meta) { _log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE); _type = type; _meta = meta; if (_meta != null) { _abstract = Modifier.isAbstract(_meta.getDescribedType(). getModifiers()); _fields = getDeclaredPrimaryKeyFields(_meta); } } /** * Return metadata for primary key fields declared in the given class. */ private static FieldMetaData[] getDeclaredPrimaryKeyFields (ClassMetaData meta) { if (meta.getPCSuperclass() == null) return meta.getPrimaryKeyFields(); // remove the primary key fields that are not declared // in the current class FieldMetaData[] fields = meta.getPrimaryKeyFields(); List decs = new ArrayList(fields.length); for (int i = 0; i < fields.length; i++) if (fields[i].getDeclaringType() == meta.getDescribedType()) decs.add(fields[i]); return (FieldMetaData[]) decs.toArray(new FieldMetaData[decs.size()]); } /** * Return false if this tool is configured to throw an exception on * an attempt to generate an id class for a type that does not use * application identity. */ public boolean getIgnoreErrors() { return _ignore; } /** * Set to false if this tool should throw an exception on * an attempt to generate an id class for a type that does not use * application identity. */ public void setIgnoreErrors(boolean ignore) { _ignore = ignore; } /** * The code formatter for the generated Java code. */ public CodeFormat getCodeFormat() { return _format; } /** * Set the code formatter for the generated Java code. */ public void setCodeFormat(CodeFormat format) { _format = format; } /** * The directory to write source to. Defaults to the directory * of the Java file for the set type. If the given directory does not * match the package of the object id, the package structure will be * created below the directory. */ public File getDirectory() { return _dir; } /** * The directory to write source to. Defaults to the directory * of the Java file for the set type. If the given directory does not * match the package of the object id, the package structure will be * created below the directory. */ public void setDirectory(File dir) { _dir = dir; } /** * The token to use to separate stringified primary key field values. */ public String getToken() { return _token; } /** * The token to use to separate stringified primary key field values. */ public void setToken(String token) { _token = token; } /** * The writer to write source to, or null to write to default file. */ public Writer getWriter() { return _writer; } /** * The writer to write source to, or null to write to default file. */ public void setWriter(Writer writer) { _writer = writer; } /** * Return the type we are generating an application id for. */ public Class getType() { return _type; } /** * Return metadata for the type we are generating an application id for. */ public ClassMetaData getMetaData() { return _meta; } /** * Return the code generated for the application id, or null * if invalid class or the {@link #run} method has not been called. */ public String getCode() { return _code; } /** * Returns true if the application identity class should be an inner class. */ public boolean isInnerClass() { Class oidClass = _meta.getObjectIdType(); return oidClass.getName().indexOf('$') != -1; } /** * Returns the short class name for the object id class. */ private String getClassName() { if (_meta.isOpenJPAIdentity()) return null; // convert from SomeClass$ID to ID String className = Strings.getClassName(_meta.getObjectIdType()); if (isInnerClass()) className = className.substring(className.lastIndexOf('$') + 1); return className; } /** * Generates the sourcecode for the application id class; returns * false if the class is invalid. */ public boolean run() { if (_log.isInfoEnabled()) _log.info(_loc.get("appid-start", _type)); // ensure that this type is a candidate for application identity if (_meta == null || _meta.getIdentityType() != ClassMetaData.ID_APPLICATION || _meta.isOpenJPAIdentity()) { if (!_ignore) throw new UserException(_loc.get("appid-invalid", _type)); // else just warn if (_log.isWarnEnabled()) _log.warn(_loc.get("appid-warn", _type)); return false; } Class oidClass = _meta.getObjectIdType(); Class superOidClass = null; // allow diff oid class in subclass (horizontal) if (_meta.getPCSuperclass() != null) { superOidClass = _meta.getPCSuperclassMetaData().getObjectIdType(); if (oidClass == null || oidClass.equals(superOidClass)) { // just warn if (_log.isWarnEnabled()) _log.warn(_loc.get("appid-warn", _type)); return false; } } // ensure that an id class is declared if (oidClass == null) throw new UserException(_loc.get("no-id-class", _type)). setFatal(true); // ensure there is at least one pk field if we are // non-absract, and see if we have any byte[] boolean bytes = false; for (int i = 0; !bytes && i < _fields.length; i++) bytes = _fields[i].getDeclaredType() == byte[].class; // collect info on id type String className = getClassName(); String packageName = Strings.getPackageName(oidClass); String packageDec = ""; if (packageName.length() > 0) packageDec = "package " + packageName + ";"; String imports = getImports(); String fieldDecs = getFieldDeclarations(); String constructor = getConstructor(superOidClass != null); String properties = getProperties(); String fromStringCode = getFromStringCode(superOidClass != null); String toStringCode = getToStringCode(superOidClass != null); String equalsCode = getEqualsCode(superOidClass != null); String hashCodeCode = getHashCodeCode(superOidClass != null); // build the java code CodeFormat code = newCodeFormat(); if (!isInnerClass() && packageDec.length() > 0) code.append(packageDec).afterSection(); if (!isInnerClass() && imports.length() > 0) code.append(imports).afterSection(); code.append("/**").endl(). append(" * "). append(_loc.get("appid-comment-for", _type.getName())). endl(). append(" *").endl(). append(" * ").append(_loc.get("appid-comment-gen")).endl(). append(" * ").append(getClass().getName()).endl(). append(" */").endl(); code.append("public "); if (isInnerClass()) code.append("static "); code.append("class ").append(className); if (code.getBraceOnSameLine()) code.append(" "); else code.endl().tab(); if (superOidClass != null) { code.append("extends " + Strings.getClassName(superOidClass)); if (code.getBraceOnSameLine()) code.append(" "); else code.endl().tab(); } code.append("implements Serializable").openBrace(1).endl(); // if we use a byte array we need a static array for encoding to string if (bytes) { code.tab().append("private static final char[] HEX = "). append("new char[] {").endl(); code.tab(2).append("'0', '1', '2', '3', '4', '5', '6', '7',"). endl(); code.tab(2).append("'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'"). endl(); code.tab().append("};").endl(2); } // static block to register class code.tab().append("static").openBrace(2).endl(); code.tab(2).append("// register persistent class in JVM").endl(); code.tab(2).append("try { Class.forName").openParen(true). append("\"").append(_type.getName()).append("\""). closeParen().append(";").append(" }").endl(); code.tab(2).append("catch").openParen(true). append("Exception e").closeParen().append(" {}").endl(); code.closeBrace(2); // field declarations if (fieldDecs.length() > 0) code.endl(2).append(fieldDecs); // default constructor code.afterSection().tab().append("public ").append(className). parens().openBrace(2).endl(); code.closeBrace(2); // string constructor code.afterSection().append(constructor); // properties if (properties.length() > 0) code.afterSection().append(properties); // toString, equals, hashCode methods if (toStringCode.length() > 0) code.afterSection().append(toStringCode); if (hashCodeCode.length() > 0) code.afterSection().append(hashCodeCode); if (equalsCode.length() > 0) code.afterSection().append(equalsCode); if (fromStringCode.length() > 0) code.afterSection().append(fromStringCode); // if we have any byte array fields, we have to add the extra // methods for handling byte arrays if (bytes) { code.afterSection().append(getToBytesByteArrayCode()); code.afterSection().append(getToStringByteArrayCode()); code.afterSection().append(getEqualsByteArrayCode()); code.afterSection().append(getHashCodeByteArrayCode()); } // base classes might need to define a custom tokenizer if (superOidClass == null && getTokenizer(false) == TOKENIZER_CUSTOM) code.afterSection().append(getCustomTokenizerClass()); code.endl(); code.closeBrace(1); _code = code.toString(); // if this is an inner class, then indent the entire // code unit one tab level if (isInnerClass()) { // indent the entire code block one level to make it // a propertly indented innder class _code = code.getTab() + Strings.replace(_code, J2DoPrivHelper.getLineSeparator(), J2DoPrivHelper.getLineSeparator() + code.getTab()); } return true; } /** * Writes the generated code to the proper file. */ public void record() throws IOException { if (_code == null) return; Writer writer = _writer; if (writer == null) { File file = getFile(); Files.backup(file, false); writer = new FileWriter(file); } PrintWriter printer = new PrintWriter(writer); printer.print(_code); printer.flush(); if (_writer == null) writer.close(); } /** * Return the necessary imports for the class. */ private String getImports() { Set pkgs = getImportPackages(); CodeFormat imports = newCodeFormat(); String base = Strings.getPackageName(_meta.getObjectIdType()); String pkg; for (Iterator itr = pkgs.iterator(); itr.hasNext();) { pkg = (String) itr.next(); if (pkg.length() > 0 && !"java.lang".equals(pkg) && !base.equals(pkg)) { if (imports.length() > 0) imports.endl(); imports.append("import ").append(pkg).append(".*;"); } } return imports.toString(); } /** * Returns the collection of packages that need to be imported. */ public Set getImportPackages() { Set pkgs = new TreeSet(); pkgs.add(Strings.getPackageName(_type)); Class superOidClass = null; if (_meta != null && _meta.getPCSuperclassMetaData() != null) superOidClass = _meta.getPCSuperclassMetaData().getObjectIdType(); if (superOidClass != null) pkgs.add(Strings.getPackageName(superOidClass)); pkgs.add("java.io"); pkgs.add("java.util"); Class type; for (int i = 0; i < _fields.length; i++) { type = _fields[i].getObjectIdFieldType(); if (type != byte[].class && type != char[].class && !type.getName().startsWith("java.sql.")) { pkgs.add(Strings.getPackageName(type)); } } return pkgs; } /** * Return the code to declare all primary key fields. */ private String getFieldDeclarations() { CodeFormat code = newCodeFormat(); for (int i = 0; i < _fields.length; i++) { if (i > 0) code.endl(); code.tab().append("public ").append(getTypeName(_fields[i])). append(" ").append(_fields[i].getName()).append(";"); } return code.toString(); } /** * Return the type name to declare the given field as. */ private String getTypeName(FieldMetaData fmd) { Class type = fmd.getObjectIdFieldType(); if (type == byte[].class) return "byte[]"; if (type == char[].class) return "char[]"; if (type.getName().startsWith("java.sql.")) return type.getName(); return Strings.getClassName(type); } /** * Return the getters and setters for all primary key fields. */ private String getProperties() { if (AccessCode.isExplicit(_meta.getAccessType()) && AccessCode.isField(_meta.getAccessType())) return ""; CodeFormat code = newCodeFormat(); String propName; String typeName; for (int i = 0; i < _fields.length; i++) { if (i > 0) code.afterSection(); typeName = getTypeName(_fields[i]); propName = StringUtils.capitalize(_fields[i].getName()); code.tab().append("public ").append(typeName).append(" "); if (_fields[i].getDeclaredTypeCode() == JavaTypes.BOOLEAN || _fields[i].getDeclaredTypeCode() == JavaTypes.BOOLEAN_OBJ) code.append("is"); else code.append("get"); code.append(propName).parens().openBrace(2).endl(); code.tab(2).append("return ").append(_fields[i].getName()). append(";").endl(); code.closeBrace(2); code.afterSection(); code.tab().append("public void set").append(propName); code.openParen(true).append(typeName).append(" "). append(_fields[i].getName()).closeParen(); code.openBrace(2).endl(); code.tab(2).append("this.").append(_fields[i].getName()). append(" = ").append(_fields[i].getName()).append(";"). endl(); code.closeBrace(2); } return code.toString(); } /** * Return the string constructor code. */ private String getConstructor(boolean hasSuperclass) { CodeFormat code = newCodeFormat(); code.tab().append("public "); code.append(getClassName()); code.openParen(true).append("String str").closeParen(); code.openBrace(2).endl(); if (_fields.length != 0 || (hasSuperclass && _meta.getPrimaryKeyFields().length > 0)) { code.tab(2).append("fromString").openParen(true). append("str").closeParen().append(";").endl(); } code.closeBrace(2); return code.toString(); } /** * Create the fromString method that parses the result of our toString * method. If we have superclasses with id fields, this will call * super.fromString() so that the parent class can parse its own fields. */ private String getFromStringCode(boolean hasSuperclass) { // if we are below a concrete class then we cannot declare any // more primary key fields; thus, just use the parent invocation if (hasConcreteSuperclass()) return ""; if (_fields.length == 0) return ""; hasSuperclass = hasSuperclass && getDeclaredPrimaryKeyFields (_meta.getPCSuperclassMetaData()).length > 0; String toke = getTokenizer(hasSuperclass); CodeFormat code = newCodeFormat(); if (_abstract || hasSuperclass) code.tab().append("protected ").append(toke). append(" fromString"); else code.tab().append("private void fromString"); code.openParen(true).append("String str").closeParen(); code.openBrace(2).endl(); // if we have any Object-type fields, die immediately for (int i = 0; i < _fields.length; i++) { if (_fields[i].getObjectIdFieldType() != Object.class) continue; code.tab(2).append("throw new UnsupportedOperationException"). parens().append(";").endl(); code.closeBrace(2); return code.toString(); } if (toke != null) { code.tab(2).append(toke).append(" toke = "); if (hasSuperclass) { // call super.fromString(str) to get the tokenizer that was // used to parse the superclass code.append("super.fromString").openParen(true). append("str").closeParen(); } else { // otherwise construct a new tokenizer with the string code.append("new ").append(toke).openParen(true). append("str"); if (toke == TOKENIZER_STD) code.append(", \"").append(_token).append("\""); code.closeParen(); } code.append(";").endl(); } for (int i = 0; i < _fields.length; i++) { if (toke != null) { code.tab(2).append("str = toke.nextToken").parens(). append(";").endl(); } code.tab(2).append(getConversionCode(_fields[i], "str")).endl(); } if (_abstract || hasSuperclass) code.tab(2).append("return toke;").endl(); code.closeBrace(2); return code.toString(); } /** * Returns the type of tokenizer to use, or null if none. */ private String getTokenizer(boolean hasSuperclass) { if (!_abstract && !hasSuperclass && _fields.length == 1) return null; if (_token.length() == 1) return TOKENIZER_STD; return TOKENIZER_CUSTOM; } /** * Get parsing code for the given field. */ private String getConversionCode(FieldMetaData field, String var) { CodeFormat parse = newCodeFormat(); if (field.getName().equals(var)) parse.append("this."); parse.append(field.getName()).append(" = "); Class type = field.getObjectIdFieldType(); if (type == Date.class) { parse.append("new Date").openParen(true). append("Long.parseLong").openParen(true). append(var).closeParen().closeParen(); } else if (type == java.sql.Date.class || type == java.sql.Timestamp.class || type == java.sql.Time.class) { parse.append(type.getName()).append(".valueOf").openParen(true). append(var).closeParen(); } else if (type == String.class) parse.append(var); else if (type == Character.class) { parse.append("new Character").openParen(true).append(var). append(".charAt").openParen(true).append(0). closeParen().closeParen(); } else if (type == byte[].class) parse.append("toBytes").openParen(true).append(var).closeParen(); else if (type == char[].class) parse.append(var).append(".toCharArray").parens(); else if (!type.isPrimitive()) { parse.append("new ").append(Strings.getClassName(type)). openParen(true).append(var).closeParen(); } else // primitive { switch (type.getName().charAt(0)) { case 'b': if (type == boolean.class) parse.append("\"true\".equals").openParen(true). append(var).closeParen(); else parse.append("Byte.parseByte").openParen(true). append(var).closeParen(); break; case 'c': parse.append(var).append(".charAt").openParen(true). append(0).closeParen(); break; case 'd': parse.append("Double.parseDouble").openParen(true). append(var).closeParen(); break; case 'f': parse.append("Float.parseFloat").openParen(true). append(var).closeParen(); break; case 'i': parse.append("Integer.parseInt").openParen(true). append(var).closeParen(); break; case 'l': parse.append("Long.parseLong").openParen(true). append(var).closeParen(); break; case 's': parse.append("Short.parseShort").openParen(true). append(var).closeParen(); break; } } if (!type.isPrimitive() && type != byte[].class) { CodeFormat isNull = newCodeFormat(); isNull.append("if").openParen(true).append("\"null\".equals"). openParen(true).append(var).closeParen().closeParen(). endl().tab(3); if (field.getName().equals(var)) isNull.append("this."); isNull.append(field.getName()).append(" = null;").endl(); isNull.tab(2).append("else").endl(); isNull.tab(3).append(parse); parse = isNull; } return parse.append(";").toString(); } /** * Return an equality method that compares all pk variables. * Must deal correctly with both primitives and objects. */ private String getEqualsCode(boolean hasSuperclass) { // if we are below a concrete class then we cannot declare any // more primary key fields; thus, just use the parent invocation if (hasConcreteSuperclass() || (hasSuperclass && _fields.length == 0)) return ""; CodeFormat code = newCodeFormat(); code.tab().append("public boolean equals").openParen(true). append("Object obj").closeParen().openBrace(2).endl(); code.tab(2).append("if").openParen(true). append("this == obj").closeParen().endl(); code.tab(3).append("return true;").endl(); // call super.equals() if we have a superclass String className = getClassName(); if (hasSuperclass) { code.tab(2).append("if").openParen(true). append("!super.equals").openParen(true). append("obj").closeParen().closeParen().endl(); code.tab(3).append("return false;").endl(); } else { code.tab(2).append("if").openParen(true). append("obj == null || obj.getClass").parens(). append(" != ").append("getClass").parens(). closeParen().endl(); code.tab(3).append("return false;").endl(); } String name; Class type; for (int i = 0; i < _fields.length; i++) { if (i == 0) { code.endl().tab(2).append(className).append(" other = "). openParen(false).append(className).closeParen(). append(" obj;").endl(); } // if this is not the first field, add an && if (i == 0) code.tab(2).append("return "); else code.endl().tab(3).append("&& "); name = _fields[i].getName(); type = _fields[i].getObjectIdFieldType(); if (type.isPrimitive()) { code.openParen(false).append(name).append(" == "). append("other.").append(name).closeParen(); } else if (type == byte[].class) { code.openParen(false).append("equals").openParen(true). append(name).append(", ").append("other."). append(name).closeParen().closeParen(); } else if (type == char[].class) { // ((name == null && other.name == null) // || (name != null && String.valueOf (name). // equals (String.valueOf (other.name)))) code.append("(").openParen(false).append(name). append(" == null && other.").append(name). append(" == null").closeParen().endl(); code.tab(3).append("|| "); code.openParen(false).append(name).append(" != null "). append("&& String.valueOf").openParen(true).append(name). closeParen().append(".").endl(); code.tab(3).append("equals").openParen(true). append("String.valueOf").openParen(true). append("other.").append(name).closeParen().closeParen(). closeParen().append(")"); } else { // ((name == null && other.name == null) // || (name != null && name.equals (other.name))) code.append("(").openParen(false).append(name). append(" == null && other.").append(name). append(" == null").closeParen().endl(); code.tab(3).append("|| "); code.openParen(false).append(name).append(" != null "). append("&& ").append(name).append(".equals"). openParen(true).append("other.").append(name). closeParen().closeParen().append(")"); } } // no _fields: just return true after checking instanceof if (_fields.length == 0) code.tab(2).append("return true;").endl(); else code.append(";").endl(); code.closeBrace(2); return code.toString(); } /** * Return a hashCode method that takes into account all * primary key values. Must deal correctly with both primitives and objects. */ private String getHashCodeCode(boolean hasSuperclass) { // if we are below a concrete class then we cannot declare any // more primary key fields; thus, just use the parent invocation if (hasConcreteSuperclass() || (hasSuperclass && _fields.length == 0)) return ""; CodeFormat code = newCodeFormat(); code.tab().append("public int hashCode").parens(). openBrace(2).endl(); if (_fields.length == 0) code.tab(2).append("return 17;").endl(); else if (_fields.length == 1 && !hasSuperclass) { code.tab(2).append("return "); appendHashCodeCode(_fields[0], code); code.append(";").endl(); } else { code.tab(2).append("int rs = "); if (hasSuperclass) { // call super.hashCode() if we have a superclass code.append("super.hashCode").openParen(true). closeParen().append(";"); } else code.append("17;"); code.endl(); for (int i = 0; i < _fields.length; i++) { code.tab(2).append("rs = rs * 37 + "); appendHashCodeCode(_fields[i], code); code.append(";").endl(); } code.tab(2).append("return rs;").endl(); } code.closeBrace(2); return code.toString(); } /** * Return true if this class has a concrete superclass. */ private boolean hasConcreteSuperclass() { for (ClassMetaData sup = _meta.getPCSuperclassMetaData(); sup != null; sup = sup.getPCSuperclassMetaData()) { if (!Modifier.isAbstract(sup.getDescribedType().getModifiers())) return true; } return false; } /** * Append code calculating the hashcode for the given field. */ private void appendHashCodeCode(FieldMetaData field, CodeFormat code) { String name = field.getName(); if ("rs".equals(name)) name = "this." + name; Class type = field.getObjectIdFieldType(); if (type.isPrimitive()) { if (type == boolean.class) { // ((name) ? 1 : 0) code.append("(").openParen(false).append(name).closeParen(). append(" ? 1 : 0").append(")"); } else if (type == long.class) { // (int) (name ^ (name >>> 32)) code.openParen(false).append("int").closeParen(). append(" ").openParen(false).append(name). append(" ^ ").openParen(false).append(name). append(" >>> 32").closeParen().closeParen(); } else if (type == double.class) { // (int) (Double.doubleToLongBits (name) // ^ (Double.doubleToLongBits (name) >>> 32)) code.openParen(false).append("int").closeParen(). append(" ").openParen(false). append("Double.doubleToLongBits").openParen(true). append(name).closeParen().endl(); code.tab(3).append("^ ").openParen(false). append("Double.doubleToLongBits").openParen(true). append(name).closeParen().append(" >>> 32"). closeParen().closeParen(); } else if (type == float.class) { // Float.floatToIntBits (name) code.append("Float.floatToIntBits").openParen(true). append(name).closeParen(); } else if (type == int.class) code.append(name); else { // (int) name code.openParen(false).append("int").closeParen(). append(" ").append(name); } } else if (type == byte[].class) { // hashCode (name); code.append("hashCode").openParen(true).append(name). closeParen(); } else if (type == char[].class) { // ((name == null) ? 0 : String.valueOf (name).hashCode ()) code.append("(").openParen(false).append(name). append(" == null").closeParen().append(" ? 0 : "). append("String.valueOf").openParen(true).append(name). closeParen().append(".hashCode").parens().append(")"); } else { // ((name == null) ? 0 : name.hashCode ()) code.append("(").openParen(false).append(name). append(" == null").closeParen().append(" ? 0 : "). append(name).append(".hashCode").parens().append(")"); } } /** * Return a method to create a string containing the primary key * values that define the application id object. */ private String getToStringCode(boolean hasSuperclass) { // if we are below a concrete class then we cannot declare any // more primary key fields; thus, just use the parent invocation if (hasConcreteSuperclass() || (hasSuperclass && _fields.length == 0)) return ""; CodeFormat code = newCodeFormat(); code.tab().append("public String toString").parens(). openBrace(2).endl(); String name; Class type; String appendDelimiter = "+ \"" + _token + "\" + "; for (int i = 0; i < _fields.length; i++) { // if this is not the first field, add a + if (i == 0) { code.tab(2).append("return "); // add in the super.toString() if we have a parent if (hasSuperclass && getDeclaredPrimaryKeyFields (_meta.getPCSuperclassMetaData()).length > 0) { code.append("super.toString").parens(); code.endl().tab(3).append(appendDelimiter); } } else code.endl().tab(3).append(appendDelimiter); name = _fields[i].getName(); type = _fields[i].getObjectIdFieldType(); if (type == String.class) code.append(name); else if (type == byte[].class) code.append("toString").openParen(true). append(name).closeParen(); else if (type == char[].class) code.openParen(true).openParen(true).append(name). append(" == null").closeParen().append(" ? \"null\""). append(": String.valueOf").openParen(true). append(name).closeParen().closeParen(); else if (type == Date.class) code.openParen(true).openParen(true).append(name). append(" == null").closeParen().append(" ? \"null\""). endl().tab(4).append(": String.valueOf"). openParen(true).append(name).append(".getTime"). parens().closeParen().closeParen(); else code.append("String.valueOf").openParen(true). append(name).closeParen(); } // no fields; just use "" if (_fields.length == 0) code.tab(2).append("return \"\""); code.append(";").endl(); code.closeBrace(2); return code.toString(); } /** * Code to convert a string to a byte array. * * @see org.apache.openjpa.lib.util.Base16Encoder#decode */ private String getToBytesByteArrayCode() { CodeFormat code = newCodeFormat(); code.tab().append("private static byte[] toBytes").openParen(true). append("String s").closeParen().openBrace(2).endl(); code.tab(2).append("if").openParen(true).append("\"null\".equals"). openParen(true).append("s").closeParen().closeParen().endl(); code.tab(3).append("return null;").endl(2); code.tab(2).append("int len = s.length").parens(). append(";").endl(); code.tab(2).append("byte[] r = new byte[len / 2];").endl(); code.tab(2).append("for").openParen(true). append("int i = 0; i < r.length; i++").closeParen(). openBrace(3).endl(); code.tab(3).append("int digit1 = s.charAt").openParen(true). append("i * 2").closeParen().append(", "). append("digit2 = s.charAt").openParen(true). append("i * 2 + 1").closeParen().append(";").endl(); code.tab(3).append("if").openParen(true). append("digit1 >= '0' && digit1 <= '9'").closeParen().endl(); code.tab(4).append("digit1 -= '0';").endl(); code.tab(3).append("else if").openParen(true). append("digit1 >= 'A' && digit1 <= 'F'").closeParen().endl(); code.tab(4).append("digit1 -= 'A' - 10;").endl(); code.tab(3).append("if").openParen(true). append("digit2 >= '0' && digit2 <= '9'").closeParen().endl(); code.tab(4).append("digit2 -= '0';").endl(); code.tab(3).append("else if").openParen(true). append("digit2 >= 'A' && digit2 <= 'F'").closeParen().endl(); code.tab(4).append("digit2 -= 'A' - 10;").endl(2); code.tab(3).append("r[i] = (byte) ").openParen(false). openParen(false).append("digit1 << 4").closeParen(). append(" + digit2").closeParen().append(";").endl(); code.closeBrace(3).endl(); code.tab(2).append("return r;").endl(); code.closeBrace(2); return code.toString(); } /** * Code to convert a byte array to a string. * * @see org.apache.openjpa.lib.util.Base16Encoder#encode */ private String getToStringByteArrayCode() { CodeFormat code = newCodeFormat(); code.tab().append("private static String toString").openParen(true). append("byte[] b").closeParen().openBrace(2).endl(); code.tab(2).append("if").openParen(true). append("b == null").closeParen().endl(); code.tab(3).append("return \"null\";").endl(2); code.tab(2).append("StringBuilder r = new StringBuilder"). openParen(true).append("b.length * 2").closeParen(). append(";").endl(); code.tab(2).append("for").openParen(true). append("int i = 0; i < b.length; i++").closeParen().endl(); code.tab(3).append("for").openParen(true). append("int j = 1; j >= 0; j--").closeParen().endl(); code.tab(4).append("r.append").openParen(true). append("HEX[").openParen(false).append("b[i] >> "). openParen(false).append("j * 4").closeParen().closeParen(). append(" & 0xF]").closeParen().append(";").endl(); code.tab(2).append("return r.toString").parens(). append(";").endl(); code.closeBrace(2); return code.toString(); } /** * Code to test if two byte arrays are equal. */ private String getEqualsByteArrayCode() { CodeFormat code = newCodeFormat(); code.tab().append("private static boolean equals").openParen(true). append("byte[] b1, byte[] b2").closeParen().openBrace(2).endl(); code.tab(2).append("if").openParen(true). append("b1 == null && b2 == null").closeParen().endl(); code.tab(3).append("return true;").endl(); code.tab(2).append("if").openParen(true). append("b1 == null || b2 == null").closeParen().endl(); code.tab(3).append("return false;").endl(); code.tab(2).append("if").openParen(true). append("b1.length != b2.length").closeParen().endl(); code.tab(3).append("return false;").endl(); code.tab(2).append("for").openParen(true). append("int i = 0; i < b1.length; i++").closeParen().endl(); code.tab(3).append("if").openParen(true). append("b1[i] != b2[i]").closeParen().endl(); code.tab(4).append("return false;").endl(); code.tab(2).append("return true;").endl(); code.closeBrace(2); return code.toString(); } private String getHashCodeByteArrayCode() { CodeFormat code = newCodeFormat(); code.tab().append("private static int hashCode").openParen(true). append("byte[] b").closeParen().openBrace(2).endl(); code.tab(2).append("if").openParen(true).append("b == null"). closeParen().endl(); code.tab(3).append("return 0;").endl(); code.tab(2).append("int sum = 0;").endl(); code.tab(2).append("for").openParen(true). append("int i = 0; i < b.length; i++").closeParen().endl(); code.tab(3).append("sum += b[i];").endl(); code.tab(2).append("return sum;").endl(); code.closeBrace(2); return code.toString(); } /** * Code defining a tokenizer class. */ private String getCustomTokenizerClass() { CodeFormat code = newCodeFormat(); code.tab().append("protected static class "). append(TOKENIZER_CUSTOM).openBrace(2).endl(); code.tab(2).append("private final String str;").endl(); code.tab(2).append("private int last;").afterSection(); code.tab(2).append("public Tokenizer (String str)"). openBrace(3).endl(); code.tab(3).append("this.str = str;").endl(); code.closeBrace(3).afterSection(); code.tab(2).append("public String nextToken ()"). openBrace(3).endl(); code.tab(3).append("int next = str.indexOf").openParen(true). append("\"").append(_token).append("\", last").closeParen(). append(";").endl(); code.tab(3).append("String part;").endl(); code.tab(3).append("if").openParen(true).append("next == -1"). closeParen().openBrace(4).endl(); code.tab(4).append("part = str.substring").openParen(true). append("last").closeParen().append(";").endl(); code.tab(4).append("last = str.length").parens().append(";"). endl().closeBrace(4); if (!code.getBraceOnSameLine()) code.endl().tab(3); else code.append(" "); code.append("else").openBrace(4).endl(); code.tab(4).append("part = str.substring").openParen(true). append("last, next").closeParen().append(";").endl(); code.tab(4).append("last = next + ").append(_token.length()). append(";").endl().closeBrace(4).endl(); code.tab(3).append("return part;").endl(); code.closeBrace(3); code.endl().closeBrace(2); return code.toString(); } /** * Return the file that this tool should output to. */ private File getFile() { if (_meta == null) return null; String packageName = Strings.getPackageName(_meta.getObjectIdType()); String fileName = Strings.getClassName(_meta.getObjectIdType()) + ".java"; // if pc class in same package as oid class, try to find pc .java file File dir = null; if (_dir == null && Strings.getPackageName(_type).equals(packageName)) { dir = Files.getSourceFile(_type); if (dir != null) dir = dir.getParentFile(); } if (dir == null) dir = Files.getPackageFile(_dir, packageName, true); return new File(dir, fileName); } /** * Return a copy of the correct code format. */ private CodeFormat newCodeFormat() { return (_format == null) ? new CodeFormat() : (CodeFormat) _format.clone(); } /** * Usage: java org.apache.openjpa.enhance.ApplicationIdTool [option]* * <class name | .java file | .class file | .jdo file>+ * Where the following options are recognized. *
    *
  • -properties/-p <properties file>: The path to a OpenJPA * properties file containing information as outlined in * {@link Configuration}; optional.
  • *
  • -<property name> <property value>: All bean * properties of the standard OpenJPA {@link OpenJPAConfiguration} can be * set by using their names and supplying a value.
  • *
  • -directory/-d <output directory>: Path to the base * source directory. The package structure will be created beneath * this directory if necessary. If not specified, the tool will try * to locate the .java file in the CLASSPATH and output to the same * directory; failing that, it will use the current directory as * the base directory. *
  • -ignoreErrors/-i <true/t | false/f>: If false, an * exception will be thrown if the tool encounters any class that * does not use application identity or uses the identity class of * its superclass; defaults to true.
  • *
  • -token/-t <token>: The token to use to separate * stingified primary key field values in the stringified oid.
  • *
  • -name/-n <id class name>: The name of the identity * class to generate. If this option is specified, you must only * give a single class argument. If the class metadata names an object * id class, this argument is ignored.
  • *
  • -suffix/-s <id class suffix>: A string to suffix each * persistent class with to create the identity class name. This is * overridden by -name or by any identity class name * specified in metadata.
  • *
  • -codeFormat/-cf.<property name> < property value> * : Arguments like this will be used to configure the bean * properties of the internal {@link CodeFormat}.
  • *
* Each additional argument can be either the full class name of the * type to create an id class for, the path to the .java file for the type, * the path to the .class file for the type, or the path to a .jdo file * listing one or more types. If a .java file already exists for an * application id, it will be backed up to a file named * <orig file name>~. */ public static void main(String[] args) throws IOException, ClassNotFoundException { Options opts = new Options(); final String[] arguments = opts.setFromCmdLine(args); boolean ret = Configurations.runAgainstAllAnchors(opts, new Configurations.Runnable() { public boolean run(Options opts) throws ClassNotFoundException, IOException { OpenJPAConfiguration conf = new OpenJPAConfigurationImpl(); try { return ApplicationIdTool.run(conf, arguments, opts); } finally { conf.close(); } } }); if (!ret) System.err.println(_loc.get("appid-usage")); } /** * Run the application id tool with the given command-line and * given configuration. Returns false if invalid options were given. */ public static boolean run(OpenJPAConfiguration conf, String[] args, Options opts) throws IOException, ClassNotFoundException { Flags flags = new Flags(); flags.ignoreErrors = opts.removeBooleanProperty ("ignoreErrors", "i", flags.ignoreErrors); flags.directory = Files.getFile(opts.removeProperty("directory", "d", null), null); flags.token = opts.removeProperty("token", "t", flags.token); flags.name = opts.removeProperty("name", "n", flags.name); flags.suffix = opts.removeProperty("suffix", "s", flags.suffix); // separate the properties for the customizer and code format Options formatOpts = new Options(); Map.Entry entry; String key; for (Iterator itr = opts.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); key = (String) entry.getKey(); if (key.startsWith("codeFormat.")) { formatOpts.put(key.substring(11), entry.getValue()); itr.remove(); } else if (key.startsWith("cf.")) { formatOpts.put(key.substring(3), entry.getValue()); itr.remove(); } } if (!formatOpts.isEmpty()) { flags.format = new CodeFormat(); formatOpts.setInto(flags.format); } Configurations.populateConfiguration(conf, opts); ClassLoader loader = conf.getClassResolverInstance(). getClassLoader(ApplicationIdTool.class, null); return run(conf, args, flags, loader); } /** * Run the tool. Returns false if invalid options were given. */ public static boolean run(OpenJPAConfiguration conf, String[] args, Flags flags, ClassLoader loader) throws IOException, ClassNotFoundException { MetaDataRepository repos = conf.newMetaDataRepositoryInstance(); repos.setValidate(repos.VALIDATE_NONE, true); loadObjectIds(repos, flags.name == null && flags.suffix == null); Log log = conf.getLog(OpenJPAConfiguration.LOG_TOOL); Collection classes; if (args.length == 0) { log.info(_loc.get("running-all-classes")); classes = repos.loadPersistentTypes(true, loader); } else { ClassArgParser cap = conf.getMetaDataRepositoryInstance(). getMetaDataFactory().newClassArgParser(); cap.setClassLoader(loader); classes = new HashSet(); for (int i = 0; i < args.length; i++) classes.addAll(Arrays.asList(cap.parseTypes(args[i]))); } if (flags.name != null && classes.size() > 1) throw new UserException(_loc.get("name-mult-args", classes)); ApplicationIdTool tool; Class cls; ClassMetaData meta; BCClassLoader bc = AccessController .doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(new Project())); for (Iterator itr = classes.iterator(); itr.hasNext();) { cls = (Class) itr.next(); log.info(_loc.get("appid-running", cls)); meta = repos.getMetaData(cls, null, false); setObjectIdType(meta, flags, bc); tool = new ApplicationIdTool(conf, cls, meta); tool.setDirectory(flags.directory); tool.setIgnoreErrors(flags.ignoreErrors); tool.setToken(flags.token); tool.setCodeFormat(flags.format); if (tool.run()) { log.info(_loc.get("appid-output", tool.getFile())); tool.record(); } else log.info(_loc.get("appid-norun")); } bc.getProject().clear(); return true; } /** * Set the object id type of the given metadata. */ private static void setObjectIdType(ClassMetaData meta, Flags flags, BCClassLoader bc) throws ClassNotFoundException { if (meta == null || (meta.getObjectIdType() != null && (!meta.isOpenJPAIdentity() || flags.name == null)) || getDeclaredPrimaryKeyFields(meta).length == 0) return; Class desc = meta.getDescribedType(); Class cls = null; if (flags.name != null) cls = loadClass(desc, flags.name, bc); else if (flags.suffix != null) cls = loadClass(desc, desc.getName() + flags.suffix, bc); meta.setObjectIdType(cls, false); } /** * Load the given class name even if it does not exist. */ private static Class loadClass(Class context, String name, BCClassLoader bc) throws ClassNotFoundException { if (name.indexOf('.') == -1 && context.getName().indexOf('.') != -1) name = Strings.getPackageName(context) + "." + name; // first try with regular class loader ClassLoader loader = AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(context)); if (loader == null) loader = AccessController.doPrivileged( J2DoPrivHelper.getContextClassLoaderAction()); try { return Class.forName(name, false, loader); } catch (Throwable t) { } // create class BCClass oid = bc.getProject().loadClass(name, null); oid.addDefaultConstructor(); return Class.forName(name, false, bc); } /** * Tell the metadata factory to load object id classes even if they don't * exist. */ private static void loadObjectIds(MetaDataRepository repos, boolean fatal) { MetaDataFactory mdf = repos.getMetaDataFactory(); if (mdf instanceof DelegatingMetaDataFactory) mdf = ((DelegatingMetaDataFactory) mdf).getInnermostDelegate(); if (mdf instanceof ObjectIdLoader) ((ObjectIdLoader) mdf).setLoadObjectIds(); else if (fatal) throw new InvalidStateException(_loc.get("factory-not-oidloader")). setFatal(true); } /** * Run flags. */ public static class Flags { public File directory = null; public boolean ignoreErrors = true; public String token = TOKEN_DEFAULT; public CodeFormat format = null; public String name = null; public String suffix = null; } /** * Interface implemented by metadata factories that can load non-existant * object id classes. */ public static interface ObjectIdLoader { /** * Turn on the loading of all identity classes, even if they don't * exist. */ public void setLoadObjectIds (); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ReflectingPersistenceCapable.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ReflectingPersistenceCapa0000644000000000000000000003213212133327272030413 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.Method; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StateManagerImpl; import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.ApplicationIds; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.ObjectId; /** * Implementation of the {@link PersistenceCapable} interface that can handle * the persistence-capable contract for instances that were not enhanced * before class load time. * * @since 1.0.0 */ public class ReflectingPersistenceCapable implements PersistenceCapable, ManagedInstanceProvider, Serializable { private Object o; private StateManager sm; // this will be reconstituted in readObject() private transient PersistenceCapable pcSubclassInstance; // this will reconstituted by a call to pcReplaceStateManager() by the // instance that has a reference to the deserialized data private transient ClassMetaData meta; private boolean serializationUserVisible = true; public ReflectingPersistenceCapable(Object o, OpenJPAConfiguration conf) { this.o = o; Class type = o.getClass(); pcSubclassInstance = PCRegistry.newInstance(type, null, false); meta = conf.getMetaDataRepositoryInstance() .getMetaData(type, null, true); } public int pcGetEnhancementContractVersion() { return PCEnhancer.ENHANCER_VERSION; } public Object pcGetGenericContext() { if (sm == null) return null; else return sm.getGenericContext(); } public StateManager pcGetStateManager() { return sm; } public void pcReplaceStateManager(StateManager sm) { this.sm = sm; if (meta == null && sm instanceof OpenJPAStateManager) meta = ((OpenJPAStateManager) sm).getMetaData(); } public void pcProvideField(int i) { Object value = getValue(i, o); switch (meta.getField(i).getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: sm.providedBooleanField(this, i, value == null ? false : ((Boolean) value).booleanValue()); break; case JavaTypes.BYTE: sm.providedByteField(this, i, value == null ? 0 : ((Byte) value).byteValue()); break; case JavaTypes.CHAR: sm.providedCharField(this, i, value == null ? 0 : ((Character) value).charValue()); break; case JavaTypes.DOUBLE: sm.providedDoubleField(this, i, value == null ? 0 : ((Double) value).doubleValue()); break; case JavaTypes.FLOAT: sm.providedFloatField(this, i, value == null ? 0 : ((Float) value).floatValue()); break; case JavaTypes.INT: sm.providedIntField(this, i, value == null ? 0 : ((Integer) value).intValue()); break; case JavaTypes.LONG: sm.providedLongField(this, i, value == null ? 0 : ((Long) value).longValue()); break; case JavaTypes.SHORT: sm.providedShortField(this, i, value == null ? 0 : ((Short) value).shortValue()); break; case JavaTypes.STRING: sm.providedStringField(this, i, (String) value); break; default: sm.providedObjectField(this, i, value); break; } } public void pcProvideFields(int[] fieldIndices) { for(int i = 0; i < fieldIndices.length; i++) pcProvideField(fieldIndices[i]); } public void pcReplaceField(int i) { switch(meta.getField(i).getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: setValue(i, o, Boolean.valueOf( sm.replaceBooleanField(this, i))); break; case JavaTypes.BYTE: setValue(i, o, Byte.valueOf(sm.replaceByteField(this, i))); break; case JavaTypes.CHAR: setValue(i, o, Character.valueOf(sm.replaceCharField(this, i))); break; case JavaTypes.DOUBLE: setValue(i, o, new Double(sm.replaceDoubleField(this, i))); break; case JavaTypes.FLOAT: setValue(i, o, new Float(sm.replaceFloatField(this, i))); break; case JavaTypes.INT: setValue(i, o, Integer.valueOf(sm.replaceIntField(this, i))); break; case JavaTypes.LONG: setValue(i, o, Long.valueOf(sm.replaceLongField(this, i))); break; case JavaTypes.SHORT: setValue(i, o, Short.valueOf(sm.replaceShortField(this, i))); break; case JavaTypes.STRING: setValue(i, o, sm.replaceStringField(this, i)); break; default: setValue(i, o, sm.replaceObjectField(this, i)); break; } } public void pcReplaceFields(int[] fieldIndices) { for(int i = 0; i < fieldIndices.length; i++) pcReplaceField(fieldIndices[i]); } public void pcCopyField(Object fromObject, int i) { // this doesn't need switch treatment because we're just // reflecting on both sides, bypassing field managers. setValue(i, o, getValue(i, fromObject)); } public void pcCopyFields(Object fromObject, int[] fieldIndices) { if (fromObject instanceof ReflectingPersistenceCapable) fromObject = ((ReflectingPersistenceCapable) fromObject) .getManagedInstance(); for(int i = 0; i < fieldIndices.length; i++) pcCopyField(fromObject, fieldIndices[i]); } public void pcDirty(String fieldName) { if (sm != null) sm.dirty(fieldName); } public Object pcFetchObjectId() { if (sm != null) return sm.fetchObjectId(); else return null; } public Object pcGetVersion() { if (sm == null) return null; else return sm.getVersion(); } public boolean pcIsDirty() { if (sm == null) return false; else { if (sm instanceof StateManagerImpl) ((StateManagerImpl) sm).dirtyCheck(); return sm.isDirty(); } } public boolean pcIsTransactional() { if (sm == null) return false; else return sm.isTransactional(); } public boolean pcIsPersistent() { if (sm == null) return false; else return sm.isPersistent(); } public boolean pcIsNew() { if (sm == null) return false; else return sm.isNew(); } public boolean pcIsDeleted() { if (sm == null) return false; else return sm.isDeleted(); } // null == unknown public Boolean pcIsDetached() { if (sm != null) return Boolean.valueOf(sm.isDetached()); // ##### we could do a lot more here if a detached state field // ##### was specified. return null; } public PersistenceCapable pcNewInstance(StateManager sm, boolean clear) { return pcSubclassInstance.pcNewInstance(sm, clear); } public PersistenceCapable pcNewInstance(StateManager sm, Object oid, boolean clear) { return pcSubclassInstance.pcNewInstance(sm, oid, clear); } public Object pcNewObjectIdInstance() { FieldMetaData[] pkFields = meta.getPrimaryKeyFields(); Object[] pks = new Object[pkFields.length]; for (int i = 0; i < pkFields.length; i++) pks[i] = getValue(pkFields[i].getIndex(), o); return ApplicationIds.fromPKValues(pks, meta); } public Object pcNewObjectIdInstance(Object oid) { return pcSubclassInstance.pcNewObjectIdInstance(oid); } public void pcCopyKeyFieldsToObjectId(Object oid) { Object target; if (oid instanceof ObjectId) target = ((ObjectId) oid).getId(); else target = oid; FieldMetaData[] pks = meta.getPrimaryKeyFields(); for (int i = 0; i < pks.length; i++) { Object val = getValue(pks[i].getIndex(), o); Field f = Reflection.findField(target.getClass(), pks[i].getName(), true); Reflection.set(target, f, val); } } public void pcCopyKeyFieldsToObjectId(FieldSupplier supplier, Object obj) { // This is only ever invoked against PCs in the PCRegistry. Such PCs // will always be enhanced types or subtypes of user types, and will // never be a ReflectingPersistenceCapable. throw new InternalException(); } public void pcCopyKeyFieldsFromObjectId(FieldConsumer consumer, Object obj) { // This is only ever invoked against PCs in the PCRegistry. Such PCs // will always be enhanced types or subtypes of user types, and will // never be a ReflectingPersistenceCapable. throw new InternalException(); } public Object pcGetDetachedState() { // ##### we can implement this if a state field has been set return null; } public void pcSetDetachedState(Object state) { // StateManagerImpl will invoke this with null during instance // initialization if (state != null) throw new UnsupportedOperationException(); // ##### we can implement this if a state field has been set } public void pcSetSerializationUserVisible(boolean userVisible) { serializationUserVisible = userVisible; } public boolean pcIsSerializationUserVisible() { return serializationUserVisible; } public Object getManagedInstance() { return o; } private Object getValue(int i, Object o) { FieldMetaData fmd = meta.getField(i); if (AccessCode.isProperty(fmd.getAccessType())) { Field field = Reflection.findField(meta.getDescribedType(), toFieldName(i), true); return Reflection.get(o, field); } else { Field field = (Field) meta.getField(i).getBackingMember(); return Reflection.get(o, field); } } private String toFieldName(int i) { if (pcSubclassInstance instanceof AttributeTranslator) return ((AttributeTranslator) pcSubclassInstance) .pcAttributeIndexToFieldName(i); else return meta.getField(i).getName(); } private void setValue(int i, Object o, Object val) { FieldMetaData fmd = meta.getField(i); if (AccessCode.isProperty(fmd.getAccessType())) { if (!meta.isIntercepting()) { Method meth = Reflection.findSetter(meta.getDescribedType(), meta.getField(i).getName(), true); Reflection.set(o, meth, val); } else { Field field = Reflection.findField(meta.getDescribedType(), toFieldName(i), true); Reflection.set(o, field, val); } } else { Field field = (Field) meta.getField(i).getBackingMember(); Reflection.set(o, field, val); } } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeObject(meta.getDescribedType()); } private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { in.defaultReadObject(); Class type = (Class) in.readObject(); pcSubclassInstance = PCRegistry.newInstance(type, null, false); ImplHelper.registerPersistenceCapable(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/package.html0000644000000000000000000000204112133327272025671 0ustar

OpenJPA Enhancer

This package provides a bytecode enhancer used to post-process classes for use in a OpenJPA runtime. A tool for generating application identity class sourcecode is also provided.

././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.ja0000644000000000000000000002141112133327272030241 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.ByteArrayInputStream; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.GeneralException; import serp.bytecode.BCClass; import serp.bytecode.Project; import serp.bytecode.lowlevel.ConstantPoolTable; /** * Transformer that makes persistent classes implement the * {@link PersistenceCapable} interface at runtime. * * @author Abe White * @nojavadoc */ public class PCClassFileTransformer implements ClassFileTransformer { private static final Localizer _loc = Localizer.forPackage (PCClassFileTransformer.class); private final MetaDataRepository _repos; private final PCEnhancer.Flags _flags; private final ClassLoader _tmpLoader; private final Log _log; private final Set _names; private boolean _transforming = false; /** * Constructor. * * @param repos metadata repository to use internally * @param opts enhancer configuration options * @param loader temporary class loader for loading intermediate classes */ public PCClassFileTransformer(MetaDataRepository repos, Options opts, ClassLoader loader) { this(repos, toFlags(opts), loader, opts.removeBooleanProperty ("scanDevPath", "ScanDevPath", false)); } /** * Create enhancer flags from the given options. */ private static PCEnhancer.Flags toFlags(Options opts) { PCEnhancer.Flags flags = new PCEnhancer.Flags(); flags.addDefaultConstructor = opts.removeBooleanProperty ("addDefaultConstructor", "AddDefaultConstructor", flags.addDefaultConstructor); flags.enforcePropertyRestrictions = opts.removeBooleanProperty ("enforcePropertyRestrictions", "EnforcePropertyRestrictions", flags.enforcePropertyRestrictions); return flags; } /** * Constructor. * * @param repos metadata repository to use internally * @param flags enhancer configuration * @param loader temporary class loader for loading intermediate classes * @param devscan whether to scan the dev classpath for persistent types * if none are configured */ public PCClassFileTransformer(MetaDataRepository repos, PCEnhancer.Flags flags, ClassLoader tmpLoader, boolean devscan) { _repos = repos; _tmpLoader = tmpLoader; _log = repos.getConfiguration(). getLog(OpenJPAConfiguration.LOG_ENHANCE); _flags = flags; _names = repos.getPersistentTypeNames(devscan, tmpLoader); if (_names == null && _log.isInfoEnabled()) _log.info(_loc.get("runtime-enhance-pcclasses")); } public byte[] transform(ClassLoader loader, String className, Class redef, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException { if (loader == _tmpLoader) return null; // JDK bug -- OPENJPA-1676 if (className == null) { return null; } // prevent re-entrant calls, which can occur if the enhancing // loader is used to also load OpenJPA libraries; this is to prevent // recursive enhancement attempts for internal openjpa libraries if (_transforming) return null; _transforming = true; return transform0(className, redef, bytes); } /** * We have to split the transform method into two methods to avoid * ClassCircularityError when executing method using pure-JIT JVMs * such as JRockit. */ private byte[] transform0(String className, Class redef, byte[] bytes) throws IllegalClassFormatException { byte[] returnBytes = null; try { Boolean enhance = needsEnhance(className, redef, bytes); if (enhance != null && _log.isTraceEnabled()) _log.trace(_loc.get("needs-runtime-enhance", className, enhance)); if (enhance != Boolean.TRUE) return null; PCEnhancer enhancer = new PCEnhancer(_repos.getConfiguration(), new Project().loadClass(new ByteArrayInputStream(bytes), _tmpLoader), _repos); enhancer.setAddDefaultConstructor(_flags.addDefaultConstructor); enhancer.setEnforcePropertyRestrictions (_flags.enforcePropertyRestrictions); if (enhancer.run() == PCEnhancer.ENHANCE_NONE) return null; BCClass pcb = enhancer.getPCBytecode(); returnBytes = AsmAdaptor.toByteArray(pcb, pcb.toByteArray()); return returnBytes; } catch (Throwable t) { _log.warn(_loc.get("cft-exception-thrown", className), t); if (t instanceof RuntimeException) throw (RuntimeException) t; if (t instanceof IllegalClassFormatException) throw (IllegalClassFormatException) t; throw new GeneralException(t); } finally { _transforming = false; if (returnBytes != null && _log.isTraceEnabled()) _log.trace(_loc.get("runtime-enhance-complete", className, bytes.length, returnBytes.length)); } } /** * Return whether the given class needs enhancement. */ private Boolean needsEnhance(String clsName, Class redef, byte[] bytes) { if (redef != null) { Class[] intfs = redef.getInterfaces(); for (int i = 0; i < intfs.length; i++) if (PersistenceCapable.class.getName(). equals(intfs[i].getName())) return Boolean.valueOf(!isEnhanced(bytes)); return null; } if (_names != null) { if (_names.contains(clsName.replace('/', '.'))) return Boolean.valueOf(!isEnhanced(bytes)); return null; } if (clsName.startsWith("java/") || clsName.startsWith("javax/")) return null; if (isEnhanced(bytes)) return Boolean.FALSE; try { Class c = Class.forName(clsName.replace('/', '.'), false, _tmpLoader); if (_repos.getMetaData(c, null, false) != null) return Boolean.TRUE; return null; } catch (ClassNotFoundException cnfe) { // cannot load the class: this might mean that it is a proxy // or otherwise inaccessible class which can't be an entity return Boolean.FALSE; } catch (LinkageError cce) { // this can happen if we are loading classes that this // class depends on; these will never be enhanced anyway return Boolean.FALSE; } catch (RuntimeException re) { throw re; } catch (Throwable t) { throw new GeneralException(t); } } /** * Analyze the bytecode to see if the given class definition implements * {@link PersistenceCapable}. */ private static boolean isEnhanced(byte[] b) { ConstantPoolTable table = new ConstantPoolTable(b); int idx = table.getEndIndex(); idx += 6; // skip access, cls, super int ifaces = table.readUnsignedShort(idx); int clsEntry, utfEntry; String name; for (int i = 0; i < ifaces; i++) { idx += 2; clsEntry = table.readUnsignedShort(idx); utfEntry = table.readUnsignedShort(table.get(clsEntry)); name = table.readString(table.get(utfEntry)); if ("org/apache/openjpa/enhance/PersistenceCapable".equals(name)) return true; } return false; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java0000644000000000000000000010235412133327272026355 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.ReferenceMap; import org.apache.openjpa.lib.util.Reflectable; import org.apache.openjpa.lib.util.Localizer.Message; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.UserException; /** * Reflection utilities used to support and augment enhancement. Used both * at enhancement time and at runtime. * * @author Abe White */ public class Reflection { private static final Localizer _loc = Localizer.forPackage (Reflection.class); // Weak HashMap caches of getter/setter/beanProperty methods private static Map, Map> getterMethodCache = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD); private static Map, Map> setterMethodCache = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD); private static Map, Set> beanPropertiesNameCache = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD); private static Method getGetterMethod(Class cls, String prop) { Method rtnMethod = null; Map clsMap = getterMethodCache.get(cls); if (clsMap != null) { rtnMethod = clsMap.get(prop); } return rtnMethod; } private static void setGetterMethod(Class cls, String prop, Method method) { Map clsMap = getterMethodCache.get(cls); if (clsMap == null) { clsMap = new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK); getterMethodCache.put(cls, clsMap); } clsMap.put(prop, method); } private static Method getSetterMethod(Class cls, String prop) { Method rtnMethod = null; Map clsMap = setterMethodCache.get(cls); if (clsMap != null) { rtnMethod = clsMap.get(prop); } return rtnMethod; } private static void setSetterMethod(Class cls, String prop, Method method) { Map clsMap = setterMethodCache.get(cls); if (clsMap == null) { clsMap = new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK); setterMethodCache.put(cls, clsMap); } clsMap.put(prop, method); } /** * Return the getter method matching the given property name, optionally * throwing an exception if none. */ public static Method findGetter(Class cls, String prop, boolean mustExist) { Method m = getGetterMethod(cls, prop); if (m != null) { return m; } String capProp = StringUtils.capitalize(prop); try { // this algorithm searches for a get or is method in // a breadth-first manner. for (Class c = cls; c != null && c != Object.class; c = c.getSuperclass()) { m = getDeclaredMethod(c, "get" + capProp, null); if (m != null) { setGetterMethod(cls, prop, m); return m; } else { m = getDeclaredMethod(c, "is" + capProp, null); if (m != null && (m.getReturnType() == boolean.class || m.getReturnType() == Boolean.class)) { setGetterMethod(cls, prop, m); return m; } } } } catch (Exception e) { throw new GeneralException(e); } if (mustExist) throw new UserException(_loc.get("bad-getter", cls, prop)); return null; } /** * Return the setter method matching the given property name, optionally * throwing an exception if none. The property must also have a getter. */ public static Method findSetter(Class cls, String prop, boolean mustExist) { Method getter = findGetter(cls, prop, mustExist); return (getter == null) ? null : findSetter(cls, prop, getter.getReturnType(), mustExist); } /** * Return the setter method matching the given property name, optionally * throwing an exception if none. */ public static Method findSetter(Class cls, String prop, Class param, boolean mustExist) { Method m = getSetterMethod(cls, prop); if (m != null) { return m; } String name = "set" + StringUtils.capitalize(prop); try { for (Class c = cls; c != null && c != Object.class; c = c.getSuperclass()) { m = getDeclaredMethod(c, name, param); if (m != null) { setSetterMethod(cls, prop, m); return m; } } } catch (Exception e) { throw new GeneralException(e); } if (mustExist) throw new UserException(_loc.get("bad-setter", cls, prop)); return null; } /** * Invokes cls.getDeclaredMethods(), and returns the method * that matches the name and param arguments. * Avoids the exception thrown by Class.getDeclaredMethod() * for performance reasons. param may be null. Additionally, * if there are multiple methods with different return types, this will * return the method defined in the least-derived class. * * @since 0.9.8 */ static Method getDeclaredMethod(Class cls, String name, Class param) { Method[] methods = (Method[]) AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodsAction(cls)); Method candidate = null; for (int i = 0 ; i < methods.length; i++) { if (name.equals(methods[i].getName())) { Class[] methodParams = methods[i].getParameterTypes(); if (param == null && methodParams.length == 0) candidate = mostDerived(methods[i], candidate); else if (param != null && methodParams.length == 1 && param.equals(methodParams[0])) candidate = mostDerived(methods[i], candidate); } } return candidate; } static Method mostDerived(Method meth1, Method meth2) { if (meth1 == null) return meth2; if (meth2 == null) return meth1; Class cls2 = meth2.getDeclaringClass(); Class cls1 = meth1.getDeclaringClass(); if (cls1.equals(cls2)) { Class ret1 = meth1.getReturnType(); Class ret2 = meth2.getReturnType(); if (ret1.isAssignableFrom(ret2)) return meth2; else if (ret2.isAssignableFrom(ret1)) return meth1; else throw new IllegalArgumentException( _loc.get("most-derived-unrelated-same-type", meth1, meth2) .getMessage()); } else { if (cls1.isAssignableFrom(cls2)) return meth2; else if (cls2.isAssignableFrom(cls1)) return meth1; else throw new IllegalArgumentException( _loc.get("most-derived-unrelated", meth1, meth2) .getMessage()); } } /** * Return the field with the given name, optionally throwing an exception * if none. */ public static Field findField(Class cls, String name, boolean mustExist) { try { Field f; for (Class c = cls; c != null && c != Object.class; c = c.getSuperclass()) { f = getDeclaredField(c, name); if (f != null) return f; } } catch (Exception e) { throw new GeneralException(e); } if (mustExist) throw new UserException(_loc.get("bad-field", cls, name)); return null; } /** * Invokes cls.getDeclaredFields(), and returns the field * that matches the name argument. Avoids the exception * thrown by Class.getDeclaredField() for performance reasons. * * @since 0.9.8 */ private static Field getDeclaredField(Class cls, String name) { Field[] fields = AccessController.doPrivileged( J2DoPrivHelper.getDeclaredFieldsAction(cls)); for (int i = 0 ; i < fields.length; i++) { if (name.equals(fields[i].getName())) return fields[i]; } return null; } /** * Return the value of the given field in the given object. */ public static Object get(Object target, Field field) { if (target == null || field == null) return null; makeAccessible(field, field.getModifiers()); try { return field.get(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Get the value of the given named field or a corresponding getter method. * * @return null if the field does not exist and mustExist is set to false or * the given target is null. * * @exception UserException if mustExist is true and the field or getter * method is non-existent */ public static Object getValue(Object obj, String prop, boolean mustExist) { if (obj == null) return null; Class cls = obj.getClass(); Field field = findField(cls, prop, false); if (field != null) return get(obj, field); Method getter = findGetter(cls, prop, false); if (getter != null) return get(obj, getter); if (mustExist) throw new UserException(_loc.get("bad-field", cls, prop)); return null; // should not reach } /** * Make the given member accessible if it isn't already. */ private static void makeAccessible(AccessibleObject ao, int mods) { try { if (!Modifier.isPublic(mods) && !ao.isAccessible()) AccessController.doPrivileged(J2DoPrivHelper .setAccessibleAction(ao, true)); } catch (SecurityException se) { throw new UserException(_loc.get("reflect-security", ao)). setFatal(true); } } /** * Wrap the given reflection exception as a runtime exception. */ private static RuntimeException wrapReflectionException(Throwable t, Message message) { if (t instanceof InvocationTargetException) t = ((InvocationTargetException) t).getTargetException(); t.initCause(new IllegalArgumentException(message.getMessage())); if (t instanceof RuntimeException) return (RuntimeException) t; return new GeneralException(t); } /** * Return the value of the given field in the given object. */ public static boolean getBoolean(Object target, Field field) { if (target == null || field == null) return false; makeAccessible(field, field.getModifiers()); try { return field.getBoolean(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Return the value of the given field in the given object. */ public static byte getByte(Object target, Field field) { if (target == null || field == null) return (byte) 0; makeAccessible(field, field.getModifiers()); try { return field.getByte(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Return the value of the given field in the given object. */ public static char getChar(Object target, Field field) { if (target == null || field == null) return (char) 0; makeAccessible(field, field.getModifiers()); try { return field.getChar(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Return the value of the given field in the given object. */ public static double getDouble(Object target, Field field) { if (target == null || field == null) return 0D; makeAccessible(field, field.getModifiers()); try { return field.getDouble(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Return the value of the given field in the given object. */ public static float getFloat(Object target, Field field) { if (target == null || field == null) return 0F; makeAccessible(field, field.getModifiers()); try { return field.getFloat(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Return the value of the given field in the given object. */ public static int getInt(Object target, Field field) { if (target == null || field == null) return 0; makeAccessible(field, field.getModifiers()); try { return field.getInt(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Return the value of the given field in the given object. */ public static long getLong(Object target, Field field) { if (target == null || field == null) return 0L; makeAccessible(field, field.getModifiers()); try { return field.getLong(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Return the value of the given field in the given object. */ public static short getShort(Object target, Field field) { if (target == null || field == null) return (short) 0; makeAccessible(field, field.getModifiers()); try { return field.getShort(target); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-field", target, field)); } } /** * Return the return value of the given getter in the given object. */ public static Object get(Object target, Method getter) { if (target == null || getter == null) return null; makeAccessible(getter, getter.getModifiers()); try { return getter.invoke(target, (Object[]) null); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("get-method", target, getter)); } } /** * Return the return value of the given getter in the given object. */ public static boolean getBoolean(Object target, Method getter) { Object o = get(target, getter); return (o == null) ? false : ((Boolean) o).booleanValue(); } /** * Return the return value of the given getter in the given object. */ public static byte getByte(Object target, Method getter) { Object o = get(target, getter); return (o == null) ? (byte) 0 : ((Number) o).byteValue(); } /** * Return the return value of the given getter in the given object. */ public static char getChar(Object target, Method getter) { Object o = get(target, getter); return (o == null) ? (char) 0 : ((Character) o).charValue(); } /** * Return the return value of the given getter in the given object. */ public static double getDouble(Object target, Method getter) { Object o = get(target, getter); return (o == null) ? 0D : ((Number) o).doubleValue(); } /** * Return the return value of the given getter in the given object. */ public static float getFloat(Object target, Method getter) { Object o = get(target, getter); return (o == null) ? 0F : ((Number) o).floatValue(); } /** * Return the return value of the given getter in the given object. */ public static int getInt(Object target, Method getter) { Object o = get(target, getter); return (o == null) ? 0 : ((Number) o).intValue(); } /** * Return the return value of the given getter in the given object. */ public static long getLong(Object target, Method getter) { Object o = get(target, getter); return (o == null) ? 0L : ((Number) o).longValue(); } /** * Return the return value of the given getter in the given object. */ public static short getShort(Object target, Method getter) { Object o = get(target, getter); return (o == null) ? (short) 0 : ((Number) o).shortValue(); } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, Object value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.set(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, value == null ? "" : value.getClass()})); } } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, boolean value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.setBoolean(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "boolean"})); } } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, byte value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.setByte(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "byte"})); } } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, char value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.setChar(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "char"})); } } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, double value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.setDouble(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "double"})); } } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, float value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.setFloat(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "float"})); } } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, int value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.setInt(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "int"})); } } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, long value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.setLong(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "long"})); } } /** * Set the value of the given field in the given object. */ public static void set(Object target, Field field, short value) { if (target == null || field == null) return; makeAccessible(field, field.getModifiers()); try { field.setShort(target, value); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "short"})); } } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, Object value, Field field) { set(target, field, value); } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, boolean value, Field field) { set(target, field, value); } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, byte value, Field field) { set(target, field, value); } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, char value, Field field) { set(target, field, value); } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, double value, Field field) { set(target, field, value); } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, float value, Field field) { set(target, field, value); } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, int value, Field field) { set(target, field, value); } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, long value, Field field) { set(target, field, value); } /** * Set the value of the given field in the given object. * Same behavior as above methods, but parameter ordering is rearranged * to simplify usage from generated bytecodes. * * @since 1.0.0 */ public static void set(Object target, short value, Field field) { set(target, field, value); } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, Object value) { if (target == null || setter == null) return; makeAccessible(setter, setter.getModifiers()); try { setter.invoke(target, new Object[] { value }); } catch (Throwable t) { throw wrapReflectionException(t, _loc.get("set-method", new Object[]{target, setter, value, value == null ? "" : value.getClass()})); } } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, boolean value) { set(target, setter, (value) ? Boolean.TRUE : Boolean.FALSE); } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, byte value) { set(target, setter, Byte.valueOf(value)); } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, char value) { set(target, setter, Character.valueOf(value)); } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, double value) { set(target, setter, new Double(value)); } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, float value) { set(target, setter, new Float(value)); } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, int value) { set(target, setter, Integer.valueOf(value)); } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, long value) { set(target, setter, Long.valueOf(value)); } /** * Invoke the given setter on the given object. */ public static void set(Object target, Method setter, short value) { set(target, setter, Short.valueOf(value)); } /** * Gets all bean-style property names of the given Class or its superclass. * A bean-style property 'abc' exists in Class C iff C has declared * following pair of methods: * public void setAbc(Y y) or public C setAbc(Y y) * public Y getAbc(); * * If a getter property is annotated with {@link Reflectable}, then * it is ignored. * */ public static Set getBeanStylePropertyNames(Class c) { if (c == null) return Collections.emptySet(); Set result = beanPropertiesNameCache.get(c); if (result != null) { return result; } Method[] methods = c.getMethods(); if (methods == null || methods.length < 2) return Collections.emptySet(); result = new TreeSet(); for (Method m : methods) { if (m.getName().startsWith("get")) { if (!canReflect(m)) continue; String prop = StringUtils.capitalize(m.getName() .substring("get".length())); Class rtype = m.getReturnType(); try { Method setter = c.getMethod("set"+prop, new Class[]{rtype}); if (setter.getReturnType() == void.class || setter.getReturnType().isAssignableFrom(c)) result.add(prop); } catch (NoSuchMethodException e) { } } } beanPropertiesNameCache.put(c, result); return result; } /** * Gets all public field names of the given Class. * */ public static Set getPublicFieldNames(Class c) { if (c == null) return Collections.EMPTY_SET; Field[] fields = c.getFields(); if (fields == null || fields.length == 0) return Collections.EMPTY_SET; Set result = new TreeSet(); for (Field f : fields) { if (canReflect(f)) result.add(f.getName()); } return result; } /** * Gets values of all field f the given class such that f exactly * match the given modifiers and are of given type (Object implies any type) * unless f is annotated as {@link Reflectable}. * */ public static Set getFieldValues(Class c, int mods, Class t){ if (c == null) return Collections.EMPTY_SET; Field[] fields = c.getFields(); if (fields == null || fields.length == 0) return Collections.EMPTY_SET; Set result = new TreeSet(); for (Field f : fields) { if (mods == f.getModifiers() && (t == Object.class || t.isAssignableFrom(f.getType())) && canReflect(f)) { try { result.add((T)f.get(null)); } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } } } return result; } /** * Affirms if the given member is selected for reflection. The decision is * based on the following truth table on both the class-level and * member-level annotation (null annotation represents MAYBE) * * Class member * MAYBE MAYBE YES * MAYBE YES YES * MAYBE NO NO * * YES MAYBE YES * YES YES YES * YES NO NO * * NO YES YES * NO MAYBE NO * NO NO NO * */ static boolean canReflect(Reflectable cls, Reflectable member) { if (cls == null || cls.value()) { return member == null || member.value() == true; } else { return member != null && member.value() == true; } } /** * Affirms if the original declaration the given field is annotated * for reflection. */ static boolean canReflect(Field field) { Class cls = field.getDeclaringClass(); return canReflect((Reflectable)cls.getAnnotation(Reflectable.class), field.getAnnotation(Reflectable.class)); } /** * Affirms if the original declaration the given method is annotated * for reflection. */ static boolean canReflect(Method method) { Class cls = getDeclaringClass(method); if (cls != method.getDeclaringClass()) method = getDeclaringMethod(cls, method); return canReflect((Reflectable)cls.getAnnotation(Reflectable.class), method.getAnnotation(Reflectable.class)); } /** * Gets the declaring class of the given method signature but also checks * if the method is declared in an interface. If yes, then returns the * interface. */ public static Class getDeclaringClass(Method m) { if (m == null) return null; Class cls = m.getDeclaringClass(); Class[] intfs = cls.getInterfaces(); for (Class intf : intfs) { if (getDeclaringMethod(intf, m) != null) cls = intf; } return cls; } /** * Gets the method in the given class that has the same signature of the * given method, if exists. Otherwise, null. */ public static Method getDeclaringMethod(Class c, Method m) { try { Method m0 = c.getMethod(m.getName(), m.getParameterTypes()); return m0; } catch (Exception e) { return null; } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/RuntimeUnenhancedClassesModes.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/RuntimeUnenhancedClassesM0000644000000000000000000000217212133327272030407 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * Possible values for the openjpa.RuntimeUnenhancedClasses * configuration setting. * * @since 1.0.0 */ public interface RuntimeUnenhancedClassesModes { public final static int SUPPORTED = 0; public final static int UNSUPPORTED = 1; public final static int WARN = 2; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/StateManager.java0000644000000000000000000001613012133327272026632 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.IOException; import java.io.ObjectOutput; /** * Internal state manager for managed instances. */ public interface StateManager { // DO NOT ADD ADDITIONAL DEPENDENCIES TO THIS CLASS public static final int SET_USER = 0; public static final int SET_REMOTE = 1; public static final int SET_ATTACH = 2; /** * Persistence context. */ public Object getGenericContext(); /** * Return the persistence-capable primary key object by extracting the * identity value of the related instance stored in the given field from * the given object id. */ public Object getPCPrimaryKey(Object oid, int field); /** * Change state manager. */ public StateManager replaceStateManager(StateManager sm); /** * Returns the optimistic version for this instance. */ public Object getVersion(); /** * Whether the instance has been modified in this transaction. */ public boolean isDirty(); /** * Whether the instance is transactional. */ public boolean isTransactional(); /** * Whether the instance is persistent. */ public boolean isPersistent(); /** * Whether the instance is newly-persisted in this transaction. */ public boolean isNew(); /** * Whether the instance is deleted in this transaction. */ public boolean isDeleted(); /** * Whether the instance is detached (i.e. this manager is a detached * state manager) */ public boolean isDetached(); /** * Make named field dirty. */ public void dirty(String field); /** * Return the object id, assigning it if necessary. */ public Object fetchObjectId(); /** * Callback to prepare instance for serialization. * * @return true to null detached state after serialize */ public boolean serializing(); /** * Write detached state object and detached state manager to the * given stream. * * @return true if managed fields also written to stream */ public boolean writeDetached(ObjectOutput out) throws IOException; /** * Proxy the given detached field after deserialization. */ public void proxyDetachedDeserialized(int idx); /** * Field access callback. */ public void accessingField(int idx); /** * Setting state callback. */ public void settingBooleanField(PersistenceCapable pc, int idx, boolean cur, boolean next, int set); /** * Setting state callback. */ public void settingCharField(PersistenceCapable pc, int idx, char cur, char next, int set); /** * Setting state callback. */ public void settingByteField(PersistenceCapable pc, int idx, byte cur, byte next, int set); /** * Setting state callback. */ public void settingShortField(PersistenceCapable pc, int idx, short cur, short next, int set); /** * Setting state callback. */ public void settingIntField(PersistenceCapable pc, int idx, int cur, int next, int set); /** * Setting state callback. */ public void settingLongField(PersistenceCapable pc, int idx, long cur, long next, int set); /** * Setting state callback. */ public void settingFloatField(PersistenceCapable pc, int idx, float cur, float next, int set); /** * Setting state callback. */ public void settingDoubleField(PersistenceCapable pc, int idx, double cur, double next, int set); /** * Setting state callback. */ public void settingStringField(PersistenceCapable pc, int idx, String cur, String next, int set); /** * Setting state callback. */ public void settingObjectField(PersistenceCapable pc, int idx, Object cur, Object next, int set); /** * Provide state callback. */ public void providedBooleanField(PersistenceCapable pc, int idx, boolean cur); /** * Provide state callback. */ public void providedCharField(PersistenceCapable pc, int idx, char cur); /** * Provide state callback. */ public void providedByteField(PersistenceCapable pc, int idx, byte cur); /** * Provide state callback. */ public void providedShortField(PersistenceCapable pc, int idx, short cur); /** * Provide state callback. */ public void providedIntField(PersistenceCapable pc, int idx, int cur); /** * Provide state callback. */ public void providedLongField(PersistenceCapable pc, int idx, long cur); /** * Provide state callback. */ public void providedFloatField(PersistenceCapable pc, int idx, float cur); /** * Provide state callback. */ public void providedDoubleField(PersistenceCapable pc, int idx, double cur); /** * Provide state callback. */ public void providedStringField(PersistenceCapable pc, int idx, String cur); /** * Provide state callback. */ public void providedObjectField(PersistenceCapable pc, int idx, Object cur); /** * Replace state callback. */ public boolean replaceBooleanField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public char replaceCharField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public byte replaceByteField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public short replaceShortField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public int replaceIntField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public long replaceLongField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public float replaceFloatField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public double replaceDoubleField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public String replaceStringField(PersistenceCapable pc, int idx); /** * Replace state callback. */ public Object replaceObjectField (PersistenceCapable pc, int idx); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java0000644000000000000000000061550212133327272026235 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.Externalizable; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.Serializable; import java.io.ObjectStreamException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.meta.ClassArgParser; import org.apache.openjpa.lib.util.BytecodeWriter; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.lib.util.Services; import org.apache.openjpa.lib.util.Localizer.Message; import org.apache.openjpa.lib.util.svn.SVNUtils; import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.meta.ValueStrategies; import org.apache.openjpa.util.ApplicationIds; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.BigDecimalId; import org.apache.openjpa.util.BigIntegerId; import org.apache.openjpa.util.ByteId; import org.apache.openjpa.util.CharId; import org.apache.openjpa.util.DateId; import org.apache.openjpa.util.DoubleId; import org.apache.openjpa.util.Id; import org.apache.openjpa.util.IntId; import org.apache.openjpa.util.FloatId; import org.apache.openjpa.util.LongId; import org.apache.openjpa.util.ObjectId; import org.apache.openjpa.util.ShortId; import org.apache.openjpa.util.StringId; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; import org.apache.openjpa.util.ImplHelper; import serp.bytecode.BCClass; import serp.bytecode.BCField; import serp.bytecode.BCMethod; import serp.bytecode.Code; import serp.bytecode.Constants; import serp.bytecode.Exceptions; import serp.bytecode.FieldInstruction; import serp.bytecode.GetFieldInstruction; import serp.bytecode.IfInstruction; import serp.bytecode.Instruction; import serp.bytecode.JumpInstruction; import serp.bytecode.LoadInstruction; import serp.bytecode.LookupSwitchInstruction; import serp.bytecode.MethodInstruction; import serp.bytecode.Project; import serp.bytecode.PutFieldInstruction; import serp.bytecode.TableSwitchInstruction; import serp.bytecode.ClassInstruction; import serp.util.Strings; /** * Bytecode enhancer used to enhance persistent classes from metadata. The * enhancer must be invoked on all persistence-capable and persistence aware * classes. * * @author Abe White */ public class PCEnhancer { // Designates a version for maintaining compatbility when PCEnhancer // modifies enhancement that can break serialization or other contracts // Each enhanced class will return the value of this field via // public int getEnhancementContractVersion() public static final int ENHANCER_VERSION; boolean _addVersionInitFlag = true; public static final int ENHANCE_NONE = 0; public static final int ENHANCE_AWARE = 2 << 0; public static final int ENHANCE_INTERFACE = 2 << 1; public static final int ENHANCE_PC = 2 << 2; public static final String PRE = "pc"; public static final String ISDETACHEDSTATEDEFINITIVE = PRE + "isDetachedStateDefinitive"; private static final Class PCTYPE = PersistenceCapable.class; private static final String SM = PRE + "StateManager"; private static final Class SMTYPE = StateManager.class; private static final String INHERIT = PRE + "InheritedFieldCount"; private static final String CONTEXTNAME = "GenericContext"; private static final Class USEREXCEP = UserException.class; private static final Class INTERNEXCEP = InternalException.class; private static final Class HELPERTYPE = PCRegistry.class; private static final String SUPER = PRE + "PCSuperclass"; private static final Class OIDFSTYPE = FieldSupplier.class; private static final Class OIDFCTYPE = FieldConsumer.class; private static final String VERSION_INIT_STR = PRE + "VersionInit"; private static final Localizer _loc = Localizer.forPackage (PCEnhancer.class); private static final String REDEFINED_ATTRIBUTE = PCEnhancer.class.getName() + "#redefined-type"; private static final AuxiliaryEnhancer[] _auxEnhancers; static { Class[] classes = Services.getImplementorClasses( AuxiliaryEnhancer.class, AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(AuxiliaryEnhancer.class))); List auxEnhancers = new ArrayList(classes.length); for (int i = 0; i < classes.length; i++) { try { auxEnhancers.add(AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(classes[i]))); } catch (Throwable t) { // aux enhancer may rely on non-existant spec classes, etc } } _auxEnhancers = (AuxiliaryEnhancer[]) auxEnhancers.toArray (new AuxiliaryEnhancer[auxEnhancers.size()]); int rev = 0; Properties revisionProps = new Properties(); try { InputStream in = PCEnhancer.class.getResourceAsStream("/META-INF/org.apache.openjpa.revision.properties"); if (in != null) { try { revisionProps.load(in); } finally { in.close(); } } String prop = revisionProps.getProperty("openjpa.enhancer.revision"); rev = SVNUtils.svnInfoToInteger(prop); } catch (Exception e) { } if (rev > 0) { ENHANCER_VERSION = rev; } else { // Something bad happened and we couldn't load from the properties file. We need to default to using the // value of 2 because that is the value that was the value as of rev.511998. ENHANCER_VERSION = 2; } } private BCClass _pc; private final BCClass _managedType; private final MetaDataRepository _repos; private final ClassMetaData _meta; private final Log _log; private Collection _oids = null; private boolean _defCons = true; private boolean _redefine = false; private boolean _subclass = false; private boolean _fail = false; private Set _violations = null; private File _dir = null; private BytecodeWriter _writer = null; private Map _backingFields = null; // map of set / get names => field names private Map _attrsToFields = null; // map of attr names => field names private Map _fieldsToAttrs = null; // map of field names => attr names private boolean _isAlreadyRedefined = false; private boolean _isAlreadySubclassed = false; private boolean _bcsConfigured = false; private boolean _optimizeIdCopy = false; // whether to attempt optimizing id copy /** * Constructor. Supply configuration and type to enhance. This will look * up the metadata for type from conf's * repository. */ public PCEnhancer(OpenJPAConfiguration conf, Class type) { this(conf, AccessController.doPrivileged(J2DoPrivHelper .loadProjectClassAction(new Project(), type)), (MetaDataRepository) null); } /** * Constructor. Supply configuration and type to enhance. This will look * up the metadata for meta by converting back to a class * and then loading from conf's repository. */ public PCEnhancer(OpenJPAConfiguration conf, ClassMetaData meta) { this(conf, AccessController.doPrivileged(J2DoPrivHelper .loadProjectClassAction(new Project(), meta.getDescribedType())), meta.getRepository()); } /** * Constructor. Supply configuration. * * @param type the bytecode representation fo the type to * enhance; this can be created from any stream or file * @param repos a metadata repository to use for metadata access, * or null to create a new reporitory; the repository * from the given configuration isn't used by default * because the configuration might be an * implementation-specific subclass whose metadata * required more than just base metadata files * @deprecated use {@link #PCEnhancer(OpenJPAConfiguration, BCClass, MetaDataRepository, ClassLoader)} instead. */ public PCEnhancer(OpenJPAConfiguration conf, BCClass type, MetaDataRepository repos) { this(conf, type, repos, null); } /** * Constructor. Supply configuration. * * @param type the bytecode representation fo the type to * enhance; this can be created from any stream or file * @param repos a metadata repository to use for metadata access, * or null to create a new reporitory; the repository * from the given configuration isn't used by default * because the configuration might be an * implementation-specific subclass whose metadata * required more than just base metadata files * @param loader the environment classloader to use for loading * classes and resources. */ public PCEnhancer(OpenJPAConfiguration conf, BCClass type, MetaDataRepository repos, ClassLoader loader) { _managedType = type; _pc = type; _log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE); if (repos == null) { _repos = conf.newMetaDataRepositoryInstance(); _repos.setSourceMode(MetaDataRepository.MODE_META); } else _repos = repos; _meta = _repos.getMetaData(type.getType(), loader, false); configureOptimizeIdCopy(); } /** * Constructor. Supply repository. The repository's configuration will * be used, and the metadata passed in will be used as-is without doing * any additional lookups. This is useful when running the enhancer * during metadata load. * * @param repos a metadata repository to use for metadata access, * or null to create a new reporitory; the repository * from the given configuration isn't used by default * because the configuration might be an * implementation-specific subclass whose metadata * required more than just base metadata files * @param type the bytecode representation fo the type to * enhance; this can be created from any stream or file * @param meta the metadata to use for processing this type. * * @since 1.1.0 */ public PCEnhancer(MetaDataRepository repos, BCClass type, ClassMetaData meta) { _managedType = type; _pc = type; _log = repos.getConfiguration() .getLog(OpenJPAConfiguration.LOG_ENHANCE); _repos = repos; _meta = meta; } static String toPCSubclassName(Class cls) { return Strings.getPackageName(PCEnhancer.class) + "." + cls.getName().replace('.', '$') + "$pcsubclass"; } /** * Whether or not className is the name for a * dynamically-created persistence-capable subclass. * * @since 1.1.0 */ public static boolean isPCSubclassName(String className) { return className.startsWith(Strings.getPackageName(PCEnhancer.class)) && className.endsWith("$pcsubclass"); } /** * If className is a dynamically-created persistence-capable * subclass name, returns the name of the class that it subclasses. * Otherwise, returns className. * * @since 1.1.0 */ public static String toManagedTypeName(String className) { if (isPCSubclassName(className)) { className = className.substring( Strings.getPackageName(PCEnhancer.class).length() + 1); className = className.substring(0, className.lastIndexOf("$")); // this is not correct for nested PCs className = className.replace('$', '.'); } return className; } /** * Constructor. Supply configuration, type, and metadata. */ public PCEnhancer(OpenJPAConfiguration conf, BCClass type, ClassMetaData meta) { this(conf, type, meta.getRepository()); } /** * Return the bytecode representation of the persistence-capable class * being manipulated. */ public BCClass getPCBytecode() { return _pc; } /** * Return the bytecode representation of the managed class being * manipulated. This is usually the same as {@link #getPCBytecode}, * except when running the enhancer to redefine and subclass * existing persistent types. */ public BCClass getManagedTypeBytecode() { return _managedType; } /** * Return the metadata for the class being manipulated, or null if not * a persistent type. */ public ClassMetaData getMetaData() { return _meta; } /** * A boolean indicating whether the enhancer should add a no-args * constructor if one is not already present in the class. OpenJPA * requires that a no-arg constructor (whether created by the compiler * or by the user) be present in a PC. */ public boolean getAddDefaultConstructor() { return _defCons; } /** * A boolean indicating whether the enhancer should add a no-args * constructor if one is not already present in the class. OpenJPA * requires that a no-arg constructor (whether created by the compiler * or by the user) be present in a PC. */ public void setAddDefaultConstructor(boolean addDefaultConstructor) { _defCons = addDefaultConstructor; } /** * Whether the enhancer should mutate its arguments, or just run validation * and optional subclassing logic on them. Usually used in conjunction with * setCreateSubclass(true). * * @since 1.0.0 */ public boolean getRedefine() { return _redefine; } /** * Whether the enhancer should mutate its arguments, or just run validation * and optional subclassing logic on them. Usually used in conjunction with * setCreateSubclass(true). * * @since 1.0.0 */ public void setRedefine(boolean redefine) { _redefine = redefine; } /** * Whether the type that this instance is enhancing has already been * redefined. * * @since 1.0.0 */ public boolean isAlreadyRedefined() { return _isAlreadyRedefined; } /** * Whether the type that this instance is enhancing has already been * subclassed in this instance's environment classloader. * * @since 1.0.0 */ public boolean isAlreadySubclassed() { return _isAlreadySubclassed; } /** * Whether the enhancer should make its arguments persistence-capable, * or generate a persistence-capable subclass. * * @since 1.0.0 */ public boolean getCreateSubclass() { return _subclass; } /** * Whether the enhancer should make its arguments persistence-capable, * or generate a persistence-capable subclass. * * @since 1.0.0 */ public void setCreateSubclass(boolean subclass) { _subclass = subclass; _addVersionInitFlag = false; } /** * Whether to fail if the persistent type uses property access and * bytecode analysis shows that it may be violating OpenJPA's property * access restrictions. */ public boolean getEnforcePropertyRestrictions() { return _fail; } /** * Whether to fail if the persistent type uses property access and * bytecode analysis shows that it may be violating OpenJPA's property * access restrictions. */ public void setEnforcePropertyRestrictions(boolean fail) { _fail = fail; } /** * The base build directory to generate code to. The proper package * structure will be created beneath this directory. Defaults to * overwriting the existing class file if null. */ public File getDirectory() { return _dir; } /** * The base build directory to generate code to. The proper package * structure will be creaed beneath this directory. Defaults to * overwriting the existing class file if null. */ public void setDirectory(File dir) { _dir = dir; } /** * Return the current {@link BytecodeWriter} to write to or null if none. */ public BytecodeWriter getBytecodeWriter() { return _writer; } /** * Set the {@link BytecodeWriter} to write the bytecode to or null if none. */ public void setBytecodeWriter(BytecodeWriter writer) { _writer = writer; } /** * Perform bytecode enhancements. * * @return ENHANCE_* constant */ public int run() { Class type = _managedType.getType(); try { // if managed interface, skip if (_pc.isInterface()) return ENHANCE_INTERFACE; // check if already enhanced ClassLoader loader = AccessController.doPrivileged(J2DoPrivHelper.getClassLoaderAction(type)); for (Class iface : _managedType.getDeclaredInterfaceTypes()) { if (iface.getName().equals(PCTYPE.getName())) { if (_log.isTraceEnabled()) { _log.trace(_loc.get("pc-type", type, loader)); } return ENHANCE_NONE; } } if (_log.isTraceEnabled()) { _log.trace(_loc.get("enhance-start", type, loader)); } configureBCs(); // validate properties before replacing field access so that // we build up a record of backing fields, etc if (isPropertyAccess(_meta)) { validateProperties(); if (getCreateSubclass()) addAttributeTranslation(); } replaceAndValidateFieldAccess(); processViolations(); if (_meta != null) { enhanceClass(); addFields(); addStaticInitializer(); addPCMethods(); addAccessors(); addAttachDetachCode(); addSerializationCode(); addCloningCode(); runAuxiliaryEnhancers(); return ENHANCE_PC; } return ENHANCE_AWARE; } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(_loc.get("enhance-error", type.getName(), e.getMessage()), e); } } private void configureBCs() { if (!_bcsConfigured) { if (getRedefine()) { if (_managedType.getAttribute(REDEFINED_ATTRIBUTE) == null) _managedType.addAttribute(REDEFINED_ATTRIBUTE); else _isAlreadyRedefined = true; } if (getCreateSubclass()) { PCSubclassValidator val = new PCSubclassValidator( _meta, _managedType, _log, _fail); val.assertCanSubclass(); _pc = _managedType.getProject().loadClass( toPCSubclassName(_managedType.getType())); if (_pc.getSuperclassBC() != _managedType) { _pc.setSuperclass(_managedType); _pc.setAbstract(_managedType.isAbstract()); _pc.declareInterface(DynamicPersistenceCapable.class); } else { _isAlreadySubclassed = true; } } _bcsConfigured = true; } } /** * Write the generated bytecode. */ public void record() throws IOException { if (_managedType != _pc && getRedefine()) record(_managedType); record(_pc); if (_oids != null) for (Iterator itr = _oids.iterator(); itr.hasNext();) record((BCClass) itr.next()); } /** * Write the given class. */ private void record(BCClass bc) throws IOException { if (_writer != null) _writer.write(bc); else if (_dir == null) AsmAdaptor.write(bc); else { File dir = Files.getPackageFile(_dir, bc.getPackageName(), true); AsmAdaptor.write(bc, new File(dir, bc.getClassName() + ".class")); } } /** * Validate that the methods that use a property-access instance are * written correctly. This method also gathers information on each * property's backing field. */ private void validateProperties() { FieldMetaData[] fmds; if (getCreateSubclass()) fmds = _meta.getFields(); else fmds = _meta.getDeclaredFields(); Method meth; BCMethod getter, setter; BCField returned, assigned = null; for (int i = 0; i < fmds.length; i++) { if (!(fmds[i].getBackingMember() instanceof Method) ) { // If not mixed access is not defined, flag the field members, // otherwise do not process them because they are valid // persistent attributes. if (!_meta.isMixedAccess()) { addViolation("property-bad-member", new Object[]{ fmds[i], fmds[i].getBackingMember() }, true); } continue; } meth = (Method) fmds[i].getBackingMember(); // ##### this will fail if we override and don't call super. BCClass declaringType = _managedType.getProject() .loadClass(fmds[i].getDeclaringType()); getter = declaringType.getDeclaredMethod(meth.getName(), meth.getParameterTypes()); if (getter == null) { addViolation("property-no-getter", new Object[]{ fmds[i] }, true); continue; } returned = getReturnedField(getter); if (returned != null) registerBackingFieldInfo(fmds[i], getter, returned); setter = declaringType.getDeclaredMethod(getSetterName(fmds[i]), new Class[]{ fmds[i].getDeclaredType() }); if (setter == null) { if (returned == null) { addViolation("property-no-setter", new Object[]{ fmds[i] }, true); continue; } else if (!getRedefine()) { // create synthetic setter setter = _managedType.declareMethod(getSetterName(fmds[i]), void.class, new Class[]{ fmds[i].getDeclaredType() }); setter.makePrivate(); Code code = setter.getCode(true); code.aload().setThis(); code.xload().setParam(0); code.putfield().setField(returned); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } } if (setter != null) assigned = getAssignedField(setter); if (assigned != null) { if (setter != null) registerBackingFieldInfo(fmds[i], setter, assigned); if (assigned != returned) addViolation("property-setter-getter-mismatch", new Object[] { fmds[i], assigned.getName(), (returned == null) ? null : returned.getName() }, false); } } } private void registerBackingFieldInfo(FieldMetaData fmd, BCMethod method, BCField field) { if (_backingFields == null) _backingFields = new HashMap(); _backingFields.put(method.getName(), field.getName()); if (_attrsToFields == null) _attrsToFields = new HashMap(); _attrsToFields.put(fmd.getName(), field.getName()); if (_fieldsToAttrs == null) _fieldsToAttrs = new HashMap(); _fieldsToAttrs.put(field.getName(), fmd.getName()); } private void addAttributeTranslation() { // Get all field metadata ArrayList propFmds = new ArrayList(); FieldMetaData[] fmds = _meta.getFields(); if (_meta.isMixedAccess()) { // Stores indexes of property access fields to be used in // propFmds = new ArrayList(); // Determine which fields have property access and save their // indexes for (int i = 0; i < fmds.length; i++) { if (isPropertyAccess(fmds[i])) propFmds.add(i); } // if no fields have property access do not do attribute translation if (propFmds.size() == 0) return; } _pc.declareInterface(AttributeTranslator.class); BCMethod method = _pc.declareMethod(PRE + "AttributeIndexToFieldName", String.class, new Class[] { int.class }); method.makePublic(); Code code = method.getCode(true); // switch (val) code.iload().setParam(0); if (!_meta.isMixedAccess()) { // if not mixed access use a table switch on all property-based fmd. // a table switch is more efficient with +1 incremental operations TableSwitchInstruction tabins = code.tableswitch(); tabins.setLow(0); tabins.setHigh(fmds.length - 1); // case i: // return <_attrsToFields.get(fmds[i].getName())> for (int i = 0; i < fmds.length; i++) { tabins.addTarget(code.constant().setValue( _attrsToFields.get(fmds[i].getName()))); code.areturn(); } // default: throw new IllegalArgumentException () tabins.setDefaultTarget(throwException (code, IllegalArgumentException.class)); } else { // In mixed access mode, property indexes are not +1 incremental // a lookup switch must be used to do indexed lookup. LookupSwitchInstruction lookupins = code.lookupswitch(); for (Integer i : propFmds) { lookupins.addCase(i, code.constant().setValue( _attrsToFields.get(fmds[i].getName()))); code.areturn(); } // default: throw new IllegalArgumentException () lookupins.setDefaultTarget(throwException (code, IllegalArgumentException.class)); } code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Return the name of the setter method for the given field. */ private static String getSetterName(FieldMetaData fmd) { return "set" + StringUtils.capitalize(fmd.getName()); } /** * Return the field returned by the given method, or null if none. * Package-protected and static for testing. */ static BCField getReturnedField(BCMethod meth) { return findField(meth, (AccessController.doPrivileged( J2DoPrivHelper.newCodeAction())).xreturn() .setType(meth.getReturnType()), false); } /** * Return the field assigned in the given method, or null if none. * Package-protected and static for testing. */ static BCField getAssignedField(BCMethod meth) { return findField(meth, (AccessController.doPrivileged( J2DoPrivHelper.newCodeAction())).putfield(), true); } /** * Return the field returned / assigned by meth. Returns * null if non-fields (methods, literals, parameters, variables) are * returned, or if non-parameters are assigned to fields. */ private static BCField findField(BCMethod meth, Instruction template, boolean findAccessed) { // ignore any static methods. OpenJPA only currently supports // non-static setters and getters if (meth.isStatic()) return null; Code code = meth.getCode(false); if (code == null) return null; code.beforeFirst(); BCField field = null, cur; Instruction templateIns, prevIns, earlierIns; while (code.searchForward(template)) { int backupCount = 3; templateIns = code.previous(); if (!code.hasPrevious()) return null; prevIns = code.previous(); if (prevIns instanceof ClassInstruction && code.hasPrevious()) { prevIns = code.previous(); backupCount++; } if (!code.hasPrevious()) return null; earlierIns = code.previous(); // if the opcode two before the template was an aload_0, check // against the middle instruction based on what type of find // we're doing if (!(earlierIns instanceof LoadInstruction) || !((LoadInstruction) earlierIns).isThis()) return null; // if the middle instruction was a getfield, then it's the // field that's being accessed if (!findAccessed && prevIns instanceof GetFieldInstruction) { final FieldInstruction fPrevIns = (FieldInstruction) prevIns; cur = AccessController.doPrivileged( J2DoPrivHelper.getFieldInstructionFieldAction(fPrevIns)); // if the middle instruction was an xload_1, then the // matched instruction is the field that's being set. } else if (findAccessed && prevIns instanceof LoadInstruction && ((LoadInstruction) prevIns).getParam() == 0) { final FieldInstruction fTemplateIns = (FieldInstruction) templateIns; cur = AccessController.doPrivileged(J2DoPrivHelper .getFieldInstructionFieldAction(fTemplateIns)); } else return null; if (field != null && cur != field) return null; field = cur; // ready for next search iteration while (backupCount > 0) { code.next(); backupCount--; } } return field; } /** * Record a violation of the property access restrictions. */ private void addViolation(String key, Object[] args, boolean fatal) { if (_violations == null) _violations = new HashSet(); _violations.add(_loc.get(key, args)); _fail |= fatal; } /** * Log / throw recorded property access violations. */ private void processViolations() { if (_violations == null) return; String sep = J2DoPrivHelper.getLineSeparator(); StringBuilder buf = new StringBuilder(); for (Iterator itr = _violations.iterator(); itr.hasNext();) { buf.append(itr.next()); if (itr.hasNext()) buf.append(sep); } Message msg = _loc.get("property-violations", buf); if (_fail) throw new UserException(msg); if (_log.isWarnEnabled()) _log.warn(msg); } /** * Replaced all direct access to managed fields with the appropriate * pcGet/pcSet method. Note that this includes access to fields * owned by PersistenceCapable classes other than this one. */ private void replaceAndValidateFieldAccess() throws NoSuchMethodException { // create template putfield/getfield instructions to search for Code template = AccessController.doPrivileged( J2DoPrivHelper.newCodeAction()); Instruction put = template.putfield(); Instruction get = template.getfield(); Instruction stat = template.invokestatic(); // look through all methods; this is done before any methods are added // so we don't need to worry about excluding synthetic methods. BCMethod[] methods = _managedType.getDeclaredMethods(); Code code; for (int i = 0; i < methods.length; i++) { code = methods[i].getCode(false); // don't modify the methods specified by the auxiliary enhancers if (code != null && !skipEnhance(methods[i])) { replaceAndValidateFieldAccess(code, get, true, stat); replaceAndValidateFieldAccess(code, put, false, stat); } } } /** * Replaces all instructions matching the given template in the given * code block with calls to the appropriate generated getter/setter. * * @param code the code block to modify; the code iterator will * be placed before the first instruction on method start, * and will be after the last instruction on method completion * @param ins the template instruction to search for; either a * getfield or putfield instruction * @param get boolean indicating if this is a get instruction * @param stat template invokestatic instruction to replace with */ private void replaceAndValidateFieldAccess(Code code, Instruction ins, boolean get, Instruction stat) throws NoSuchMethodException { code.beforeFirst(); FieldInstruction fi; MethodInstruction mi; ClassMetaData owner; String name, typeName, methodName; while (code.searchForward(ins)) { // back up to the matched instruction fi = (FieldInstruction) code.previous(); name = fi.getFieldName(); typeName = fi.getFieldTypeName(); owner = getPersistenceCapableOwner(name, fi.getFieldDeclarerType()); FieldMetaData fmd = owner == null ? null : owner.getField(name); if (isPropertyAccess(fmd)) { // if we're directly accessing a field in another class // hierarchy that uses property access, something is wrong if (owner != _meta && owner.getDeclaredField(name) != null && _meta != null && !owner.getDescribedType() .isAssignableFrom(_meta.getDescribedType())) throw new UserException(_loc.get("property-field-access", new Object[]{ _meta, owner, name, code.getMethod().getName() })); // if we're directly accessing a property-backing field outside // the property in our own class, notify user if (isBackingFieldOfAnotherProperty(name, code)) addViolation("property-field-access", new Object[]{ _meta, owner, name, code.getMethod().getName() }, false); } if (owner == null || owner.getDeclaredField(fromBackingFieldName(name)) == null) { // not persistent field? code.next(); continue; } else if (!getRedefine() && !getCreateSubclass() && isFieldAccess(fmd)) { // replace the instruction with a call to the generated access // method mi = (MethodInstruction) code.set(stat); // invoke the proper access method, whether getter or setter String prefix = (get) ? PRE + "Get" : PRE + "Set"; methodName = prefix + name; if (get) { mi.setMethod(getType(owner).getName(), methodName, typeName, new String[] { getType(owner).getName() }); } else { mi.setMethod(getType(owner).getName(), methodName, "void", new String[] { getType(owner).getName(), typeName }); } code.next(); } else if (getRedefine()) { name = fromBackingFieldName(name); if (get) { addNotifyAccess(code, owner.getField(name)); code.next(); } else { // insert the set operations after the field mutation, but // first load the old value for use in the // StateManager.settingXXX method. loadManagedInstance(code, false); final FieldInstruction fFi = fi; code.getfield().setField( AccessController.doPrivileged(J2DoPrivHelper .getFieldInstructionFieldAction(fFi))); int val = code.getNextLocalsIndex(); code.xstore().setLocal(val).setType(fi.getFieldType()); // move past the putfield code.next(); addNotifyMutation(code, owner.getField(name), val, -1); } } else { code.next(); } code.calculateMaxLocals(); code.calculateMaxStack(); } } private void addNotifyAccess(Code code, FieldMetaData fmd) { // PCHelper.accessingField(this, ); code.aload().setThis(); code.constant().setValue(fmd.getIndex()); code.invokestatic().setMethod(RedefinitionHelper.class, "accessingField", void.class, new Class[] { Object.class, int.class }); } /** * This must be called after setting the value in the object. * * @param code * @param val the position in the local variable table where the * old value is stored * @param param the parameter position containing the new value, or * -1 if the new value is unavailable and should therefore be looked * up. * @throws NoSuchMethodException */ private void addNotifyMutation(Code code, FieldMetaData fmd, int val, int param) throws NoSuchMethodException { // PCHelper.settingField(this, , old, new); code.aload().setThis(); code.constant().setValue(fmd.getIndex()); Class type = fmd.getDeclaredType(); // we only have special signatures for primitives and Strings if (!type.isPrimitive() && type != String.class) type = Object.class; code.xload().setLocal(val).setType(type); if (param == -1) { loadManagedInstance(code, false); addGetManagedValueCode(code, fmd); } else { code.xload().setParam(param).setType(type); } code.invokestatic().setMethod(RedefinitionHelper.class, "settingField", void.class, new Class[] { Object.class, int.class, type, type }); } /** * Return true if the given instruction accesses a field that is a backing * field of another property in this property-access class. */ private boolean isBackingFieldOfAnotherProperty(String name, Code code) { String methName = code.getMethod().getName(); return !"".equals(methName) && _backingFields != null && !name.equals(_backingFields.get(methName)) && _backingFields.containsValue(name); } /** * Helper method to return the declaring PersistenceCapable class of * the given field. * * @param fieldName the name of the field * @param owner the nominal owner of the field * @return the metadata for the PersistenceCapable type that * declares the field (and therefore has the static method), or null if none */ private ClassMetaData getPersistenceCapableOwner(String fieldName, Class owner) { // find the actual ancestor class that declares the field, then // check if the class is persistent, and if the field is managed Field f = Reflection.findField(owner, fieldName, false); if (f == null) return null; // managed interface if (_meta != null && _meta.getDescribedType().isInterface()) return _meta; return _repos.getMetaData(f.getDeclaringClass(), null, false); } /** * Adds all synthetic methods to the bytecode by delegating to * the various addXXXMethods () functions in this class. Includes * all static field access methods. * Note that the 'stock' methods like pcIsTransactional, * pcFetchObjectId, etc are defined only in the * least-derived PersistenceCapable type. */ private void addPCMethods() throws NoSuchMethodException { addClearFieldsMethod(); addNewInstanceMethod(true); addNewInstanceMethod(false); addManagedFieldCountMethod(); addReplaceFieldsMethods(); addProvideFieldsMethods(); addCopyFieldsMethod(); if (_meta.getPCSuperclass() == null || getCreateSubclass()) { addStockMethods(); addGetVersionMethod(); addReplaceStateManagerMethod(); if (_meta.getIdentityType() != ClassMetaData.ID_APPLICATION) addNoOpApplicationIdentityMethods(); } // add the app id methods to each subclass rather // than just the superclass, since it is possible to have // a subclass with an app id hierarchy that matches the // persistent class inheritance hierarchy if (_meta.getIdentityType() == ClassMetaData.ID_APPLICATION && (_meta.getPCSuperclass() == null || getCreateSubclass() || _meta.getObjectIdType() != _meta.getPCSuperclassMetaData().getObjectIdType())) { addCopyKeyFieldsToObjectIdMethod(true); addCopyKeyFieldsToObjectIdMethod(false); addCopyKeyFieldsFromObjectIdMethod(true); addCopyKeyFieldsFromObjectIdMethod(false); if (_meta.hasAbstractPKField() == true) { addGetIDOwningClass(); } if (_meta.isEmbeddedOnly() && _meta.getIdentityType() == ClassMetaData.ID_APPLICATION) { _log.error(_loc.get("ID-field-in-embeddable-unsupported", _meta.toString())); } addNewObjectIdInstanceMethod(true); addNewObjectIdInstanceMethod(false); } else if (_meta.hasPKFieldsFromAbstractClass()){ addGetIDOwningClass(); } } /** * Add a method to clear all persistent fields; we'll call this from * the new instance method to ensure that unloaded fields have * default values. */ private void addClearFieldsMethod() throws NoSuchMethodException { // protected void pcClearFields () BCMethod method = _pc.declareMethod(PRE + "ClearFields", void.class, null); method.makeProtected(); Code code = method.getCode(true); // super.pcClearFields () if (_meta.getPCSuperclass() != null && !getCreateSubclass()) { code.aload().setThis(); code.invokespecial().setMethod(getType(_meta. getPCSuperclassMetaData()), PRE + "ClearFields", void.class, null); } FieldMetaData[] fmds = _meta.getDeclaredFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].getManagement() != FieldMetaData.MANAGE_PERSISTENT) continue; loadManagedInstance(code, false); switch (fmds[i].getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: case JavaTypes.BYTE: case JavaTypes.CHAR: case JavaTypes.INT: case JavaTypes.SHORT: code.constant().setValue(0); break; case JavaTypes.DOUBLE: code.constant().setValue(0D); break; case JavaTypes.FLOAT: code.constant().setValue(0F); break; case JavaTypes.LONG: code.constant().setValue(0L); break; default: code.constant().setNull(); break; } addSetManagedValueCode(code, fmds[i]); } code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds the pcNewInstance method to the bytecode. * These methods are used by the impl helper to create new * managed instances efficiently without reflection. * * @param oid set to true to mimic the method version that takes * an oid value as well as a state manager */ private void addNewInstanceMethod(boolean oid) { // public PersistenceCapable pcNewInstance (...) Class[] args = (oid) ? new Class[]{ SMTYPE, Object.class, boolean.class } : new Class[]{ SMTYPE, boolean.class }; BCMethod method = _pc.declareMethod(PRE + "NewInstance", PCTYPE, args); Code code = method.getCode(true); // if the type is abstract, throw a UserException if (_pc.isAbstract()) { throwException(code, USEREXCEP); code.calculateMaxStack(); code.calculateMaxLocals(); return; } // XXX pc = new XXX (); code.anew().setType(_pc); code.dup(); code.invokespecial().setMethod("", void.class, null); int inst = code.getNextLocalsIndex(); code.astore().setLocal(inst); // if (clear) // pc.pcClearFields (); code.iload().setParam((oid) ? 2 : 1); JumpInstruction noclear = code.ifeq(); code.aload().setLocal(inst); code.invokevirtual().setMethod(PRE + "ClearFields", void.class, null); // pc.pcStateManager = sm; noclear.setTarget(code.aload().setLocal(inst)); code.aload().setParam(0); code.putfield().setField(SM, SMTYPE); // copy key fields from oid if (oid) { code.aload().setLocal(inst); code.aload().setParam(1); code.invokevirtual().setMethod(PRE + "CopyKeyFieldsFromObjectId", void.class, new Class[]{ Object.class }); } // return pc; code.aload().setLocal(inst); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds the protected static int pcGetManagedFieldCount () * method to the bytecode, returning the inherited field count added * to the number of managed fields in the current PersistenceCapable class. */ private void addManagedFieldCountMethod() { // protected static int pcGetManagedFieldCount () BCMethod method = _pc.declareMethod(PRE + "GetManagedFieldCount", int.class, null); method.setStatic(true); method.makeProtected(); Code code = method.getCode(true); // return + pcInheritedFieldCount // awhite: the above should work, but I'm seeing a messed up situation // all of a sudden where when a subclass calls this method, it somehow // happens before is ever invoked, and so our // pcInheritedFieldCount field isn't initialized! so instead, // return + .pcGetManagedFieldCount () code.constant().setValue(_meta.getDeclaredFields().length); if (_meta.getPCSuperclass() != null) { Class superClass = getType(_meta.getPCSuperclassMetaData()); String superName = getCreateSubclass() ? PCEnhancer.toPCSubclassName(superClass) : superClass.getName(); code.invokestatic().setMethod(superName, PRE + "GetManagedFieldCount", int.class.getName(), null); code.iadd(); } code.ireturn(); code.calculateMaxStack(); } /** * Adds the {@link PersistenceCapable#pcProvideField} and * {@link PersistenceCapable#pcProvideFields} methods to the bytecode. */ private void addProvideFieldsMethods() throws NoSuchMethodException { // public void pcProvideField (int fieldNumber) BCMethod method = _pc.declareMethod(PRE + "ProvideField", void.class, new Class[]{ int.class }); Code code = method.getCode(true); // adds everything through the switch () int relLocal = beginSwitchMethod(PRE + "ProvideField", code); // if no fields in this inst, just throw exception FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields() : _meta.getDeclaredFields(); if (fmds.length == 0) throwException(code, IllegalArgumentException.class); else { // switch (val) code.iload().setLocal(relLocal); TableSwitchInstruction tabins = code.tableswitch(); tabins.setLow(0); tabins.setHigh(fmds.length - 1); // = pcStateManager.providedField // (this, fieldNumber); for (int i = 0; i < fmds.length; i++) { tabins.addTarget(loadManagedInstance(code, false)); code.getfield().setField(SM, SMTYPE); loadManagedInstance(code, false); code.iload().setParam(0); loadManagedInstance(code, false); addGetManagedValueCode(code, fmds[i]); code.invokeinterface().setMethod(getStateManagerMethod (fmds[i].getDeclaredType(), "provided", false, false)); code.vreturn(); } // default: throw new IllegalArgumentException () tabins.setDefaultTarget(throwException (code, IllegalArgumentException.class)); } code.calculateMaxStack(); code.calculateMaxLocals(); addMultipleFieldsMethodVersion(method); } /** * Adds the {@link PersistenceCapable#pcReplaceField} and * {@link PersistenceCapable#pcReplaceFields} methods to the bytecode. */ private void addReplaceFieldsMethods() throws NoSuchMethodException { // public void pcReplaceField (int fieldNumber) BCMethod method = _pc.declareMethod(PRE + "ReplaceField", void.class, new Class[]{ int.class }); Code code = method.getCode(true); // adds everything through the switch () int relLocal = beginSwitchMethod(PRE + "ReplaceField", code); // if no fields in this inst, just throw exception FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields() : _meta.getDeclaredFields(); if (fmds.length == 0) throwException(code, IllegalArgumentException.class); else { // switch (val) code.iload().setLocal(relLocal); TableSwitchInstruction tabins = code.tableswitch(); tabins.setLow(0); tabins.setHigh(fmds.length - 1); // = pcStateManager.replaceField // (this, fieldNumber); for (int i = 0; i < fmds.length; i++) { // for the addSetManagedValueCode call below. tabins.addTarget(loadManagedInstance(code, false, fmds[i])); loadManagedInstance(code, false, fmds[i]); code.getfield().setField(SM, SMTYPE); loadManagedInstance(code, false, fmds[i]); code.iload().setParam(0); code.invokeinterface().setMethod(getStateManagerMethod (fmds[i].getDeclaredType(), "replace", true, false)); if (!fmds[i].getDeclaredType().isPrimitive()) code.checkcast().setType(fmds[i].getDeclaredType()); addSetManagedValueCode(code, fmds[i]); if(_addVersionInitFlag){ if(fmds[i].isVersion()){ // If this case is setting the version field // pcVersionInit = true; loadManagedInstance(code, false); code.constant().setValue(1); putfield(code, null, VERSION_INIT_STR, boolean.class); } } code.vreturn(); } // default: throw new IllegalArgumentException () tabins.setDefaultTarget(throwException (code, IllegalArgumentException.class)); } code.calculateMaxStack(); code.calculateMaxLocals(); addMultipleFieldsMethodVersion(method); } /** * Adds the {@link PersistenceCapable#pcCopyFields} method to the bytecode. */ private void addCopyFieldsMethod() throws NoSuchMethodException { // public void pcCopyField (Object pc, int field) BCMethod method = _pc.declareMethod(PRE + "CopyField", void.class.getName(), new String[]{ _managedType.getName(), int.class.getName() }); method.makeProtected(); Code code = method.getCode(true); // adds everything through the switch () int relLocal = beginSwitchMethod(PRE + "CopyField", code); // if no fields in this inst, just throw exception FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields() : _meta.getDeclaredFields(); if (fmds.length == 0) throwException(code, IllegalArgumentException.class); else { // switch (val) code.iload().setLocal(relLocal); TableSwitchInstruction tabins = code.tableswitch(); tabins.setLow(0); tabins.setHigh(fmds.length - 1); for (int i = 0; i < fmds.length; i++) { // = other.; // or set (other.get); tabins.addTarget(loadManagedInstance(code, false, fmds[i])); code.aload().setParam(0); addGetManagedValueCode(code, fmds[i], false); addSetManagedValueCode(code, fmds[i]); // break; code.vreturn(); } // default: throw new IllegalArgumentException () tabins.setDefaultTarget(throwException (code, IllegalArgumentException.class)); } code.calculateMaxStack(); code.calculateMaxLocals(); addMultipleFieldsMethodVersion(method); } /** * Helper method to add the code common to the beginning of both the * pcReplaceField method and the pcProvideField method. This includes * calculating the relative field number of the desired field and calling * the superclass if necessary. * * @return the index in which the local variable holding the relative * field number is stored */ private int beginSwitchMethod(String name, Code code) { boolean copy = (PRE + "CopyField").equals(name); int fieldNumber = (copy) ? 1 : 0; int relLocal = code.getNextLocalsIndex(); if (getCreateSubclass()) { code.iload().setParam(fieldNumber); code.istore().setLocal(relLocal); return relLocal; } // int rel = fieldNumber - pcInheritedFieldCount code.iload().setParam(fieldNumber); code.getstatic().setField(INHERIT, int.class); code.isub(); code.istore().setLocal(relLocal); code.iload().setLocal(relLocal); // super: if (rel < 0) super.pcReplaceField (fieldNumber); return; // no super: if (rel < 0) throw new IllegalArgumentException (); JumpInstruction ifins = code.ifge(); if (_meta.getPCSuperclass() != null) { loadManagedInstance(code, false); String[] args; if (copy) { args = new String[]{ getType(_meta.getPCSuperclassMetaData()). getName(), int.class.getName() }; code.aload().setParam(0); } else args = new String[]{ int.class.getName() }; code.iload().setParam(fieldNumber); code.invokespecial().setMethod(getType(_meta. getPCSuperclassMetaData()).getName(), name, void.class.getName(), args); code.vreturn(); } else throwException(code, IllegalArgumentException.class); ifins.setTarget(code.nop()); return relLocal; } /** * This helper method, given the pcReplaceField or pcProvideField * method, adds the bytecode for the corresponding 'plural' version * of the method -- the version that takes an int[] of fields to * to access rather than a single field. The multiple fields version * simply loops through the provided indexes and delegates to the * singular version for each one. */ private void addMultipleFieldsMethodVersion(BCMethod single) { boolean copy = (PRE + "CopyField").equals(single.getName()); // public void s (int[] fields) Class[] args = (copy) ? new Class[]{ Object.class, int[].class } : new Class[]{ int[].class }; BCMethod method = _pc.declareMethod(single.getName() + "s", void.class, args); Code code = method.getCode(true); int fieldNumbers = 0; int inst = 0; if (copy) { fieldNumbers = 1; if (getCreateSubclass()) { // get the managed instance into the local variable table code.aload().setParam(0); code.invokestatic().setMethod(ImplHelper.class, "getManagedInstance", Object.class, new Class[] { Object.class }); code.checkcast().setType(_managedType); inst = code.getNextLocalsIndex(); code.astore().setLocal(inst); // there might be a difference between the classes of 'this' // vs 'other' in this context; use the PC methods to get the SM code.aload().setParam(0); code.aload().setThis(); code.getfield().setField(SM, SMTYPE); code.invokestatic().setMethod(ImplHelper.class, "toPersistenceCapable", PersistenceCapable.class, new Class[] { Object.class, Object.class }); code.invokeinterface().setMethod(PersistenceCapable.class, "pcGetStateManager", StateManager.class, null); } else { // XXX other = (XXX) pc; code.aload().setParam(0); code.checkcast().setType(_pc); inst = code.getNextLocalsIndex(); code.astore().setLocal(inst); // access the other's sm field directly code.aload().setLocal(inst); code.getfield().setField(SM, SMTYPE); } // if (other.pcStateManager != pcStateManager) // throw new IllegalArgumentException loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); JumpInstruction ifins = code.ifacmpeq(); throwException(code, IllegalArgumentException.class); ifins.setTarget(code.nop()); // if (pcStateManager == null) // throw new IllegalStateException loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); ifins = code.ifnonnull(); throwException(code, IllegalStateException.class); ifins.setTarget(code.nop()); } // for (int i = 0; code.constant().setValue(0); int idx = code.getNextLocalsIndex(); code.istore().setLocal(idx); JumpInstruction testins = code.go2(); // (fields[i]); Instruction bodyins = loadManagedInstance(code, false); if (copy) code.aload().setLocal(inst); code.aload().setParam(fieldNumbers); code.iload().setLocal(idx); code.iaload(); code.invokevirtual().setMethod(single); // i++; code.iinc().setIncrement(1).setLocal(idx); // i < fields.length testins.setTarget(code.iload().setLocal(idx)); code.aload().setParam(fieldNumbers); code.arraylength(); code.ificmplt().setTarget(bodyins); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds the 'stock' methods to the bytecode; these include methods * like {@link PersistenceCapable#pcFetchObjectId} * and {@link PersistenceCapable#pcIsTransactional}. */ private void addStockMethods() throws NoSuchMethodException { try { // pcGetGenericContext translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "get" + CONTEXTNAME, (Class[]) null)), false); // pcFetchObjectId translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "fetchObjectId", (Class[]) null)), false); // pcIsDeleted translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "isDeleted", (Class[]) null)), false); // pcIsDirty translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "isDirty", (Class[]) null)), true); // pcIsNew translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "isNew", (Class[]) null)), false); // pcIsPersistent translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "isPersistent", (Class[]) null)), false); // pcIsTransactional translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "isTransactional", (Class[]) null)), false); // pcSerializing translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "serializing", (Class[]) null)), false); // pcDirty translateFromStateManagerMethod( AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction( SMTYPE, "dirty", new Class[]{ String.class })), false); // pcGetStateManager BCMethod meth = _pc.declareMethod(PRE + "GetStateManager", StateManager.class, null); Code code = meth.getCode(true); loadManagedInstance(code, false); code.getfield().setField(SM, StateManager.class); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } catch (PrivilegedActionException pae) { throw (NoSuchMethodException) pae.getException(); } } /** * Helper method to add a stock method to the bytecode. Each * stock method simply delegates to a corresponding StateManager method. * Given the StateManager method, then, this function translates it into * the wrapper method that should be added to the bytecode. */ private void translateFromStateManagerMethod(Method m, boolean isDirtyCheckMethod) { // form the name of the method by prepending 'pc' to the sm method String name = PRE + StringUtils.capitalize(m.getName()); Class[] params = m.getParameterTypes(); Class returnType = m.getReturnType(); // add the method to the pc BCMethod method = _pc.declareMethod(name, returnType, params); Code code = method.getCode(true); // if (pcStateManager == null) return ; loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); JumpInstruction ifins = code.ifnonnull(); if (returnType.equals(boolean.class)) code.constant().setValue(false); else if (!returnType.equals(void.class)) code.constant().setNull(); code.xreturn().setType(returnType); // if this is the dirty-check method and we're subclassing but not // redefining, hook into PCHelper to do the dirty check if (isDirtyCheckMethod && !getRedefine()) { // RedefinitionHelper.dirtyCheck(sm); ifins.setTarget(loadManagedInstance(code, false)); code.getfield().setField(SM, SMTYPE); code.dup(); // for the return statement below code.invokestatic().setMethod(RedefinitionHelper.class, "dirtyCheck", void.class, new Class[] { SMTYPE }); } else { ifins.setTarget(loadManagedInstance(code, false)); code.getfield().setField(SM, SMTYPE); } // return pcStateManager. (); // managed instance loaded above in if-else block for (int i = 0; i < params.length; i++) code.xload().setParam(i); code.invokeinterface().setMethod(m); code.xreturn().setType(returnType); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds the {@link PersistenceCapable#pcGetVersion} method to the bytecode. */ private void addGetVersionMethod() throws NoSuchMethodException { BCMethod method = _pc.declareMethod(PRE + "GetVersion", Object.class, null); Code code = method.getCode(true); // if (pcStateManager == null) loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); JumpInstruction ifins = code.ifnonnull(); FieldMetaData versionField = _meta.getVersionField(); if (versionField == null) code.constant().setNull(); // return null; else { // return ; Class wrapper = toPrimitiveWrapper(versionField); if (wrapper != versionField.getDeclaredType()) { code.anew().setType(wrapper); code.dup(); } loadManagedInstance(code, false); addGetManagedValueCode(code, versionField); if (wrapper != versionField.getDeclaredType()) code.invokespecial().setMethod(wrapper, "", void.class, new Class[]{ versionField.getDeclaredType() }); } code.areturn(); // return pcStateManager.getVersion (); ifins.setTarget(loadManagedInstance(code, false)); code.getfield().setField(SM, SMTYPE); code.invokeinterface().setMethod(SMTYPE, "getVersion", Object.class, null); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Return the version field type as a primitive wrapper, or null if * the version field is not primitive. */ private Class toPrimitiveWrapper(FieldMetaData fmd) { switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: return Boolean.class; case JavaTypes.BYTE: return Byte.class; case JavaTypes.CHAR: return Character.class; case JavaTypes.DOUBLE: return Double.class; case JavaTypes.FLOAT: return Float.class; case JavaTypes.INT: return Integer.class; case JavaTypes.LONG: return Long.class; case JavaTypes.SHORT: return Short.class; } return fmd.getDeclaredType(); } /** * Adds the {@link PersistenceCapable#pcReplaceStateManager} * method to the bytecode. */ private void addReplaceStateManagerMethod() { // public void pcReplaceStateManager (StateManager sm) BCMethod method = _pc.declareMethod(PRE + "ReplaceStateManager", void.class, new Class[]{ SMTYPE }); method.getExceptions(true).addException(SecurityException.class); Code code = method.getCode(true); // if (pcStateManager != null) // pcStateManager = pcStateManager.replaceStateManager(sm); loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); JumpInstruction ifins = code.ifnull(); loadManagedInstance(code, false); loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); code.aload().setParam(0); code.invokeinterface().setMethod(SMTYPE, "replaceStateManager", SMTYPE, new Class[]{ SMTYPE }); code.putfield().setField(SM, SMTYPE); code.vreturn(); // SecurityManager sec = System.getSecurityManager (); // if (sec != null) // sec.checkPermission (Permission.SET_STATE_MANAGER); ifins.setTarget(code.invokestatic().setMethod(System.class, "getSecurityManager", SecurityManager.class, null)); // pcStateManager = sm; ifins.setTarget(loadManagedInstance(code, false)); code.aload().setParam(0); code.putfield().setField(SM, SMTYPE); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Creates the PersistenceCapable methods dealing with application * identity and gives them no-op implementations. */ private void addNoOpApplicationIdentityMethods() { // public void pcCopyKeyFieldsToObjectId (ObjectIdFieldSupplier fs, // Object oid) BCMethod method = _pc.declareMethod(PRE + "CopyKeyFieldsToObjectId", void.class, new Class[]{ OIDFSTYPE, Object.class }); Code code = method.getCode(true); code.vreturn(); code.calculateMaxLocals(); // public void pcCopyKeyFieldsToObjectId (Object oid) method = _pc.declareMethod(PRE + "CopyKeyFieldsToObjectId", void.class, new Class[]{ Object.class }); code = method.getCode(true); code.vreturn(); code.calculateMaxLocals(); // public void pcCopyKeyFieldsFromObjectId (ObjectIdFieldConsumer fc, // Object oid) method = _pc.declareMethod(PRE + "CopyKeyFieldsFromObjectId", void.class, new Class[]{ OIDFCTYPE, Object.class }); code = method.getCode(true); code.vreturn(); code.calculateMaxLocals(); // public void pcCopyKeyFieldsFromObjectId (Object oid) method = _pc.declareMethod(PRE + "CopyKeyFieldsFromObjectId", void.class, new Class[]{ Object.class }); code = method.getCode(true); code.vreturn(); code.calculateMaxLocals(); // public Object pcNewObjectIdInstance () method = _pc.declareMethod(PRE + "NewObjectIdInstance", Object.class, null); code = method.getCode(true); code.constant().setNull(); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // public Object pcNewObjectIdInstance (Object obj) method = _pc.declareMethod(PRE + "NewObjectIdInstance", Object.class, new Class[]{ Object.class }); code = method.getCode(true); code.constant().setNull(); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds the pcCopyKeyFieldsToObjectId methods * to classes using application identity. */ private void addCopyKeyFieldsToObjectIdMethod(boolean fieldManager) throws NoSuchMethodException { // public void pcCopyKeyFieldsToObjectId (ObjectIdFieldSupplier fs, // Object oid) String[] args = (fieldManager) ? new String[]{ OIDFSTYPE.getName(), Object.class.getName() } : new String[]{ Object.class.getName() }; BCMethod method = _pc.declareMethod(PRE + "CopyKeyFieldsToObjectId", void.class.getName(), args); Code code = method.getCode(true); // single field identity always throws exception if (_meta.isOpenJPAIdentity()) { throwException(code, INTERNEXCEP); code.calculateMaxStack(); code.calculateMaxLocals(); return; } // call superclass method if (_meta.getPCSuperclass() != null && !getCreateSubclass()) { loadManagedInstance(code, false); for (int i = 0; i < args.length; i++) code.aload().setParam(i); code.invokespecial().setMethod(getType(_meta. getPCSuperclassMetaData()).getName(), PRE + "CopyKeyFieldsToObjectId", void.class.getName(), args); } // Object id = oid; if (fieldManager) code.aload().setParam(1); else code.aload().setParam(0); if (_meta.isObjectIdTypeShared()) { // oid = ((ObjectId) id).getId (); code.checkcast().setType(ObjectId.class); code.invokevirtual().setMethod(ObjectId.class, "getId", Object.class, null); } // id = () oid; int id = code.getNextLocalsIndex(); Class oidType = _meta.getObjectIdType(); code.checkcast().setType(oidType); code.astore().setLocal(id); // int inherited = pcInheritedFieldCount; int inherited = 0; if (fieldManager) { code.getstatic().setField(INHERIT, int.class); inherited = code.getNextLocalsIndex(); code.istore().setLocal(inherited); } // id. = fs.fetchField (); or... // id. = pc.; FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields() : _meta.getDeclaredFields(); Class type; String name; Field field; Method setter; boolean reflect; // If optimizeIdCopy is enabled and not a field manager method, try to // optimize the copyTo by using a public constructor instead of reflection if (_optimizeIdCopy) { ArrayList pkfields = optimizeIdCopy(oidType, fmds); if (pkfields != null) { // search for a constructor on the IdClass that can be used // to construct the IdClass int parmOrder[] = getIdClassConstructorParmOrder(oidType, pkfields, fmds); if (parmOrder != null) { // If using a field manager, values must be loaded into locals so they can be properly ordered // as constructor parameters. int[] localIndexes = new int[fmds.length]; if (fieldManager) { for (int k = 0; k < fmds.length; k++) { if (!fmds[k].isPrimaryKey()) continue; code.aload().setParam(0); code.constant().setValue(k); code.iload().setLocal(inherited); code.iadd(); code.invokeinterface().setMethod(getFieldSupplierMethod(fmds[k].getObjectIdFieldType())); localIndexes[k] = code.getNextLocalsIndex(); storeLocalValue(code, localIndexes[k], fmds[k].getObjectIdFieldTypeCode()); } } // found a matching constructor. parm array is constructor parm order code.anew().setType(oidType); code.dup(); // build the parm list in order Class[] clsArgs = new Class[parmOrder.length]; for (int i = 0; i < clsArgs.length; i++) { int parmIndex = parmOrder[i]; clsArgs[i] = fmds[parmIndex].getObjectIdFieldType(); if (!fieldManager) { loadManagedInstance(code, false); addGetManagedValueCode(code, fmds[parmIndex]); } else { // Load constructor parameters in appropriate order loadLocalValue(code, localIndexes[parmIndex], fmds[parmIndex].getObjectIdFieldTypeCode()); if (fmds[parmIndex].getObjectIdFieldTypeCode() == JavaTypes.OBJECT && !fmds[parmIndex].getDeclaredType().isEnum()) { code.checkcast().setType(ObjectId.class); code.invokevirtual().setMethod(ObjectId.class, "getId", Object.class, null); } // if the type of this field meta data is // non-primitive and non-string, be sure to cast // to the appropriate type. if (!clsArgs[i].isPrimitive() && !clsArgs[i].getName().equals(String.class.getName())) code.checkcast().setType(clsArgs[i]); } } // invoke the public constructor to create a new local id code.invokespecial().setMethod(oidType, "", void.class, clsArgs); int ret = code.getNextLocalsIndex(); code.astore().setLocal(ret); // swap out the app id with the new one code.aload().setLocal( fieldManager ? 2 : 1); code.checkcast().setType(ObjectId.class); code.aload().setLocal(ret); code.invokestatic().setMethod(ApplicationIds.class, "setAppId", void.class, new Class[] { ObjectId.class, Object.class }); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); return; } } } for (int i = 0; i < fmds.length; i++) { if (!fmds[i].isPrimaryKey()) continue; code.aload().setLocal(id); name = fmds[i].getName(); type = fmds[i].getObjectIdFieldType(); if (isFieldAccess(fmds[i])) { setter = null; field = Reflection.findField(oidType, name, true); reflect = !Modifier.isPublic(field.getModifiers()); if (reflect) { code.classconstant().setClass(oidType); code.constant().setValue(name); code.constant().setValue(true); code.invokestatic().setMethod(Reflection.class, "findField", Field.class, new Class[] { Class.class, String.class, boolean.class }); } } else { field = null; setter = Reflection.findSetter(oidType, name, type, true); reflect = !Modifier.isPublic(setter.getModifiers()); if (reflect) { code.classconstant().setClass(oidType); code.constant().setValue(name); code.classconstant().setClass(type); code.constant().setValue(true); code.invokestatic().setMethod(Reflection.class, "findSetter", Method.class, new Class[] { Class.class, String.class, Class.class, boolean.class }); } } if (fieldManager) { code.aload().setParam(0); code.constant().setValue(i); code.iload().setLocal(inherited); code.iadd(); code.invokeinterface().setMethod (getFieldSupplierMethod(type)); if (fmds[i].getObjectIdFieldTypeCode() == JavaTypes.OBJECT && !fmds[i].getDeclaredType().isEnum()) { code.checkcast().setType(ObjectId.class); code.invokevirtual().setMethod(ObjectId.class, "getId", Object.class, null); } // if the type of this field meta data is // non-primitive and non-string, be sure to cast // to the appropriate type. if (!reflect && !type.isPrimitive() && !type.getName().equals(String.class.getName())) code.checkcast().setType(type); } else { loadManagedInstance(code, false); addGetManagedValueCode(code, fmds[i]); // get id/pk from pc instance if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) addExtractObjectIdFieldValueCode(code, fmds[i]); } if (reflect && field != null) { code.invokestatic().setMethod(Reflection.class, "set", void.class, new Class[] { Object.class, Field.class, (type.isPrimitive()) ? type : Object.class }); } else if (reflect) { code.invokestatic().setMethod(Reflection.class, "set", void.class, new Class[] { Object.class, Method.class, (type.isPrimitive()) ? type : Object.class }); } else if (field != null) code.putfield().setField(field); else code.invokevirtual().setMethod(setter); } code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds the appropriate load method for the given type and local * index. */ private void loadLocalValue(Code code, int locidx, int typeCode) { switch (typeCode) { case JavaTypes.CHAR: case JavaTypes.BYTE: case JavaTypes.SHORT: case JavaTypes.INT: code.iload().setLocal(locidx); break; case JavaTypes.DOUBLE: code.dload().setLocal(locidx); break; case JavaTypes.FLOAT: code.fload().setLocal(locidx); break; case JavaTypes.LONG: code.lload().setLocal(locidx); break; default: code.aload().setLocal(locidx); break; } } /** * Adds the appropriate store method for the given type and local * index. */ private void storeLocalValue(Code code, int locidx, int typeCode) { switch (typeCode) { case JavaTypes.CHAR: case JavaTypes.BYTE: case JavaTypes.SHORT: case JavaTypes.INT: code.istore().setLocal(locidx); break; case JavaTypes.DOUBLE: code.dstore().setLocal(locidx); break; case JavaTypes.FLOAT: code.fstore().setLocal(locidx); break; case JavaTypes.LONG: code.lstore().setLocal(locidx); break; default: code.astore().setLocal(locidx); break; } } /** * Add code to extract the id of the given primary key relation field for * setting into an objectid instance. */ private void addExtractObjectIdFieldValueCode(Code code, FieldMetaData pk) { // if (val != null) // val = ((PersistenceCapable) val).pcFetchObjectId(); int pc = code.getNextLocalsIndex(); code.astore().setLocal(pc); code.aload().setLocal(pc); JumpInstruction ifnull1 = code.ifnull(); code.aload().setLocal(pc); code.checkcast().setType(PersistenceCapable.class); if (!pk.getTypeMetaData().isOpenJPAIdentity()) code.invokeinterface().setMethod(PersistenceCapable.class, PRE + "FetchObjectId", Object.class, null); else code.invokeinterface().setMethod(PersistenceCapable.class, PRE + "NewObjectIdInstance", Object.class, null); int oid = code.getNextLocalsIndex(); code.astore().setLocal(oid); code.aload().setLocal(oid); JumpInstruction ifnull2 = code.ifnull(); // for datastore / single-field identity: // if (val != null) // val = ((OpenJPAId) val).getId(); ClassMetaData pkmeta = pk.getDeclaredTypeMetaData(); int pkcode = pk.getObjectIdFieldTypeCode(); Class pktype = pk.getObjectIdFieldType(); if (pkmeta.getIdentityType() == ClassMetaData.ID_DATASTORE && pkcode == JavaTypes.LONG) { code.aload().setLocal(oid); code.checkcast().setType(Id.class); code.invokevirtual().setMethod(Id.class, "getId", long.class, null); } else if (pkmeta.getIdentityType() == ClassMetaData.ID_DATASTORE) { code.aload().setLocal(oid); } else if (pkmeta.isOpenJPAIdentity()) { switch (pkcode) { case JavaTypes.BYTE_OBJ: code.anew().setType(Byte.class); code.dup(); // no break case JavaTypes.BYTE: code.aload().setLocal(oid); code.checkcast().setType(ByteId.class); code.invokevirtual().setMethod(ByteId.class, "getId", byte.class, null); if (pkcode == JavaTypes.BYTE_OBJ) code.invokespecial().setMethod(Byte.class, "", void.class, new Class[] {byte.class}); break; case JavaTypes.CHAR_OBJ: code.anew().setType(Character.class); code.dup(); // no break case JavaTypes.CHAR: code.aload().setLocal(oid); code.checkcast().setType(CharId.class); code.invokevirtual().setMethod(CharId.class, "getId", char.class, null); if (pkcode == JavaTypes.CHAR_OBJ) code.invokespecial().setMethod(Character.class, "", void.class, new Class[] {char.class}); break; case JavaTypes.DOUBLE_OBJ: code.anew().setType(Double.class); code.dup(); // no break case JavaTypes.DOUBLE: code.aload().setLocal(oid); code.checkcast().setType(DoubleId.class); code.invokevirtual().setMethod(DoubleId.class, "getId", double.class, null); if (pkcode == JavaTypes.DOUBLE_OBJ) code.invokespecial().setMethod(Double.class, "", void.class, new Class[]{double.class}); break; case JavaTypes.FLOAT_OBJ: code.anew().setType(Float.class); code.dup(); // no break case JavaTypes.FLOAT: code.aload().setLocal(oid); code.checkcast().setType(FloatId.class); code.invokevirtual().setMethod(FloatId.class, "getId", float.class, null); if (pkcode == JavaTypes.FLOAT_OBJ) code.invokespecial().setMethod(Float.class, "", void.class, new Class[]{float.class}); break; case JavaTypes.INT_OBJ: code.anew().setType(Integer.class); code.dup(); // no break case JavaTypes.INT: code.aload().setLocal(oid); code.checkcast().setType(IntId.class); code.invokevirtual().setMethod(IntId.class, "getId", int.class, null); if (pkcode == JavaTypes.INT_OBJ) code.invokespecial().setMethod(Integer.class, "", void.class, new Class[] {int.class}); break; case JavaTypes.LONG_OBJ: code.anew().setType(Long.class); code.dup(); // no break case JavaTypes.LONG: code.aload().setLocal(oid); code.checkcast().setType(LongId.class); code.invokevirtual().setMethod(LongId.class, "getId", long.class, null); if (pkcode == JavaTypes.LONG_OBJ) code.invokespecial().setMethod(Long.class, "", void.class, new Class[] {long.class}); break; case JavaTypes.SHORT_OBJ: code.anew().setType(Short.class); code.dup(); // no break case JavaTypes.SHORT: code.aload().setLocal(oid); code.checkcast().setType(ShortId.class); code.invokevirtual().setMethod(ShortId.class, "getId", short.class, null); if (pkcode == JavaTypes.SHORT_OBJ) code.invokespecial().setMethod(Short.class, "", void.class, new Class[]{short.class}); break; case JavaTypes.DATE: code.aload().setLocal(oid); code.checkcast().setType(DateId.class); code.invokevirtual().setMethod(DateId.class, "getId", Date.class, null); if (pktype != Date.class) { // java.sql.Date.class code.checkcast().setType(pktype); } break; case JavaTypes.STRING: code.aload().setLocal(oid); code.checkcast().setType(StringId.class); code.invokevirtual().setMethod(StringId.class, "getId", String.class, null); break; case JavaTypes.BIGDECIMAL: code.aload().setLocal(oid); code.checkcast().setType(BigDecimalId.class); code.invokevirtual().setMethod(BigDecimalId.class, "getId", BigDecimal.class, null); break; case JavaTypes.BIGINTEGER: code.aload().setLocal(oid); code.checkcast().setType(BigIntegerId.class); code.invokevirtual().setMethod(BigIntegerId.class, "getId", BigInteger.class, null); break; default: code.aload().setLocal(oid); code.checkcast().setType(ObjectId.class); code.invokevirtual().setMethod(ObjectId.class, "getId", Object.class, null); } } else if (pkmeta.getObjectIdType() != null) { code.aload().setLocal(oid); if (pkcode == JavaTypes.OBJECT) { code.checkcast().setType(ObjectId.class); code.invokevirtual().setMethod(ObjectId.class, "getId", Object.class, null); } code.checkcast().setType(pktype); } else code.aload().setLocal(oid); JumpInstruction go2 = code.go2(); // if (val == null) // val = ; Instruction def; switch (pkcode) { case JavaTypes.BOOLEAN: def = code.constant().setValue(false); break; case JavaTypes.BYTE: def = code.constant().setValue((byte) 0); break; case JavaTypes.CHAR: def = code.constant().setValue((char) 0); break; case JavaTypes.DOUBLE: def = code.constant().setValue(0D); break; case JavaTypes.FLOAT: def = code.constant().setValue(0F); break; case JavaTypes.INT: def = code.constant().setValue(0); break; case JavaTypes.LONG: def = code.constant().setValue(0L); break; case JavaTypes.SHORT: def = code.constant().setValue((short) 0); break; default: def = code.constant().setNull(); } ifnull1.setTarget(def); ifnull2.setTarget(def); go2.setTarget(code.nop()); } /** * Adds the pcCopyKeyFieldsFromObjectId methods * to classes using application identity. */ private void addCopyKeyFieldsFromObjectIdMethod(boolean fieldManager) throws NoSuchMethodException { // public void pcCopyKeyFieldsFromObjectId (ObjectIdFieldConsumer fc, // Object oid) String[] args = (fieldManager) ? new String[]{ OIDFCTYPE.getName(), Object.class.getName() } : new String[]{ Object.class.getName() }; BCMethod method = _pc.declareMethod(PRE + "CopyKeyFieldsFromObjectId", void.class.getName(), args); Code code = method.getCode(true); // call superclass method if (_meta.getPCSuperclass() != null && !getCreateSubclass()) { loadManagedInstance(code, false); for (int i = 0; i < args.length; i++) code.aload().setParam(i); code.invokespecial().setMethod(getType(_meta. getPCSuperclassMetaData()).getName(), PRE + "CopyKeyFieldsFromObjectId", void.class.getName(), args); } if (fieldManager) code.aload().setParam(1); else code.aload().setParam(0); if (!_meta.isOpenJPAIdentity() && _meta.isObjectIdTypeShared()) { // oid = ((ObjectId) id).getId (); code.checkcast().setType(ObjectId.class); code.invokevirtual().setMethod(ObjectId.class, "getId", Object.class, null); } // cast = () oid; int id = code.getNextLocalsIndex(); Class oidType = _meta.getObjectIdType(); code.checkcast().setType(oidType); code.astore().setLocal(id); // fs.storeField (, id.); or... // this. = id. // or for single field identity: id.getId () FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields() : _meta.getDeclaredFields(); String name; Class type; Class unwrapped; Field field; Method getter; for (int i = 0; i < fmds.length; i++) { if (!fmds[i].isPrimaryKey()) continue; name = fmds[i].getName(); type = fmds[i].getObjectIdFieldType(); if (!fieldManager && fmds[i].getDeclaredTypeCode() == JavaTypes.PC) { // if (sm == null) return; loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); JumpInstruction ifins = code.ifnonnull(); code.vreturn(); // sm.getPCPrimaryKey(oid, i + pcInheritedFieldCount); ifins.setTarget(loadManagedInstance(code, false)); code.dup(); // leave orig on stack to set value into code.getfield().setField(SM, SMTYPE); code.aload().setLocal(id); code.constant().setValue(i); code.getstatic().setField(INHERIT, int.class); code.iadd(); code.invokeinterface().setMethod(StateManager.class, "getPCPrimaryKey", Object.class, new Class[] { Object.class, int.class }); code.checkcast().setType(fmds[i].getDeclaredType()); } else { unwrapped = (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) ? type : unwrapSingleFieldIdentity(fmds[i]); if (fieldManager) { code.aload().setParam(0); code.constant().setValue(i); code.getstatic().setField(INHERIT, int.class); code.iadd(); } else loadManagedInstance(code, false); if (unwrapped != type) { code.anew().setType(type); code.dup(); } code.aload().setLocal(id); if (_meta.isOpenJPAIdentity()) { if (oidType == ObjectId.class) { code.invokevirtual().setMethod(oidType, "getId", Object.class, null); if (!fieldManager && type != Object.class) code.checkcast().setType(fmds[i].getDeclaredType()); } else if (oidType == DateId.class) { code.invokevirtual().setMethod(oidType, "getId", Date.class, null); if (!fieldManager && type != Date.class) code.checkcast().setType(fmds[i].getDeclaredType()); } else { code.invokevirtual().setMethod(oidType, "getId", unwrapped, null); if (unwrapped != type) code.invokespecial().setMethod(type, "", void.class, new Class[]{ unwrapped }); } } else if (isFieldAccess(fmds[i])) { field = Reflection.findField(oidType, name, true); if (Modifier.isPublic(field.getModifiers())) code.getfield().setField(field); else { boolean usedFastOid = false; if (_optimizeIdCopy) { // If fastOids, ignore access type and try to use a public getter getter = Reflection.findGetter(oidType, name, false); if (getter != null && Modifier.isPublic(getter.getModifiers())) { usedFastOid = true; code.invokevirtual().setMethod(getter); } } if (!usedFastOid) { // Reflection.getXXX(oid, Reflection.findField(...)); code.classconstant().setClass(oidType); code.constant().setValue(name); code.constant().setValue(true); code.invokestatic().setMethod(Reflection.class, "findField", Field.class, new Class[] { Class.class, String.class, boolean.class }); code.invokestatic().setMethod (getReflectionGetterMethod(type, Field.class)); if (!type.isPrimitive() && type != Object.class) code.checkcast().setType(type); } } } else { getter = Reflection.findGetter(oidType, name, true); if (Modifier.isPublic(getter.getModifiers())) code.invokevirtual().setMethod(getter); else { // Reflection.getXXX(oid, Reflection.findGetter(...)); code.classconstant().setClass(oidType); code.constant().setValue(name); code.constant().setValue(true); code.invokestatic().setMethod(Reflection.class, "findGetter", Method.class, new Class[] { Class.class, String.class, boolean.class }); code.invokestatic().setMethod (getReflectionGetterMethod(type, Method.class)); if (!type.isPrimitive() && type != Object.class) code.checkcast().setType(type); } } } if (fieldManager) code.invokeinterface().setMethod(getFieldConsumerMethod(type)); else addSetManagedValueCode(code, fmds[i]); } code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Return if the class uses the Class/String constructor * instead of just String. */ private Boolean usesClassStringIdConstructor() { if (_meta.getIdentityType() != ClassMetaData.ID_APPLICATION) return Boolean.FALSE; if (_meta.isOpenJPAIdentity()) { if (_meta.getObjectIdType() == ObjectId.class) return null; return Boolean.TRUE; } Class oidType = _meta.getObjectIdType(); try { oidType.getConstructor(new Class[]{ Class.class, String.class }); return Boolean.TRUE; } catch (Throwable t) { } try { oidType.getConstructor(new Class[]{ String.class }); return Boolean.FALSE; } catch (Throwable t) { } return null; } /** * If the given field is a wrapper-type single field identity primary key, * return its corresponding primitive class. Else return the field type. */ private Class unwrapSingleFieldIdentity(FieldMetaData fmd) { if (!fmd.getDefiningMetaData().isOpenJPAIdentity()) return fmd.getDeclaredType(); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BYTE_OBJ: return byte.class; case JavaTypes.CHAR_OBJ: return char.class; case JavaTypes.DOUBLE_OBJ: return double.class; case JavaTypes.FLOAT_OBJ: return float.class; case JavaTypes.INT_OBJ: return int.class; case JavaTypes.SHORT_OBJ: return short.class; case JavaTypes.LONG_OBJ: return long.class; default: return fmd.getDeclaredType(); } } /** * Return the proper getter method of the {@link Reflection} helper for * a field or getter method of the given type. */ private Method getReflectionGetterMethod(Class type, Class argType) throws NoSuchMethodException { String name = "get"; if (type.isPrimitive()) name += StringUtils.capitalize(type.getName()); return Reflection.class.getMethod(name, new Class[] { Object.class, argType }); } /** * Return the proper fetch method of the ObjectIdFieldSupplier for * a field of the given type. */ private Method getFieldSupplierMethod(Class type) throws NoSuchMethodException { return getMethod(OIDFSTYPE, type, "fetch", true, false, false); } /** * Return the proper fetch method of the ObjectIdFieldConsumer for * a field of the given type. */ private Method getFieldConsumerMethod(Class type) throws NoSuchMethodException { return getMethod(OIDFCTYPE, type, "store", false, false, false); } /** * Adds the pcNewObjectIdInstance method to classes using * application identity. */ private void addNewObjectIdInstanceMethod(boolean obj) throws NoSuchMethodException { // public Object pcNewObjectIdInstance () Class[] args = (obj) ? new Class[]{ Object.class } : null; BCMethod method = _pc.declareMethod(PRE + "NewObjectIdInstance", Object.class, args); Code code = method.getCode(true); Boolean usesClsString = usesClassStringIdConstructor(); Class oidType = _meta.getObjectIdType(); if (obj && usesClsString == null) { // throw new IllegalArgumentException (...); String msg = _loc.get("str-cons", oidType, _meta.getDescribedType()).getMessage(); code.anew().setType(IllegalArgumentException.class); code.dup(); code.constant().setValue(msg); code.invokespecial().setMethod(IllegalArgumentException.class, "", void.class, new Class[]{ String.class }); code.athrow(); code.calculateMaxStack(); code.calculateMaxLocals(); return; } if (!_meta.isOpenJPAIdentity() && _meta.isObjectIdTypeShared()) { // new ObjectId (cls, oid) code.anew().setType(ObjectId.class); code.dup(); if(_meta.isEmbeddedOnly() || _meta.hasAbstractPKField() == true) { code.aload().setThis(); code.invokevirtual().setMethod(PRE + "GetIDOwningClass", Class.class, null); } else { code.classconstant().setClass(getType(_meta)); } } // new (); code.anew().setType(oidType); code.dup(); if (_meta.isOpenJPAIdentity() || (obj && usesClsString == Boolean.TRUE)) { if ((_meta.isEmbeddedOnly() && ! (_meta.getIdentityType() == ClassMetaData.ID_APPLICATION)) || _meta.hasAbstractPKField() == true ) { code.aload().setThis(); code.invokevirtual().setMethod(PRE + "GetIDOwningClass", Class.class, null); } else { code.classconstant().setClass(getType(_meta)); } } if (obj) { code.aload().setParam(0); code.checkcast().setType(String.class); if (usesClsString == Boolean.TRUE) args = new Class[]{ Class.class, String.class }; else if (usesClsString == Boolean.FALSE) args = new Class[]{ String.class }; } else if (_meta.isOpenJPAIdentity()) { // new Identity (XXX.class, ); loadManagedInstance(code, false); FieldMetaData pk = _meta.getPrimaryKeyFields()[0]; addGetManagedValueCode(code, pk); if (pk.getDeclaredTypeCode() == JavaTypes.PC) addExtractObjectIdFieldValueCode(code, pk); if (_meta.getObjectIdType() == ObjectId.class) args = new Class[]{ Class.class, Object.class }; else if (_meta.getObjectIdType() == Date.class) args = new Class[]{ Class.class, Date.class }; else args = new Class[]{ Class.class, pk.getObjectIdFieldType() }; } code.invokespecial().setMethod(oidType, "", void.class, args); if (!_meta.isOpenJPAIdentity() && _meta.isObjectIdTypeShared()) code.invokespecial().setMethod(ObjectId.class, "", void.class, new Class[]{ Class.class, Object.class }); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * When communicating with the StateManager, many methods are used * depending on the class of state being passed. This method, * given the type of information being passed and the prefix * ('provided', 'replace', etc) of the method to * call, returns the StateManager method that should be used. * * @param type the type of state being passed * @param prefix the prefix of the method to call; all methods * end in '[state type]Field'; only the prefix varies * @param get true if receiving information from the * StateManager, false if passing it to the SM * @param curValue true if the current state value is passed to * the StateManager as an extra argument */ private Method getStateManagerMethod(Class type, String prefix, boolean get, boolean curValue) throws NoSuchMethodException { return getMethod(SMTYPE, type, prefix, get, true, curValue); } /** * Return the method of the given owner type matching the given criteria. * * @param type the type of state being passed * @param prefix the prefix of the method to call; all methods * end in '[state type]Field'; only the prefix varies * @param get true if receiving information from the * owner, false if passing it to the owner * @param haspc true if the pc is passed as an extra argument * @param curValue true if the current state value is passed to * the owner as an extra argument */ private Method getMethod(Class owner, Class type, String prefix, boolean get, boolean haspc, boolean curValue) throws NoSuchMethodException { // all methods end in [field type]Field, where the field type // can be any of the primitve types (but capitalized), 'String', // or 'Object'; figure out what type to use String typeName = type.getName(); if (type.isPrimitive()) typeName = typeName.substring(0, 1).toUpperCase(Locale.ENGLISH) + typeName.substring(1); else if (type.equals(String.class)) typeName = "String"; else { typeName = "Object"; type = Object.class; } // the field index is always passed as an arg; the pc instance and // the current value may be passed; if setting the new value is // also passed List plist = new ArrayList(4); if (haspc) plist.add(PCTYPE); plist.add(int.class); if (!get || curValue) plist.add(type); if (!get && curValue) { plist.add(type); plist.add(int.class); } // use reflection to return the right method String name = prefix + typeName + "Field"; Class[] params = (Class[]) plist.toArray(new Class[plist.size()]); try { return AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodAction(owner, name, params)); } catch (PrivilegedActionException pae) { throw (NoSuchMethodException) pae.getException(); } } /** * Helper method to add the code necessary to throw the given * exception type, sans message. */ private Instruction throwException(Code code, Class type) { Instruction ins = code.anew().setType(type); code.dup(); code.invokespecial().setMethod(type, "", void.class, null); code.athrow(); return ins; } /** * Adds the PersistenceCapable interface to the class being * enhanced, and adds a default constructor for use by OpenJPA * if it is not already present. */ private void enhanceClass() { // make the class implement PersistenceCapable _pc.declareInterface(PCTYPE); // add a version stamp addGetEnhancementContractVersionMethod(); // find the default constructor BCMethod method = _pc.getDeclaredMethod("", (String[]) null); // a default constructor is required if (method == null) { String name = _pc.getName(); if (!_defCons) throw new UserException(_loc.get("enhance-defaultconst", name)); method = _pc.addDefaultConstructor(); String access; if (_meta.isDetachable()) { // externalizable requires that the constructor // be public, so make the added constructor public method.makePublic(); access = "public"; } else if (_pc.isFinal()) { method.makePrivate(); access = "private"; } else { method.makeProtected(); access = "protected"; } if (!(_meta.getDescribedType().isInterface() || getCreateSubclass()) && _log.isWarnEnabled()) _log.warn(_loc.get("enhance-adddefaultconst", name, access)); } } /** * Adds the following fields to the PersistenceCapable instance: *
    *
  • private static int pcInheritedFieldCount
  • *
  • private static Class pcPCSuperclass *
  • *
  • private static String[] pcFieldNames
  • *
  • private static Class[] pcFieldTypes
  • *
  • private static byte[] pcFieldFlags
  • *
  • protected transient StateManager pcStateManager * if no PersistenceCapable superclass present)
  • *
*/ private void addFields() { _pc.declareField(INHERIT, int.class).setStatic(true); _pc.declareField(PRE + "FieldNames", String[].class).setStatic(true); _pc.declareField(PRE + "FieldTypes", Class[].class).setStatic(true); _pc.declareField(PRE + "FieldFlags", byte[].class).setStatic(true); _pc.declareField(SUPER, Class.class).setStatic(true); if (_addVersionInitFlag && _meta.getVersionField() != null) { // protected transient boolean pcVersionInit; BCField field = _pc.declareField(VERSION_INIT_STR, boolean.class); field.makeProtected(); field.setTransient(true); } if (_meta.getPCSuperclass() == null || getCreateSubclass()) { BCField field = _pc.declareField(SM, SMTYPE); field.makeProtected(); field.setTransient(true); } } /** * Modifies the class initialization method (creating one if necessary) * to initialize the static fields of the PersistenceCapable instance and * to register it with the impl helper. */ private void addStaticInitializer() { Code code = getOrCreateClassInitCode(true); if (_meta.getPCSuperclass() != null) { if (getCreateSubclass()) { code.constant().setValue(0); code.putstatic().setField(INHERIT, int.class); } else { // pcInheritedFieldCount = .pcGetManagedFieldCount() code.invokestatic().setMethod(getType(_meta. getPCSuperclassMetaData()).getName(), PRE + "GetManagedFieldCount", int.class.getName(), null); code.putstatic().setField(INHERIT, int.class); } // pcPCSuperclass = ; // this intentionally calls getDescribedType() directly // instead of PCEnhancer.getType() code.classconstant().setClass( _meta.getPCSuperclassMetaData().getDescribedType()); code.putstatic().setField(SUPER, Class.class); } // pcFieldNames = new String[] { "", "", ... }; FieldMetaData[] fmds = _meta.getDeclaredFields(); code.constant().setValue(fmds.length); code.anewarray().setType(String.class); for (int i = 0; i < fmds.length; i++) { code.dup(); code.constant().setValue(i); code.constant().setValue(fmds[i].getName()); code.aastore(); } code.putstatic().setField(PRE + "FieldNames", String[].class); // pcFieldTypes = new Class[] { .class, .class, ... }; code.constant().setValue(fmds.length); code.anewarray().setType(Class.class); for (int i = 0; i < fmds.length; i++) { code.dup(); code.constant().setValue(i); code.classconstant().setClass(fmds[i].getDeclaredType()); code.aastore(); } code.putstatic().setField(PRE + "FieldTypes", Class[].class); // pcFieldFlags = new byte[] { , , ... }; code.constant().setValue(fmds.length); code.newarray().setType(byte.class); for (int i = 0; i < fmds.length; i++) { code.dup(); code.constant().setValue(i); code.constant().setValue(getFieldFlag(fmds[i])); code.bastore(); } code.putstatic().setField(PRE + "FieldFlags", byte[].class); // PCRegistry.register (cls, // pcFieldNames, pcFieldTypes, pcFieldFlags, // pcPCSuperclass, alias, new XXX ()); code.classconstant().setClass(_meta.getDescribedType()); code.getstatic().setField(PRE + "FieldNames", String[].class); code.getstatic().setField(PRE + "FieldTypes", Class[].class); code.getstatic().setField(PRE + "FieldFlags", byte[].class); code.getstatic().setField(SUPER, Class.class); if (_meta.isMapped() || _meta.isAbstract()) code.constant().setValue(_meta.getTypeAlias()); else code.constant().setNull(); if (_pc.isAbstract()) code.constant().setNull(); else { code.anew().setType(_pc); code.dup(); code.invokespecial().setMethod("", void.class, null); } code.invokestatic().setMethod(HELPERTYPE, "register", void.class, new Class[]{ Class.class, String[].class, Class[].class, byte[].class, Class.class, String.class, PCTYPE }); code.vreturn(); code.calculateMaxStack(); } /** * Return the flag for the given field. */ private static byte getFieldFlag(FieldMetaData fmd) { if (fmd.getManagement() == FieldMetaData.MANAGE_NONE) return -1; byte flags = 0; if (fmd.getDeclaredType().isPrimitive() || Serializable.class.isAssignableFrom(fmd.getDeclaredType())) flags = PersistenceCapable.SERIALIZABLE; if (fmd.getManagement() == FieldMetaData.MANAGE_TRANSACTIONAL) flags |= PersistenceCapable.CHECK_WRITE; else if (!fmd.isPrimaryKey() && !fmd.isInDefaultFetchGroup()) flags |= PersistenceCapable.CHECK_WRITE | PersistenceCapable.CHECK_READ; else flags |= PersistenceCapable.MEDIATE_WRITE | PersistenceCapable.MEDIATE_READ; return flags; } /** * Adds the code to properly handle PersistenceCapable serialization * to the bytecode. This includes creating and initializing the * static serialVersionUID constant if not already defined, * as well as creating a custom writeObject method if the * class is Serializable and does not define them. */ private void addSerializationCode() { if (externalizeDetached() || !Serializable.class.isAssignableFrom(_meta.getDescribedType())) return; if (getCreateSubclass()) { // ##### what should happen if a type is Externalizable? It looks // ##### like Externalizable classes will not be serialized as PCs // ##### based on this logic. if (!Externalizable.class.isAssignableFrom( _meta.getDescribedType())) addSubclassSerializationCode(); return; } // if not already present, add a serialVersionUID field; if the instance // is detachable and uses detached state without a declared field, // can't add a serial version UID because we'll be adding extra fields // to the enhanced version BCField field = _pc.getDeclaredField("serialVersionUID"); if (field == null) { Long uid = null; try { uid = ObjectStreamClass.lookup (_meta.getDescribedType()).getSerialVersionUID(); } catch (Throwable t) { // last-chance catch for bug #283 (which can happen // in a variety of ClassLoading environments) if (_log.isTraceEnabled()) _log.warn(_loc.get("enhance-uid-access", _meta), t); else _log.warn(_loc.get("enhance-uid-access", _meta)); } // if we couldn't access the serialVersionUID, we will have to // skip the override of that field and not be serialization // compatible with non-enhanced classes if (uid != null) { field = _pc.declareField("serialVersionUID", long.class); field.makePrivate(); field.setStatic(true); field.setFinal(true); Code code = getOrCreateClassInitCode(false); code.beforeFirst(); code.constant().setValue(uid.longValue()); code.putstatic().setField(field); code.calculateMaxStack(); } } // add write object method BCMethod write = _pc.getDeclaredMethod("writeObject", new Class[]{ ObjectOutputStream.class }); boolean full = write == null; if (full) { // private void writeObject (ObjectOutputStream out) write = _pc.declareMethod("writeObject", void.class, new Class[]{ ObjectOutputStream.class }); write.getExceptions(true).addException(IOException.class); write.makePrivate(); } modifyWriteObjectMethod(write, full); // and read object BCMethod read = _pc.getDeclaredMethod("readObject", new Class[]{ ObjectInputStream.class }); full = read == null; if (full) { // private void readObject (ObjectInputStream in) read = _pc.declareMethod("readObject", void.class, new Class[]{ ObjectInputStream.class }); read.getExceptions(true).addException(IOException.class); read.getExceptions(true).addException (ClassNotFoundException.class); read.makePrivate(); } modifyReadObjectMethod(read, full); } private void addSubclassSerializationCode() { // for generated subclasses, serialization must write an instance of // the superclass instead of the subclass, so that the client VM can // deserialize successfully. // private Object writeReplace() throws ObjectStreamException BCMethod method = _pc.declareMethod("writeReplace", Object.class, null); method.getExceptions(true).addException(ObjectStreamException.class); Code code = method.getCode(true); // Object o = new () code.anew().setType(_managedType); // for return code.dup(); // for post- work code.dup(); // for code.invokespecial().setMethod(_managedType.getType(), "", void.class, null); // copy all the fields. // ##### limiting to JPA @Transient limitations FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].isTransient()) continue; // o. = this. (or reflective analog) code.dup(); // for putfield code.aload().setThis(); // for getfield getfield(code, _managedType, fmds[i].getName()); putfield(code, _managedType, fmds[i].getName(), fmds[i].getDeclaredType()); } code.areturn().setType(Object.class); code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Whether the class being enhanced should externalize to a detached * instance rather than serialize. */ private boolean externalizeDetached() { return ClassMetaData.SYNTHETIC.equals(_meta.getDetachedState()) && Serializable.class.isAssignableFrom(_meta.getDescribedType()) && !_repos.getConfiguration().getDetachStateInstance(). isDetachedStateTransient(); } /** * Adds a custom writeObject method that delegates to the * {@link ObjectOutputStream#defaultWriteObject} method, * but only after calling the internal pcSerializing method. */ private void modifyWriteObjectMethod(BCMethod method, boolean full) { Code code = method.getCode(true); code.beforeFirst(); // bool clear = pcSerializing (); loadManagedInstance(code, false); code.invokevirtual().setMethod(PRE + "Serializing", boolean.class, null); int clear = code.getNextLocalsIndex(); code.istore().setLocal(clear); if (full) { // out.defaultWriteObject (); code.aload().setParam(0); code.invokevirtual().setMethod(ObjectOutputStream.class, "defaultWriteObject", void.class, null); code.vreturn(); } Instruction tmplate = (AccessController.doPrivileged( J2DoPrivHelper.newCodeAction())).vreturn(); JumpInstruction toret; Instruction ret; code.beforeFirst(); while (code.searchForward(tmplate)) { ret = code.previous(); // if (clear) pcSetDetachedState (null); code.iload().setLocal(clear); toret = code.ifeq(); loadManagedInstance(code, false); code.constant().setNull(); code.invokevirtual().setMethod(PRE + "SetDetachedState", void.class, new Class[]{ Object.class }); toret.setTarget(ret); code.next(); // jump over return } code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds a custom readObject method that delegates to the * {@link ObjectInputStream#readObject} method. */ private void modifyReadObjectMethod(BCMethod method, boolean full) { Code code = method.getCode(true); code.beforeFirst(); // if this instance uses synthetic detached state, note that it has // been deserialized if (ClassMetaData.SYNTHETIC.equals(_meta.getDetachedState())) { loadManagedInstance(code, false); code.getstatic().setField(PersistenceCapable.class, "DESERIALIZED", Object.class); code.invokevirtual().setMethod(PRE + "SetDetachedState", void.class, new Class[]{ Object.class }); } if (full) { // in.defaultReadObject (); code.aload().setParam(0); code.invokevirtual().setMethod(ObjectInputStream.class, "defaultReadObject", void.class, null); code.vreturn(); } code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Creates the pcIsDetached() method to determine if an instance * is detached. */ private void addIsDetachedMethod() throws NoSuchMethodException { // public boolean pcIsDetached() BCMethod method = _pc.declareMethod(PRE + "IsDetached", Boolean.class, null); method.makePublic(); Code code = method.getCode(true); boolean needsDefinitiveMethod = writeIsDetachedMethod(code); code.calculateMaxStack(); code.calculateMaxLocals(); if (!needsDefinitiveMethod) return; // private boolean pcIsDetachedStateDefinitive() // return false; // auxilliary enhancers may change the return value of this method // if their specs consider detached state definitive method = _pc.declareMethod(ISDETACHEDSTATEDEFINITIVE, boolean.class, null); method.makePrivate(); code = method.getCode(true); code.constant().setValue(false); code.ireturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Creates the body of the pcIsDetached() method to determine if an * instance is detached. * * @return true if we need a pcIsDetachedStateDefinitive method, false * otherwise */ private boolean writeIsDetachedMethod(Code code) throws NoSuchMethodException { // not detachable: return Boolean.FALSE if (!_meta.isDetachable()) { code.getstatic().setField(Boolean.class, "FALSE", Boolean.class); code.areturn(); return false; } // if (sm != null) // return (sm.isDetached ()) ? Boolean.TRUE : Boolean.FALSE; loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); JumpInstruction ifins = code.ifnull(); loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); code.invokeinterface().setMethod(SMTYPE, "isDetached", boolean.class, null); JumpInstruction iffalse = code.ifeq(); code.getstatic().setField(Boolean.class, "TRUE", Boolean.class); code.areturn(); iffalse.setTarget(code.getstatic().setField(Boolean.class, "FALSE", Boolean.class)); code.areturn(); // if we use detached state: // if (pcGetDetachedState () != null // && pcGetDetachedState != DESERIALIZED) // return Boolean.TRUE; Boolean state = _meta.usesDetachedState(); JumpInstruction notdeser = null; Instruction target; if (state != Boolean.FALSE) { ifins.setTarget(loadManagedInstance(code, false)); code.invokevirtual().setMethod(PRE + "GetDetachedState", Object.class, null); ifins = code.ifnull(); loadManagedInstance(code, false); code.invokevirtual().setMethod(PRE + "GetDetachedState", Object.class, null); code.getstatic().setField(PersistenceCapable.class, "DESERIALIZED", Object.class); notdeser = code.ifacmpeq(); code.getstatic().setField(Boolean.class, "TRUE", Boolean.class); code.areturn(); if (state == Boolean.TRUE) { // if we have to use detached state: // return Boolean.FALSE; target = code.getstatic().setField(Boolean.class, "FALSE", Boolean.class); ifins.setTarget(target); notdeser.setTarget(target); code.areturn(); return false; } } // create artificial target to simplify target = code.nop(); ifins.setTarget(target); if (notdeser != null) notdeser.setTarget(target); // allow users with version or auto-assigned pk fields to manually // construct a "detached" instance, so check these before taking into // account non-existent detached state // consider detached if version is non-default FieldMetaData version = _meta.getVersionField(); if (state != Boolean.TRUE && version != null) { // if ( != ) // return true; loadManagedInstance(code, false); addGetManagedValueCode(code, version); ifins = ifDefaultValue(code, version); code.getstatic().setField(Boolean.class, "TRUE", Boolean.class); code.areturn(); if (!_addVersionInitFlag){ // else return false; ifins.setTarget(code.getstatic().setField(Boolean.class, "FALSE", Boolean.class)); }else{ // noop ifins.setTarget(code.nop()); // if (pcVersionInit != false) // return true // else return null; // (returning null because we don't know the correct answer) loadManagedInstance(code, false); getfield(code, null, VERSION_INIT_STR); ifins = code.ifeq(); code.getstatic().setField(Boolean.class, "TRUE", Boolean.class); code.areturn(); ifins.setTarget(code.nop()); code.constant().setNull(); } code.areturn(); return false; } // consider detached if auto-genned primary keys are non-default ifins = null; JumpInstruction ifins2 = null; boolean hasAutoAssignedPK = false; if (state != Boolean.TRUE && _meta.getIdentityType() == ClassMetaData.ID_APPLICATION) { // for each pk field: // if ( != [&& !"".equals ()]) // return Boolean.TRUE; FieldMetaData[] pks = _meta.getPrimaryKeyFields(); for (int i = 0; i < pks.length; i++) { if (pks[i].getValueStrategy() == ValueStrategies.NONE) continue; target = loadManagedInstance(code, false); if (ifins != null) ifins.setTarget(target); if (ifins2 != null) ifins2.setTarget(target); ifins2 = null; addGetManagedValueCode(code, pks[i]); ifins = ifDefaultValue(code, pks[i]); if (pks[i].getDeclaredTypeCode() == JavaTypes.STRING) { code.constant().setValue(""); loadManagedInstance(code, false); addGetManagedValueCode(code, pks[i]); code.invokevirtual().setMethod(String.class, "equals", boolean.class, new Class[]{ Object.class }); ifins2 = code.ifne(); } code.getstatic().setField(Boolean.class, "TRUE", Boolean.class); code.areturn(); } } // create artificial target to simplify target = code.nop(); if (ifins != null) ifins.setTarget(target); if (ifins2 != null) ifins2.setTarget(target); // if has auto-assigned pk and we get to this point, must have default // value, so must be new instance if (hasAutoAssignedPK) { code.getstatic().setField(Boolean.class, "FALSE", Boolean.class); code.areturn(); return false; } // if detached state is not definitive, just give up now and return // null so that the runtime will perform a DB lookup to determine // whether we're detached or new code.aload().setThis(); code.invokespecial().setMethod(ISDETACHEDSTATEDEFINITIVE, boolean.class, null); ifins = code.ifne(); code.constant().setNull(); code.areturn(); ifins.setTarget(code.nop()); // no detached state: if instance uses detached state and it's not // synthetic or the instance is not serializable or the state isn't // transient, must not be detached if (state == null && (!ClassMetaData.SYNTHETIC.equals(_meta.getDetachedState()) || !Serializable.class.isAssignableFrom(_meta.getDescribedType()) || !_repos.getConfiguration().getDetachStateInstance(). isDetachedStateTransient())) { // return Boolean.FALSE code.getstatic().setField(Boolean.class, "FALSE", Boolean.class); code.areturn(); return true; } // no detached state: if instance uses detached state (and must be // synthetic and transient in serializable instance at this point), // not detached if state not set to DESERIALIZED if (state == null) { // if (pcGetDetachedState () == null) // instead of DESERIALIZED // return Boolean.FALSE; loadManagedInstance(code, false); code.invokevirtual().setMethod(PRE + "GetDetachedState", Object.class, null); ifins = code.ifnonnull(); code.getstatic().setField(Boolean.class, "FALSE", Boolean.class); code.areturn(); ifins.setTarget(code.nop()); } // give up; we just don't know code.constant().setNull(); code.areturn(); return true; } /** * Compare the given field to its Java default, returning the * comparison instruction. The field value will already be on the stack. */ private static JumpInstruction ifDefaultValue(Code code, FieldMetaData fmd) { switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: case JavaTypes.BYTE: case JavaTypes.CHAR: case JavaTypes.INT: case JavaTypes.SHORT: return code.ifeq(); case JavaTypes.DOUBLE: code.constant().setValue(0D); code.dcmpl(); return code.ifeq(); case JavaTypes.FLOAT: code.constant().setValue(0F); code.fcmpl(); return code.ifeq(); case JavaTypes.LONG: code.constant().setValue(0L); code.lcmp(); return code.ifeq(); default: return code.ifnull(); } } /** * Helper method to get the code for the class initializer method, * creating the method if it does not already exist. */ private Code getOrCreateClassInitCode(boolean replaceLast) { BCMethod clinit = _pc.getDeclaredMethod(""); Code code; if (clinit != null) { code = clinit.getCode(true); if (replaceLast) { Code template = AccessController.doPrivileged( J2DoPrivHelper.newCodeAction()); code.searchForward(template.vreturn()); code.previous(); code.set(template.nop()); code.next(); } return code; } // add static initializer method if non exists clinit = _pc.declareMethod("", void.class, null); clinit.makePackage(); clinit.setStatic(true); clinit.setFinal(true); code = clinit.getCode(true); if (!replaceLast) { code.vreturn(); code.previous(); } return code; } /** * Adds bytecode modifying the cloning behavior of the class being * enhanced to correctly replace the pcStateManager * instance fields of any clone created with their default values. * Also, if this class is the base PC type and does not declared * a clone method, one will be added. Also, if _pc is a synthetic * subclass, create the clone() method that clears the state manager * that may have been initialized in a super's clone() method. */ private void addCloningCode() { if (_meta.getPCSuperclass() != null && !getCreateSubclass()) return; // add the clone method if necessary BCMethod clone = _pc.getDeclaredMethod("clone", (String[]) null); String superName = _managedType.getSuperclassName(); Code code = null; if (clone == null) { // add clone support for base classes // which also implement cloneable boolean isCloneable = Cloneable.class.isAssignableFrom( _managedType.getType()); boolean extendsObject = superName.equals(Object.class.getName()); if (!isCloneable || (!extendsObject && !getCreateSubclass())) return; if (!getCreateSubclass()) if (_log.isTraceEnabled()) _log.trace( _loc.get("enhance-cloneable", _managedType.getName())); // add clone method // protected Object clone () throws CloneNotSupportedException clone = _pc.declareMethod("clone", Object.class, null); if (!setVisibilityToSuperMethod(clone)) clone.makeProtected(); clone.getExceptions(true).addException (CloneNotSupportedException.class); code = clone.getCode(true); // return super.clone (); loadManagedInstance(code, false); code.invokespecial().setMethod(superName, "clone", Object.class.getName(), null); code.areturn(); } else { // get the clone method code code = clone.getCode(false); if (code == null) return; } // create template super.clone () instruction to match against Instruction template = (AccessController.doPrivileged( J2DoPrivHelper.newCodeAction())).invokespecial() .setMethod(superName, "clone", Object.class.getName(), null); // find calls to the template instruction; on match // clone will be on stack code.beforeFirst(); if (code.searchForward(template)) { // (() clone).pcStateManager = null; code.dup(); code.checkcast().setType(_pc); code.constant().setNull(); code.putfield().setField(SM, SMTYPE); // if modified, increase stack code.calculateMaxStack(); code.calculateMaxLocals(); } } /** * Gets the auxiliary enhancers registered as {@link Services services}. */ public AuxiliaryEnhancer[] getAuxiliaryEnhancers() { return _auxEnhancers; } /** * Allow any registered auxiliary code generators to run. */ private void runAuxiliaryEnhancers() { for (int i = 0; i < _auxEnhancers.length; i++) _auxEnhancers[i].run(_pc, _meta); } /** * Affirms if the given method be skipped. * * @param method method to be skipped or not * @return true if any of the auxiliary enhancers skips the given method, * or if the method is a constructor */ private boolean skipEnhance(BCMethod method) { if ("".equals(method.getName())) return true; for (int i = 0; i < _auxEnhancers.length; i++) if (_auxEnhancers[i].skipEnhance(method)) return true; return false; } /** * Adds synthetic field access methods that will replace all direct * field accesses. */ private void addAccessors() throws NoSuchMethodException { FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields() : _meta.getDeclaredFields(); for (int i = 0; i < fmds.length; i++) { if (getCreateSubclass()) { if (!getRedefine() && isPropertyAccess(fmds[i])) { addSubclassSetMethod(fmds[i]); addSubclassGetMethod(fmds[i]); } } else { addGetMethod(i, fmds[i]); addSetMethod(i, fmds[i]); } } } /** * Adds a non-static setter that delegates to the super methods, and * performs any necessary field tracking. */ private void addSubclassSetMethod(FieldMetaData fmd) throws NoSuchMethodException { Class propType = fmd.getDeclaredType(); String setterName = getSetterName(fmd); BCMethod setter = _pc.declareMethod(setterName, void.class, new Class[] { propType }); setVisibilityToSuperMethod(setter); Code code = setter.getCode(true); // not necessary if we're already tracking access via redefinition if (!getRedefine()) { // get the orig value onto stack code.aload().setThis(); addGetManagedValueCode(code, fmd); int val = code.getNextLocalsIndex(); code.xstore().setLocal(val).setType(fmd.getDeclaredType()); addNotifyMutation(code, fmd, val, 0); } // ##### test case: B extends A. Methods defined in A. What // ##### happens? // super.setXXX(...) code.aload().setThis(); code.xload().setParam(0).setType(propType); code.invokespecial().setMethod(_managedType.getType(), setterName, void.class, new Class[] { propType }); code.vreturn(); code.calculateMaxLocals(); code.calculateMaxStack(); } private boolean setVisibilityToSuperMethod(BCMethod method) { BCMethod[] methods = _managedType.getMethods(method.getName(), method.getParamTypes()); if (methods.length == 0) throw new UserException(_loc.get("no-accessor", _managedType.getName(), method.getName())); BCMethod superMeth = methods[0]; if (superMeth.isPrivate()) { method.makePrivate(); return true; } else if (superMeth.isPackage()) { method.makePackage(); return true; } else if (superMeth.isProtected()) { method.makeProtected(); return true; } else if (superMeth.isPublic()) { method.makePublic(); return true; } return false; } /** * Adds a non-static getter that delegates to the super methods, and * performs any necessary field tracking. */ private void addSubclassGetMethod(FieldMetaData fmd) { String methName = "get" + StringUtils.capitalize(fmd.getName()); if (_managedType.getMethods(methName, new Class[0]).length == 0) methName = "is" + StringUtils.capitalize(fmd.getName()); BCMethod getter = _pc.declareMethod(methName, fmd.getDeclaredType(), null); setVisibilityToSuperMethod(getter); getter.makePublic(); Code code = getter.getCode(true); // if we're not already tracking field access via reflection, then we // must make the getter hook in lazy loading before accessing the super // method. if (!getRedefine()) addNotifyAccess(code, fmd); code.aload().setThis(); code.invokespecial().setMethod(_managedType.getType(), methName, fmd.getDeclaredType(), null); code.xreturn().setType(fmd.getDeclaredType()); code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Adds a static getter method for the given field. * The generated method interacts with the instance state and the * StateManager to get the value of the field. * * @param index the relative number of the field * @param fmd metadata about the field to get */ private void addGetMethod(int index, FieldMetaData fmd) throws NoSuchMethodException { BCMethod method = createGetMethod(fmd); Code code = method.getCode(true); // if reads are not checked, just return the value byte fieldFlag = getFieldFlag(fmd); if ((fieldFlag & PersistenceCapable.CHECK_READ) == 0 && (fieldFlag & PersistenceCapable.MEDIATE_READ) == 0) { loadManagedInstance(code, true, fmd); addGetManagedValueCode(code, fmd); code.xreturn().setType(fmd.getDeclaredType()); code.calculateMaxStack(); code.calculateMaxLocals(); return; } // if (inst.pcStateManager == null) return inst.; loadManagedInstance(code, true, fmd); code.getfield().setField(SM, SMTYPE); JumpInstruction ifins = code.ifnonnull(); loadManagedInstance(code, true, fmd); addGetManagedValueCode(code, fmd); code.xreturn().setType(fmd.getDeclaredType()); // int field = pcInheritedFieldCount + ; int fieldLocal = code.getNextLocalsIndex(); ifins.setTarget(code.getstatic().setField(INHERIT, int.class)); code.constant().setValue(index); code.iadd(); code.istore().setLocal(fieldLocal); // inst.pcStateManager.accessingField (field); // return inst.; loadManagedInstance(code, true, fmd); code.getfield().setField(SM, SMTYPE); code.iload().setLocal(fieldLocal); code.invokeinterface().setMethod(SMTYPE, "accessingField", void.class, new Class[]{ int.class }); loadManagedInstance(code, true, fmd); addGetManagedValueCode(code, fmd); code.xreturn().setType(fmd.getDeclaredType()); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds a static setter method for the given field. * The generated method interacts with the instance state and the * StateManager to set the value of the field. * * @param index the relative number of the field * @param fmd metadata about the field to set */ private void addSetMethod(int index, FieldMetaData fmd) throws NoSuchMethodException { BCMethod method = createSetMethod(fmd); Code code = method.getCode(true); // PCEnhancer uses static methods; PCSubclasser does not. int firstParamOffset = getAccessorParameterOffset(fmd); // if (inst.pcStateManager == null) inst. = value; loadManagedInstance(code, true, fmd); code.getfield().setField(SM, SMTYPE); JumpInstruction ifins = code.ifnonnull(); loadManagedInstance(code, true, fmd); code.xload().setParam(firstParamOffset); addSetManagedValueCode(code, fmd); if(fmd.isVersion()==true && _addVersionInitFlag){ // if we are setting the version, flip the versionInit flag to true loadManagedInstance(code, true); code.constant().setValue(1); // pcVersionInit = true; putfield(code, null, VERSION_INIT_STR, boolean.class); } code.vreturn(); // inst.pcStateManager.settingField (inst, // pcInheritedFieldCount + , inst., value, 0); ifins.setTarget(loadManagedInstance(code, true, fmd)); code.getfield().setField(SM, SMTYPE); loadManagedInstance(code, true, fmd); code.getstatic().setField(INHERIT, int.class); code.constant().setValue(index); code.iadd(); loadManagedInstance(code, true, fmd); addGetManagedValueCode(code, fmd); code.xload().setParam(firstParamOffset); code.constant().setValue(0); code.invokeinterface().setMethod(getStateManagerMethod (fmd.getDeclaredType(), "setting", false, true)); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Determines which attach / detach methods to use. */ private void addAttachDetachCode() throws NoSuchMethodException { // see if any superclasses are detachable boolean parentDetachable = false; for (ClassMetaData parent = _meta.getPCSuperclassMetaData(); parent != null; parent = parent.getPCSuperclassMetaData()) { if (parent.isDetachable()) { parentDetachable = true; break; } } // if parent not detachable, we need to add the detach state fields and // accessor methods if (_meta.getPCSuperclass() == null || getCreateSubclass() || parentDetachable != _meta.isDetachable()) { addIsDetachedMethod(); addDetachedStateMethods(_meta.usesDetachedState() != Boolean.FALSE); } // if we detach on serialize, we also need to implement the // externalizable interface to write just the state for the fields // being detached if (externalizeDetached()) { try { addDetachExternalize(parentDetachable, _meta.usesDetachedState() != Boolean.FALSE); } catch (NoSuchMethodException nsme) { throw new GeneralException(nsme); } } } /** * Add the fields to hold detached state and their accessor methods. * * @param impl whether to fully implement detach state functionality */ private void addDetachedStateMethods(boolean impl) { Field detachField = _meta.getDetachedStateField(); String name = null; String declarer = null; if (impl && detachField == null) { name = PRE + "DetachedState"; declarer = _pc.getName(); BCField field = _pc.declareField(name, Object.class); field.makePrivate(); field.setTransient(true); } else if (impl) { name = detachField.getName(); declarer = detachField.getDeclaringClass().getName(); } // public Object pcGetDetachedState () BCMethod method = _pc.declareMethod(PRE + "GetDetachedState", Object.class, null); method.setStatic(false); method.makePublic(); int access = method.getAccessFlags(); Code code = method.getCode(true); if (impl) { // return pcDetachedState; loadManagedInstance(code, false); getfield(code, _managedType.getProject().loadClass(declarer), name); } else code.constant().setNull(); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); // public void pcSetDetachedState (Object state) method = _pc.declareMethod(PRE + "SetDetachedState", void.class, new Class []{ Object.class }); method.setAccessFlags(access); code = method.getCode(true); if (impl) { // pcDetachedState = state; loadManagedInstance(code, false); code.aload().setParam(0); putfield(code, _managedType.getProject().loadClass(declarer), name, Object.class); } code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Adds to code the instructions to get field * attrName declared in type declarer * onto the top of the stack. * * The instance to access must already be on the top of the * stack when this is invoked. */ private void getfield(Code code, BCClass declarer, String attrName) { if (declarer == null) declarer = _managedType; // first, see if we can convert the attribute name to a field name String fieldName = toBackingFieldName(attrName); // next, find the field in the managed type hierarchy BCField field = null; outer: for (BCClass bc = _pc; bc != null; bc = bc.getSuperclassBC()) { BCField[] fields = AccessController .doPrivileged(J2DoPrivHelper.getBCClassFieldsAction(bc, fieldName)); for (int i = 0; i < fields.length; i++) { field = fields[i]; // if we reach a field declared in this type, then this is the // most-masking field, and is the one that we want. if (fields[i].getDeclarer() == declarer) { break outer; } } } if (getCreateSubclass() && code.getMethod().getDeclarer() == _pc && (field == null || !field.isPublic())) { // we're creating the subclass, not redefining the user type. // Reflection.getXXX(this, Reflection.findField(...)); code.classconstant().setClass(declarer); code.constant().setValue(fieldName); code.constant().setValue(true); code.invokestatic().setMethod(Reflection.class, "findField", Field.class, new Class[] { Class.class, String.class, boolean.class }); Class type = _meta.getField(attrName).getDeclaredType(); try { code.invokestatic().setMethod( getReflectionGetterMethod(type, Field.class)); } catch (NoSuchMethodException e) { // should never happen throw new InternalException(e); } if (!type.isPrimitive() && type != Object.class) code.checkcast().setType(type); } else { code.getfield().setField(declarer.getName(), fieldName, field.getType().getName()); } } /** * Adds to code the instructions to set field * attrName declared in type declarer * to the value of type fieldType on the top of the stack. * * When this method is invoked, the value to load must * already be on the top of the stack in code, * and the instance to load into must be second. */ private void putfield(Code code, BCClass declarer, String attrName, Class fieldType) { if (declarer == null) declarer = _managedType; String fieldName = toBackingFieldName(attrName); if (getRedefine() || getCreateSubclass()) { // Reflection.set(this, Reflection.findField(...), value); code.classconstant().setClass(declarer); code.constant().setValue(fieldName); code.constant().setValue(true); code.invokestatic().setMethod(Reflection.class, "findField", Field.class, new Class[] { Class.class, String.class, boolean.class }); code.invokestatic().setMethod(Reflection.class, "set", void.class, new Class[] { Object.class, fieldType.isPrimitive() ? fieldType : Object.class, Field.class }); } else { code.putfield() .setField(declarer.getName(), fieldName, fieldType.getName()); } } /** * If using property access, see if there is a different backing field * name for the persistent attribute name. */ private String toBackingFieldName(String name) { // meta is null when enhancing persistence-aware FieldMetaData fmd = _meta == null ? null : _meta.getField(name); if (_meta != null && isPropertyAccess(fmd) && _attrsToFields != null && _attrsToFields.containsKey(name)) name = (String)_attrsToFields.get(name); return name; } /** * If using property access, see if there is a different persistent * attribute name for the backing field name. */ private String fromBackingFieldName(String name) { // meta is null when enhancing persistence-aware FieldMetaData fmd = _meta == null ? null : _meta.getField(name); if (_meta != null && isPropertyAccess(fmd) && _fieldsToAttrs != null && _fieldsToAttrs.containsKey(name)) return (String)_fieldsToAttrs.get(name); else return name; } /** * Implement the externalizable interface to detach on serialize. */ private void addDetachExternalize(boolean parentDetachable, boolean detachedState) throws NoSuchMethodException { // ensure that the declared default constructor is public // for externalization BCMethod meth = _pc.getDeclaredMethod("", (String[]) null); if (!meth.isPublic()) { if (_log.isWarnEnabled()) _log.warn(_loc.get("enhance-defcons-extern", _meta.getDescribedType())); meth.makePublic(); } // declare externalizable interface if (!Externalizable.class.isAssignableFrom(_meta.getDescribedType())) _pc.declareInterface(Externalizable.class); // make sure the user doesn't already have custom externalization or // serialization methods Class[] input = new Class[]{ ObjectInputStream.class }; Class[] output = new Class[]{ ObjectOutputStream.class }; if (_managedType.getDeclaredMethod("readObject", input) != null || _managedType.getDeclaredMethod("writeObject", output) != null) throw new UserException(_loc.get("detach-custom-ser", _meta)); input[0] = ObjectInput.class; output[0] = ObjectOutput.class; if (_managedType.getDeclaredMethod("readExternal", input) != null || _managedType.getDeclaredMethod("writeExternal", output) != null) throw new UserException(_loc.get("detach-custom-extern", _meta)); // create list of all unmanaged serializable fields BCField[] fields = _managedType.getDeclaredFields(); Collection unmgd = new ArrayList(fields.length); for (int i = 0; i < fields.length; i++) { if (!fields[i].isTransient() && !fields[i].isStatic() && !fields[i].isFinal() && !fields[i].getName().startsWith(PRE) && _meta.getDeclaredField(fields[i].getName()) == null) unmgd.add(fields[i]); } addReadExternal(parentDetachable, detachedState); addReadUnmanaged(unmgd, parentDetachable); addWriteExternal(parentDetachable, detachedState); addWriteUnmanaged(unmgd, parentDetachable); } /** * Add custom readExternal method. */ private void addReadExternal(boolean parentDetachable, boolean detachedState) throws NoSuchMethodException { Class[] inargs = new Class[]{ ObjectInput.class }; BCMethod meth = _pc.declareMethod("readExternal", void.class, inargs); Exceptions exceps = meth.getExceptions(true); exceps.addException(IOException.class); exceps.addException(ClassNotFoundException.class); Code code = meth.getCode(true); // super.readExternal (in); // not sure if this works: this is depending on the order of the enhancement! // if the subclass gets enhanced first, then the superclass misses // the Externalizable at this point! Class sup = _meta.getDescribedType().getSuperclass(); if (!parentDetachable && Externalizable.class.isAssignableFrom(sup)) { loadManagedInstance(code, false); code.aload().setParam(0); code.invokespecial().setMethod(sup, "readExternal", void.class, inargs); } // readUnmanaged (in); loadManagedInstance(code, false); code.aload().setParam(0); code.invokevirtual().setMethod(getType(_meta), PRE + "ReadUnmanaged", void.class, inargs); if (detachedState) { // pcSetDetachedState (in.readObject ()); loadManagedInstance(code, false); code.aload().setParam(0); code.invokeinterface().setMethod(ObjectInput.class, "readObject", Object.class, null); code.invokevirtual().setMethod(PRE + "SetDetachedState", void.class, new Class[]{ Object.class }); // pcReplaceStateManager ((StateManager) in.readObject ()); loadManagedInstance(code, false); code.aload().setParam(0); code.invokeinterface().setMethod(ObjectInput.class, "readObject", Object.class, null); code.checkcast().setType(StateManager.class); code.invokevirtual().setMethod(PRE + "ReplaceStateManager", void.class, new Class[]{ StateManager.class }); } addReadExternalFields(); // readExternalFields(in.readObject ()); loadManagedInstance(code, false); code.aload().setParam(0); code.invokevirtual().setMethod("readExternalFields", void.class, inargs); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } private void addReadExternalFields() throws NoSuchMethodException { Class[] inargs = new Class[]{ ObjectInput.class }; BCMethod meth = _pc.declareMethod("readExternalFields", void.class, inargs); meth.setAccessFlags(Constants.ACCESS_PROTECTED); Exceptions exceps = meth.getExceptions(true); exceps.addException(IOException.class); exceps.addException(ClassNotFoundException.class); Code code = meth.getCode(true); Class sup = _meta.getPCSuperclass(); if (sup != null) { //add a call to super.readExternalFields() loadManagedInstance(code, false); code.aload().setParam(0); code.invokespecial().setMethod(sup, "readExternalFields", void.class, inargs); } // read managed fields FieldMetaData[] fmds = _meta.getDeclaredFields(); for (int i = 0; i < fmds.length; i++) { if (!fmds[i].isTransient()) { readExternal(code, fmds[i].getName(), fmds[i].getDeclaredType(), fmds[i]); } } code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Read unmanaged fields from the stream (pcReadUnmanaged). */ private void addReadUnmanaged(Collection unmgd, boolean parentDetachable) throws NoSuchMethodException { Class[] inargs = new Class[]{ ObjectInput.class }; BCMethod meth = _pc.declareMethod(PRE + "ReadUnmanaged", void.class, inargs); meth.makeProtected(); Exceptions exceps = meth.getExceptions(true); exceps.addException(IOException.class); exceps.addException(ClassNotFoundException.class); Code code = meth.getCode(true); // super.readUnmanaged (in); if (parentDetachable) { loadManagedInstance(code, false); code.aload().setParam(0); code.invokespecial().setMethod(getType(_meta. getPCSuperclassMetaData()), PRE + "ReadUnmanaged", void.class, inargs); } // read declared unmanaged serializable fields BCField field; for (Iterator itr = unmgd.iterator(); itr.hasNext();) { field = (BCField) itr.next(); readExternal(code, field.getName(), field.getType(), null); } code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Helper method to read a field from an externalization input stream. */ private void readExternal(Code code, String fieldName, Class type, FieldMetaData fmd) throws NoSuchMethodException { String methName; if (type.isPrimitive()) { methName = type.getName(); methName = methName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methName.substring(1); methName = "read" + methName; } else methName = "readObject"; // = in.read (); loadManagedInstance(code, false); code.aload().setParam(0); Class ret = (type.isPrimitive()) ? type : Object.class; code.invokeinterface().setMethod(ObjectInput.class, methName, ret, null); if (!type.isPrimitive() && type != Object.class) code.checkcast().setType(type); if (fmd == null) putfield(code, null, fieldName, type); else { addSetManagedValueCode(code, fmd); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.DATE: case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.OBJECT: case JavaTypes.CALENDAR: // if (sm != null) // sm.proxyDetachedDeserialized (); loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); IfInstruction ifins = code.ifnull(); loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); code.constant().setValue(fmd.getIndex()); code.invokeinterface().setMethod(SMTYPE, "proxyDetachedDeserialized", void.class, new Class[]{ int.class }); ifins.setTarget(code.nop()); } } } /** * Add custom writeExternal method. */ private void addWriteExternal(boolean parentDetachable, boolean detachedState) throws NoSuchMethodException { Class[] outargs = new Class[]{ ObjectOutput.class }; BCMethod meth = _pc.declareMethod("writeExternal", void.class, outargs); Exceptions exceps = meth.getExceptions(true); exceps.addException(IOException.class); Code code = meth.getCode(true); // super.writeExternal (out); Class sup = getType(_meta).getSuperclass(); if (!parentDetachable && Externalizable.class.isAssignableFrom(sup)) { loadManagedInstance(code, false); code.aload().setParam(0); code.invokespecial().setMethod(sup, "writeExternal", void.class, outargs); } // writeUnmanaged (out); loadManagedInstance(code, false); code.aload().setParam(0); code.invokevirtual().setMethod(getType(_meta), PRE + "WriteUnmanaged", void.class, outargs); JumpInstruction go2 = null; if (detachedState) { // if (sm != null) // if (sm.writeDetached (out)) // return; loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); IfInstruction ifnull = code.ifnull(); loadManagedInstance(code, false); code.getfield().setField(SM, SMTYPE); code.aload().setParam(0); code.invokeinterface().setMethod(SMTYPE, "writeDetached", boolean.class, outargs); go2 = code.ifeq(); code.vreturn(); // else // out.writeObject (pcGetDetachedState ()); Class[] objargs = new Class[]{ Object.class }; ifnull.setTarget(code.aload().setParam(0)); loadManagedInstance(code, false); code.invokevirtual().setMethod(PRE + "GetDetachedState", Object.class, null); code.invokeinterface().setMethod(ObjectOutput.class, "writeObject", void.class, objargs); // out.writeObject (null) // StateManager code.aload().setParam(0); code.constant().setValue((Object) null); code.invokeinterface().setMethod(ObjectOutput.class, "writeObject", void.class, objargs); } if (go2 != null) go2.setTarget(code.nop()); addWriteExternalFields(); loadManagedInstance(code, false); code.aload().setParam(0); code.invokevirtual().setMethod("writeExternalFields", void.class, outargs); // return code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } private void addWriteExternalFields() throws NoSuchMethodException { Class[] outargs = new Class[]{ ObjectOutput.class }; BCMethod meth = _pc.declareMethod("writeExternalFields", void.class, outargs); meth.setAccessFlags(Constants.ACCESS_PROTECTED); Exceptions exceps = meth.getExceptions(true); exceps.addException(IOException.class); Code code = meth.getCode(true); Class sup = _meta.getPCSuperclass(); if (sup != null) { // add a call to super.readExternalFields() loadManagedInstance(code, false); code.aload().setParam(0); code.invokespecial().setMethod(sup, "writeExternalFields", void.class, outargs); } FieldMetaData[] fmds = _meta.getDeclaredFields(); for (int i = 0; i < fmds.length; i++) { if (!fmds[i].isTransient()) { writeExternal(code, fmds[i].getName(), fmds[i].getDeclaredType(), fmds[i]); } } // return code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Write unmanaged fields to the stream (pcWriteUnmanaged). */ private void addWriteUnmanaged(Collection unmgd, boolean parentDetachable) throws NoSuchMethodException { Class[] outargs = new Class[]{ ObjectOutput.class }; BCMethod meth = _pc.declareMethod(PRE + "WriteUnmanaged", void.class, outargs); meth.makeProtected(); Exceptions exceps = meth.getExceptions(true); exceps.addException(IOException.class); Code code = meth.getCode(true); // super.writeUnmanaged (out); if (parentDetachable) { loadManagedInstance(code, false); code.aload().setParam(0); code.invokespecial().setMethod(getType(_meta. getPCSuperclassMetaData()), PRE + "WriteUnmanaged", void.class, outargs); } // write declared unmanaged serializable fields BCField field; for (Iterator itr = unmgd.iterator(); itr.hasNext();) { field = (BCField) itr.next(); writeExternal(code, field.getName(), field.getType(), null); } code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Helper method to write a field to an externalization output stream. */ private void writeExternal(Code code, String fieldName, Class type, FieldMetaData fmd) throws NoSuchMethodException { String methName; if (type.isPrimitive()) { methName = type.getName(); methName = methName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methName.substring(1); methName = "write" + methName; } else methName = "writeObject"; // out.write (); code.aload().setParam(0); loadManagedInstance(code, false); if (fmd == null) getfield(code, null, fieldName); else addGetManagedValueCode(code, fmd); Class[] args = new Class[]{ type }; if (type == byte.class || type == char.class || type == short.class) args[0] = int.class; else if (!type.isPrimitive()) args[0] = Object.class; code.invokeinterface().setMethod(ObjectOutput.class, methName, void.class, args); } private void addGetManagedValueCode(Code code, FieldMetaData fmd) throws NoSuchMethodException { addGetManagedValueCode(code, fmd, true); } /** * Load the field value specified by fmd onto the stack. * Before this method is called, the object that the data should be loaded * from will be on the top of the stack. * * @param fromSameClass if true, then fmd is * being loaded from an instance of the same class as the current execution * context. If false, then the instance on the top of the stack * might be a superclass of the current execution context's 'this' instance. */ private void addGetManagedValueCode(Code code, FieldMetaData fmd, boolean fromSameClass) throws NoSuchMethodException { // if redefining, then we must always reflect (or access the field // directly if accessible), since the redefined methods will always // trigger method calls to StateManager, even from internal direct- // access usage. We could work around this by not redefining, and // just do a subclass approach instead. But this is not a good option, // since it would sacrifice lazy loading and efficient dirty tracking. if (getRedefine() || isFieldAccess(fmd)) { getfield(code, null, fmd.getName()); } else if (getCreateSubclass()) { // property access, and we're not redefining. If we're operating // on an instance that is definitely the same type as 'this', then // call superclass method to bypass tracking. Otherwise, reflect // to both bypass tracking and avoid class verification errors. if (fromSameClass) { Method meth = (Method) fmd.getBackingMember(); code.invokespecial().setMethod(meth); } else { getfield(code, null, fmd.getName()); } } else { // regular enhancement + property access Method meth = (Method) fmd.getBackingMember(); code.invokevirtual().setMethod(PRE + meth.getName(), meth.getReturnType(), meth.getParameterTypes()); } } /** * Store the value at the top of the stack into the field value specified * by fmd. Before this method is called, the data to load will * be on the top of the stack and the object that the data should be loaded * into will be second in the stack. */ private void addSetManagedValueCode(Code code, FieldMetaData fmd) throws NoSuchMethodException { // if redefining, then we must always reflect (or access the field // directly if accessible), since the redefined methods will always // trigger method calls to StateManager, even from internal direct- // access usage. We could work around this by not redefining, and // just do a subclass approach instead. But this is not a good option, // since it would sacrifice lazy loading and efficient dirty tracking. if (getRedefine() || isFieldAccess(fmd)) { putfield(code, null, fmd.getName(), fmd.getDeclaredType()); } else if (getCreateSubclass()) { // property access, and we're not redefining. invoke the // superclass method to bypass tracking. code.invokespecial().setMethod(_managedType.getType(), getSetterName(fmd), void.class, new Class[] { fmd.getDeclaredType() }); } else { // regular enhancement + property access code.invokevirtual().setMethod(PRE + getSetterName(fmd), void.class, new Class[] { fmd.getDeclaredType() }); } } /** * Add the {@link Instruction}s to load the instance to modify onto the * stack, and return it. If forStatic is set, then * code is in an accessor method or another static method; * otherwise, it is in one of the PC-specified methods. * * @return the first instruction added to code. */ private Instruction loadManagedInstance(Code code, boolean forStatic, FieldMetaData fmd) { if (forStatic && isFieldAccess(fmd)) return code.aload().setParam(0); return code.aload().setThis(); } /** * Add the {@link Instruction}s to load the instance to modify onto the * stack, and return it. This method should not be used to load static * fields. * * @return the first instruction added to code. */ private Instruction loadManagedInstance(Code code, boolean forStatic) { return loadManagedInstance(code, forStatic, null); } private int getAccessorParameterOffset(FieldMetaData fmd) { return isFieldAccess(fmd) ? 1 : 0; } /** * Affirms if the given class is using field-based access. */ boolean isPropertyAccess(ClassMetaData meta) { return meta != null && (meta.isMixedAccess() || AccessCode.isProperty(meta.getAccessType())); } /** * Affirms if the given field is using field-based access. */ boolean isPropertyAccess(FieldMetaData fmd) { return fmd != null && AccessCode.isProperty(fmd.getAccessType()); } /** * Affirms if the given field is using method-based access. */ boolean isFieldAccess(FieldMetaData fmd) { return fmd != null && AccessCode.isField(fmd.getAccessType()); } /** * Create the generated getter {@link BCMethod} for fmd. The * calling environment will then populate this method's code block. */ private BCMethod createGetMethod(FieldMetaData fmd) { BCMethod getter; if (isFieldAccess(fmd)) { // static pcGet (XXX inst) BCField field = _pc.getDeclaredField(fmd.getName()); getter = _pc.declareMethod(PRE + "Get" + fmd.getName(), fmd. getDeclaredType().getName(), new String[]{ _pc.getName() }); getter.setAccessFlags(field.getAccessFlags() & ~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE); getter.setStatic(true); getter.setFinal(true); return getter; } // property access: // copy the user's getter method to a new name; we can't just reset // the name, because that will also reset all calls to the method Method meth = (Method) fmd.getBackingMember(); getter = _pc.getDeclaredMethod(meth.getName(), meth.getParameterTypes()); BCMethod newgetter = _pc.declareMethod(PRE + meth.getName(), meth.getReturnType(), meth.getParameterTypes()); newgetter.setAccessFlags(getter.getAccessFlags()); newgetter.makeProtected(); transferCodeAttributes(getter, newgetter); return getter; } /** * Create the generated setter {@link BCMethod} for fmd. The * calling environment will then populate this method's code block. */ private BCMethod createSetMethod(FieldMetaData fmd) { BCMethod setter; if (isFieldAccess(fmd)) { // static void pcSet (XXX inst, value) BCField field = _pc.getDeclaredField(fmd.getName()); setter = _pc.declareMethod(PRE + "Set" + fmd.getName(), void.class, new Class[]{ getType(_meta), fmd.getDeclaredType() }); setter.setAccessFlags(field.getAccessFlags() & ~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE); setter.setStatic(true); setter.setFinal(true); return setter; } // property access: // copy the user's getter method to a new name; we can't just reset // the name, because that will also reset all calls to the method setter = _pc.getDeclaredMethod(getSetterName(fmd), new Class[]{ fmd.getDeclaredType() }); BCMethod newsetter = _pc.declareMethod(PRE + setter.getName(), setter.getReturnName(), setter.getParamNames()); newsetter.setAccessFlags(setter.getAccessFlags()); newsetter.makeProtected(); transferCodeAttributes(setter, newsetter); return setter; } private void addGetEnhancementContractVersionMethod() { // public int getEnhancementContractVersion() BCMethod method = _pc.declareMethod(PRE + "GetEnhancementContractVersion", int.class, null); method.makePublic(); Code code = method.getCode(true); code.constant().setValue(ENHANCER_VERSION); code.ireturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Return the concrete type for the given class, i.e. impl for managed * interfaces */ public Class getType(ClassMetaData meta) { if (meta.getInterfaceImpl() != null) return meta.getInterfaceImpl(); return meta.getDescribedType(); } /** * Move code-related attributes from one method to another. */ private static void transferCodeAttributes(BCMethod from, BCMethod to) { Code code = from.getCode(false); if (code != null) { to.addAttribute(code); from.removeCode(); } Exceptions exceps = from.getExceptions(false); if (exceps != null) to.addAttribute(exceps); } /** * Usage: java org.apache.openjpa.enhance.PCEnhancer [option]* * <class name | .java file | .class file | .jdo file>+ * Where the following options are recognized. *
    *
  • -properties/-p <properties file>: The path to a OpenJPA * properties file containing information as outlined in * {@link Configuration}; optional.
  • *
  • -<property name> <property value>: All bean * properties of the standard OpenJPA {@link OpenJPAConfiguration} can be * set by using their names and supplying a value; for example: *
  • -directory/-d <build directory>: The path to the base * directory where enhanced classes are stored. By default, the * enhancer overwrites the original .class file with the enhanced * version. Use this option to store the generated .class file in * another directory. The package structure will be created beneath * the given directory.
  • *
  • -addDefaultConstructor/-adc [true/t | false/f]: Whether to * add a default constructor to persistent classes missing one, as * opposed to throwing an exception. Defaults to true.
  • *
  • -tmpClassLoader/-tcl [true/t | false/f]: Whether to * load the pre-enhanced classes using a temporary class loader. * Defaults to true. Set this to false when attempting to debug * class loading errors.
  • *
  • -enforcePropertyRestrictions/-epr [true/t | false/f]: * Whether to throw an exception if a PROPERTY access entity appears * to be violating standard property restrictions. Defaults to false.
  • *
* Each additional argument can be either the full class name of the * type to enhance, the path to the .java file for the type, the path to * the .class file for the type, or the path to a .jdo file listing one * or more types to enhance. * If the type being enhanced has metadata, it will be enhanced as a * persistence capable class. If not, it will be considered a persistence * aware class, and all access to fields of persistence capable classes * will be replaced by the appropriate get/set method. If the type * explicitly declares the persistence-capable interface, it will * not be enhanced. Thus, it is safe to invoke the enhancer on classes * that are already enhanced. */ public static void main(String[] args) { Options opts = new Options(); args = opts.setFromCmdLine(args); if (!run(args, opts)) System.err.println(_loc.get("enhance-usage")); } /** * Run the tool. Returns false if invalid options given. Runs against all * the persistence units defined in the resource to parse. */ public static boolean run(final String[] args, Options opts) { return Configurations.runAgainstAllAnchors(opts, new Configurations.Runnable() { public boolean run(Options opts) throws IOException { OpenJPAConfiguration conf = new OpenJPAConfigurationImpl(); try { return PCEnhancer.run(conf, args, opts); } finally { conf.close(); } } }); } /** * Run the tool. Returns false if invalid options given. */ public static boolean run(OpenJPAConfiguration conf, String[] args, Options opts) throws IOException { Flags flags = new Flags(); flags.directory = Files.getFile(opts.removeProperty("directory", "d", null), null); flags.addDefaultConstructor = opts.removeBooleanProperty ("addDefaultConstructor", "adc", flags.addDefaultConstructor); flags.tmpClassLoader = opts.removeBooleanProperty ("tmpClassLoader", "tcl", flags.tmpClassLoader); flags.enforcePropertyRestrictions = opts.removeBooleanProperty ("enforcePropertyRestrictions", "epr", flags.enforcePropertyRestrictions); // for unit testing BytecodeWriter writer = (BytecodeWriter) opts.get( PCEnhancer.class.getName() + "#bytecodeWriter"); Configurations.populateConfiguration(conf, opts); return run(conf, args, flags, null, writer, null); } /** * Enhance the given classes. */ public static boolean run(OpenJPAConfiguration conf, String[] args, Flags flags, MetaDataRepository repos, BytecodeWriter writer, ClassLoader loader) throws IOException { if (loader == null) loader = conf.getClassResolverInstance(). getClassLoader(PCEnhancer.class, null); if (flags.tmpClassLoader) loader = AccessController.doPrivileged(J2DoPrivHelper .newTemporaryClassLoaderAction(loader)); if (repos == null) { repos = conf.newMetaDataRepositoryInstance(); repos.setSourceMode(MetaDataRepository.MODE_META); } Log log = conf.getLog(OpenJPAConfiguration.LOG_TOOL); Collection classes; if (args == null || args.length == 0) { classes = repos.getPersistentTypeNames(true, loader); if (classes == null) { log.warn(_loc.get("no-class-to-enhance")); return false; } } else { ClassArgParser cap = conf.getMetaDataRepositoryInstance(). getMetaDataFactory().newClassArgParser(); cap.setClassLoader(loader); classes = new HashSet(); for (int i = 0; i < args.length; i++) classes.addAll(Arrays.asList(cap.parseTypes(args[i]))); } Project project = new Project(); BCClass bc; PCEnhancer enhancer; Collection persAwareClasses = new HashSet(); int status; for (Iterator itr = classes.iterator(); itr.hasNext();) { Object o = itr.next(); if (log.isInfoEnabled()) log.info(_loc.get("enhance-running", o)); if (o instanceof String) bc = project.loadClass((String) o, loader); else bc = project.loadClass((Class) o); enhancer = new PCEnhancer(conf, bc, repos, loader); if (writer != null) enhancer.setBytecodeWriter(writer); enhancer.setDirectory(flags.directory); enhancer.setAddDefaultConstructor(flags.addDefaultConstructor); status = enhancer.run(); if (status == ENHANCE_NONE) { if (log.isTraceEnabled()) log.trace(_loc.get("enhance-norun")); } else if (status == ENHANCE_INTERFACE) { if (log.isTraceEnabled()) log.trace(_loc.get("enhance-interface")); } else if (status == ENHANCE_AWARE) { persAwareClasses.add(o); enhancer.record(); } else { enhancer.record(); } project.clear(); } if(log.isInfoEnabled() && !persAwareClasses.isEmpty()){ log.info(_loc.get("pers-aware-classes", persAwareClasses.size(), persAwareClasses)); } return true; } /** * Run flags. */ public static class Flags { public File directory = null; public boolean addDefaultConstructor = true; public boolean tmpClassLoader = true; public boolean enforcePropertyRestrictions = false; } /** * Plugin interface for additional enhancement. */ public static interface AuxiliaryEnhancer { public void run (BCClass bc, ClassMetaData meta); public boolean skipEnhance(BCMethod m); } private void addGetIDOwningClass() throws NoSuchMethodException { BCMethod method = _pc.declareMethod(PRE + "GetIDOwningClass", Class.class, null); Code code = method.getCode(true); code.classconstant().setClass(getType(_meta)); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * This static public worker method detects and logs any Entities that may have been enhanced at build time by * a version of the enhancer that is older than the current version. * * @param cls * - A non-null Class implementing org.apache.openjpa.enhance.PersistenceCapable. * @param log * - A non-null org.apache.openjpa.lib.log.Log. * * @throws - IllegalStateException if cls doesn't implement org.apache.openjpa.enhance.PersistenceCapable. * * @return true if the provided Class is down level from the current PCEnhancer.ENHANCER_VERSION. False * otherwise. */ public static boolean checkEnhancementLevel(Class cls, Log log) { if (cls == null || log == null) { return false; } PersistenceCapable pc = PCRegistry.newInstance(cls, null, false); if (pc == null) { return false; } if (pc.pcGetEnhancementContractVersion() < PCEnhancer.ENHANCER_VERSION) { log.info(_loc.get("down-level-enhanced-entity", new Object[] { cls.getName(), pc.pcGetEnhancementContractVersion(), PCEnhancer.ENHANCER_VERSION })); return true; } return false; } /** * Read the optimizedIdCopy value from the config (if available) */ private void configureOptimizeIdCopy() { if (_repos != null && _repos.getConfiguration() != null) { _optimizeIdCopy = _repos.getConfiguration().getOptimizeIdCopy(); } } /* * Cycles through all primary keys verifying whether they can and should * be used for faster oid copy. The field must be private and must * not have a public setter. If this is the case, the list of pk fields is * returned. If not, returns null. */ private ArrayList optimizeIdCopy(Class oidType, FieldMetaData[] fmds) { // collect all object id fields and verify they // a) have a private field // b) do not have a public setter ArrayList pkFields = new ArrayList(); // build list of primary key fields for (int i = 0; i < fmds.length; i++) { if (!fmds[i].isPrimaryKey()) continue; // optimizing copy with PC type not (yet) supported if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) { return null; } String name = fmds[i].getName(); Field fld = Reflection.findField(oidType, name, false); if (fld == null || Modifier.isPublic(fld.getModifiers())) { return null; } Method setter = Reflection.findSetter(oidType, name, false); if (setter == null || !Modifier.isPublic(setter.getModifiers())) { pkFields.add(i); } else { return null; } } return pkFields.size() > 0 ? pkFields : null; } /* * Cycles through all constructors of an IdClass and examines the instructions to find * a matching constructor for the provided pk fields. If a match is found, it returns * the order (relative to the field metadata) of the constructor parameters. If a match * is not found, returns null. */ private int[] getIdClassConstructorParmOrder(Class oidType, ArrayList pkfields, FieldMetaData[] fmds) { Project project = new Project(); BCClass bc = project.loadClass(oidType); BCMethod[] methods = bc.getDeclaredMethods(""); if (methods == null || methods.length == 0) { return null; } int parmOrder[] = new int[pkfields.size()]; for (BCMethod method : methods) { // constructor must be public if (!method.isPublic()) { continue; } Class[] parmTypes = method.getParamTypes(); // make sure the constructors have the same # of parms as // the number of pk fields if (parmTypes.length != pkfields.size()) { continue; } int parmOrderIndex = 0; Code code = method.getCode(false); Instruction[] ins = code.getInstructions(); for (int i = 0; i < ins.length; i++) { if (ins[i] instanceof PutFieldInstruction) { PutFieldInstruction pfi = (PutFieldInstruction)ins[i]; for (int j = 0; j < pkfields.size(); j++) { int fieldNum = pkfields.get(j); // Compare the field being set with the current pk field String parmName = fmds[fieldNum].getName(); Class parmType = fmds[fieldNum].getType(); if (parmName.equals(pfi.getFieldName())) { // backup and examine the load instruction parm if (i > 0 && ins[i-1] instanceof LoadInstruction) { LoadInstruction li = (LoadInstruction)ins[i-1]; // Get the local index from the instruction. This will be the index // of the constructor parameter. must be less than or equal to the // max parm index to prevent from picking up locals that could have // been produced within the constructor. Also make sure the parm type // matches the fmd type int parm = li.getLocal(); if (parm <= pkfields.size() && parmTypes[parm-1].equals(parmType)) { parmOrder[parmOrderIndex] = fieldNum; parmOrderIndex++; } } else { // Some other instruction found. can't make a determination of which local/parm // is being used on the putfield. break; } } } } } if (parmOrderIndex == pkfields.size()) { return parmOrder; } } return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/FieldSupplier.java0000644000000000000000000000366012133327272027032 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * Supplies persistent field values. */ public interface FieldSupplier { /** * Return the value of the given field. */ boolean fetchBooleanField(int fieldIndex); /** * Return the value of the given field. */ char fetchCharField(int fieldIndex); /** * Return the value of the given field. */ byte fetchByteField(int fieldIndex); /** * Return the value of the given field. */ short fetchShortField(int fieldIndex); /** * Return the value of the given field. */ int fetchIntField(int fieldIndex); /** * Return the value of the given field. */ long fetchLongField(int fieldIndex); /** * Return the value of the given field. */ float fetchFloatField(int fieldIndex); /** * Return the value of the given field. */ double fetchDoubleField(int fieldIndex); /** * Return the value of the given field. */ String fetchStringField(int fieldIndex); /** * Return the value of the given field. */ Object fetchObjectField (int fieldIndex); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancerAgent.java0000644000000000000000000001640512133327272027211 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.lang.instrument.Instrumentation; import java.security.AccessController; import java.util.List; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.util.ClassResolver; /** *

* Java agent that makes persistent classes work with OpenJPA at runtime. This * is achieved by either running the enhancer on the classes as they are loaded, * or by redefining the classes on the fly. The agent is launched at JVM startup * from the command line: *

* *

* java -javaagent:openjpa.jar[=<options>] The options string * should be formatted as a OpenJPA plugin, and may contain any properties * understood by the OpenJPA enhancer or any configuration properties. For * example: *

* *

* java -javaagent:openjpa.jar *

* *

* By default, if specified, the agent runs the OpenJPA enhancer on all classes * listed in the first persistence unit as they are loaded, and redefines all * other persistent classes when they are encountered. To disable enhancement at * class-load time and rely solely on the redefinition logic, set the * ClassLoadEnhancement flag to false. To disable redefinition and rely solely * on pre-deployment or class-load enhancement, set the RuntimeRedefinition flag * to false. *

* *

* java -javaagent:openjpa.jar=ClassLoadEnhancement=false *

* * @author Abe White * @author Patrick Linskey */ public class PCEnhancerAgent { private static boolean loadAttempted = false; private static boolean loadSuccessful = false; private static boolean disableDynamicAgent = false; /** * @return True if the Agent has ran successfully. False otherwise. */ public static synchronized boolean getLoadSuccessful() { return loadSuccessful; } /** * @return True if the dynamic agent was disabled via configuration. */ public static void disableDynamicAgent(){ disableDynamicAgent=true; } /** * @param log * @return True if the agent is loaded successfully */ public static synchronized boolean loadDynamicAgent(Log log) { if (loadAttempted == false && disableDynamicAgent == false) { Instrumentation inst = InstrumentationFactory.getInstrumentation(log); if (inst != null) { premain("", inst); return true; } // If we successfully get the Instrumentation, we will call premain // where loadAttempted will be set to true. This case is the path // where we were unable to get Instrumentation so we need to set the // loadAttempted flag to true. We do this so we will only run // through this code one time. loadAttempted = true; } return false; } public static void premain(String args, Instrumentation inst) { // If the enhancer has already completed, noop. This can happen // if runtime enhancement is specified via javaagent, and // openJPA tries to dynamically enhance. // The agent will be disabled when running in an application // server. synchronized (PCEnhancerAgent.class) { if (loadAttempted == true) { return; } // See the comment in loadDynamicAgent as to why we set this to true // in multiple places. loadAttempted = true; } Options opts = Configurations.parseProperties(args); if (opts.containsKey("ClassLoadEnhancement") || opts.containsKey("classLoadEnhancement")) { if (opts.getBooleanProperty( "ClassLoadEnhancement", "classLoadEnhancement", true)) registerClassLoadEnhancer(inst, opts); } else if (opts.containsKey("RuntimeEnhancement") || opts.containsKey("runtimeEnhancement")) { // Deprecated property setting if (opts.getBooleanProperty( "RuntimeEnhancement", "runtimeEnhancement", true)) registerClassLoadEnhancer(inst, opts); } else { // if neither is set, then we should be turning it on. We need this // logic instead of just a getBooleanProperty() because of the // backwards-compat logic flow. registerClassLoadEnhancer(inst, opts); } if (opts.getBooleanProperty( "RuntimeRedefinition", "runtimeRedefinition", true)) { InstrumentationFactory.setInstrumentation(inst); } else { InstrumentationFactory.setDynamicallyInstallAgent(false); } loadSuccessful = true; } private static void registerClassLoadEnhancer(Instrumentation inst, Options opts) { List anchors = Configurations. getFullyQualifiedAnchorsInPropertiesLocation(opts); for (String a : anchors) { Options clonedOptions = (Options) opts.clone(); clonedOptions.setProperty("properties", a); OpenJPAConfiguration conf = new OpenJPAConfigurationImpl(); Configurations.populateConfiguration(conf, clonedOptions); // don't allow connections conf.setConnectionUserName(null); conf.setConnectionPassword(null); conf.setConnectionURL(null); conf.setConnectionDriverName(null); conf.setConnectionFactoryName(null); // set single class resolver final ClassLoader tmpLoader = AccessController .doPrivileged(J2DoPrivHelper .newTemporaryClassLoaderAction(AccessController .doPrivileged(J2DoPrivHelper.getContextClassLoaderAction()) )); conf.setClassResolver(new ClassResolver() { public ClassLoader getClassLoader(Class context, ClassLoader env) { return tmpLoader; } }); conf.setReadOnly(Configuration.INIT_STATE_FREEZING); conf.instantiateAll(); // avoid threading issues PCClassFileTransformer transformer = new PCClassFileTransformer (conf.newMetaDataRepositoryInstance(), clonedOptions, tmpLoader); inst.addTransformer(transformer); conf.close(); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AttributeTranslator.java0000644000000000000000000000232312133327272030273 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * Instances of this interface can convert a positional index for a * {@link FieldMetaData} that uses property access into the underlying * field name. Instances of {@link DynamicPersistenceCapable} for types * that use property access will implement this interface. * * @since 1.0.0 */ public interface AttributeTranslator { public String pcAttributeIndexToFieldName(int i); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCRegistry.java0000644000000000000000000002264112133327272026316 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.Map; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.ReferenceMap; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashSet; import org.apache.openjpa.util.UserException; /** * Tracks registered persistence-capable classes. * * @since 0.4.0 * @author Abe White */ public class PCRegistry { // DO NOT ADD ADDITIONAL DEPENDENCIES TO THIS CLASS private static final Localizer _loc = Localizer.forPackage(PCRegistry.class); // map of persistent classes to meta structures; weak so the VM can GC classes private static final Map,Meta> _metas = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD); // register class listeners // Weak reference prevents OutOfMemeoryError as described in OPENJPA-2042 private static final Collection _listeners = new ConcurrentReferenceHashSet( ConcurrentReferenceHashSet.WEAK); /** * Register a {@link RegisterClassListener}. */ public static void addRegisterClassListener(RegisterClassListener rcl) { if (rcl == null) return; // we have to be positive that every listener gets notified for // every class, so lots of locking synchronized (_listeners) { _listeners.add(rcl); } synchronized (_metas) { for (Class cls : _metas.keySet()) rcl.register(cls); } } /** * Removes a {@link RegisterClassListener}. */ public static boolean removeRegisterClassListener(RegisterClassListener rcl) { synchronized (_listeners) { return _listeners.remove(rcl); } } /** * Get the field names for a PersistenceCapable class. */ public static String[] getFieldNames(Class pcClass) { Meta meta = getMeta(pcClass); return meta.fieldNames; } /** * Get the field types for a PersistenceCapable class. */ public static Class[] getFieldTypes(Class pcClass) { Meta meta = getMeta(pcClass); return meta.fieldTypes; } /** * Return the persistent superclass for a PersistenceCapable * class, or null if none. The superclass may or may not implement * {@link PersistenceCapable}, depending on the access type of the class. */ public static Class getPersistentSuperclass(Class pcClass) { Meta meta = getMeta(pcClass); return meta.pcSuper; } /** * Create a new instance of the class and assign its state manager. * The new instance has its flags set to LOAD_REQUIRED. */ public static PersistenceCapable newInstance(Class pcClass, StateManager sm, boolean clear) { Meta meta = getMeta(pcClass); return (meta.pc == null) ? null : meta.pc.pcNewInstance(sm, clear); } /** * Create a new instance of the class and assign its state manager and oid. * The new instance has its flags set to LOAD_REQUIRED. */ public static PersistenceCapable newInstance(Class pcClass, StateManager sm, Object oid, boolean clear) { Meta meta = getMeta(pcClass); return (meta.pc == null) ? null : meta.pc.pcNewInstance(sm, oid, clear); } /** * Return the persistence-capable type for type. This might * be a generated subclass of type. * * @since 1.1.0 */ public static Class getPCType(Class type) { Meta meta = getMeta(type); return (meta.pc == null) ? null : meta.pc.getClass(); } /** * Create a new identity object for the given * PersistenceCapable class. */ public static Object newObjectId(Class pcClass) { Meta meta = getMeta(pcClass); return (meta.pc == null) ? null : meta.pc.pcNewObjectIdInstance(); } /** * Create a new identity object for the given * PersistenceCapable class, using the String * form of the constructor. */ public static Object newObjectId(Class pcClass, String str) { Meta meta = getMeta(pcClass); return (meta.pc == null) ? null : meta.pc.pcNewObjectIdInstance(str); } /** * Return the alias for the given type. */ public static String getTypeAlias(Class pcClass) { return getMeta(pcClass).alias; } /** * Copy fields from an outside source to the key fields in the identity * object. */ public static void copyKeyFieldsToObjectId(Class pcClass, FieldSupplier fm, Object oid) { Meta meta = getMeta(pcClass); if (meta.pc == null) throw new UserException(_loc.get("copy-no-id", pcClass)); meta.pc.pcCopyKeyFieldsToObjectId(fm, oid); } /** * Copy fields to an outside source from the key fields in the identity * object. */ public static void copyKeyFieldsFromObjectId(Class pcClass, FieldConsumer fm, Object oid) { Meta meta = getMeta(pcClass); if (meta.pc == null) throw new UserException(_loc.get("copy-no-id", pcClass)); meta.pc.pcCopyKeyFieldsFromObjectId(fm, oid); } /** * Register metadata by class. * * @param fieldTypes managed field types * @param fieldFlags managed field flags * @param sup the most immediate persistent superclass * @param pcClass the PersistenceCapable class * @param fieldNames managed field names * @param alias the class alias * @param pc an instance of the class, if not abstract */ public static void register(Class pcClass, String[] fieldNames, Class[] fieldTypes, byte[] fieldFlags, Class sup, String alias, PersistenceCapable pc) { if (pcClass == null) throw new NullPointerException(); // we have to be positive that every listener gets notified for // every class, so lots of locking Meta meta = new Meta(pc, fieldNames, fieldTypes, sup, alias); synchronized (_metas) { _metas.put(pcClass, meta); } synchronized (_listeners) { for (RegisterClassListener r : _listeners){ if (r != null) { r.register(pcClass); } } } } /** * De-Register all metadata associated with the given ClassLoader. * Allows ClassLoaders to be garbage collected. * * @param cl the ClassLoader */ public static void deRegister(ClassLoader cl) { synchronized (_metas) { for (Class pcClass : _metas.keySet()) { if (pcClass.getClassLoader() == cl) { _metas.remove(pcClass); } } } } /** * Returns a collection of class objects of the registered * persistence-capable classes. */ public static Collection> getRegisteredTypes() { return Collections.unmodifiableCollection(_metas.keySet()); } /** * Returns true if the given class is already registered. */ public static boolean isRegistered(Class cls) { return _metas.containsKey(cls); } /** * Look up the metadata for a PersistenceCapable class. */ private static Meta getMeta(Class pcClass) { Meta ret = (Meta) _metas.get(pcClass); if (ret == null) throw new IllegalStateException(_loc.get("no-meta", pcClass). getMessage()); return ret; } /** * Listener for persistent class registration events. */ public static interface RegisterClassListener { public void register(Class cls); } /** * This is a helper class to manage metadata per persistence-capable class. */ private static class Meta { public final PersistenceCapable pc; public final String[] fieldNames; public final Class[] fieldTypes; public final Class pcSuper; public final String alias; public Meta(PersistenceCapable pc, String[] fieldNames, Class[] fieldTypes, Class pcSuper, String alias) { this.pc = pc; this.fieldNames = fieldNames; this.fieldTypes = fieldTypes; this.pcSuper = pcSuper; this.alias = alias; } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicPersistenceCapable.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicPersistenceCapable0000644000000000000000000000204612133327272030401 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * Instances that implement this marker interface are dynamically-generated * subtypes of managed types that were loaded before being enhanced. * * @since 1.0.0 */ public interface DynamicPersistenceCapable { } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/CodeGenerator.java0000644000000000000000000005241312133327272027004 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.File; import java.io.IOException; import java.io.Writer; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.WordUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.util.CodeFormat; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.lib.util.ParameterTemplate; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import serp.util.Strings; /** * Generates Java class code from metadata. * * @author Abe White * @author Stephen Kim * @since 0.3.0 * @nojavadoc */ public class CodeGenerator { private File _dir = null; private CodeFormat _format = null; private ClassMetaData _meta = null; private Class _type = null; private ParameterTemplate _code = null; /** * Constructor. Supply configuration and class to generate code for. */ public CodeGenerator(OpenJPAConfiguration conf, Class type) { this(conf.newMetaDataRepositoryInstance(). getMetaData(type, null, true)); } /** * Constructor. Supply configuration and metadata to generate code for. */ public CodeGenerator(ClassMetaData meta) { _meta = meta; _type = meta.getDescribedType(); } /** * The directory to write source to. Defaults to the current directory. * If the given directory does not match the package of the metadata, the * package structure will be created below the directory. */ public File getCodeDirectory() { return _dir; } /** * The directory to write source to. Defaults to the current directory. * If the given directory does not match the package of the metadata, the * package structure will be created below the directory. */ public void setDirectory(File dir) { _dir = dir; } /** * The code formatter for the generated Java code. */ public CodeFormat getCodeFormat() { return _format; } /** * Set the code formatter for the generated Java code. */ public void setCodeFormat(CodeFormat format) { _format = format; } /** * Return the type being generated. */ public Class getType() { return _type; } /** * Return metadata for the type being generated. */ public ClassMetaData getMetaData() { return _meta; } /** * Return the generated code, or null if {@link #generateCode} has not * been called. */ public String getCode() { return (_code == null) ? null : _code.toString(); } /** * Writes the generated code to the proper directory. */ public void generateCode() { // setup parameters String className = Strings.getClassName(_type); String packageName = Strings.getPackageName(_type); String packageDec = ""; if (packageName.length() > 0) packageDec = "package " + packageName + ";"; String extendsDec = ""; String extendsName = ""; if (!_type.getSuperclass().getName().equals(Object.class.getName())) { extendsName = Strings.getClassName(_type.getSuperclass()); extendsDec = "extends " + extendsName; } String imports = getImports(); String[] fieldCode = getFieldCode(); String constructor = getConstructor(); // get code template _code = new ParameterTemplate(); String codeStr = getClassCode(); if (codeStr != null) { _code.append(codeStr); _code.setParameter("packageDec", packageDec); _code.setParameter("imports", imports); _code.setParameter("className", className); _code.setParameter("extendsDec", extendsDec); _code.setParameter("constructor", constructor); _code.setParameter("fieldDecs", fieldCode[0]); _code.setParameter("fieldCode", fieldCode[1]); } else _code.append(getClassCode(packageDec, imports, className, extendsName, constructor, fieldCode[0], fieldCode[1])); } /** * Write the generated code to the proper file. */ public void writeCode() throws IOException { if (_code == null) return; File file = getFile(); Files.backup(file, false); _code.write(file); } /** * Write the code to the specified {@link Writer}. */ public void writeCode(Writer out) throws IOException { if (_code == null) return; _code.write(out); } /** * Return the necessary imports for the class. */ private String getImports() { Set pkgs = getImportPackages(); CodeFormat imports = newCodeFormat(); String base = Strings.getPackageName(_type); String pkg; for (Iterator itr = pkgs.iterator(); itr.hasNext();) { pkg = (String) itr.next(); if (pkg.length() > 0 && !"java.lang".equals(pkg) && !base.equals(pkg)) { if (imports.length() > 0) imports.endl(); imports.append("import ").append(pkg).append(".*;"); } } return imports.toString(); } /** * Returns the set of packages that needs to be imported for this code. */ public Set getImportPackages() { Set pkgs = new TreeSet(); pkgs.add(Strings.getPackageName(_type.getSuperclass())); FieldMetaData[] fields = _meta.getDeclaredFields(); for (int i = 0; i < fields.length; i++) pkgs.add(Strings.getPackageName(fields[i].getDeclaredType())); fields = _meta.getPrimaryKeyFields(); for (int i = 0; i < fields.length; i++) pkgs.add(Strings.getPackageName(fields[i].getDeclaredType())); return pkgs; } /** * Return code for a primary key constructor for the given class. */ private String getConstructor() { FieldMetaData[] fields = _meta.getPrimaryKeyFields(); if (fields.length == 0) return ""; CodeFormat cons = newCodeFormat(); CodeFormat body = newCodeFormat(); // public ( cons.tab().append("public ").append(Strings.getClassName(_type)); cons.openParen(true); // append args to constructor, and build up body at same time String propertyName; String fieldType; for (int i = 0; i < fields.length; i++) { propertyName = fields[i].getName(); if (propertyName.startsWith("_")) propertyName = propertyName.substring(1); fieldType = Strings.getClassName(fields[i].getDeclaredType()); if (i > 0) cons.append(", "); cons.append(fieldType).append(" ").append(propertyName); if (_meta.getPCSuperclass() == null) { if (i > 0) body.endl(); body.tab(2); if (propertyName.equals(fields[i].getName())) body.append("this."); body.append(fields[i].getName()); body.append(" = ").append(propertyName).append(";"); } else { // super (...); if (i == 0) body.tab(2).append("super").openParen(true); else body.append(", "); body.append(propertyName); if (i == fields.length - 1) body.closeParen().append(";"); } } cons.closeParen(); cons.openBrace(2).endl(); cons.append(body.toString()).endl(); cons.closeBrace(2); return cons.toString(); } /** * Returns the Java declaration and access method code for all declared * fields. */ private String[] getFieldCode() { CodeFormat decs = newCodeFormat(); CodeFormat code = newCodeFormat(); FieldMetaData[] fields = _meta.getDeclaredFields(); for (int i = 0; i < fields.length; i++) appendFieldCode(fields[i], decs, code); fields = _meta.getDeclaredUnmanagedFields(); for (int i = 0; i < fields.length; i++) appendFieldCode(fields[i], decs, code); return new String[]{ decs.toString(), code.toString() }; } /** * Append the declaration and code for the given field to the given buffers. */ private void appendFieldCode(FieldMetaData fmd, CodeFormat decs, CodeFormat code) { String fieldName = fmd.getName(); String capFieldName = StringUtils.capitalize(fieldName); String propertyName = fieldName; if (propertyName.startsWith("_")) propertyName = propertyName.substring(1); String fieldType = Strings.getClassName(fmd.getDeclaredType()); String keyType = null; String elementType = null; String paramType = ""; if (useGenericCollections()) { if (fmd.getDeclaredTypeCode() == JavaTypes.COLLECTION) { Class elmCls = fmd.getElement().getDeclaredType(); elementType = Strings.getClassName(elmCls); paramType = decs.getParametrizedType( new String[] {elementType}); } else if (fmd.getDeclaredTypeCode() == JavaTypes.MAP) { Class keyCls = fmd.getKey().getDeclaredType(); Class elmCls = fmd.getElement().getDeclaredType(); keyType = Strings.getClassName(keyCls); elementType = Strings.getClassName(elmCls); paramType = decs.getParametrizedType( new String[] {keyType, elementType}); } } String fieldValue = getInitialValue(fmd); if (fieldValue == null) { if ("Set".equals(fieldType)) fieldValue = "new HashSet" + paramType + decs.getParens(); else if ("TreeSet".equals(fieldType)) fieldValue = "new TreeSet" + paramType + decs.getParens(); else if ("Collection".equals(fieldType)) fieldValue = "new ArrayList" + paramType + decs.getParens(); else if ("Map".equals(fieldType)) fieldValue = "new HashMap" + paramType + decs.getParens(); else if ("TreeMap".equals(fieldType)) fieldValue = "new TreeMap" + paramType + decs.getParens(); else if (fmd.getDeclaredTypeCode() == JavaTypes.COLLECTION || fmd.getDeclaredTypeCode() == JavaTypes.MAP) fieldValue = "new " + fieldType + paramType + decs.getParens(); else fieldValue = ""; } if (fieldValue.length() > 0) fieldValue = " = " + fieldValue; boolean fieldAccess = !usePropertyBasedAccess(); String custom = getDeclaration(fmd); if (decs.length() > 0) decs.endl(); ParameterTemplate templ; if (custom != null) { templ = new ParameterTemplate(); templ.append(custom); templ.setParameter("fieldName", fieldName); templ.setParameter("capFieldName", capFieldName); templ.setParameter("propertyName", propertyName); templ.setParameter("fieldType", fieldType); templ.setParameter("keyType", keyType); templ.setParameter("elementType", elementType); templ.setParameter("fieldValue", fieldValue); decs.append(templ.toString()); } else { if (fieldAccess) writeAnnotations(decs, getFieldAnnotations(fmd), 1); decs.tab().append("private ").append(fieldType). append(paramType).append(" ").append(fieldName). append(fieldValue).append(";"); if (fieldAccess) decs.endl(); } custom = getFieldCode(fmd); if (code.length() > 0) code.afterSection(); if (custom != null) { templ = new ParameterTemplate(); templ.append(custom); templ.setParameter("fieldName", fieldName); templ.setParameter("capFieldName", capFieldName); templ.setParameter("propertyName", propertyName); templ.setParameter("fieldType", fieldType); templ.setParameter("keyType", keyType); templ.setParameter("elementType", elementType); templ.setParameter("fieldValue", fieldValue); code.append(templ.toString()); } else { // getter if (!fieldAccess) writeAnnotations(code, getFieldAnnotations(fmd), 1); code.tab().append("public ").append(fieldType).append(paramType). append(" "); if ("boolean".equalsIgnoreCase(fieldType)) code.append("is"); else code.append("get"); code.append(capFieldName).parens(); code.openBrace(2).endl(); code.tab(2).append("return ").append(fieldName). append(";").endl(); code.closeBrace(2).afterSection(); // setter code.tab().append("public void set").append(capFieldName); code.openParen(true).append(fieldType).append(paramType). append(" ").append(propertyName).closeParen(); code.openBrace(2).endl(); code.tab(2); if (propertyName.equals(fieldName)) code.append("this."); code.append(fieldName).append(" = ").append(propertyName). append(";").endl(); code.closeBrace(2); } } /** * Return a code template for a generated Java class. */ private String getClassCode(String packageDec, String imports, String className, String extendsName, String constructor, String fieldDecs, String fieldCode) { CodeFormat code = newCodeFormat(); if (packageDec.length() > 0) code.append(packageDec).afterSection(); if (imports.length() > 0) code.append(imports).afterSection(); code.append("/**").endl(). append(" * Auto-generated by:").endl(). append(" * ").append(getClass().getName()).endl(). append(" */").endl(); writeAnnotations(code, getClassAnnotations(), 0); code.append("public class ").append(className); if (extendsName.length() > 0) code.extendsDec(1).append(" ").append(extendsName); openClassBrace(code); if (fieldDecs.length() > 0) code.append(fieldDecs).afterSection(); // default constructor code.tab().append("public ").append(className).parens(); code.openBrace(2).endl().closeBrace(2); if (constructor.length() > 0) code.afterSection().append(constructor); if (fieldCode.length() > 0) code.afterSection().append(fieldCode); code.endl(); closeClassBrace(code); return code.toString(); } /** * Appends the given list of annotations to code buffer. */ private void writeAnnotations (CodeFormat code, List ann, int tabLevel) { if (ann == null || ann.size() == 0) return; for (Iterator i = ann.iterator(); i.hasNext();) { if (tabLevel > 0) code.tab(tabLevel); String s = (String) i.next(); code.append(s).endl(); } } /** * Append the opening code-level brace to the code; this can be * overridden to add code to the top of the class. */ protected void openClassBrace(CodeFormat code) { code.openBrace(1).endl(); } /** * Append the closing code-level brace to the code; this can be * overridden to add code to the bottom of the class. */ protected void closeClassBrace(CodeFormat code) { code.closeBrace(1); } /** * Return Java file to write to. */ public File getFile() { String packageName = Strings.getPackageName(_type); String fileName = Strings.getClassName(_type) + ".java"; File dir = Files.getPackageFile(_dir, packageName, true); return new File(dir, fileName); } /** * Return a copy of the internal code format. */ protected CodeFormat newCodeFormat() { if (_format == null) return new CodeFormat(); return (CodeFormat) _format.clone(); } /** * Return a code template for the given class, or null to use the standard * system-generated Java code. To facilitate template reuse, the * following parameters can appear in the template; the proper values * will be subtituted by the system: *
    *
  • ${packageDec}: The package declaration, in the form * "package <package name >;", or empty string if no package.
  • *
  • ${imports}: Imports for the packages used by the declared * field types.
  • *
  • ${className}: The name of the class, without package.
  • *
  • ${extendsDec}: Extends declaration, in the form * "extends <superclass>", or empty string if no superclass.
  • *
  • ${constructor}: A constructor that takes in all primary key fields * of the class, or empty string if the class uses datastore identity.
  • *
  • ${fieldDecs}: Declarations of all the declared fields.
  • *
  • ${fieldCode}: Get/set methods for all the declared fields.
  • *
Returns null by default. */ protected String getClassCode() { return null; } /** * Return code for the initial value for the given field, or null to use * the default generated by the system. Returns null by default. */ protected String getInitialValue(FieldMetaData field) { return null; } /** * Return a code template for the declaration of the given field, or null * to use the system-generated default Java code. * To facilitate template reuse, the following parameters can appear in * your template; the proper values will be subtituted by the system: *
    *
  • ${fieldName}: The name of the field.
  • *
  • ${capFieldName}: The capitalized field name.
  • *
  • ${propertyName}: The field name without leading '_', if any.
  • *
  • ${fieldType}: The field's type name.
  • *
  • ${keyType}: Key type name for maps, null otherwise.
  • *
  • ${elementType}: Element type name for collections, null otherwise. *
  • *
  • ${fieldValue}: The field's initial value, in the form * " = <value>", or empty string if none.
  • *
Returns null by default. */ protected String getDeclaration(FieldMetaData field) { return null; } /** * Return a code template for the get/set methods of the given field, or * null to use the system-generated default Java code. * To facilitate template reuse, the following parameters can appear in * your template; the proper values will be subtituted by the system: *
    *
  • ${fieldName}: The name of the field.
  • *
  • ${capFieldName}: The capitalized field name.
  • *
  • ${propertyName}: The field name without leading '_', if any.
  • *
  • ${fieldType}: The field's type name.
  • *
  • ${keyType}: Key type name for maps, null otherwise.
  • *
  • ${elementType}: Element type name for collections, null otherwise. *
  • *
  • ${fieldValue}: The field's initial value, in the form * "= <value>", or empty string if none.
  • *
*/ protected String getFieldCode (FieldMetaData field) { return null; } /** * Whether to use property-based access on generated code. * Defaults to false (field-based). */ protected boolean usePropertyBasedAccess () { return false; } /** * Return class-level annotations. Returns null by default. */ protected List getClassAnnotations() { return null; } /** * Return field-level annotations. Returns null by default. */ protected List getFieldAnnotations(FieldMetaData field) { return null; } /** * Whether to use generic collections on one-to-many and many-to-many * relations instead of untyped collections. * * Override in descendants to change default behavior. */ protected boolean useGenericCollections() { return false; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorage.java0000644000000000000000000000642712133327272027200 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * Interface for dynamically generated classes. Certain getters/setters * may either return null or throw an exception depending on the * {@link DynamicStorageGenerator}'s field policy. * * @author Steve Kim * @nojavadoc * @since 0.3.2.0 */ public interface DynamicStorage { /** * Return the number of fields, regardless of type */ public int getFieldCount(); /** * Return the number of object fields */ public int getObjectCount(); /** * Factory method for getting new instances of the same definition. */ public DynamicStorage newInstance(); /** * Get the boolean at the given index. */ public boolean getBoolean(int field); /** * Set the boolean at the given index. */ public void setBoolean(int field, boolean val); /** * Get the byte at the given index. */ public byte getByte(int field); /** * Set the byte at the given index. */ public void setByte(int field, byte val); /** * Get the char at the given index. */ public char getChar(int field); /** * Set the char at the given index. */ public void setChar(int field, char val); /** * Get the double at the given index. */ public double getDouble(int field); /** * Set the double at the given index. */ public void setDouble(int field, double val); /** * Get the float at the given index. */ public float getFloat(int field); /** * Set the float at the given index. */ public void setFloat(int field, float val); /** * Get the int at the given index. */ public int getInt(int field); /** * Set the int at the given index. */ public void setInt(int field, int val); /** * Get the long at the given index. */ public long getLong(int field); /** * Set the long at the given index. */ public void setLong(int field, long val); /** * Get the short at the given index. */ public short getShort(int field); /** * Set the short at the given index. */ public void setShort(int field, short val); /** * Get the object at the given index. */ public Object getObject(int field); /** * Set the object at the given index. */ public void setObject(int field, Object val); /** * Ensure object capacity */ public void initialize (); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ClassRedefiner.java0000644000000000000000000001311612133327272027151 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.lang.instrument.ClassDefinition; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; import java.lang.reflect.Method; import java.security.ProtectionDomain; import java.util.Map; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.JavaVersions; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InternalException; /** * Redefines the method bodies of existing classes. Supports Java 5 VMs that * have a java agent installed on the command line as well as newer VMs without * any -javaagent flag. * * @since 1.0.0 */ public class ClassRedefiner { private static final Localizer _loc = Localizer.forPackage(ClassRedefiner.class); private static Boolean _canRedefine = null; /** * For each element in classes, this method will redefine * all the element's methods such that field accesses are intercepted * in-line. If {@link #canRedefineClasses()} returns false, * this method is a no-op. */ public static void redefineClasses(OpenJPAConfiguration conf, final Map,byte[]> classes) { Log log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE); if (classes == null || classes.size() == 0 || !canRedefineClasses(log)) return; Instrumentation inst = null; ClassFileTransformer t = null; try { inst = InstrumentationFactory.getInstrumentation(log); Class[] array = classes.keySet().toArray(new Class[classes.size()]); if (JavaVersions.VERSION >= 6) { log.trace(_loc.get("retransform-types", classes.keySet())); t = new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String clsName, Class classBeingRedefined, ProtectionDomain pd, byte[] classfileBuffer) { return classes.get(classBeingRedefined); } }; // these are Java 6 methods, and we don't have a Java 6 build // module yet. The cost of reflection here is negligible // compared to the redefinition / enhancement costs in total, // so this should not be a big problem. Method meth = inst.getClass().getMethod("addTransformer", new Class[] { ClassFileTransformer.class, boolean.class }); meth.invoke(inst, new Object[] { t, true }); meth = inst.getClass().getMethod("retransformClasses", new Class[] { array.getClass() }); meth.invoke(inst, new Object[] { array }); } else { log.trace(_loc.get("redefine-types", classes.keySet())); // in a Java 5 context, we can use class redefinition instead ClassDefinition[] defs = new ClassDefinition[array.length]; for (int i = 0; i < defs.length; i++) defs[i] = new ClassDefinition(array[i], classes.get(array[i])); inst.redefineClasses(defs); } } catch (Exception e) { throw new InternalException(e); } finally { if (inst != null && t != null) inst.removeTransformer(t); } } /** * @return whether or not this VM has an instrumentation installed that * permits redefinition of classes. This assumes that all the arguments * will be modifiable classes according to * {@link java.lang.instrument.Instrumentation#isModifiableClass}, and * only checks whether or not an instrumentation is available and * if retransformation is possible. */ public static boolean canRedefineClasses(Log log) { if (_canRedefine == null) { try { Instrumentation inst = InstrumentationFactory.getInstrumentation(log); if (inst == null) { _canRedefine = Boolean.FALSE; } else if (JavaVersions.VERSION == 5) { // if instrumentation is non-null and we're using Java 5, // isRetransformClassesSupported isn't available, // so we use the more basic class redefinition instead. _canRedefine = Boolean.TRUE; } else { _canRedefine = (Boolean) Instrumentation.class.getMethod( "isRetransformClassesSupported").invoke(inst); } } catch (Exception e) { _canRedefine = Boolean.FALSE; } } return _canRedefine.booleanValue(); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ManagedClassSubclasser.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ManagedClassSubclasser.ja0000644000000000000000000003335112133327272030305 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.BytecodeWriter; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.lib.util.Localizer.Message; import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.GeneratedClasses; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.MetaDataException; import org.apache.openjpa.util.UserException; import serp.bytecode.BCClass; /** * Redefines the method bodies of existing unenhanced classes to make them * notify state managers of mutations. * * @since 1.0.0 */ public class ManagedClassSubclasser { private static final Localizer _loc = Localizer.forPackage( ManagedClassSubclasser.class); /** * For each element in classes, creates and registers a * new subclass that implements {@link PersistenceCapable}, and prepares * OpenJPA to handle new instances of the unenhanced type. If this is * invoked in a Java 6 environment, this method will redefine the methods * for each class in the argument list such that field accesses are * intercepted in-line. If invoked in a Java 5 environment, this * redefinition is not possible; in these contexts, when using field * access, OpenJPA will need to do state comparisons to detect any change * to any instance at any time, and when using property access, OpenJPA * will need to do state comparisons to detect changes to newly inserted * instances after a flush has been called. * * @return the new subclasses, or null if classes * is null. * @throws UserException if conf requires build-time * enhancement and classes includes unenhanced types. * * @since 1.0.0 */ public static List> prepareUnenhancedClasses( final OpenJPAConfiguration conf, final Collection> classes, final ClassLoader envLoader) { if (classes == null) return null; if (classes.size() == 0) return Collections.emptyList(); Log log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE); if (conf.getRuntimeUnenhancedClassesConstant() != RuntimeUnenhancedClassesModes.SUPPORTED) { Collection> unenhanced = new ArrayList>(); for (Class cls : classes) if (!PersistenceCapable.class.isAssignableFrom(cls)) unenhanced.add(cls); if (unenhanced.size() > 0) { if (PCEnhancerAgent.getLoadSuccessful() == true) { // This means that the enhancer has been ran but we // have some unenhanced classes. This can happen if an // entity is loaded by the JVM before the EntityManger // was created. Warn the user. if (log.isWarnEnabled()) { log.warn(_loc.get("entities-loaded-before-em")); } if (log.isTraceEnabled()) { log.trace(ManagedClassSubclasser.class.getName() + ".prepareUnenhancedClasses()" + " - The following classes are unenhanced " + unenhanced.toString()); } } Message msg = _loc.get("runtime-optimization-disabled", Exceptions.toClassNames(unenhanced)); if (conf.getRuntimeUnenhancedClassesConstant() == RuntimeUnenhancedClassesModes.WARN) { log.warn(msg); } else { throw new UserException(msg); } } return null; } boolean redefine = ClassRedefiner.canRedefineClasses(log); if (redefine) { log.info(_loc.get("enhance-and-subclass-and-redef-start", classes)); } else { log.warn(_loc.get("enhance-and-subclass-no-redef-start", classes)); } final Map, byte[]> map = new HashMap, byte[]>(); final List> subs = new ArrayList>(classes.size()); final List> ints = new ArrayList>(classes.size()); Set> unspecified = null; for (Class cls : classes) { final Class c = cls; final PCEnhancer enhancer = new PCEnhancer(conf, cls); enhancer.setBytecodeWriter(new BytecodeWriter() { public void write(BCClass bc) throws IOException { ManagedClassSubclasser.write(bc, enhancer, map, c, subs, ints); } }); if (redefine) { enhancer.setRedefine(true); } enhancer.setCreateSubclass(true); enhancer.setAddDefaultConstructor(true); // set this before enhancement as well as after since enhancement // uses a different metadata repository, and the metadata config // matters in the enhancement contract. In order to avoid a // NullPointerException, check for no metadata and throw an // exception if none exists. Otherwise, don't do any warning here, // since we'll issue warnings when we do the final metadata // reconfiguration at the end of this method. ClassMetaData meta = enhancer.getMetaData(); if (meta == null) { throw new MetaDataException(_loc.get("no-meta", cls)).setFatal(true); } configureMetaData(meta, conf, redefine, false); unspecified = collectRelatedUnspecifiedTypes(enhancer.getMetaData(), classes, unspecified); int runResult = enhancer.run(); if (runResult == PCEnhancer.ENHANCE_PC) { try { enhancer.record(); } catch (IOException e) { // our impl of BytecodeWriter doesn't throw IOException throw new InternalException(e); } } } if (unspecified != null && !unspecified.isEmpty()) throw new UserException(_loc.get("unspecified-unenhanced-types", Exceptions.toClassNames(classes), unspecified)); ClassRedefiner.redefineClasses(conf, map); for (Class cls : map.keySet()) { setIntercepting(conf, envLoader, cls); configureMetaData(conf, envLoader, cls, redefine); } for (Class cls : subs) configureMetaData(conf, envLoader, cls, redefine); for (Class cls : ints) setIntercepting(conf, envLoader, cls); return subs; } private static Set> collectRelatedUnspecifiedTypes(ClassMetaData meta, Collection> classes, Set> unspecified) { unspecified = collectUnspecifiedType(meta.getPCSuperclass(), classes, unspecified); for (FieldMetaData fmd : meta.getFields()) { if (fmd.isTransient()) continue; if (fmd.isTypePC()) unspecified = collectUnspecifiedType(fmd.getType(), classes, unspecified); if (fmd.getElement() != null && fmd.getElement().isTypePC()) unspecified = collectUnspecifiedType(fmd.getElement().getType(), classes, unspecified); if (fmd.getKey() != null && fmd.getKey().isTypePC()) unspecified = collectUnspecifiedType(fmd.getKey().getType(), classes, unspecified); if (fmd.getValue() != null && fmd.getValue().isTypePC()) unspecified = collectUnspecifiedType(fmd.getValue().getType(), classes, unspecified); } return unspecified; } private static Set> collectUnspecifiedType(Class cls, Collection> classes, Set> unspecified) { if (cls != null && !classes.contains(cls) && !ImplHelper.isManagedType(null, cls) && !cls.isInterface()) { if (unspecified == null) unspecified = new HashSet>(); unspecified.add(cls); } return unspecified; } private static void configureMetaData(OpenJPAConfiguration conf, ClassLoader envLoader, Class cls, boolean redefineAvailable) { ClassMetaData meta = conf.getMetaDataRepositoryInstance() .getMetaData(cls, envLoader, true); configureMetaData(meta, conf, redefineAvailable, true); } private static void configureMetaData(ClassMetaData meta, OpenJPAConfiguration conf, boolean redefineAvailable, boolean warn) { setDetachedState(meta); // If warn & (implicit field access | mixed access) & noredef if (warn && ((AccessCode.isField(meta.getAccessType()) && !meta.isMixedAccess()) || meta.isMixedAccess()) && !redefineAvailable) { // only warn about declared fields; superclass fields will be // warned about when the superclass is handled for (FieldMetaData fmd : meta.getDeclaredFields()) { if (AccessCode.isProperty(fmd.getAccessType())) continue; switch (fmd.getTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.MAP: // we can lazily load these, since we own the // relationship container break; default: if (!fmd.isInDefaultFetchGroup() && !(fmd.isVersion() || fmd.isPrimaryKey())) { Log log = conf.getLog( OpenJPAConfiguration.LOG_ENHANCE); log.warn(_loc.get("subclasser-fetch-group-override", meta.getDescribedType().getName(), fmd.getName())); fmd.setInDefaultFetchGroup(true); } } } } } private static void write(BCClass bc, PCEnhancer enhancer, Map, byte[]> map, Class cls, List> subs, List> ints) throws IOException { if (bc == enhancer.getManagedTypeBytecode()) { // if it was already defined, don't put it in the map, // but do set the metadata accordingly. if (enhancer.isAlreadyRedefined()) ints.add(bc.getType()); else { map.put(bc.getType(), bc.toByteArray()); debugBytecodes(bc); } } else { if (!enhancer.isAlreadySubclassed()) { debugBytecodes(bc); // this is the new subclass ClassLoader loader = GeneratedClasses.getMostDerivedLoader( cls, PersistenceCapable.class); subs.add(GeneratedClasses.loadBCClass(bc, loader)); } } } public static void debugBytecodes(BCClass bc) throws IOException { // Write the bytecodes to disk for debugging purposes. if ("true".equals(System.getProperty( ManagedClassSubclasser.class.getName() + ".dumpBytecodes"))) { File tmp = new File(System.getProperty("java.io.tmpdir")); File dir = new File(tmp, "openjpa"); dir = new File(dir, "pcsubclasses"); dir.mkdirs(); dir = Files.getPackageFile(dir, bc.getPackageName(), true); File f = new File(dir, bc.getClassName() + ".class"); System.err.println("Writing to " + f); AsmAdaptor.write(bc, f); } } private static void setIntercepting(OpenJPAConfiguration conf, ClassLoader envLoader, Class cls) { ClassMetaData meta = conf.getMetaDataRepositoryInstance() .getMetaData(cls, envLoader, true); meta.setIntercepting(true); } /** * If the metadata is configured to use a synthetic * detached state, reset it to not use a detached * state field, since we can't add fields when redefining. */ private static void setDetachedState(ClassMetaData meta) { if (ClassMetaData.SYNTHETIC.equals(meta.getDetachedState())) meta.setDetachedState(null); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java0000644000000000000000000012157512133327272027234 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.util.BitSet; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.AbstractPCData; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.PCData; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import java.util.concurrent.ConcurrentHashMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.InternalException; import serp.bytecode.BCClass; import serp.bytecode.BCField; import serp.bytecode.BCMethod; import serp.bytecode.Code; import serp.bytecode.Constants; import serp.bytecode.ExceptionHandler; import serp.bytecode.Instruction; import serp.bytecode.JumpInstruction; import serp.bytecode.LookupSwitchInstruction; /** * Generates {@link PCData} instances which avoid primitive wrappers * to optimize memory use and performance at the cost of slightly higher * startup time. * * @author Steve Kim * @nojavadoc * @since 0.3.2 */ public class PCDataGenerator extends DynamicStorageGenerator { private static final Localizer _loc = Localizer.forPackage (PCDataGenerator.class); protected static final String POSTFIX = "$openjpapcdata"; private final Map, DynamicStorage> _generated = new ConcurrentHashMap, DynamicStorage>(); private final OpenJPAConfiguration _conf; private final Log _log; public PCDataGenerator(OpenJPAConfiguration conf) { _conf = conf; _log = _conf.getLogFactory().getLog(OpenJPAConfiguration.LOG_ENHANCE); } /** * Return the configuration. */ public OpenJPAConfiguration getConfiguration() { return _conf; } /** * Return a {@link PCData} instance for the given oid and metadata. */ public PCData generatePCData(Object oid, ClassMetaData meta) { if (meta == null) return null; Class type = meta.getDescribedType(); DynamicStorage storage = _generated.get(type); if (storage == null) { storage = generateStorage(meta); _generated.put(type, storage); if (_log.isTraceEnabled()) _log.trace(_loc.get("pcdata-created", type.getName(), meta)); } DynamicPCData data = (DynamicPCData) storage.newInstance(); data.setId(oid); data.setStorageGenerator(this); finish(data, meta); return data; } /** * Actually generate the factory instance. */ private DynamicStorage generateStorage(ClassMetaData meta) { if (_log.isTraceEnabled()) _log.trace(_loc.get("pcdata-generate", meta)); FieldMetaData[] fields = meta.getFields(); int[] types = new int[fields.length]; for (int i = 0; i < types.length; i++) types[i] = replaceType(fields[i]); return generateStorage(types, meta); } /** * Perform any final actions before the pcdata is returned to client code. */ protected void finish(DynamicPCData data, ClassMetaData meta) { } protected int getCreateFieldMethods(int typeCode) { if (typeCode >= JavaTypes.OBJECT) return POLICY_SILENT; // don't bother creating set/get methods return POLICY_EMPTY; } protected void declareClasses(BCClass bc) { super.declareClasses(bc); bc.declareInterface(DynamicPCData.class); bc.setSuperclass(AbstractPCData.class); } protected final String getClassName(Object obj) { return getUniqueName(((ClassMetaData) obj).getDescribedType()); } /** * Creates a unique name for the given type's pcdata implementation. */ protected String getUniqueName(Class type) { return type.getName() + "$" + System.identityHashCode(type) + POSTFIX; } protected final void decorate(Object obj, BCClass bc, int[] types) { super.decorate(obj, bc, types); ClassMetaData meta = (ClassMetaData) obj; enhanceConstructor(bc); addBaseFields(bc); addImplDataMethods(bc, meta); addFieldImplDataMethods(bc, meta); addVersionMethods(bc); addGetType(bc, meta); addLoadMethod(bc, meta); addLoadWithFieldsMethod(bc, meta); addStoreMethods(bc, meta); addNewEmbedded(bc); addGetData(bc); decorate(bc, meta); } /** * Apply additional decoration to generated class. */ protected void decorate(BCClass bc, ClassMetaData meta) { } /** * Enhance constructor to initialize fields */ private void enhanceConstructor(BCClass bc) { BCMethod cons = bc.getDeclaredMethod("", (String[]) null); Code code = cons.getCode(false); code.afterLast(); code.previous(); // private BitSet loaded = new BitSet(); BCField loaded = addBeanField(bc, "loaded", BitSet.class); loaded.setFinal(true); code.aload().setThis(); code.anew().setType(BitSet.class); code.dup(); code.constant().setValue(bc.getFields().length); code.invokespecial().setMethod(BitSet.class, "", void.class, new Class[]{ int.class }); code.putfield().setField(loaded); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Have to load the type since it may not be available to the * same classloader (i.e. rar vs. ear). The context classloader * (i.e. the user app classloader) should be fine. */ private void addGetType(BCClass bc, ClassMetaData meta) { BCField type = bc.declareField("type", Class.class); type.setStatic(true); type.makePrivate(); // public Class getType() { BCMethod getter = bc.declareMethod("getType", Class.class, null); getter.makePublic(); Code code = getter.getCode(true); // if (type == null) { // try { // type = Class.forName // (meta.getDescribedType().getName(), true, // Thread.currentThread().getContextClassLoader()); // } catch (ClassNotFoundException cnfe) { // throw new InternalException(); // } // } code.getstatic().setField(type); Collection jumps = new LinkedList(); jumps.add(code.ifnonnull()); ExceptionHandler handler = code.addExceptionHandler(); handler.setTryStart(code.constant().setValue (meta.getDescribedType().getName())); code.constant().setValue(true); code.invokestatic().setMethod(Thread.class, "currentThread", Thread.class, null); code.invokevirtual().setMethod(Thread.class, "getContextClassLoader", ClassLoader.class, null); code.invokestatic().setMethod(Class.class, "forName", Class.class, new Class[]{ String.class, boolean.class, ClassLoader.class }); code.putstatic().setField(type); Instruction go2 = code.go2(); jumps.add(go2); handler.setTryEnd(go2); handler.setCatch(ClassNotFoundException.class); handler.setHandlerStart(throwException (code, InternalException.class)); setTarget(code.getstatic().setField(type), jumps); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Declare standard dynamic pcdata fields. */ private void addBaseFields(BCClass bc) { addBeanField(bc, "id", Object.class); BCField field = addBeanField(bc, "storageGenerator", PCDataGenerator.class); field.setAccessFlags(field.getAccessFlags() | Constants.ACCESS_TRANSIENT); } /** * Add methods for loading and storing class-level impl data. */ private void addImplDataMethods(BCClass bc, ClassMetaData meta) { // void storeImplData(OpenJPAStateManager); BCMethod meth = bc.declareMethod("storeImplData", void.class, new Class[]{ OpenJPAStateManager.class }); Code code = meth.getCode(true); BCField impl = null; if (!usesImplData(meta)) code.vreturn(); else { // if (sm.isImplDataCacheable()) // setImplData(sm.getImplData()); impl = addBeanField(bc, "implData", Object.class); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "isImplDataCacheable", boolean.class, null); JumpInstruction ifins = code.ifeq(); code.aload().setThis(); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getImplData", Object.class, null); code.invokevirtual().setMethod("setImplData", void.class, new Class[]{ Object.class }); ifins.setTarget(code.vreturn()); } code.calculateMaxStack(); code.calculateMaxLocals(); // void loadImplData(OpenJPAStateManager); meth = bc.declareMethod("loadImplData", void.class, new Class[]{ OpenJPAStateManager.class }); code = meth.getCode(true); if (!usesImplData(meta)) code.vreturn(); else { // if (sm.getImplData() == null && implData != null) // sm.setImplData(impl, true); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getImplData", Object.class, null); JumpInstruction ifins = code.ifnonnull(); code.aload().setThis(); code.getfield().setField(impl); JumpInstruction ifins2 = code.ifnull(); code.aload().setParam(0); code.aload().setThis(); code.getfield().setField(impl); code.constant().setValue(true); code.invokeinterface().setMethod(OpenJPAStateManager.class, "setImplData", void.class, new Class[]{ Object.class, boolean.class }); Instruction ins = code.vreturn(); ifins.setTarget(ins); ifins2.setTarget(ins); } code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Add methods for loading and storing class-level impl data. */ private void addFieldImplDataMethods(BCClass bc, ClassMetaData meta) { // public void loadImplData(OpenJPAStateManager sm, int i) BCMethod meth = bc.declareMethod("loadImplData", void.class, new Class[]{ OpenJPAStateManager.class, int.class }); meth.makePrivate(); Code code = meth.getCode(true); int count = countImplDataFields(meta); BCField impl = null; if (count == 0) code.vreturn(); else { // Object[] fieldImpl impl = bc.declareField("fieldImpl", Object[].class); impl.makePrivate(); // if (fieldImpl != null) code.aload().setThis(); code.getfield().setField(impl); JumpInstruction ifins = code.ifnonnull(); code.vreturn(); // Object obj = null; int obj = code.getNextLocalsIndex(); ifins.setTarget(code.constant().setNull()); code.astore().setLocal(obj); // establish switch target, then move before it Instruction target = code.aload().setLocal(obj); code.previous(); // switch(i) code.iload().setParam(1); LookupSwitchInstruction lswitch = code.lookupswitch(); FieldMetaData[] fields = meta.getFields(); int cacheable = 0; for (int i = 0; i < fields.length; i++) { if (!usesImplData(fields[i])) continue; // case x: obj = fieldImpl[y]; break; lswitch.addCase(i, code.aload().setThis()); code.getfield().setField(impl); code.constant().setValue(cacheable++); code.aaload(); code.astore().setLocal(obj); code.go2().setTarget(target); } lswitch.setDefaultTarget(target); // if (obj != null) code.next(); // jump back over target ifins = code.ifnonnull(); code.vreturn(); // sm.setImplData(index, impl); ifins.setTarget(code.aload().setParam(0)); code.iload().setParam(1); code.aload().setLocal(obj); code.invokeinterface().setMethod(OpenJPAStateManager.class, "setImplData", void.class, new Class[]{ int.class, Object.class }); code.vreturn(); } code.calculateMaxLocals(); code.calculateMaxStack(); // void storeImplData(OpenJPAStateManager sm, int index, boolean loaded) meth = bc.declareMethod("storeImplData", void.class, new Class[]{ OpenJPAStateManager.class, int.class, boolean.class }); code = meth.getCode(true); if (count == 0) code.vreturn(); else { // int arrIdx = -1; // switch(index) int arrIdx = code.getNextLocalsIndex(); code.constant().setValue(-1); code.istore().setLocal(arrIdx); code.iload().setParam(1); LookupSwitchInstruction lswitch = code.lookupswitch(); // establish switch target, then move before it Instruction switchTarget = code.iload().setLocal(arrIdx); code.previous(); FieldMetaData[] fields = meta.getFields(); int cacheable = 0; for (int i = 0; i < fields.length; i++) { if (!usesImplData(fields[i])) continue; // case x: arrIdx = y; break; lswitch.addCase(i, code.constant().setValue(cacheable++)); code.istore().setLocal(arrIdx); code.go2().setTarget(switchTarget); } lswitch.setDefaultTarget(switchTarget); code.next(); // step over switch target // if (arrIdx != -1) code.constant().setValue(-1); JumpInstruction ifins = code.ificmpne(); code.vreturn(); // create null target, then move before it Instruction nullTarget = code.aload().setThis(); code.previous(); // if (loaded) ifins.setTarget(code.iload().setParam(2)); code.ifeq().setTarget(nullTarget); // Object obj = sm.getImplData(index) int obj = code.getNextLocalsIndex(); code.aload().setParam(0); code.iload().setParam(1); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getImplData", Object.class, new Class[]{ int.class }); code.astore().setLocal(obj); // if (obj != null) code.aload().setLocal(obj); code.ifnull().setTarget(nullTarget); // if (fieldImpl == null) // fieldImpl = new Object[fields]; code.aload().setThis(); code.getfield().setField(impl); ifins = code.ifnonnull(); code.aload().setThis(); code.constant().setValue(count); code.anewarray().setType(Object.class); code.putfield().setField(impl); // fieldImpl[arrIdx] = obj; // return; ifins.setTarget(code.aload().setThis()); code.getfield().setField(impl); code.iload().setLocal(arrIdx); code.aload().setLocal(obj); code.aastore(); code.vreturn(); // if (fieldImpl != null) // fieldImpl[index] = null; code.next(); // step over nullTarget code.getfield().setField(impl); ifins = code.ifnonnull(); code.vreturn(); ifins.setTarget(code.aload().setThis()); code.getfield().setField(impl); code.iload().setLocal(arrIdx); code.constant().setNull(); code.aastore(); code.vreturn(); } code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Add methods for loading and storing version data. */ protected void addVersionMethods(BCClass bc) { // void storeVersion(OpenJPAStateManager sm); addBeanField(bc, "version", Object.class); BCMethod meth = bc.declareMethod("storeVersion", void.class, new Class[]{ OpenJPAStateManager.class }); Code code = meth.getCode(true); // version = sm.getVersion(); code.aload().setThis(); code.aload().setParam(0); code.invokeinterface() .setMethod(OpenJPAStateManager.class, "getVersion", Object.class, null); code.putfield().setField("version", Object.class); code.vreturn(); code.calculateMaxStack(); code.calculateMaxLocals(); // void loadVersion(OpenJPAStateManager sm) meth = bc.declareMethod("loadVersion", void.class, new Class[]{ OpenJPAStateManager.class }); code = meth.getCode(true); // if (sm.getVersion() == null) // sm.setVersion(version); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getVersion", Object.class, null); JumpInstruction ifins = code.ifnonnull(); code.aload().setParam(0); code.aload().setThis(); code.getfield().setField("version", Object.class); code.invokeinterface() .setMethod(OpenJPAStateManager.class, "setVersion", void.class, new Class[]{ Object.class }); ifins.setTarget(code.vreturn()); code.calculateMaxStack(); code.calculateMaxLocals(); } private void addLoadMethod(BCClass bc, ClassMetaData meta) { // public void load(OpenJPAStateManager sm, FetchConfiguration fetch, // Object context) Code code = addLoadMethod(bc, false); FieldMetaData[] fmds = meta.getFields(); Collection jumps = new LinkedList(); Collection jumps2; int local = code.getNextLocalsIndex(); code.constant().setNull(); code.astore().setLocal(local); int inter = code.getNextLocalsIndex(); code.constant().setNull(); code.astore().setLocal(inter); int objectCount = 0; boolean intermediate; for (int i = 0; i < fmds.length; i++) { jumps2 = new LinkedList(); intermediate = usesIntermediate(fmds[i]); setTarget(code.aload().setThis(), jumps); // if (loaded.get(i)) or (!loaded.get(i)) depending on inter resp code.getfield().setField("loaded", BitSet.class); code.constant().setValue(i); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); jumps.add(code.ifne()); if (intermediate) addLoadIntermediate(code, i, objectCount, jumps2, inter); jumps2.add(code.go2()); // if (fetch.requiresFetch(fmds[i])!=FetchConfiguration.FETCH_NONE) setTarget(code.aload().setParam(1), jumps); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getMetaData", ClassMetaData.class, null); code.constant().setValue(fmds[i].getIndex()); code.invokevirtual().setMethod(ClassMetaData.class, "getField", FieldMetaData.class, new Class[]{int.class}); code.invokeinterface().setMethod (FetchConfiguration.class, "requiresFetch", int.class, new Class[]{FieldMetaData.class}); code.constant().setValue(FetchConfiguration.FETCH_NONE); jumps2.add(code.ificmpeq()); addLoad(bc, code, fmds[i], objectCount, local, false); jumps = jumps2; if (replaceType(fmds[i]) >= JavaTypes.OBJECT) objectCount++; } setTarget(code.vreturn(), jumps); code.calculateMaxStack(); code.calculateMaxLocals(); } private void addLoadWithFieldsMethod(BCClass bc, ClassMetaData meta) { Code code = addLoadMethod(bc, true); // public void load(OpenJPAStateManager sm, BitSet fields, // FetchConfiguration fetch, Object conn) FieldMetaData[] fmds = meta.getFields(); Collection jumps = new LinkedList(); Collection jumps2; int objectCount = 0; boolean intermediate; int local = code.getNextLocalsIndex(); code.constant().setNull(); code.astore().setLocal(local); int inter = code.getNextLocalsIndex(); code.constant().setNull(); code.astore().setLocal(inter); for (int i = 0; i < fmds.length; i++) { jumps2 = new LinkedList(); intermediate = usesIntermediate(fmds[i]); // if (fields.get(i)) // { // if (loaded.get(i)) setTarget(code.aload().setParam(1), jumps); code.constant().setValue(i); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); jumps2.add(code.ifeq()); code.aload().setThis(); code.getfield().setField("loaded", BitSet.class); code.constant().setValue(i); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); if (intermediate) jumps.add(code.ifeq()); else jumps2.add(code.ifeq()); addLoad(bc, code, fmds[i], objectCount, local, true); if (usesImplData(fmds[i])) { // loadImplData(sm, i); code.aload().setThis(); code.aload().setParam(0); code.constant().setValue(i); code.invokevirtual().setMethod("loadImplData", void.class, new Class[]{ OpenJPAStateManager.class, int.class }); } // fields.clear(i); code.aload().setParam(1); code.constant().setValue(i); code.invokevirtual().setMethod(BitSet.class, "clear", void.class, new Class[] { int.class }); jumps2.add(code.go2()); if (intermediate) setTarget(addLoadIntermediate (code, i, objectCount, jumps2, inter), jumps); jumps = jumps2; if (replaceType(fmds[i]) >= JavaTypes.OBJECT) objectCount++; } setTarget(code.vreturn(), jumps); code.calculateMaxStack(); code.calculateMaxLocals(); } /** * Declare and start the base load method. */ private Code addLoadMethod(BCClass bc, boolean fields) { Class[] args = null; if (fields) args = new Class[]{ OpenJPAStateManager.class, BitSet.class, FetchConfiguration.class, Object.class }; else args = new Class[]{ OpenJPAStateManager.class, FetchConfiguration.class, Object.class }; BCMethod load = bc.declareMethod("load", void.class, args); Code code = load.getCode(true); //loadVersion(sm); code.aload().setThis(); code.aload().setParam(0); code.invokevirtual().setMethod("loadVersion", void.class, new Class[]{ OpenJPAStateManager.class }); //loadImplData(sm); code.aload().setThis(); code.aload().setParam(0); code.invokevirtual().setMethod("loadImplData", void.class, new Class[]{ OpenJPAStateManager.class }); return code; } /** * Add the field load. */ private Instruction addLoad(BCClass bc, Code code, FieldMetaData fmd, int objectCount, int local, boolean fields) { int index = fmd.getIndex(); int typeCode = replaceType(fmd); Instruction first; if (typeCode < JavaTypes.OBJECT) { // sm.store(i, field) Class type = forType(fmd.getTypeCode()); first = code.aload().setParam(0); code.constant().setValue(index); code.aload().setThis(); code.getfield().setField(getFieldName(index), type); code.invokeinterface().setMethod(OpenJPAStateManager.class, "store" + StringUtils.capitalize(type.getName()), void.class, new Class[]{ int.class, type }); } else { // fmd = sm.getMetaData().getField(i); int offset = fields ? 1 : 0; first = code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getMetaData", ClassMetaData.class, null); code.constant().setValue(fmd.getIndex()); code.invokevirtual().setMethod(ClassMetaData.class, "getField", FieldMetaData.class, new Class[]{ int.class }); code.astore().setLocal(local); // sm.storeField(i, toField(sm, fmd, objects[objectCount], // fetch, context); code.aload().setParam(0); code.constant().setValue(index); code.aload().setThis(); code.aload().setParam(0); code.aload().setLocal(local); code.aload().setThis(); code.getfield().setField("objects", Object[].class); code.constant().setValue(objectCount); code.aaload(); code.aload().setParam(1 + offset); code.aload().setParam(2 + offset); code.invokevirtual().setMethod(bc.getName(), "toField", Object.class.getName(), toStrings(new Class[]{ OpenJPAStateManager.class, FieldMetaData.class, Object.class, FetchConfiguration.class, Object.class })); code.invokeinterface().setMethod(OpenJPAStateManager.class, "storeField", void.class, new Class[]{ int.class, Object.class }); } return first; } /** * Load intermediate data if possible. */ private Instruction addLoadIntermediate(Code code, int index, int objectCount, Collection jumps2, int inter) { // { // Object inter = objects[objectCount]; Instruction first = code.aload().setThis(); code.getfield().setField("objects", Object[].class); code.constant().setValue(objectCount); code.aaload(); code.astore().setLocal(inter); // if (inter != null && !sm.getLoaded().get(index)) code.aload().setLocal(inter); jumps2.add(code.ifnull()); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getLoaded", BitSet.class, null); code.constant().setValue(index); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); jumps2.add(code.ifne()); // sm.setIntermediate(index, inter); // } // end else code.aload().setParam(0); code.constant().setValue(index); code.aload().setLocal(inter); code.invokeinterface().setMethod(OpenJPAStateManager.class, "setIntermediate", void.class, new Class[]{ int.class, Object.class }); return first; } private void addStoreMethods(BCClass bc, ClassMetaData meta) { // i.e. void store(OpenJPAStateManager sm, BitSet fields); addStoreMethod(bc, meta, true); // i.e. void store(OpenJPAStateManager sm); addStoreMethod(bc, meta, false); } private void addStoreMethod(BCClass bc, ClassMetaData meta, boolean fields) { BCMethod store; if (fields) store = bc.declareMethod("store", void.class, new Class[]{ OpenJPAStateManager.class, BitSet.class }); else store = bc.declareMethod("store", void.class, new Class[]{ OpenJPAStateManager.class }); Code code = store.getCode(true); // initialize(); code.aload().setThis(); code.invokevirtual().setMethod("initialize", void.class, null); // storeVersion(sm); code.aload().setThis(); code.aload().setParam(0); code.invokevirtual().setMethod("storeVersion", void.class, new Class[]{ OpenJPAStateManager.class }); // storeImplData(sm); code.aload().setThis(); code.aload().setParam(0); code.invokevirtual().setMethod("storeImplData", void.class, new Class[]{ OpenJPAStateManager.class }); FieldMetaData[] fmds = meta.getFields(); Collection jumps = new LinkedList(); int objectCount = 0; for (int i = 0; i < fmds.length; i++) { if (fields) { // if (fields != null && fields.get(index)) setTarget(code.aload().setParam(1), jumps); jumps.add(code.ifnull()); code.aload().setParam(1); code.constant().setValue(i); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); jumps.add(code.ifeq()); } else { // if (sm.getLoaded().get(index))) setTarget(code.aload().setParam(0), jumps); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getLoaded", BitSet.class, null); code.constant().setValue(i); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); jumps.add(code.ifeq()); } addStore(bc, code, fmds[i], objectCount); if (usesIntermediate(fmds[i])) { JumpInstruction elseIns = code.go2(); // else if (!loaded.get(index)) setTarget(code.aload().setThis(), jumps); jumps.add(elseIns); code.getfield().setField("loaded", BitSet.class); code.constant().setValue(i); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); jumps.add(code.ifne()); // Object val = sm.getIntermediate(index); // if (val != null) // objects[objectCount] = val; code.aload().setParam(0); code.constant().setValue(i); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getIntermediate", Object.class, new Class[]{ int.class }); int local = code.getNextLocalsIndex(); code.astore().setLocal(local); code.aload().setLocal(local); jumps.add(code.ifnull()); code.aload().setThis(); code.getfield().setField("objects", Object[].class); code.constant().setValue(objectCount); code.aload().setLocal(local); code.aastore(); } if (replaceType(fmds[i]) >= JavaTypes.OBJECT) objectCount++; } setTarget(code.vreturn(), jumps); code.calculateMaxLocals(); code.calculateMaxStack(); } private void addStore(BCClass bc, Code code, FieldMetaData fmd, int objectCount) { int typeCode = replaceType(fmd); int index = fmd.getIndex(); if (typeCode < JavaTypes.OBJECT) { Class type = forType(typeCode); // field = sm.fetch(index) code.aload().setThis(); code.aload().setParam(0); code.constant().setValue(index); code.invokeinterface().setMethod(OpenJPAStateManager.class, "fetch" + StringUtils.capitalize(type.getName()), type, new Class[]{ int.class }); code.putfield().setField(getFieldName(index), type); code.aload().setThis(); code.getfield().setField("loaded", BitSet.class); code.constant().setValue(index); code.invokevirtual().setMethod(BitSet.class, "set", void.class, new Class[]{ int.class }); } else { // Object val = toData(sm.getMetaData().getField(index), // sm.fetchField(index, false), sm.getContext()); int local = code.getNextLocalsIndex(); code.aload().setThis(); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getMetaData", ClassMetaData.class, null); code.constant().setValue(fmd.getIndex()); code.invokevirtual().setMethod(ClassMetaData.class, "getField", FieldMetaData.class, new Class[]{ int.class }); code.aload().setParam(0); code.constant().setValue(fmd.getIndex()); code.constant().setValue(false); code.invokeinterface().setMethod(OpenJPAStateManager.class, "fetchField", Object.class, new Class[] { int.class, boolean.class }); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getContext", StoreContext.class, null); code.invokevirtual().setMethod(bc.getName(), "toData", Object.class.getName(), toStrings(new Class []{ FieldMetaData.class, Object.class, StoreContext.class })); code.astore().setLocal(local); // if (val == NULL) { // val = null; // loaded.clear(index); // } else // loaded.set(index); // objects[objectCount] = val; code.aload().setLocal(local); code.getstatic().setField(AbstractPCData.class, "NULL", Object.class); JumpInstruction ifins = code.ifacmpne(); code.constant().setNull(); code.astore().setLocal(local); code.aload().setThis(); code.getfield().setField("loaded", BitSet.class); code.constant().setValue(index); code.invokevirtual().setMethod(BitSet.class, "clear", void.class, new Class[]{ int.class }); JumpInstruction go2 = code.go2(); ifins.setTarget(code.aload().setThis()); code.getfield().setField("loaded", BitSet.class); code.constant().setValue(index); code.invokevirtual().setMethod(BitSet.class, "set", void.class, new Class[]{ int.class }); go2.setTarget(code.aload().setThis()); code.getfield().setField("objects", Object[].class); code.constant().setValue(objectCount); code.aload().setLocal(local); code.aastore(); } if (!usesImplData(fmd)) return; // storeImplData(sm, i, loaded.get(i); code.aload().setThis(); code.aload().setParam(0); code.constant().setValue(index); code.aload().setThis(); code.getfield().setField("loaded", BitSet.class); code.constant().setValue(index); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); code.invokevirtual().setMethod("storeImplData", void.class, new Class[]{ OpenJPAStateManager.class, int.class, boolean.class }); } private void addNewEmbedded(BCClass bc) { // void newEmbeddedPCData(OpenJPAStateManager embedded) BCMethod meth = bc.declareMethod("newEmbeddedPCData", PCData.class, new Class[]{ OpenJPAStateManager.class }); Code code = meth.getCode(true); // return getStorageGenerator().generatePCData // (sm.getId(), sm.getMetaData()); code.aload().setThis(); code.getfield().setField("storageGenerator", PCDataGenerator.class); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getId", Object.class, null); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getMetaData", ClassMetaData.class, null); code.invokevirtual().setMethod(PCDataGenerator.class, "generatePCData", PCData.class, new Class[] { Object.class, ClassMetaData.class }); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); } private void addGetData(BCClass bc) { // return getObjectField(i); BCMethod method = bc.declareMethod("getData", Object.class, new Class[]{ int.class }); Code code = method.getCode(true); code.aload().setThis(); code.iload().setParam(0); code.invokevirtual().setMethod("getObject", Object.class, new Class[]{ int.class }); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); } ///////////// // Utilities ///////////// /** * Return a valid {@link JavaTypes} constant for the given field */ protected int replaceType(FieldMetaData fmd) { if (usesIntermediate(fmd)) return JavaTypes.OBJECT; return fmd.getTypeCode(); } /** * Whether the given field uses a cacheable intermediate value. */ protected boolean usesIntermediate(FieldMetaData fmd) { return fmd.usesIntermediate(); } /** * Whether the given type might have cacheable class-level impl data. */ protected boolean usesImplData(ClassMetaData meta) { return true; } /** * Whether the given field might have cacheable impl data. */ protected boolean usesImplData(FieldMetaData fmd) { return fmd.usesImplData() == null; } /** * The number of fields with cacheable impl data. */ private int countImplDataFields(ClassMetaData meta) { FieldMetaData[] fmds = meta.getFields(); int count = 0; for (int i = 0; i < fmds.length; i++) if (usesImplData(fmds[i])) count++; return count; } /** * Add method which defers to AbstractPCData. */ protected void callAbstractPCData(BCClass bc, String name, Class retType, Class[] args) { BCMethod meth = bc.declareMethod(name, retType, args); Code code = meth.getCode(true); code.aload().setThis(); for (int i = 0; i < args.length; i++) code.xload().setParam(i).setType(args[i]); code.invokevirtual().setMethod(AbstractPCData.class, name, retType, args); if (!void.class.equals(retType)) code.xreturn().setType(retType); code.calculateMaxLocals(); code.calculateMaxStack(); } /** * Set the collection of {@link JumpInstruction}s to the given instruction, * clearing the collection in the process. */ protected void setTarget(Instruction ins, Collection jumps) { for (Iterator it = jumps.iterator(); it.hasNext();) ((JumpInstruction) it.next()).setTarget(ins); jumps.clear(); } /** * Transform the given array of classes to strings. */ private static String[] toStrings(Class[] cls) { String[] strings = new String[cls.length]; for (int i = 0; i < strings.length; i++) strings[i] = cls[i].getName(); return strings; } /** * Dynamic {@link PCData}s generated will implement this interface * to simplify initialization. */ public static interface DynamicPCData extends PCData { public void setId(Object oid); public PCDataGenerator getStorageGenerator(); public void setStorageGenerator (PCDataGenerator generator); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/FieldManager.java0000644000000000000000000000170112133327272026573 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * Manages persistent fields. */ public interface FieldManager extends FieldConsumer, FieldSupplier { } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java0000644000000000000000000001061012133327272026307 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URLDecoder; import serp.bytecode.BCClass; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; /** * Use ASM to add required StackMapTable attribute to the byte code generated by * Serp. */ public final class AsmAdaptor { private static final int Java7_MajorVersion = 51; @SuppressWarnings("deprecation") public static void write(BCClass bc) throws IOException { if (bc.getMajorVersion() < Java7_MajorVersion) { bc.write(); } else { String name = bc.getName(); int dotIndex = name.lastIndexOf('.') + 1; name = name.substring(dotIndex); Class type = bc.getType(); OutputStream out = new FileOutputStream( URLDecoder.decode(type.getResource(name + ".class").getFile())); try { writeJava7(bc, out); } finally { out.flush(); out.close(); } } } public static void write(BCClass bc, File outFile) throws IOException { if (bc.getMajorVersion() < Java7_MajorVersion) { bc.write(outFile); } else { OutputStream out = new FileOutputStream(outFile); try { writeJava7(bc, out); } finally { out.flush(); out.close(); } } } public static byte[] toByteArray(BCClass bc, byte[] returnBytes) throws IOException { if (bc.getMajorVersion() >= Java7_MajorVersion) { returnBytes = toJava7ByteArray(bc, returnBytes); } return returnBytes; } private static void writeJava7(BCClass bc, OutputStream out) throws IOException { byte[] java7Bytes = toJava7ByteArray(bc, bc.toByteArray()); out.write(java7Bytes); } private static byte[] toJava7ByteArray(BCClass bc, byte[] classBytes) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(classBytes); BufferedInputStream bis = new BufferedInputStream(bais); ClassWriter cw = new BCClassWriter(ClassWriter.COMPUTE_FRAMES, bc.getClassLoader()); ClassReader cr = new ClassReader(bis); cr.accept(cw, 0); return cw.toByteArray(); } private static class BCClassWriter extends ClassWriter { private final ClassLoader _loader; BCClassWriter(int flags, ClassLoader loader) { super(flags); _loader = loader; } @Override protected String getCommonSuperClass(String type1, String type2) { Class class1; Class class2; try { class1 = _loader.loadClass(type1.replace('/', '.')); class2 = _loader.loadClass(type2.replace('/', '.')); } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } if (class1.isAssignableFrom(class2)) { return type1; } if (class2.isAssignableFrom(class1)) { return type2; } if (class1.isInterface() || class2.isInterface()) { return "java/lang/Object"; } do { class1 = class1.getSuperclass(); } while (!class1.isAssignableFrom(class2)); return class1.getName().replace('.', '/'); } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ManagedInstanceProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ManagedInstanceProvider.j0000644000000000000000000000177612133327272030335 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * Instances of this interface can provide an underlying instance. * * @since 1.0.0 */ public interface ManagedInstanceProvider { public Object getManagedInstance(); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/InstrumentationFactory.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/InstrumentationFactory.ja0000644000000000000000000004002712133327272030465 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.lang.instrument.Instrumentation; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.net.URL; import java.net.URLClassLoader; import java.security.AccessController; import java.security.CodeSource; import java.security.PrivilegedAction; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.JavaVendors; import org.apache.openjpa.lib.util.JavaVersions; import org.apache.openjpa.lib.util.Localizer; /** * Factory for obtaining an {@link Instrumentation} instance. * * @author Marc Prud'hommeaux * @since 1.0.0 */ public class InstrumentationFactory { private static Instrumentation _inst; private static boolean _dynamicallyInstall = true; private static final String _name = InstrumentationFactory.class.getName(); private static final Localizer _loc = Localizer.forPackage( InstrumentationFactory.class); /** * This method is not synchronized because when the agent is loaded from * getInstrumentation() that method will cause agentmain(..) to be called. * Synchronizing this method would cause a deadlock. * * @param inst The instrumentation instance to be used by this factory. */ public static void setInstrumentation(Instrumentation inst) { _inst = inst; } /** * Configures whether or not this instance should attempt to dynamically * install an agent in the VM. Defaults to true. */ public static synchronized void setDynamicallyInstallAgent(boolean val) { _dynamicallyInstall = val; } /** * @param log OpenJPA log. * @return null if Instrumentation can not be obtained, or if any * Exceptions are encountered. */ public static synchronized Instrumentation getInstrumentation(final Log log) { if (log.isTraceEnabled() == true) { log.trace(_name + ".getInstrumentation() _inst:" + _inst + " _dynamicallyInstall:" + _dynamicallyInstall); } if ( _inst != null || !_dynamicallyInstall) return _inst; // dynamic loading of the agent is only available in JDK 1.6+ if (JavaVersions.VERSION < 6) { if (log.isTraceEnabled() == true) { log.trace(_name + ".getInstrumentation() Dynamic loading only supported on Java SE 6 or later"); } return null; } AccessController.doPrivileged(new PrivilegedAction() { public Object run() { // Dynamic agent enhancement should only occur when the OpenJPA library is // loaded using the system class loader. Otherwise, the OpenJPA // library may get loaded by separate, disjunct loaders, leading to linkage issues. try { if (!InstrumentationFactory.class.getClassLoader().equals( ClassLoader.getSystemClassLoader())) { return null; } } catch (Throwable t) { return null; } JavaVendors vendor = JavaVendors.getCurrentVendor(); File toolsJar = null; // When running on IBM, the attach api classes are packaged in vm.jar which is a part // of the default vm classpath. if (vendor.isIBM() == false) { // If we can't find the tools.jar and we're not on IBM we can't load the agent. toolsJar = findToolsJar(log); if (toolsJar == null) { return null; } } Class vmClass = loadVMClass(toolsJar, log, vendor); if (vmClass == null) { return null; } String agentPath = getAgentJar(log); if (agentPath == null) { return null; } loadAgent(log, agentPath, vmClass); return null; }// end run() }); // If the load(...) agent call was successful, this variable will no // longer be null. return _inst; }//end getInstrumentation() /** * The method that is called when a jar is added as an agent at runtime. * All this method does is store the {@link Instrumentation} for * later use. */ public static void agentmain(String agentArgs, Instrumentation inst) { InstrumentationFactory.setInstrumentation(inst); } /** * Create a new jar file for the sole purpose of specifying an Agent-Class * to load into the JVM. * * @return absolute path to the new jar file. */ private static String createAgentJar() throws IOException { File file = File.createTempFile(InstrumentationFactory.class.getName(), ".jar"); file.deleteOnExit(); ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(file)); zout.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF")); PrintWriter writer = new PrintWriter(new OutputStreamWriter(zout)); writer .println("Agent-Class: " + InstrumentationFactory.class.getName()); writer.println("Can-Redefine-Classes: true"); // IBM doesn't support retransform writer.println("Can-Retransform-Classes: " + Boolean.toString(JavaVendors.getCurrentVendor().isIBM() == false)); writer.close(); return file.getAbsolutePath(); } /** * This private worker method attempts to find [java_home]/lib/tools.jar. * Note: The tools.jar is a part of the SDK, it is not present in the JRE. * * @return If tools.jar can be found, a File representing tools.jar.
* If tools.jar cannot be found, null. */ private static File findToolsJar(Log log) { String javaHome = System.getProperty("java.home"); File javaHomeFile = new File(javaHome); File toolsJarFile = new File(javaHomeFile, "lib" + File.separator + "tools.jar"); if (toolsJarFile.exists() == false) { if (log.isTraceEnabled() == true) { log.trace(_name + ".findToolsJar() -- couldn't find default " + toolsJarFile.getAbsolutePath()); } // If we're on an IBM SDK, then remove /jre off of java.home and try again. if (javaHomeFile.getAbsolutePath().endsWith(File.separator + "jre") == true) { javaHomeFile = javaHomeFile.getParentFile(); toolsJarFile = new File(javaHomeFile, "lib" + File.separator + "tools.jar"); if (toolsJarFile.exists() == false) { if (log.isTraceEnabled() == true) { log.trace(_name + ".findToolsJar() -- for IBM SDK couldn't find " + toolsJarFile.getAbsolutePath()); } } } else if (System.getProperty("os.name").toLowerCase().indexOf("mac") >= 0) { // If we're on a Mac, then change the search path to use ../Classes/classes.jar. if (javaHomeFile.getAbsolutePath().endsWith(File.separator + "Home") == true) { javaHomeFile = javaHomeFile.getParentFile(); toolsJarFile = new File(javaHomeFile, "Classes" + File.separator + "classes.jar"); if (toolsJarFile.exists() == false) { if (log.isTraceEnabled() == true) { log.trace(_name + ".findToolsJar() -- for Mac OS couldn't find " + toolsJarFile.getAbsolutePath()); } } } } } if (toolsJarFile.exists() == false) { return null; } else { if (log.isTraceEnabled() == true) { log.trace(_name + ".findToolsJar() -- found " + toolsJarFile.getAbsolutePath()); } return toolsJarFile; } } /** * This private worker method will return a fully qualified path to a jar * that has this class defined as an Agent-Class in it's * META-INF/manifest.mf file. Under normal circumstances the path should * point to the OpenJPA jar. If running in a development environment a * temporary jar file will be created. * * @return absolute path to the agent jar or null if anything unexpected * happens. */ private static String getAgentJar(Log log) { File agentJarFile = null; // Find the name of the File that this class was loaded from. That // jar *should* be the same location as our agent. CodeSource cs = InstrumentationFactory.class.getProtectionDomain().getCodeSource(); if (cs != null) { URL loc = cs.getLocation(); if(loc!=null){ agentJarFile = new File(loc.getFile()); } } // Determine whether the File that this class was loaded from has this // class defined as the Agent-Class. boolean createJar = false; if (cs == null || agentJarFile == null || agentJarFile.isDirectory() == true) { createJar = true; }else if(validateAgentJarManifest(agentJarFile, log, _name) == false){ // We have an agentJarFile, but this class isn't the Agent-Class. createJar=true; } String agentJar; if (createJar == true) { // This can happen when running in eclipse as an OpenJPA // developer or for some reason the CodeSource is null. We // should log a warning here because this will create a jar // in your temp directory that doesn't always get cleaned up. try { agentJar = createAgentJar(); if (log.isInfoEnabled() == true) { log.info(_loc.get("temp-file-creation", agentJar)); } } catch (IOException ioe) { if (log.isTraceEnabled() == true) { log.trace(_name + ".getAgentJar() caught unexpected " + "exception.", ioe); } agentJar = null; } } else { agentJar = agentJarFile.getAbsolutePath(); } return agentJar; }//end getAgentJar /** * Attach and load an agent class. * * @param log Log used if the agent cannot be loaded. * @param agentJar absolute path to the agent jar. * @param vmClass VirtualMachine.class from tools.jar. */ private static void loadAgent(Log log, String agentJar, Class vmClass) { try { // first obtain the PID of the currently-running process // ### this relies on the undocumented convention of the // RuntimeMXBean's // ### name starting with the PID, but there appears to be no other // ### way to obtain the current process' id, which we need for // ### the attach process RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); String pid = runtime.getName(); if (pid.indexOf("@") != -1) pid = pid.substring(0, pid.indexOf("@")); // JDK1.6: now attach to the current VM so we can deploy a new agent // ### this is a Sun JVM specific feature; other JVMs may offer // ### this feature, but in an implementation-dependent way Object vm = vmClass.getMethod("attach", new Class[] { String.class }) .invoke(null, new Object[] { pid }); // now deploy the actual agent, which will wind up calling // agentmain() vmClass.getMethod("loadAgent", new Class[] { String.class }) .invoke(vm, new Object[] { agentJar }); vmClass.getMethod("detach", new Class[] {}).invoke(vm, new Object[] {}); } catch (Throwable t) { if (log.isTraceEnabled() == true) { // Log the message from the exception. Don't log the entire // stack as this is expected when running on a JDK that doesn't // support the Attach API. log.trace(_name + ".loadAgent() caught an exception. Message: " + t.getMessage()); } } } /** * If ibm is false, this private method will create a new URLClassLoader and attempt to load the * com.sun.tools.attach.VirtualMachine class from the provided toolsJar file. * *

* If ibm is true, this private method will ignore the toolsJar parameter and load the * com.ibm.tools.attach.VirtualMachine class. * * * @return The AttachAPI VirtualMachine class
* or null if something unexpected happened. */ private static Class loadVMClass(File toolsJar, Log log, JavaVendors vendor) { try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); String cls = vendor.getVirtualMachineClassName(); if (vendor.isIBM() == false) { loader = new URLClassLoader(new URL[] { toolsJar.toURI().toURL() }, loader); } return loader.loadClass(cls); } catch (Exception e) { if (log.isTraceEnabled()) { log.trace(_name + ".loadVMClass() failed to load the VirtualMachine class"); } } return null; } /** * This private worker method will validate that the provided agentClassName * is defined as the Agent-Class in the manifest file from the provided jar. * * @param agentJarFile * non-null agent jar file. * @param log * non-null logger. * @param agentClassName * the non-null agent class name. * @return True if the provided agentClassName is defined as the Agent-Class * in the manifest from the provided agentJarFile. False otherwise. */ private static boolean validateAgentJarManifest(File agentJarFile, Log log, String agentClassName) { try { JarFile jar = new JarFile(agentJarFile); Manifest manifest = jar.getManifest(); if (manifest == null) { return false; } Attributes attributes = manifest.getMainAttributes(); String ac = attributes.getValue("Agent-Class"); if (ac != null && ac.equals(agentClassName)) { return true; } } catch (Exception e) { if (log.isTraceEnabled() == true) { log.trace(_name + ".validateAgentJarManifest() caught unexpected " + "exception " + e.getMessage()); } } return false; }// end validateAgentJarManifest } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCSubclassValidator.java0000644000000000000000000002601712133327272030134 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Modifier; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.util.UserException; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Localizer.Message; import org.apache.openjpa.lib.log.Log; import serp.bytecode.BCField; import serp.bytecode.BCClass; import serp.bytecode.BCMethod; /** *

Validates that a given type meets the JPA contract, plus a few * OpenJPA-specific additions for subclassing / redefinition: * *

    *
  • must have an accessible no-args constructor
  • *
  • must be a public or protected class
  • *
  • must not be final
  • *
  • must not extend an enhanced class
  • *
  • all persistent data represented by accessible setter/getter * methods (persistent properties)
  • *
  • if versioning is to be used, exactly one persistent property for * the numeric version data
  • * *
  • When using property access, the backing field for a persistent * property must be: *
      * *
    • private
    • *
    • set only in the designated setter, * in the constructor, or in {@link Object#clone()}, * readObject(ObjectInputStream), or * {@link Externalizable#readExternal(ObjectInput)}.
    • *
    • read only in the designated getter and the * constructor.
    • *
    *
  • *
* *

If you use this technique and use the new keyword instead * of a OpenJPA-supplied construction routine, OpenJPA will need to do extra * work with persistent-new-flushed instances, since OpenJPA cannot in this * case track what happens to such an instance.

* * @since 1.0.0 */ public class PCSubclassValidator { private static final Localizer loc = Localizer.forPackage(PCSubclassValidator.class); private final ClassMetaData meta; private final BCClass pc; private final Log log; private final boolean failOnContractViolations; private Collection errors; private Collection contractViolations; public PCSubclassValidator(ClassMetaData meta, BCClass bc, Log log, boolean enforceContractViolations) { this.meta = meta; this.pc = bc; this.log = log; this.failOnContractViolations = enforceContractViolations; } public void assertCanSubclass() { Class superclass = meta.getDescribedType(); String name = superclass.getName(); if (superclass.isInterface()) addError(loc.get("subclasser-no-ifaces", name), meta); if (Modifier.isFinal(superclass.getModifiers())) addError(loc.get("subclasser-no-final-classes", name), meta); if (Modifier.isPrivate(superclass.getModifiers())) addError(loc.get("subclasser-no-private-classes", name), meta); if (PersistenceCapable.class.isAssignableFrom(superclass)) addError(loc.get("subclasser-super-already-pc", name), meta); try { Constructor c = superclass.getDeclaredConstructor(new Class[0]); if (!(Modifier.isProtected(c.getModifiers()) || Modifier.isPublic(c.getModifiers()))) addError(loc.get("subclasser-private-ctor", name), meta); } catch (NoSuchMethodException e) { addError(loc.get("subclasser-no-void-ctor", name), meta); } // if the BCClass we loaded is already pc and the superclass is not, // then we should never get here, so let's make sure that the // calling context is caching correctly by throwing an exception. if (pc.isInstanceOf(PersistenceCapable.class) && !PersistenceCapable.class.isAssignableFrom(superclass)) throw new InternalException( loc.get("subclasser-class-already-pc", name)); if (AccessCode.isProperty(meta.getAccessType())) checkPropertiesAreInterceptable(); if (errors != null && !errors.isEmpty()) throw new UserException(errors.toString()); else if (contractViolations != null && !contractViolations.isEmpty() && log.isWarnEnabled()) log.warn(contractViolations.toString()); } private void checkPropertiesAreInterceptable() { // just considers accessor methods for now. FieldMetaData[] fmds = meta.getFields(); for (int i = 0; i < fmds.length; i++) { Method getter = getBackingMember(fmds[i]); if (getter == null) { addError(loc.get("subclasser-no-getter", fmds[i].getName()), fmds[i]); continue; } BCField returnedField = checkGetterIsSubclassable(getter, fmds[i]); Method setter = setterForField(fmds[i]); if (setter == null) { addError(loc.get("subclasser-no-setter", fmds[i].getName()), fmds[i]); continue; } BCField assignedField = checkSetterIsSubclassable(setter, fmds[i]); if (assignedField == null) continue; if (assignedField != returnedField) addContractViolation(loc.get ("subclasser-setter-getter-field-mismatch", fmds[i].getName(), returnedField,assignedField), fmds[i]); // ### scan through all the rest of the class to make sure it // ### doesn't use the field. } } private Method getBackingMember(FieldMetaData fmd) { Member back = fmd.getBackingMember(); if (Method.class.isInstance(back)) return (Method)back; Method getter = Reflection.findGetter(meta.getDescribedType(), fmd.getName(), false); if (getter != null) fmd.backingMember(getter); return getter; } private Method setterForField(FieldMetaData fmd) { try { return fmd.getDeclaringType().getDeclaredMethod( "set" + StringUtils.capitalize(fmd.getName()), new Class[]{ fmd.getDeclaredType() }); } catch (NoSuchMethodException e) { return null; } } /** * @return the name of the field that is returned by meth, or * null if something other than a single field is * returned, or if it cannot be determined what is returned. */ private BCField checkGetterIsSubclassable(Method meth, FieldMetaData fmd) { checkMethodIsSubclassable(meth, fmd); BCField field = PCEnhancer.getReturnedField(getBCMethod(meth)); if (field == null) { addContractViolation(loc.get("subclasser-invalid-getter", fmd.getName()), fmd); return null; } else { return field; } } /** * @return the field that is set in meth, or * null if something other than a single field is * set, or if it cannot be determined what is set. */ private BCField checkSetterIsSubclassable(Method meth, FieldMetaData fmd) { checkMethodIsSubclassable(meth, fmd); BCField field = PCEnhancer.getAssignedField(getBCMethod(meth)); if (field == null) { addContractViolation(loc.get("subclasser-invalid-setter", fmd.getName()), fmd); return null; } else { return field; } } private BCMethod getBCMethod(Method meth) { BCClass bc = pc.getProject().loadClass(meth.getDeclaringClass()); return bc.getDeclaredMethod(meth.getName(), meth.getParameterTypes()); } private void checkMethodIsSubclassable(Method meth, FieldMetaData fmd) { String className = fmd.getDefiningMetaData(). getDescribedType().getName(); if (!(Modifier.isProtected(meth.getModifiers()) || Modifier.isPublic(meth.getModifiers()))) addError(loc.get("subclasser-private-accessors-unsupported", className, meth.getName()), fmd); if (Modifier.isFinal(meth.getModifiers())) addError(loc.get("subclasser-final-methods-not-allowed", className, meth.getName()), fmd); if (Modifier.isNative(meth.getModifiers())) addContractViolation(loc.get ("subclasser-native-methods-not-allowed", className, meth.getName()), fmd); if (Modifier.isStatic(meth.getModifiers())) addError(loc.get("subclasser-static-methods-not-supported", className, meth.getName()), fmd); } private void addError(Message s, ClassMetaData cls) { if (errors == null) errors = new ArrayList(); errors.add(loc.get("subclasser-error-meta", s, cls.getDescribedType().getName(), cls.getSourceFile())); } private void addError(Message s, FieldMetaData fmd) { if (errors == null) errors = new ArrayList(); errors.add(loc.get("subclasser-error-field", s, fmd.getFullName(), fmd.getDeclaringMetaData().getSourceFile())); } private void addContractViolation(Message m, FieldMetaData fmd) { // add the violation as an error in case we're processing violations // as errors; this keeps them in the order that they were found rather // than just adding the violations to the end of the list. if (failOnContractViolations) addError(m, fmd); if (contractViolations == null) contractViolations = new ArrayList(); contractViolations.add(loc.get ("subclasser-contract-violation-field", m.getMessage(), fmd.getFullName(), fmd.getDeclaringMetaData().getSourceFile())); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/FieldConsumer.java0000644000000000000000000000401112133327272027011 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * Consumes persistent field values. */ public interface FieldConsumer { /** * Set the value of the given field. */ void storeBooleanField(int fieldIndex, boolean value); /** * Set the value of the given field. */ void storeCharField(int fieldIndex, char value); /** * Set the value of the given field. */ void storeByteField(int fieldIndex, byte value); /** * Set the value of the given field. */ void storeShortField(int fieldIndex, short value); /** * Set the value of the given field. */ void storeIntField(int fieldIndex, int value); /** * Set the value of the given field. */ void storeLongField(int fieldIndex, long value); /** * Set the value of the given field. */ void storeFloatField(int fieldIndex, float value); /** * Set the value of the given field. */ void storeDoubleField(int fieldIndex, double value); /** * Set the value of the given field. */ void storeStringField(int fieldIndex, String value); /** * Set the value of the given field. */ void storeObjectField(int fieldIndex, Object value); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PersistenceCapable.java0000644000000000000000000000517712133327272030024 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.enhance; /** * The interface that persistent instances will implement. * * @author Marc Prud'hommeaux */ public interface PersistenceCapable { // DO NOT ADD ADDITIONAL DEPENDENCIES TO THIS CLASS public static final byte READ_WRITE_OK = 0; public static final byte LOAD_REQUIRED = 1; public static final byte READ_OK = -1; public static final byte CHECK_READ = 1; public static final byte MEDIATE_READ = 2; public static final byte CHECK_WRITE = 4; public static final byte MEDIATE_WRITE = 8; public static final byte SERIALIZABLE = 16; public static final Object DESERIALIZED = new Object(); int pcGetEnhancementContractVersion(); Object pcGetGenericContext(); StateManager pcGetStateManager(); void pcReplaceStateManager(StateManager sm); void pcProvideField(int fieldIndex); void pcProvideFields(int[] fieldIndices); void pcReplaceField(int fieldIndex); void pcReplaceFields(int[] fieldIndex); void pcCopyFields(Object fromObject, int[] fields); void pcDirty(String fieldName); Object pcFetchObjectId(); Object pcGetVersion(); boolean pcIsDirty(); boolean pcIsTransactional(); boolean pcIsPersistent(); boolean pcIsNew(); boolean pcIsDeleted(); Boolean pcIsDetached(); // null == unknown PersistenceCapable pcNewInstance(StateManager sm, boolean clear); PersistenceCapable pcNewInstance(StateManager sm, Object obj, boolean clear); Object pcNewObjectIdInstance(); Object pcNewObjectIdInstance(Object obj); void pcCopyKeyFieldsToObjectId(Object obj); void pcCopyKeyFieldsToObjectId(FieldSupplier supplier, Object obj); void pcCopyKeyFieldsFromObjectId(FieldConsumer consumer, Object obj); Object pcGetDetachedState(); void pcSetDetachedState(Object state); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/0000755000000000000000000000000012133327272023272 5ustar ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedValueStateManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedValueStateManager.0000644000000000000000000004210412133327272030266 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.ObjectOutput; import java.util.BitSet; import org.apache.openjpa.enhance.FieldManager; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.ImplHelper; /** * Implementation of {@link OpenJPAStateManager} designed to retrieve * values from a detached instance, including when managed by a * {@link DetachedStateManager}. */ public class DetachedValueStateManager extends TransferFieldManager implements OpenJPAStateManager { private static final Localizer _loc = Localizer.forPackage (DetachedValueStateManager.class); private PersistenceCapable _pc; private StoreContext _ctx; private ClassMetaData _meta; public DetachedValueStateManager(Object pc, StoreContext ctx) { this(ImplHelper.toPersistenceCapable(pc, ctx.getConfiguration()), ctx.getConfiguration().getMetaDataRepositoryInstance() .getMetaData(ImplHelper.getManagedInstance(pc).getClass(), ctx.getClassLoader(), true), ctx); } public DetachedValueStateManager(PersistenceCapable pc, ClassMetaData meta, StoreContext ctx) { _pc = ImplHelper.toPersistenceCapable(pc, ctx.getConfiguration()); _meta = meta; _ctx = ctx; } public void initialize(Class forType, PCState state) { throw new UnsupportedOperationException(); } public void load(FetchConfiguration fetch) { throw new UnsupportedOperationException(); } public Object getManagedInstance() { return _pc; } public PersistenceCapable getPersistenceCapable() { return _pc; } public ClassMetaData getMetaData() { return _meta; } public OpenJPAStateManager getOwner() { return null; } public int getOwnerIndex() { throw new UnsupportedOperationException(); } public boolean isEmbedded() { return false; } public boolean isFlushed() { return false; } public boolean isFlushedDirty() { return false; } public boolean isProvisional() { return false; } public BitSet getLoaded() { throw new UnsupportedOperationException(); } public BitSet getDirty() { throw new UnsupportedOperationException(); } public BitSet getFlushed() { throw new UnsupportedOperationException(); } public BitSet getUnloaded(FetchConfiguration fetch) { throw new UnsupportedOperationException(); } public Object newProxy(int field) { throw new UnsupportedOperationException(); } public Object newFieldProxy(int field) { throw new UnsupportedOperationException(); } public boolean isDefaultValue(int field) { throw new UnsupportedOperationException(); } public StoreContext getContext() { return _ctx; } public PCState getPCState() { throw new UnsupportedOperationException(); } public Object getId() { return getObjectId(); } public Object getObjectId() { throw new UnsupportedOperationException(); } public void setObjectId(Object oid) { throw new UnsupportedOperationException(); } public boolean assignObjectId(boolean flush) { throw new UnsupportedOperationException(); } public Object getLock() { throw new UnsupportedOperationException(); } public void setLock(Object lock) { throw new UnsupportedOperationException(); } public Object getVersion() { throw new UnsupportedOperationException(); } public void setVersion(Object version) { throw new UnsupportedOperationException(); } public void setNextVersion(Object version) { throw new UnsupportedOperationException(); } public boolean isVersionUpdateRequired() { throw new UnsupportedOperationException(); } public boolean isVersionCheckRequired() { throw new UnsupportedOperationException(); } public Object getImplData() { throw new UnsupportedOperationException(); } public Object setImplData(Object data, boolean cacheable) { throw new UnsupportedOperationException(); } public boolean isImplDataCacheable() { throw new UnsupportedOperationException(); } public Object getImplData(int field) { throw new UnsupportedOperationException(); } public Object setImplData(int field, Object data) { throw new UnsupportedOperationException(); } public boolean isImplDataCacheable(int field) { throw new UnsupportedOperationException(); } public Object getIntermediate(int field) { throw new UnsupportedOperationException(); } public void setIntermediate(int field, Object value) { throw new UnsupportedOperationException(); } void provideField(int field) { if (_pc.pcGetStateManager() != null) throw new InternalException(_loc.get("detach-val-mismatch", _pc)); _pc.pcReplaceStateManager(this); _pc.pcProvideField(field); _pc.pcReplaceStateManager(null); } public boolean fetchBoolean(int field) { throw new UnsupportedOperationException(); } public byte fetchByte(int field) { throw new UnsupportedOperationException(); } public char fetchChar(int field) { throw new UnsupportedOperationException(); } public double fetchDouble(int field) { throw new UnsupportedOperationException(); } public float fetchFloat(int field) { throw new UnsupportedOperationException(); } public int fetchInt(int field) { throw new UnsupportedOperationException(); } public long fetchLong(int field) { throw new UnsupportedOperationException(); } public Object fetchObject(int field) { throw new UnsupportedOperationException(); } public short fetchShort(int field) { throw new UnsupportedOperationException(); } public String fetchString(int field) { throw new UnsupportedOperationException(); } public Object fetchFromDetachedSM(DetachedStateManager sm, int field) { sm.lock(); sm.provideField(field); Object val = fetchField(sm, field); sm.clear(); sm.unlock(); return val; } public Object fetch(int field) { StateManager sm = _pc.pcGetStateManager(); if (sm != null) { if (sm instanceof DetachedStateManager) return fetchFromDetachedSM((DetachedStateManager) sm, field); if (_ctx.getAllowReferenceToSiblingContext() && sm instanceof StateManagerImpl) { return ((StateManagerImpl) sm).fetch(field); } throw new UnsupportedException(_loc.get("detach-val-badsm", _pc)); } provideField(field); Object val = fetchField(field, false); clear(); return _meta.getField(field).getExternalValue(val, _ctx.getBroker()); } public Object fetchField(int field, boolean transitions) { if (transitions) throw new IllegalArgumentException(); return fetchField(this, field); } private Object fetchField(FieldManager fm, int field) { FieldMetaData fmd = _meta.getField(field); if (fmd == null) throw new InternalException(); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.STRING: return fm.fetchStringField(field); case JavaTypes.OBJECT: return fm.fetchObjectField(field); case JavaTypes.BOOLEAN: return (fm.fetchBooleanField(field)) ? Boolean.TRUE : Boolean.FALSE; case JavaTypes.BYTE: return Byte.valueOf(fm.fetchByteField(field)); case JavaTypes.CHAR: return Character.valueOf(fm.fetchCharField(field)); case JavaTypes.DOUBLE: return Double.valueOf(fm.fetchDoubleField(field)); case JavaTypes.FLOAT: return Float.valueOf(fm.fetchFloatField(field)); case JavaTypes.INT: return fm.fetchIntField(field); case JavaTypes.LONG: return fm.fetchLongField(field); case JavaTypes.SHORT: return Short.valueOf(fm.fetchShortField(field)); default: return fm.fetchObjectField(field); } } public Object fetchInitialField(int field) { throw new UnsupportedOperationException(); } public void storeBoolean(int field, boolean externalVal) { throw new UnsupportedOperationException(); } public void storeByte(int field, byte externalVal) { throw new UnsupportedOperationException(); } public void storeChar(int field, char externalVal) { throw new UnsupportedOperationException(); } public void storeDouble(int field, double externalVal) { throw new UnsupportedOperationException(); } public void storeFloat(int field, float externalVal) { throw new UnsupportedOperationException(); } public void storeInt(int field, int externalVal) { throw new UnsupportedOperationException(); } public void storeLong(int field, long externalVal) { throw new UnsupportedOperationException(); } public void storeObject(int field, Object externalVal) { throw new UnsupportedOperationException(); } public void storeShort(int field, short externalVal) { throw new UnsupportedOperationException(); } public void storeString(int field, String externalVal) { throw new UnsupportedOperationException(); } public void store(int field, Object value) { throw new UnsupportedOperationException(); } public void storeField(int field, Object value) { throw new UnsupportedOperationException(); } public void dirty(int field) { throw new UnsupportedOperationException(); } public void removed(int field, Object removed, boolean key) { throw new UnsupportedOperationException(); } public boolean beforeRefresh(boolean refreshAll) { throw new UnsupportedOperationException(); } public void setRemote(int field, Object value) { throw new UnsupportedOperationException(); } /////////////////////////////// // StateManager implementation /////////////////////////////// public Object getGenericContext() { return _ctx; } public Object getPCPrimaryKey(Object oid, int field) { throw new UnsupportedOperationException(); } public StateManager replaceStateManager(StateManager sm) { return sm; } public boolean isDirty() { return true; } public boolean isTransactional() { return false; } public boolean isPersistent() { return true; } public boolean isNew() { return false; } public boolean isDeleted() { return false; } public boolean isDetached() { return true; } public void dirty(String field) { throw new UnsupportedOperationException(); } public Object fetchObjectId() { return getObjectId(); } public boolean serializing() { throw new UnsupportedOperationException(); } public boolean writeDetached(ObjectOutput out) { throw new UnsupportedOperationException(); } public void proxyDetachedDeserialized(int idx) { throw new UnsupportedOperationException(); } public void accessingField(int idx) { throw new UnsupportedOperationException(); } public void providedBooleanField(PersistenceCapable pc, int idx, boolean cur) { longval = cur ? 1 : 0; } public void providedCharField(PersistenceCapable pc, int idx, char cur) { longval = cur; } public void providedByteField(PersistenceCapable pc, int idx, byte cur) { longval = cur; } public void providedShortField(PersistenceCapable pc, int idx, short cur) { longval = cur; } public void providedIntField(PersistenceCapable pc, int idx, int cur) { longval = cur; } public void providedLongField(PersistenceCapable pc, int idx, long cur) { longval = cur; } public void providedFloatField(PersistenceCapable pc, int idx, float cur) { dblval = cur; } public void providedDoubleField(PersistenceCapable pc, int idx, double cur) { dblval = cur; } public void providedStringField(PersistenceCapable pc, int idx, String cur) { objval = cur; } public void providedObjectField(PersistenceCapable pc, int idx, Object cur) { objval = cur; } public void settingBooleanField(PersistenceCapable pc, int idx, boolean cur, boolean next, int set) { throw new UnsupportedOperationException(); } public void settingCharField(PersistenceCapable pc, int idx, char cur, char next, int set) { throw new UnsupportedOperationException(); } public void settingByteField(PersistenceCapable pc, int idx, byte cur, byte next, int set) { throw new UnsupportedOperationException(); } public void settingShortField(PersistenceCapable pc, int idx, short cur, short next, int set) { throw new UnsupportedOperationException(); } public void settingIntField(PersistenceCapable pc, int idx, int cur, int next, int set) { throw new UnsupportedOperationException(); } public void settingLongField(PersistenceCapable pc, int idx, long cur, long next, int set) { throw new UnsupportedOperationException(); } public void settingFloatField(PersistenceCapable pc, int idx, float cur, float next, int set) { throw new UnsupportedOperationException(); } public void settingDoubleField(PersistenceCapable pc, int idx, double cur, double next, int set) { throw new UnsupportedOperationException(); } public void settingStringField(PersistenceCapable pc, int idx, String cur, String next, int set) { throw new UnsupportedOperationException(); } public void settingObjectField(PersistenceCapable pc, int idx, Object cur, Object next, int set) { throw new UnsupportedOperationException(); } public boolean replaceBooleanField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public char replaceCharField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public byte replaceByteField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public short replaceShortField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public int replaceIntField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public long replaceLongField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public float replaceFloatField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public double replaceDoubleField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public String replaceStringField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public Object replaceObjectField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } @Override public boolean isDelayed(int field) { return false; } @Override public void setDelayed(int field, boolean delay) { throw new UnsupportedOperationException(); } @Override public void loadDelayedField(int field) { throw new UnsupportedOperationException(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java0000644000000000000000000003317612133327272027730 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.util.Collection; import java.util.Map; import java.util.Set; import org.apache.openjpa.lib.rop.ResultList; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.meta.FieldMetaData; /** * Allows configuration and optimization of how objects are loaded from * the data store. * * @since 0.3.0 * @author Abe White * @author Pinaki Poddar */ public interface FetchConfiguration extends Serializable, Cloneable, LockLevels, LockScopes, QueryFlushModes { /** * Constant to revert any setting back to its default value. */ public static final int DEFAULT = -99; /** * Constant indicating that a field does not require fetching. * * @see #requiresFetch */ public static final int FETCH_NONE = 0; /** * Constant indicating that a field requires a fetch and load of fetched * data. * * @see #requiresFetch */ public static final int FETCH_LOAD = 1; /** * Constant indicating that a reference to the field's value must be * fetched, but loading data is not necessary. Used when we know the * data will be loaded anyway, such as when traversing the back-ptr of * a bidirectional relation where the other side is also being fetched. * * @see #requiresFetch */ public static final int FETCH_REF = 2; /** * Return the context associated with this configuration; * may be null if it has not been set or this object has been serialized. */ public StoreContext getContext(); /** * Called automatically by the system to associate the fetch configuration * with a context before use. The fetch configuration properties should * be synchronized with the context's configuration object. Subclasses * for specific back ends cannot rely on the context's configuration * implementing their back end's configuration sub-interface. */ public void setContext(StoreContext ctx); /** * Clone this instance. */ public Object clone(); /** * Copy the state from the given fetch configuration to this one. */ public void copy(FetchConfiguration fetch); /** * Return the fetch batch size for large result set support. * Defaults to the openjpa.FetchBatchSize setting. Note * that this property will be ignored under some data stores. */ public int getFetchBatchSize(); /** * Set the fetch batch size for large result set support. * Defaults to the openjpa.FetchBatchSize setting. Note * that this property will be ignored under some data stores. */ public FetchConfiguration setFetchBatchSize(int fetchBatchSize); /** * Return the maximum depth of fetched instance graph. * Defaults to 1 */ public int getMaxFetchDepth(); /** * Set the maximum depth of the fetched instance graph. * * @param max denotes limiting length of traversal path from a root * instance. -1 implies no limit. 0 is not * permissible. */ public FetchConfiguration setMaxFetchDepth(int max); /** * Return whether or not query caching is enabled. If this returns * true but the datacache plugin is not installed, caching * will not be enabled. If this * returns false, query caching will not be used * even if the datacache plugin is installed. */ public boolean getQueryCacheEnabled(); /** * Control whether or not query caching is enabled. This has no effect * if the datacache plugin is not installed, or if the query cache size * is set to zero. */ public FetchConfiguration setQueryCacheEnabled(boolean cache); /** * The query automatic flush configuration. */ public int getFlushBeforeQueries(); /** * The query automatic flush configuration. */ public FetchConfiguration setFlushBeforeQueries(int flush); /** * Affirms if extended path lookup feature is active. * * @since 2.0.0 */ public boolean getExtendedPathLookup(); /** * Sets extended path lookup feature. * * @since 2.0.0 */ public FetchConfiguration setExtendedPathLookup(boolean flag); /** * Returns immutable set of names of the fetch groups that this component * will use when loading objects. Defaults to the * openjpa.FetchGroups setting. This set is not thread safe. */ public Set getFetchGroups(); /** * Return true if the given fetch group has been added. */ public boolean hasFetchGroup(String group); /** * Adds group to the set of fetch group names to * use when loading objects. */ public FetchConfiguration addFetchGroup(String group); /** * Adds groups to the set of fetch group names to * use when loading objects. */ public FetchConfiguration addFetchGroups(Collection groups); /** * Remove the given fetch group. */ public FetchConfiguration removeFetchGroup(String group); /** * Removes groups from the set of fetch group names * to use when loading objects. */ public FetchConfiguration removeFetchGroups(Collection groups); /** * Clears the set of fetch group names to use when loading * data. After this operation is invoked, only those fields in * the default fetch group (and any requested field) will be * loaded when loading an object. */ public FetchConfiguration clearFetchGroups(); /** * Resets the set of fetch groups to the list in the global configuration. */ public FetchConfiguration resetFetchGroups(); /** * Returns the set of fully-qualified field names that this component * will use when loading objects. Defaults to the empty set. This set is * not thread safe. */ public Set getFields(); /** * Return true if the given fully-qualified field has been added. */ public boolean hasField(String field); /** * Adds field to the set of fully-qualified field names to * use when loading objects. */ public FetchConfiguration addField(String field); /** * Adds fields to the set of fully-qualified field names to * use when loading objects. */ public FetchConfiguration addFields(Collection fields); /** * Remove the given fully-qualified field. */ public FetchConfiguration removeField(String field); /** * Removes fields from the set of fully-qualified field names * to use when loading objects. */ public FetchConfiguration removeFields(Collection fields); /** * Clears the set of field names to use when loading * data. After this operation is invoked, only those fields in * the configured fetch groups will be loaded when loading an object. */ public FetchConfiguration clearFields(); /** * The number of milliseconds to wait for an object lock, or -1 for no * limit. * * @since 0.3.1 */ public int getLockTimeout(); /** * The number of milliseconds to wait for an object lock, or -1 for no * limit. * * @since 0.3.1 */ public FetchConfiguration setLockTimeout(int timeout); /** * The lock scope for next fetch. * * @since 2.0.0 */ public int getLockScope(); /** * The lock scope for next fetch. * * @since 2.0.0 */ public FetchConfiguration setLockScope(int scope); /** * The number of milliseconds to wait for a query, or -1 for no * limit. * * @since 2.0.0 */ public int getQueryTimeout(); /** * The number of milliseconds to wait for a query, or -1 for no * limit. * * @since 2.0.0 */ public FetchConfiguration setQueryTimeout(int timeout); /** * The lock level to use for locking loaded objects. * * @since 0.3.1 */ public int getReadLockLevel(); /** * The lock level to use for locking loaded objects. * * @since 0.3.1 */ public FetchConfiguration setReadLockLevel(int level); /** * The lock level to use for locking dirtied objects. * * @since 0.3.1 */ public int getWriteLockLevel(); /** * Gets the current storage mode for data cache. * * @since 2.0.0 */ public DataCacheStoreMode getCacheStoreMode(); /** * Sets the current storage mode for data cache. * * @since 2.0.0 */ public void setCacheStoreMode(DataCacheStoreMode mode); /** * Gets the current retrieve mode for data cache. * * @since 2.0.0 */ public DataCacheRetrieveMode getCacheRetrieveMode(); /** * Sets the current retrieve mode for data cache. * * @since 2.0.0 */ public void setCacheRetrieveMode(DataCacheRetrieveMode mode); /** * The lock level to use for locking dirtied objects. * * @since 0.3.1 */ public FetchConfiguration setWriteLockLevel(int level); /** * Return a new result list for the current fetch configuration. */ public ResultList newResultList(ResultObjectProvider rop); /** * Sets an arbitrary query hint that may be utilized during execution. * The hint may be specific to a particular database. A hint, if known * to this receiver, may have a corresponding setter method, then the hint sets the value. * Otherwise the hint is stored opaquely by the receiver. * * @param name the name of the hint * @param value the value of the hint. If the hint has a corresponding setter, then * the type of value must be same as the setter argument. * @param original the value of the hint as specified by the user. * * @since 2.0.0 */ public void setHint(String name, Object value, Object original); /** * Sets an arbitrary query hint that may be utilized during execution. * The hint may be specific to a particular database. A hint, if known * to this receiver, may have a corresponding setter method, then the hint sets the value. * Otherwise the hint is stored opaquely by the receiver. *
* This is same as calling {@linkplain #setHint(String, Object, Object)} with the third * argument being the same as the second. * * @param name the name of the hint * @param value the value of the hint. If the hint has a corresponding setter, then * the type of value must be same as the setter argument. * * @since 2.0.0 */ public void setHint(String key, Object value); /** * Get the hint value for the specific key as originally set by the caller, or null if the hint is not specified. * * @param name the hint name * @since 0.4.0 */ public Object getHint (String key); /** * Get an immutable view of the currently active hints and their values. * The values are as specified by the user. * * @since 2.0.0 */ public Map getHints(); /** * Affirm if the given hint has been set in this receiver. * */ public boolean isHintSet(String key); /** * Root classes for recursive operations. This set is not thread safe. */ public Set> getRootClasses(); /** * Root classes for recursive operations. */ public FetchConfiguration setRootClasses(Collection> classes); /** * Root instances for recursive operations. This set is not thread safe. */ public Set getRootInstances(); /** * Root instances for recursive operations. */ public FetchConfiguration setRootInstances(Collection roots); /** * Synchronize on internal lock if multithreaded is true. */ public void lock(); /** * Release internal lock if multithreaded is true. */ public void unlock(); /** * Affirms if the given field requires to be fetched in the context * of current fetch operation. Returns one of {@link #FETCH_NONE}, * {@link #FETCH_LOAD}, {@link FETCH_REF}. * * @since 0.4.1 */ public int requiresFetch(FieldMetaData fm); /** * Return false if we know that the object being fetched with this * configuration does not require a load, because this configuration came * from a traversal of a {@link #FETCH_REF} field. */ public boolean requiresLoad(); /** * Traverse the given field to generate (possibly) a new configuration * state. * * @return a new configuration state resulting out of traversal * @since 0.4.1 */ public FetchConfiguration traverse(FieldMetaData fm); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultShape.java0000644000000000000000000003242112133327272026376 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Describes the shape of a query result. *
* A shape is described as a Java class by the generic type argument T. A shape may contain zero or more shapes. * A shape is categorized as follows: *
  • A primitive shape can not have child shapes e.g. Foo or float. *
  • A compound shape has zero or more child shapes e.g. Foo{} or Foo{String, int} or * Foo{String,Bar{Double},int}. *
  • A nesting shape has one or more compound child shape(s). * For example, Foo{String,Bar{Double},int}. On the other hand, Foo{String, int} is a compound shape but is not * nesting because all its child shapes are primitive. *
    * A primitive category shape is declared during construction and immutable. * The category of a non-primitive shape is mutable. *
    * Notice that all nested shapes are compound shapes but not all compound shapes are nesting. *
    * A compound shape can add other primitive shapes or nest other shapes to any arbitrary depth. * However, a shape does not allow recursive nesting of shapes. *
    * Usage: * The purpose of a shape is to populate an instance of T from an array of input values where each * array element is further specified with a type and an alias. FillStrategy determines how a shape * populates an instance of T by consuming the input array element values. * The input data is presented as an Object[] with a parallel array of types because the primitive * types (short, float etc.) are not preserved in the input array. For certain FillStrategy such as * MAP or BEAN, the alias of the input array element are used to identify the Map key or setter * methods respectively. * * @author Pinaki Poddar * * @since 2.0.0 * */ @SuppressWarnings("serial") public class ResultShape implements Serializable { private final Class cls; // the type of value this shape represents or populates private final boolean isPrimitive; // flags this shape as primitive private boolean isNesting; // flags this shape as nesting private String alias; private final FillStrategy strategy; // the strategy to populate this shape private final List> children; // children of this shape. null for primitives private Set> parents; // the shapes that have nested this shape /** * Construct a non-primitive shape with ASSIGN or ARRAY fill strategy. */ public ResultShape(Class cls) { this(cls, false); } /** * Construct a primitive or non-primitive shape with ASSIGN or ARRAY fill strategy. * If the shape is declared as primitive then the given class can not be an array. */ public ResultShape(Class cls, boolean primitive) { this(cls, cls.isArray() ? new FillStrategy.Array(cls) : new FillStrategy.Assign(), primitive); if (cls.isArray() && primitive) throw new IllegalArgumentException(cls.getSimpleName() + " can not be primitive shape"); } /** * * Construct a non-primitive shape with the given fill strategy. */ public ResultShape(Class cls, FillStrategy strategy) { this(cls, strategy, false); } /** * Construct a shape with the given fill strategy. * */ public ResultShape(Class cls, FillStrategy strategy, boolean primitive) { if (cls == null) throw new NullPointerException(); this.cls = cls; this.strategy = strategy; isPrimitive = primitive; children = isPrimitive ? null : new ArrayList>(); } // /** // * Construct a shape with the MAP fill strategy to invoke the given method. // * // */ // public ResultShape(Class cls, Method putMethod) { // if (cls == null) throw new NullPointerException(); // this.cls = cls; // this.strategy = new FillStrategy.Map(putMethod); // isPrimitive = true; // children = new ArrayList>(); // } // // /** // * Construct a shape with the CONSTRUCTOR fill strategy to invoke the given constructor. // * // */ // public ResultShape(Class cls, Constructor cons) { // if (cls == null) throw new NullPointerException(); // this.cls = cls; // this.strategy = new FillStrategy.NewInstance(cons); // isPrimitive = false; // children = new ArrayList>(); // } /** * Gets the type of instance populated by this shape. */ public Class getType() { return cls; } public FillStrategy getStrategy() { return strategy; } public ResultShape setAlias(String alias) { this.alias = alias; return this; } public String getAlias() { return alias; } /** * Gets the list of classes to compose this shape and all its children. * For example, a shape Foo{String,Bar{int, Date}, Double} will return * {String, int, Date, Double} */ public List> getCompositeTypes() { List> result = new ArrayList>(); if (isPrimitive() || children.isEmpty()) { result.add(cls); } else { for (ResultShape child : children) { result.addAll(child.getCompositeTypes()); } } return result; } /** * Gets the list of classes to compose this shape only i.e. without expanding the children's shape. * For example, a shape Foo{String,Bar{int, Date}, Double} will return {String, Bar, Double} */ public List> getTypes() { List> result = new ArrayList>(); if (children.isEmpty()) { result.add(cls); } else { for (ResultShape child : children) { result.add(child.getType()); } } return result; } /** * Creates a new shape of type X with the given class arguments and nests * the new shape within this shape. * * @return newly created nested shape */ public ResultShape nest(Class cls, FillStrategy strategy, Class... classes) { assertNotPrimitive(); ResultShape child = new ResultShape(cls, strategy, true); this.nest(child.add(classes)); return child; } /** * Nest the given shape. * * @param shape The given shape can not be a parent of this shape * to prohibit recursive nesting. * * @return this shape itself */ public ResultShape nest(ResultShape shape) { assertNotPrimitive(); if (shape.isParent(this)) throw new IllegalArgumentException(this + " can not nest recursive " + shape); children.add(shape); shape.addParent(this); isNesting |= !shape.isPrimitive(); return this; } /** * Adds the given shape as one of the parents of this shape. * */ private void addParent(ResultShape p) { if (parents == null) parents = new HashSet>(); parents.add(p); } /** * Adds the given classes as child shapes of this shape. * The child shapes are primitive shapes. */ public ResultShape add(Class... classes) { assertNotPrimitive(); for (Class c : classes) { children.add(new ResultShape(c, true)); } return this; } /** * Gets all the child shapes. */ public List> getChildren() { return Collections.unmodifiableList(children); } /** * Affirms if this shape can have child shapes. */ public boolean isCompound() { return !isPrimitive; } /** * Affirms if this shape can not have any child shape. * A primitive shape uses ASSIGN strategy. */ public boolean isPrimitive() { return isPrimitive; } /** * Affirms if at least one child shape of this shape is a compound shape. */ public boolean isNesting() { return isNesting; } /** * Affirms if this shape is nested within other shapes. */ public boolean isNested() { return parents != null; } /** * Affirms if the given shape is a parent (or grandparent) of this shape. */ public boolean isParent(ResultShape p) { if (p.getParents().contains(this)) return true; if (children != null) { for (ResultShape child : children) { if (child.isParent(p)) return true; } } return false; } void assertNotPrimitive() { if (isPrimitive) throw new UnsupportedOperationException("Can not add/nest shape to primitive shape " + this); } /** * Gets the immediate parents of this shape. */ public Set> getParents() { return parents == null ? Collections.EMPTY_SET : Collections.unmodifiableSet(parents); } /** * Total number of arguments required to populate the shape and all its child shapes. */ public int argLength() { if (isPrimitive() || children.isEmpty()) return 1; int l = 0; for (ResultShape child : children) { l += child.argLength(); } return l; } /** * Number of arguments to populate this shape only. */ public int length() { if (isPrimitive() || children.isEmpty()) return 1; return children.size(); } // ====================================================================================== // Data Population Routines // ====================================================================================== /** * Fill this shape and its children with the given array element values. * The parallel arrays contain the actual values, the types of these values and aliases. * The type and alias information are used for packing Map or invoking constructor. * The type can be different from what can be determined from array elements because * of boxing of primitive types. * The actual constructor argument types are sourced from types[] array. */ public T pack(Object[] values, Class[] types, String[] aliases) { if (values.length < argLength()) // input can be longer than required throw new IndexOutOfBoundsException(values.length + " values are less than " + argLength() + " argumenets required to pack " + this); Object[] args = new Object[length()]; Class[] argTypes = new Class[length()]; String[] argAliases = new String[length()]; if (isPrimitive() || children.isEmpty()) { args[0] = values[0]; argTypes[0] = types[0]; argAliases[0] = aliases[0]; } else { // pack each children int start = 0; int i = 0; for (ResultShape rs : children) { int finish = start + rs.argLength(); args[i] = rs.pack(chop(values, start, finish), chop(types, start, finish), chop(aliases, start, finish)); argTypes[i] = rs.getType(); argAliases[0] = rs.getAlias(); start = finish; i++; } } return (T)strategy.fill(args, argTypes, argAliases); } /** * Chop an array from start to finish. */ X[] chop(X[] values, int start, int finish) { X[] result = (X[])Array.newInstance(values.getClass().getComponentType(), finish-start); System.arraycopy(values, start, result, 0, finish-start); return result; } /** * Gets a human-readable representation of this shape. * */ public String toString() { StringBuilder buf = new StringBuilder(cls.getSimpleName()); if (isPrimitive() || children.isEmpty()) return buf.toString(); int i = 0; for (ResultShape child : children) { buf.append(i++ == 0 ? "{" : ", "); buf.append(child); } if (!children.isEmpty()) buf.append("}"); return buf.toString(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachState.java0000644000000000000000000000263712133327272026336 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Constants for which fields to include in the detach graph. * * @author Abe White * @since 0.4.0 */ public interface DetachState { /** * Mode to detach all fields in the current fetch groups. * * @since 0.9.8 */ public static final int DETACH_FETCH_GROUPS = 0; /** * @deprecated */ public static final int DETACH_FGS = 0; /** * Mode to detach all currently-loaded fields. */ public static final int DETACH_LOADED = 1; /** * Mode to detach all fields. */ public static final int DETACH_ALL = 2; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SaveFieldManager.java0000644000000000000000000002067112133327272027300 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.BitSet; import java.util.Collection; import java.util.Date; import java.util.Map; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.ProxyManager; /** * FieldManager type used to store information for rollback. * * @author Abe White */ public class SaveFieldManager extends ClearFieldManager implements Serializable { private final StateManagerImpl _sm; private final BitSet _unloaded; private BitSet _saved = null; private int[] _copyField = null; private transient PersistenceCapable _state = null; // used to track field value during store/fetch cycle private Object _field = null; /** * Constructor. Provide {@link StateManagerImpl} of instance to save. */ SaveFieldManager(StateManagerImpl sm, PersistenceCapable pc, BitSet dirty) { _sm = sm; _state = pc; // if instance is new or transient all fields will be marked dirty even // though they have their original values, so we can restore them; // otherwise, we need to record already-dirty persistent fields as // ones we won't be able to restore FieldMetaData[] fields = _sm.getMetaData().getFields(); if (_sm.isNew() || !_sm.isPersistent() || dirty == null) _unloaded = new BitSet(fields.length); else { _unloaded = (BitSet) dirty.clone(); for (int i = 0; i < fields.length; i++) if (fields[i].getManagement() != fields[i].MANAGE_PERSISTENT) _unloaded.clear(i); } } /** * Return the persistence capable copy holding the rollback field values. */ public PersistenceCapable getState() { return _state; } /** * Return the currently-loaded fields that will be unloaded after rollback. */ public BitSet getUnloaded() { return _unloaded; } /** * Save the given field. If this method returns true, then you need * to use this field manager to replace the given field in the instance * returned by {@link #getState}. */ public boolean saveField(int field) { // if not loaded we can't save orig value; mark as unloaded on rollback if (_sm.getLoaded() != null && !_sm.getLoaded().get(field)) { _unloaded.set(field); return false; } // already saved? if (_saved != null && _saved.get(field)) return false; FieldMetaData fmd = _sm.getMetaData().getField(field); boolean mutable = false; switch (fmd.getDeclaredTypeCode()) { case JavaTypes.DATE: case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.OBJECT: mutable = true; } // if this is not an inverse field and the proper restore flag is // not set, skip it if (_sm.getBroker().getInverseManager() == null || fmd.getInverseMetaDatas().length == 0) { // use sm's restore directive, not broker's int restore = _sm.getBroker().getRestoreState(); if (restore == RestoreState.RESTORE_NONE || (mutable && restore == RestoreState.RESTORE_IMMUTABLE)) { _unloaded.set(field); return false; } } // prepare to save the field if (_state == null) _state = _sm.getPersistenceCapable().pcNewInstance(_sm, true); if (_saved == null) _saved = new BitSet(_sm.getMetaData().getFields().length); _saved.set(field); // if mutable, return true to indicate that the field needs to be // copied by providing and replacing it using this field manager if (mutable) return true; // immutable fields can just be copied over if (_copyField == null) _copyField = new int[1]; _copyField[0] = field; getState().pcCopyFields(_sm.getPersistenceCapable(), _copyField); return false; } /** * Restore the given field. If this method returns true, then you need * to use this field manager to replace the given field in the state * manager's instance. */ public boolean restoreField(int field) { // if the given field needs to be unloaded, return true so that it gets // replaced with a default value if (_unloaded.get(field)) return true; // if the field was not saved, it must not have gotten dirty; just // return false so that the current value is kept if (_saved == null || !_saved.get(field)) return false; // copy the saved field over if (_copyField == null) _copyField = new int[1]; _copyField[0] = field; _sm.getPersistenceCapable().pcCopyFields(getState(), _copyField); return false; } /** * Compare the given field. * @return true if the field is the same in the current * state and in the saved state; otherwise, false. */ public boolean isFieldEqual(int field, Object current) { // if the field is not available, assume that it has changed. if (_saved == null || !_saved.get(field)) return false; if (!(getState().pcGetStateManager() instanceof StateManagerImpl)) return false; StateManagerImpl sm = (StateManagerImpl) getState().pcGetStateManager(); SingleFieldManager single = new SingleFieldManager(sm, sm.getBroker()); sm.provideField(getState(), single, field); Object old = single.fetchObjectField(field); return current == old || current != null && current.equals(old); } public Object fetchObjectField(int field) { // return the copied field during save, or a null value during restore Object val = _field; _field = null; return val; } public void storeObjectField(int field, Object curVal) { // copy mutable fields ProxyManager proxy = _sm.getBroker().getConfiguration(). getProxyManagerInstance(); FieldMetaData fmd = _sm.getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.ARRAY: _field = proxy.copyArray(curVal); break; case JavaTypes.COLLECTION: _field = proxy.copyCollection((Collection) curVal); break; case JavaTypes.MAP: _field = proxy.copyMap((Map) curVal); break; case JavaTypes.DATE: _field = proxy.copyDate((Date) curVal); break; case JavaTypes.OBJECT: _field = proxy.copyCustom(curVal); if (_field == null) _field = curVal; break; default: _field = curVal; } // if we couldn't get a copy of the sco, act like it wasn't saved if (curVal != null && _field == null) { _unloaded.set(field); _saved.clear(field); } } private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); _sm.writePC(oos, _state); } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); _state = _sm.readPC(ois); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/InMemorySavepointManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/InMemorySavepointManager.j0000644000000000000000000000421212133327272030367 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * A {@link SavepointManager} implementation which stores all data in memory. * * @author Steve Kim * @since 0.3.4 */ public class InMemorySavepointManager implements SavepointManager { private boolean _preFlush = true; /** * Return whether to call {@link Broker#preFlush} * when a savepoint is set. While this will allow for tracking of * newly embedded fields, it has the side effect of going through * pre-flush operations. */ public boolean getPreFlush() { return _preFlush; } /** * Set whether to call {@link Broker#preFlush} * when a savepoint is set. While this will allow for tracking of * newly embedded fields, it has the side effect of going through * pre-flush operations. */ public void setPreFlush(boolean preFlush) { _preFlush = preFlush; } public OpenJPASavepoint newSavepoint(String name, Broker broker) { // pre-flush after creating savepoint b/c pre-flush may add/change // states OpenJPASavepoint save = new OpenJPASavepoint(broker, name, true); if (_preFlush) broker.preFlush(); return save; } public boolean supportsIncrementalFlush() { // cannot incrementally flush as saved fields may become out of synch. return false; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingResultList.java0000644000000000000000000002631212133327272030237 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.ObjectStreamException; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.apache.openjpa.lib.rop.ResultList; import org.apache.openjpa.util.RuntimeExceptionTranslator; /** * Delegating result list that can also perform exception translation * for use in facades. * * @since 0.4.0 * @author Marc Prud'hommeaux * @nojavadoc */ public class DelegatingResultList implements ResultList { private final ResultList _del; private final RuntimeExceptionTranslator _trans; /** * Constructor; supply delegate. */ public DelegatingResultList(ResultList list) { this(list, null); } /** * Constructor; supply delegate and exception translator. */ public DelegatingResultList(ResultList list, RuntimeExceptionTranslator trans) { _del = list; _trans = trans; } /** * Return the direct delegate. */ public ResultList getDelegate() { return _del; } /** * Return the native delegate. */ public ResultList getInnermostDelegate() { return _del instanceof DelegatingResultList ? ((DelegatingResultList) _del).getInnermostDelegate() : _del; } /** * Writes delegate, which may in turn write a normal list. */ public Object writeReplace() throws ObjectStreamException { return _del; } public int hashCode() { try { return getInnermostDelegate().hashCode(); } catch (RuntimeException re) { throw translate(re); } } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingResultList) other = ((DelegatingResultList) other).getInnermostDelegate(); try { return getInnermostDelegate().equals(other); } catch (RuntimeException re) { throw translate(re); } } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public boolean isProviderOpen() { try { return _del.isProviderOpen(); } catch (RuntimeException re) { throw translate(re); } } public Object getUserObject() { try { return _del.getUserObject(); } catch (RuntimeException re) { throw translate(re); } } public void setUserObject(Object opaque) { try { _del.setUserObject(opaque); } catch (RuntimeException re) { throw translate(re); } } public void close() { try { _del.close(); } catch (RuntimeException re) { throw translate(re); } } public boolean isClosed() { try { return _del.isClosed(); } catch (RuntimeException re) { throw translate(re); } } public int size() { try { return _del.size(); } catch (RuntimeException re) { throw translate(re); } } public boolean isEmpty() { try { return _del.isEmpty(); } catch (RuntimeException re) { throw translate(re); } } public boolean contains(Object o) { try { return _del.contains(o); } catch (RuntimeException re) { throw translate(re); } } public Iterator iterator() { return listIterator(); } public Object[] toArray() { try { return _del.toArray(); } catch (RuntimeException re) { throw translate(re); } } public Object[] toArray(Object[] a) { try { return _del.toArray(a); } catch (RuntimeException re) { throw translate(re); } } public boolean add(T o) { try { return _del.add(o); } catch (RuntimeException re) { throw translate(re); } } public boolean remove(Object o) { try { return _del.remove(o); } catch (RuntimeException re) { throw translate(re); } } public boolean containsAll(Collection c) { try { return _del.containsAll(c); } catch (RuntimeException re) { throw translate(re); } } public boolean addAll(Collection c) { try { return _del.addAll(c); } catch (RuntimeException re) { throw translate(re); } } public boolean addAll(int index, Collection c) { try { return _del.addAll(index, c); } catch (RuntimeException re) { throw translate(re); } } public boolean removeAll(Collection c) { try { return _del.removeAll(c); } catch (RuntimeException re) { throw translate(re); } } public boolean retainAll(Collection c) { try { return _del.retainAll(c); } catch (RuntimeException re) { throw translate(re); } } public void clear() { try { _del.clear(); } catch (RuntimeException re) { throw translate(re); } } public T get(int index) { try { return _del.get(index); } catch (RuntimeException re) { throw translate(re); } } public T set(int index, T element) { try { return _del.set(index, element); } catch (RuntimeException re) { throw translate(re); } } public void add(int index, T element) { try { _del.add(index, element); } catch (RuntimeException re) { throw translate(re); } } public T remove(int index) { try { return _del.remove(index); } catch (RuntimeException re) { throw translate(re); } } public int indexOf(Object o) { try { return _del.indexOf(o); } catch (RuntimeException re) { throw translate(re); } } public int lastIndexOf(Object o) { try { return _del.lastIndexOf(o); } catch (RuntimeException re) { throw translate(re); } } public ListIterator listIterator() { try { return new DelegatingListIterator(_del.listIterator()); } catch (RuntimeException re) { throw translate(re); } } public ListIterator listIterator(int index) { try { return new DelegatingListIterator(_del.listIterator(index)); } catch (RuntimeException re) { throw translate(re); } } public List subList(int fromIndex, int toIndex) { try { return _del.subList(fromIndex, toIndex); } catch (RuntimeException re) { throw translate(re); } } public String toString() { try { return _del.toString(); } catch (RuntimeException re) { throw translate(re); } } /** * Delegating iterator that also performs exception translation. */ public class DelegatingListIterator implements ListIterator { private final ListIterator _del; /** * Constructor; supply delegate. */ public DelegatingListIterator(ListIterator it) { _del = it; } /** * Return the direct delegate. */ public ListIterator getDelegate() { return _del; } /** * Return the native delegate. */ public ListIterator getInnermostDelegate() { return _del instanceof DelegatingListIterator ? ((DelegatingListIterator) _del).getInnermostDelegate() : _del; } public int hashCode() { try { return getInnermostDelegate().hashCode(); } catch (RuntimeException re) { throw translate(re); } } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingListIterator) other = ((DelegatingListIterator) other).getInnermostDelegate(); try { return getInnermostDelegate().equals(other); } catch (RuntimeException re) { throw translate(re); } } public boolean hasNext() { try { return _del.hasNext(); } catch (RuntimeException re) { throw translate(re); } } public T next() { try { return _del.next(); } catch (RuntimeException re) { throw translate(re); } } public boolean hasPrevious() { try { return _del.hasPrevious(); } catch (RuntimeException re) { throw translate(re); } } public T previous() { try { return _del.previous(); } catch (RuntimeException re) { throw translate(re); } } public int nextIndex() { try { return _del.nextIndex(); } catch (RuntimeException re) { throw translate(re); } } public int previousIndex() { try { return _del.previousIndex(); } catch (RuntimeException re) { throw translate(re); } } public void remove() { try { _del.remove(); } catch (RuntimeException re) { throw translate(re); } } public void set(T o) { try { _del.set(o); } catch (RuntimeException re) { throw translate(re); } } public void add(T o) { try { _del.add(o); } catch (RuntimeException re) { throw translate (re); } } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ENonTransState.java0000644000000000000000000000471312133327272027012 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an embedded instance that is not transactional, but that * allows access to persistent data. This state is reachable only if the * retainValues flag of the broker is set. * * @author Abe White */ @SuppressWarnings("serial") class ENonTransState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { if (previous == null) return; // spec says all proxies to second class objects should be reset context.proxyFields(true, true); context.setDirty(false); context.clearSavedFields(); } PCState delete(StateManagerImpl context) { context.preDelete(); return EDELETED; } PCState transactional(StateManagerImpl context) { // state is discarded when entering the transaction if (!context.getBroker().getOptimistic()) context.clearFields(); return ECLEAN; } PCState release(StateManagerImpl context) { return TRANSIENT; } PCState evict(StateManagerImpl context) { return TRANSIENT; } PCState beforeRead(StateManagerImpl context, int field) { return error("embed-ref", context); } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return error("embed-ref", context); } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return EDIRTY; } boolean isPersistent() { return true; } public String toString() { return "Embedded-Nontransactional"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreQuery.java0000644000000000000000000003200112133327272026253 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.util.Iterator; import java.util.Map; import org.apache.commons.collections.map.LinkedMap; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.Constant; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.kernel.exps.QueryExpressions; import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; /** * Component that executes queries against the datastore. For * expression-based queries, consider subclassing * {@link ExpressionStoreManagerQuery}. * * @author Abe White * @since 0.4.0 */ public interface StoreQuery extends QueryOperations, Serializable { // linkedmap doesn't allow a size of 0, so use 1 // This is deprecated public static final LinkedMap EMPTY_PARAMS = new LinkedMap(1); public static final OrderedMap> EMPTY_ORDERED_PARAMS = new OrderedMap>(); public static final ClassMetaData[] EMPTY_METAS = new ClassMetaData[0]; public static final String[] EMPTY_STRINGS = new String[0]; public static final Object[] EMPTY_OBJECTS = new Object[0]; public static final Class[] EMPTY_CLASSES = new Class[0]; public static final boolean[] EMPTY_BOOLEANS = new boolean[0]; /** * Return the query context that has been set. */ public QueryContext getContext(); /** * Set the current query context. This will be called before use. */ public void setContext(QueryContext ctx); /** * This is invoked when the user or a facade creates a new query with * an object that the system does not recognize. Return true if * the object is recognized by the store, false otherwise. */ public boolean setQuery(Object query); /** * Return the standard filter listener for the given tag, or null. */ public FilterListener getFilterListener(String tag); /** * Return the standard filter listener for the given tag, or null. */ public AggregateListener getAggregateListener(String tag); /** * Create a new key for caching compiled query information. May be null. */ public Object newCompilationKey(); /** * Create a new compilation for this query. May be null. */ public Object newCompilation(); /** * Get the current compilation for this query. If it is null, do not create. */ public Object getCompilation(); /** * Populate internal data from compilation. */ public void populateFromCompilation(Object comp); /** * Invalidate any internal compilation state. */ public void invalidateCompilation(); /** * True if this query supports datastore execution, false if it * can only run in memory. */ public boolean supportsDataStoreExecution(); /** * True if this query supports in-memory execution, false if it * can only run against the datastore. */ public boolean supportsInMemoryExecution(); /** * Return an executor for in-memory execution of this query. * Executors must be cachable and thread safe. If this class returns * true from {@link #supportsAbstractExecutors}, the given metadata * will always be for the candidate class of this query, or possibly * null if the candidate class is not itself persistence capable (like * an interface or abstract base class). Otherwise, the given type will * be a mapped class. * * @param subs whether to include dependent mapped subclasses in the * results; independent subclasses should never be included */ public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs); /** * Return an executor for datastore execution of this query. * Executors must be cachable and thread safe. If this class returns * true from {@link #supportsAbstractExecutors}, the given metadata * will always be for the candidate class of this query, or possibly * null if the candidate class is not itself persistence capable (like * an interface or abstract base class). Otherwise, the given type will * be a mapped class. * * @param subs whether to include dependent mapped subclasses in the * results; independent subclasses should never be included */ public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs); /** * Return true if this query supports execution against abstract or * interface types. Returns false by default, meaning we will only * request executors for persistent classes. In this case, we will * automatically combine the results of the executors for all * implementing classes if we execute a query for an interface for * abstract type. */ public boolean supportsAbstractExecutors(); /** * Whether this query requires a candidate class. */ public boolean requiresCandidateType(); /** * Whether this query requires parameters to be declared. */ public boolean requiresParameterDeclarations(); /** * Whether this query supports declared parameters. */ public boolean supportsParameterDeclarations(); public Object evaluate(Object value, Object ob, Object[] params, OpenJPAStateManager sm); /** * A query result range. */ public static class Range { public long start = 0L; public long end = Long.MAX_VALUE; public boolean lrs = false; public Range() { } public Range(long start, long end) { this.start = start; this.end = end; } } /** * An executor provides a uniform interface to the mechanism for executing * either an in-memory or datastore query. In the common case, the * {@link #executeQuery} method will be called before other methods, * though this is not guaranteed. * * @author Marc Prud'hommeaux */ public static interface Executor { /** * Return the result of executing this query with the given parameter * values. If this query is a projection and this executor does not * pack results itself, each element of the returned result object * provider should be an object array containing the projection values. * * @param lrs true if the query result should be treated as a * large result set, assuming the query is not an * aggregate and does not have grouping * @see #isPacking */ public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, Range range); /** * Deleted the objects that result from the execution of the * query, retuning the number of objects that were deleted. */ public Number executeDelete(StoreQuery q, Object[] params); /** * Updates the objects that result from the execution of the * query, retuning the number of objects that were updated. */ public Number executeUpdate(StoreQuery q, Object[] params); /** * Return a description of the commands that will be sent to * the datastore in order to execute the query. */ public String[] getDataStoreActions(StoreQuery q, Object[] params, Range range); /** * Validate components of query. */ public void validate(StoreQuery q); /** * Mutate the given range to set any range information stored in * the query string and/or parameters. */ public void getRange(StoreQuery q, Object[] params, Range range); /** * Extract the value of the orderIndexth ordering * expression in {@link Query#getOrderingClauses} from the * given result object. The result object will be an object from * the result object provider returned from {@link #executeQuery}. * This method is used when several result lists have to be merged * in memory. If this exeuctor's parent query supports executors on * abstract or interface classes, this method will not be used. * * @see StoreQuery#supportsAbstractExecutors */ public Object getOrderingValue(StoreQuery q, Object[] params, Object resultObject, int orderIndex); /** * Return the ordering direction for all ordering clauses, or empty * array if none. */ public boolean[] getAscending(StoreQuery q); /** * Return true if this executor packs projections into the result * class itself. Executors for query languages that allow projections * without result clauses must return true and perform the result * packing themselves. */ public boolean isPacking(StoreQuery q); /** * If this is not a projection but the candidate results are placed * into a result class with an alias, return that alias. */ public String getAlias(StoreQuery q); /** * Return the alias for each projection element, or empty array * if not a projection. */ public String[] getProjectionAliases(StoreQuery q); /** * Return the expected types of the projections used by this query, * or an empty array if not a projection. */ public Class[] getProjectionTypes(StoreQuery q); /** * Return an array of all persistent classes used in this query, or * empty array if unknown. */ public ClassMetaData[] getAccessPathMetaDatas(StoreQuery q); /** * Returns the operation this executor is meant to execute. * * @see QueryOperations */ public int getOperation(StoreQuery q); /** * Return true if the compiled query is an aggregate. */ public boolean isAggregate(StoreQuery q); public boolean isDistinct(StoreQuery q); /** * Whether the compiled query has grouping. */ public boolean hasGrouping(StoreQuery q); /** * Return a map of parameter names to types. The returned * {@link Map#entrySet}'s {@link Iterator} must return values in the * order in which they were declared or used. */ public OrderedMap> getOrderedParameterTypes(StoreQuery q); /** * Return a map of parameter names to types. The returned * {@link Map#entrySet}'s {@link Iterator} must return values in the * order in which they were declared or used.
    * * Warning: Deprecated. Use {@linkplain #getOrderedParameterTypes(StoreQuery)} instead. */ @Deprecated public LinkedMap getParameterTypes(StoreQuery q); /** * Return an array from the given user parameter values. * The array ordering is same as what this executor expects for its * executeXXX() methods as its Object[] parameters. * If the given userParams is null or empty return an empty array * rather than null. * * @return array with parameter values ordered in the same way as this * receiver's executeXXX() method expects. * * @since 2.0.0 */ public Object[] toParameterArray(StoreQuery q, Map userParams); /** * Returns the result class, if any. */ public Class getResultClass(StoreQuery q); public ResultShape getResultShape(StoreQuery q); /** * Return a map of {@link FieldMetaData} to update * {@link Constant}s, in cases where this query is for a bulk update. */ public Map getUpdates (StoreQuery q); /** * Return the parsed query expressions for our candidate types. * The expressions are available only after query has been parsed. * * @since 2.0.0 */ public QueryExpressions[] getQueryExpressions(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachManager.java0000644000000000000000000003017712133327272026644 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.collections.map.IdentityMap; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.event.CallbackModes; import org.apache.openjpa.event.LifecycleEvent; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.CallbackException; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.OptimisticException; import org.apache.openjpa.util.ProxyManager; import org.apache.openjpa.util.UserException; /** * Handles attaching instances. * * @author Marc Prud'hommeaux */ public class AttachManager { private static final Localizer _loc = Localizer.forPackage (AttachManager.class); private final BrokerImpl _broker; private final ProxyManager _proxy; private final OpCallbacks _call; private final boolean _copyNew; private final boolean _failFast; private final IdentityMap _attached = new IdentityMap(); private final Collection _visitedNodes = new ArrayList(); // reusable strategies private AttachStrategy _version; private AttachStrategy _detach; /** * Constructor. Supply broker attaching to. */ public AttachManager(BrokerImpl broker, boolean copyNew, OpCallbacks call) { _broker = broker; _proxy = broker.getConfiguration().getProxyManagerInstance(); _call = call; _copyNew = copyNew; _failFast = (broker.getConfiguration().getMetaDataRepositoryInstance(). getMetaDataFactory().getDefaults().getCallbackMode() & CallbackModes.CALLBACK_FAIL_FAST) != 0; } /** * Return the behavior supplied on construction. */ public OpCallbacks getBehavior() { return _call; } /** * Return whether to copy new instances being persisted. */ public boolean getCopyNew() { return _copyNew; } /** * Return an attached version of the given instance. */ public Object attach(Object pc) { if (pc == null) return null; CallbackException excep = null; try { return attach(pc, null, null, null, true); } catch (CallbackException ce) { excep = ce; return null; // won't be reached as the exceps will be rethrown } finally { List exceps = null; if (excep == null || !_failFast) exceps = invokeAfterAttach(null); else exceps = Collections.singletonList(excep); _attached.clear(); throwExceptions(exceps, null, false); } } /** * Return attached versions of the given instances. */ public Object[] attachAll(Collection instances) { Object[] attached = new Object[instances.size()]; List exceps = null; List failed = null; boolean opt = true; boolean failFast = false; try { int i = 0; for (Iterator itr = instances.iterator(); itr.hasNext(); i++) { try { attached[i] = attach(itr.next(), null, null, null, true); } catch (OpenJPAException ke) { // track exceptions and optimistic failed objects if (opt && !(ke instanceof OptimisticException)) opt = false; if (opt && ke.getFailedObject() != null) failed = add(failed, ke.getFailedObject()); exceps = add(exceps, ke); if (ke instanceof CallbackException && _failFast) { failFast = true; break; } } catch (RuntimeException re) { exceps = add(exceps, re); } } } finally { // invoke post callbacks unless all failed if (!failFast && (exceps == null || exceps.size() < instances.size())) exceps = invokeAfterAttach(exceps); _attached.clear(); } throwExceptions(exceps, failed, opt); return attached; } /** * Invoke postAttach() on any attached instances that implement * PostAttachCallback. This will be done after the entire graph has * been attached. */ private List invokeAfterAttach(List exceps) { Set entries = _attached.entrySet(); for (Iterator i = entries.iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); Object attached = entry.getValue(); StateManagerImpl sm = _broker.getStateManagerImpl(attached, true); if (sm.isNew()) continue; try { _broker.fireLifecycleEvent(attached, entry.getKey(), sm.getMetaData(), LifecycleEvent.AFTER_ATTACH); } catch (RuntimeException re) { exceps = add(exceps, re); if (_failFast && re instanceof CallbackException) break; } } return exceps; } /** * Add an object to the list. */ private List add(List list, Object obj) { if (list == null) list = new LinkedList(); list.add(obj); return list; } /** * Throw exception for failures. */ private void throwExceptions(List exceps, List failed, boolean opt) { if (exceps == null) return; if (exceps.size() == 1) throw (RuntimeException) exceps.get(0); Throwable[] t = (Throwable[]) exceps.toArray (new Throwable[exceps.size()]); if (opt && failed != null) throw new OptimisticException(failed, t); if (opt) throw new OptimisticException(t); throw new UserException(_loc.get("nested-exceps")). setNestedThrowables(t); } /** * Attach. * * @param toAttach the detached object * @param into the instance we're attaching into * @param owner state manager for into * @param ownerMeta the field we traversed to find toAttach * @param explicit whether to make new instances explicitly persistent */ Object attach(Object toAttach, PersistenceCapable into, OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit) { if (toAttach == null) return null; // check if already attached Object attached = _attached.get(toAttach); if (attached != null) return attached; //### need to handle ACT_CASCADE int action = processArgument(toAttach); if ((action & OpCallbacks.ACT_RUN) == 0 && (action & OpCallbacks.ACT_CASCADE) != 0) { if(_visitedNodes.contains(_broker.getStateManager(toAttach))) return toAttach; return handleCascade(toAttach,owner); } if ((action & OpCallbacks.ACT_RUN) == 0) return toAttach; //### need to handle ACT_RUN without also ACT_CASCADE ClassMetaData meta = _broker.getConfiguration(). getMetaDataRepositoryInstance().getMetaData( ImplHelper.getManagedInstance(toAttach).getClass(), _broker.getClassLoader(), true); return getStrategy(toAttach).attach(this, toAttach, meta, into, owner, ownerMeta, explicit); } private Object handleCascade(Object toAttach, OpenJPAStateManager owner) { StateManagerImpl sm = _broker.getStateManagerImpl(toAttach, true); BitSet loaded = sm.getLoaded(); FieldMetaData[] fmds = sm.getMetaData().getDefinedFields(); for (FieldMetaData fmd : fmds) { if (fmd.getElement().getCascadeAttach() == ValueMetaData.CASCADE_IMMEDIATE) { FieldMetaData[] inverseFieldMappings = fmd.getInverseMetaDatas(); if (inverseFieldMappings.length != 0) { _visitedNodes.add(sm); // Only try to attach this field is it is loaded if (loaded.get(fmd.getIndex())) { getStrategy(toAttach).attachField(this, toAttach, sm, fmd, true); } } } } return toAttach; } /** * Determine the action to take on the given argument. */ private int processArgument(Object obj) { if (_call == null) return OpCallbacks.ACT_RUN; return _call.processArgument(OpCallbacks.OP_ATTACH, obj, _broker.getStateManager(obj)); } /** * Calculate proper attach strategy for instance. */ private AttachStrategy getStrategy(Object toAttach) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(toAttach, getBroker().getConfiguration()); if (pc.pcGetStateManager() instanceof AttachStrategy) return (AttachStrategy) pc.pcGetStateManager(); Object obj = pc.pcGetDetachedState(); if (obj instanceof AttachStrategy) return (AttachStrategy) obj; if (obj == null || obj == PersistenceCapable.DESERIALIZED) { // new or detached without state if (_version == null) _version = new VersionAttachStrategy(); return _version; } // detached state if (_detach == null) _detach = new DetachedStateAttachStrategy(); return _detach; } /** * Owning broker. */ BrokerImpl getBroker() { return _broker; } /** * System proxy manager. */ ProxyManager getProxyManager() { return _proxy; } /** * If the passed in argument has already been attached, return * the (cached) attached copy. */ PersistenceCapable getAttachedCopy(Object pc) { return ImplHelper.toPersistenceCapable(_attached.get(pc), getBroker().getConfiguration()); } /** * Record the attached copy in the cache. */ void setAttachedCopy(Object from, PersistenceCapable into) { _attached.put(from, into); } /** * Fire before-attach event. */ void fireBeforeAttach(Object pc, ClassMetaData meta) { _broker.fireLifecycleEvent(pc, null, meta, LifecycleEvent.BEFORE_ATTACH); } /** * Return the detached oid of the given instance. */ Object getDetachedObjectId(Object pc) { if (pc == null) return null; return getStrategy(pc).getDetachedObjectId(this, pc); } /** * Throw an exception if the given object is not managed; otherwise * return its state manager. */ StateManagerImpl assertManaged(Object obj) { StateManagerImpl sm = _broker.getStateManagerImpl(obj, true); if (sm == null) throw new UserException(_loc.get("not-managed", Exceptions.toString(obj))).setFailedObject (obj); return sm; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBrokerFactory.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBrokerFactory.ja0000644000000000000000000001511512133327272030351 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Map; import java.util.Properties; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.util.RuntimeExceptionTranslator; /////////////////////////////////////////////////////////////// // NOTE: when adding a public API method, be sure to add it to // JDO and JPA facades! /////////////////////////////////////////////////////////////// /** * Delegating broker factory that can also perform exception translation * for use in facades. * * @since 0.4.0 * @author Abe White * @nojavadoc */ public class DelegatingBrokerFactory implements BrokerFactory { private final BrokerFactory _factory; private final DelegatingBrokerFactory _del; private final RuntimeExceptionTranslator _trans; /** * Constructor; supply delegate. */ public DelegatingBrokerFactory(BrokerFactory factory) { this(factory, null); } /** * Constructor; supply delegate and exception translator. */ public DelegatingBrokerFactory(BrokerFactory factory, RuntimeExceptionTranslator trans) { _factory = factory; if (factory instanceof DelegatingBrokerFactory) _del = (DelegatingBrokerFactory) factory; else _del = null; _trans = trans; } /** * Return the direct delegate. */ public BrokerFactory getDelegate() { return _factory; } /** * Return the native delegate. */ public BrokerFactory getInnermostDelegate() { return (_del == null) ? _factory : _del.getInnermostDelegate(); } public int hashCode() { return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingBrokerFactory) other = ((DelegatingBrokerFactory) other).getInnermostDelegate(); return getInnermostDelegate().equals(other); } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public OpenJPAConfiguration getConfiguration() { try { return _factory.getConfiguration(); } catch (RuntimeException re) { throw translate(re); } } public Map getProperties() { try { return _factory.getProperties(); } catch (RuntimeException re) { throw translate(re); } } public Set getSupportedProperties() { try { return _factory.getSupportedProperties(); } catch (RuntimeException re) { throw translate(re); } } public Object putUserObject(Object key, Object val) { try { return _factory.putUserObject(key, val); } catch (RuntimeException re) { throw translate(re); } } public Object getUserObject(Object key) { try { return _factory.getUserObject(key); } catch (RuntimeException re) { throw translate(re); } } public Broker newBroker() { try { return _factory.newBroker(); } catch (RuntimeException re) { throw translate(re); } } public Broker newBroker(String user, String pass, boolean managed, int connRetainMode, boolean findExisting) { return newBroker(user, pass, managed, connRetainMode, findExisting, "", ""); } public Broker newBroker(String user, String pass, boolean managed, int connRetainMode, boolean findExisting, String cfName, String cf2Name) { try { return _factory.newBroker(user, pass, managed, connRetainMode, findExisting, cfName, cf2Name); } catch (RuntimeException re) { throw translate(re); } } public void addLifecycleListener(Object listener, Class[] classes) { try { _factory.addLifecycleListener(listener, classes); } catch (RuntimeException re) { throw translate(re); } } public void removeLifecycleListener(Object listener) { try { _factory.removeLifecycleListener(listener); } catch (RuntimeException re) { throw translate(re); } } public void addTransactionListener(Object listener) { try { _factory.addTransactionListener(listener); } catch (RuntimeException re) { throw translate(re); } } public void removeTransactionListener(Object listener) { try { _factory.removeTransactionListener(listener); } catch (RuntimeException re) { throw translate(re); } } public void close() { try { _factory.close(); } catch (RuntimeException re) { throw translate(re); } } public boolean isClosed() { try { return _factory.isClosed(); } catch (RuntimeException re) { throw translate(re); } } public void lock() { try { _factory.lock(); } catch (RuntimeException re) { throw translate(re); } } public void unlock() { try { _factory.unlock(); } catch (RuntimeException re) { throw translate(re); } } public void assertOpen() { try { _factory.assertOpen(); } catch (RuntimeException re) { throw translate(re); } } public void postCreationCallback() { try { _factory.postCreationCallback(); } catch (RuntimeException re) { throw translate(re); } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractPCResultObjectProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractPCResultObjectProv0000644000000000000000000001147512133327272030410 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.ObjectNotFoundException; import org.apache.openjpa.util.StoreException; /** * Abstract implementation of {@link PCResultObjectProvider} * that implements {@link ResultObjectProvider#getResultObject} * by assembling the necessary information about the object to be loaded. * * @author Patrick Linskey */ public abstract class AbstractPCResultObjectProvider implements PCResultObjectProvider { /** * The {@link StoreContext} that this result object * provider will load objects into. */ protected final StoreContext ctx; /** * Create a new provider for loading PC objects from the input * into ctx. */ public AbstractPCResultObjectProvider(StoreContext ctx) { this.ctx = ctx; } /** * Return the context this provider was constructed with. */ public StoreContext getContext() { return ctx; } public void initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch) throws Exception { sm.initialize(getPCType(), state); load(sm, fetch); } public Object getResultObject() throws Exception { Class type = getPCType(); MetaDataRepository repos = ctx.getConfiguration(). getMetaDataRepositoryInstance(); ClassMetaData meta = repos.getMetaData (type, ctx.getClassLoader(), true); Object oid = getObjectId(meta); Object res = ctx.find(oid, null, null, this, 0); if (res == null) throw new ObjectNotFoundException(oid); return res; } /** * Implement this method to extract the object id value from the * current record of the input. */ protected abstract Object getObjectId(ClassMetaData meta) throws Exception; /** * Implement this method to extract the type of the pc stored * in the current record of the input. */ protected abstract Class getPCType() throws Exception; /** * Load data from the current input record into the given state * manager. Remember to call {@link OpenJPAStateManager#setVersion} to set * the optimistic versioning information, if it has any. */ protected abstract void load(OpenJPAStateManager sm, FetchConfiguration fetch) throws Exception; /** * Override if desired. Does nothing by default. */ public void open() throws Exception { } /** * Override if desired. Returns false by default. * * @see ResultObjectProvider#supportsRandomAccess */ public boolean supportsRandomAccess() { return false; } /** * Implement this method to advance the input. * * @see ResultObjectProvider#next */ public abstract boolean next() throws Exception; /** * Override if desired. Throws an exception by default. * * @see ResultObjectProvider#absolute */ public boolean absolute(int pos) throws Exception { throw new UnsupportedOperationException(); } /** * Override if desired. Returns {@link Integer#MAX_VALUE} by default. * * @see ResultObjectProvider#size */ public int size() throws Exception { return Integer.MAX_VALUE; } /** * Override if desired. Throws an exception by default. * * @see ResultObjectProvider#reset */ public void reset() throws Exception { throw new UnsupportedOperationException(); } /** * Override if desired. Does nothing by default. * * @see ResultObjectProvider#close */ public void close() throws Exception { } /** * Throws a {@link StoreException} by default. */ public void handleCheckedException(Exception e) { throw new StoreException (e); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/MethodStoreQuery.java0000644000000000000000000002575712133327272027440 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.collections.map.LinkedMap; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.lib.rop.ListResultObjectProvider; import org.apache.openjpa.lib.rop.RangeResultObjectProvider; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; /** * A query that is executed by a user-defined method. * * @author Abe White * @nojavadoc */ public class MethodStoreQuery extends AbstractStoreQuery { public static final String LANGUAGE = QueryLanguages.LANG_METHODQL; private static final Class[] ARGS_DATASTORE = new Class[]{ StoreContext.class, ClassMetaData.class, boolean.class, Map.class, FetchConfiguration.class }; private static final Class[] ARGS_INMEM = new Class[]{ StoreContext.class, ClassMetaData.class, boolean.class, Object.class, Map.class, FetchConfiguration.class }; private static final int OBJ_INDEX = 3; private static final Localizer _loc = Localizer.forPackage (MethodStoreQuery.class); private OrderedMap> _params = null; public void invalidateCompilation() { if (_params != null) _params.clear(); } public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs) { return new MethodExecutor(this, meta, subs, true); } public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs) { return new MethodExecutor(this, meta, subs, false); } public boolean supportsInMemoryExecution() { return true; } public boolean supportsDataStoreExecution() { return true; } public boolean requiresCandidateType() { return false; } /** * Parse the parameter declarations. */ private OrderedMap> bindParameterTypes() { ctx.lock(); try { if (_params != null) return _params; String params = ctx.getParameterDeclaration(); if (params == null) return EMPTY_ORDERED_PARAMS; List decs = Filters.parseDeclaration(params, ',', "parameters"); if (_params == null) _params = new OrderedMap>(); String name; Class cls; for (int i = 0; i < decs.size(); i += 2) { name = (String) decs.get(i); cls = ctx.classForName(name, null); if (cls == null) throw new UserException(_loc.get("bad-param-type", name)); _params.put(decs.get(i + 1), cls); } return _params; } finally { ctx.unlock(); } } /** * Uses a user-defined method named by the filter string to execute the * query. */ private static class MethodExecutor extends AbstractExecutor implements Executor { private final ClassMetaData _meta; private final boolean _subs; private final boolean _inMem; private Method _meth = null; public MethodExecutor(MethodStoreQuery q, ClassMetaData candidate, boolean subclasses, boolean inMem) { _meta = candidate; _subs = subclasses; _inMem = inMem; } public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, Range range) { // convert the parameters into a map Map paramMap; if (params.length == 0) paramMap = Collections.EMPTY_MAP; else { Map paramTypes = q.getContext().getOrderedParameterTypes(); paramMap = new HashMap((int) (params.length * 1.33 + 1)); int idx = 0; for (Iterator itr = paramTypes.keySet().iterator(); itr.hasNext(); idx++) paramMap.put(itr.next(), params[idx]); } FetchConfiguration fetch = q.getContext().getFetchConfiguration(); StoreContext sctx = q.getContext().getStoreContext(); ResultObjectProvider rop; Object[] args; if (_inMem) { args = new Object[]{ sctx, _meta, (_subs) ? Boolean.TRUE : Boolean.FALSE, null, paramMap, fetch }; Iterator itr = null; Collection coll = q.getContext().getCandidateCollection(); if (coll == null) { Extent ext = q.getContext().getQuery(). getCandidateExtent(); itr = ext.iterator(); } else itr = coll.iterator(); List results = new ArrayList(); try { Object obj; while (itr.hasNext()) { obj = itr.next(); if (obj == null || !_meta.getDescribedType().isInstance(obj)) continue; args[OBJ_INDEX] = obj; if (((Boolean) invoke(q, args)).booleanValue()) results.add(obj); } } finally { ImplHelper.close(itr); } rop = new ListResultObjectProvider(results); } else { // datastore args = new Object[]{ sctx, _meta, (_subs) ? Boolean.TRUE : Boolean.FALSE, paramMap, fetch }; rop = (ResultObjectProvider) invoke(q, args); } if (range.start != 0 || range.end != Long.MAX_VALUE) rop = new RangeResultObjectProvider(rop, range.start,range.end); return rop; } /** * Invoke the internal method with the given arguments, returning the * result. */ private Object invoke(StoreQuery q, Object[] args) { validate(q); try { return _meth.invoke(null, args); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new UserException(_loc.get("method-error", _meth, Exceptions.toString(Arrays.asList(args))), e); } } public void validate(StoreQuery q) { if (_meth != null) return; String methName = q.getContext().getQueryString(); if (StringUtils.isEmpty(methName)) throw new UserException(_loc.get("no-method")); int dotIdx = methName.lastIndexOf('.'); Class cls; if (dotIdx == -1) cls = _meta.getDescribedType(); else { cls = q.getContext().classForName(methName.substring(0, dotIdx), null); if (cls == null) throw new UserException(_loc.get("bad-method-class", methName.substring(0, dotIdx), methName)); methName = methName.substring(dotIdx + 1); } Method meth; Class[] types = (_inMem) ? ARGS_INMEM : ARGS_DATASTORE; try { meth = cls.getMethod(methName, types); } catch (Exception e) { String msg = (_inMem) ? "bad-inmem-method" : "bad-datastore-method"; throw new UserException(_loc.get(msg, methName, cls)); } if (!Modifier.isStatic(meth.getModifiers())) throw new UserException(_loc.get("method-not-static", meth)); if (!ResultObjectProvider.class.isAssignableFrom( meth.getReturnType())) throw new UserException(_loc.get("method-return-type-invalid", meth, meth.getReturnType())); _meth = meth; } public OrderedMap> getOrderedParameterTypes(StoreQuery q) { return ((MethodStoreQuery) q).bindParameterTypes(); } public Object[] toParameterArray(StoreQuery q, Map userParams) { if (userParams == null || userParams.isEmpty()) return StoreQuery.EMPTY_OBJECTS; OrderedMap> paramTypes = getOrderedParameterTypes(q); Object[] arr = new Object[userParams.size()]; int base = positionalParameterBase(userParams.keySet()); for (Object key : paramTypes.keySet()) { int idx = (key instanceof Integer) ? ((Integer)key).intValue() - base : paramTypes.indexOf(key); if (idx >= arr.length || idx < 0) throw new UserException(_loc.get("gap-query-param", new Object[]{q.getContext().getQueryString(), key, userParams.size(), userParams})); arr[idx] = userParams.get(key); } return arr; } /** * Return the base (generally 0 or 1) to use for positional parameters. */ private static int positionalParameterBase(Collection params) { int low = Integer.MAX_VALUE; Object obj; int val; for (Iterator itr = params.iterator(); itr.hasNext();) { obj = itr.next(); if (!(obj instanceof Number)) return 0; // use 0 base when params are mixed types val = ((Number) obj).intValue(); if (val == 0) return val; if (val < low) low = val; } return low; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNewDeletedState.java0000644000000000000000000000451712133327272027305 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an instance that was made persistent, then deleted within the * current transaction. * * @author Abe White */ @SuppressWarnings("serial") class PNewDeletedState extends PCState { PCState commit(StateManagerImpl context) { return TRANSIENT; } PCState commitRetain(StateManagerImpl context) { return TRANSIENT; } PCState rollback(StateManagerImpl context) { return TRANSIENT; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return TRANSIENT; } PCState persist(StateManagerImpl context) { context.eraseFlush(); return PNEW; } PCState nontransactional(StateManagerImpl context) { return error("deleted", context); } PCState release(StateManagerImpl context) { return error("deleted", context); } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } boolean isTransactional() { return true; } boolean isPersistent() { return true; } boolean isNew() { return true; } boolean isDeleted() { return true; } boolean isDirty() { return true; } public String toString() { return "Persistent-New-Deleted"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractFieldManager.java0000644000000000000000000000604412133327272030143 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.enhance.FieldManager; import org.apache.openjpa.util.InternalException; /** * Abstract {@link FieldManager} for easy subclassing. Throws exceptions * for all methods. * * @author Abe White */ abstract class AbstractFieldManager implements FieldManager { public boolean fetchBooleanField(int field) { throw new InternalException(); } public byte fetchByteField(int field) { throw new InternalException(); } public char fetchCharField(int field) { throw new InternalException(); } public double fetchDoubleField(int field) { throw new InternalException(); } public float fetchFloatField(int field) { throw new InternalException(); } public int fetchIntField(int field) { throw new InternalException(); } public long fetchLongField(int field) { throw new InternalException(); } public Object fetchObjectField(int field) { throw new InternalException(); } public short fetchShortField(int field) { throw new InternalException(); } public String fetchStringField(int field) { throw new InternalException(); } public void storeBooleanField(int field, boolean curVal) { throw new InternalException(); } public void storeByteField(int field, byte curVal) { throw new InternalException(); } public void storeCharField(int field, char curVal) { throw new InternalException(); } public void storeDoubleField(int field, double curVal) { throw new InternalException(); } public void storeFloatField(int field, float curVal) { throw new InternalException(); } public void storeIntField(int field, int curVal) { throw new InternalException(); } public void storeLongField(int field, long curVal) { throw new InternalException(); } public void storeObjectField(int field, Object curVal) { throw new InternalException(); } public void storeShortField(int field, short curVal) { throw new InternalException(); } public void storeStringField(int field, String curVal) { throw new InternalException(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCData.java0000644000000000000000000000635512133327272025242 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.util.BitSet; /** * Holds data about a single persistence capable instance. This interface is * used in the caching framework, and may also be used by simple store manager * back-ends to hold persistent state. * * @author Patrick Linskey */ public interface PCData extends Serializable { /** * Return the id of this instance. */ public Object getId(); /** * Return the type of this instance. */ public Class getType(); /** * Returns the instance-level impl data, or null if none. */ public Object getImplData(); /** * Sets the stored instance-level impl data. */ public void setImplData(Object val); /** * Returns the current version object that this data was loaded from. */ public Object getVersion(); /** * Sets the current version object that this data was loaded from. */ public void setVersion(Object version); /** * Loads all fields that are currently stored in the cache * into the given state manager. * * @param sm the state manager to load * @param fetch the fetch configuration to use for loading related objects * @param context current context information */ public void load(OpenJPAStateManager sm, FetchConfiguration fetch, Object context); /** * Loads some or all of the marked fields from the cache into the * given state manager. * * @param sm the state manager to load * @param fields the fields to load; clear the bits for the fields * that are successfully loaded * @param fetch the fetch configuration to use for loading related objects * @param context current context information */ public void load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch, Object context); /** * Store all loaded fields of the state manager. */ public void store(OpenJPAStateManager sm); /** * Store the given fields from the state manager. */ public void store(OpenJPAStateManager sm, BitSet fields); /** * Return the data stored in the given field index. */ public Object getData(int i); /** * Whether the given field index has stored data. */ public boolean isLoaded(int i); /** * Get the name of the cache where this data is stored. */ public String getCache(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ManagedCache.java0000644000000000000000000002471512133327272026426 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.ReferenceHashSet; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.UserException; /** * Cache of managed objects. Must be static for serialization reasons. */ class ManagedCache implements Serializable { private static final Localizer _loc = Localizer.forPackage(ManagedCache.class); private Map _main; // oid -> sm private Map _conflicts = null; // conflict oid -> new sm private Map _news = null; // tmp id -> new sm private Collection _embeds = null; // embedded/non-persistent sms private Collection _untracked = null; // hard refs to untracked sms private BrokerImpl broker; /** * Constructor; supply primary cache map. */ ManagedCache(BrokerImpl broker) { this.broker = broker; _main = (Map) broker.newManagedObjectCache(); } /** * Return the instance for the given oid, optionally allowing * new instances. */ public StateManagerImpl getById(Object oid, boolean allowNew) { if (oid == null) return null; // check main cache for oid StateManagerImpl sm = _main.get(oid); StateManagerImpl sm2; if (sm != null) { // if it's a new instance, we know it's the only match, because // other pers instances override new instances in _cache if (sm.isNew() && !sm.isDeleted()) return (allowNew) ? sm : null; if (!allowNew || !sm.isDeleted()) return sm; // sm is deleted; check conflict cache if (_conflicts != null) { sm2 = _conflicts.get(oid); if (sm2 != null) return sm2; } } // at this point sm is null or deleted; check the new cache for // any matches. this allows us to match app id objects to new // instances without permanent oids if (allowNew && _news != null && !_news.isEmpty()) { sm2 = _news.get(oid); if (sm2 != null) return sm2; } return sm; } /** * Call this method when a new state manager initializes itself. */ public void add(StateManagerImpl sm) { if (!sm.isIntercepting()) { if (_untracked == null) _untracked = new HashSet(); _untracked.add(sm); } if (!sm.isPersistent() || sm.isEmbedded()) { if (_embeds == null) _embeds = new ReferenceHashSet(ReferenceHashSet.WEAK); _embeds.add(sm); return; } // initializing new instance; put in new cache because won't have // permanent oid yet if (sm.isNew()) { if (_news == null) _news = new HashMap(); _news.put(sm.getId(), sm); return; } // initializing persistent instance; put in main cache StateManagerImpl orig = _main.put(sm.getObjectId(), sm); if (orig != null) { _main.put(sm.getObjectId(), orig); throw new UserException(_loc.get("dup-load", sm.getObjectId(), Exceptions.toString(orig.getManagedInstance()))) .setFailedObject(sm.getManagedInstance()); } } /** * Remove the given state manager from the cache when it transitions * to transient. */ public void remove(Object id, StateManagerImpl sm) { // if it has a permanent oid, remove from main / conflict cache, // else remove from embedded/nontrans cache, and if not there // remove from new cache StateManagerImpl orig; if (sm.getObjectId() != null) { orig = _main.remove(id); if (orig != sm) { if (orig != null) _main.put(id, orig); // put back if (_conflicts != null) { orig = _conflicts.remove(id); if (orig != null && orig != sm) _conflicts.put(id, orig); // put back } } } else if ((_embeds == null || !_embeds.remove(sm)) && _news != null) { orig = _news.remove(id); if (orig != null && orig != sm) _news.put(id, orig); // put back } if (_untracked != null) _untracked.remove(sm); } /** * An embedded or nonpersistent managed instance has been persisted. */ public void persist(StateManagerImpl sm) { if (_embeds != null) _embeds.remove(sm); } /** * A new instance has just been assigned a permanent oid. */ public void assignObjectId(Object id, StateManagerImpl sm) { // if assigning oid, remove from new cache and put in primary; may // not be in new cache if another new instance had same id StateManagerImpl orig = null; if (_news != null) { orig = _news.remove(id); if (orig != null && orig != sm) _news.put(id, orig); // put back } // put in main cache, but make sure we don't replace another // instance with the same oid orig = _main.put(sm.getObjectId(), sm); if (orig != null) { _main.put(sm.getObjectId(), orig); if (!orig.isDeleted()) throw new UserException(_loc.get("dup-oid-assign", sm.getObjectId(), Exceptions.toString(sm.getManagedInstance()))) .setFailedObject(sm.getManagedInstance()); // same oid as deleted instance; put in conflict cache if (_conflicts == null) _conflicts = new HashMap(); _conflicts.put(sm.getObjectId(), sm); } } /** * A new instance has committed; recache under permanent oid. */ public void commitNew(Object id, StateManagerImpl sm) { // if the id didn't change, the instance was already assigned an // id, but it could have been in conflict cache StateManagerImpl orig; if (sm.getObjectId() == id) { orig = (_conflicts == null) ? null : _conflicts.remove(id); if (orig == sm) { orig = _main.put(id, sm); if (orig != null && !orig.isDeleted()) { _main.put(sm.getObjectId(), orig); throw new UserException(_loc.get("dup-oid-assign", sm.getObjectId(), Exceptions.toString( sm.getManagedInstance()))) .setFailedObject(sm.getManagedInstance()) .setFatal(true); } } return; } // oid changed, so it must previously have been a new instance // without an assigned oid. remove it from the new cache; ok if // we end up removing another instance with same id if (_news != null) _news.remove(id); // and put into main cache now that id is assigned orig = _main.put(sm.getObjectId(), sm); if (orig != null && orig != sm && !orig.isDeleted()) { // put back orig and throw error _main.put(sm.getObjectId(), orig); throw new UserException(_loc.get("dup-oid-assign", sm.getObjectId(), Exceptions.toString(sm.getManagedInstance()))) .setFailedObject(sm.getManagedInstance()).setFatal(true); } } /** * Return a copy of all cached persistent objects. */ public Collection copy() { // proxies not included here because the state manager is always // present in other caches too int size = _main.size(); if (_conflicts != null) size += _conflicts.size(); if (_news != null) size += _news.size(); if (_embeds != null) size += _embeds.size(); if (size == 0) return Collections.EMPTY_LIST; List copy = new ArrayList(size); for (StateManagerImpl sm : _main.values()) copy.add(sm); if (_conflicts != null && !_conflicts.isEmpty()) for (StateManagerImpl sm : _conflicts.values()) copy.add(sm); if (_news != null && !_news.isEmpty()) for (StateManagerImpl sm : _news.values()) copy.add(sm); if (_embeds != null && !_embeds.isEmpty()) for (StateManagerImpl sm : _embeds) copy.add(sm); return copy; } /** * Clear the cache. */ public void clear() { _main = (Map) broker.newManagedObjectCache(); if (_conflicts != null) _conflicts = null; if (_news != null) _news = null; if (_embeds != null) _embeds = null; if (_untracked != null) _untracked = null; } /** * Clear new instances without permanent oids. */ public void clearNew() { if (_news != null) _news = null; } void dirtyCheck() { if (_untracked == null) return; for (StateManagerImpl sm : _untracked) sm.dirtyCheck(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SavepointManager.java0000644000000000000000000000243512133327272027404 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * A manager for handling savepoints. * * @author Steve Kim * @since 0.3.4 */ public interface SavepointManager { /** * Return whether the savepoints generated by this manager * can handle incremental flushes to the datastore. */ public boolean supportsIncrementalFlush(); /** * Return a new savepoint for the given name, which may be null. */ public OpenJPASavepoint newSavepoint(String name, Broker broker); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/package.html0000644000000000000000000000174712133327272025564 0ustar

    OpenJPA Runtime Kernel

    This package provides a common OpenJPA runtime environment that can be adapted for use with various data store mechanisms.

    openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ECopyState.java0000644000000000000000000000444712133327272026166 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an instance that was copied and made embedded within the * current transaction. * * @author Abe White */ @SuppressWarnings("serial") class ECopyState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { // no need to save fields, because this transition doesn't happen // until the flush process begins context.setLoaded(true); context.setDirty(true); } void beforeFlush(StateManagerImpl context, boolean logical, OpCallbacks call) { context.preFlush(logical, call); } PCState commit(StateManagerImpl context) { return TRANSIENT; } PCState commitRetain(StateManagerImpl context) { return ENONTRANS; } PCState rollback(StateManagerImpl context) { return TRANSIENT; } PCState rollbackRestore(StateManagerImpl context) { return ENONTRANS; } PCState delete(StateManagerImpl context) { context.preDelete(); return EDELETED; } PCState nontransactional(StateManagerImpl context) { return error("dirty", context); } PCState release(StateManagerImpl context) { return TRANSIENT; } boolean isTransactional() { return true; } boolean isPersistent() { return true; } boolean isDirty() { return true; } public String toString() { return "Embedded-Copy"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4StringSeq.java0000644000000000000000000000352012133327272027471 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.lib.util.UUIDGenerator; import org.apache.openjpa.meta.ClassMetaData; /** * Sequence for generating 16-character UUID strings. * * @author Jeremy Bauer */ public class UUIDType4StringSeq implements Seq { private static final UUIDType4StringSeq _instance = new UUIDType4StringSeq(); private String _last = null; /** * Return the singleton instance. */ public static UUIDType4StringSeq getInstance() { return _instance; } /** * Hide constructor. */ private UUIDType4StringSeq() { } public void setType(int type) { } public synchronized Object next(StoreContext ctx, ClassMetaData meta) { _last = UUIDGenerator.nextString(UUIDGenerator.TYPE4); return _last; } public synchronized Object current(StoreContext ctx, ClassMetaData meta) { return _last; } public void allocate(int additional, StoreContext ctx, ClassMetaData meta) { } public void close() { } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AuditManager.java0000644000000000000000000002427412133327272026507 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; import org.apache.openjpa.audit.Auditable; import org.apache.openjpa.audit.AuditableOperation; import org.apache.openjpa.audit.Auditor; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.enhance.PCRegistry.RegisterClassListener; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.event.LifecycleEvent; import org.apache.openjpa.event.LifecycleListener; import org.apache.openjpa.event.TransactionEvent; import org.apache.openjpa.event.TransactionListener; /** * Controller for audit facility. * This controller performs the following basic duties: *
  • Records auditable types at class laoding time *
  • Listens to instance life cycle changes and transaction. *
  • Collects auditable instances on instance life cycle changes. *
  • Delegates real auditing to the {@link Auditor} at transaction boundary. * * @author Pinaki Poddar * */ public class AuditManager extends InMemorySavepointManager implements TransactionListener, RegisterClassListener { private final Auditor _auditor; private final Set> _allTypes; private final Set> _newTypes; private final Set> _updateTypes; private final Set> _deleteTypes; private final Map _saved; private final ReentrantLock _lock = new ReentrantLock(); public AuditManager(Auditor auditor) { super(); if (auditor == null) { throw new NullPointerException("null auditor"); } setPreFlush(false); _auditor = auditor; _allTypes = new HashSet>(); _newTypes = new HashSet>(); _updateTypes = new HashSet>(); _deleteTypes = new HashSet>(); _saved = new ConcurrentHashMap(); PCRegistry.addRegisterClassListener(this); } /** * Records all auditable classes in operation-specific sets. */ @Override public void register(Class cls) { Auditable auditable = cls.getAnnotation(Auditable.class); if (auditable == null) { return; } List events = Arrays.asList(auditable.values()); if (events.contains(AuditableOperation.ALL) || events.contains(AuditableOperation.CREATE)) { _newTypes.add(cls); _allTypes.add(cls); } if (events.contains(AuditableOperation.ALL) || events.contains(AuditableOperation.UPDATE)) { _updateTypes.add(cls); _allTypes.add(cls); } if (events.contains(AuditableOperation.ALL) || events.contains(AuditableOperation.DELETE)) { _deleteTypes.add(cls); _allTypes.add(cls); } } public Auditor getAuditor() { return _auditor; } public Set> getAuditedTypes() { return Collections.unmodifiableSet(_allTypes); } /** * ----------------------------------------------------------------------- * Transaction callbacks. * ----------------------------------------------------------------------- */ @Override public void afterBegin(TransactionEvent event) { _lock.lock(); try { Broker broker = (Broker)event.getSource(); AuditCallback cb = new AuditCallback(broker); broker.addLifecycleListener(cb, _allTypes.toArray(new Class[_allTypes.size()])); _saved.put(broker, cb); } finally { _lock.unlock(); } } @Override public void beforeCommit(TransactionEvent event) { _lock.lock(); try { AuditCallback cb = _saved.get(event.getSource()); if (cb != null) { cb.audit(); } } finally { _lock.unlock(); } } @Override public void afterCommit(TransactionEvent event) { _saved.remove(event.getSource()); } @Override public void afterRollback(TransactionEvent event) { _saved.remove(event.getSource()); } @Override public void afterCommitComplete(TransactionEvent event) { _saved.remove(event.getSource()); } @Override public void afterRollbackComplete(TransactionEvent event) { _saved.remove(event.getSource()); } @Override public void beforeFlush(TransactionEvent event) { } @Override public void afterFlush(TransactionEvent event) { } @Override public void afterStateTransitions(TransactionEvent event) { } /** * Support functions. */ /** * Extracts the persistence capable instance from the source of the given event. * @return null if an instance can not be extracted. */ protected PersistenceCapable getPersistenceCapable(LifecycleEvent evt) { Object source = evt.getSource(); return source instanceof PersistenceCapable ? (PersistenceCapable)source : null; } /** * Extracts the broker from the given persistence capable instance. * @param pc a persistence capable instance * @return null if a Broker can notbe extracted */ protected Broker getBroker(PersistenceCapable pc) { if (pc == null) return null; Object ctx = pc.pcGetGenericContext(); return ctx instanceof Broker ? (Broker)ctx : null; } /** * Gets an implementation. * @param instance * @return */ private StateManagerImpl getImpl(Object instance) { if (instance instanceof PersistenceCapable) { StateManager sm = ((PersistenceCapable)instance).pcGetStateManager(); if (sm instanceof StateManagerImpl) { return (StateManagerImpl)sm; } else { return null; } } else { return null; } } /** * Affirms if the given state manager is auditable for the given operation. * @param op an auditable operation * @param sm * @return */ protected boolean isAuditable(AuditableOperation op, StateManagerImpl sm) { if (sm == null) return false; Class cls = sm.getMetaData().getDescribedType(); return (op == AuditableOperation.ALL && _allTypes.contains(cls) || op == AuditableOperation.CREATE && _newTypes.contains(cls)) ||(op == AuditableOperation.UPDATE && _updateTypes.contains(cls)) ||(op == AuditableOperation.DELETE && _deleteTypes.contains(cls)); } /** * Listens to entity life cycle operations and saves them for auditing. * */ private class AuditCallback implements LifecycleListener { private final Broker _broker; private final Map _audits = new ConcurrentHashMap(); AuditCallback(Broker broker) { _broker = broker; } void audit() { if (_audits.isEmpty()) return; Collection news = new HashSet(); Collection updates = new HashSet(); Collection deletes = new HashSet(); for (Map.Entry e : _audits.entrySet()) { StateManagerImpl sm = e.getKey(); Audited audited = new Audited(sm, e.getValue()); if (sm.getPCState().isNew()) { news.add(audited); } else if (sm.getPCState().isDeleted()) { deletes.add(audited); } else if (sm.getPCState().isDirty()) { updates.add(audited); } } try { _auditor.audit(_broker, news, updates, deletes); } catch (Exception e) { if (_auditor.isRollbackOnError()) { throw new RuntimeException("dump", e); } else { e.printStackTrace(); } } } /** * Saves the source of the given event for auditing. * @param op an auditable operation * @param event the event */ protected void save(AuditableOperation op, LifecycleEvent event) { StateManagerImpl sm = getImpl(event.getSource()); if (sm != null && !_audits.containsKey(sm) && isAuditable(op, sm)) { Broker broker = sm.getBroker(); OpenJPASavepoint savepoint = newSavepoint("", broker); savepoint.save(Collections.singleton(sm)); Map states = savepoint.getStates(); Map.Entry e = states.entrySet().iterator().next(); PersistenceCapable copy = e.getValue().getCopy(); copy.pcReplaceStateManager(null); _audits.put(sm, copy); } } /** * Life-cycle callbacks */ @Override public void afterLoad(LifecycleEvent event) { save(AuditableOperation.ALL, event); } @Override public void afterPersist(LifecycleEvent event) { save(AuditableOperation.CREATE, event); } @Override public void beforeDelete(LifecycleEvent event) { save(AuditableOperation.DELETE, event); } @Override public void beforeDirty(LifecycleEvent event) { save(AuditableOperation.UPDATE, event); } @Override public void beforePersist(LifecycleEvent event) { } @Override public void afterRefresh(LifecycleEvent event) { } @Override public void beforeStore(LifecycleEvent event) { } @Override public void afterStore(LifecycleEvent event) { } @Override public void beforeClear(LifecycleEvent event) { } @Override public void afterClear(LifecycleEvent event) { } @Override public void afterDelete(LifecycleEvent event) { } @Override public void afterDirty(LifecycleEvent event) { } @Override public void beforeDirtyFlushed(LifecycleEvent event) { } @Override public void afterDirtyFlushed(LifecycleEvent event) { } @Override public void beforeDetach(LifecycleEvent event) { } @Override public void afterDetach(LifecycleEvent event) { } @Override public void beforeAttach(LifecycleEvent event) { } @Override public void afterAttach(LifecycleEvent event) { } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultShapePacker.java0000644000000000000000000000425112133327272027524 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Calendar; import org.apache.openjpa.util.ProxyCalendar; /** * Packs result by delegation to a ResultShape. * * @author Pinaki Poddar * */ public class ResultShapePacker extends ResultPacker { private final ResultShape _shape; private final Class[] _types; private final String[] _aliases; public ResultShapePacker(Class[] types, String[] aliases, Class resultClass, ResultShape shape) { super(); // bypass superclass implementation _shape = shape; _types = types; _aliases = aliases; } @Override public Object pack(Object o) { return pack(new Object[]{o}); } @Override public Object pack(Object[] values) { // Check for proxied calenders and cleanup if any are found. if (_types != null) { for (Class t : _types) { if (t.equals(Calendar.class)) { for (int i = 0; i < values.length; i++) { if (values[i] instanceof ProxyCalendar) { values[i] = ((ProxyCalendar) values[i]).copy((ProxyCalendar) values[i]); } } } } } if (_shape == null) return super.pack(values); return _shape.pack(values, _types, _aliases); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/LockScopes.java0000644000000000000000000000227112133327272026204 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Defines lock scope levels used for MixedLockManager. * * @since 2.0.0 */ public interface LockScopes { /** * Generic Normal lock scope level. Value of 0. * */ public static final int LOCKSCOPE_NORMAL = 0; /** * Generic extended lock scope level. Value of 10. */ public static final int LOCKSCOPE_EXTENDED = 10; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManagerLite.java0000644000000000000000000001067312133327272027445 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import java.util.Collection; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.util.Proxy; /** * Handles detaching instances. */ public class DetachManagerLite { private final boolean _detachProxies; private final TransferFieldManager _tsm; public DetachManagerLite(OpenJPAConfiguration conf) { _detachProxies = conf.getDetachStateInstance().getDetachProxyFields(); _tsm = new TransferFieldManager(); } /** * This method will detach all provided StateManagers in place. * * @param states * The StateManagers to be detached. */ public void detachAll(Collection states) { for (StateManagerImpl sm : states) { ClassMetaData cmd = sm.getMetaData(); if (sm.isPersistent() && cmd.isDetachable()) { PersistenceCapable pc = sm.getPersistenceCapable(); if (pc.pcIsDetached() == false) { // Detach proxy fields. BitSet loaded = sm.getLoaded(); for (FieldMetaData fmd : cmd.getProxyFields()) { if (loaded.get(fmd.getIndex())) { detachProxyField(fmd, pc, sm, _tsm); } } pc.pcReplaceStateManager(null); } } } } /** * Detach the provided proxy field. * * @param fmd * The field to be detached. * @param pc * The PersistenceCapable that the field belongs to. * @param sm * The StateManagerImpl that the PersistenceCapable belongs to. */ private void detachProxyField(FieldMetaData fmd, PersistenceCapable pc, StateManagerImpl sm, TransferFieldManager fm) { int fieldIndex = fmd.getIndex(); if (fmd.isLRS() == true) { // need to null out LRS fields. nullField(fieldIndex, pc, sm, fm); } else { Object o = sm.fetchObject(fieldIndex); if (o instanceof Proxy) { // Get unproxied object and replace Proxy proxy = (Proxy) o; if (!_detachProxies) { // Even if we're not detaching proxies, we need to remove the reference to the SM. proxy.setOwner(null, -1); return; } Object unproxied = proxy.copy(proxy); fm.storeObjectField(fieldIndex, unproxied); sm.replaceField(pc, fm, fieldIndex); fm.clear(); // clean up old proxy proxy.setOwner(null, -1); if (proxy.getChangeTracker() != null) { proxy.getChangeTracker().stopTracking(); } } } } /** * Private worker method that replaces the value at fieldIndex in sm with null. * * @param fieldIndex * The index of the field to be nulled out. * @param pc * The PersistenceCapable that the field belongs to. * @param sm * The StateManagerImpl that the PersistenceCapable belongs to. */ private void nullField(int fieldIndex, PersistenceCapable pc, StateManagerImpl sm, TransferFieldManager fm) { fm.storeObjectField(fieldIndex, null); sm.replaceField(pc, fm, fieldIndex); fm.clear(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNonTransDeletedState.java0000644000000000000000000000443012133327272030310 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an instance that was deleted outside a transaction. * * @author Steve Kim */ @SuppressWarnings("serial") public class PNonTransDeletedState extends PCState { PCState persist(StateManagerImpl context) { return PNONTRANS; } PCState transactional(StateManagerImpl context) { return PDELETED; } PCState beforeRead(StateManagerImpl context, int field) { return error("deleted", context); } PCState beforeNontransactionalRead(StateManagerImpl context, int field) { return error("deleted", context); } PCState beforeOptimisticRead(StateManagerImpl context, int field) { return error("deleted", context); } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } PCState beforeNontransactionalWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } boolean isPendingTransactional() { return true; } boolean isPersistent() { return true; } boolean isDeleted() { return true; } boolean isDirty() { return true; } public String toString() { return "Persistent-Notransactional-Deleted"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ROPStoreManager.java0000644000000000000000000000566212133327272027116 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.StoreException; /** * Wraps the native store manager to handle calls using custom * {@link PCResultObjectProvider}s. * * @author Abe White */ class ROPStoreManager extends DelegatingStoreManager { public ROPStoreManager(StoreManager delegate) { super(delegate); } public boolean exists(OpenJPAStateManager sm, Object context) { if (context instanceof PCResultObjectProvider) context = null; return super.exists(sm, context); } public boolean initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch, Object context) { if (context instanceof PCResultObjectProvider) { try { ((PCResultObjectProvider) context).initialize(sm, state, fetch); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new StoreException(e); } return true; } return super.initialize(sm, state, fetch, context); } public boolean syncVersion(OpenJPAStateManager sm, Object context) { // the only way this gets called with a rop context is if the // rop didn't load any version info on initialize, so just null // it out so we don't get unexpected results when our delegate // expectes a different context type if (context instanceof PCResultObjectProvider) context = null; return super.syncVersion(sm, context); } public boolean load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch, int lockLevel, Object context) { // the only way this gets called with a rop context is if the // rop didn't load the field on initialize, so just null // it out so we don't get unexpected results when our delegate // expectes a different context type if (context instanceof PCResultObjectProvider) context = null; return super.load(sm, fields, fetch, lockLevel, context); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNonTransNewState.java0000644000000000000000000000333312133327272027474 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an instance that was persisted outside a transaction. * * @author Steve Kim */ @SuppressWarnings("serial") class PNonTransNewState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.setLoaded(true); context.setDirty(true); } PCState delete(StateManagerImpl context) { return TRANSIENT; } PCState transactional(StateManagerImpl context) { return PNEW; } PCState release(StateManagerImpl context) { return TRANSIENT; } boolean isPersistent() { return true; } boolean isNew() { return true; } boolean isDirty() { return true; } boolean isPendingTransactional() { return true; } public String toString() { return "Persistent-Notransactional-New"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/OpCallbacks.java0000644000000000000000000000402312133327272026312 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Allows facades to control the particulars of persistence operations * through callbacks. * * @author Abe White */ public interface OpCallbacks { public static final int OP_PERSIST = 0; public static final int OP_DELETE = 1; public static final int OP_REFRESH = 2; public static final int OP_RETRIEVE = 3; public static final int OP_RELEASE = 4; public static final int OP_EVICT = 5; public static final int OP_ATTACH = 6; public static final int OP_DETACH = 7; public static final int OP_NONTRANSACTIONAL = 8; public static final int OP_TRANSACTIONAL = 9; public static final int OP_LOCK = 10; public static final int ACT_NONE = 0; public static final int ACT_CASCADE = 2 << 0; public static final int ACT_RUN = 2 << 1; /** * Process operation argument. Throw proper * {@link org.apache.openjpa.util.OpenJPAException} for illegal value. * * @param op the operation constant * @param arg the object passed to the operation * @param sm the argument's state manager, or null if none * @return the action to take on the argument */ public int processArgument(int op, Object arg, OpenJPAStateManager sm); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Bootstrap.java0000644000000000000000000001476512133327272026127 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.AccessController; import org.apache.openjpa.conf.BrokerFactoryValue; import org.apache.openjpa.lib.conf.ConfigurationProvider; import org.apache.openjpa.lib.conf.MapConfigurationProvider; import org.apache.openjpa.lib.conf.ProductDerivations; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; /** * Helper methods for acquiring {@link BrokerFactory} objects * * @since 0.4.0.0 */ public class Bootstrap { private static final Class[] CONFIGURATION_ARG = new Class[]{ ConfigurationProvider.class }; private static final Class[] CONFIGURATION_CLASSLOADER_ARGS = new Class[] { ConfigurationProvider.class, ClassLoader.class }; private static Localizer s_loc = Localizer.forPackage(Bootstrap.class); /** * Return a new factory for the default configuration. */ public static BrokerFactory newBrokerFactory() { return Bootstrap.newBrokerFactory(null, null); } /** * Return a new factory for the given configuration. The classloader * will be used to load the factory class. If no classloader is given, * the thread's context classloader is used. */ public static BrokerFactory newBrokerFactory(ConfigurationProvider conf, ClassLoader loader) { try { BrokerFactory factory = invokeFactory(conf, loader, "newInstance", CONFIGURATION_ARG, new Object[] { conf }); factory.postCreationCallback(); return factory; } catch (InvocationTargetException ite) { Throwable cause = ite.getTargetException(); if (cause instanceof OpenJPAException) throw (OpenJPAException) cause; throw new InternalException(s_loc.get("new-brokerfactory-excep", getFactoryClassName(conf, loader)), cause); } catch (Exception e) { throw new UserException(s_loc.get("bad-new-brokerfactory", getFactoryClassName(conf, loader)), e).setFatal(true); } } /** * Return a pooled factory for the default configuration. */ public static BrokerFactory getBrokerFactory() { return Bootstrap.getBrokerFactory(null, null); } /** * Return a pooled factory for the given configuration. The classloader * will be used to load the factory class. If no classloader is given, * the thread's context classloader is used. */ public static BrokerFactory getBrokerFactory(ConfigurationProvider conf, ClassLoader loader) { try { return invokeFactory(conf, loader, "getInstance", CONFIGURATION_CLASSLOADER_ARGS, new Object[] { conf, loader }); } catch (InvocationTargetException ite) { Throwable cause = ite.getTargetException(); if (cause instanceof OpenJPAException) throw (OpenJPAException) cause; throw new InternalException(s_loc.get("brokerfactory-excep", getFactoryClassName(conf, loader)), cause); } catch (Exception e) { throw new UserException(s_loc.get("bad-brokerfactory", getFactoryClassName(conf, loader)), e).setFatal(true); } } private static BrokerFactory invokeFactory(ConfigurationProvider conf, ClassLoader loader, String methodName, Class[] argTypes, Object[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { if (conf == null) conf = new MapConfigurationProvider(); ProductDerivations.beforeConfigurationConstruct(conf); Class cls = getFactoryClass(conf, loader); Method meth; try { meth = cls.getMethod(methodName, argTypes); } catch (NoSuchMethodException nsme) { // handle cases where there is a mismatch between loaders by falling // back to the configuration's class loader for broker resolution cls = getFactoryClass(conf, AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(conf.getClass()))); meth = cls.getMethod(methodName, argTypes); } return (BrokerFactory) meth.invoke(null, args); } private static String getFactoryClassName(ConfigurationProvider conf, ClassLoader loader) { try { return getFactoryClass(conf, loader).getName(); } catch (Exception e) { return "<" + e.toString() + ">"; } } /** * Instantiate the factory class designated in properties. */ private static Class getFactoryClass(ConfigurationProvider conf, ClassLoader loader) { if (loader == null) loader = AccessController.doPrivileged( J2DoPrivHelper.getContextClassLoaderAction()); Object cls = BrokerFactoryValue.get(conf); if (cls instanceof Class) return (Class) cls; BrokerFactoryValue value = new BrokerFactoryValue(); value.setString((String) cls); String clsName = value.getClassName(); if (clsName == null) throw new UserException(s_loc.get("no-brokerfactory", conf.getProperties())).setFatal(true); try { return Class.forName(clsName, true, loader); } catch (Exception e) { throw new UserException(s_loc.get("bad-brokerfactory-class", clsName), e).setFatal(true); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java0000644000000000000000000005457412133327272027103 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.lang.reflect.Array; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.commons.lang.ObjectUtils; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.UserException; /** * Strategy for attaching objects. * * @author Marc Prud'hommeaux * @author Steve Kim * @nojavadoc */ abstract class AttachStrategy extends TransferFieldManager { private static final Localizer _loc = Localizer.forPackage (AttachStrategy.class); /** * Attach. * * @param manager manager holding cache of attached instances * @param toAttach detached instance * @param meta metadata for the instance being attached * @param into instance we're attaching into * @param owner state manager for into * @param ownerMeta field we traversed to find toAttach * @param explicit whether to make new instances explicitly persistent */ public abstract Object attach(AttachManager manager, Object toAttach, ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit); /** * Return the identity of the given detached instance. */ protected abstract Object getDetachedObjectId(AttachManager manager, Object toAttach); /** * Provide the given field into this field manager. */ protected abstract void provideField(Object toAttach, StateManagerImpl sm, int field); /** * Return a PNew/PNewProvisional managed object for the given detached * instance. */ protected StateManagerImpl persist(AttachManager manager, PersistenceCapable pc, ClassMetaData meta, Object appId, boolean explicit) { PersistenceCapable newInstance; if (!manager.getCopyNew()) newInstance = pc; else if (appId == null) // datastore identity or application identity with generated keys newInstance = pc.pcNewInstance(null, false); else // application identity: use existing fields newInstance = pc.pcNewInstance(null, appId, false); StateManagerImpl sm = (StateManagerImpl) manager.getBroker().persist (newInstance, appId, explicit, manager.getBehavior(), !manager.getCopyNew()); attachPCKeyFields(pc, sm, meta, manager); return sm; } private void attachPCKeyFields(PersistenceCapable fromPC, StateManagerImpl sm, ClassMetaData meta, AttachManager manager) { if (fromPC.pcGetStateManager() == null) { fromPC.pcReplaceStateManager(sm); FieldMetaData[] fmds = meta.getDefinedFields(); for (FieldMetaData fmd : fmds) { if (fmd.isPrimaryKey()) { attachField(manager, fromPC, sm, fmd, true); } } fromPC.pcReplaceStateManager(null); } } /** * Attach the given field into the given instance. * * @param toAttach the detached persistent instance * @param sm state manager for the managed instance we're copying * into; toAttach also uses this state manager * @param fmd metadata on the field we're copying * @param nullLoaded if false, nulls will be considered unloaded and will * not be attached */ protected boolean attachField(AttachManager manager, Object toAttach, StateManagerImpl sm, FieldMetaData fmd, boolean nullLoaded) { if (fmd.isVersion() || fmd.getManagement() != FieldMetaData.MANAGE_PERSISTENT) return false; PersistenceCapable into = sm.getPersistenceCapable(); int i = fmd.getIndex(); provideField(toAttach, sm, i); int set = StateManager.SET_ATTACH; Object val; switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: sm.settingBooleanField(into, i, sm.fetchBooleanField(i), fetchBooleanField(i), set); break; case JavaTypes.BYTE: sm.settingByteField(into, i, sm.fetchByteField(i), fetchByteField(i), set); break; case JavaTypes.CHAR: sm.settingCharField(into, i, sm.fetchCharField(i), fetchCharField(i), set); break; case JavaTypes.DOUBLE: sm.settingDoubleField(into, i, sm.fetchDoubleField(i), fetchDoubleField(i), set); break; case JavaTypes.FLOAT: sm.settingFloatField(into, i, sm.fetchFloatField(i), fetchFloatField(i), set); break; case JavaTypes.INT: sm.settingIntField(into, i, sm.fetchIntField(i), fetchIntField(i), set); break; case JavaTypes.LONG: sm.settingLongField(into, i, sm.fetchLongField(i), fetchLongField(i), set); break; case JavaTypes.SHORT: sm.settingShortField(into, i, sm.fetchShortField(i), fetchShortField(i), set); break; case JavaTypes.STRING: String sval = fetchStringField(i); if (sval == null && !nullLoaded) return false; sm.settingStringField(into, i, sm.fetchStringField(i), sval, set); break; case JavaTypes.DATE: case JavaTypes.CALENDAR: case JavaTypes.NUMBER: case JavaTypes.BOOLEAN_OBJ: case JavaTypes.BYTE_OBJ: case JavaTypes.CHAR_OBJ: case JavaTypes.DOUBLE_OBJ: case JavaTypes.FLOAT_OBJ: case JavaTypes.INT_OBJ: case JavaTypes.LONG_OBJ: case JavaTypes.SHORT_OBJ: case JavaTypes.BIGDECIMAL: case JavaTypes.BIGINTEGER: case JavaTypes.LOCALE: case JavaTypes.OBJECT: case JavaTypes.OID: case JavaTypes.ENUM: val = fetchObjectField(i); if (val == null && !nullLoaded) return false; sm.settingObjectField(into, i, sm.fetchObjectField(i), val, set); break; case JavaTypes.PC: case JavaTypes.PC_UNTYPED: Object frmpc = fetchObjectField(i); if (frmpc == null && !nullLoaded) return false; OpenJPAStateManager tosm = manager.getBroker().getStateManager (sm.fetchObjectField(i)); PersistenceCapable topc = (tosm == null) ? null : tosm.getPersistenceCapable(); if (frmpc != null || topc != null) { if (fmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) { // Use the attached copy of the object, if available PersistenceCapable cpy = manager.getAttachedCopy(frmpc); if (cpy != null) { frmpc = cpy; } else { frmpc = getReference(manager, frmpc, sm, fmd); } } else { PersistenceCapable intopc = topc; if (!fmd.isEmbeddedPC() && frmpc != null && topc != null && !ObjectUtils.equals(topc.pcFetchObjectId(), manager.getDetachedObjectId(frmpc))) { intopc = null; } frmpc = manager.attach(frmpc, intopc, sm, fmd, false); } if (frmpc != topc) sm.settingObjectField(into, i, topc, frmpc, set); } break; case JavaTypes.COLLECTION: Collection frmc = (Collection) fetchObjectField(i); if (frmc == null && !nullLoaded) return false; Collection toc = (Collection) sm.fetchObjectField(i); if ((toc != null && !toc.isEmpty()) || frmc != null && !frmc.isEmpty()) { if (frmc == null) sm.settingObjectField(into, i, toc, null, set); else if (toc == null) { sm.settingObjectField(into, i, null, attachCollection(manager, frmc, sm, fmd), set); } else if (toc instanceof Set && frmc instanceof Set) replaceCollection(manager, frmc, toc, sm, fmd); else { sm.settingObjectField(into, i, toc, replaceList(manager, frmc, toc, sm, fmd), set); } } break; case JavaTypes.MAP: Map frmm = (Map) fetchObjectField(i); if (frmm == null && !nullLoaded) return false; Map tom = (Map) sm.fetchObjectField(i); if ((tom != null && !tom.isEmpty()) || (frmm != null && !frmm.isEmpty())) { if (frmm == null) sm.settingObjectField(into, i, tom, null, set); else if (tom == null) sm.settingObjectField(into, i, null, attachMap(manager, frmm, sm, fmd), set); else replaceMap(manager, frmm, tom, sm, fmd); } break; case JavaTypes.ARRAY: Object frma = fetchObjectField(i); if (frma == null && !nullLoaded) return false; Object toa = sm.fetchObjectField(i); if ((toa != null && Array.getLength(toa) > 0) || (frma != null && Array.getLength(frma) > 0)) { if (frma == null) sm.settingObjectField(into, i, toa, null, set); else sm.settingObjectField(into, i, toa, replaceArray(manager, frma, toa, sm, fmd), set); } break; default: throw new InternalException(fmd.toString()); } return true; } /** * Return a managed, possibly hollow reference for the given detached * object. */ protected Object getReference(AttachManager manager, Object toAttach, OpenJPAStateManager sm, ValueMetaData vmd) { if (toAttach == null) return null; if (manager.getBroker().isNew(toAttach)) { // Check if toAttach is already mapped to a managed instance PersistenceCapable pc = manager.getAttachedCopy(toAttach); if (pc != null) { return pc; } else { return toAttach; } } else if (manager.getBroker().isPersistent(toAttach)) { return toAttach; } else if (manager.getBroker().isDetached(toAttach)) { Object oid = manager.getDetachedObjectId(toAttach); if (oid != null) { return manager.getBroker().find(oid, false, null); } } throw new UserException(_loc.get("cant-cascade-attach", vmd)).setFailedObject(toAttach); } /** * Replace the contents of toc with the contents of * frmc. Neither collection is null. */ private void replaceCollection(AttachManager manager, Collection frmc, Collection toc, OpenJPAStateManager sm, FieldMetaData fmd) { // if frmc collection is empty, just clear toc if (frmc.isEmpty()) { if (!toc.isEmpty()) toc.clear(); return; } // if this is a pc collection, attach all instances boolean pc = fmd.getElement().isDeclaredTypePC(); if (pc) frmc = attachCollection(manager, frmc, sm, fmd); // remove all elements from the toc collection that aren't in frmc toc.retainAll(frmc); // now add all elements that are in frmc but not toc if (frmc.size() != toc.size()) { for (Iterator i = frmc.iterator(); i.hasNext();) { Object ob = i.next(); if (!toc.contains(ob)) toc.add(ob); } } } /** * Return a new collection with the attached contents of the given one. */ protected Collection attachCollection(AttachManager manager, Collection orig, OpenJPAStateManager sm, FieldMetaData fmd) { Collection coll = copyCollection(manager, orig, fmd, sm); ValueMetaData vmd = fmd.getElement(); if (!vmd.isDeclaredTypePC()) return coll; // unfortunately we have to clear the original and re-add coll.clear(); Object elem; for (Iterator itr = orig.iterator(); itr.hasNext();) { if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) elem = getReference(manager, itr.next(), sm, vmd); else elem = manager.attach(itr.next(), null, sm, vmd, false); coll.add(elem); } return coll; } /** * Copies the given collection. */ private Collection copyCollection(AttachManager manager, Collection orig, FieldMetaData fmd) { Collection coll = manager.getProxyManager().copyCollection(orig); if (coll == null) throw new UserException(_loc.get("not-copyable", fmd)); return coll; } /** * Copies the given collection. */ private Collection copyCollection(AttachManager manager, Collection orig, FieldMetaData fmd, OpenJPAStateManager sm) { if (orig == null) throw new UserException(_loc.get("not-copyable", fmd)); try { return copyCollection(manager, orig, fmd); } catch (Exception e) { Collection coll = (Collection) sm.newFieldProxy(fmd.getIndex()); coll.addAll(orig); return coll; } } /** * Copies the given map. */ private Map copyMap(AttachManager manager, Map orig, FieldMetaData fmd, OpenJPAStateManager sm) { if (orig == null) throw new UserException(_loc.get("not-copyable", fmd)); try { return manager.getProxyManager().copyMap(orig); } catch (Exception e) { Map map = (Map) sm.newFieldProxy(fmd.getIndex()); for (Entry entry : ((Map) orig).entrySet()) { map.put(entry.getKey(), entry.getValue()); } return map; } } /** * Returns an attached version of the frml * list if it is different than tol. If the lists * will be identical, returns tol. Neither list is null. */ private Collection replaceList(AttachManager manager, Collection frml, Collection tol, OpenJPAStateManager sm, FieldMetaData fmd) { boolean pc = fmd.getElement().isDeclaredTypePC(); if (pc) frml = attachCollection(manager, frml, sm, fmd); // if the only diff between frml and tol is some added elements at // the end, make the changes directly in tol if (frml.size() >= tol.size()) { Iterator frmi = frml.iterator(); for (Iterator toi = tol.iterator(); toi.hasNext();) { // if there's an incompatibility, just return a copy of frml // (it's already copied if we attached it) if (!equals(frmi.next(), toi.next(), pc)) return (pc) ? frml : copyCollection(manager, frml, fmd, sm); } // just add the extra elements in frml to tol and return tol while (frmi.hasNext()) tol.add(frmi.next()); return tol; } // the lists are different; just make sure frml is copied and return it return (pc) ? frml : copyCollection(manager, frml, fmd, sm); } /** * Replace the contents of tom with the contents of * frmm. Neither map is null. */ private void replaceMap(AttachManager manager, Map frmm, Map tom, OpenJPAStateManager sm, FieldMetaData fmd) { if (frmm.isEmpty()) { if (!tom.isEmpty()) tom.clear(); return; } // if this is a pc map, attach all instances boolean keyPC = fmd.getKey().isDeclaredTypePC(); boolean valPC = fmd.getElement().isDeclaredTypePC(); if (keyPC || valPC) frmm = attachMap(manager, frmm, sm, fmd); // make sure all the keys in the from map are in the two map, and // that they have the same values for (Iterator i = frmm.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); if (!tom.containsKey(entry.getKey()) || !equals(tom.get(entry.getKey()), entry.getValue(), valPC)) { tom.put(entry.getKey(), entry.getValue()); } } // remove any keys in the to map that aren't in the from map if (tom.size() != frmm.size()) { for (Iterator i = tom.keySet().iterator(); i.hasNext();) { if (!(frmm.containsKey(i.next()))) i.remove(); } } } /** * Make sure all the values in the given map are attached. */ protected Map attachMap(AttachManager manager, Map orig, OpenJPAStateManager sm, FieldMetaData fmd) { Map map = copyMap(manager, orig, fmd, sm); if (map == null) throw new UserException(_loc.get("not-copyable", fmd)); ValueMetaData keymd = fmd.getKey(); ValueMetaData valmd = fmd.getElement(); if (!keymd.isDeclaredTypePC() && !valmd.isDeclaredTypePC()) return map; // if we have to replace keys, just clear and re-add; otherwise // we can use the entry set to reset the values only Map.Entry entry; if (keymd.isDeclaredTypePC()) { map.clear(); Object key, val; for (Iterator itr = orig.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); key = entry.getKey(); if (keymd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) key = getReference(manager, key, sm, keymd); else key = manager.attach(key, null, sm, keymd, false); val = entry.getValue(); if (valmd.isDeclaredTypePC()) { if (valmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) val = getReference(manager, val, sm, valmd); else val = manager.attach(val, null, sm, valmd, false); } map.put(key, val); } } else { Object val; for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); if (valmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) val = getReference(manager, entry.getValue(), sm, valmd); else val = manager.attach(entry.getValue(), null, sm, valmd, false); entry.setValue(val); } } return map; } /** * Returns an attached version of the frma * array if it is different than toa. If the arrays * will be identical, returns toa. */ private Object replaceArray(AttachManager manager, Object frma, Object toa, OpenJPAStateManager sm, FieldMetaData fmd) { int len = Array.getLength(frma); boolean diff = toa == null || len != Array.getLength(toa); // populate an array copy on the initial assumption that the array // is dirty Object newa = Array.newInstance(fmd.getElement().getDeclaredType(), len); ValueMetaData vmd = fmd.getElement(); boolean pc = vmd.isDeclaredTypePC(); Object elem; for (int i = 0; i < len; i++) { elem = Array.get(frma, i); if (pc) { if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) elem = getReference(manager, elem, sm, vmd); else elem = manager.attach(elem, null, sm, vmd, false); } diff = diff || !equals(elem, Array.get(toa, i), pc); Array.set(newa, i, elem); } return (diff) ? newa : toa; } /** * Return true if the given objects are equal. PCs are compared for * on JVM identity. */ private static boolean equals(Object a, Object b, boolean pc) { if (a == b) return true; if (pc || a == null || b == null) return false; return a.equals (b); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java0000644000000000000000000010423012133327272027615 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.IOException; import java.io.ObjectOutput; import java.io.Serializable; import java.sql.Timestamp; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.Map; import java.util.TimeZone; import org.apache.openjpa.conf.Compatibility; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.ChangeTracker; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.LRSProxy; import org.apache.openjpa.util.MapChangeTracker; import org.apache.openjpa.util.ObjectId; import org.apache.openjpa.util.Proxies; import org.apache.openjpa.util.Proxy; import org.apache.openjpa.util.ProxyManager; import org.apache.openjpa.util.UserException; /** * FieldManager type used to hold onto a single field value and then * dispense it via the fetch methods. The manager can also perform actions * on the held field. */ class SingleFieldManager extends TransferFieldManager implements Serializable { private static final Localizer _loc = Localizer.forPackage(SingleFieldManager.class); private final StateManagerImpl _sm; private final BrokerImpl _broker; private final boolean _checkDbOnCascadePersist; public SingleFieldManager(StateManagerImpl sm, BrokerImpl broker) { _sm = sm; _broker = broker; _checkDbOnCascadePersist = _broker.getConfiguration().getCompatibilityInstance().getCheckDatabaseForCascadePersistToDetachedEntity(); } /** * Proxy the held field if needed. Return true if the field needs to * be replaced with the now-proxied instance. */ public boolean proxy(boolean reset, boolean replaceNull) { FieldMetaData fmd = _sm.getMetaData().getField(field); Proxy proxy = null; boolean ret = false; switch (fmd.getDeclaredTypeCode()) { case JavaTypes.DATE: if (objval == null) return false; proxy = checkProxy(fmd); if (proxy == null) { proxy = (Proxy) _sm.newFieldProxy(field); ((Date) proxy).setTime(((Date) objval).getTime()); if (proxy instanceof Timestamp && objval instanceof Timestamp) ((Timestamp) proxy).setNanos(((Timestamp) objval).getNanos()); ret = true; } break; case JavaTypes.CALENDAR: if (objval == null) return false; proxy = checkProxy(fmd); if (proxy == null) { proxy = (Proxy) _sm.newFieldProxy(field); ((Calendar) proxy).setTime(((Calendar) objval).getTime()); ret = true; } else { Object init = fmd.getInitializer(); if (init != null && init instanceof TimeZone) { ((Calendar) proxy).setTimeZone((TimeZone)init); } } break; case JavaTypes.COLLECTION: if (objval == null && !replaceNull) return false; proxy = checkProxy(fmd); if (proxy == null) { proxy = (Proxy) _sm.newFieldProxy(field); if (objval != null) ((Collection) proxy).addAll((Collection) objval); ret = true; } break; case JavaTypes.MAP: if (objval == null && !replaceNull) return false; proxy = checkProxy(fmd); if (proxy == null) { proxy = (Proxy) _sm.newFieldProxy(field); if (objval != null) ((Map) proxy).putAll((Map) objval); ret = true; } break; case JavaTypes.OBJECT: if (objval == null) return false; proxy = checkProxy(fmd); if (proxy == null) { proxy = getProxyManager().newCustomProxy(objval, _sm.getBroker().getConfiguration(). getCompatibilityInstance().getAutoOff()); ret = proxy != null; } break; } if (proxy != null) { proxy.setOwner(_sm, field); ChangeTracker tracker = proxy.getChangeTracker(); if (reset && tracker != null) { if (fmd.getDeclaredTypeCode() == JavaTypes.MAP) { // track values if key is derived from value, else keys boolean keys = fmd.getKey().getValueMappedBy() == null; ((MapChangeTracker) tracker).setTrackKeys(keys); } tracker.startTracking(); } objval = proxy; } return ret; } /** * If the current field is a usable proxy and it should be a proxy, return it; else return null. * * This method will skim out Calendar instances that were proxied before we knew if they need to be proxied. */ private Proxy checkProxy(FieldMetaData fmd) { if (!(objval instanceof Proxy)) return null; Proxy proxy = (Proxy) objval; if (proxy.getOwner() == null || Proxies.isOwner(proxy, _sm, field)) { if (fmd.getProxyType().isAssignableFrom(proxy.getClass()) || (fmd.isLRS() && (objval instanceof LRSProxy))) { return proxy; } } return null; } /** * Unproxies the current field if needed. */ public void unproxy() { if (objval == null) return; FieldMetaData fmd = _sm.getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.DATE: case JavaTypes.OBJECT: if (objval instanceof Proxy) { Proxy proxy = (Proxy) objval; proxy.setOwner(null, -1); if (proxy.getChangeTracker() != null) proxy.getChangeTracker().stopTracking(); } } } /** * Release the currently embedded field (make it transient). */ public void releaseEmbedded() { if (objval == null) return; FieldMetaData fmd = _sm.getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.PC: if (fmd.isEmbeddedPC()) releaseEmbedded(fmd, objval); break; case JavaTypes.ARRAY: if (fmd.getElement().isEmbeddedPC()) releaseEmbedded(fmd.getElement(), (Object[]) objval); break; case JavaTypes.COLLECTION: if (fmd.getElement().isEmbeddedPC()) releaseEmbedded(fmd.getElement(), (Collection) objval); break; case JavaTypes.MAP: if (fmd.getKey().isEmbeddedPC()) releaseEmbedded(fmd.getKey(), ((Map) objval).keySet()); if (fmd.getElement().isEmbeddedPC()) releaseEmbedded(fmd.getElement(), ((Map) objval).values()); break; } } /** * Release the given embedded objects. */ private void releaseEmbedded(ValueMetaData vmd, Object[] objs) { for (int i = 0; i < objs.length; i++) releaseEmbedded(vmd, objs[i]); } /** * Release the given embedded objects. */ private void releaseEmbedded(ValueMetaData vmd, Collection objs) { for (Iterator itr = objs.iterator(); itr.hasNext();) releaseEmbedded(vmd, itr.next()); } /** * Release the given embedd object. */ private void releaseEmbedded(ValueMetaData vmd, Object obj) { if (obj == null) return; StateManagerImpl sm = _broker.getStateManagerImpl(obj, false); if (sm != null && sm.getOwner() == _sm && sm.getOwnerIndex() == vmd.getFieldMetaData().getIndex()) sm.release(true); } /** * Persist the stored field safely, preventing infinite recursion using * the given set of already-persisted objects. This method is only called * for fields that we know have cascade-immediate settings. */ public void persist(OpCallbacks call) { if (objval == null) return; FieldMetaData fmd = _sm.getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.PC: case JavaTypes.PC_UNTYPED: if (!_broker.isDetachedNew() && _broker.isDetached(objval)) return; // allow but ignore _broker.persist(objval, true, call); break; case JavaTypes.ARRAY: _broker.persistAll(Arrays.asList((Object[]) objval), true, call); break; case JavaTypes.COLLECTION: _broker.persistAll((Collection) objval, true, call); break; case JavaTypes.MAP: if (fmd.getKey().getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE) _broker.persistAll(((Map) objval).keySet(), true, call); if (fmd.getElement().getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE) _broker.persistAll(((Map) objval).values(), true, call); break; } } /** * Delete and/or dereference field values. */ public void delete(OpCallbacks call) { delete(true, call); } /** * Dereference field values. */ public void dereferenceDependent() { delete(false, null, true); } private void delete(boolean immediate, OpCallbacks call) { delete(immediate, call, false); } /** * Delete or dereference the stored field as necessary. */ private void delete(boolean immediate, OpCallbacks call, boolean deref) { if (objval == null) return; FieldMetaData fmd = _sm.getMetaData().getField(field); if (fmd.getCascadeDelete() != ValueMetaData.CASCADE_NONE) { // immediate cascade works on field value; dependent deref // works on external value if ((immediate || fmd.isEmbeddedPC()) && fmd.getCascadeDelete() == ValueMetaData.CASCADE_IMMEDIATE) { if (fmd.isEmbeddedPC() && deref) { StateManagerImpl sm = _broker.getStateManagerImpl(objval, false); if (sm != null) dereferenceEmbedDependent(sm); } delete(fmd, objval, call); } else if (fmd.getCascadeDelete() == ValueMetaData.CASCADE_AUTO) dereferenceDependent(fmd.getExternalValue(objval, _broker)); return; } Object external = null; ValueMetaData vmd = fmd.getKey(); if ((immediate || vmd.isEmbeddedPC()) && vmd.getCascadeDelete() == ValueMetaData.CASCADE_IMMEDIATE) delete(vmd, ((Map) objval).keySet(), call); else if (vmd.getCascadeDelete() == ValueMetaData.CASCADE_AUTO) { external = fmd.getExternalValue(objval, _broker); if (external == null) return; dereferenceDependent(((Map) external).keySet()); } vmd = fmd.getElement(); if ((immediate || vmd.isEmbeddedPC()) && vmd.getCascadeDelete() == ValueMetaData.CASCADE_IMMEDIATE) { switch (fmd.getDeclaredTypeCode()) { case JavaTypes.COLLECTION: delete(vmd, (Collection) objval, call); break; case JavaTypes.ARRAY: delete(vmd, (Object[]) objval, call); break; case JavaTypes.MAP: delete(vmd, ((Map) objval).values(), call); break; } } else if (vmd.getCascadeDelete() == ValueMetaData.CASCADE_AUTO) { if (external == null) { external = fmd.getExternalValue(objval, _broker); if (external == null) return; } switch (fmd.getTypeCode()) { case JavaTypes.COLLECTION: dereferenceDependent((Collection) external); break; case JavaTypes.ARRAY: dereferenceDependent((Object[]) external); break; case JavaTypes.MAP: dereferenceDependent(((Map) external).values()); break; } } } /** * Delete the objects in the given value. */ private void delete(ValueMetaData vmd, Object[] objs, OpCallbacks call) { for (int i = 0; i < objs.length; i++) delete(vmd, objs[i], call); } /** * Delete the objects embedded in the given value. */ private void delete(ValueMetaData vmd, Collection objs, OpCallbacks call) { for (Iterator itr = objs.iterator(); itr.hasNext();) delete(vmd, itr.next(), call); } /** * Delete an object embedded in the given value. */ void delete(ValueMetaData vmd, Object obj, OpCallbacks call) { if (obj == null) return; // delete if unknowned or this isn't an embedded field or if owned by us StateManagerImpl sm = _broker.getStateManagerImpl(obj, false); if (sm != null && (sm.getOwner() == null || !vmd.isEmbeddedPC() || (sm.getOwner() == _sm && sm.getOwnerIndex() == vmd.getFieldMetaData().getIndex()))) _broker.delete(sm.getManagedInstance(), sm, call); } /** * Dereference all valid persistent objects in the given collection. */ private void dereferenceDependent(Object[] objs) { for (int i = 0; i < objs.length; i++) dereferenceDependent(objs[i]); } /** * Dereference all valid persistent objects in the given collection. */ private void dereferenceDependent(Collection objs) { for (Iterator itr = objs.iterator(); itr.hasNext();) dereferenceDependent(itr.next()); } /** * Dereference the given object. */ void dereferenceDependent(Object obj) { if (obj == null) return; StateManagerImpl sm = _broker.getStateManagerImpl(obj, false); if (sm != null) sm.setDereferencedDependent(true, true); } void dereferenceEmbedDependent(StateManagerImpl sm) { sm.setDereferencedEmbedDependent(true); } /** * Recursively invoke the broker to gather cascade-refresh objects in * the current field into the given set. This method is only called * for fields that we know have cascade-refresh settings. */ public void gatherCascadeRefresh(OpCallbacks call) { if (objval == null) return; FieldMetaData fmd = _sm.getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.PC: case JavaTypes.PC_UNTYPED: _broker.gatherCascadeRefresh(objval, call); break; case JavaTypes.ARRAY: gatherCascadeRefresh((Object[]) objval, call); break; case JavaTypes.COLLECTION: gatherCascadeRefresh((Collection) objval, call); break; case JavaTypes.MAP: if (fmd.getKey().getCascadeRefresh() == ValueMetaData.CASCADE_IMMEDIATE) gatherCascadeRefresh(((Map) objval).keySet(), call); if (fmd.getElement().getCascadeRefresh() == ValueMetaData.CASCADE_IMMEDIATE) gatherCascadeRefresh(((Map) objval).values(), call); break; } } /** * Gather each element. */ private void gatherCascadeRefresh(Object[] arr, OpCallbacks call) { for (int i = 0; i < arr.length; i++) _broker.gatherCascadeRefresh(arr[i], call); } /** * Gather each element. */ private void gatherCascadeRefresh(Collection coll, OpCallbacks call) { for (Iterator itr = coll.iterator(); itr.hasNext();) _broker.gatherCascadeRefresh(itr.next(), call); } /** * Perform pre-flush tasks on the current field. This includes checking * for nulls, persisting pcs, embedding embedded fields, and ref'ing * pc fields. Return true if the field needs to be replaced with the * new value. */ public boolean preFlush(boolean logical, OpCallbacks call) { // only care about object fields FieldMetaData fmd = _sm.getMetaData().getField(field); if (fmd.getDeclaredTypeCode() < JavaTypes.OBJECT) return false; // perform pers-by-reach and dependent refs boolean ret = preFlush(fmd, logical, call); // manage inverses InverseManager manager = _broker.getInverseManager(); if (manager != null) manager.correctRelations(_sm, fmd, objval); return ret; } /** * Return true if the last-provided field has a default value. */ public boolean isDefaultValue() { return dblval == 0 && longval == 0 && (objval == null || "".equals(objval)); } /** * Write the stored field or its default value to the given stream. */ public void serialize(ObjectOutput out, boolean def) throws IOException { FieldMetaData fmd = _sm.getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: out.writeBoolean(!def && longval == 1); break; case JavaTypes.BYTE: out.writeByte((def) ? (byte) 0 : (byte) longval); break; case JavaTypes.CHAR: out.writeChar((def) ? (char) 0 : (char) longval); break; case JavaTypes.DOUBLE: out.writeDouble((def) ? 0D : dblval); break; case JavaTypes.FLOAT: out.writeFloat((def) ? 0F : (float) dblval); break; case JavaTypes.INT: out.writeInt((def) ? 0 : (int) longval); break; case JavaTypes.LONG: out.writeLong((def) ? 0L : longval); break; case JavaTypes.SHORT: out.writeShort((def) ? (short) 0 : (short) longval); break; default: out.writeObject((def) ? null : objval); } } /** * Helper method to perform pre flush actions on the current object. */ private boolean preFlush(FieldMetaData fmd, boolean logical, OpCallbacks call) { // check for illegal nulls if (objval == null) { if (fmd.getNullValue() == FieldMetaData.NULL_EXCEPTION || fmd.getDeclaredTypeCode() == JavaTypes.OID) throw new InvalidStateException(_loc.get("null-value", fmd.getName(), _sm.getManagedInstance())). setFatal(true); return false; } // nothing else to do for non-persistent if (fmd.getManagement() != FieldMetaData.MANAGE_PERSISTENT) return false; // don't allow managed objectid field value if (fmd.getDeclaredTypeCode() == JavaTypes.OID) { _sm.assertNotManagedObjectId(objval); if (_sm.getObjectId() != null && !objval.equals(((ObjectId) _sm.getObjectId()).getId())) throw new InvalidStateException(_loc.get("changed-oid", _sm.getObjectId(), objval, Exceptions.toString(_sm.getManagedInstance()))). setFatal(true); } // check for pcs in field value if (preFlush(fmd, fmd.getDeclaredTypeCode(), fmd.getKey().getDeclaredTypeCode(), fmd.getElement().getDeclaredTypeCode(), false, logical, call)) return true; // also check for pcs in externalized values if (fmd.isExternalized()) preFlush(fmd, fmd.getTypeCode(), fmd.getKey().getTypeCode(), fmd.getElement().getTypeCode(), true, logical, call); return false; } /** * Make new objects persistent and ref other objects so referenced * dependent objects won't be deleted. */ private boolean preFlush(FieldMetaData fmd, int type, int keyType, int elemType, boolean external, boolean logical, OpCallbacks call) { Object val = objval; if (val == null) return false; boolean copy = false; switch (type) { case JavaTypes.PC: if (fmd.isEmbeddedPC()) { objval = embed(fmd, val); copy = true; } else { if (external) val = fmd.getExternalValue(val, _broker); if (val != null) preFlushPC(fmd, val, logical, call); } break; case JavaTypes.PC_UNTYPED: if (external) val = fmd.getExternalValue(val, _broker); if (val != null) preFlushPC(fmd, val, logical, call); break; case JavaTypes.ARRAY: if (fmd.getElement().isEmbeddedPC()) embed(fmd.getElement(), (Object[]) val); else if (elemType == JavaTypes.PC || elemType == JavaTypes.PC_UNTYPED) { if (external) val = fmd.getExternalValue(val, _broker); if (val != null) preFlushPCs(fmd.getElement(), (Object[]) val, logical, call); } break; case JavaTypes.COLLECTION: if (fmd.getElement().isEmbeddedPC()) { objval = embed(fmd.getElement(), (Collection) val); copy = true; } else if (elemType == JavaTypes.PC || elemType == JavaTypes.PC_UNTYPED) { boolean flushed = false; if (external) val = fmd.getExternalValue(val, _broker); else if (val instanceof Proxy) { // shortcut change trackers; also ensures we don't // iterate lrs fields ChangeTracker ct = ((Proxy) val).getChangeTracker(); if (ct != null && ct.isTracking()) { preFlushPCs(fmd.getElement(), ct.getAdded(), logical, call); preFlushPCs(fmd.getElement(), ct.getChanged(), logical, call); flushed = true; } } if (!flushed && val != null) preFlushPCs(fmd.getElement(), (Collection) val, logical, call); } break; case JavaTypes.MAP: boolean keyEmbed = fmd.getKey().isEmbeddedPC(); boolean valEmbed = fmd.getElement().isEmbeddedPC(); if (keyEmbed || valEmbed) { objval = embed(fmd, (Map) val, keyEmbed, valEmbed); copy = keyEmbed; } if (!keyEmbed && (keyType == JavaTypes.PC || keyType == JavaTypes.PC_UNTYPED)) { boolean flushed = false; if (external) { val = fmd.getExternalValue(val, _broker); external = false; } else if (val instanceof Proxy) { // shortcut change trackers; also ensures we don't // iterate lrs fields MapChangeTracker ct = (MapChangeTracker) ((Proxy) val). getChangeTracker(); if (ct != null && ct.isTracking() && ct.getTrackKeys()) { preFlushPCs(fmd.getKey(), ct.getAdded(), logical, call); preFlushPCs(fmd.getKey(), ct.getChanged(), logical, call); flushed = true; } } if (!flushed && val != null) preFlushPCs(fmd.getKey(), ((Map) val).keySet(), logical, call); } if (!valEmbed && (elemType == JavaTypes.PC || elemType == JavaTypes.PC_UNTYPED)) { boolean flushed = false; if (external) val = fmd.getExternalValue(val, _broker); else if (val instanceof Proxy) { // shortcut change trackers; also ensures we don't // iterate lrs fields MapChangeTracker ct = (MapChangeTracker) ((Proxy) val). getChangeTracker(); if (ct != null && ct.isTracking()) { if (ct.getTrackKeys()) { preFlushPCs(fmd.getElement(), ct.getAdded(), (Map) val, logical, call); preFlushPCs(fmd.getElement(), ct.getChanged(), (Map) val, logical, call); } else { preFlushPCs(fmd.getElement(), ct.getAdded(), logical, call); preFlushPCs(fmd.getElement(), ct.getChanged(), logical, call); } flushed = true; } } if (!flushed && val != null) preFlushPCs(fmd.getElement(), ((Map) val).values(), logical, call); } break; } return copy; } /** * Make new objects persistent and ref all valid persistent objects for * the given keys. */ private void preFlushPCs(ValueMetaData vmd, Collection keys, Map map, boolean logical, OpCallbacks call) { for (Iterator itr = keys.iterator(); itr.hasNext();) preFlushPC(vmd, map.get(itr.next()), logical, call); } /** * Make new objects persistent and ref all valid persistent objects in * the given array. */ private void preFlushPCs(ValueMetaData vmd, Object[] objs, boolean logical, OpCallbacks call) { for (int i = 0; i < objs.length; i++) preFlushPC(vmd, objs[i], logical, call); } /** * Make new objects persistent and ref all valid persistent objects in * the given collection. */ private void preFlushPCs(ValueMetaData vmd, Collection objs, boolean logical, OpCallbacks call) { for (Iterator itr = objs.iterator(); itr.hasNext();) preFlushPC(vmd, itr.next(), logical, call); } /** * Perform pre flush operations on the given object. */ private void preFlushPC(ValueMetaData vmd, Object obj, boolean logical, OpCallbacks call) { if (obj == null) return; OpenJPAStateManager sm; if (vmd.getCascadePersist() == ValueMetaData.CASCADE_NONE) { if (!_broker.isDetachedNew() && _broker.isDetached(obj, _checkDbOnCascadePersist)) { return; // allow but ignore } sm = _broker.getStateManager(obj); if (sm == null || !sm.isPersistent()) { if (((StoreContext)_broker).getAllowReferenceToSiblingContext() && ImplHelper.isManageable(obj) && ((PersistenceCapable)obj).pcGetStateManager() != null) { return; } else { throw new InvalidStateException(_loc.get("cant-cascade-persist", vmd.toString(), Exceptions.toString(obj), sm == null ? " unmanaged" : sm.getPCState().getClass().getSimpleName())) .setFailedObject(obj); } } } else { if (vmd.getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE) { if (!_broker.isDetachedNew() && _broker.isDetached(obj, _checkDbOnCascadePersist)) { return; // allow but ignore } } sm = _broker.getStateManager(obj); if (sm == null || !sm.isProvisional()) { sm = _broker.persist(obj, null, true, call); // ensure generated IDs get assigned properly if (!logical) ((StateManagerImpl)sm).assignObjectId(false, true); // Call preFetch on this and any related persistent fields. // This will ensure IDs get assigned to those that need them. if (_broker.isFlushing()) { ((StateManagerImpl)sm).preFlush(logical, call); } } } if (sm != null) { // if deleted and not managed inverse, die if (sm.isDeleted() && (_broker.getInverseManager() == null || vmd.getFieldMetaData().getInverseMetaDatas().length == 0)) throw new UserException(_loc.get("ref-to-deleted", Exceptions.toString(obj), vmd, Exceptions.toString(_sm.getManagedInstance()))). setFailedObject(obj); StateManagerImpl smimpl = (StateManagerImpl) sm; smimpl.nonprovisional(logical, call); smimpl.setDereferencedDependent(false, true); } } /** * Make all elements of the given array embedded. */ private void embed(ValueMetaData vmd, Object[] arr) { for (int i = 0; i < arr.length; i++) arr[i] = embed(vmd, arr[i]); } /** * Create a copy of the given collection containing embedded elements. */ private Collection embed(ValueMetaData vmd, Collection orig) { // we have to copy to get a collection of the right type and size, // though we immediately clear it if (orig == null) throw new UserException(_loc.get("not-copyable", vmd.getFieldMetaData())); Collection coll = null; try { coll = getProxyManager().copyCollection(orig); } catch (Exception e) { coll = (Collection) _sm.newFieldProxy(vmd.getFieldMetaData().getIndex()); } coll.clear(); for (Iterator itr = orig.iterator(); itr.hasNext();) coll.add(embed(vmd, itr.next())); return coll; } /** * Embed the elements of the given map. */ private Map embed(FieldMetaData fmd, Map orig, boolean keyEmbed, boolean valEmbed) { Map map; Map.Entry entry; // if we have to replace keys, we need to copy the map; otherwise // we can mutate the values directly if (keyEmbed) { if (orig == null) throw new UserException(_loc.get("not-copyable", fmd)); // we have to copy to get a collection of the right type and size, // though we immediately clear it try { map = getProxyManager().copyMap(orig); } catch (Exception e) { map = (Map) _sm.newFieldProxy(fmd.getIndex()); } map.clear(); Object key, val; for (Iterator itr = orig.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); key = embed(fmd.getKey(), entry.getKey()); val = entry.getValue(); if (valEmbed) val = embed(fmd.getElement(), val); map.put(key, val); } } else { map = orig; for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); entry.setValue(embed(fmd.getElement(), entry.getValue())); } } return map; } /** * Make the given object embedded. */ private Object embed(ValueMetaData vmd, Object obj) { if (obj == null) return null; return _broker.embed(obj, null, _sm, vmd).getManagedInstance(); } /** * Return the proxy manager. */ private ProxyManager getProxyManager () { return _broker.getConfiguration ().getProxyManagerInstance (); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectIdStateManager.java0000644000000000000000000005144412133327272030124 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.IOException; import java.io.ObjectOutput; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.BitSet; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.enhance.Reflection; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.ImplHelper; /** * State manager used to access state of embedded object id primary key fields. * * @author Abe White * @nojavadoc */ public class ObjectIdStateManager implements OpenJPAStateManager { private static final Byte ZERO_BYTE = Byte.valueOf((byte)0); private static final Character ZERO_CHAR = Character.valueOf((char)0); private static final Double ZERO_DOUBLE = Double.valueOf(0); private static final Float ZERO_FLOAT = Float.valueOf(0); private static final Short ZERO_SHORT = Short.valueOf((short)0); private Object _oid; private final OpenJPAStateManager _owner; private final ValueMetaData _vmd; /** * Constructor; supply embedded object id and its owner. * * @param owner may be null */ public ObjectIdStateManager(Object oid, OpenJPAStateManager owner, ValueMetaData ownerVal) { _oid = oid; _owner = owner; _vmd = ownerVal; } public Object getGenericContext() { return (_owner == null) ? null : _owner.getGenericContext(); } public Object getPCPrimaryKey(Object oid, int field) { throw new UnsupportedOperationException(); } public StateManager replaceStateManager(StateManager sm) { throw new UnsupportedOperationException(); } public Object getVersion() { return null; } public void setVersion(Object version) { throw new UnsupportedOperationException(); } public boolean isDirty() { return false; } public boolean isTransactional() { return false; } public boolean isPersistent() { return false; } public boolean isNew() { return false; } public boolean isDeleted() { return false; } public boolean isDetached() { return true; } public boolean isVersionUpdateRequired() { return false; } public boolean isVersionCheckRequired() { return false; } public void dirty(String field) { throw new UnsupportedOperationException(); } public Object fetchObjectId() { return null; } public void accessingField(int idx) { throw new UnsupportedOperationException(); } public boolean serializing() { throw new UnsupportedOperationException(); } public boolean writeDetached(ObjectOutput out) throws IOException { throw new UnsupportedOperationException(); } public void proxyDetachedDeserialized(int idx) { throw new UnsupportedOperationException(); } public void settingBooleanField(PersistenceCapable pc, int idx, boolean cur, boolean next, int set) { throw new UnsupportedOperationException(); } public void settingCharField(PersistenceCapable pc, int idx, char cur, char next, int set) { throw new UnsupportedOperationException(); } public void settingByteField(PersistenceCapable pc, int idx, byte cur, byte next, int set) { throw new UnsupportedOperationException(); } public void settingShortField(PersistenceCapable pc, int idx, short cur, short next, int set) { throw new UnsupportedOperationException(); } public void settingIntField(PersistenceCapable pc, int idx, int cur, int next, int set) { throw new UnsupportedOperationException(); } public void settingLongField(PersistenceCapable pc, int idx, long cur, long next, int set) { throw new UnsupportedOperationException(); } public void settingFloatField(PersistenceCapable pc, int idx, float cur, float next, int set) { throw new UnsupportedOperationException(); } public void settingDoubleField(PersistenceCapable pc, int idx, double cur, double next, int set) { throw new UnsupportedOperationException(); } public void settingStringField(PersistenceCapable pc, int idx, String cur, String next, int set) { throw new UnsupportedOperationException(); } public void settingObjectField(PersistenceCapable pc, int idx, Object cur, Object next, int set) { throw new UnsupportedOperationException(); } public void providedBooleanField(PersistenceCapable pc, int idx, boolean cur) { throw new UnsupportedOperationException(); } public void providedCharField(PersistenceCapable pc, int idx, char cur) { throw new UnsupportedOperationException(); } public void providedByteField(PersistenceCapable pc, int idx, byte cur) { throw new UnsupportedOperationException(); } public void providedShortField(PersistenceCapable pc, int idx, short cur) { throw new UnsupportedOperationException(); } public void providedIntField(PersistenceCapable pc, int idx, int cur) { throw new UnsupportedOperationException(); } public void providedLongField(PersistenceCapable pc, int idx, long cur) { throw new UnsupportedOperationException(); } public void providedFloatField(PersistenceCapable pc, int idx, float cur) { throw new UnsupportedOperationException(); } public void providedDoubleField(PersistenceCapable pc, int idx, double cur) { throw new UnsupportedOperationException(); } public void providedStringField(PersistenceCapable pc, int idx, String cur) { throw new UnsupportedOperationException(); } public void providedObjectField(PersistenceCapable pc, int idx, Object cur) { throw new UnsupportedOperationException(); } public boolean replaceBooleanField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public char replaceCharField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public byte replaceByteField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public short replaceShortField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public int replaceIntField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public long replaceLongField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public float replaceFloatField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public double replaceDoubleField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public String replaceStringField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } public Object replaceObjectField(PersistenceCapable pc, int idx) { throw new UnsupportedOperationException(); } /////////////////////////////////// // OpenJPAStateManager implementation /////////////////////////////////// public void initialize(Class forType, PCState state) { throw new UnsupportedOperationException(); } public void load(FetchConfiguration fetch) { throw new UnsupportedOperationException(); } public Object getManagedInstance() { return _oid; } public PersistenceCapable getPersistenceCapable() { return ImplHelper.toPersistenceCapable(_oid, _vmd.getRepository().getConfiguration()); } public ClassMetaData getMetaData() { return _vmd.getEmbeddedMetaData(); } public OpenJPAStateManager getOwner() { return _owner; } public int getOwnerIndex() { return _vmd.getFieldMetaData().getIndex(); } public boolean isEmbedded() { return true; } public boolean isFlushed() { return false; } public boolean isFlushedDirty() { return false; } public boolean isProvisional() { return false; } public BitSet getLoaded() { throw new UnsupportedOperationException(); } public BitSet getDirty() { throw new UnsupportedOperationException(); } public BitSet getFlushed() { throw new UnsupportedOperationException(); } public BitSet getUnloaded(FetchConfiguration fetch) { throw new UnsupportedOperationException(); } public Object newProxy(int field) { throw new UnsupportedOperationException(); } public Object newFieldProxy(int field) { throw new UnsupportedOperationException(); } public boolean isDefaultValue(int field) { Object val = getValue(field); if (val == null) return true; FieldMetaData fmd = getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: return Boolean.FALSE.equals(val); case JavaTypes.CHAR: return ((Character) val).charValue() == 0; case JavaTypes.BYTE: case JavaTypes.DOUBLE: case JavaTypes.FLOAT: case JavaTypes.INT: case JavaTypes.LONG: case JavaTypes.SHORT: return ((Number) val).intValue() == 0; case JavaTypes.STRING: return "".equals(val); default: return false; } } public StoreContext getContext() { return (_owner == null) ? null : _owner.getContext(); } public PCState getPCState() { throw new UnsupportedOperationException(); } public Object getObjectId() { return null; } public void setObjectId(Object oid) { throw new UnsupportedOperationException(); } public boolean assignObjectId(boolean flush) { throw new UnsupportedOperationException(); } public Object getId() { return null; } public Object getLock() { return null; } public void setLock(Object lock) { throw new UnsupportedOperationException(); } public void setNextVersion(Object version) { throw new UnsupportedOperationException(); } public Object getImplData() { return null; } public Object setImplData(Object data, boolean cacheable) { throw new UnsupportedOperationException(); } public boolean isImplDataCacheable() { return false; } public Object getImplData(int field) { return null; } public Object setImplData(int field, Object data) { throw new UnsupportedOperationException(); } public boolean isImplDataCacheable(int field) { return false; } public Object getIntermediate(int field) { return null; } public void setIntermediate(int field, Object data) { throw new UnsupportedOperationException(); } public void removed(int field, Object removed, boolean key) { throw new UnsupportedOperationException(); } public boolean beforeRefresh(boolean all) { throw new UnsupportedOperationException(); } public void dirty(int field) { throw new UnsupportedOperationException(); } public void storeBoolean(int field, boolean extVal) { setValue(field, (extVal) ? Boolean.TRUE : Boolean.FALSE, true); } public void storeByte(int field, byte extVal) { setValue(field, Byte.valueOf(extVal), true); } public void storeChar(int field, char extVal) { setValue(field, Character.valueOf(extVal), true); } public void storeInt(int field, int extVal) { setValue(field, extVal, true); } public void storeShort(int field, short extVal) { setValue(field, Short.valueOf(extVal), true); } public void storeLong(int field, long extVal) { setValue(field, extVal, true); } public void storeFloat(int field, float extVal) { setValue(field, Float.valueOf(extVal), true); } public void storeDouble(int field, double extVal) { setValue(field, Double.valueOf(extVal), true); } public void storeString(int field, String extVal) { setValue(field, extVal, extVal != null); } public void storeObject(int field, Object extVal) { setValue(field, extVal, extVal != null); } public void store(int field, Object extVal) { boolean forceInst = true; if (extVal == null) { extVal = getDefaultValue(field); forceInst = false; } setValue(field, extVal, forceInst); } public void storeBooleanField(int field, boolean extVal) { storeBoolean(field, extVal); } public void storeByteField(int field, byte extVal) { storeByte(field, extVal); } public void storeCharField(int field, char extVal) { storeChar(field, extVal); } public void storeIntField(int field, int extVal) { storeInt(field, extVal); } public void storeShortField(int field, short extVal) { storeShort(field, extVal); } public void storeLongField(int field, long extVal) { storeLong(field, extVal); } public void storeFloatField(int field, float extVal) { storeFloat(field, extVal); } public void storeDoubleField(int field, double extVal) { storeDouble(field, extVal); } public void storeStringField(int field, String extVal) { storeString(field, extVal); } public void storeObjectField(int field, Object extVal) { storeObject(field, extVal); } public void storeField(int field, Object value) { store(field, value); } public boolean fetchBoolean(int field) { return ((Boolean) getValue(field)).booleanValue(); } public byte fetchByte(int field) { return ((Number) getValue(field)).byteValue(); } public char fetchChar(int field) { return ((Character) getValue(field)).charValue(); } public short fetchShort(int field) { return ((Number) getValue(field)).shortValue(); } public int fetchInt(int field) { return ((Number) getValue(field)).intValue(); } public long fetchLong(int field) { return ((Number) getValue(field)).longValue(); } public float fetchFloat(int field) { return ((Number) getValue(field)).floatValue(); } public double fetchDouble(int field) { return ((Number) getValue(field)).doubleValue(); } public String fetchString(int field) { return (String) getValue(field); } public Object fetchObject(int field) { return getValue(field); } public Object fetch(int field) { Object ret = getValue(field); if (ret == null) ret = getDefaultValue(field); return ret; } public boolean fetchBooleanField(int field) { return fetchBoolean(field); } public byte fetchByteField(int field) { return fetchByte(field); } public char fetchCharField(int field) { return fetchChar(field); } public short fetchShortField(int field) { return fetchShort(field); } public int fetchIntField(int field) { return fetchInt(field); } public long fetchLongField(int field) { return fetchLong(field); } public float fetchFloatField(int field) { return fetchFloat(field); } public double fetchDoubleField(int field) { return fetchDouble(field); } public String fetchStringField(int field) { return fetchString(field); } public Object fetchObjectField(int field) { return fetch(field); } public Object fetchField(int field, boolean transitions) { return fetch(field); } public Object fetchInitialField(int field) { throw new UnsupportedOperationException(); } public void setRemote(int field, Object value) { store(field, value); } public void lock() { } public void unlock() { } /** * Return the default value of the given field based on its type. */ private Object getDefaultValue(int field) { FieldMetaData fmd = getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: return Boolean.FALSE; case JavaTypes.BYTE: return ZERO_BYTE; case JavaTypes.CHAR: return ZERO_CHAR; case JavaTypes.DOUBLE: return ZERO_DOUBLE; case JavaTypes.FLOAT: return ZERO_FLOAT; case JavaTypes.INT: return 0; case JavaTypes.LONG: return 0L; case JavaTypes.SHORT: return ZERO_SHORT; default: return null; } } /** * Return the value of the given field using reflection. * Relies on the fact that all oid fields/properties are made public * during enhancement. */ private Object getValue(int field) { if (_oid == null) return null; FieldMetaData fmd = getMetaData().getField(field); Object val = null; if (fmd.getBackingMember() instanceof Field) val = Reflection.get(_oid, (Field) fmd.getBackingMember()); else if (fmd.getBackingMember() instanceof Method) val = Reflection.get(_oid, (Method) fmd.getBackingMember()); else if (AccessCode.isField(fmd.getDefiningMetaData().getAccessType())) val = Reflection.get(_oid, Reflection.findField(_oid.getClass(), fmd.getName(), true)); else val = Reflection.get(_oid, Reflection.findGetter(_oid.getClass(), fmd.getName(), true)); if (fmd.getValue().getEmbeddedMetaData() != null) return new ObjectIdStateManager(val, null, fmd); return val; } /** * Set the value of the given field using reflection. * Relies on the fact that all oid fields/properties are made public * during enhancement. */ private void setValue(int field, Object val, boolean forceInst) { if (_oid == null && forceInst) { try { _oid = AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction( getMetaData().getDescribedType())); } catch (Exception e) { if (e instanceof PrivilegedActionException) e = ((PrivilegedActionException) e).getException(); throw new GeneralException(e); } } else if (_oid == null) return; FieldMetaData fmd = getMetaData().getField(field); if (fmd.getBackingMember() instanceof Field) Reflection.set(_oid, (Field) fmd.getBackingMember(), val); else if (AccessCode.isField(fmd.getDefiningMetaData().getAccessType())) Reflection.set(_oid, Reflection.findField(_oid.getClass(), fmd.getName(), true), val); else Reflection.set(_oid, Reflection.findSetter(_oid.getClass(), fmd.getName(), fmd.getDeclaredType(), true), val); } @Override public boolean isDelayed(int field) { return false; } @Override public void setDelayed(int field, boolean delay) { throw new UnsupportedOperationException(); } @Override public void loadDelayedField(int field) { throw new UnsupportedOperationException(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingExtent.java0000644000000000000000000001134212133327272027371 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Iterator; import java.util.List; import org.apache.openjpa.util.RuntimeExceptionTranslator; /////////////////////////////////////////////////////////////// // NOTE: when adding a public API method, be sure to add it to // JDO and JPA facades! /////////////////////////////////////////////////////////////// /** * Delegating extent that also can perform exception translation for use * in facades. * * @since 0.4.0 * @author Abe White * @nojavadoc */ public class DelegatingExtent implements Extent { private final Extent _extent; private final DelegatingExtent _del; private final RuntimeExceptionTranslator _trans; /** * Constructor; supply delegate. */ public DelegatingExtent(Extent extent) { this(extent, null); } /** * Constructor; supply delegate and exception translator. */ public DelegatingExtent(Extent extent, RuntimeExceptionTranslator trans) { _extent = extent; if (extent instanceof DelegatingExtent) _del = (DelegatingExtent) extent; else _del = null; _trans = trans; } /** * Return the direct delegate. */ public Extent getDelegate() { return _extent; } /** * Return the native delegate. */ public Extent getInnermostDelegate() { return (_del == null) ? _extent : _del.getInnermostDelegate(); } public int hashCode() { return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingExtent) other = ((DelegatingExtent) other).getInnermostDelegate(); return getInnermostDelegate().equals(other); } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public Class getElementType() { try { return _extent.getElementType(); } catch (RuntimeException re) { throw translate(re); } } public boolean hasSubclasses() { try { return _extent.hasSubclasses(); } catch (RuntimeException re) { throw translate(re); } } public Broker getBroker() { try { return _extent.getBroker(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration getFetchConfiguration() { try { return _extent.getFetchConfiguration(); } catch (RuntimeException re) { throw translate(re); } } public boolean getIgnoreChanges() { try { return _extent.getIgnoreChanges(); } catch (RuntimeException re) { throw translate(re); } } public void setIgnoreChanges(boolean ignoreCache) { try { _extent.setIgnoreChanges(ignoreCache); } catch (RuntimeException re) { throw translate(re); } } public List list() { try { return _extent.list(); } catch (RuntimeException re) { throw translate(re); } } public Iterator iterator() { try { return _extent.iterator(); } catch (RuntimeException re) { throw translate(re); } } public void closeAll() { try { _extent.closeAll(); } catch (RuntimeException re) { throw translate(re); } } public void lock() { try { _extent.lock(); } catch (RuntimeException re) { throw translate(re); } } public void unlock() { try { _extent.unlock(); } catch (RuntimeException re) { throw translate(re); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java0000644000000000000000000007601612133327272026632 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.IOException; import java.io.ObjectOutput; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.BitSet; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.commons.collections.map.IdentityMap; import org.apache.openjpa.conf.Compatibility; import org.apache.openjpa.conf.DetachOptions; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.event.CallbackModes; import org.apache.openjpa.event.LifecycleEvent; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.CallbackException; import org.apache.openjpa.util.ObjectNotFoundException; import org.apache.openjpa.util.Proxy; import org.apache.openjpa.util.ProxyManager; import org.apache.openjpa.util.UserException; /** * Handles detaching instances. * * @author Marc Prud'hommeaux * @nojavadoc */ public class DetachManager implements DetachState { private static Localizer _loc = Localizer.forPackage(DetachManager.class); private final BrokerImpl _broker; private final boolean _copy; private final boolean _full; private final ProxyManager _proxy; private final DetachOptions _opts; private final OpCallbacks _call; private final boolean _failFast; private boolean _flushed = false; private boolean _flushBeforeDetach; private boolean _cascadeWithDetach; private boolean _reloadOnDetach; // if we're not detaching full, we need to track all detached objects; // if we are, then we use a special field manager for more efficient // detachment than the standard one private final IdentityMap _detached; private final DetachFieldManager _fullFM; /** * Used to prepare a detachable instance that does not externalize * detached state. */ static boolean preSerialize(StateManagerImpl sm) { if (!sm.isPersistent()) return false; if (sm.getBroker().getConfiguration().getCompatibilityInstance() .getFlushBeforeDetach()) { flushDirty(sm); } ClassMetaData meta = sm.getMetaData(); boolean setState = meta.getDetachedState() != null && !ClassMetaData.SYNTHETIC.equals(meta.getDetachedState()); BitSet idxs = (setState) ? new BitSet(meta.getFields().length) : null; preDetach(sm.getBroker(), sm, idxs, false, true); if (setState) { sm.getPersistenceCapable().pcSetDetachedState(getDetachedState (sm, idxs)); return false; // don't null state } return true; } /** * Used by classes that externalize detached state. * * @return whether to use a detached state manager */ static boolean writeDetachedState(StateManagerImpl sm, ObjectOutput out, BitSet idxs) throws IOException { if (!sm.isPersistent()) { out.writeObject(null); // state out.writeObject(null); // sm return false; } // dirty state causes flush flushDirty(sm); Broker broker = sm.getBroker(); preDetach(broker, sm, idxs, false, true); // write detached state object and state manager DetachOptions opts = broker.getConfiguration(). getDetachStateInstance(); if (!opts.getDetachedStateManager() || !useDetachedStateManager(sm, opts)) { out.writeObject(getDetachedState(sm, idxs)); out.writeObject(null); return false; } out.writeObject(null); out.writeObject(new DetachedStateManager(sm.getPersistenceCapable(), sm, idxs, opts.getAccessUnloaded(), broker.getMultithreaded())); return true; } /** * Ready the object for detachment, including loading the fields to be * detached and updating version information. * * @param idxs the indexes of fields to detach will be set as a side * effect of this method */ private static void preDetach(Broker broker, StateManagerImpl sm, BitSet idxs, boolean full, boolean reloadOnDetach) { // make sure the existing object has the right fields fetched; call // even if using currently-loaded fields for detach to make sure // version is set int detachMode = broker.getDetachState(); int loadMode = StateManagerImpl.LOAD_FGS; BitSet exclude = null; if (detachMode == DETACH_LOADED) exclude = StoreContext.EXCLUDE_ALL; else if (detachMode == DETACH_ALL) loadMode = StateManagerImpl.LOAD_ALL; try { if (detachMode != DETACH_LOADED || reloadOnDetach || (!reloadOnDetach && !full)) { sm.load(broker.getFetchConfiguration(), loadMode, exclude, null, false); } } catch (ObjectNotFoundException onfe) { // consume the exception } // create bitset of fields to detach; if mode is all we can use // currently loaded bitset clone, since we know all fields are loaded if (idxs != null) { if (detachMode == DETACH_FETCH_GROUPS) setFetchGroupFields(broker, sm, idxs); else idxs.or(sm.getLoaded()); // clear lrs fields FieldMetaData[] fmds = sm.getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) if (fmds[i].isLRS()) idxs.clear(i); } } /** * Generate the detached state for the given instance. */ private static Object getDetachedState(StateManagerImpl sm, BitSet fields) { // if datastore, store id in first element int offset = (sm.getMetaData().getIdentityType() == ClassMetaData.ID_DATASTORE) ? 1 : 0; // make version state array one larger for new instances; marks new // instances without affecting serialization size much Object[] state; if (sm.isNew()) state = new Object[3 + offset]; else state = new Object[2 + offset]; if (offset > 0) { Object id; if (sm.isEmbedded() || sm.getObjectId() == null) id = sm.getId(); else id = sm.getObjectId(); state[0] = id.toString(); } state[offset] = sm.getVersion(); state[offset + 1] = fields; return state; } /** * Flush or invoke pre-store callbacks on the given broker if * needed. Return true if flushed/stored, false otherwise. */ private static boolean flushDirty(StateManagerImpl sm) { if (!sm.isDirty() || !sm.getBroker().isActive()) return false; // only flush if there are actually any dirty non-flushed fields BitSet dirtyFields = sm.getDirty(); BitSet flushedFields = sm.getFlushed(); for (int i = 0; i < dirtyFields.size(); i++) { if (dirtyFields.get(i) && !flushedFields.get(i)) { if (sm.getBroker().getRollbackOnly()) sm.getBroker().preFlush(); else sm.getBroker().flush(); return true; } } return false; } /** * Create a bit set for the fields in the current fetch groups. */ private static void setFetchGroupFields(Broker broker, StateManagerImpl sm, BitSet idxs) { FetchConfiguration fetch = broker.getFetchConfiguration(); FieldMetaData[] fmds = sm.getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].isPrimaryKey() || fetch.requiresFetch(fmds[i]) != FetchConfiguration.FETCH_NONE) idxs.set(i); } } /** * Constructor. * * @param broker owning broker * @param full whether the entire broker cache is being detached; if * this is the case, we assume the broker has already * flushed if needed, and that we're detaching in-place */ public DetachManager(BrokerImpl broker, boolean full, OpCallbacks call) { _broker = broker; _proxy = broker.getConfiguration().getProxyManagerInstance(); _opts = broker.getConfiguration().getDetachStateInstance(); _flushed = full; _call = call; _failFast = (broker.getConfiguration().getMetaDataRepositoryInstance(). getMetaDataFactory().getDefaults().getCallbackMode() & CallbackModes.CALLBACK_FAIL_FAST) != 0; // we can only rely on our "full" shortcuts if we know we won't be // loading any more data _full = full && broker.getDetachState() == DetachState.DETACH_LOADED; if (_full) { _detached = null; _fullFM = new DetachFieldManager(); } else { _detached = new IdentityMap(); _fullFM = null; } Compatibility compatibility = broker.getConfiguration().getCompatibilityInstance(); _flushBeforeDetach = compatibility.getFlushBeforeDetach(); _reloadOnDetach = compatibility.getReloadOnDetach(); _cascadeWithDetach = compatibility.getCascadeWithDetach(); if (full) { _copy = false; } else { _copy = compatibility.getCopyOnDetach();; } } /** * Return a detached version of the given instance. */ public Object detach(Object toDetach) { List exceps = null; try { return detachInternal(toDetach); } catch (CallbackException ce) { exceps = new ArrayList(1); exceps.add(ce); return null; // won't be reached as exception will be rethrown } finally { if (exceps == null || !_failFast) exceps = invokeAfterDetach(Collections.singleton(toDetach), exceps); if (_detached != null) _detached.clear(); throwExceptions(exceps); } } /** * Return detached versions of all the given instances. If not copying, * null will be returned. */ public Object[] detachAll(Collection instances) { List exceps = null; List detached = null; if (_copy) detached = new ArrayList(instances.size()); boolean failFast = false; try { Object detach; for (Iterator itr = instances.iterator(); itr.hasNext();) { detach = detachInternal(itr.next()); if (_copy) detached.add(detach); } } catch (RuntimeException re) { if (re instanceof CallbackException && _failFast) failFast = true; exceps = add(exceps, re); } finally { if (!failFast) exceps = invokeAfterDetach(instances, exceps); if (_detached != null) _detached.clear(); } throwExceptions(exceps); if (_copy) return detached.toArray(); return null; } /** * Invoke postDetach() on any detached instances that implement * PostDetachCallback. This will be done after the entire graph has * been detached. This method has the side-effect of also clearing * out the map of all detached instances. */ private List invokeAfterDetach(Collection objs, List exceps) { Iterator itr = (_full) ? objs.iterator() : _detached.entrySet().iterator(); Object orig, detached; Map.Entry entry; while (itr.hasNext()) { if (_full) { orig = itr.next(); detached = orig; } else { entry = (Map.Entry) itr.next(); orig = entry.getKey(); detached = entry.getValue(); } StateManagerImpl sm = _broker.getStateManagerImpl(orig, true); try { if (sm != null) _broker.fireLifecycleEvent(detached, orig, sm.getMetaData(), LifecycleEvent.AFTER_DETACH); } catch (CallbackException ce) { exceps = add(exceps, ce); if (_failFast) break; // don't continue processing } } return exceps; } /** * Add an exception to the list. */ private List add(List exceps, RuntimeException re) { if (exceps == null) exceps = new LinkedList(); exceps.add(re); return exceps; } /** * Throw all gathered exceptions. */ private void throwExceptions(List exceps) { if (exceps == null) return; if (exceps.size() == 1) throw (RuntimeException) exceps.get(0); throw new UserException(_loc.get("nested-exceps")). setNestedThrowables((Throwable[]) exceps.toArray (new Throwable[exceps.size()])); } /** * Detach. */ private Object detachInternal(Object toDetach) { if (toDetach == null) return null; // already detached? if (_detached != null) { Object detached = _detached.get(toDetach); if (detached != null) return detached; } StateManagerImpl sm = _broker.getStateManagerImpl(toDetach, true); if (_call != null && (_call.processArgument(OpCallbacks.OP_DETACH, toDetach, sm) & OpCallbacks.ACT_RUN) == 0) return toDetach; if (sm == null) return toDetach; // Call PreDetach first as we can't tell if the new system // fired an event or just did not fail. _broker.fireLifecycleEvent(toDetach, null, sm.getMetaData(), LifecycleEvent.BEFORE_DETACH); if(! _flushed) { if(_flushBeforeDetach) { // any dirty instances cause a flush to occur flushDirty(sm); } _flushed = true; } BitSet fields = new BitSet(); preDetach(_broker, sm, fields, _full, _reloadOnDetach); // create and store new object before copy to avoid endless recursion PersistenceCapable pc = sm.getPersistenceCapable(); PersistenceCapable detachedPC; if (_copy) detachedPC = pc.pcNewInstance(null, true); else detachedPC = pc; if (_detached != null) _detached.put(toDetach, detachedPC); // detach fields and set detached variables DetachedStateManager detSM = null; if (_opts.getDetachedStateManager() && useDetachedStateManager(sm, _opts) && !(sm.isNew() && !sm.isDeleted() && !sm.isFlushed())) detSM = new DetachedStateManager(detachedPC, sm, fields, _opts.getAccessUnloaded(), _broker.getMultithreaded()); if (_full) { _fullFM.setStateManager(sm); if (_copy || _reloadOnDetach) { _fullFM.detachVersion(); } _fullFM.reproxy(detSM); _fullFM.setStateManager(null); } else { InstanceDetachFieldManager fm = new InstanceDetachFieldManager(detachedPC, detSM); fm.setStateManager(sm); fm.detachFields(fields); } if (!Boolean.FALSE.equals(sm.getMetaData().usesDetachedState())) detachedPC.pcSetDetachedState(getDetachedState(sm, fields)); if (!_copy) sm.release(false, true); if (detSM != null) detachedPC.pcReplaceStateManager(detSM); return detachedPC; } private static boolean useDetachedStateManager(StateManagerImpl sm, DetachOptions opts) { ClassMetaData meta = sm.getMetaData(); return !Boolean.FALSE.equals(meta.usesDetachedState()) && ClassMetaData.SYNTHETIC.equals(meta.getDetachedState()) && opts.getDetachedStateManager(); } /** * Base detach field manager. */ private static class DetachFieldManager extends TransferFieldManager { protected StateManagerImpl sm; /** * Set the source state manager. */ public void setStateManager(StateManagerImpl sm) { this.sm = sm; } /** * Transfer the current version object from the state manager to the * detached instance. */ public void detachVersion() { FieldMetaData fmd = sm.getMetaData().getVersionField(); if (fmd == null) return; Object val = JavaTypes.convert(sm.getVersion(), fmd.getTypeCode()); val = fmd.getFieldValue(val, sm.getBroker()); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.LONG: case JavaTypes.SHORT: case JavaTypes.INT: case JavaTypes.BYTE: longval = (val == null) ? 0L : ((Number) val).longValue(); break; case JavaTypes.DOUBLE: case JavaTypes.FLOAT: dblval = (val == null) ? 0D : ((Number) val).doubleValue(); break; default: objval = val; } sm.replaceField(getDetachedPersistenceCapable(), this, fmd.getIndex()); } /** * Unproxies second class object fields. */ public void reproxy(DetachedStateManager dsm) { for (FieldMetaData fmd : sm.getMetaData().getProxyFields()) { switch (fmd.getDeclaredTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.MAP: // lrs proxies not detached if (fmd.isLRS()) { objval = null; sm.replaceField(getDetachedPersistenceCapable(), this, fmd.getIndex()); break; } // no break case JavaTypes.CALENDAR: case JavaTypes.DATE: case JavaTypes.OBJECT: sm.provideField(getDetachedPersistenceCapable(), this, fmd.getIndex()); if (objval instanceof Proxy) { Proxy proxy = (Proxy) objval; if (proxy.getChangeTracker() != null) proxy.getChangeTracker().stopTracking(); proxy.setOwner(dsm, (dsm == null) ? -1 : fmd.getIndex()); } } } clear(); } /** * Return the instance being detached. */ protected PersistenceCapable getDetachedPersistenceCapable() { return sm.getPersistenceCapable(); } } /** * FieldManager that can copy all the fields from one * PersistenceCapable instance to another. One of the * instances must be managed by a StateManager, and the * other must be unmanaged. * * @author Marc Prud'hommeaux */ private class InstanceDetachFieldManager extends DetachFieldManager { private final PersistenceCapable _to; private final DetachedStateManager _detSM; /** * Constructor. Supply instance to to copy to. */ public InstanceDetachFieldManager(PersistenceCapable to, DetachedStateManager detSM) { _to = to; _detSM = detSM; } protected PersistenceCapable getDetachedPersistenceCapable() { return _to; } /** * Detach the fields of the state manager given on construction to * the persistence capable given on construction. * Only the fields in the given bit set will be copied. */ public void detachFields(BitSet fgfields) { PersistenceCapable from = sm.getPersistenceCapable(); FieldMetaData[] pks = sm.getMetaData().getPrimaryKeyFields(); FieldMetaData[] fmds = sm.getMetaData().getFields(); if (_copy) _to.pcReplaceStateManager(sm); try { // we start with pk fields: objects might rely on pk fields for // equals and hashCode methods, and this ensures that pk fields // are set properly if we return any partially-detached objects // due to reentrant calls when traversing relations for (int i = 0; i < pks.length; i++) detachField(from, pks[i].getIndex(), true); detachVersion(); for (int i = 0; i < fmds.length; i++) if (!fmds[i].isPrimaryKey() && !fmds[i].isVersion()) detachField(from, i, fgfields.get(i)); } finally { // clear the StateManager from the target object if (_copy) _to.pcReplaceStateManager(null); } } /** * Detach (or clear) the given field index. */ private void detachField(PersistenceCapable from, int i, boolean fg) { // tell the state manager to provide the fields from the source to // this field manager, which will then replace the field with a // detached version if (fg) sm.provideField(from, this, i); else if (!_copy) { // if not copying and field should not be detached, clear it clear(); sm.replaceField(_to, this, i); } } public void storeBooleanField(int field, boolean curVal) { super.storeBooleanField(field, curVal); sm.replaceField(_to, this, field); } public void storeByteField(int field, byte curVal) { super.storeByteField(field, curVal); sm.replaceField(_to, this, field); } public void storeCharField(int field, char curVal) { super.storeCharField(field, curVal); sm.replaceField(_to, this, field); } public void storeDoubleField(int field, double curVal) { super.storeDoubleField(field, curVal); sm.replaceField(_to, this, field); } public void storeFloatField(int field, float curVal) { super.storeFloatField(field, curVal); sm.replaceField(_to, this, field); } public void storeIntField(int field, int curVal) { super.storeIntField(field, curVal); sm.replaceField(_to, this, field); } public void storeLongField(int field, long curVal) { super.storeLongField(field, curVal); sm.replaceField(_to, this, field); } public void storeShortField(int field, short curVal) { super.storeShortField(field, curVal); sm.replaceField(_to, this, field); } public void storeStringField(int field, String curVal) { super.storeStringField(field, curVal); sm.replaceField(_to, this, field); } public void storeObjectField(int field, Object curVal) { super.storeObjectField(field, detachField(curVal, field)); sm.replaceField(_to, this, field); } /** * Set the owner of the field's proxy to the detached state manager. */ private Object reproxy(Object obj, int field) { if (obj != null && _detSM != null && obj instanceof Proxy) ((Proxy) obj).setOwner(_detSM, field); return obj; } /** * Detach the given value if needed. */ private Object detachField(Object curVal, int field) { if (curVal == null) return null; FieldMetaData fmd = sm.getMetaData().getField(field); boolean cascade = false; if(_cascadeWithDetach || fmd.getCascadeDetach() == ValueMetaData.CASCADE_IMMEDIATE || fmd.getKey().getCascadeDetach() == ValueMetaData.CASCADE_IMMEDIATE || fmd.getElement().getCascadeDetach() == ValueMetaData.CASCADE_IMMEDIATE) { cascade = true; } Object newVal = null; switch (fmd.getDeclaredTypeCode()) { case JavaTypes.ARRAY: if (_copy) newVal = _proxy.copyArray(curVal); else newVal = curVal; if (cascade) { detachArray(newVal, fmd); } return newVal; case JavaTypes.COLLECTION: if (_copy) { if (_detSM != null) { newVal = _proxy.newCollectionProxy(fmd.getProxyType(), fmd.getElement().getDeclaredType(), fmd.getInitializer() instanceof Comparator ? (Comparator) fmd.getInitializer() : null, sm.getBroker().getConfiguration(). getCompatibilityInstance().getAutoOff()); ((Collection) newVal).addAll((Collection) curVal); } else newVal = _proxy.copyCollection((Collection) curVal); } else newVal = curVal; if (cascade) { detachCollection((Collection) newVal, (Collection) curVal, fmd); } return reproxy(newVal, field); case JavaTypes.MAP: if (_copy) { if (_detSM != null) { newVal = _proxy.newMapProxy(fmd.getProxyType(), fmd.getKey().getDeclaredType(), fmd.getElement().getDeclaredType(), fmd.getInitializer() instanceof Comparator ? (Comparator) fmd.getInitializer() : null, sm.getBroker().getConfiguration(). getCompatibilityInstance().getAutoOff()); ((Map) newVal).putAll((Map) curVal); } else newVal = _proxy.copyMap((Map) curVal); } else newVal = curVal; if (cascade) { detachMap((Map) newVal, (Map) curVal, fmd); } return reproxy(newVal, field); case JavaTypes.CALENDAR: newVal = (_copy) ? _proxy.copyCalendar((Calendar) curVal) : curVal; return reproxy(newVal, field); case JavaTypes.DATE: newVal = (_copy) ? _proxy.copyDate((Date) curVal) : curVal; return reproxy(newVal, field); case JavaTypes.OBJECT: if (_copy) newVal = _proxy.copyCustom(curVal); return reproxy((newVal == null) ? curVal : newVal, field); case JavaTypes.PC: case JavaTypes.PC_UNTYPED: if (cascade) { return detachInternal(curVal); } return curVal; default: return curVal; } } /** * Make sure all the values in the given array are detached. */ private void detachArray(Object array, FieldMetaData fmd) { if (!fmd.getElement().isDeclaredTypePC()) return; int len = Array.getLength(array); for (int i = 0; i < len; i++) Array.set(array, i, detachInternal(Array.get(array, i))); } /** * Make sure all the values in the given collection are detached. */ private void detachCollection(Collection coll, Collection orig, FieldMetaData fmd) { // coll can be null if not copyable if (_copy && coll == null) throw new UserException(_loc.get("not-copyable", fmd)); if (!fmd.getElement().isDeclaredTypePC()) return; // unfortunately we have to clear the original and re-add to copy if (_copy) coll.clear(); Object detached; for (Iterator itr = orig.iterator(); itr.hasNext();) { detached = detachInternal(itr.next()); if (_copy) coll.add(detached); } } /** * Make sure all the values in the given map are detached. */ private void detachMap(Map map, Map orig, FieldMetaData fmd) { // map can be null if not copyable if (_copy && map == null) throw new UserException(_loc.get("not-copyable", fmd)); boolean keyPC = fmd.getKey().isDeclaredTypePC(); boolean valPC = fmd.getElement().isDeclaredTypePC(); if (!keyPC && !valPC) return; // if we have to copy keys, just clear and re-add; otherwise // we can use the entry set to reset the values only Map.Entry entry; if (!_copy || keyPC) { if (_copy) map.clear(); Object key, val; for (Iterator itr = orig.entrySet().iterator(); itr.hasNext();){ entry = (Map.Entry) itr.next(); key = entry.getKey(); if (keyPC) key = detachInternal(key); val = entry.getValue(); if (valPC) val = detachInternal(val); if (_copy) map.put(key, val); } } else { for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next (); entry.setValue (detachInternal (entry.getValue ())); } } } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNonTransState.java0000644000000000000000000001073212133327272027023 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; /** * Lifecycle state. * Represents a persistent instance that is not transactional, but that * allows access to persistent data. This state is reachable only if the * RetainState property is set. * * @author Abe White */ @SuppressWarnings("serial") class PNonTransState extends PCState { private static final Localizer _loc = Localizer.forPackage (PNonTransState.class); @Override void initialize(StateManagerImpl context, PCState previous) { if (previous == null) return; // If our previous state is clean, we don't need to do any sort of cleanup if (previous != PCLEAN) { // spec says all proxies to second class objects should be reset context.proxyFields(true, false); context.setDirty(false); } context.clearSavedFields(); } PCState delete(StateManagerImpl context) { context.preDelete(); if (!context.getBroker().isActive()) return PNONTRANSDELETED; return PDELETED; } PCState transactional(StateManagerImpl context) { // state is discarded when entering the transaction if (!context.getBroker().getOptimistic() || context.getBroker().getAutoClear() == AutoClear.CLEAR_ALL) context.clearFields(); return PCLEAN; } PCState release(StateManagerImpl context) { return TRANSIENT; } PCState evict(StateManagerImpl context) { return HOLLOW; } PCState beforeRead(StateManagerImpl context, int field) { // state is discarded when entering the transaction context.clearFields(); return PCLEAN; } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return beforeWrite(context, field, mutate, false); } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { if (context.getBroker().getAutoClear() == AutoClear.CLEAR_ALL) return beforeWrite(context, field, mutate, true); return PDIRTY; } private PCState beforeWrite(StateManagerImpl context, int field, boolean mutate, boolean optimistic) { // if this is a direct mutation on an SCO field, we can't clear our // fields because that would also null the SCO; depending on whether // the user was directly manipulating the field or was using a method, // that will result in either an NPE or having the SCO be detached // from its owning object, making the user's change have no affect if (mutate && !optimistic) { Log log = context.getBroker().getConfiguration().getLog (OpenJPAConfiguration.LOG_RUNTIME); if (log.isWarnEnabled()) { log.warn(_loc.get("pessimistic-mutate", context.getMetaData().getField(field), context.getManagedInstance())); } } else if (!mutate) { // state is stored for rollback and fields are reloaded if (context.getDirty().length() > 0) context.saveFields(true); context.clearFields(); context.load(null, context.LOAD_FGS, null, null, true); } return PDIRTY; } PCState beforeNontransactionalWrite(StateManagerImpl context, int field, boolean mutate) { return PNONTRANSDIRTY; } boolean isPersistent() { return true; } public String toString() { return "Persistent-Notransactional"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DistinctResultList.java0000644000000000000000000001307512133327272027757 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.apache.openjpa.lib.rop.ResultList; import org.apache.openjpa.util.RuntimeExceptionTranslator; /** * An immutable list that imposes uniqueness on its member. This implementation * traverses the entire result list on construction. So it is not suitable or * efficient for large results. All mutation operations (except clear()) throw * {@link UnsupportedOperationException}. * * @author Pinaki Poddar * @since 2.0.0 * * @param * element type */ public class DistinctResultList implements List, Serializable { private static final long serialVersionUID = -6140119764940777922L; private final ArrayList _del; private final RuntimeExceptionTranslator _trans; public DistinctResultList(ResultList list, RuntimeExceptionTranslator trans) { _del = new ArrayList(); _trans = trans; for (E e : list) { if (!_del.contains(e)) _del.add(e); } } public boolean add(E o) { throw new UnsupportedOperationException(); } public void add(int index, E element) { throw new UnsupportedOperationException(); } public boolean addAll(Collection c) { throw new UnsupportedOperationException(); } public boolean addAll(int index, Collection c) { throw new UnsupportedOperationException(); } public void clear() { try { _del.clear(); } catch (RuntimeException re) { throw translate(re); } } public boolean contains(Object o) { try { return _del.contains(o); } catch (RuntimeException re) { throw translate(re); } } public boolean containsAll(Collection c) { try { return _del.containsAll(c); } catch (RuntimeException re) { throw translate(re); } } public E get(int index) { try { return _del.get(index); } catch (RuntimeException re) { throw translate(re); } } public int indexOf(Object o) { try { return _del.indexOf(o); } catch (RuntimeException re) { throw translate(re); } } public boolean isEmpty() { try { return _del.isEmpty(); } catch (RuntimeException re) { throw translate(re); } } public Iterator iterator() { try { return _del.iterator(); } catch (RuntimeException re) { throw translate(re); } } public int lastIndexOf(Object o) { try { return _del.indexOf(o); } catch (RuntimeException re) { throw translate(re); } } public ListIterator listIterator() { try { return _del.listIterator(); } catch (RuntimeException re) { throw translate(re); } } public ListIterator listIterator(int index) { try { return _del.listIterator(index); } catch (RuntimeException re) { throw translate(re); } } public boolean remove(Object o) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } public boolean removeAll(Collection c) { throw new UnsupportedOperationException(); } public boolean retainAll(Collection c) { throw new UnsupportedOperationException(); } public E set(int index, E element) { throw new UnsupportedOperationException(); } public int size() { try { return _del.size(); } catch (RuntimeException re) { throw translate(re); } } public List subList(int fromIndex, int toIndex) { try { return _del.subList(fromIndex, toIndex); } catch (RuntimeException re) { throw translate(re); } } public Object[] toArray() { try { return _del.toArray(); } catch (RuntimeException re) { throw translate(re); } } public T[] toArray(T[] a) { try { return _del.toArray(a); } catch (RuntimeException re) { throw translate(re); } } protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public Object writeReplace() throws ObjectStreamException { return _del; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/TCleanState.java0000644000000000000000000000422312133327272026305 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a transient instance that is managed by a StateManager and * may be participating in the current transaction, but has not yet been * modified. * * @author Abe White */ @SuppressWarnings("serial") class TCleanState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { if (previous == null) return; // need to replace the second class objects with proxies that // listen for dirtying so we can track changes to these objects context.proxyFields(true, false); context.clearSavedFields(); context.setLoaded(true); context.setDirty(false); } PCState persist(StateManagerImpl context) { return (context.getBroker().isActive()) ? PNEW : PNONTRANSNEW; } PCState delete(StateManagerImpl context) { return error("transient", context); } PCState nontransactional(StateManagerImpl context) { return TRANSIENT; } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return TDIRTY; } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return TDIRTY; } public String toString() { return "Transient-Clean"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java0000644000000000000000000003775312133327272030451 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.lang.reflect.Field; import java.util.Collection; import java.util.Iterator; import java.util.Map; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.Reflection; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.event.LifecycleEvent; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.meta.ValueStrategies; import org.apache.openjpa.util.ApplicationIds; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.ObjectNotFoundException; import org.apache.openjpa.util.OptimisticException; /** * Handles attaching instances using version and primary key fields. * * @nojavadoc * @author Steve Kim */ class VersionAttachStrategy extends AttachStrategy implements DetachState { private static final Localizer _loc = Localizer.forPackage (VersionAttachStrategy.class); protected Object getDetachedObjectId(AttachManager manager, Object toAttach) { Broker broker = manager.getBroker(); ClassMetaData meta = broker.getConfiguration(). getMetaDataRepositoryInstance().getMetaData( ImplHelper.getManagedInstance(toAttach).getClass(), broker.getClassLoader(), true); return ApplicationIds.create(ImplHelper.toPersistenceCapable(toAttach, broker.getConfiguration()), meta); } protected void provideField(Object toAttach, StateManagerImpl sm, int field) { sm.provideField(ImplHelper.toPersistenceCapable(toAttach, sm.getContext().getConfiguration()), this, field); } public Object attach(AttachManager manager, Object toAttach, ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit) { BrokerImpl broker = manager.getBroker(); PersistenceCapable pc = ImplHelper.toPersistenceCapable(toAttach, meta.getRepository().getConfiguration()); boolean embedded = ownerMeta != null && ownerMeta.isEmbeddedPC(); boolean isNew = !broker.isDetached(pc); Object version = null; StateManagerImpl sm; // if the state manager for the embedded instance is null, then // it should be treated as a new instance (since the // newly persisted owner may create a new embedded instance // in the constructor); fixed bug #1075. // also, if the user has attached a detached obj from somewhere // else in the graph to an embedded field that was previously null, // copy into a new embedded instance if (embedded && (isNew || into == null || broker.getStateManager(into) == null)) { if (into == null) into = pc.pcNewInstance(null, false); sm = (StateManagerImpl) broker.embed(into, null, owner, ownerMeta); into = sm.getPersistenceCapable(); } else if (isNew) { Object oid = null; if (!isPrimaryKeysGenerated(meta)) oid = ApplicationIds.create(pc, meta); sm = persist(manager, pc, meta, oid, explicit); into = sm.getPersistenceCapable(); } else if (!embedded && into == null) { Object id = getDetachedObjectId(manager, toAttach); if (id != null) into = ImplHelper.toPersistenceCapable(broker.find(id, true, null), broker.getConfiguration()); if (into == null) throw new OptimisticException(_loc.get("attach-version-del", ImplHelper.getManagedInstance(pc).getClass(), id, version)) .setFailedObject(toAttach); sm = manager.assertManaged(into); if (meta.getDescribedType() != sm.getMetaData().getDescribedType()) { throw new ObjectNotFoundException(_loc.get ("attach-wrongclass", id, toAttach.getClass(), sm.getMetaData().getDescribedType())). setFailedObject(toAttach); } } else sm = manager.assertManaged(into); // mark that we attached the instance *before* we // fill in values to avoid endless recursion manager.setAttachedCopy(toAttach, into); // if persisting in place, just attach field values if (pc == into) { attachFieldsInPlace(manager, sm); return into; } if (isNew) { broker.fireLifecycleEvent(toAttach, null, meta, LifecycleEvent.BEFORE_PERSIST); } else { // invoke any preAttach on the detached instance manager.fireBeforeAttach(toAttach, meta); } // assign the detached pc the same state manager as the object we're // copying into during the attach process StateManager smBefore = pc.pcGetStateManager(); pc.pcReplaceStateManager(sm); int detach = (isNew) ? DETACH_ALL : broker.getDetachState(); FetchConfiguration fetch = broker.getFetchConfiguration(); try { FieldMetaData[] fmds = sm.getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) { switch (detach) { case DETACH_ALL: attachField(manager, toAttach, sm, fmds[i], true); break; case DETACH_FETCH_GROUPS: if (fetch.requiresFetch(fmds[i]) != FetchConfiguration.FETCH_NONE) attachField(manager, toAttach, sm, fmds[i], true); break; case DETACH_LOADED: attachField(manager, toAttach, sm, fmds[i], false); break; } } } finally { pc.pcReplaceStateManager(smBefore); } if (!embedded && !isNew) compareVersion(sm, pc); return ImplHelper.getManagedInstance(into); } /** * Make sure the version information is correct in the detached object. */ private void compareVersion(StateManagerImpl sm, PersistenceCapable pc) { Object version = pc.pcGetVersion(); // In the event that the version field is a primitive and it is the types default value, we can't differentiate // between a value that was set to be the default, and one that defaulted to that value. if (version != null && JavaTypes.isPrimitiveDefault(version, sm.getMetaData().getVersionField().getTypeCode())) { Field pcVersionInitField = null; try { pcVersionInitField = pc.getClass().getDeclaredField("pcVersionInit"); Object pcField = Reflection.get(pc, pcVersionInitField); if (pcField != null) { boolean bool = (Boolean) pcField; if (bool == false) { // If this field if false, that means that the pcGetVersion returned a default value rather than // and actual value. version = null; } } } catch (Exception e) { // Perhaps this is an Entity that was enhanced before the pcVersionInit field was added. } } if (version == null) { return; } // don't need to load unloaded fields since its implicitly // a single field value StoreManager store = sm.getBroker().getStoreManager(); switch (store.compareVersion(sm, version, sm.getVersion())) { case StoreManager.VERSION_LATER: // we have a later version: set it into the object. // lock validation will occur at commit time sm.setVersion(version); break; case StoreManager.VERSION_EARLIER: case StoreManager.VERSION_DIFFERENT: sm.setVersion(version); throw new OptimisticException(sm.getManagedInstance()); case StoreManager.VERSION_SAME: // no action required break; } } /** * Attach the fields of an in-place persisted instance. */ private void attachFieldsInPlace(AttachManager manager, StateManagerImpl sm) { FieldMetaData[] fmds = sm.getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].getManagement() != FieldMetaData.MANAGE_PERSISTENT) continue; Object cur, attached; switch (fmds[i].getDeclaredTypeCode()) { case JavaTypes.PC: case JavaTypes.PC_UNTYPED: cur = sm.fetchObjectField(i); attached = attachInPlace(manager, sm, fmds[i], cur); break; case JavaTypes.ARRAY: if (!fmds[i].getElement().isDeclaredTypePC()) continue; cur = sm.fetchObjectField(i); attached = attachInPlace(manager, sm, fmds[i], (Object[]) cur); break; case JavaTypes.COLLECTION: if (!fmds[i].getElement().isDeclaredTypePC()) continue; cur = sm.fetchObjectField(i); attached = attachInPlace(manager, sm, fmds[i], (Collection) cur); break; case JavaTypes.MAP: if (!fmds[i].getElement().isDeclaredTypePC() && !fmds[i].getKey().isDeclaredTypePC()) continue; cur = sm.fetchObjectField(i); attached = attachInPlace(manager, sm, fmds[i], (Map) cur); break; default: continue; } if (cur != attached) sm.settingObjectField(sm.getPersistenceCapable(), i, cur, attached, StateManager.SET_REMOTE); } } /** * Attach the given pc. */ private Object attachInPlace(AttachManager manager, StateManagerImpl sm, ValueMetaData vmd, Object pc) { if (pc == null) return null; Object attached = manager.getAttachedCopy(pc); if (attached != null) return attached; OpenJPAStateManager into = manager.getBroker().getStateManager(pc); PersistenceCapable intoPC = (into == null) ? null : into.getPersistenceCapable(); if (vmd.isEmbedded()) return manager.attach(pc, intoPC, sm, vmd, false); return manager.attach(pc, intoPC, null, null, false); } /** * Attach the given array. */ private Object[] attachInPlace(AttachManager manager, StateManagerImpl sm, FieldMetaData fmd, Object[] arr) { if (arr == null) return null; for (int i = 0; i < arr.length; i++) arr[i] = attachInPlace(manager, sm, fmd.getElement(), arr[i]); return arr; } /** * Attach the given collection. */ private Collection attachInPlace(AttachManager manager, StateManagerImpl sm, FieldMetaData fmd, Collection coll) { if (coll == null || coll.isEmpty()) return coll; // copy if elements embedded or contains detached, which will mean // we'll have to copy the existing elements Collection copy = null; if (fmd.getElement().isEmbedded()) copy = (Collection) sm.newFieldProxy(fmd.getIndex()); else { for (Iterator itr = coll.iterator(); itr.hasNext();) { if (manager.getBroker().isDetached(itr.next())) { copy = (Collection) sm.newFieldProxy(fmd.getIndex()); break; } } } Object attached; for (Iterator itr = coll.iterator(); itr.hasNext();) { attached = attachInPlace(manager, sm, fmd.getElement(), itr.next()); if (copy != null) copy.add(attached); } return (copy == null) ? coll : copy; } /** * Attach the given map. */ private Map attachInPlace(AttachManager manager, StateManagerImpl sm, FieldMetaData fmd, Map map) { if (map == null || map.isEmpty()) return map; Map copy = null; Map.Entry entry; boolean keyPC = fmd.getKey().isDeclaredTypePC(); boolean valPC = fmd.getElement().isDeclaredTypePC(); // copy if embedded pcs or detached pcs, which will require us to // copy elements if (fmd.getKey().isEmbeddedPC() || fmd.getElement().isEmbeddedPC()) copy = (Map) sm.newFieldProxy(fmd.getIndex()); else { for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); if ((keyPC && manager.getBroker().isDetached(entry.getKey())) || (valPC && manager.getBroker().isDetached (entry.getValue()))) { copy = (Map) sm.newFieldProxy(fmd.getIndex()); break; } } } Object key, val; for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); key = entry.getKey(); if (keyPC) key = attachInPlace(manager, sm, fmd.getKey(), key); val = entry.getValue(); if (valPC) val = attachInPlace(manager, sm, fmd.getElement(), val); if (copy != null) copy.put(key, val); } return (copy == null) ? map : copy; } /** * Find a PersistenceCapable instance of an Object if it exists in the * database. If the object is null or can't be found in the database. * * @param pc An object which will be attached into the current context. The * object may or may not correspond to a row in the database. * * @return If the object is null or can't be found in the database this * method returns null. Otherwise a PersistenceCapable representation of the * object is returned. */ protected PersistenceCapable findFromDatabase(AttachManager manager, Object pc) { Object oid = manager.getBroker().newObjectId(pc.getClass(), manager.getDetachedObjectId(pc)); if (oid != null) { return ImplHelper.toPersistenceCapable( manager.getBroker().find(oid, true, null), manager.getBroker().getConfiguration()); } else { return null; } } private boolean isPrimaryKeysGenerated(ClassMetaData meta) { FieldMetaData[] pks = meta.getPrimaryKeyFields(); for (int i = 0; i < pks.length; i++) { if (pks[i].getValueStrategy() != ValueStrategies.NONE) return true; } return false; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNewFlushedDeletedFlushedState.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNewFlushedDeletedFlushedS0000644000000000000000000000261212133327272030327 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an instance that was made persistent within the * current transaction, flushed, deleted, and flushed. * * @author Patrick Linskey */ @SuppressWarnings("serial") class PNewFlushedDeletedFlushedState extends PNewFlushedDeletedState { @Override void initialize(StateManagerImpl context, PCState previous) { } PCState persist(StateManagerImpl context) { context.eraseFlush(); return PNEW; } public String toString() { return "Persistent-New-Flushed-Deleted-Flushed"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/OpenJPAStateManager.java0000644000000000000000000004140112133327272027665 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import org.apache.openjpa.enhance.FieldManager; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.Proxy; /** * Interface implemented by OpenJPA state managers. Each state manager * manages the state of a single persistence capable instance. The * state manager is also responsible for all communications about the * instance to the {@link StoreManager}. * The fetchXXXField and storeXXXField * methods can be used to get and set fields of the managed persistent object. * Most back-end code, however, should use the similar * fetchXXX and storeXXX methods in place of * the field methods. These methods function just like the field methods, but * also pass the value through the externalizer and factory the field may have. * * @author Abe White */ public interface OpenJPAStateManager extends StateManager, FieldManager { /** * A user is setting the field. */ public static final int SET_USER = 0; /** * The remote broker framework is setting the field on the server. */ public static final int SET_REMOTE = 1; /** * The field is being attached by a detached state manager; the value is * from the detached instance. */ public static final int SET_ATTACH = 2; /** * Initialize the state manager with a new instance of the given * persistence capable type and the proper lifecycle state. * Invoking this method may change the object id and metadata for the * state manager, as the concrete type specified in the parameter may be * a subclass of the expected type. * * @param forType the type for which to create a new instance * @param state the initial state to which to set the instance * @since 0.3.1.2 */ public void initialize(Class forType, PCState state); /** * Load fetch group fields. */ public void load(FetchConfiguration fetch); /** * Return the managed instance. */ public Object getManagedInstance(); /** * Return the {@link PersistenceCapable} instance that provides access to * the instance managed by this state manager. May be a proxy around * the actual managed instance. */ public PersistenceCapable getPersistenceCapable(); /** * Get the metadata for this instance. */ public ClassMetaData getMetaData(); /** * Return the owning state if this is an embedded instance. */ public OpenJPAStateManager getOwner(); /** * Return the owning value's field index * * @since 1.1.0 */ public int getOwnerIndex(); /** * Return true if this instance has an owner, meaning it is an embedded * value. */ public boolean isEmbedded(); /** * Return whether this object has been flushed to the datastore in this * transaction. */ public boolean isFlushed(); /** * Return whether this object has been flushed, then dirtied again. */ public boolean isFlushedDirty(); /** * Return whether this object is provisionally persistent. */ public boolean isProvisional(); /** * Return a read-only mask of the indexes of all loaded fields. */ public BitSet getLoaded(); /** * Return a read-only mask of the indexes of all dirty fields. */ public BitSet getDirty(); /** * Return a read-only mask of the indexes of all fields that have been * flushed since they were last changed. */ public BitSet getFlushed(); /** * Return a mutable mask of the unloaded fields that need loading based * on the given fetch configuration. Pass in null to retrieve all * unloaded fields. */ public BitSet getUnloaded(FetchConfiguration fetch); /** * Create a new hollow proxy instance for the given field. In cases where * the field externalizes to an SCO but is declared something else, the * returned object may not implement {@link Proxy}. In all other cases, * this method delegates to the system * {@link org.apache.openjpa.util.ProxyManager} * with the correct field information. The returned proxy's owner is * unset so that modifications to the proxy will not be tracked while its * state is initialized. Calling {@link #storeField} or {@link #store} * will set the proxy's owner automatically. */ public Object newProxy(int field); /** * Create a new hollow proxy instance for the given field. This method * differs from {@link #newProxy} in that it returns a proxy for the * field's declared type, not its externalized type. * * @see #newProxy */ public Object newFieldProxy(int field); /** * Return true if the given field has a default value. */ public boolean isDefaultValue(int field); /** * Return the managing context. */ public StoreContext getContext(); /** * Return the state that this object is in. */ public PCState getPCState(); /** * Return the identifier for this state manager. This may return a * temporary identifier for new unflushed instances that have not been * assigned an object id, or for non-persistent or embedded instances. * For all other instances this method is the same as {@link #getObjectId}. */ public Object getId(); /** * Return the instance's object id. This method will return null if no * oid has been assigned. Oids are assigned to newly-persisted instances * when the user first asks for it, or on flush. */ public Object getObjectId(); /** * Set the object id for the managed instance. Some back ends may not be * able to assign a permanent oid until flush. Do not call this method on * application identity instances; changing the primary key fields of * application identity objects through the storeXXXField * methods will automatically change the oid. */ public void setObjectId(Object oid); /** * Ask the store manager to assign a permanent oid to this new instance. * * @param flush if true, flush if necessary to get a permanent oid; if * false, the oid may be left unassigned * @return true if an oid assigned, false otherwise */ public boolean assignObjectId(boolean flush); /** * The lock object set for this instance. This object is generally * managed by the system lock manager. */ public Object getLock(); /** * The lock object set for this instance. This object is generally * managed by the system lock manager. */ public void setLock(Object lock); /** * Return the current version indicator for this instance. */ public Object getVersion(); /** * Set the version indicator for this instance, as loaded from the * data store. This method is used by the {@link StoreManager} when * loading instance data. On rollback, the version will be rolled back * to this value. Version objects should be serializable and should not * require vendor-specific classes, because they are transferred to * detached objects. */ public void setVersion(Object version); /** * Set the next version indicator in the datastore pending a successful * flush. The {@link StoreManager} uses this method during flush. */ public void setNextVersion(Object version); /** * Returns true if this state needs to issue a version update, possibly * as a result of being locked. */ public boolean isVersionUpdateRequired(); /** * Returns true if this state needs to issue a version check at flush time. */ public boolean isVersionCheckRequired(); /** * An object that concrete back ends can associate with each instance. * This object is not used or modified in any way by the generic * persistence layer. */ public Object getImplData(); /** * An object that concrete back ends can associate with each instance. * This object is not used or modified in any way by the generic * persistence layer. * * @param cacheable whether the impl data can be shared among instances * in different contexts if L2 caching is enabled * @return the previous impl data value, if any */ public Object setImplData(Object data, boolean cacheable); /** * Whether the instance-level impl data can be shared among instances * in different contexts if L2 caching is enabled. */ public boolean isImplDataCacheable(); /** * Field-level impl data. Field-level data only applies to loaded fields, * and is cleared when the field is cleared. */ public Object getImplData(int field); /** * Field-level impl data. Field-level data only applies to loaded fields, * and is cleared when the field is cleared. Whether the data is cached * across instances depends on the corresponding field metadata's response * to {@link FieldMetaData#usesImplData}. * * @return the previous impl data value, if any */ public Object setImplData(int field, Object data); /** * Whether the field's impl data is loaded and can be shared among * instances in different contexts if L2 caching is enabled. */ public boolean isImplDataCacheable(int field); /** * Use intermediate field data to store intermediate information that * might be available before the field is fully loaded. The system * will automatically clear this data when the field gets loaded. * This data should be cacheable; the datastore cache will attempt to * cache it if the field value is not available. */ public Object getIntermediate(int field); /** * Use intermediate field data to store intermediate information that * might be available before the field is fully loaded. The system * will automatically clear this data when the field gets loaded. * This data should be cacheable; the datastore cache will attempt to * cache it if the field value is not available. */ public void setIntermediate(int field, Object value); /** * Return the external value of the given field. */ public boolean fetchBoolean(int field); /** * Return the external value of the given field. */ public byte fetchByte(int field); /** * Return the external value of the given field. */ public char fetchChar(int field); /** * Return the external value of the given field. */ public double fetchDouble(int field); /** * Return the external value of the given field. */ public float fetchFloat(int field); /** * Return the external value of the given field. */ public int fetchInt(int field); /** * Return the external value of the given field. */ public long fetchLong(int field); /** * Return the external value of the given field. */ public Object fetchObject(int field); /** * Return the external value of the given field. */ public short fetchShort(int field); /** * Return the external value of the given field. */ public String fetchString(int field); /** * Return the externalized value of the field with the given index as an * object. If there is no externalizer, this is equivalent to * {@link #fetchField}. */ public Object fetch(int field); /** * Return the value of the field with the given index as an object. * * @param transitions if true, this method will cause state transitions * to occur as if the field were accessed normally */ public Object fetchField(int field, boolean transitions); /** * Return the value of the field at the specified index as of the * beginning of the transaction. * * @since 0.3.1.1 */ public Object fetchInitialField(int field); /** * Set the given external value back into the given field. */ public void storeBoolean(int field, boolean externalVal); /** * Set the given external value back into the given field. */ public void storeByte(int field, byte externalVal); /** * Set the given external value back into the given field. */ public void storeChar(int field, char externalVal); /** * Set the given external value back into the given field. */ public void storeDouble(int field, double externalVal); /** * Set the given external value back into the given field. */ public void storeFloat(int field, float externalVal); /** * Set the given external value back into the given field. */ public void storeInt(int field, int externalVal); /** * Set the given external value back into the given field. */ public void storeLong(int field, long externalVal); /** * Set the given external value back into the given field. */ public void storeObject(int field, Object externalVal); /** * Set the given external value back into the given field. */ public void storeShort(int field, short externalVal); /** * Set the given external value back into the given field. */ public void storeString(int field, String externalVal); /** * Set the value of the field with the given index as from the external * object value. If there is no externalizer, this is equivalent to * {@link #storeField}. */ public void store(int field, Object value); /** * Set the value of the field with the given index as an object. */ public void storeField(int field, Object value); /** * Mark the given field as dirty. */ public void dirty(int field); /** * Notification that an element has been removed from the given field. */ public void removed(int field, Object removed, boolean key); /** * Prepare the instance for refresh * * @param refreshAll true if this instance is one of a collection of * objects being refreshed * @return true if the object needs a refresh, false otherwise * @see Broker#refresh */ public boolean beforeRefresh(boolean refreshAll); /** * Set the given field to the given value. Make the field dirty as * if user code set it. Do not delete dependent objects in the field's * current value. This method is invoked by the remote package to * synch a server-side state manager with remote changes. We do not * need to delete dependent instances because they will have been * deleted when the field changed on the client side, and those * client-side deletes will be transmitted independently. * * @since 0.3.1 */ public void setRemote (int field, Object value); /** * Some field types (collection proxies) support delayed loading. Delayed loading * is a step beyond lazy loading. Delayed load allows an instance of a field to be * returned without actually loading it. * * @param field * @return true if the field is setup for delayed access */ public boolean isDelayed(int field); /** * Some field types (collection proxies) support delayed loading. Delayed loading * is a step beyond lazy loading. Delayed load allows an instance of a field to be * returned without actually loading it. * * @param field */ public void setDelayed(int field, boolean delay); /** * If a field was marked delayed in a previous load operation this method can be * used to load the field. * @param field */ public void loadDelayedField(int field); /** * Fetch an object field by index. * @param field */ public Object fetchObjectField(int field); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FinalizingBrokerImpl.java0000644000000000000000000000255612133327272030226 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Subtype of {@link BrokerImpl} that automatically closes itself during * finalization. This implementation guards against potential resource leaks, * but also incurs a scalability bottleneck as instances are enlisted in the * finalization queue and subsequently cleaned up. * * @since 0.9.7 */ public class FinalizingBrokerImpl extends BrokerImpl { /** * Close on finalize. */ protected void finalize() throws Throwable { super.finalize(); if (!isClosed()) free(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PreparedQueryCache.java0000644000000000000000000002042412133327272027653 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.util.List; import java.util.Map; import org.apache.openjpa.lib.conf.Configurable; /** * A cache to create and maintain {@link PreparedQuery prepared queries}. * * To cache a PreparedQuery is two-stage process. In the first stage, * {@link #register(String, Query, FetchConfiguration)} register} * an identification key and a compiled Query Q to create a * hollow PreparedQuery instance P in the cache. In the second stage, after Q * executes, {@link #initialize(String, Object)} initialize} the hollow * Prepared Query P from the result of execution such as the target * database query PQ and its parameters. After initialization, P can * be used with re-parameterization for subsequent execution of the original * Query Q. * * The target database query PQ associated to a cached prepared query P * may depend upon query execution context such as fetch plan or * lock group. This cache, by design, does not monitor the context or * automatically invalidate an entry P when the original query Q is executed * with context parameters that affect the target query PQ. * * The user must notify this receiver to invalidate a cached entry P when * execution context changes in a way that will modify the resultant database * language query PQ. * * One of the built-in mechanism (available in JPA facade) is to set query hints * to either invalidate the query entirely or ignore the cached version for the * current execution. * * @see QueryHints#HINT_IGNORE_PREPARED_QUERY * @see QueryHints#HINT_INVALIDATE_PREPARED_QUERY * * This cache allows customization of whether a query can be cached or not * via either explicit marking of certain keys as non-cachable (which is * irreversible or strong) or addition/removal of exclusion patterns * (which is reversible or weak). * * @see #markUncachable(String) * @see #addExclusionPattern(String) * @see #setExcludes(String) * @see #removeExclusionPattern(String) * * @author Pinaki Poddar * * @since 2.0.0 */ public interface PreparedQueryCache extends Configurable { /** * Register the given query for caching against the given key if it has not * already been cached. If the query can not be cached, then mark it as such * to avoid computing for the same key again. * * @return TRUE the query is registered in the cache by this call * null if the query is already registered in the cache * FALSE if can not be registered in the cache, either because * it is known not to be cacheable from a previous attempt or * a hint is given to ignore the cached version. */ public Boolean register(String key, Query query, FetchConfiguration hints); /** * Initialize the cached Prepared Query registered with the given * key earlier by the given execution result. If it is not possible to * initialize the Prepared Query from the given execution result, then * the corresponding key will be marked as invalid for caching. * * @param key the key used during registration * @param executionResult an opaque instance carrying the execution result * of the original query. * * @return the initialized Prepared Query. If it is not possible to * initialize the cached, possibly hollow Prepared Query from the given * result, return null. */ public PreparedQuery initialize(String key, Object executionResult); /** * Get a map view of the cached queries indexed by identifier. */ public Map getMapView(); /** * Cache the given PreparedQuery. * The key is the identifier of the given PreparedQuery itself. * The query must not be cached if either the key matches any exclusion * pattern or the key has been marked non-cachable. * * @return true if the given query is cached. false if it can not be cached * due to exclusion. * * @see #markUncachable(String) * @see #setExcludes(String) * @see #addExclusionPattern(String) */ public boolean cache(PreparedQuery q); /** * Remove the PreparedQuery with the given identifier from this cache. */ public boolean invalidate(String id); /** * Get the PreparedQuery with the given identifier if it exists. null * otherwise. */ public PreparedQuery get(String id); /** * Affirms if a PreparedQuery can be cached against the given key. * * @return Boolean.FALSE if the given key is explicitly marked before as not * be cached or matches any of the exclusion patterns. * Boolean.TRUE if the given key currently exists in the cache. * Otherwise, return null implying this receiver can not determine whether * this key can be cached on not. * */ public Boolean isCachable(String id); /** * Marks the given key as not amenable to caching. * Explicit marking helps to avoid repeated computational cost of * determining whether a query can be cached or not. * * @param id is the key to be excluded * @param exclusion directs whether exclusion is irreversible or not. * * @return The value for the given key if it had been cached before. null * otherwise. */ public PreparedQuery markUncachable(String id, Exclusion exclusion); /** * Returns the exclusion status of if the given query key. * * @return null implies that the key is not excluded. */ public Exclusion isExcluded(String id); /** * Gets the exclusion patterns. */ public List getExcludes(); /** * Sets one or more exclusion regular expression patterns separated by * semicolon. Any existing cache entry whose key matches any of the given * pattern will be marked non-cachable in a reversible manner. */ public void setExcludes(String excludes); /** * Adds the given pattern to the list of excluded patterns. Any existing * cache entry whose key matches the given pattern will be marked * non-cachable in a reversible manner. */ public void addExclusionPattern(String pattern); /** * Removes the given pattern from the list of excluded patterns. * Any excluded key that matches the given pattern can now be cached * again, unless it has been marked non-cachable explicitly. * * @see #markUncachable(String, Exclusion) */ public void removeExclusionPattern(String pattern); /** * Clears all cached queries. */ public void clear(); /** * Enable/disable gathering of statistics. * */ public void setEnableStatistics(boolean enable); /** * Affirm if statistics is gathered. * */ public boolean getEnableStatistics(); /** * Gets the simple statistics for executed queries. * If the statistics gathering is disabled, an empty statistics is returned. */ public QueryStatistics getStatistics(); /** * A structure to describe the strength and reason for excluding a query from the cache. * */ public static interface Exclusion { /** * Affirms if this exclusion is strong i.e. can never be reversed. */ public boolean isStrong(); /** * Gets the human-readable reason for excluding this query from being cached. */ public String getReason(); /** * The pattern (either the exact query string or a regular expression) that * denotes this exclusion. */ public String getPattern(); /** * Affirms if this exclusion matches the given identifier. */ boolean matches(String id); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfigurati0000644000000000000000000003554412133327272030440 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Collection; import java.util.Map; import java.util.Set; import org.apache.openjpa.lib.rop.ResultList; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.util.RuntimeExceptionTranslator; /////////////////////////////////////////////////////////////// // NOTE: when adding a public API method, be sure to add it to // JDO and JPA facades! /////////////////////////////////////////////////////////////// /** * Delegating fetch configuration that can also perform exception * translation for use in facades. * * @author Abe White * @nojavadoc */ public class DelegatingFetchConfiguration implements FetchConfiguration { private final FetchConfiguration _fetch; private final DelegatingFetchConfiguration _del; private final RuntimeExceptionTranslator _trans; /** * Constructor; supply delegate. */ public DelegatingFetchConfiguration(FetchConfiguration fetch) { this(fetch, null); } /** * Constructor; supply delegate and exception translator. */ public DelegatingFetchConfiguration(FetchConfiguration fetch, RuntimeExceptionTranslator trans) { _fetch = fetch; if (fetch instanceof DelegatingFetchConfiguration) _del = (DelegatingFetchConfiguration) fetch; else _del = null; _trans = trans; } /** * Return the direct delegate. */ public FetchConfiguration getDelegate() { return _fetch; } /** * Return the native delegate. */ public FetchConfiguration getInnermostDelegate() { return (_del == null) ? _fetch : _del.getInnermostDelegate(); } public int hashCode() { return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingFetchConfiguration) other = ((DelegatingFetchConfiguration) other). getInnermostDelegate(); return getInnermostDelegate().equals(other); } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public StoreContext getContext() { try { return _fetch.getContext(); } catch (RuntimeException re) { throw translate(re); } } public void setContext(StoreContext ctx) { try { _fetch.setContext(ctx); } catch (RuntimeException re) { throw translate(re); } } public int getFetchBatchSize() { try { return _fetch.getFetchBatchSize(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setFetchBatchSize(int fetchBatchSize) { try { _fetch.setFetchBatchSize(fetchBatchSize); return this; } catch (RuntimeException re) { throw translate(re); } } public int getMaxFetchDepth() { try { return _fetch.getMaxFetchDepth(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setMaxFetchDepth(int depth) { try { _fetch.setMaxFetchDepth(depth); return this; } catch (RuntimeException re) { throw translate(re); } } public Set getRootInstances() { try { return _fetch.getRootInstances(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setRootInstances(Collection roots) { try { _fetch.setRootInstances(roots); return this; } catch (RuntimeException re) { throw translate(re); } } public Set getRootClasses() { try { return _fetch.getRootClasses(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setRootClasses(Collection roots) { try { _fetch.setRootClasses(roots); return this; } catch (RuntimeException re) { throw translate(re); } } public boolean getQueryCacheEnabled() { try { return _fetch.getQueryCacheEnabled(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setQueryCacheEnabled(boolean cache) { try { _fetch.setQueryCacheEnabled(cache); return this; } catch (RuntimeException re) { throw translate(re); } } public int getFlushBeforeQueries() { try { return _fetch.getFlushBeforeQueries(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setFlushBeforeQueries(int flush) { try { _fetch.setFlushBeforeQueries(flush); return this; } catch (RuntimeException re) { throw translate(re); } } public boolean getExtendedPathLookup() { try { return _fetch.getExtendedPathLookup(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setExtendedPathLookup(boolean flag) { try { _fetch.setExtendedPathLookup(flag); return this; } catch (RuntimeException re) { throw translate(re); } } public Set getFetchGroups() { try { return _fetch.getFetchGroups(); } catch (RuntimeException re) { throw translate(re); } } public boolean hasFetchGroup(String group) { try { return _fetch.hasFetchGroup(group); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration addFetchGroup(String group) { try { _fetch.addFetchGroup(group); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration addFetchGroups(Collection groups) { try { _fetch.addFetchGroups(groups); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration removeFetchGroup(String group) { try { _fetch.removeFetchGroup(group); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration removeFetchGroups(Collection groups) { try { _fetch.removeFetchGroups(groups); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration clearFetchGroups() { try { _fetch.clearFetchGroups(); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration resetFetchGroups() { try { _fetch.resetFetchGroups(); return this; } catch (RuntimeException re) { throw translate(re); } } public Set getFields() { try { return _fetch.getFields(); } catch (RuntimeException re) { throw translate(re); } } public boolean hasField(String field) { try { return _fetch.hasField(field); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration addField(String field) { try { _fetch.addField(field); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration addFields(Collection fields) { try { _fetch.addFields(fields); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration removeField(String field) { try { _fetch.removeField(field); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration removeFields(Collection fields) { try { _fetch.removeFields(fields); return this; } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration clearFields() { try { _fetch.clearFields(); return this; } catch (RuntimeException re) { throw translate(re); } } public int getLockTimeout() { try { return _fetch.getLockTimeout(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setLockTimeout(int timeout) { try { _fetch.setLockTimeout(timeout); return this; } catch (RuntimeException re) { throw translate(re); } } public int getQueryTimeout() { try { return _fetch.getQueryTimeout(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setQueryTimeout(int timeout) { try { _fetch.setQueryTimeout(timeout); return this; } catch (RuntimeException re) { throw translate(re); } } public int getLockScope() { try { return _fetch.getLockScope(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setLockScope(int scope) { try { _fetch.setLockScope(scope); return this; } catch (RuntimeException re) { throw translate(re); } } public int getReadLockLevel() { try { return _fetch.getReadLockLevel(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setReadLockLevel(int level) { try { _fetch.setReadLockLevel(level); return this; } catch (RuntimeException re) { throw translate(re); } } public int getWriteLockLevel() { try { return _fetch.getWriteLockLevel(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration setWriteLockLevel(int level) { try { _fetch.setWriteLockLevel(level); return this; } catch (RuntimeException re) { throw translate(re); } } public ResultList newResultList(ResultObjectProvider rop) { try { return _fetch.newResultList(rop); } catch (RuntimeException re) { throw translate(re); } } public void copy(FetchConfiguration fetch) { try { _fetch.copy(fetch); } catch (RuntimeException re) { throw translate(re); } } public Object clone() { try { return _fetch.clone(); } catch (RuntimeException re) { throw translate(re); } } public void setHint(String name, Object value) { try { _fetch.setHint(name, value); } catch (RuntimeException re) { throw translate(re); } } public void setHint(String name, Object value, Object original) { try { _fetch.setHint(name, value, original); } catch (RuntimeException re) { throw translate(re); } } public boolean isHintSet(String key) { try { return _fetch.isHintSet(key); } catch (RuntimeException re) { throw translate(re); } } public Object getHint(String name) { try { return _fetch.getHint(name); } catch (RuntimeException re) { throw translate(re); } } public Map getHints() { try { return _fetch.getHints(); } catch (RuntimeException re) { throw translate(re); } } public int requiresFetch(FieldMetaData fmd) { try { return _fetch.requiresFetch(fmd); } catch (RuntimeException re) { throw translate(re); } } public boolean requiresLoad() { try { return _fetch.requiresLoad(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration traverse(FieldMetaData fmd) { try { return _fetch.traverse(fmd); } catch (RuntimeException re) { throw translate(re); } } public void lock() { try { _fetch.lock(); } catch (RuntimeException re) { throw translate(re); } } public void unlock() { try { _fetch.unlock(); } catch (RuntimeException re) { throw translate(re); } } public DataCacheRetrieveMode getCacheRetrieveMode() { try { return _fetch.getCacheRetrieveMode(); } catch (RuntimeException re) { throw translate(re); } } public DataCacheStoreMode getCacheStoreMode() { try { return _fetch.getCacheStoreMode(); } catch (RuntimeException re) { throw translate(re); } } public void setCacheRetrieveMode(DataCacheRetrieveMode mode) { try { _fetch.setCacheRetrieveMode(mode); } catch (RuntimeException re) { throw translate(re); } } public void setCacheStoreMode(DataCacheStoreMode mode) { try { _fetch.setCacheStoreMode(mode); } catch (RuntimeException re) { throw translate(re); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Audited.java0000644000000000000000000000533012133327272025515 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import org.apache.openjpa.audit.AuditableOperation; import org.apache.openjpa.enhance.PersistenceCapable; /** * Carries immutable information about an audited persistent instance. * * @author Pinaki Poddar * */ public final class Audited { private final StateManagerImpl _sm; private final PersistenceCapable _original; /** * Supply a state manager and a transient copy. * @param sm a state manager, must not be null. * @param o the transient copy */ Audited(StateManagerImpl sm, PersistenceCapable o) { if (sm == null || o == null) throw new NullPointerException("sm: " + sm + " original: " + o); if (o.pcGetStateManager() != null) throw new IllegalArgumentException(o + " is not transient"); _sm = sm; _original = o; } /** * Gets the current state of the persistent instance. */ public Object getManagedObject() { return _sm.getManagedInstance(); } /** * Gets the original state of the persistent instance as a transient instance. */ public Object getOriginalObject() { return _original; } /** * Gets the name of the updated fields. * * @return persistent property names that are modified. * For deleted instances the array is empty and for newly created instances * the array contains all the fields. */ public String[] getUpdatedFields() { BitSet dirty = _sm.getDirty(); String[] names = new String[dirty.cardinality()]; int j = 0; for (int i = 0; i < dirty.size(); i++) { if (dirty.get(i)) { names[j++] = _sm.getMetaData().getField(i).getName(); } } return names; } /** * Gets the type of this audit. */ public AuditableOperation getType() { PCState state = _sm.getPCState(); if (state.isNew()) return AuditableOperation.CREATE; if (state.isDeleted()) return AuditableOperation.DELETE; if (state.isDirty()) return AuditableOperation.UPDATE; return null; // should not happen } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AutoDetach.java0000644000000000000000000000353512133327272026164 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Bit flags for when to automatically detach the entire persistence context. */ public interface AutoDetach { /** * Detach context on close. */ public static final int DETACH_CLOSE = 2 << 0; /** * Detach context on transaction commit. */ public static final int DETACH_COMMIT = 2 << 1; /** * Detach context on any nontransctional read, such that each * nontransactional operation uses a new persistence context in essence. */ public static final int DETACH_NONTXREAD = 2 << 2; /** * Detach context on failed transaction commit / rollback. */ public static final int DETACH_ROLLBACK = 2 << 3; /** * Do not detach at all. Skips proxying second-class containers. */ public static final int DETACH_NONE = 2 << 4; public static final String[] names = {"CLOSE", "COMMIT", "NONTXREAD", "ROLLBACK", "NONE"}; public static final int[] values = {DETACH_CLOSE, DETACH_COMMIT, DETACH_NONTXREAD, DETACH_ROLLBACK, DETACH_NONE}; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCDataImpl.java0000644000000000000000000002504212133327272026056 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import java.util.Map; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; /** * Default {@link PCData} implementation. * * @author Patrick Linskey * @author Abe White * @nojavadoc */ public class PCDataImpl extends AbstractPCData { private final Object _oid; private final Class _type; private final String _cache; private final Object[] _data; private final BitSet _loaded; private Object _version = null; private Object _impl = null; private Object[] _fieldImpl = null; public PCDataImpl(Object oid, ClassMetaData meta) { this(oid, meta, DataCache.NAME_DEFAULT); } /** * Constructor. */ public PCDataImpl(Object oid, ClassMetaData meta, String name) { _oid = oid; _type = meta.getDescribedType(); _cache = name; int len = meta.getFields().length; _data = new Object[len]; _loaded = new BitSet(len); } public Object getId() { return _oid; } public Class getType() { return _type; } public BitSet getLoaded() { return _loaded; } public Object getData(int index) { // make sure index is actually loaded to avoid returning an // intermediate value return (_loaded.get(index)) ? _data[index] : null; } public void setData(int index, Object val) { _loaded.set(index); _data[index] = val; } public void clearData(int index) { _loaded.clear(index); _data[index] = null; } public Object getImplData() { return _impl; } public void setImplData(Object val) { _impl = val; } public Object getImplData(int index) { return (_fieldImpl != null) ? _fieldImpl[index] : null; } public void setImplData(int index, Object val) { if (val != null) { if (_fieldImpl == null) _fieldImpl = new Object[_data.length]; _fieldImpl[index] = val; } else if (_fieldImpl != null) _fieldImpl[index] = null; } public Object getIntermediate(int index) { return (!_loaded.get(index)) ? _data[index] : null; } public void setIntermediate(int index, Object val) { _loaded.clear(index); _data[index] = val; } public boolean isLoaded(int index) { return _loaded.get(index); } public void setLoaded(int index, boolean loaded) { if (loaded) _loaded.set(index); else _loaded.clear(index); } public Object getVersion() { return _version; } public void setVersion(Object version) { _version = version; } public void load(OpenJPAStateManager sm, FetchConfiguration fetch, Object context) { loadVersion(sm); loadImplData(sm); FieldMetaData[] fmds = sm.getMetaData().getFields(); ((StateManagerImpl)sm).setLoading(true); for (int i = 0; i < fmds.length; i++) { // load intermediate data for all unloaded fields and data for // fields in configured fetch groups if (!isLoaded(i)) loadIntermediate(sm, fmds[i]); else if (!sm.getLoaded().get(i) && fetch.requiresFetch(fmds[i]) != FetchConfiguration.FETCH_NONE) loadField(sm, fmds[i], fetch, context); } } public void load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch, Object context) { loadVersion(sm); loadImplData(sm); // attempt to load given fields int len = (fields == null) ? 0 : fields.length(); FieldMetaData fmd; for (int i = 0; i < len; i++) { if (!fields.get(i)) continue; fmd = sm.getMetaData().getField(i); boolean loading = false; if(sm.getContext() != null && sm.getContext() instanceof BrokerImpl) { loading = ((BrokerImpl) sm.getContext()).isLoading(sm.getObjectId()); } if (!isLoaded(i) || loading) { // prevent reentrant calls. loadIntermediate(sm, fmd); } else { loadField(sm, fmd, fetch, context); loadImplData(sm, fmd); fields.clear(i); } } } /** * Set version information into the given state manager. */ protected void loadVersion(OpenJPAStateManager sm) { if (sm.getVersion() == null) sm.setVersion(getVersion()); } /** * Set impl data information into the given state manager. */ protected void loadImplData(OpenJPAStateManager sm) { Object impl = getImplData(); if (sm.getImplData() == null && impl != null) sm.setImplData(impl, true); } /** * Set field-level information into the given state manager. */ protected void loadField(OpenJPAStateManager sm, FieldMetaData fmd, FetchConfiguration fetch, Object context) { int index = fmd.getIndex(); Object val = toField(sm, fmd, getData(index), fetch, context); // If val is null, make sure that we don't send back a null Embeddable or ElementCollection...perhaps others? // Probably should think about trying to shove this data back into the cache at this point so we don't // continually run through this code. if (val == null && fmd.isEmbeddedPC()) { val = sm.getContext().embed(null, null, sm, fmd).getManagedInstance(); } else if (val == null && fmd.isElementCollection()) { val = sm.newProxy(index); } sm.storeField(index, val); } /** * Set field-level impl data into the given state manager. */ protected void loadImplData(OpenJPAStateManager sm, FieldMetaData fmd) { int index = fmd.getIndex(); Object impl = getImplData(index); if (impl != null) sm.setImplData(index, impl); } /** * Set intermediate information for the given field into the state manager. */ protected void loadIntermediate(OpenJPAStateManager sm, FieldMetaData fmd) { int index = fmd.getIndex(); Object inter = getIntermediate(index); if (inter != null && !sm.getLoaded().get(index)) sm.setIntermediate(index, inter); } public void store(OpenJPAStateManager sm) { storeVersion(sm); storeImplData(sm); FieldMetaData[] fmds = sm.getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) { if (sm.getLoaded().get(i)) { storeField(sm, fmds[i]); storeImplData(sm, fmds[i], isLoaded(i)); } else if (!isLoaded(i)) storeIntermediate(sm, fmds[i]); } } public void store(OpenJPAStateManager sm, BitSet fields) { storeVersion(sm); storeImplData(sm); FieldMetaData[] fmds = sm.getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) { if (fields != null && fields.get(i)) { storeField(sm, fmds[i]); storeImplData(sm, fmds[i], isLoaded(i)); } else if (!isLoaded(i)) storeIntermediate(sm, fmds[i]); } } /** * Store version information from the given state manager. */ protected void storeVersion(OpenJPAStateManager sm) { setVersion(sm.getVersion()); } /** * Store impl data from the given state manager. */ protected void storeImplData(OpenJPAStateManager sm) { if (sm.isImplDataCacheable()) setImplData(sm.getImplData()); } /** * Store field-level information from the given state manager. */ protected void storeField(OpenJPAStateManager sm, FieldMetaData fmd) { if (fmd.getManagement() != fmd.MANAGE_PERSISTENT) return; int index = fmd.getIndex(); OpenJPAStateManager dsm = null; if (sm.getPersistenceCapable().pcIsDetached()) { dsm = (DetachedStateManager) sm.getPersistenceCapable(). pcGetStateManager(); sm.getPersistenceCapable().pcReplaceStateManager(sm); } Object val = toData(fmd, sm.fetchField(index, false), sm.getContext()); if (dsm != null) sm.getPersistenceCapable().pcReplaceStateManager(dsm); if (val != NULL) setData(index, val); else // unable to store field value; clear out any old values clearData(index); } /** * Store the intermediate field value for the given field. */ protected void storeIntermediate(OpenJPAStateManager sm, FieldMetaData fmd) { int index = fmd.getIndex(); Object val = sm.getIntermediate(index); if (val != null) setIntermediate(index, val); } /** * Store impl data for the given field. */ protected void storeImplData(OpenJPAStateManager sm, FieldMetaData fmd, boolean fieldLoaded) { int index = fmd.getIndex(); if (fieldLoaded) { // is there impl data to store? Object impl = sm.getImplData(index); if (impl != null && sm.isImplDataCacheable(index)) setImplData(index, impl); } else setImplData(index, null); } /** * Return a new {@link PCData} implementation of the right type for * embedded instances. Returns a {@link PCDataImpl} by default. */ public AbstractPCData newEmbeddedPCData(OpenJPAStateManager sm) { return new PCDataImpl(sm.getId (), sm.getMetaData (), _cache); } public String getCache() { return _cache; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PreparedQuery.java0000644000000000000000000000754612133327272026741 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Map; import org.apache.openjpa.kernel.PreparedQueryCache.Exclusion; /** * A prepared query associates a compiled query to a parsed state that * can be executed possibly with more efficiency. An obvious example is to * associate a compiled query to an executable SQL string. * * The query expressed in target language can be executed directly bypassing * the critical translation cost to the data store target language on every * execution. * * As the subsequent execution of a cached query will bypass normal query * compilation, the post-compilation state of the original query is captured by * this receiver to be transferred to the executable query instance. * * This receiver must not hold any context-sensitive reference or dependency. * Because the whole idea of preparing a query (for a cost) is to be able to * execute the same logical query in different persistence contexts. However, * a prepared query may not be valid when some parameters of execution context * such as lock group or fetch plan changes in a way that will change the target * query. Refer to {@link PreparedQueryCache} for invalidation mechanism on * possible actions under such circumstances. * * The query execution model does account for context changes that do * not impact the target query e.g. bind variables. * * @author Pinaki Poddar * * @since 2.0.0 */ public interface PreparedQuery { /** * Get the immutable identifier of this receiver used for * * {@link PreparedQueryCache cache}. */ public String getIdentifier(); /** * Get the target database query. */ public String getTargetQuery(); /** * Get the original query. */ public String getOriginalQuery(); /** * Gets the language in which this query is expressed. */ public String getLanguage(); /** * Fill in the post-compilation state of the given Query. This must be * called when a original query is substituted by this receiver and hence * the original query is not parsed or compiled. * * @param q A Query which has been substituted by this receiver and hence * does not have its post-compilation state. */ public void setInto(Query q); /** * Initialize from the given argument. * * @param o an opaque instance supposed to carry post-execution data such * as target database query, parameters of the query etc. * * @return Exclusion if this receiver can initialize itself from the given * argument. false otherwise. */ public Exclusion initialize(Object o); /** * Affirms if this receiver has been initialized. */ public boolean isInitialized(); /** * Get the list of parameters in a map where an entry represents a parameter * key and value after replacing with the given user parameters. * * Must be invoked after initialize(). * * @param user the map of parameter key and value set by the user on the * original query. */ public Map reparametrize(Map user, Broker broker); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AutoClear.java0000644000000000000000000000224412133327272026016 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * State clearing constants. * * @author Abe White * @since 0.4.0 */ public interface AutoClear { /** * Clear state when entering a datastore transaction. */ public static final int CLEAR_DATASTORE = 0; /** * Clear state when entering any transaction. */ public static final int CLEAR_ALL = 1; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/TimeSeededSeq.java0000644000000000000000000000373312133327272026624 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.meta.ClassMetaData; //////////////////////////////////////////////////////////// // NOTE: Do not change property names; see SequenceMetaData // for standard property names. //////////////////////////////////////////////////////////// /** * A simplistic implementation of a {@link Seq} used * to provide datastore ids. Starts with an id equal to the system's * current time in milliseconds and increments from there. * * @author Greg Campbell */ public class TimeSeededSeq implements Seq { private long _id = System.currentTimeMillis(); private int _increment = 1; public void setType(int type) { } public int getIncrement() { return _increment; } public void setIncrement(int increment) { _increment = increment; } public synchronized Object next(StoreContext ctx, ClassMetaData meta) { _id += _increment; return _id; } public synchronized Object current(StoreContext ctx, ClassMetaData meta) { return _id; } public void allocate(int additional, StoreContext ctx, ClassMetaData meta) { } public void close() { } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/LockManager.java0000644000000000000000000001046612133327272026327 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Collection; import org.apache.openjpa.lib.util.Closeable; /** * Handles obtaining and releasing locks on objects. The lock manager * generally does not have to worry about synchronization, as the context is * responsible for synchronizing the calls it makes to the lock manager. * * @author Marc Prud'hommeaux */ public interface LockManager extends Closeable, LockLevels { /** * Set the context this lock manager is associated with. * This will be invoked in the lock manager before any other methods are * called. */ public void setContext(StoreContext ctx); /** * Return the lock level of the specified instance, or * {@link LockLevels#LOCK_NONE} if not locked. */ public int getLockLevel(OpenJPAStateManager sm); /** * Obtain a lock on the specified object. This method may be called when * a user explicitly locks an object, and is also called automatically * for every object accessed during a transaction. The implementation * must track already-locked objects, and must be optimized to return * quickly when the given object does not need additional locking. * The lock manager might use the state manager's lock object for * bookkeeping information. * * @param sm the object to lock * @param level one of the lock constants defined in {@link LockLevels}, * or a custom level * @param timeout the timeout in milliseconds, or a negative number for * no timeout * @param sdata the context information passed from the store manager * to the persistence context, if any; lock managers * specific to a certain back end may be able to take * advantage of this; others should ignore it * @throws org.apache.openjpa.util.LockException if a lock cannot be * obtained in the given number of milliseconds * @see OpenJPAStateManager#setLock */ public void lock(OpenJPAStateManager sm, int level, int timeout, Object sdata); /** * Perform the same function as previous lock method and has the option * to perform a version check after the lock function has completed. */ public void refreshLock(OpenJPAStateManager sm, int level, int timeout, Object sdata); /** * Obtain locks on the specified objects. * * @see #lock */ public void lockAll(Collection sms, int level, int timeout, Object sdata); /** * Release the lock on the given object. This method will be called * automatically for each state manager with a lock object set on * transaction completion, just before the call to {@link #endTransaction}. * The lock manager should null the state manager's lock object. Note * that some state manager may be garbage collected during a transaction; * thus lock managers cannot rely on this method being called for every * state manager. * * @see OpenJPAStateManager#setLock */ public void release(OpenJPAStateManager sm); /** * Notification that a transaction is beginning. Locks are only obtained * within transactions, so an implementation might use this method to * initialize bookkeeping datastructures, etc. */ public void beginTransaction(); /** * Notification that the current transaction has ended. Clear all * datastructures, release any left over locks, etc. */ public void endTransaction(); /** * Free any resources. */ public void close (); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java0000644000000000000000000004051312133327272027231 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Collection; import java.util.Map; import org.apache.commons.collections.map.LinkedMap; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.util.RuntimeExceptionTranslator; /** * Delegating query that can also perform exception translation * for use in facades. * * @since 0.4.0 * @author Abe White * @nojavadoc */ public class DelegatingQuery implements Query { /////////////////////////////////////////////////////////////// // NOTE: when adding a public API method, be sure to add it to // JDO and JPA facades! /////////////////////////////////////////////////////////////// private final Query _query; private final DelegatingQuery _del; private final transient RuntimeExceptionTranslator _trans; /** * Constructor; supply delegate. */ public DelegatingQuery(Query query) { this(query, null); } /** * Constructor; supply delegate and exception translator. */ public DelegatingQuery(Query query, RuntimeExceptionTranslator trans) { _query = query; if (query instanceof DelegatingQuery) _del = (DelegatingQuery) query; else _del = null; _trans = trans; } /** * Return the direct delegate. */ public Query getDelegate() { return _query; } /** * Return the native delegate. */ public Query getInnermostDelegate() { return (_del == null) ? _query : _del.getInnermostDelegate(); } public int hashCode() { return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingQuery) other = ((DelegatingQuery) other).getInnermostDelegate(); return getInnermostDelegate().equals(other); } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public Broker getBroker() { try { return _query.getBroker(); } catch (RuntimeException re) { throw translate(re); } } public Query getQuery() { return this; } public StoreContext getStoreContext() { try { return _query.getStoreContext(); } catch (RuntimeException re) { throw translate(re); } } public int getOperation() { try { return _query.getOperation(); } catch (RuntimeException re) { throw translate(re); } } public String getLanguage() { try { return _query.getLanguage(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration getFetchConfiguration() { try { return _query.getFetchConfiguration(); } catch (RuntimeException re) { throw translate(re); } } public String getQueryString() { try { return _query.getQueryString(); } catch (RuntimeException re) { throw translate(re); } } public boolean getIgnoreChanges() { try { return _query.getIgnoreChanges(); } catch (RuntimeException re) { throw translate(re); } } public Object getCompilation() { try { return _query.getCompilation(); } catch (RuntimeException re) { throw translate(re); } } public String getAlias() { try { return _query.getAlias(); } catch (RuntimeException re) { throw translate(re); } } public String[] getProjectionAliases() { try { return _query.getProjectionAliases(); } catch (RuntimeException re) { throw translate(re); } } public Class[] getProjectionTypes() { try { return _query.getProjectionTypes(); } catch (RuntimeException re) { throw translate(re); } } public boolean isAggregate() { try { return _query.isAggregate(); } catch (RuntimeException re) { throw translate(re); } } public boolean hasGrouping() { try { return _query.hasGrouping(); } catch (RuntimeException re) { throw translate(re); } } public ClassMetaData[] getAccessPathMetaDatas() { try { return _query.getAccessPathMetaDatas(); } catch (RuntimeException re) { throw translate(re); } } public FilterListener getFilterListener(String tag) { try { return _query.getFilterListener(tag); } catch (RuntimeException re) { throw translate(re); } } public AggregateListener getAggregateListener(String tag) { try { return _query.getAggregateListener(tag); } catch (RuntimeException re) { throw translate(re); } } public Collection getFilterListeners() { try { return _query.getFilterListeners(); } catch (RuntimeException re) { throw translate(re); } } public Collection getAggregateListeners() { try { return _query.getAggregateListeners(); } catch (RuntimeException re) { throw translate(re); } } public Collection getCandidateCollection() { try { return _query.getCandidateCollection(); } catch (RuntimeException re) { throw translate(re); } } public Class getCandidateType() { try { return _query.getCandidateType(); } catch (RuntimeException re) { throw translate(re); } } public boolean hasSubclasses() { try { return _query.hasSubclasses(); } catch (RuntimeException re) { throw translate(re); } } public void setCandidateType(Class cls, boolean subs) { try { _query.setCandidateType(cls, subs); } catch (RuntimeException re) { throw translate(re); } } public boolean isReadOnly() { try { return _query.isReadOnly(); } catch (RuntimeException re) { throw translate(re); } } public void setReadOnly(boolean readOnly) { try { _query.setReadOnly(readOnly); } catch (RuntimeException re) { throw translate(re); } } public Class getResultMappingScope() { try { return _query.getResultMappingScope(); } catch (RuntimeException re) { throw translate(re); } } public String getResultMappingName() { try { return _query.getResultMappingName(); } catch (RuntimeException re) { throw translate(re); } } public void setResultMapping(Class scope, String name) { try { _query.setResultMapping(scope, name); } catch (RuntimeException re) { throw translate(re); } } public boolean isUnique() { try { return _query.isUnique(); } catch (RuntimeException re) { throw translate(re); } } public void setUnique(boolean unique) { try { _query.setUnique(unique); } catch (RuntimeException re) { throw translate(re); } } public boolean isDistinct() { try { return _query.isDistinct(); } catch (RuntimeException re) { throw translate(re); } } public Class getResultType() { try { return _query.getResultType(); } catch (RuntimeException re) { throw translate(re); } } public void setResultType(Class cls) { try { _query.setResultType(cls); } catch (RuntimeException re) { throw translate(re); } } public long getStartRange() { try { return _query.getStartRange(); } catch (RuntimeException re) { throw translate(re); } } public long getEndRange() { try { return _query.getEndRange(); } catch (RuntimeException re) { throw translate(re); } } public void setRange(long start, long end) { try { _query.setRange(start, end); } catch (RuntimeException re) { throw translate(re); } } public String getParameterDeclaration() { try { return _query.getParameterDeclaration(); } catch (RuntimeException re) { throw translate(re); } } public OrderedMap> getOrderedParameterTypes() { try { return _query.getOrderedParameterTypes(); } catch (RuntimeException re) { throw translate(re); } } public LinkedMap getParameterTypes() { try { return _query.getParameterTypes(); } catch (RuntimeException re) { throw translate(re); } } public Map getUpdates() { try { return _query.getUpdates(); } catch (RuntimeException re) { throw translate(re); } } public void declareParameters(String params) { try { _query.declareParameters(params); } catch (RuntimeException re) { throw translate(re); } } public Number deleteInMemory(StoreQuery q, StoreQuery.Executor ex, Object[] params) { try { return _query.deleteInMemory(q, ex, params); } catch (RuntimeException re) { throw translate(re); } } public Number updateInMemory(StoreQuery q, StoreQuery.Executor ex, Object[] params) { try { return _query.updateInMemory(q, ex, params); } catch (RuntimeException re) { throw translate(re); } } public Class classForName(String name, String[] imports) { try { return _query.classForName(name, imports); } catch (RuntimeException re) { throw translate(re); } } public void lock() { try { _query.lock(); } catch (RuntimeException re) { throw translate(re); } } public void unlock() { try { _query.unlock(); } catch (RuntimeException re) { throw translate(re); } } public void addFilterListener(FilterListener listener) { try { _query.addFilterListener(listener); } catch (RuntimeException re) { throw translate(re); } } public void removeFilterListener(FilterListener listener) { try { _query.removeFilterListener(listener); } catch (RuntimeException re) { throw translate(re); } } public void addAggregateListener(AggregateListener listener) { try { _query.addAggregateListener(listener); } catch (RuntimeException re) { throw translate(re); } } public void removeAggregateListener(AggregateListener listener) { try { _query.removeAggregateListener(listener); } catch (RuntimeException re) { throw translate(re); } } public Extent getCandidateExtent() { try { return _query.getCandidateExtent(); } catch (RuntimeException re) { throw translate(re); } } public void setCandidateExtent(Extent extent) { try { _query.setCandidateExtent(extent); } catch (RuntimeException re) { throw translate(re); } } public void setCandidateCollection(Collection coll) { try { _query.setCandidateCollection(coll); } catch (RuntimeException re) { throw translate(re); } } public void compile() { try { _query.compile(); } catch (RuntimeException re) { throw translate(re); } } public Object execute() { try { return _query.execute(); } catch (RuntimeException re) { throw translate(re); } } public Object execute(Map params) { try { return _query.execute(params); } catch (RuntimeException re) { throw translate(re); } } public Object execute(Object[] params) { try { return _query.execute(params); } catch (RuntimeException re) { throw translate(re); } } public long deleteAll() { try { return _query.deleteAll(); } catch (RuntimeException re) { throw translate(re); } } public long deleteAll(Object[] parameters) { try { return _query.deleteAll(parameters); } catch (RuntimeException re) { throw translate(re); } } public long deleteAll(Map parameterMap) { try { return _query.deleteAll(parameterMap); } catch (RuntimeException re) { throw translate(re); } } public long updateAll() { try { return _query.updateAll(); } catch (RuntimeException re) { throw translate(re); } } public long updateAll(Object[] parameters) { try { return _query.updateAll(parameters); } catch (RuntimeException re) { throw translate(re); } } public long updateAll(Map parameterMap) { try { return _query.updateAll(parameterMap); } catch (RuntimeException re) { throw translate(re); } } public void closeAll() { try { _query.closeAll(); } catch (RuntimeException re) { throw translate(re); } } public void closeResources() { try { _query.closeResources(); } catch (RuntimeException re) { throw translate(re); } } public String[] getDataStoreActions(Map params) { try { return _query.getDataStoreActions(params); } catch (RuntimeException re) { throw translate(re); } } public boolean setQuery(Object query) { try { return _query.setQuery(query); } catch (RuntimeException re) { throw translate(re); } } public void setIgnoreChanges(boolean ignore) { try { _query.setIgnoreChanges(ignore); } catch (RuntimeException re) { throw translate(re); } } public void assertOpen() { try { _query.assertOpen(); } catch (RuntimeException re) { throw translate(re); } } public void assertNotReadOnly() { try { _query.assertNotReadOnly(); } catch (RuntimeException re) { throw translate(re); } } public void assertNotSerialized() { try { _query.assertNotSerialized(); } catch (RuntimeException re) { throw translate(re); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryLanguages.java0000644000000000000000000000540312133327272027073 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.HashMap; import java.util.Map; import org.apache.openjpa.kernel.exps.ExpressionParser; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Services; import org.apache.openjpa.util.InternalException; /** * Constants and utilities for query languages. */ public class QueryLanguages { public static final String LANG_SQL = "openjpa.SQL"; public static final String LANG_PREPARED_SQL = "openjpa.prepared.SQL"; public static final String LANG_METHODQL = "openjpa.MethodQL"; private static Map _expressionParsers = new HashMap(); static { // Load and cache all the query languages available in the system. Class[] classes = Services.getImplementorClasses( ExpressionParser.class, AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(ExpressionParser.class))); for (int i = 0; i < classes.length; i++) { ExpressionParser ep; try { ep = (ExpressionParser) AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(classes[i])); } catch (PrivilegedActionException pae) { throw new InternalException(pae.getException()); } catch (InstantiationException e) { throw new InternalException(e); } catch (IllegalAccessException e) { throw new InternalException(e); } _expressionParsers.put(ep.getLanguage(), ep); } } /** * Return the {@link ExpressionParser} for language, or * null if no expression parser exists in the system for * the specified language. */ public static ExpressionParser parserForLanguage(String language) { return (ExpressionParser) _expressionParsers.get(language); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java0000644000000000000000000022332612133327272026074 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.collections.map.LinkedMap; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.Constant; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.kernel.exps.Literal; import org.apache.openjpa.kernel.exps.Path; import org.apache.openjpa.kernel.exps.QueryExpressions; import org.apache.openjpa.kernel.exps.Val; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.rop.EagerResultList; import org.apache.openjpa.lib.rop.ListResultList; import org.apache.openjpa.lib.rop.MergedResultObjectProvider; import org.apache.openjpa.lib.rop.RangeResultObjectProvider; import org.apache.openjpa.lib.rop.ResultList; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.lib.util.ReferenceHashSet; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.NoResultException; import org.apache.openjpa.util.NonUniqueResultException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.UserException; import serp.util.Strings; /** * Implementation of the {@link Query} interface. * * @author Abe White * @nojavadoc */ @SuppressWarnings("serial") public class QueryImpl implements Query { private static final Localizer _loc = Localizer.forPackage(QueryImpl.class); private final String _language; private final StoreQuery _storeQuery; private transient final BrokerImpl _broker; private transient final Log _log; private transient ClassLoader _loader = null; // query has its own internal lock private ReentrantLock _lock; // unparsed state private Class _class = null; private boolean _subclasses = true; private boolean _readOnly = false; private String _query = null; private String _params = null; // parsed state private transient Compilation _compiled = null; private transient boolean _compiling = false; private transient ResultPacker _packer = null; // candidates private transient Collection _collection = null; private transient Extent _extent = null; // listeners private Map _filtListeners = null; private Map _aggListeners = null; // configuration for loading objects private FetchConfiguration _fc = null; private boolean _ignoreChanges = false; private Class _resultMappingScope = null; private String _resultMappingName = null; // these fields should only be used directly after we have a compilation, // because their values may be encoded in the query string private Boolean _unique = null; private Class _resultClass = null; private transient long _startIdx = 0; private transient long _endIdx = Long.MAX_VALUE; private transient boolean _rangeSet = false; // remember the list of all the results we have returned so we // can free their resources when close or closeAll is called private transient final Collection _resultLists = new ReferenceHashSet(ReferenceHashSet.WEAK); private boolean _printParameters = false; /** * Construct a query managed by the given broker. */ public QueryImpl(Broker broker, String language, StoreQuery storeQuery) { _broker = (BrokerImpl) broker; _language = language; _storeQuery = storeQuery; _fc = (FetchConfiguration) broker.getFetchConfiguration().clone(); _log = broker.getConfiguration().getLog(OpenJPAConfiguration.LOG_QUERY); _storeQuery.setContext(this); _printParameters = _broker.getPrintParameters(); if (_broker != null && _broker.getMultithreaded()) _lock = new ReentrantLock(); } /** * Internal store query. */ public StoreQuery getStoreQuery() { return _storeQuery; } public Broker getBroker() { return _broker; } public Query getQuery() { return this; } public StoreContext getStoreContext() { return _broker; } public String getLanguage() { return _language; } public FetchConfiguration getFetchConfiguration() { return _fc; } public String getQueryString() { return _query; } public boolean getIgnoreChanges() { assertOpen(); return _ignoreChanges; } public void setIgnoreChanges(boolean flag) { lock(); try { assertOpen(); // allowed modification: no read-only check _ignoreChanges = flag; } finally { unlock(); } } public boolean isReadOnly() { assertOpen(); return _readOnly; } public void setReadOnly(boolean flag) { lock(); try { assertOpen(); _readOnly = flag; } finally { unlock(); } } public void addFilterListener(FilterListener listener) { lock(); try { assertOpen(); assertNotReadOnly(); if (_filtListeners == null) _filtListeners = new HashMap(5); _filtListeners.put(listener.getTag(), listener); } finally { unlock(); } } public void removeFilterListener(FilterListener listener) { lock(); try { assertOpen(); assertNotReadOnly(); if (_filtListeners != null) _filtListeners.remove(listener.getTag()); } finally { unlock(); } } public Collection getFilterListeners() { if (_filtListeners == null) return Collections.emptyList(); else return _filtListeners.values(); } public FilterListener getFilterListener(String tag) { // first check listeners for this query if (_filtListeners != null) { FilterListener listen = (FilterListener) _filtListeners.get(tag); if (listen != null) return listen; } // check user-defined listeners from configuration FilterListener[] confListeners = _broker.getConfiguration(). getFilterListenerInstances(); for (int i = 0; i < confListeners.length; i++) if (confListeners[i].getTag().equals(tag)) return confListeners[i]; // check store listeners return _storeQuery.getFilterListener(tag); } public void addAggregateListener(AggregateListener listener) { lock(); try { assertOpen(); assertNotReadOnly(); if (_aggListeners == null) _aggListeners = new HashMap(5); _aggListeners.put(listener.getTag(), listener); } finally { unlock(); } } public void removeAggregateListener(AggregateListener listener) { lock(); try { assertOpen(); assertNotReadOnly(); if (_aggListeners != null) _aggListeners.remove(listener.getTag()); } finally { unlock(); } } public Collection getAggregateListeners() { if (_aggListeners == null) return Collections.emptyList(); else return _aggListeners.values(); } public AggregateListener getAggregateListener(String tag) { // first check listeners for this query if (_aggListeners != null) { AggregateListener listen = (AggregateListener) _aggListeners. get(tag); if (listen != null) return listen; } // check user-defined listeners from configuration AggregateListener[] confListeners = _broker.getConfiguration(). getAggregateListenerInstances(); for (int i = 0; i < confListeners.length; i++) if (confListeners[i].getTag().equals(tag)) return confListeners[i]; // check store listeners return _storeQuery.getAggregateListener(tag); } public Extent getCandidateExtent() { // if just the class is set, fetch the corresponding extent; if the // extent is already set but its ignore cache setting is wrong, // get a new extent with the correct setting (don't modify orig extent // in case the user has a reference to it and might use it) lock(); try { Class cls = getCandidateType(); if (_extent == null && _collection == null && _broker != null && cls != null) { _extent = _broker.newExtent(cls, _subclasses); _extent.setIgnoreChanges(_ignoreChanges); } else if (_extent != null && _extent.getIgnoreChanges() != _ignoreChanges && cls != null){ _extent = _broker.newExtent(cls, _extent.hasSubclasses()); _extent.setIgnoreChanges(_ignoreChanges); } return _extent; } finally { unlock(); } } public void setCandidateExtent(Extent candidateExtent) { lock(); try { assertOpen(); assertNotReadOnly(); if (candidateExtent == _extent) return; if (candidateExtent == null) { _extent = null; return; } // if extent then not collection _extent = candidateExtent; _collection = null; boolean invalidate = false; if (_extent.getElementType() != _class) { _class = _extent.getElementType(); _loader = null; invalidate = true; } if (_extent.hasSubclasses() != _subclasses) { _subclasses = _extent.hasSubclasses(); invalidate = true; } if (invalidate) invalidateCompilation(); } finally { unlock(); } } public Collection getCandidateCollection() { assertOpen(); return _collection; } public void setCandidateCollection(Collection candidateCollection) { if (!_storeQuery.supportsInMemoryExecution()) throw new UnsupportedException(_loc.get("query-nosupport", _language)); lock(); try { assertOpen(); // if collection then not extent _collection = candidateCollection; if (_collection != null) _extent = null; } finally { unlock(); } } public Class getCandidateType() { lock(); try { assertOpen(); if (_class != null || _compiled != null || _query == null || _broker == null) return _class; // check again after compilation; maybe encoded in string compileForCompilation(); return _class; } finally { unlock(); } } public void setCandidateType(Class candidateClass, boolean subs) { lock(); try { assertOpen(); assertNotReadOnly(); _class = candidateClass; _subclasses = subs; _loader = null; invalidateCompilation(); } finally { unlock(); } } public boolean hasSubclasses() { return _subclasses; } public String getResultMappingName() { assertOpen(); return _resultMappingName; } public Class getResultMappingScope() { assertOpen(); return _resultMappingScope; } public void setResultMapping(Class scope, String name) { lock(); try { assertOpen(); _resultMappingScope = scope; _resultMappingName = name; _packer = null; } finally { unlock(); } } public boolean isUnique() { lock(); try { assertOpen(); if (_unique != null) return _unique.booleanValue(); if ((_query == null && _language.endsWith("JPQL")) || _compiling || _broker == null) return false; // check again after compilation; maybe encoded in string if (_compiled == null) { compileForCompilation(); if (_unique != null) return _unique.booleanValue(); } // no explicit setting; default StoreQuery.Executor ex = compileForExecutor(); if (!ex.isAggregate(_storeQuery)) return false; return !ex.hasGrouping(_storeQuery); } finally { unlock(); } } /** * Affirms if this query has originated by parsing a string-based query. */ public boolean isParsedQuery() { return getQueryString() != null; } public void setUnique(boolean unique) { lock(); try { assertOpen(); assertNotReadOnly(); _unique = (unique) ? Boolean.TRUE : Boolean.FALSE; } finally { unlock(); } } public Class getResultType() { lock(); try { assertOpen(); if (_resultClass != null || _compiled != null || _query == null || _broker == null) return _resultClass; // check again after compilation; maybe encoded in string compileForCompilation(); return _resultClass; } finally { unlock(); } } public void setResultType(Class cls) { lock(); try { assertOpen(); // allowed modification: no read-only check _resultClass = cls; _packer = null; } finally { unlock(); } } public long getStartRange() { assertOpen(); return _startIdx; } public long getEndRange() { assertOpen(); return _endIdx; } public void setRange(long start, long end) { if (start < 0 || end < 0) throw new UserException(_loc.get("invalid-range", String.valueOf(start), String.valueOf(end))); if (end - start > Integer.MAX_VALUE && end != Long.MAX_VALUE) throw new UserException(_loc.get("range-too-big", String.valueOf(start), String.valueOf(end))); lock(); try { assertOpen(); // allowed modification: no read-only check _startIdx = start; _endIdx = end; _rangeSet = true; } finally { unlock(); } } public String getParameterDeclaration() { lock(); try { assertOpen(); if (_params != null || _compiled != null || _compiling || _broker == null) return _params; // check again after compilation; maybe encoded in string compileForCompilation(); return _params; } finally { unlock(); } } public void declareParameters(String params) { if (!_storeQuery.supportsParameterDeclarations()) throw new UnsupportedException(_loc.get("query-nosupport", _language)); lock(); try { assertOpen(); assertNotReadOnly(); _params = StringUtils.trimToNull(params); invalidateCompilation(); } finally { unlock(); } } public void compile() { lock(); try { assertOpen(); StoreQuery.Executor ex = compileForExecutor(); getResultPacker(_storeQuery, ex); ex.validate(_storeQuery); } finally { unlock(); } } public Object getCompilation() { lock(); try { return compileForCompilation().storeData; } finally { unlock(); } } /** * Compile query properties. */ private Compilation compileForCompilation() { if (_compiled != null || _compiling) return _compiled; assertNotSerialized(); assertOpen(); boolean readOnly = _readOnly; _readOnly = false; _compiling = true; try { _compiled = compilationFromCache(); return _compiled; } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { _compiling = false; _readOnly = readOnly; } } /** * Find the cached compilation for the current query, creating one if it * does not exist. */ protected Compilation compilationFromCache() { Map compCache = _broker.getConfiguration().getQueryCompilationCacheInstance(); if (compCache == null || !isParsedQuery()) { return newCompilation(); } else { CompilationKey key = new CompilationKey(); key.queryType = _storeQuery.getClass(); key.candidateType = getCandidateType(); key.subclasses = hasSubclasses(); key.query = getQueryString(); key.language = getLanguage(); key.storeKey = _storeQuery.newCompilationKey(); Compilation comp = (Compilation) compCache.get(key); // parse declarations if needed boolean cache = false; if (comp == null) { comp = newCompilation(); // only cache those queries that can be compiled cache = comp.storeData != null; } else _storeQuery.populateFromCompilation(comp.storeData); // cache parsed state if needed if (cache) compCache.put(key, comp); return comp; } } /** * Create and populate a new compilation. */ private Compilation newCompilation() { Compilation comp = new Compilation(); comp.storeData = _storeQuery.newCompilation(); _storeQuery.populateFromCompilation(comp.storeData); return comp; } /** * Compile for execution, choosing between datastore and in-mem * compilation based on what we support and our settings. */ private StoreQuery.Executor compileForExecutor() { Compilation comp = compileForCompilation(); if (_collection == null) { if (comp.datastore != null) return comp.datastore; if (comp.memory != null) return comp.memory; if (_storeQuery.supportsDataStoreExecution()) return compileForDataStore(comp); return compileForInMemory(comp); } if (comp.memory != null) return comp.memory; if (comp.datastore != null) return comp.datastore; if (_storeQuery.supportsInMemoryExecution()) return compileForInMemory(comp); return compileForDataStore(comp); } /** * Create an expression tree for datastore execution. */ private StoreQuery.Executor compileForDataStore(Compilation comp) { if (comp.datastore == null) comp.datastore = createExecutor(false); return comp.datastore; } /** * Create an expression tree for in-memory execution. */ private StoreQuery.Executor compileForInMemory(Compilation comp) { if (comp.memory == null) comp.memory = createExecutor(true); return comp.memory; } /** * Return a query executor of the proper type. */ private StoreQuery.Executor createExecutor(boolean inMem) { assertCandidateType(); MetaDataRepository repos = _broker.getConfiguration(). getMetaDataRepositoryInstance(); ClassMetaData meta = repos.getMetaData(_class, _broker.getClassLoader(), false); ClassMetaData[] metas; if (_class == null || _storeQuery.supportsAbstractExecutors()) metas = new ClassMetaData[]{ meta }; else if (_subclasses && (meta == null || meta.isManagedInterface())) metas = repos.getImplementorMetaDatas(_class, _broker.getClassLoader(), true); else if (meta != null && (_subclasses || meta.isMapped())) metas = new ClassMetaData[]{ meta }; else metas = StoreQuery.EMPTY_METAS; if (metas.length == 0) throw new UserException(_loc.get("no-impls", _class)); try { if (metas.length == 1) { if (inMem) return _storeQuery.newInMemoryExecutor(metas[0], _subclasses); return _storeQuery.newDataStoreExecutor(metas[0], _subclasses); } // multiple implementors StoreQuery.Executor[] es = new StoreQuery.Executor[metas.length]; for (int i = 0; i < es.length; i++) { if (inMem) es[i] = _storeQuery.newInMemoryExecutor(metas[i], true); else es[i] = _storeQuery.newDataStoreExecutor(metas[i], true); } return new MergedExecutor(es); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } } /** * Clear any compilation, forcing this query to be recompiled * next time it's executed. This should be invoked whenever any * state changes that would cause the underlying query * representation to change. * * @since 0.3.0 */ private boolean invalidateCompilation() { if (_compiling) return false; _storeQuery.invalidateCompilation(); _compiled = null; _packer = null; return true; } public Object execute() { return execute((Object[]) null); } public Object execute(Object[] params) { return execute(OP_SELECT, params); } public Object execute(Map params) { return execute(OP_SELECT, params); } private Object execute(int operation, Object[] params) { if (params == null) params = StoreQuery.EMPTY_OBJECTS; lock(); try { assertNotSerialized(); _broker.beginOperation(true); try { assertOpen(); _broker.assertNontransactionalRead(); // get executor Compilation comp = compileForCompilation(); StoreQuery.Executor ex = (isInMemory(operation)) ? compileForInMemory(comp) : compileForDataStore(comp); assertParameters(_storeQuery, ex, params); if (_log.isTraceEnabled()) logExecution(operation, ex.getOrderedParameterTypes(_storeQuery), params); if (operation == OP_SELECT) return execute(_storeQuery, ex, params); if (operation == OP_DELETE) return delete(_storeQuery, ex, params); if (operation == OP_UPDATE) return update(_storeQuery, ex, params); throw new UnsupportedException(); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new UserException(e); } finally { _broker.endOperation(); } } finally { unlock(); } } private Object execute(int operation, Map params) { if (params == null) params = Collections.EMPTY_MAP; lock(); try { _broker.beginOperation(true); try { assertNotSerialized(); assertOpen(); _broker.assertNontransactionalRead(); // get executor Compilation comp = compileForCompilation(); StoreQuery.Executor ex = (isInMemory(operation)) ? compileForInMemory(comp) : compileForDataStore(comp); assertParameters(_storeQuery, ex, params); Object[] arr = (params.isEmpty()) ? StoreQuery.EMPTY_OBJECTS : ex.toParameterArray(_storeQuery, params); if (_log.isTraceEnabled()) logExecution(operation, params); if (operation == OP_SELECT) return execute(_storeQuery, ex, arr); if (operation == OP_DELETE) return delete(_storeQuery, ex, arr); if (operation == OP_UPDATE) return update(_storeQuery, ex, arr); throw new UnsupportedException(); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new UserException(_loc.get("query-execution-error", _query), e); } finally { _broker.endOperation(); } } finally { unlock(); } } public long deleteAll() { return deleteAll((Object[]) null); } public long deleteAll(Object[] params) { return ((Number) execute(OP_DELETE, params)).longValue(); } public long deleteAll(Map params) { return ((Number) execute(OP_DELETE, params)).longValue(); } public long updateAll() { return updateAll((Object[]) null); } public long updateAll(Object[] params) { return ((Number) execute(OP_UPDATE, params)).longValue(); } public long updateAll(Map params) { return ((Number) execute(OP_UPDATE, params)).longValue(); } /** * Converts the values of given params Map into an array in * consultation of the paramTypes Map. * * The indexing of the resultant array is significant for following * interrelated but tacit assumptions: * The values in the returned Object[] is consumed by {@link Parameter} * expressions. Query parsing creates these Parameters and sets their * key and index. The index set on the Parameter by the parser is the * same index used to access the Object[] elements returned by this method. * * {@link JPQLExpressionBuilder} creates and populates parameters as * follows: * The parameter key is not the token encountered by the parser, but * converted to Integer or String based on the context in which the token * appeared. * The index for positional (Integer) parameter is the value of the key * minus 1. * The index for named (String) parameter is the order in which the * token appeared to parser during scanning. * * * The first LinkedMap argument to this method is the result of parsing. * This LinkedMap contains the parameter key and their expected * (if determinable) value types. That it is a LinkedMap points to the * fact that an ordering is implicit. The ordering of the keys in this Map * is the same as the order in which parser encountered the parameter * tokens. * * For example, parsing result of the following two JPQL queries * a) UPDATE CompUser e SET e.name= ?1, e.age = ?2 WHERE e.userid = ?3 * b) UPDATE CompUser e SET e.name= :name, e.age = :age WHERE e.userid = * :id * The parameter keys will appear in the order (3,2,1) or (:id, :name, :age) * in the given LinkedMap because WHERE clause is parsed before SET clause. * The corresponding Parameter Expressions created by the parser will have * following key and index: * a) 1:0, 2:1, 3:2 * b) name:1, age:2, id:0 * * The purpose of this method is to produce an Object[] with an indexing * scheme that matches the indexing of the Parameter Expression. * The user map (the second argument) should produce the following Object[] * in two above-mentioned cases * a) {1:"Shannon",2:29,3:5032} --> ["Shannon", 29, 5032] * b) {"name":"Shannon", "age":29, "id":5032} --> [5032, "Shannon", 29] * */ /** * Return whether we should execute this query in memory. */ private boolean isInMemory(int operation) { // if there are any dirty instances in the current trans that are // involved in this query, we have to execute in memory or flush boolean inMem = !_storeQuery.supportsDataStoreExecution() || _collection != null; if (!inMem && (!_ignoreChanges || operation != OP_SELECT) && _broker.isActive() && isAccessPathDirty()) { int flush = _fc.getFlushBeforeQueries(); if ((flush == FLUSH_TRUE || (flush == FLUSH_WITH_CONNECTION && _broker.hasConnection()) || operation != OP_SELECT || !_storeQuery.supportsInMemoryExecution()) && _broker.getConfiguration().supportedOptions(). contains(OpenJPAConfiguration.OPTION_INC_FLUSH)) { _broker.flush(); } else { if (_log.isInfoEnabled()) _log.info(_loc.get("force-in-mem", _class)); inMem = true; } } if (inMem && !_storeQuery.supportsInMemoryExecution()) throw new InvalidStateException(_loc.get("cant-exec-inmem", _language)); return inMem; } /** * Execute the query using the given compilation, executor, and parameter * values. All other execute methods delegate to this one or to * {@link #execute(StoreQuery.Executor,Map)} after validation and locking. */ private Object execute(StoreQuery q, StoreQuery.Executor ex, Object[] params) throws Exception { // if this is an impossible result range, return null / empty list StoreQuery.Range range = new StoreQuery.Range(_startIdx, _endIdx); if (!_rangeSet) ex.getRange(q, params, range); if (range.start >= range.end) return emptyResult(q, ex); // execute; if we have a result class or we have only one result // and so need to remove it from its array, wrap in a packing rop range.lrs = isLRS(range.start, range.end); ResultObjectProvider rop = ex.executeQuery(q, params, range); try { return toResult(q, ex, rop, range); } catch (Exception e) { if (rop != null) try { rop.close(); } catch (Exception e2) {} throw e; } } /** * Delete the query using the given executor, and parameter * values. All other execute methods delegate to this one or to * {@link #delete(StoreQuery.Executor,Map)} after validation and locking. * The return value will be a Number indicating the number of * instances deleted. */ private Number delete(StoreQuery q, StoreQuery.Executor ex, Object[] params) throws Exception { assertBulkModify(q, ex, params); return ex.executeDelete(q, params); } public Number deleteInMemory(StoreQuery q, StoreQuery.Executor executor, Object[] params) { try { Object o = execute(q, executor, params); if (!(o instanceof Collection)) o = Collections.singleton(o); int size = 0; for (Iterator i = ((Collection) o).iterator(); i.hasNext(); size++) _broker.delete(i.next(), null); return size; } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new UserException(e); } } /** * Update the query using the given compilation, executor, and parameter * values. All other execute methods delegate to this one or to * {@link #update(StoreQuery.Executor,Map)} after validation and locking. * The return value will be a Number indicating the number of * instances updated. */ private Number update(StoreQuery q, StoreQuery.Executor ex, Object[] params) throws Exception { assertBulkModify(q, ex, params); return ex.executeUpdate(q, params); } public Number updateInMemory(StoreQuery q, StoreQuery.Executor executor, Object[] params) { try { Object o = execute(q, executor, params); if (!(o instanceof Collection)) o = Collections.singleton(o); int size = 0; for (Iterator i = ((Collection) o).iterator(); i.hasNext(); size++) updateInMemory(i.next(), params, q); return size; } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new UserException(e); } } /** * Set the values for the updates in memory. * * @param ob the persistent instance to change * @param params the parameters passed to the query */ private void updateInMemory(Object ob, Object[] params, StoreQuery q) { for (Iterator it = getUpdates().entrySet().iterator(); it.hasNext();) { Map.Entry e = (Map.Entry) it.next(); Path path = (Path) e.getKey(); FieldMetaData fmd = (FieldMetaData) path.last(); OpenJPAStateManager sm = _broker.getStateManager(ob); Object val; Object value = e.getValue(); if (value instanceof Val) { val = ((Val) value). evaluate(ob, null, getStoreContext(), params); } else if (value instanceof Literal) { val = ((Literal) value).getValue(); } else if (value instanceof Constant) { val = ((Constant) value).getValue(params); } else { try { val = q.evaluate(value, ob, params, sm); } catch (UnsupportedException e1) { throw new UserException( _loc.get("fail-to-get-update-value")); } } int i = fmd.getIndex(); PersistenceCapable into = ImplHelper.toPersistenceCapable(ob, _broker.getConfiguration()); // set the actual field in the instance int set = OpenJPAStateManager.SET_USER; switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: sm.settingBooleanField(into, i, sm.fetchBooleanField(i), val == null ? false : ((Boolean) val).booleanValue(), set); break; case JavaTypes.BYTE: sm.settingByteField(into, i, sm.fetchByteField(i), val == null ? 0 : ((Number) val).byteValue(), set); break; case JavaTypes.CHAR: sm.settingCharField(into, i, sm.fetchCharField(i), val == null ? 0 : val.toString().charAt(0), set); break; case JavaTypes.DOUBLE: sm.settingDoubleField(into, i, sm.fetchDoubleField(i), val == null ? 0 : ((Number) val).doubleValue(), set); break; case JavaTypes.FLOAT: sm.settingFloatField(into, i, sm.fetchFloatField(i), val == null ? 0 : ((Number) val).floatValue(), set); break; case JavaTypes.INT: sm.settingIntField(into, i, sm.fetchIntField(i), val == null ? 0 : ((Number) val).intValue(), set); break; case JavaTypes.LONG: sm.settingLongField(into, i, sm.fetchLongField(i), val == null ? 0 : ((Number) val).longValue(), set); break; case JavaTypes.SHORT: sm.settingShortField(into, i, sm.fetchShortField(i), val == null ? 0 : ((Number) val).shortValue(), set); break; case JavaTypes.STRING: sm.settingStringField(into, i, sm.fetchStringField(i), val == null ? null : val.toString(), set); break; case JavaTypes.DATE: case JavaTypes.NUMBER: case JavaTypes.BOOLEAN_OBJ: case JavaTypes.BYTE_OBJ: case JavaTypes.CHAR_OBJ: case JavaTypes.DOUBLE_OBJ: case JavaTypes.FLOAT_OBJ: case JavaTypes.INT_OBJ: case JavaTypes.LONG_OBJ: case JavaTypes.SHORT_OBJ: case JavaTypes.BIGDECIMAL: case JavaTypes.BIGINTEGER: case JavaTypes.LOCALE: case JavaTypes.OBJECT: case JavaTypes.OID: case JavaTypes.ENUM: sm.settingObjectField(into, i, sm.fetchObjectField(i), val, set); break; default: throw new UserException(_loc.get("only-update-primitives")); } } } /** * Trace log that the query is executing. */ private void logExecution(int op, OrderedMap> types, Object[] params) { OrderedMap pmap = new OrderedMap(); if (params.length > 0) { if (types != null && types.size() == params.length) { int i = 0; for (Iterator itr = types.keySet().iterator(); itr.hasNext();) pmap.put(itr.next(), params[i++]); } else { for (int i = 0; i < params.length; i++) pmap.put(String.valueOf(i), params[i]); } } logExecution(op, pmap); } /** * Trace log that the query is executing. */ private void logExecution(int op, Map params) { String s = _query; if (StringUtils.isEmpty(s)) s = toString(); String msg = "executing-query"; if (params.isEmpty() == false) { msg = "executing-query-with-params"; } // If we aren't supposed to print parameters, replace values with '?' Object p = (_printParameters) ? params : "?"; _log.trace(_loc.get(msg, s, p)); } /** * Return whether this should be treated as a potential large result set. */ private boolean isLRS(long start, long end) { long range = end - start; return _fc.getFetchBatchSize() >= 0 && !(range <= _fc.getFetchBatchSize() || (_fc.getFetchBatchSize() == 0 && range <= 50)); } /** * Return the query result for the given result object provider. */ protected Object toResult(StoreQuery q, StoreQuery.Executor ex, ResultObjectProvider rop, StoreQuery.Range range) throws Exception { // pack projections if necessary String[] aliases = ex.getProjectionAliases(q); if (!ex.isPacking(q)) { ResultPacker packer = getResultPacker(q, ex); if (packer != null || aliases.length == 1) rop = new PackingResultObjectProvider(rop, packer, aliases.length); } // if single result, extract it if (_unique == Boolean.TRUE || (aliases.length > 0 && !ex.hasGrouping(q) && ex.isAggregate(q))) return singleResult(rop, range); // now that we've executed the query, we can call isAggregate and // hasGrouping efficiently boolean detach = (_broker.getAutoDetach() & AutoDetach.DETACH_NONTXREAD) > 0 && !_broker.isActive(); boolean lrs = range.lrs && !ex.isAggregate(q) && !ex.hasGrouping(q); ResultList res = new ListResultList(Collections.emptyList()); try { res = (!detach && lrs) ? _fc.newResultList(rop) : new EagerResultList(rop); res.setUserObject(new Object[]{rop,ex}); _resultLists.add(decorateResultList(res)); } catch (OpenJPAException e) { if (e.getFailedObject() == null) { e.setFailedObject(getQueryString()); } throw e; } return res; } /** * Optionally decorate the native result. */ protected RemoveOnCloseResultList decorateResultList(ResultList res) { return new RemoveOnCloseResultList(res); } /** * Return a result packer for this projection, or null. */ private ResultPacker getResultPacker(StoreQuery q, StoreQuery.Executor ex) { if (_packer != null) return _packer; Class resultClass = (_resultClass != null) ? _resultClass : ex.getResultClass(q); if (resultClass == null) return null; String[] aliases = ex.getProjectionAliases(q); ResultShape shape = ex.getResultShape(q); if (shape != null) { // using JPA2.0 style result shape for packing if (aliases.length == 0) { _packer = new ResultShapePacker(new Class[]{_class}, new String[]{""}, resultClass, shape); } else { _packer = new ResultShapePacker(ex.getProjectionTypes(q), aliases, resultClass, shape); } } else { if (aliases.length == 0) { // result class but no result; means candidate is being set // into some result class _packer = new ResultPacker(_class, getAlias(), resultClass); } else if (resultClass != null) { // projection Class[] types = ex.getProjectionTypes(q); _packer = new ResultPacker(types, aliases, resultClass); } } return _packer; } /** * Create an empty result for this query. */ private Object emptyResult(StoreQuery q, StoreQuery.Executor ex) { if (_unique == Boolean.TRUE || (_unique == null && !ex.hasGrouping(q) && ex.isAggregate(q))) return null; return Collections.EMPTY_LIST; } /** * Extract an expected single result from the given provider. Used when * the result is an ungrouped aggregate or the unique flag is set to true. */ private Object singleResult(ResultObjectProvider rop, StoreQuery.Range range) throws Exception { rop.open(); try { // move to expected result boolean next = rop.next(); // extract single result; throw an exception if multiple results // match and not constrainted by range, or if a unique query with // no results Object single = null; if (next) { single = rop.getResultObject(); if (range.end != range.start + 1 && rop.next()) throw new NonUniqueResultException(_loc.get("not-unique", _class, _query)); } else if (_unique == Boolean.TRUE) throw new NoResultException(_loc.get("no-result", _class, _query)); // if unique set to false, use collection if (_unique == Boolean.FALSE) { if (!next) return Collections.EMPTY_LIST; // Collections.singletonList is JDK 1.3, so... return Arrays.asList(new Object[]{ single }); } // return single result return single; } finally { rop.close(); } } /** * Calculates whether the access path of this query intersects with * any dirty objects in the transaction. */ private boolean isAccessPathDirty() { return isAccessPathDirty(_broker, getAccessPathMetaDatas()); } public static boolean isAccessPathDirty(Broker broker, ClassMetaData[] accessMetas) { Collection> persisted = broker.getPersistedTypes(); Collection> updated = broker.getUpdatedTypes(); Collection> deleted = broker.getDeletedTypes(); if (persisted.isEmpty() && updated.isEmpty() && deleted.isEmpty()) return false; // if no access metas, assume every dirty object affects path just // to be safe if (accessMetas.length == 0) return true; // compare dirty classes to the access path classes Class accClass; for (int i = 0; i < accessMetas.length; i++) { if (accessMetas[i] == null) continue; // shortcut if actual class is dirty accClass = accessMetas[i].getDescribedType(); if (persisted.contains(accClass) || updated.contains(accClass) || deleted.contains(accClass)) return true; // check for dirty subclass for (Iterator> dirty = persisted.iterator(); dirty.hasNext();) if (accClass.isAssignableFrom(dirty.next())) return true; for (Iterator> dirty = updated.iterator(); dirty.hasNext();) if (accClass.isAssignableFrom(dirty.next())) return true; for (Iterator> dirty = deleted.iterator(); dirty.hasNext();) if (accClass.isAssignableFrom(dirty.next())) return true; } // no intersection return false; } public void closeAll() { closeResults(true); } public void closeResources() { closeResults(false); } /** * Close open results. */ private void closeResults(boolean force) { lock(); try { assertOpen(); RemoveOnCloseResultList res; for (Iterator itr = _resultLists.iterator(); itr.hasNext();) { res = itr.next(); if (force || res.isProviderOpen()) res.close(false); } _resultLists.clear(); } finally { unlock(); } } public String[] getDataStoreActions(Map params) { if (params == null) params = Collections.EMPTY_MAP; lock(); try { assertNotSerialized(); assertOpen(); StoreQuery.Executor ex = compileForExecutor(); assertParameters(_storeQuery, ex, params); Object[] arr = ex.toParameterArray(_storeQuery, params); StoreQuery.Range range = new StoreQuery.Range(_startIdx, _endIdx); if (!_rangeSet) ex.getRange(_storeQuery, arr, range); return ex.getDataStoreActions(_storeQuery, arr, range); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new UserException(e); } finally { unlock(); } } public boolean setQuery(Object query) { lock(); try { assertOpen(); assertNotReadOnly(); if (query == null || query instanceof String) { invalidateCompilation(); _query = (String) query; if (_query != null) _query = _query.trim(); return true; } if (!(query instanceof QueryImpl)) return _storeQuery.setQuery(query); // copy all non-transient state from the given query invalidateCompilation(); QueryImpl q = (QueryImpl) query; _class = q._class; _subclasses = q._subclasses; _query = q._query; _ignoreChanges = q._ignoreChanges; _unique = q._unique; _resultClass = q._resultClass; _params = q._params; _resultMappingScope = q._resultMappingScope; _resultMappingName = q._resultMappingName; _readOnly = q._readOnly; // don't share mutable objects _fc.copy(q._fc); if (q._filtListeners != null) _filtListeners = new HashMap(q._filtListeners); if (q._aggListeners != null) _aggListeners = new HashMap(q._aggListeners); return true; } finally { unlock(); } } public String getAlias() { lock(); try { String alias = compileForExecutor().getAlias(_storeQuery); if (alias == null) alias = Strings.getClassName(_class); return alias; } finally { unlock(); } } public String[] getProjectionAliases() { lock(); try { return compileForExecutor().getProjectionAliases(_storeQuery); } finally { unlock(); } } public Class[] getProjectionTypes() { lock(); try { return compileForExecutor().getProjectionTypes(_storeQuery); } finally { unlock(); } } public int getOperation() { lock(); try { return compileForExecutor().getOperation(_storeQuery); } finally { unlock(); } } public boolean isAggregate() { lock(); try { return compileForExecutor().isAggregate(_storeQuery); } finally { unlock(); } } public boolean isDistinct() { lock(); try { return compileForExecutor().isDistinct(_storeQuery); } finally { unlock(); } } public boolean hasGrouping() { lock(); try { return compileForExecutor().hasGrouping(_storeQuery); } finally { unlock(); } } public ClassMetaData[] getAccessPathMetaDatas() { lock(); try { ClassMetaData[] metas = compileForExecutor(). getAccessPathMetaDatas(_storeQuery); return (metas == null) ? StoreQuery.EMPTY_METAS : metas; } finally { unlock(); } } public OrderedMap> getOrderedParameterTypes() { lock(); try { return compileForExecutor().getOrderedParameterTypes(_storeQuery); } finally { unlock(); } } public LinkedMap getParameterTypes() { lock(); try { LinkedMap wrap = new LinkedMap(); wrap.putAll(compileForExecutor().getOrderedParameterTypes(_storeQuery)); return wrap; } finally { unlock(); } } public Map getUpdates() { lock(); try { return compileForExecutor().getUpdates(_storeQuery); } finally { unlock(); } } public void lock() { if (_lock != null) _lock.lock(); } public void unlock() { if (_lock != null) _lock.unlock(); } public synchronized void startLocking() { if (_lock == null) { _lock = new ReentrantLock(); } } public synchronized void stopLocking() { if (_lock != null && !_broker.getMultithreaded()) _lock = null; } ///////// // Utils ///////// public Class classForName(String name, String[] imports) { // full class name or primitive type? Class type = toClass(name); if (type != null) return type; // first check the aliases map in the MetaDataRepository ClassLoader loader = (_class == null) ? _loader : AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(_class)); ClassMetaData meta = _broker.getConfiguration(). getMetaDataRepositoryInstance().getMetaData(name, loader, false); if (meta != null) return meta.getDescribedType(); // try the name in the package of the candidate class if (_class != null) { String fullName = _class.getName().substring (0, _class.getName().lastIndexOf('.') + 1) + name; type = toClass(fullName); if (type != null) return type; } // try java.lang type = toClass("java.lang." + name); if (type != null) return type; // try each import if (imports != null && imports.length > 0) { String dotName = "." + name; String importName; for (int i = 0; i < imports.length; i++) { importName = imports[i]; // full class name import if (importName.endsWith(dotName)) type = toClass(importName); // wildcard; strip to package else if (importName.endsWith(".*")) { importName = importName.substring (0, importName.length() - 1); type = toClass(importName + name); } if (type != null) return type; } } return null; } /** * Return the {@link Class} for the given name, or null if name not valid. */ private Class toClass(String name) { if (_loader == null) _loader = _broker.getConfiguration().getClassResolverInstance(). getClassLoader(_class, _broker.getClassLoader()); try { return Strings.toClass(name, _loader); } catch (RuntimeException re) { } catch (NoClassDefFoundError ncdfe) { } return null; } public void assertOpen() { if (_broker != null) _broker.assertOpen(); } public void assertNotReadOnly() { if (_readOnly) throw new InvalidStateException(_loc.get("read-only")); } public void assertNotSerialized() { if (_broker == null) throw new InvalidStateException(_loc.get("serialized")); } /** * Check that a candidate class has been set for the query. */ private void assertCandidateType() { if (_class == null && _storeQuery.requiresCandidateType()) throw new InvalidStateException(_loc.get("no-class")); } /** * Check that we are in a state to be able to perform a bulk operation; * also flush the current modfications if any elements are currently dirty. */ private void assertBulkModify(StoreQuery q, StoreQuery.Executor ex, Object[] params) { _broker.assertActiveTransaction(); if (_startIdx != 0 || _endIdx != Long.MAX_VALUE) throw new UserException(_loc.get("no-modify-range")); if (_resultClass != null) throw new UserException(_loc.get("no-modify-resultclass")); StoreQuery.Range range = new StoreQuery.Range(); ex.getRange(q, params, range); if (range.start != 0 || range.end != Long.MAX_VALUE) throw new UserException(_loc.get("no-modify-range")); } /** * Checks that the passed parameters match the declarations. */ protected void assertParameters(StoreQuery q, StoreQuery.Executor ex, Object[] params) { if (!q.requiresParameterDeclarations() || !isParsedQuery()) return; OrderedMap> paramTypes = ex.getOrderedParameterTypes(q); int typeCount = paramTypes.size(); if (typeCount > params.length) throw new UserException(_loc.get("unbound-params", paramTypes.keySet())); Iterator>> itr = paramTypes.entrySet().iterator(); Map.Entry> entry; for (int i = 0; itr.hasNext(); i++) { entry = itr.next(); if (entry.getValue().isPrimitive() && params[i] == null) throw new UserException(_loc.get("null-primitive-param", entry.getKey())); } } protected void assertParameters(StoreQuery q, StoreQuery.Executor ex, Map params) { if (!q.requiresParameterDeclarations()) return; OrderedMap> paramTypes = ex.getOrderedParameterTypes(q); for (Object actual : params.keySet()) { if (!paramTypes.containsKey(actual)) throw new UserException(_loc.get("unbound-params", actual, paramTypes.keySet())); } for (Object expected : paramTypes.keySet()) { if (!params.containsKey(expected)) throw new UserException(_loc.get("unbound-params", expected, paramTypes.keySet())); } for (Entry> entry : paramTypes.entrySet()) { if (entry.getValue().isPrimitive() && params.get(entry.getKey()) == null) throw new UserException(_loc.get("null-primitive-param", entry.getKey())); } } public String toString() { StringBuilder buf = new StringBuilder(255); buf.append("Query: ").append(super.toString()); buf.append("; candidate class: ").append(_class); buf.append("; query: ").append(_query); return buf.toString(); } /** * Struct of compiled query properties. */ protected static class Compilation implements Serializable { public StoreQuery.Executor memory = null; public StoreQuery.Executor datastore = null; public Object storeData = null; } /** * Struct to hold the unparsed properties associated with a query. */ private static class CompilationKey implements Serializable { public Class queryType = null; public Class candidateType = null; public boolean subclasses = true; public String query = null; public String language = null; public Object storeKey = null; public int hashCode() { int rs = 17; rs = 37 * rs + ((queryType == null) ? 0 : queryType.hashCode()); rs = 37 * rs + ((query == null) ? 0 : query.hashCode()); rs = 37 * rs + ((language == null) ? 0 : language.hashCode()); rs = 37 * rs + ((storeKey == null) ? 0 : storeKey.hashCode()); if (subclasses) rs++; return rs; } public boolean equals(Object other) { if (other == this) return true; if (other == null || other.getClass() != getClass()) return false; CompilationKey key = (CompilationKey) other; if (key.queryType != queryType || !StringUtils.equals(key.query, query) || !StringUtils.equals(key.language, language)) return false; if (key.subclasses != subclasses) return false; if (!ObjectUtils.equals(key.storeKey, storeKey)) return false; // allow either candidate type to be null because it might be // encoded in the query string, but if both are set then they // must be equal return key.candidateType == null || candidateType == null || key.candidateType == candidateType; } } /** * A merged executor executes multiple Queries and returns * a merged result list with the appropriate ordering (if more than * one query needs to be executed). This executor has the following * limitations: *
      *
    • It cannot combine aggregates. *
    • It cannot collate the result lists if ordering is specified and * a result string is given, but does not include the ordering * criteria.
    • *
    • It cannot filter duplicate results from different result lists if * the result is marked distinct. This would require tracking all * previous results, which would interfere with large result set * handling.
    • *
    * * @author Marc Prud'hommeaux * @nojavadoc */ private static class MergedExecutor implements StoreQuery.Executor { private final StoreQuery.Executor[] _executors; public MergedExecutor(StoreQuery.Executor[] executors) { _executors = executors; } public QueryExpressions[] getQueryExpressions() { return _executors[0].getQueryExpressions(); } public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, StoreQuery.Range range) { if (_executors.length == 1) return _executors[0].executeQuery(q, params, range); // use lrs settings if we couldn't take advantage of the start index // so that hopefully the skip to the start will be efficient StoreQuery.Range ropRange = new StoreQuery.Range(0, range.end); ropRange.lrs = range.lrs || (range.start > 0 && q.getContext(). getFetchConfiguration().getFetchBatchSize() >= 0); // execute the query; we cannot use the lower bound of the result // range, but we can take advantage of the upper bound ResultObjectProvider[] rops = new ResultObjectProvider[_executors.length]; for (int i = 0; i < _executors.length; i++) rops[i] = _executors[i].executeQuery(q, params, ropRange); boolean[] asc = _executors[0].getAscending(q); ResultObjectProvider rop; if (asc.length == 0) rop = new MergedResultObjectProvider(rops); else rop = new OrderingMergedResultObjectProvider(rops, asc, _executors, q, params); // if there is a lower bound, wrap in range rop if (range.start != 0) rop = new RangeResultObjectProvider(rop, range.start, range.end); return rop; } public Number executeDelete(StoreQuery q, Object[] params) { long num = 0; for (int i = 0; i < _executors.length; i++) num += _executors[i].executeDelete(q, params).longValue(); return num; } public Number executeUpdate(StoreQuery q, Object[] params) { long num = 0; for (int i = 0; i < _executors.length; i++) num += _executors[i].executeUpdate(q, params).longValue(); return num; } public String[] getDataStoreActions(StoreQuery q, Object[] params, StoreQuery.Range range) { if (_executors.length == 1) return _executors[0].getDataStoreActions(q, params, range); List results = new ArrayList(_executors.length); StoreQuery.Range ropRange = new StoreQuery.Range(0L, range.end); String[] actions; for (int i = 0; i < _executors.length; i++) { actions = _executors[i].getDataStoreActions(q, params,ropRange); if (actions != null && actions.length > 0) results.addAll(Arrays.asList(actions)); } return (String[]) results.toArray(new String[results.size()]); } public void validate(StoreQuery q) { _executors[0].validate(q); } public void getRange(StoreQuery q, Object[] params, StoreQuery.Range range) { _executors[0].getRange(q, params, range); } public Object getOrderingValue(StoreQuery q, Object[] params, Object resultObject, int idx) { // unfortunately, at this point (must be a merged rop containing // other merged rops) we have no idea which executor to extract // the value from return _executors[0].getOrderingValue(q, params, resultObject, idx); } public boolean[] getAscending(StoreQuery q) { return _executors[0].getAscending(q); } public String getAlias(StoreQuery q) { return _executors[0].getAlias(q); } public String[] getProjectionAliases(StoreQuery q) { return _executors[0].getProjectionAliases(q); } public Class getResultClass(StoreQuery q) { return _executors[0].getResultClass(q); } public ResultShape getResultShape(StoreQuery q) { return _executors[0].getResultShape(q); } public Class[] getProjectionTypes(StoreQuery q) { return _executors[0].getProjectionTypes(q); } public boolean isPacking(StoreQuery q) { return _executors[0].isPacking(q); } public ClassMetaData[] getAccessPathMetaDatas(StoreQuery q) { if (_executors.length == 1) return _executors[0].getAccessPathMetaDatas(q); // create set of base class metadatas in access path List metas = null; for (int i = 0; i < _executors.length; i++) metas = Filters.addAccessPathMetaDatas(metas, _executors[i]. getAccessPathMetaDatas(q)); if (metas == null) return StoreQuery.EMPTY_METAS; return (ClassMetaData[]) metas.toArray (new ClassMetaData[metas.size()]); } public boolean isAggregate(StoreQuery q) { if (!_executors[0].isAggregate(q)) return false; // we can't merge aggregates throw new UnsupportedException(_loc.get("merged-aggregate", q.getContext().getCandidateType(), q.getContext().getQueryString())); } public boolean isDistinct(StoreQuery q) { return _executors[0].isDistinct(q); } public int getOperation(StoreQuery q) { return _executors[0].getOperation(q); } public boolean hasGrouping(StoreQuery q) { return _executors[0].hasGrouping(q); } public OrderedMap> getOrderedParameterTypes(StoreQuery q) { return _executors[0].getOrderedParameterTypes(q); } public LinkedMap getParameterTypes(StoreQuery q) { return _executors[0].getParameterTypes(q); } public Object[] toParameterArray(StoreQuery q, Map userParams) { return _executors[0].toParameterArray(q, userParams); } public Map getUpdates(StoreQuery q) { return _executors[0].getUpdates(q); } } /** * Result object provider that packs results before returning them. */ public static class PackingResultObjectProvider implements ResultObjectProvider { private final ResultObjectProvider _delegate; private final ResultPacker _packer; private final int _len; public PackingResultObjectProvider(ResultObjectProvider delegate, ResultPacker packer, int resultLength) { _delegate = delegate; _packer = packer; _len = resultLength; } public boolean supportsRandomAccess() { return _delegate.supportsRandomAccess(); } public void open() throws Exception { _delegate.open(); } public Object getResultObject() throws Exception { Object ob = _delegate.getResultObject(); if (_packer == null && _len == 1) return ((Object[]) ob)[0]; if (_packer == null) return ob; if (_len == 0) return _packer.pack(ob); return _packer.pack((Object[]) ob); } public boolean next() throws Exception { return _delegate.next(); } public boolean absolute(int pos) throws Exception { return _delegate.absolute(pos); } public int size() throws Exception { return _delegate.size(); } public void reset() throws Exception { _delegate.reset(); } public void close() throws Exception { _delegate.close(); } public void handleCheckedException(Exception e) { _delegate.handleCheckedException(e); } public ResultObjectProvider getDelegate() { return _delegate; } } /** * Result list that removes itself from the query's open result list * when it is closed. Public for testing. */ public class RemoveOnCloseResultList implements ResultList { private final ResultList _res; public RemoveOnCloseResultList(ResultList res) { _res = res; } public ResultList getDelegate() { return _res; } public boolean isProviderOpen() { return _res.isProviderOpen(); } public Object getUserObject() { return _res.getUserObject(); } public void setUserObject(Object opaque) { _res.setUserObject(opaque); } public boolean isClosed() { return _res.isClosed(); } public void close() { close(true); } public void close(boolean remove) { if (isClosed()) return; _res.close(); if (!remove) return; lock(); try { // don't use standard _resultLists.remove method b/c relies on // collection equality, which relies on element equality, which // means we end up traversing entire result lists! for (Iterator itr = _resultLists.iterator(); itr.hasNext();) { if (itr.next() == this) { itr.remove(); break; } } } finally { unlock(); } } public int size() { return _res.size(); } public boolean isEmpty() { return _res.isEmpty(); } public boolean contains(Object o) { return _res.contains(o); } public Iterator iterator() { return _res.iterator(); } public Object[] toArray() { return _res.toArray(); } public Object[] toArray(Object[] a) { return _res.toArray(a); } public boolean add(Object o) { return _res.add(o); } public boolean remove(Object o) { return _res.remove(o); } public boolean containsAll(Collection c) { return _res.containsAll(c); } public boolean addAll(Collection c) { return _res.addAll(c); } public boolean addAll(int idx, Collection c) { return _res.addAll(idx, c); } public boolean removeAll(Collection c) { return _res.removeAll(c); } public boolean retainAll(Collection c) { return _res.retainAll(c); } public void clear() { _res.clear(); } public Object get(int idx) { return _res.get(idx); } public Object set(int idx, Object o) { return _res.set(idx, o); } public void add(int idx, Object o) { _res.add(idx, o); } public Object remove(int idx) { return _res.remove(idx); } public int indexOf(Object o) { return _res.indexOf(o); } public int lastIndexOf(Object o) { return _res.lastIndexOf(o); } public ListIterator listIterator() { return _res.listIterator(); } public ListIterator listIterator(int idx) { return _res.listIterator(idx); } public List subList(int start, int end) { return _res.subList(start, end); } public boolean equals(Object o) { return _res.equals(o); } public int hashCode() { return _res.hashCode(); } public String toString () { return _res.toString (); } public Object writeReplace () { return _res; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FinderQuery.java0000644000000000000000000000356212133327272026400 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * A finder query is a query for an instance of a class by its primary key. * A finder query is parameterized by the type of key K, type of value V and * type of result R. * * @author Pinaki Poddar * * @since 2.0.0 * */ public interface FinderQuery { /** * Gets the identifier of this receiver. * */ public K getIdentifier(); /** * Gets the value to which this receiver delegates its execution. * * @return */ public V getDelegate(); /** * Execute the query for a given instance. * * @param sm the StateManager for a given instance carrying the primary key * values. * @param store the data store against which the query is to be executed. * @param fetch fetch parameters * * @return the result of execution. * */ public R execute(OpenJPAStateManager sm, StoreManager store, FetchConfiguration fetch); /** * Gets the query string. * */ public String getQueryString(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java0000644000000000000000000054045412133327272026217 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Modifier; import java.security.AccessController; import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.ReentrantLock; import javax.transaction.Status; import javax.transaction.Synchronization; import org.apache.commons.collections.iterators.IteratorChain; import org.apache.commons.collections.map.IdentityMap; import org.apache.commons.collections.map.LinkedMap; import org.apache.commons.collections.set.MapBackedSet; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.Compatibility; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.datacache.QueryCache; import org.apache.openjpa.datacache.TypesChangedEvent; import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.Reflection; import org.apache.openjpa.event.LifecycleEvent; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.event.RemoteCommitEventManager; import org.apache.openjpa.event.TransactionEvent; import org.apache.openjpa.event.TransactionEventManager; import org.apache.openjpa.instrumentation.InstrumentationManager; import org.apache.openjpa.kernel.exps.ExpressionParser; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.ReferenceHashMap; import org.apache.openjpa.lib.util.ReferenceHashSet; import org.apache.openjpa.lib.util.ReferenceMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.meta.SequenceMetaData; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.meta.ValueStrategies; import org.apache.openjpa.util.ApplicationIds; import org.apache.openjpa.util.CallbackException; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.NoTransactionException; import org.apache.openjpa.util.ObjectExistsException; import org.apache.openjpa.util.ObjectId; import org.apache.openjpa.util.ObjectNotFoundException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.OptimisticException; import org.apache.openjpa.util.RuntimeExceptionTranslator; import org.apache.openjpa.util.StoreException; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.UserException; import org.apache.openjpa.util.WrappedException; import org.apache.openjpa.validation.ValidatingLifecycleEventManager; /** * Concrete {@link Broker}. The broker handles object-level behavior, * but leaves all interaction with the data store to a {@link StoreManager} * that must be supplied at initialization. * * @author Abe White */ @SuppressWarnings("serial") public class BrokerImpl implements Broker, FindCallbacks, Cloneable, Serializable { /** * Incremental flush. */ protected static final int FLUSH_INC = 0; /** * Flush in preparation of commit. */ protected static final int FLUSH_COMMIT = 1; /** * Flush to check consistency of cache, then immediately rollback changes. */ protected static final int FLUSH_ROLLBACK = 2; /** * Run persistence-by-reachability and other flush-time operations without * accessing the database. */ protected static final int FLUSH_LOGICAL = 3; static final int STATUS_INIT = 0; static final int STATUS_TRANSIENT = 1; static final int STATUS_OID_ASSIGN = 2; static final int STATUS_COMMIT_NEW = 3; private static final int FLAG_ACTIVE = 2 << 0; private static final int FLAG_STORE_ACTIVE = 2 << 1; private static final int FLAG_CLOSE_INVOKED = 2 << 2; private static final int FLAG_PRESTORING = 2 << 3; private static final int FLAG_DEREFDELETING = 2 << 4; private static final int FLAG_FLUSHING = 2 << 5; private static final int FLAG_STORE_FLUSHING = 2 << 6; private static final int FLAG_FLUSHED = 2 << 7; private static final int FLAG_FLUSH_REQUIRED = 2 << 8; private static final int FLAG_REMOTE_LISTENER = 2 << 9; private static final int FLAG_RETAINED_CONN = 2 << 10; private static final int FLAG_TRANS_ENDING = 2 << 11; private static final Object[] EMPTY_OBJECTS = new Object[0]; private String _connectionFactoryName = ""; private String _connectionFactory2Name = ""; private static final Localizer _loc = Localizer.forPackage(BrokerImpl.class); // the store manager in use; this may be a decorator such as a // data cache store manager around the native store manager private transient DelegatingStoreManager _store = null; private FetchConfiguration _fc = null; private String _user = null; private String _pass = null; // these must be rebuilt by the facade layer during its deserialization private transient Log _log = null; private transient Compatibility _compat = null; private transient ManagedRuntime _runtime = null; private transient LockManager _lm = null; private transient InverseManager _im = null; private transient ReentrantLock _lock = null; private transient OpCallbacks _call = null; private transient RuntimeExceptionTranslator _extrans = null; private transient InstrumentationManager _instm = null; // ref to producing factory and configuration private transient AbstractBrokerFactory _factory = null; private transient OpenJPAConfiguration _conf = null; private transient MetaDataRepository _repo = null; // cache class loader associated with the broker private transient ClassLoader _loader = null; // user state private Synchronization _sync = null; private Map _userObjects = null; // managed object caches private ManagedCache _cache = null; private TransactionalCache _transCache = null; private Set _transAdditions = null; private Set _derefCache = null; private Set _derefAdditions = null; // these are used for method-internal state only private transient Map _loading = null; private transient Set _operating = null; private transient boolean _operatingDirty = true; private Set> _persistedClss = null; private Set> _updatedClss = null; private Set> _deletedClss = null; private Set _pending = null; private int findAllDepth = 0; // track instances that become transactional after the first savepoint // (the first uses the transactional cache) private Set _savepointCache = null; private LinkedMap _savepoints = null; private transient SavepointManager _spm = null; // track open queries and extents so we can free their resources on close private transient ReferenceHashSet _queries = null; private transient ReferenceHashSet _extents = null; // track operation stack depth. Transient because operations cannot // span serialization. private transient int _operationCount = 0; // options private boolean _nontransRead = false; private boolean _nontransWrite = false; private boolean _retainState = false; private int _autoClear = CLEAR_DATASTORE; private int _restoreState = RESTORE_IMMUTABLE; private boolean _optimistic = false; private boolean _ignoreChanges = false; private boolean _multithreaded = false; private boolean _managed = false; private boolean _syncManaged = false; private int _connRetainMode = CONN_RETAIN_DEMAND; private boolean _evictDataCache = false; private boolean _populateDataCache = true; private boolean _largeTransaction = false; private int _autoDetach = 0; private int _detachState = DETACH_LOADED; private boolean _detachedNew = true; private boolean _orderDirty = false; private boolean _cachePreparedQuery = true; private boolean _cacheFinderQuery = true; private boolean _suppressBatchOLELogging = false; private boolean _allowReferenceToSiblingContext = false; private boolean _postLoadOnMerge = false; // status private int _flags = 0; // this is not in status because it should not be serialized private transient boolean _isSerializing = false; // transient because closed brokers can't be serialized private transient boolean _closed = false; private transient RuntimeException _closedException = null; // event managers private TransactionEventManager _transEventManager = null; private int _transCallbackMode = 0; private LifecycleEventManager _lifeEventManager = null; private int _lifeCallbackMode = 0; private transient DetachManagerLite _dmLite; private transient boolean _initializeWasInvoked = false; private transient boolean _fromWriteBehindCallback = false; private LinkedList _fcs; // Set of supported property keys. The keys in this set correspond to bean-style setter methods // that can be set by reflection. The keys are not qualified by any prefix. private static Set _supportedPropertyNames; static { _supportedPropertyNames = new HashSet(); _supportedPropertyNames.addAll(Arrays.asList(new String[] { "AutoClear", "AutoDetach", "CacheFinderQuery", "CachePreparedQuery", "DetachedNew", "DetachState", "EvictFromDataCache", "IgnoreChanges", "LifecycleListenerCallbackMode", "Multithreaded", "NontransactionalRead", "NontransactionalWrite", "Optimistic", "PopulateDataCache", "RestoreState", "RetainState", })); } private boolean _printParameters = false; private static final String PRINT_PARAMETERS_CONFIG_STR = "PrintParameters"; /** * Set the persistence manager's authentication. This is the first * method called after construction. * * @param user the username this broker represents; used when pooling * brokers to make sure that a request to the factory for * a connection with an explicit user is delegated to a suitable broker * @param pass the password for the above user */ public void setAuthentication(String user, String pass) { _user = user; _pass = pass; } /** * Initialize the persistence manager. This method is called * automatically by the factory before use. * * @param factory the factory used to create this broker * @param sm a concrete StoreManager implementation to * handle interaction with the data store * @param managed the transaction mode * @param connMode the connection retain mode * @param fromDeserialization whether this call happened because of a * deserialization or creation of a new BrokerImpl. */ public void initialize(AbstractBrokerFactory factory, DelegatingStoreManager sm, boolean managed, int connMode, boolean fromDeserialization) { initialize(factory, sm, managed, connMode, fromDeserialization, false); } public void initialize(AbstractBrokerFactory factory, DelegatingStoreManager sm, boolean managed, int connMode, boolean fromDeserialization, boolean fromWriteBehindCallback) { _fromWriteBehindCallback = fromWriteBehindCallback; _initializeWasInvoked = true; _loader = AccessController.doPrivileged( J2DoPrivHelper.getContextClassLoaderAction()); if (!fromDeserialization){ _conf = factory.getConfiguration(); _repo = _conf.getMetaDataRepositoryInstance(); } _compat = _conf.getCompatibilityInstance(); _factory = factory; _log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); if (!fromDeserialization) _cache = new ManagedCache(this); // Force creation of a new operating set _operatingDirty = true; initializeOperatingSet(); _connRetainMode = connMode; _managed = managed; if (managed) _runtime = _conf.getManagedRuntimeInstance(); else _runtime = new LocalManagedRuntime(this); if (!fromDeserialization) { _lifeEventManager = _conf.getLifecycleEventManagerInstance(); _transEventManager = new TransactionEventManager(); int cmode = _repo.getMetaDataFactory().getDefaults().getCallbackMode(); setLifecycleListenerCallbackMode(cmode); setTransactionListenerCallbackMode(cmode); // setup default options _factory.configureBroker(this); } // make sure to do this after configuring broker so that store manager // can look to broker configuration; we set both store and lock managers // before initializing them because they may each try to access the // other in their initialization _store = sm; _lm = _conf.newLockManagerInstance(); _im = _conf.newInverseManagerInstance(); _spm = _conf.getSavepointManagerInstance(); _store.setContext(this); _lm.setContext(this); if (_connRetainMode == CONN_RETAIN_ALWAYS) retainConnection(); if (!fromDeserialization) { _fc = _store.newFetchConfiguration(); _fc.setContext(this); } _instm = _conf.getInstrumentationManagerInstance(); if (_instm != null) { _instm.start(InstrumentationLevel.BROKER, this); } _dmLite = new DetachManagerLite(_conf); _printParameters = Boolean.parseBoolean(Configurations.parseProperties(_conf.getConnectionFactoryProperties()).getProperty( PRINT_PARAMETERS_CONFIG_STR, "false")); // synch with the global transaction in progress, if any if (_factory.syncWithManagedTransaction(this, false)) beginInternal(); } @SuppressWarnings("unchecked") private void initializeOperatingSet() { if(_operatingDirty) { _operatingDirty = false; _operating = MapBackedSet.decorate(new IdentityHashMap()); } } /** * Gets the unmodifiable set of instances being operated. */ protected Set getOperatingSet() { return Collections.unmodifiableSet(_operating); } public Object clone() throws CloneNotSupportedException { if (_initializeWasInvoked) throw new CloneNotSupportedException(); else { return super.clone(); } } /** * Create a {@link Map} to be used for the primary managed object cache. * Maps oids to state managers. By default, this creates a * {@link ReferenceMap} with soft values. */ protected Map newManagedObjectCache() { return new ReferenceHashMap(ReferenceMap.HARD, ReferenceMap.SOFT); } ////////////////////////////////// // Implementation of StoreContext ////////////////////////////////// public Broker getBroker() { return this; } ////////////// // Properties ////////////// public void setImplicitBehavior(OpCallbacks call, RuntimeExceptionTranslator ex) { if (_call == null) _call = call; if (_extrans == null) _extrans = ex; } RuntimeExceptionTranslator getInstanceExceptionTranslator() { return (_operationCount == 0) ? _extrans : null; } public BrokerFactory getBrokerFactory() { return _factory; } public OpenJPAConfiguration getConfiguration() { return _conf; } public FetchConfiguration getFetchConfiguration() { return _fc; } public FetchConfiguration pushFetchConfiguration() { return pushFetchConfiguration(null); } public FetchConfiguration pushFetchConfiguration(FetchConfiguration fc) { if (_fcs == null) _fcs = new LinkedList(); _fcs.add(_fc); _fc = (FetchConfiguration) (fc != null ? fc : _fc).clone(); return _fc; } public void popFetchConfiguration() { if (_fcs == null || _fcs.isEmpty()) throw new UserException( _loc.get("fetch-configuration-stack-empty")); _fc = _fcs.removeLast(); } public int getConnectionRetainMode() { return _connRetainMode; } public boolean isManaged() { return _managed; } public ManagedRuntime getManagedRuntime() { return _runtime; } public ClassLoader getClassLoader() { return _loader; } public DelegatingStoreManager getStoreManager() { return _store; } public LockManager getLockManager() { return _lm; } public InverseManager getInverseManager() { return _im; } public String getConnectionUserName() { return _user; } public String getConnectionPassword() { return _pass; } public boolean getMultithreaded() { return _multithreaded; } public void setMultithreaded(boolean multithreaded) { assertOpen(); _multithreaded = multithreaded; if (multithreaded && _lock == null) _lock = new ReentrantLock(); else if (!multithreaded) _lock = null; } public boolean getIgnoreChanges() { return _ignoreChanges; } public void setIgnoreChanges(boolean val) { assertOpen(); _ignoreChanges = val; } public boolean getNontransactionalRead() { return _nontransRead; } public void setNontransactionalRead(boolean val) { assertOpen(); if ((_flags & FLAG_PRESTORING) != 0) throw new UserException(_loc.get("illegal-op-in-prestore")); // make sure the runtime supports it if (val && !_conf.supportedOptions().contains (OpenJPAConfiguration.OPTION_NONTRANS_READ)) throw new UnsupportedException(_loc.get ("nontrans-read-not-supported")); _nontransRead = val; } public boolean getNontransactionalWrite() { return _nontransWrite; } public void setNontransactionalWrite(boolean val) { assertOpen(); if ((_flags & FLAG_PRESTORING) != 0) throw new UserException(_loc.get("illegal-op-in-prestore")); _nontransWrite = val; } public boolean getOptimistic() { return _optimistic; } public void setOptimistic(boolean val) { assertOpen(); if ((_flags & FLAG_ACTIVE) != 0) throw new InvalidStateException(_loc.get("trans-active", "Optimistic")); // make sure the runtime supports it if (val && !_conf.supportedOptions().contains(OpenJPAConfiguration.OPTION_OPTIMISTIC)) throw new UnsupportedException(_loc.get ("optimistic-not-supported")); _optimistic = val; } public int getRestoreState() { return _restoreState; } public void setRestoreState(int val) { assertOpen(); if ((_flags & FLAG_ACTIVE) != 0) throw new InvalidStateException(_loc.get("trans-active", "Restore")); _restoreState = val; } public boolean getRetainState() { return _retainState; } public void setRetainState(boolean val) { assertOpen(); if ((_flags & FLAG_PRESTORING) != 0) throw new UserException(_loc.get("illegal-op-in-prestore")); _retainState = val; } public int getAutoClear() { return _autoClear; } public void setAutoClear(int val) { assertOpen(); _autoClear = val; } public int getAutoDetach() { return _autoDetach; } /** * Sets automatic detachment option. *
    * If the given flag contains {@link AutoDetach#DETACH_NONE} option, * then no other option can be specified. */ public void setAutoDetach(int detachFlags) { assertOpen(); assertAutoDetachValue(detachFlags); _autoDetach = detachFlags; } public void setAutoDetach(int detachFlag, boolean on) { assertOpen(); assertAutoDetachValue(on ? _autoDetach | detachFlag : _autoDetach & ~detachFlag); if (on) _autoDetach |= detachFlag; else _autoDetach &= ~detachFlag; } public int getDetachState() { return _detachState; } public void setDetachState(int mode) { assertOpen(); _detachState = mode; } public boolean isDetachedNew() { return _detachedNew; } public void setDetachedNew(boolean isNew) { assertOpen(); _detachedNew = isNew; } public boolean getSyncWithManagedTransactions() { return _syncManaged; } public void setSyncWithManagedTransactions(boolean sync) { assertOpen(); _syncManaged = sync; } public boolean getEvictFromDataCache() { return _evictDataCache; } public void setEvictFromDataCache(boolean evict) { assertOpen(); _evictDataCache = evict; } public boolean getPopulateDataCache() { return _populateDataCache; } public void setPopulateDataCache(boolean cache) { assertOpen(); _populateDataCache = cache; } public boolean isTrackChangesByType() { return _largeTransaction; } public void setTrackChangesByType(boolean largeTransaction) { assertOpen(); _largeTransaction = largeTransaction; } public Object getUserObject(Object key) { beginOperation(false); try { return (_userObjects == null) ? null : _userObjects.get(key); } finally { endOperation(); } } public Object putUserObject(Object key, Object val) { beginOperation(false); try { if (val == null) return (_userObjects == null) ? null : _userObjects.remove(key); if (_userObjects == null) _userObjects = new HashMap(); return _userObjects.put(key, val); } finally { endOperation(); } } /** * Get current configuration property values used by this instance. * This values are combination of the current configuration values * overwritten by values maintained by this instance such as * Optimistic flag. */ public Map getProperties() { Map props = _conf.toProperties(true); for (String s : _supportedPropertyNames) { props.put("openjpa." + s, Reflection.getValue(this, s, true)); } return props; } /** * Gets the property names that can be used to corresponding setter methods of this receiver * to set its value. */ public Set getSupportedProperties() { Set keys = _conf.getPropertyKeys(); for (String s : _supportedPropertyNames) keys.add("openjpa." + s); return keys; } // //////// // Events // //////// public void addLifecycleListener(Object listener, Class[] classes) { beginOperation(false); try { _lifeEventManager.addListener(listener, classes); } finally { endOperation(); } } public void removeLifecycleListener(Object listener) { beginOperation(false); try { _lifeEventManager.removeListener(listener); } finally { endOperation(); } } public int getLifecycleListenerCallbackMode() { return _lifeCallbackMode; } public void setLifecycleListenerCallbackMode(int mode) { beginOperation(false); try { _lifeCallbackMode = mode; _lifeEventManager.setFailFast((mode & CALLBACK_FAIL_FAST) != 0); } finally { endOperation(); } } /** * Give state managers access to the lifecycle event manager. */ public LifecycleEventManager getLifecycleEventManager() { return _lifeEventManager; } /** * Fire given lifecycle event, handling any exceptions appropriately. * * @return whether events are being processed at this time */ boolean fireLifecycleEvent(Object src, Object related, ClassMetaData meta, int eventType) { if (_lifeEventManager == null) return false; if (!_lifeEventManager.isActive(meta)) return false; lock(); Exception[] exs; try { exs = _lifeEventManager.fireEvent(src, related, meta, eventType); } finally { unlock(); } handleCallbackExceptions(exs, _lifeCallbackMode); return true; } /** * Take actions on callback exceptions depending on callback mode. */ private void handleCallbackExceptions(Exception[] exceps, int mode) { if (exceps.length == 0 || (mode & CALLBACK_IGNORE) != 0) return; OpenJPAException ce; if (exceps.length == 1) { // If the exception is already a wrapped exception throw the // exception instead of wrapping it with a callback exception if (exceps[0] instanceof WrappedException) throw (WrappedException)exceps[0]; else ce = new CallbackException(exceps[0]); } else { ce = new CallbackException(_loc.get("callback-err")). setNestedThrowables(exceps); } if ((mode & CALLBACK_ROLLBACK) != 0 && (_flags & FLAG_ACTIVE) != 0) { ce.setFatal(true); setRollbackOnlyInternal(ce); } if ((mode & CALLBACK_LOG) != 0 && _log.isWarnEnabled()) _log.warn(ce); if ((mode & CALLBACK_RETHROW) != 0) throw ce; } public void addTransactionListener(Object tl) { beginOperation(false); try { _transEventManager.addListener(tl); if (tl instanceof RemoteCommitEventManager) _flags |= FLAG_REMOTE_LISTENER; } finally { endOperation(); } } public void removeTransactionListener(Object tl) { beginOperation(false); try { if (_transEventManager.removeListener(tl) && (tl instanceof RemoteCommitEventManager)) _flags &= ~FLAG_REMOTE_LISTENER; } finally { endOperation(); } } public Collection getTransactionListeners() { return _transEventManager.getListeners(); } public int getTransactionListenerCallbackMode() { return _transCallbackMode; } public void setTransactionListenerCallbackMode(int mode) { beginOperation(false); try { _transCallbackMode = mode; _transEventManager.setFailFast((mode & CALLBACK_FAIL_FAST) != 0); } finally { endOperation(); } } /** * Fire given transaction event, handling any exceptions appropriately. */ private void fireTransactionEvent(TransactionEvent trans) { if (_transEventManager != null && _transEventManager.hasListeners()) handleCallbackExceptions(_transEventManager.fireEvent(trans), _transCallbackMode); } /** * Set whether this Broker will generate verbose optimistic lock exceptions when batching * operations. Defaults to true. * * @param b */ public void setSuppressBatchOLELogging(boolean b) { _suppressBatchOLELogging = b; } /** * Return whether this Broker will generate verbose optimistic lock exceptions when batching * operations. */ public boolean getSuppressBatchOLELogging() { return _suppressBatchOLELogging; } /////////// // Lookups /////////// public Object find(Object oid, boolean validate, FindCallbacks call) { int flags = OID_COPY | OID_ALLOW_NEW | OID_NODELETED; if (!validate) flags |= OID_NOVALIDATE; return find(oid, _fc, null, null, flags, call); } public Object find(Object oid, FetchConfiguration fetch, BitSet exclude, Object edata, int flags) { return find(oid, fetch, exclude, edata, flags, null); } /** * Internal finder. */ protected Object find(Object oid, FetchConfiguration fetch, BitSet exclude, Object edata, int flags, FindCallbacks call) { if (call == null) call = this; oid = call.processArgument(oid); if (oid == null) { if ((flags & OID_NOVALIDATE) == 0) throw new ObjectNotFoundException(_loc.get("null-oid")); return call.processReturn(oid, null); } if (fetch == null) fetch = _fc; beginOperation(true); try { assertNontransactionalRead(); // cached instance? StateManagerImpl sm = getStateManagerImplById(oid, (flags & OID_ALLOW_NEW) != 0 || hasFlushed()); if (sm != null) { if (!requiresLoad(sm, true, fetch, edata, flags)) return call.processReturn(oid, sm); if (!sm.isLoading()) { // make sure all the configured fields are loaded; do this // after making instance transactional for locking if (!sm.isTransactional() && useTransactionalState(fetch)) sm.transactional(); boolean loaded; try { loaded = sm.load(fetch, StateManagerImpl.LOAD_FGS, exclude, edata, false); } catch (ObjectNotFoundException onfe) { if ((flags & OID_NODELETED) != 0 || (flags & OID_NOVALIDATE) != 0) throw onfe; return call.processReturn(oid, null); } // if no data needed to be loaded and the user wants to // validate, just make sure the object exists if (!loaded && (flags & OID_NOVALIDATE) == 0 && _compat.getValidateTrueChecksStore() && !sm.isTransactional() && !_store.exists(sm, edata)) { if ((flags & OID_NODELETED) == 0) return call.processReturn(oid, null); throw new ObjectNotFoundException(_loc.get ("del-instance", sm.getManagedInstance(), oid)). setFailedObject(sm.getManagedInstance()); } } // since the object was cached, we may need to upgrade lock // if current level is higher than level of initial load if ((_flags & FLAG_ACTIVE) != 0) { int level = fetch.getReadLockLevel(); _lm.lock(sm, level, fetch.getLockTimeout(), edata); sm.readLocked(level, fetch.getWriteLockLevel()); } return call.processReturn(oid, sm); } // if there's no cached sm for a new/transient id type, we // it definitely doesn't exist if (oid instanceof StateManagerId) return call.processReturn(oid, null); // initialize a new state manager for the datastore instance sm = newStateManagerImpl(oid, (flags & OID_COPY) != 0); boolean load = requiresLoad(sm, false, fetch, edata, flags); sm = initialize(sm, load, fetch, edata); if (sm == null) { if ((flags & OID_NOVALIDATE) != 0) throw new ObjectNotFoundException(oid); return call.processReturn(oid, null); } // make sure all configured fields were loaded if (load) { try { sm.load(fetch, StateManagerImpl.LOAD_FGS, exclude, edata, false); } catch (ObjectNotFoundException onfe) { if ((flags & OID_NODELETED) != 0 || (flags & OID_NOVALIDATE) != 0) throw onfe; return call.processReturn(oid, null); } } return call.processReturn(oid, sm); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } /** * Initialize a newly-constructed state manager. */ protected StateManagerImpl initialize(StateManagerImpl sm, boolean load, FetchConfiguration fetch, Object edata) { if (!load) { sm.initialize(sm.getMetaData().getDescribedType(), PCState.HOLLOW); } else { PCState state = (useTransactionalState(fetch)) ? PCState.PCLEAN : PCState.PNONTRANS; sm.setLoading(true); try { if (!_store.initialize(sm, state, fetch, edata)) return null; } finally { sm.setLoading(false); } } return sm; } public Object[] findAll(Collection oids, boolean validate, FindCallbacks call) { int flags = OID_COPY | OID_ALLOW_NEW | OID_NODELETED; if (!validate) flags |= OID_NOVALIDATE; return findAll(oids, _fc, null, null, flags, call); } public Object[] findAll(Collection oids, FetchConfiguration fetch, BitSet exclude, Object edata, int flags) { return findAll(oids, fetch, exclude, edata, flags, null); } /** * Internal finder. */ protected Object[] findAll(Collection oids, FetchConfiguration fetch, BitSet exclude, Object edata, int flags, FindCallbacks call) { findAllDepth ++; // throw any exceptions for null oids up immediately if (oids == null) throw new NullPointerException("oids == null"); if ((flags & OID_NOVALIDATE) != 0 && oids.contains(null)) throw new UserException(_loc.get("null-oids")); // we have to use a map of oid->sm rather than a simple // array, so that we make sure not to create multiple sms for equivalent // oids if the user has duplicates in the given array if (_loading == null) _loading = new HashMap((int) (oids.size() * 1.33 + 1)); if (call == null) call = this; if (fetch == null) fetch = _fc; beginOperation(true); try { assertNontransactionalRead(); // collection of state managers to pass to store manager List load = null; StateManagerImpl sm; boolean initialized; boolean transState = useTransactionalState(fetch); Object obj, oid; int idx = 0; for (Iterator itr = oids.iterator(); itr.hasNext(); idx++) { // if we've already seen this oid, skip repeats obj = itr.next(); oid = call.processArgument(obj); if (oid == null || _loading.containsKey(obj)) continue; // if we don't have a cached instance or it is not transactional // and is hollow or we need to validate, load it sm = getStateManagerImplById(oid, (flags & OID_ALLOW_NEW) != 0 || hasFlushed()); initialized = sm != null; if (!initialized) sm = newStateManagerImpl(oid, (flags & OID_COPY) != 0); _loading.put(obj, sm); if (requiresLoad(sm, initialized, fetch, edata, flags)) { transState = transState || useTransactionalState(fetch); if (initialized && !sm.isTransactional() && transState) sm.transactional(); if (load == null) load = new ArrayList(oids.size() - idx); load.add(sm); } else if (!initialized) sm.initialize(sm.getMetaData().getDescribedType(), PCState.HOLLOW); } // pass all state managers in need of loading or validation to the // store manager if (load != null) { PCState state = (transState) ? PCState.PCLEAN : PCState.PNONTRANS; Collection failed = _store.loadAll(load, state, StoreManager.FORCE_LOAD_NONE, fetch, edata); // set failed instances to null if (failed != null && !failed.isEmpty()) { if ((flags & OID_NOVALIDATE) != 0) throw newObjectNotFoundException(failed); for (Iterator itr = failed.iterator(); itr.hasNext();) _loading.put(itr.next(), null); } } // create results array; make sure all configured fields are // loaded in each instance Object[] results = new Object[oids.size()]; boolean active = (_flags & FLAG_ACTIVE) != 0; int level = fetch.getReadLockLevel(); idx = 0; for (Iterator itr = oids.iterator(); itr.hasNext(); idx++) { oid = itr.next(); sm = _loading.get(oid); if (sm != null && requiresLoad(sm, true, fetch, edata, flags)) { try { sm.load(fetch, StateManagerImpl.LOAD_FGS, exclude, edata, false); if (active) { _lm.lock(sm, level, fetch.getLockTimeout(), edata); sm.readLocked(level, fetch.getWriteLockLevel()); } } catch (ObjectNotFoundException onfe) { if ((flags & OID_NODELETED) != 0 || (flags & OID_NOVALIDATE) != 0) throw onfe; sm = null; } } results[idx] = call.processReturn(oid, sm); } return results; } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { findAllDepth--; if (findAllDepth == 0) _loading = null; endOperation(); } } public boolean isLoading(Object o) { if(_loading == null ) { return false; } return _loading.containsKey(o); } private boolean hasFlushed() { return (_flags & FLAG_FLUSHED) != 0; } /** * Return whether the given instance needs loading before being returned * to the user. */ private boolean requiresLoad(OpenJPAStateManager sm, boolean initialized, FetchConfiguration fetch, Object edata, int flags) { if (!fetch.requiresLoad()) return false; if ((flags & OID_NOVALIDATE) == 0) return true; if (edata != null) // take advantage of existing result return true; if (initialized && sm.getPCState() != PCState.HOLLOW) return false; if (!initialized && sm.getMetaData().getPCSubclasses().length > 0) return true; return !_compat.getValidateFalseReturnsHollow(); } /** * Return whether to use a transactional state. */ private boolean useTransactionalState(FetchConfiguration fetch) { return (_flags & FLAG_ACTIVE) != 0 && (!_optimistic || _autoClear == CLEAR_ALL || fetch.getReadLockLevel() != LOCK_NONE); } public Object findCached(Object oid, FindCallbacks call) { if (call == null) call = this; oid = call.processArgument(oid); if (oid == null) return call.processReturn(oid, null); beginOperation(true); try { StateManagerImpl sm = getStateManagerImplById(oid, true); return call.processReturn(oid, sm); } finally { endOperation(); } } public Class getObjectIdType(Class cls) { if (cls == null) return null; beginOperation(false); try { ClassMetaData meta = _repo.getMetaData(cls, _loader, false); if (meta == null || meta.getIdentityType() == ClassMetaData.ID_UNKNOWN) return null; if (meta.getIdentityType() == ClassMetaData.ID_APPLICATION) return meta.getObjectIdType(); return _store.getDataStoreIdType(meta); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } public Object newObjectId(Class cls, Object val) { if (val == null) return null; beginOperation(false); try { ClassMetaData meta = _repo.getMetaData(cls, _loader, true); switch (meta.getIdentityType()) { case ClassMetaData.ID_DATASTORE: // delegate to store manager for datastore ids if (val instanceof String && ((String) val).startsWith(StateManagerId.STRING_PREFIX)) return new StateManagerId((String) val); return _store.newDataStoreId(val, meta); case ClassMetaData.ID_APPLICATION: if (ImplHelper.isAssignable(meta.getObjectIdType(), val.getClass())) { if (!meta.isOpenJPAIdentity() && meta.isObjectIdTypeShared()) return new ObjectId(cls, val); return val; } // stringified app id? if (val instanceof String && !_conf.getCompatibilityInstance(). getStrictIdentityValues() && !Modifier.isAbstract(cls.getModifiers())) return PCRegistry.newObjectId(cls, (String) val); Object[] arr = (val instanceof Object[]) ? (Object[]) val : new Object[]{ val }; return ApplicationIds.fromPKValues(arr, meta); default: throw new UserException(_loc.get("meta-unknownid", cls)); } } catch (IllegalArgumentException iae) { // OPENJPA-365 throw new UserException(_loc.get("bad-id-value", val, val.getClass().getName(), cls)).setCause(iae); } catch (OpenJPAException ke) { throw ke; } catch (ClassCastException cce) { throw new UserException(_loc.get("bad-id-value", val, val.getClass().getName(), cls)).setCause(cce); } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } /** * Create a new state manager for the given oid. */ private StateManagerImpl newStateManagerImpl(Object oid, boolean copy) { // see if we're in the process of loading this oid in a loadAll call StateManagerImpl sm; if (_loading != null) { sm = _loading.get(oid); if (sm != null && sm.getPersistenceCapable() == null) return sm; } // find metadata for the oid Class pcType = _store.getManagedType(oid); ClassMetaData meta; if (pcType != null) meta = _repo.getMetaData(pcType, _loader, true); else meta = _repo.getMetaData(oid, _loader, true); // copy the oid if needed if (copy && _compat.getCopyObjectIds()) { if (meta.getIdentityType() == ClassMetaData.ID_APPLICATION) oid = ApplicationIds.copy(oid, meta); else if (meta.getIdentityType() == ClassMetaData.ID_UNKNOWN) throw new UserException(_loc.get("meta-unknownid", meta)); else oid = _store.copyDataStoreId(oid, meta); } sm = newStateManagerImpl(oid, meta); sm.setObjectId(oid); return sm; } /** * Create a state manager for the given oid and metadata. */ protected StateManagerImpl newStateManagerImpl(Object oid, ClassMetaData meta) { return new StateManagerImpl(oid, meta, this); } /////////////// // Transaction /////////////// public void begin() { beginOperation(true); try { if ((_flags & FLAG_ACTIVE) != 0) throw new InvalidStateException(_loc.get("active")); _factory.syncWithManagedTransaction(this, true); beginInternal(); } finally { endOperation(); } } /** * Notify the store manager of a transaction. */ private void beginInternal() { try { beginStoreManagerTransaction(_optimistic); _flags |= FLAG_ACTIVE; // start locking if (!_optimistic) { _fc.setReadLockLevel(_conf.getReadLockLevelConstant()); _fc.setWriteLockLevel(_conf.getWriteLockLevelConstant()); _fc.setLockTimeout(_conf.getLockTimeout()); } _lm.beginTransaction(); if (_transEventManager.hasBeginListeners()) fireTransactionEvent(new TransactionEvent(this, TransactionEvent.AFTER_BEGIN, null, null, null, null)); } catch (OpenJPAException ke) { // if we already started the transaction, don't let it commit if ((_flags & FLAG_ACTIVE) != 0) setRollbackOnlyInternal(ke); throw ke.setFatal(true); } catch (RuntimeException re) { // if we already started the transaction, don't let it commit if ((_flags & FLAG_ACTIVE) != 0) setRollbackOnlyInternal(re); throw new StoreException(re).setFatal(true); } if (_pending != null) { StateManagerImpl sm; for (Iterator it = _pending.iterator(); it.hasNext();) { sm = (StateManagerImpl) it.next(); sm.transactional(); if (sm.isDirty()) setDirty(sm, true); } _pending = null; } } public void beginStore() { beginOperation(true); try { assertTransactionOperation(); if ((_flags & FLAG_STORE_ACTIVE) == 0) beginStoreManagerTransaction(false); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new StoreException(re); } finally { endOperation(); } } /** * Begin a store manager transaction. */ private void beginStoreManagerTransaction(boolean optimistic) { if (!optimistic) { retainConnection(); _store.begin(); _flags |= FLAG_STORE_ACTIVE; } else { if (_connRetainMode == CONN_RETAIN_TRANS) retainConnection(); _store.beginOptimistic(); } } /** * End the current store manager transaction. Throws an * exception to signal a forced rollback after failed commit, otherwise * returns any exception encountered during the end process. */ private RuntimeException endStoreManagerTransaction(boolean rollback) { boolean forcedRollback = false; boolean releaseConn = false; RuntimeException err = null; try { if ((_flags & FLAG_STORE_ACTIVE) != 0) { releaseConn = _connRetainMode != CONN_RETAIN_ALWAYS; if (rollback) _store.rollback(); else { // and notify the query cache. notify in one batch to reduce synch QueryCache queryCache = getConfiguration(). getDataCacheManagerInstance().getSystemQueryCache(); if (queryCache != null) { Collection> pers = getPersistedTypes(); Collection> del = getDeletedTypes(); Collection> up = getUpdatedTypes(); int size = pers.size() + del.size() + up.size(); if (size > 0) { Collection> types = new ArrayList>(size); types.addAll(pers); types.addAll(del); types.addAll(up); queryCache.onTypesChanged(new TypesChangedEvent(this, types)); } } _store.commit(); } } else { releaseConn = _connRetainMode == CONN_RETAIN_TRANS; _store.rollbackOptimistic(); } } catch (RuntimeException re) { if (!rollback) { forcedRollback = true; try { _store.rollback(); } catch (RuntimeException re2) {} } err = re; } finally { _flags &= ~FLAG_STORE_ACTIVE; } if (releaseConn) { try { releaseConnection(); } catch (RuntimeException re) { if (err == null) err = re; } } if (forcedRollback) throw err; return err; } public void commit() { beginOperation(false); try { assertTransactionOperation(); javax.transaction.Transaction trans = _runtime.getTransactionManager().getTransaction(); if (trans == null) throw new InvalidStateException(_loc.get("null-trans")); // this commit on the transaction will cause our // beforeCompletion method to be invoked trans.commit(); } catch (OpenJPAException ke) { if (_log.isTraceEnabled()) _log.trace(_loc.get("end-trans-error"), ke); throw ke; } catch (Exception e) { if (_log.isTraceEnabled()) _log.trace(_loc.get("end-trans-error"), e); throw new StoreException(e); } finally { endOperation(); } } public void rollback() { beginOperation(false); try { assertTransactionOperation(); javax.transaction.Transaction trans = _runtime.getTransactionManager().getTransaction(); if (trans != null) trans.rollback(); } catch (OpenJPAException ke) { if (_log.isTraceEnabled()) _log.trace(_loc.get("end-trans-error"), ke); throw ke; } catch (Exception e) { if (_log.isTraceEnabled()) _log.trace(_loc.get("end-trans-error"), e); throw new StoreException(e); } finally { endOperation(); } } public boolean syncWithManagedTransaction() { assertOpen(); lock(); try { if ((_flags & FLAG_ACTIVE) != 0) return true; if (!_managed) throw new InvalidStateException(_loc.get("trans-not-managed")); if (_factory.syncWithManagedTransaction(this, false)) { beginInternal(); return true; } return false; } finally { unlock(); } } public void commitAndResume() { endAndResume(true); } public void rollbackAndResume() { endAndResume(false); } private void endAndResume(boolean commit) { beginOperation(false); try { if (commit) commit(); else rollback(); begin(); } finally { endOperation(); } } public boolean getRollbackOnly() { beginOperation(true); try { if ((_flags & FLAG_ACTIVE) == 0) return false; javax.transaction.Transaction trans = _runtime.getTransactionManager().getTransaction(); if (trans == null) return false; return trans.getStatus() == Status.STATUS_MARKED_ROLLBACK; } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(e); } finally { endOperation(); } } public Throwable getRollbackCause() { beginOperation(true); try { if ((_flags & FLAG_ACTIVE) == 0) return null; javax.transaction.Transaction trans = _runtime.getTransactionManager().getTransaction(); if (trans == null) return null; if (trans.getStatus() == Status.STATUS_MARKED_ROLLBACK) return _runtime.getRollbackCause(); return null; } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(e); } finally { endOperation(); } } public void setRollbackOnly() { setRollbackOnly(new UserException()); } public void setRollbackOnly(Throwable cause) { beginOperation(true); try { assertTransactionOperation(); setRollbackOnlyInternal(cause); } finally { endOperation(); } } /** * Mark the current transaction as rollback-only. */ private void setRollbackOnlyInternal(Throwable cause) { try { javax.transaction.Transaction trans = _runtime.getTransactionManager().getTransaction(); if (trans == null) throw new InvalidStateException(_loc.get("null-trans")); // ensure tran is in a valid state to accept the setRollbackOnly int tranStatus = trans.getStatus(); if ((tranStatus != Status.STATUS_NO_TRANSACTION) && (tranStatus != Status.STATUS_ROLLEDBACK) && (tranStatus != Status.STATUS_COMMITTED)) _runtime.setRollbackOnly(cause); else if (_log.isTraceEnabled()) _log.trace(_loc.get("invalid-tran-status", Integer.valueOf( tranStatus), "setRollbackOnly")); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(e); } } public void setSavepoint(String name) { beginOperation(true); try { assertActiveTransaction(); if (_savepoints != null && _savepoints.containsKey(name)) throw new UserException(_loc.get("savepoint-exists", name)); if (hasFlushed() && !_spm.supportsIncrementalFlush()) throw new UnsupportedException(_loc.get ("savepoint-flush-not-supported")); OpenJPASavepoint save = _spm.newSavepoint(name, this); if (_savepoints == null || _savepoints.isEmpty()) { save.save(getTransactionalStates()); _savepoints = new LinkedMap(); } else { if (_savepointCache == null) save.save(Collections.EMPTY_SET); else { save.save(_savepointCache); _savepointCache.clear(); } } _savepoints.put(name, save); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(e); } finally { endOperation(); } } public void releaseSavepoint() { beginOperation(false); try { if (_savepoints == null || _savepoints.isEmpty()) throw new UserException(_loc.get("no-lastsavepoint")); releaseSavepoint((String) _savepoints.get (_savepoints.size() - 1)); } finally { endOperation(); } } public void releaseSavepoint(String savepoint) { beginOperation(false); try { assertActiveTransaction(); int index = (_savepoints == null) ? -1 : _savepoints.indexOf(savepoint); if (index < 0) throw new UserException(_loc.get("no-savepoint", savepoint)); // clear old in reverse OpenJPASavepoint save; while (_savepoints.size() > index + 1) { save = (OpenJPASavepoint) _savepoints.remove (_savepoints.size() - 1); save.release(false); } save = (OpenJPASavepoint) _savepoints.remove(index); save.release(true); if (_savepointCache != null) _savepointCache.clear(); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(e); } finally { endOperation(); } } public void rollbackToSavepoint() { beginOperation(false); try { if (_savepoints == null || _savepoints.isEmpty()) throw new UserException(_loc.get("no-lastsavepoint")); rollbackToSavepoint((String) _savepoints.get (_savepoints.size() - 1)); } finally { endOperation(); } } public void rollbackToSavepoint(String savepoint) { beginOperation(false); try { assertActiveTransaction(); int index = (_savepoints == null) ? -1 : _savepoints.indexOf(savepoint); if (index < 0) throw new UserException(_loc.get("no-savepoint", savepoint)); // clear old in reverse OpenJPASavepoint save; while (_savepoints.size() > index + 1) { save = (OpenJPASavepoint) _savepoints.remove (_savepoints.size() - 1); save.release(false); } save = (OpenJPASavepoint) _savepoints.remove(index); Collection saved = save.rollback(_savepoints.values()); if (_savepointCache != null) _savepointCache.clear(); if (hasTransactionalObjects()) { // build up a new collection of states TransactionalCache oldTransCache = _transCache; TransactionalCache newTransCache = new TransactionalCache (_orderDirty); _transCache = null; // currently there is the assumption that incremental // flush is either a) not allowed, or b) required // pre-savepoint. this solves a number of issues including // storing flushed states as well as OID handling. // if future plugins do not follow this, we need to cache // more info per state SavepointFieldManager fm; StateManagerImpl sm; for (Iterator itr = saved.iterator(); itr.hasNext();) { fm = (SavepointFieldManager) itr.next(); sm = fm.getStateManager(); sm.rollbackToSavepoint(fm); oldTransCache.remove(sm); if (sm.isDirty()) newTransCache.addDirty(sm); else newTransCache.addClean(sm); } for (Iterator itr = oldTransCache.iterator(); itr.hasNext();) { sm = (StateManagerImpl) itr.next(); sm.rollback(); removeFromTransaction(sm); } _transCache = newTransCache; } } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(e); } finally { endOperation(); } } public void flush() { beginOperation(true); try { // return silently if no trans is active, or if this is a reentrant // call, which can happen if the store manager tries to get an // auto-inc oid during flush if ((_flags & FLAG_ACTIVE) == 0 || (_flags & FLAG_STORE_FLUSHING) != 0) return; // make sure the runtime supports it if (!_conf.supportedOptions().contains(OpenJPAConfiguration.OPTION_INC_FLUSH)) throw new UnsupportedException(_loc.get ("incremental-flush-not-supported")); if (_savepoints != null && !_savepoints.isEmpty() && !_spm.supportsIncrementalFlush()) throw new UnsupportedException(_loc.get ("savepoint-flush-not-supported")); try { flushSafe(FLUSH_INC); _flags |= FLAG_FLUSHED; } catch (OpenJPAException ke) { // rollback on flush error; objects may be in inconsistent state setRollbackOnly(ke); throw ke.setFatal(true); } catch (RuntimeException re) { // rollback on flush error; objects may be in inconsistent state setRollbackOnly(re); throw new StoreException(re).setFatal(true); } } finally { endOperation(); } } public void preFlush() { beginOperation(true); try { if ((_flags & FLAG_ACTIVE) != 0) flushSafe(FLUSH_LOGICAL); } finally { endOperation(); } } public void validateChanges() { beginOperation(true); try { // if no trans, just return; if active datastore trans, flush if ((_flags & FLAG_ACTIVE) == 0) return; if ((_flags & FLAG_STORE_ACTIVE) != 0) { flush(); return; } // make sure the runtime supports inc flush if (!_conf.supportedOptions().contains(OpenJPAConfiguration.OPTION_INC_FLUSH)) throw new UnsupportedException(_loc.get ("incremental-flush-not-supported")); try { flushSafe(FLUSH_ROLLBACK); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new StoreException(re); } } finally { endOperation(); } } public boolean isActive() { beginOperation(true); try { return (_flags & FLAG_ACTIVE) != 0; } finally { endOperation(); } } public boolean isStoreActive() { // we need to lock here, because we might be in the middle of an // atomic transaction process (e.g., commitAndResume) beginOperation(true); try { return (_flags & FLAG_STORE_ACTIVE) != 0; } finally { endOperation(); } } /** * Return whether the current transaction is ending, i.e. in the 2nd phase * of a commit or rollback */ boolean isTransactionEnding() { return (_flags & FLAG_TRANS_ENDING) != 0; } public boolean beginOperation(boolean syncTrans) { lock(); try { assertOpen(); if (syncTrans && _operationCount == 0 && _syncManaged && (_flags & FLAG_ACTIVE) == 0) syncWithManagedTransaction(); return _operationCount++ == 1; } catch (OpenJPAException ke) { unlock(); throw ke; } catch (RuntimeException re) { unlock(); throw new GeneralException(re); } } /** * Mark the operation over. If outermost caller of stack, returns true * and will detach managed instances if necessary. */ public boolean endOperation() { try { if (_operationCount == 1 && (_autoDetach & DETACH_NONTXREAD) != 0 && (_flags & FLAG_ACTIVE) == 0) { detachAllInternal(null); } if (_operationCount < 1) throw new InternalException(_loc.get("multi-threaded-access")); return _operationCount == 1; } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { _operationCount--; if (_operationCount == 0) initializeOperatingSet(); unlock(); } } public Synchronization getSynchronization() { return _sync; } public void setSynchronization(Synchronization sync) { assertOpen(); _sync = sync; } /////////////////////////////////////////////// // Implementation of Synchronization interface /////////////////////////////////////////////// public void beforeCompletion() { beginOperation(false); try { // user-supplied synchronization if (_sync != null) _sync.beforeCompletion(); flushSafe(FLUSH_COMMIT); } catch (OpenJPAException ke) { if (_log.isTraceEnabled()) _log.trace(_loc.get("end-trans-error"), ke); throw translateManagedCompletionException(ke); } catch (RuntimeException re) { if (_log.isTraceEnabled()) _log.trace(_loc.get("end-trans-error"), re); throw translateManagedCompletionException(new StoreException(re)); } finally { endOperation(); } } public void afterCompletion(int status) { beginOperation(false); try { assertActiveTransaction(); _flags |= FLAG_TRANS_ENDING; endTransaction(status); if (_sync != null) _sync.afterCompletion(status); if ((_autoDetach & DETACH_COMMIT) != 0) detachAllInternal(null); else if (status == Status.STATUS_ROLLEDBACK && (_autoDetach & DETACH_ROLLBACK) != 0) { detachAllInternal(null); } // in an ee context, it's possible that the user tried to close // us but we didn't actually close because we were waiting on this // transaction; if that's true, then close now if ((_flags & FLAG_CLOSE_INVOKED) != 0 && _compat.getCloseOnManagedCommit()) free(); } catch (OpenJPAException ke) { if (_log.isTraceEnabled()) _log.trace(_loc.get("end-trans-error"), ke); throw translateManagedCompletionException(ke); } catch (RuntimeException re) { if (_log.isTraceEnabled()) _log.trace(_loc.get("end-trans-error"), re); throw translateManagedCompletionException(new StoreException(re)); } finally { _flags &= ~FLAG_ACTIVE; _flags &= ~FLAG_FLUSHED; _flags &= ~FLAG_TRANS_ENDING; // event manager nulled if freed broker if (_transEventManager != null && _transEventManager.hasEndListeners()) { fireTransactionEvent(new TransactionEvent(this, status == Status.STATUS_COMMITTED ? TransactionEvent.AFTER_COMMIT_COMPLETE : TransactionEvent.AFTER_ROLLBACK_COMPLETE, null, null, null, null)); } endOperation(); } } /** * If we're in a managed transaction, use our implicit behavior exception * translator to translate before/afterCompletion callback errors. */ private RuntimeException translateManagedCompletionException (RuntimeException re) { return (!_managed || _extrans == null) ? re : _extrans.translate(re); } /** * Flush safely, catching reentrant calls. */ private void flushSafe(int reason) { if ((_flags & FLAG_FLUSHING) != 0) throw new InvalidStateException(_loc.get("reentrant-flush")); _flags |= FLAG_FLUSHING; try { flush(reason); } finally { _flags &= ~FLAG_FLUSHING; } } /** * Flush the transactional state to the data store. Subclasses that * customize commit behavior should override this method. The method * assumes that the persistence manager is locked, is not closed, * and has an active transaction. * * @param reason one of {@link #FLUSH_INC}, {@link #FLUSH_COMMIT}, * {@link #FLUSH_ROLLBACK}, or {@link #FLUSH_LOGICAL} * @since 0.2.5 */ protected void flush(int reason) { // this will enlist proxied states as necessary so we know whether we // have anything to flush Collection transactional = getTransactionalStates(); // do we actually have to flush? only if our flags say so, or if // we have transaction listeners that need to be invoked for commit // (no need to invoke them on inc flush if nothing is dirty). we // special case the remote commit listener used by the datacache cause // we know it doesn't require the commit event when nothing changes boolean flush = (_flags & FLAG_FLUSH_REQUIRED) != 0; boolean listeners = (_transEventManager.hasFlushListeners() || _transEventManager.hasEndListeners()) && ((_flags & FLAG_REMOTE_LISTENER) == 0 || _transEventManager.getListeners().size() > 1); if (!flush && (reason != FLUSH_COMMIT || !listeners)) return; Collection mobjs = null; _flags |= FLAG_PRESTORING; try { if (flush) { // call pre store on all currently transactional objs for (Iterator itr = transactional.iterator(); itr.hasNext();) ((StateManagerImpl) itr.next()).beforeFlush(reason, _call); flushAdditions(transactional, reason); } // hopefully now all dependent instances that are going to end // up referenced have been marked as such; delete unrefed // dependents _flags |= FLAG_DEREFDELETING; if (flush && _derefCache != null && !_derefCache.isEmpty()) { for (Iterator itr = _derefCache.iterator(); itr.hasNext();) deleteDeref(itr.next()); flushAdditions(transactional, reason); } if (reason != FLUSH_LOGICAL) { // if no datastore transaction, start one; even if we don't // think we'll need to flush at this point, our transaction // listeners might introduce some dirty objects or interact // directly with the database if ((_flags & FLAG_STORE_ACTIVE) == 0) beginStoreManagerTransaction(false); if ((_transEventManager.hasFlushListeners() || _transEventManager.hasEndListeners()) && (flush || reason == FLUSH_COMMIT)) { // fire events mobjs = new ManagedObjectCollection(transactional); if (reason == FLUSH_COMMIT && _transEventManager.hasEndListeners()) { fireTransactionEvent(new TransactionEvent(this, TransactionEvent.BEFORE_COMMIT, mobjs, _persistedClss, _updatedClss, _deletedClss)); flushAdditions(transactional, reason); flush = (_flags & FLAG_FLUSH_REQUIRED) != 0; } if (flush && _transEventManager.hasFlushListeners()) { fireTransactionEvent(new TransactionEvent(this, TransactionEvent.BEFORE_FLUSH, mobjs, _persistedClss, _updatedClss, _deletedClss)); flushAdditions(transactional, reason); } } } } finally { _flags &= ~FLAG_PRESTORING; _flags &= ~FLAG_DEREFDELETING; _transAdditions = null; _derefAdditions = null; // also clear derefed set; the deletes have been recorded if (_derefCache != null) _derefCache = null; } // flush to store manager List exceps = null; try { if (flush && reason != FLUSH_LOGICAL) { _flags |= FLAG_STORE_FLUSHING; exceps = add(exceps, newFlushException(_store.flush(transactional))); } } finally { _flags &= ~FLAG_STORE_FLUSHING; if (reason == FLUSH_ROLLBACK) exceps = add(exceps, endStoreManagerTransaction(true)); else if (reason != FLUSH_LOGICAL) _flags &= ~FLAG_FLUSH_REQUIRED; // mark states as flushed if (flush) { StateManagerImpl sm; for (Iterator itr = transactional.iterator(); itr.hasNext();) { sm = (StateManagerImpl) itr.next(); try { // the state may have become transient, such as if // it is embedded and the owner has been deleted during // this flush process; bug #1100 if (sm.getPCState() == PCState.TRANSIENT) continue; sm.afterFlush(reason); if (reason == FLUSH_INC) { // if not about to clear trans cache for commit // anyway, re-cache dirty objects with default soft // refs; we don't need hard refs now that the // changes have been flushed sm.proxyFields(true, false); _transCache.flushed(sm); } } catch (Exception e) { exceps = add(exceps, e); } } } } // throw any exceptions to shortcut listeners on fail throwNestedExceptions(exceps, true); if (flush && reason != FLUSH_ROLLBACK && reason != FLUSH_LOGICAL && _transEventManager.hasFlushListeners()) { fireTransactionEvent(new TransactionEvent(this, TransactionEvent.AFTER_FLUSH, mobjs, _persistedClss, _updatedClss, _deletedClss)); } } /** * Flush newly-transactional objects. */ private void flushAdditions(Collection transactional, int reason) { boolean loop; do { // flush new transactional instances; note logical or loop = flushTransAdditions(transactional, reason) | deleteDerefAdditions(_derefCache); } while (loop); } /** * Flush transactional additions. */ private boolean flushTransAdditions(Collection transactional, int reason) { if (_transAdditions == null || _transAdditions.isEmpty()) return false; // keep local transactional list copy up to date transactional.addAll(_transAdditions); // copy the change set, then clear it for the next iteration StateManagerImpl[] states = (StateManagerImpl[]) _transAdditions. toArray(new StateManagerImpl[_transAdditions.size()]); _transAdditions = null; for (int i = 0; i < states.length; i++) states[i].beforeFlush(reason, _call); return true; } /** * Delete new dereferenced objects. */ private boolean deleteDerefAdditions(Collection derefs) { if (_derefAdditions == null || _derefAdditions.isEmpty()) return false; // remember these additions in case one becomes derefed again later derefs.addAll(_derefAdditions); StateManagerImpl[] states = (StateManagerImpl[]) _derefAdditions. toArray(new StateManagerImpl[_derefAdditions.size()]); _derefAdditions = null; for (int i = 0; i < states.length; i++) deleteDeref(states[i]); return true; } /** * Delete a dereferenced dependent. */ private void deleteDeref(StateManagerImpl sm) { int action = processArgument(OpCallbacks.OP_DELETE, sm.getManagedInstance(), sm, null); if ((action & OpCallbacks.ACT_RUN) != 0) sm.delete(); if ((action & OpCallbacks.ACT_CASCADE) != 0) sm.cascadeDelete(_call); } /** * Determine the action to take based on the user's given callbacks and * our implicit behavior. */ private int processArgument(int op, Object obj, OpenJPAStateManager sm, OpCallbacks call) { if (call != null) return call.processArgument(op, obj, sm); if (_call != null) return _call.processArgument(op, obj, sm); return OpCallbacks.ACT_RUN | OpCallbacks.ACT_CASCADE; } /** * Throw the proper exception based on the given set of flush errors, or * do nothing if no errors occurred. */ private OpenJPAException newFlushException(Collection exceps) { if (exceps == null || exceps.isEmpty()) return null; Throwable[] t = exceps.toArray(new Throwable[exceps.size()]); List failed = new ArrayList(t.length); // create fatal exception with nested exceptions for all the failed // objects; if all OL exceptions, throw a top-level OL exception boolean opt = true; for (int i = 0; opt && i < t.length; i++) { opt = t[i] instanceof OptimisticException; if (opt) { Object f = ((OptimisticException) t[i]).getFailedObject(); if (f != null) failed.add(f); } } if (opt && !failed.isEmpty()) { if(_suppressBatchOLELogging == true){ return new OptimisticException(_loc.get("broker-suppressing-exceptions",t.length)); }else{ return new OptimisticException(failed, t); } } if (opt) return new OptimisticException(t); Object failedObject = null; if (t[0] instanceof OpenJPAException){ failedObject = ((OpenJPAException)t[0]).getFailedObject(); } return new StoreException(_loc.get("rolled-back")). setNestedThrowables(t).setFatal(true).setFailedObject(failedObject); } /** * End the current transaction, making appropriate state transitions. */ protected void endTransaction(int status) { // if a data store transaction was in progress, do the // appropriate transaction change boolean rollback = status != Status.STATUS_COMMITTED; List exceps = null; try { exceps = add(exceps, endStoreManagerTransaction(rollback)); } catch (RuntimeException re) { rollback = true; exceps = add(exceps, re); } // go back to default none lock level _fc.setReadLockLevel(LOCK_NONE); _fc.setWriteLockLevel(LOCK_NONE); _fc.setLockTimeout(-1); Collection transStates; if (hasTransactionalObjects()) transStates = _transCache; else transStates = Collections.EMPTY_SET; // fire after rollback/commit event Collection mobjs = null; if (_transEventManager.hasEndListeners()) { mobjs = new ManagedObjectCollection(transStates); int eventType = (rollback) ? TransactionEvent.AFTER_ROLLBACK : TransactionEvent.AFTER_COMMIT; fireTransactionEvent(new TransactionEvent(this, eventType, mobjs, _persistedClss, _updatedClss, _deletedClss)); } // null transactional caches now so that all the removeFromTransaction // calls as we transition each object don't have to do any work; don't // clear trans cache object because we still need the transStates // reference to it below _transCache = null; if (_persistedClss != null) _persistedClss = null; if (_updatedClss != null) _updatedClss = null; if (_deletedClss != null) _deletedClss = null; // new cache would get cleared anyway during transitions, but doing so // immediately saves us some lookups _cache.clearNew(); // tell all derefed instances they're no longer derefed; we can't // rely on rollback and commit calls below cause some instances might // not be transactional if (_derefCache != null && !_derefCache.isEmpty()) { for (Iterator itr = _derefCache.iterator(); itr.hasNext();) itr.next().setDereferencedDependent(false, false); _derefCache = null; } // perform commit or rollback state transitions on each instance StateManagerImpl sm; for (Iterator itr = transStates.iterator(); itr.hasNext();) { sm = (StateManagerImpl) itr.next(); try { if (rollback) { // tell objects that may have been derefed then flushed // (and therefore deleted) to un-deref sm.setDereferencedDependent(false, false); sm.rollback(); } else { if (sm.getPCState() == PCState.PNEWDELETED || sm.getPCState() == PCState.PDELETED) { fireLifecycleEvent(sm.getPersistenceCapable(), null, sm.getMetaData(), LifecycleEvent.AFTER_DELETE_PERFORMED); } sm.commit(); } } catch (RuntimeException re) { exceps = add(exceps, re); } } // notify the lock manager to clean up and release remaining locks _lm.endTransaction(); // clear old savepoints in reverse OpenJPASavepoint save; while (_savepoints != null && _savepoints.size() > 0) { save = (OpenJPASavepoint) _savepoints.remove(_savepoints.size() - 1); save.release(false); } _savepoints = null; _savepointCache = null; // fire after state change event if (_transEventManager.hasEndListeners()) fireTransactionEvent(new TransactionEvent(this, TransactionEvent. AFTER_STATE_TRANSITIONS, mobjs, null, null, null)); // now clear trans cache; keep cleared version rather than // null to avoid having to re-create the set later; more efficient if (transStates != Collections.EMPTY_SET) { _transCache = (TransactionalCache) transStates; _transCache.clear(); } throwNestedExceptions(exceps, true); } //////////////////// // Object lifecycle //////////////////// public void persist(Object obj, OpCallbacks call) { persist(obj, null, true, call); } public OpenJPAStateManager persist(Object obj, Object id, OpCallbacks call) { return persist(obj, id, true, call); } public void persistAll(Collection objs, OpCallbacks call) { persistAll(objs, true, call); } /** * Persist the given objects. Indicate whether this was an explicit persist * (PNEW) or a provisonal persist (PNEWPROVISIONAL). */ public void persistAll(Collection objs, boolean explicit, OpCallbacks call) { if (objs.isEmpty()) return; beginOperation(true); List exceps = null; try { assertWriteOperation(); for (Object obj : objs) { try { if(obj == null) continue; persistInternal(obj, null, explicit, call, true); } catch (UserException ue) { exceps = add(exceps, ue); } catch (RuntimeException re) { throw new GeneralException(re); } } } finally { endOperation(); } throwNestedExceptions(exceps, false); } /** * If the given element is not null, add it to the given list, * creating the list if necessary. */ private List add(List l, Exception o) { if (o == null) return l; if (l == null) l = new LinkedList(); l.add(o); return l; } /** * Throw an exception wrapping the given nested exceptions. */ private void throwNestedExceptions(List exceps, boolean datastore) { if (exceps == null || exceps.isEmpty()) return; if (datastore && exceps.size() == 1) throw (RuntimeException) exceps.get(0); boolean fatal = false; Throwable[] t = exceps.toArray(new Throwable[exceps.size()]); for (int i = 0; i < t.length; i++) { if (t[i] instanceof OpenJPAException && ((OpenJPAException) t[i]).isFatal()) fatal = true; } OpenJPAException err; if (datastore) err = new StoreException(_loc.get("nested-exceps")); else err = new UserException(_loc.get("nested-exceps")); throw err.setNestedThrowables(t).setFatal(fatal); } /** * Persist the given object. Indicate whether this was an explicit persist * (PNEW) or a provisonal persist (PNEWPROVISIONAL) */ public void persist(Object obj, boolean explicit, OpCallbacks call) { persist(obj, null, explicit, call); } /** * Persist the given object. Indicate whether this was an explicit persist * (PNEW) or a provisonal persist (PNEWPROVISIONAL). * See {@link Broker} for details on this method. */ public OpenJPAStateManager persist(Object obj, Object id, boolean explicit, OpCallbacks call) { return persist(obj, id, explicit, call, true); } /** * Persist the given object. Indicate whether this was an explicit persist * (PNEW) or a provisonal persist (PNEWPROVISIONAL). * See {@link Broker} for details on this method. */ public OpenJPAStateManager persist(Object obj, Object id, boolean explicit, OpCallbacks call, boolean fireEvent) { if (obj == null) return null; beginOperation(true); try { assertWriteOperation(); return persistInternal(obj, id, explicit, call, fireEvent); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } private OpenJPAStateManager persistInternal(Object obj, Object id, boolean explicit, OpCallbacks call, boolean fireEvent) { StateManagerImpl sm = getStateManagerImpl(obj, true); if (!operatingAdd(obj)) { return sm; } int action = processArgument(OpCallbacks.OP_PERSIST, obj, sm, call); if (action == OpCallbacks.ACT_NONE) { return sm; } // ACT_CASCADE if ((action & OpCallbacks.ACT_RUN) == 0) { if (sm != null) { sm.cascadePersist(call); } else { cascadeTransient(OpCallbacks.OP_PERSIST, obj, call, "persist"); } return sm; } // ACT_RUN PersistenceCapable pc; if (sm != null) { if (sm.isDetached()) { throw new ObjectExistsException(_loc.get("persist-detached", Exceptions.toString(obj))) .setFailedObject(obj); } if (!sm.isEmbedded()) { sm.persist(); _cache.persist(sm); if ((action & OpCallbacks.ACT_CASCADE) != 0) { sm.cascadePersist(call); } return sm; } // an embedded field; notify the owner that the value has // changed by becoming independently persistent sm.getOwner().dirty(sm.getOwnerIndex()); _cache.persist(sm); pc = sm.getPersistenceCapable(); } else { pc = assertPersistenceCapable(obj); if (pc.pcIsDetached() == Boolean.TRUE) { throw new ObjectExistsException(_loc.get("persist-detached", Exceptions.toString(obj))) .setFailedObject(obj); } } ClassMetaData meta = _repo.getMetaData(obj.getClass(), _loader, true); if (fireEvent) { fireLifecycleEvent(obj, null, meta, LifecycleEvent.BEFORE_PERSIST); } // create id for instance if (id == null) { int idType = meta.getIdentityType(); if (idType == ClassMetaData.ID_APPLICATION) { id = ApplicationIds.create(pc, meta); } else if (idType == ClassMetaData.ID_UNKNOWN) { throw new UserException(_loc.get("meta-unknownid", meta)); } else { id = StateManagerId.newInstance(this); } } // make sure we don't already have the instance cached checkForDuplicateId(id, obj, meta); // if had embedded sm, null it if (sm != null) { pc.pcReplaceStateManager(null); } // create new sm sm = newStateManagerImpl(id, meta); if ((_flags & FLAG_ACTIVE) != 0) { if (explicit) { sm.initialize(pc, PCState.PNEW); } else { sm.initialize(pc, PCState.PNEWPROVISIONAL); } } else { sm.initialize(pc, PCState.PNONTRANSNEW); } if ((action & OpCallbacks.ACT_CASCADE) != 0) { sm.cascadePersist(call); } return sm; } /** * Temporarily manage the given instance in order to cascade the given * operation through it. */ private void cascadeTransient(int op, Object obj, OpCallbacks call, String errOp) { PersistenceCapable pc = assertPersistenceCapable(obj); // if using detached state manager, don't replace if (pc.pcGetStateManager() != null) throw newDetachedException(obj, errOp); ClassMetaData meta = _repo.getMetaData(obj.getClass(), _loader, true); StateManagerImpl sm = newStateManagerImpl(StateManagerId. newInstance(this), meta); sm.initialize(pc, PCState.TLOADED); try { switch (op) { case OpCallbacks.OP_PERSIST: sm.cascadePersist(call); break; case OpCallbacks.OP_DELETE: sm.cascadeDelete(call); break; case OpCallbacks.OP_REFRESH: sm.gatherCascadeRefresh(call); break; default: throw new InternalException(String.valueOf(op)); } } finally { sm.release(true); } } public void deleteAll(Collection objs, OpCallbacks call) { beginOperation(true); try { assertWriteOperation(); List exceps = null; Object obj; for (Iterator itr = objs.iterator(); itr.hasNext();) { try { obj = itr.next(); if (obj != null) delete(obj, getStateManagerImpl(obj, true), call); } catch (UserException ue) { exceps = add(exceps, ue); } } throwNestedExceptions(exceps, false); } finally { endOperation(); } } public void delete(Object obj, OpCallbacks call) { if (obj == null) return; beginOperation(true); try { assertWriteOperation(); delete(obj, getStateManagerImpl(obj, true), call); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } /** * Internal delete. */ void delete(Object obj, StateManagerImpl sm, OpCallbacks call) { if (!operatingAdd(obj)) return; int action = processArgument(OpCallbacks.OP_DELETE, obj, sm, call); if (action == OpCallbacks.ACT_NONE) return; // ACT_CASCADE if ((action & OpCallbacks.ACT_RUN) == 0) { if (sm != null) { if (!sm.isEmbedded() || !sm.getDereferencedEmbedDependent()) { sm.cascadeDelete(call); } } else cascadeTransient(OpCallbacks.OP_DELETE, obj, call, "delete"); return; } // ACT_RUN if (sm != null) { if (sm.isDetached()) throw newDetachedException(obj, "delete"); if ((action & OpCallbacks.ACT_CASCADE) != 0) { if (!sm.isEmbedded() || !sm.getDereferencedEmbedDependent()) { if (ValidatingLifecycleEventManager.class.isAssignableFrom(_lifeEventManager.getClass())) { ValidatingLifecycleEventManager _validatingLCEventManager = (ValidatingLifecycleEventManager) _lifeEventManager; boolean saved = _validatingLCEventManager.setValidationEnabled(false); try { sm.cascadeDelete(call); } finally { _validatingLCEventManager.setValidationEnabled(saved); } } else { sm.cascadeDelete(call); } } } sm.delete(); } else if (assertPersistenceCapable(obj).pcIsDetached() == Boolean.TRUE) throw newDetachedException(obj, "delete"); } /** * Throw an exception indicating that the current action can't be * performed on a detached object. */ private OpenJPAException newDetachedException(Object obj, String operation) { throw new UserException(_loc.get("bad-detached-op", operation, Exceptions.toString(obj))).setFailedObject(obj); } public void releaseAll(Collection objs, OpCallbacks call) { beginOperation(false); try { List exceps = null; for (Iterator itr = objs.iterator(); itr.hasNext();) { try { release(itr.next(), call); } catch (UserException ue) { exceps = add(exceps, ue); } } throwNestedExceptions(exceps, false); } finally { endOperation(); } } public void release(Object obj, OpCallbacks call) { if (obj == null) return; beginOperation(false); try { StateManagerImpl sm = getStateManagerImpl(obj, true); int action = processArgument(OpCallbacks.OP_RELEASE, obj, sm, call); if (sm == null) return; if ((action & OpCallbacks.ACT_RUN) != 0 && sm.isPersistent()) { boolean pending = sm.isPendingTransactional(); sm.release(true); if (pending) removeFromPendingTransaction(sm); } } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } public OpenJPAStateManager embed(Object obj, Object id, OpenJPAStateManager owner, ValueMetaData ownerMeta) { beginOperation(true); try { StateManagerImpl orig = getStateManagerImpl(obj, true); if (orig != null) { // if already embedded, nothing to do if (orig.getOwner() == owner && orig.getMetaData(). getEmbeddingMetaData() == ownerMeta) return orig; // otherwise make sure pc is fully loaded for when we copy its // data below orig.load(_fc, StateManagerImpl.LOAD_ALL, null, null, false); } // create new state manager with embedded metadata ClassMetaData meta = ownerMeta.getEmbeddedMetaData(); if (meta == null) throw new InternalException(_loc.get("bad-embed", ownerMeta)); if (id == null) id = StateManagerId.newInstance(this); StateManagerImpl sm = newStateManagerImpl(id, meta); sm.setOwner((StateManagerImpl) owner, ownerMeta); PersistenceCapable copy; PCState state; Class type = meta.getDescribedType(); if (obj != null) { // give copy and the original instance the same state manager // so that we can copy fields from one to the other StateManagerImpl copySM; PersistenceCapable pc; if (orig == null) { copySM = sm; pc = assertPersistenceCapable(obj); pc.pcReplaceStateManager(sm); } else { copySM = orig; pc = orig.getPersistenceCapable(); } try { // copy the instance. we do this even if it doesn't already // have a state manager in case it is later assigned to a // PC field; at that point it's too late to copy copy = PCRegistry.newInstance(type, copySM, false); int[] fields = new int[meta.getFields().length]; for (int i = 0; i < fields.length; i++) fields[i] = i; copy.pcCopyFields(pc, fields); state = PCState.ECOPY; copy.pcReplaceStateManager(null); } finally { // if the instance didn't have a state manager to start, // revert it to being transient if (orig == null) pc.pcReplaceStateManager(null); } } else { copy = PCRegistry.newInstance(type, sm, false); if ((_flags & FLAG_ACTIVE) != 0 && !_optimistic) state = PCState.ECLEAN; else state = PCState.ENONTRANS; } sm.initialize(copy, state); return sm; } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } /** * If not already cached, create an empty copy of the given state * manager in the given state. */ OpenJPAStateManager copy(OpenJPAStateManager copy, PCState state) { beginOperation(true); try { assertOpen(); Object oid = copy.fetchObjectId(); Class type = copy.getManagedInstance().getClass(); if (oid == null) throw new InternalException(); // cached instance? StateManagerImpl sm = null; if (!copy.isEmbedded()) sm = getStateManagerImplById(oid, true); if (sm == null) { MetaDataRepository repos = _conf. getMetaDataRepositoryInstance(); ClassMetaData meta = repos.getMetaData(type, _loader, true); // construct a new state manager with all info known sm = newStateManagerImpl(oid, meta); sm.setObjectId(oid); sm.initialize(sm.getMetaData().getDescribedType(), state); } return sm; } finally { endOperation(); } } public void refreshAll(Collection objs, OpCallbacks call) { if (objs == null || objs.isEmpty()) return; beginOperation(true); try { assertNontransactionalRead(); for (Iterator itr = objs.iterator(); itr.hasNext();) gatherCascadeRefresh(itr.next(), call); if (_operating.isEmpty()) return; if (_operating.size() == 1) refreshInternal(_operating.iterator().next(), call); else refreshInternal(_operating, call); } finally { endOperation(); } } public void refresh(Object obj, OpCallbacks call) { if (obj == null) return; beginOperation(true); try { assertNontransactionalRead(); gatherCascadeRefresh(obj, call); if (_operating.isEmpty()) return; if (_operating.size() == 1) refreshInternal(_operating.iterator().next(), call); else refreshInternal(_operating, call); } finally { endOperation(); } } /** * Gathers all objects reachable through cascade-refresh relations * into the operating set. */ void gatherCascadeRefresh(Object obj, OpCallbacks call) { if (obj == null) return; if (!operatingAdd(obj)) return; StateManagerImpl sm = getStateManagerImpl(obj, false); int action = processArgument(OpCallbacks.OP_REFRESH, obj, sm, call); if ((action & OpCallbacks.ACT_CASCADE) == 0) return; if (sm != null) sm.gatherCascadeRefresh(call); else cascadeTransient(OpCallbacks.OP_REFRESH, obj, call, "refresh"); } /** * This method is called with the full set of objects reachable via * cascade-refresh relations from the user-given instances. */ protected void refreshInternal(Collection objs, OpCallbacks call) { if (objs == null || objs.isEmpty()) return; List exceps = null; try { // collect instances that need a refresh Collection load = null; StateManagerImpl sm; Object obj; for (Iterator itr = objs.iterator(); itr.hasNext();) { obj = itr.next(); if (obj == null) continue; try { sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_REFRESH, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) continue; if (sm != null) { if (sm.isDetached()) throw newDetachedException(obj, "refresh"); else if (sm.beforeRefresh(true)) { if (load == null) load = new ArrayList(objs.size()); load.add(sm); } int level = _fc.getReadLockLevel(); int timeout = _fc.getLockTimeout(); _lm.refreshLock(sm, level, timeout, null); sm.readLocked(level, level); } else if (assertPersistenceCapable(obj).pcIsDetached() == Boolean.TRUE) throw newDetachedException(obj, "refresh"); } catch (OpenJPAException ke) { exceps = add(exceps, ke); } } // refresh all if (load != null) { Collection failed = _store.loadAll(load, null, StoreManager.FORCE_LOAD_REFRESH, _fc, null); if (failed != null && !failed.isEmpty()) exceps = add(exceps, newObjectNotFoundException(failed)); // perform post-refresh transitions and make sure all fetch // group fields are loaded for (Iterator itr = load.iterator(); itr.hasNext();) { sm = (StateManagerImpl) itr.next(); if (failed != null && failed.contains(sm.getId())) continue; try { sm.afterRefresh(); sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, false); } catch (OpenJPAException ke) { exceps = add(exceps, ke); } } } // now invoke postRefresh on all the instances for (Iterator itr = objs.iterator(); itr.hasNext();) { try { sm = getStateManagerImpl(itr.next(), true); if (sm != null && !sm.isDetached()) fireLifecycleEvent(sm.getManagedInstance(), null, sm.getMetaData(), LifecycleEvent.AFTER_REFRESH); } catch (OpenJPAException ke) { exceps = add(exceps, ke); } } } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } throwNestedExceptions(exceps, false); } /** * Optimization for single-object refresh. */ protected void refreshInternal(Object obj, OpCallbacks call) { try { StateManagerImpl sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_REFRESH, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) return; if (sm != null) { if (sm.isDetached()) throw newDetachedException(obj, "refresh"); else if (sm.beforeRefresh(false)) { sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, false); sm.afterRefresh(); } int level = _fc.getReadLockLevel(); int timeout = _fc.getLockTimeout(); _lm.refreshLock(sm, level, timeout, null); sm.readLocked(level, level); fireLifecycleEvent(sm.getManagedInstance(), null, sm.getMetaData(), LifecycleEvent.AFTER_REFRESH); } else if (assertPersistenceCapable(obj).pcIsDetached() == Boolean.TRUE) throw newDetachedException(obj, "refresh"); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } } public void retrieveAll(Collection objs, boolean dfgOnly, OpCallbacks call) { if (objs == null || objs.isEmpty()) return; if (objs.size() == 1) { retrieve(objs.iterator().next(), dfgOnly, call); return; } List exceps = null; beginOperation(true); try { assertOpen(); assertNontransactionalRead(); // collect all hollow instances for load Object obj; Collection load = null; StateManagerImpl sm; Collection sms = new ArrayList(objs.size()); for (Iterator itr = objs.iterator(); itr.hasNext();) { obj = itr.next(); if (obj == null) continue; try { sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_RETRIEVE, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) continue; if (sm != null) { if (sm.isDetached()) throw newDetachedException(obj, "retrieve"); if (sm.isPersistent()) { sms.add(sm); if (sm.getPCState() == PCState.HOLLOW) { if (load == null) load = new ArrayList(); load.add(sm); } } } else if (assertPersistenceCapable(obj).pcIsDetached() == Boolean.TRUE) throw newDetachedException(obj, "retrieve"); } catch (UserException ue) { exceps = add(exceps, ue); } } // load all hollow instances Collection failed = null; if (load != null) { int mode = (dfgOnly) ? StoreManager.FORCE_LOAD_DFG : StoreManager.FORCE_LOAD_ALL; failed = _store.loadAll(load, null, mode, _fc, null); if (failed != null && !failed.isEmpty()) exceps = add(exceps, newObjectNotFoundException(failed)); } // retrieve all non-failed instances for (Iterator itr = sms.iterator(); itr.hasNext();) { sm = itr.next(); if (failed != null && failed.contains(sm.getId())) continue; int mode = (dfgOnly) ? StateManagerImpl.LOAD_FGS : StateManagerImpl.LOAD_ALL; try { sm.beforeRead(-1); sm.load(_fc, mode, null, null, false); } catch (OpenJPAException ke) { exceps = add(exceps, ke); } } } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } throwNestedExceptions(exceps, false); } public void retrieve(Object obj, boolean dfgOnly, OpCallbacks call) { if (obj == null) return; beginOperation(true); try { assertOpen(); assertNontransactionalRead(); StateManagerImpl sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_RETRIEVE, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) return; if (sm != null) { if (sm.isDetached()) throw newDetachedException(obj, "retrieve"); if (sm.isPersistent()) { int mode = (dfgOnly) ? StateManagerImpl.LOAD_FGS : StateManagerImpl.LOAD_ALL; sm.beforeRead(-1); sm.load(_fc, mode, null, null, false); } } else if (assertPersistenceCapable(obj).pcIsDetached() == Boolean.TRUE) throw newDetachedException(obj, "retrieve"); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } public void evictAll(OpCallbacks call) { beginOperation(false); try { // evict all PClean and PNonTrans objects Collection c = getManagedStates(); StateManagerImpl sm; for (Iterator itr = c.iterator(); itr.hasNext();) { sm = itr.next(); if (sm.isPersistent() && !sm.isDirty()) evict(sm.getManagedInstance(), call); } } finally { endOperation(); } } public void evictAll(Collection objs, OpCallbacks call) { List exceps = null; beginOperation(false); try { for (Iterator itr = objs.iterator(); itr.hasNext();) { try { evict(itr.next(), call); } catch (UserException ue) { exceps = add(exceps, ue); } } } finally { endOperation(); } throwNestedExceptions(exceps, false); } public void evictAll(Extent extent, OpCallbacks call) { if (extent == null) return; beginOperation(false); try { // evict all PClean and PNonTrans objects in extent Collection c = getManagedStates(); StateManagerImpl sm; Class cls; for (Iterator itr = c.iterator(); itr.hasNext();) { sm = itr.next(); if (sm.isPersistent() && !sm.isDirty()) { cls = sm.getMetaData().getDescribedType(); if (cls == extent.getElementType() || (extent.hasSubclasses() && extent.getElementType().isAssignableFrom(cls))) evict(sm.getManagedInstance(), call); } } } finally { endOperation(); } } public void evict(Object obj, OpCallbacks call) { if (obj == null) return; beginOperation(false); try { StateManagerImpl sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_EVICT, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) return; if (sm == null) return; sm.evict(); if (_evictDataCache && sm.getObjectId() != null) { DataCache cache = _conf.getDataCacheManagerInstance().selectCache(sm); if (cache != null) cache.remove(sm.getObjectId()); } } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } public Object detach(Object obj, OpCallbacks call) { if (obj == null) return null; if (call == null) call = _call; beginOperation(true); try { return new DetachManager(this, false, call).detach(obj); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } public Object[] detachAll(Collection objs, OpCallbacks call) { if (objs == null) return null; if (objs.isEmpty()) return EMPTY_OBJECTS; if (call == null) call = _call; beginOperation(true); try { return new DetachManager(this, false, call).detachAll(objs); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } public void detachAll(OpCallbacks call) { detachAll(call, true); } public void detachAll(OpCallbacks call, boolean flush) { beginOperation(true); try { // If a flush is desired (based on input parm), then check if the // "dirty" flag is set before calling flush(). if (flush && (_flags & FLAG_FLUSH_REQUIRED) != 0) flush(); detachAllInternal(call); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } private void detachAllInternal(OpCallbacks call) { if(_conf.getDetachStateInstance().getLiteAutoDetach() == true){ detachAllInternalLite(); return; } Collection states = getManagedStates(); StateManagerImpl sm; for (Iterator itr = states.iterator(); itr.hasNext();) { sm = itr.next(); if (!sm.isPersistent()) itr.remove(); else if (!sm.getMetaData().isDetachable()) { sm.release(true); itr.remove(); } } if (states.isEmpty()) return; if (call == null) call = _call; // Make sure ALL entities are detached, even new ones that are loaded // during the detach processing boolean origCascade = _compat.getCascadeWithDetach(); _compat.setCascadeWithDetach(true); try { new DetachManager(this, true, call) .detachAll(new ManagedObjectCollection(states)); } finally { _compat.setCascadeWithDetach(origCascade); } } private void detachAllInternalLite() { ManagedCache old = _cache; _cache = new ManagedCache(this); // TODO : should I call clear on old cache first? perhaps a memory leak? Collection states = old.copy(); // Clear out all persistence context caches. if (_transCache != null) { _transCache.clear(); } if (_transAdditions != null) { _transAdditions.clear(); } if (_pending != null) { _pending = null; } if (_dmLite == null) { _dmLite = new DetachManagerLite(_conf); } _dmLite.detachAll(states); } public Object attach(Object obj, boolean copyNew, OpCallbacks call) { if (obj == null) return null; beginOperation(true); try { // make sure not to try to set rollback only if this fails assertWriteOperation(); try { return new AttachManager(this, copyNew, call).attach(obj); } catch (OptimisticException oe) { setRollbackOnly(oe); throw oe.setFatal(true); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } } finally { endOperation(); } } public Object[] attachAll(Collection objs, boolean copyNew, OpCallbacks call) { if (objs == null) return null; if (objs.isEmpty()) return EMPTY_OBJECTS; beginOperation(true); try { // make sure not to try to set rollback only if this fails assertWriteOperation(); try { return new AttachManager(this, copyNew, call).attachAll(objs); } catch (OptimisticException oe) { setRollbackOnly(oe); throw oe.setFatal(true); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } } finally { endOperation(); } } public void nontransactionalAll(Collection objs, OpCallbacks call) { beginOperation(true); try { List exceps = null; for (Iterator itr = objs.iterator(); itr.hasNext();) { try { nontransactional(itr.next(), call); } catch (UserException ue) { exceps = add(exceps, ue); } } throwNestedExceptions(exceps, false); } finally { endOperation(); } } public void nontransactional(Object obj, OpCallbacks call) { if (obj == null) return; beginOperation(true); try { StateManagerImpl sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_NONTRANSACTIONAL, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) return; if (sm != null) sm.nontransactional(); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } /** * Make the given instances transactional. */ public void transactionalAll(Collection objs, boolean updateVersion, OpCallbacks call) { if (objs.isEmpty()) return; if (objs.size() == 1) { transactional(objs.iterator().next(), updateVersion, call); return; } beginOperation(true); try { // collect all hollow instances for load, and make unmananged // instances transient-transactional Collection load = null; Object obj; StateManagerImpl sm; ClassMetaData meta; Collection sms = new LinkedHashSet(objs.size()); List exceps = null; for (Iterator itr = objs.iterator(); itr.hasNext();) { obj = itr.next(); if (obj == null) continue; try { sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_TRANSACTIONAL, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) continue; if (sm == null) { // manage transient instance meta = _repo.getMetaData(obj.getClass(), _loader, true); sm = newStateManagerImpl (StateManagerId.newInstance(this), meta); sm.initialize(assertPersistenceCapable(obj), PCState.TCLEAN); } else if (sm.isPersistent()) { assertActiveTransaction(); sms.add(sm); if (sm.getPCState() == PCState.HOLLOW) { if (load == null) load = new ArrayList(); load.add(sm); } sm.setCheckVersion(true); if (updateVersion) sm.setUpdateVersion(true); _flags |= FLAG_FLUSH_REQUIRED; // version check/up } } catch (UserException ue) { exceps = add(exceps, ue); } } // load all hollow instances Collection failed = null; if (load != null) { failed = _store.loadAll(load, null, StoreManager.FORCE_LOAD_NONE, _fc, null); if (failed != null && !failed.isEmpty()) exceps = add(exceps, newObjectNotFoundException(failed)); } transactionalStatesAll(sms, failed, exceps); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } /** * Make the given instances transactional. */ public void transactional(Object obj, boolean updateVersion, OpCallbacks call) { if (obj == null) return; beginOperation(true); try { StateManagerImpl sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_TRANSACTIONAL, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) return; if (sm != null && sm.isPersistent()) { assertActiveTransaction(); sm.transactional(); sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, false); sm.setCheckVersion(true); if (updateVersion) sm.setUpdateVersion(true); _flags |= FLAG_FLUSH_REQUIRED; // version check/up } else if (sm == null) { // manage transient instance ClassMetaData meta = _repo.getMetaData(obj.getClass(), _loader, true); Object id = StateManagerId.newInstance(this); sm = newStateManagerImpl(id, meta); sm.initialize(assertPersistenceCapable(obj), PCState.TCLEAN); } } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } /** * Transition the given state managers to transactional. */ private void transactionalStatesAll(Collection sms, Collection failed, List exceps) { // make instances transactional and make sure they are loaded StateManagerImpl sm; for (Iterator itr = sms.iterator(); itr.hasNext();) { sm = (StateManagerImpl) itr.next(); if (failed != null && failed.contains(sm.getId())) continue; try { sm.transactional(); sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, false); } catch (OpenJPAException ke) { exceps = add(exceps, ke); } } throwNestedExceptions(exceps, false); } ///////////////// // Extent, Query ///////////////// public Extent newExtent(Class type, boolean subclasses) { return newExtent(type, subclasses, null); } private Extent newExtent(Class type, boolean subclasses, FetchConfiguration fetch) { beginOperation(true); try { ExtentImpl extent = new ExtentImpl(this, type, subclasses, fetch); if (_extents == null) _extents = new ReferenceHashSet(ReferenceHashSet.WEAK); _extents.add(extent); return extent; } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } public Iterator extentIterator(Class type, boolean subclasses, FetchConfiguration fetch, boolean ignoreChanges) { Extent extent = newExtent(type, subclasses, fetch); extent.setIgnoreChanges(ignoreChanges); return extent.iterator(); } public Query newQuery(String lang, Class cls, Object query) { Query q = newQuery(lang, query); q.setCandidateType(cls, true); return q; } public Query newQuery(String lang, Object query) { // common mistakes if (query instanceof Extent || query instanceof Class) throw new UserException(_loc.get("bad-new-query")); beginOperation(false); try { StoreQuery sq = _store.newQuery(lang); if (sq == null) { ExpressionParser ep = QueryLanguages.parserForLanguage(lang); if (ep != null) sq = new ExpressionStoreQuery(ep); else if (QueryLanguages.LANG_METHODQL.equals(lang)) sq = new MethodStoreQuery(); else throw new UnsupportedException(lang); } Query q = newQueryImpl(lang, sq); q.setIgnoreChanges(_ignoreChanges); if (query != null) q.setQuery(query); // track queries if (_queries == null) _queries = new ReferenceHashSet(ReferenceHashSet.WEAK); _queries.add(q); return q; } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } /** * Create a new query. */ protected QueryImpl newQueryImpl(String lang, StoreQuery sq) { return new QueryImpl(this, lang, sq); } public Seq getIdentitySequence(ClassMetaData meta) { if (meta == null) return null; return getSequence(meta, null); } public Seq getValueSequence(FieldMetaData fmd) { if (fmd == null) return null; return getSequence(fmd.getDefiningMetaData(), fmd); } /** * Return a sequence for the given class and optional field. */ private Seq getSequence(ClassMetaData meta, FieldMetaData fmd) { // get sequence strategy from metadata int strategy; if (fmd == null) strategy = meta.getIdentityStrategy(); else strategy = fmd.getValueStrategy(); // we can handle non-native strategies without the store manager switch (strategy) { case ValueStrategies.UUID_HEX: return UUIDHexSeq.getInstance(); case ValueStrategies.UUID_STRING: return UUIDStringSeq.getInstance(); case ValueStrategies.UUID_TYPE4_HEX: return UUIDType4HexSeq.getInstance(); case ValueStrategies.UUID_TYPE4_STRING: return UUIDType4StringSeq.getInstance(); case ValueStrategies.SEQUENCE: SequenceMetaData smd = (fmd == null) ? meta.getIdentitySequenceMetaData() : fmd.getValueSequenceMetaData(); return smd.getInstance(_loader); default: // use store manager for native sequence if (fmd == null) { // This will return a sequence even for app id classes, // which is what we want for backwards-compatibility. // Even if user uses Application Identity, // user might use custom sequence information. // So, first, the sequence should be checked. // Trying to get primary key field if it has // sequence meta data. FieldMetaData[] pks = meta.getPrimaryKeyFields(); if (pks != null && pks.length == 1) { smd = pks[0].getValueSequenceMetaData(); } else { smd = meta.getIdentitySequenceMetaData(); } if (smd != null) { return smd.getInstance(_loader); } else { return _store.getDataStoreIdSequence(meta); } } return _store.getValueSequence(fmd); } } /////////// // Locking /////////// public void lock(Object obj, OpCallbacks call) { if (obj == null) return; beginOperation(true); // have to sync or lock level always NONE try { lock(obj, _fc.getWriteLockLevel(), _fc.getLockTimeout(), call); } finally { endOperation(); } } public void lock(Object obj, int level, int timeout, OpCallbacks call) { if (obj == null) return; beginOperation(true); try { assertActiveTransaction(); StateManagerImpl sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_LOCK, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) return; if (sm == null || !sm.isPersistent()) return; _lm.lock(sm, level, timeout, null); sm.readLocked(level, level); // use same level for future write } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } public void lockAll(Collection objs, OpCallbacks call) { if (objs.isEmpty()) return; beginOperation(true); // have to sync or lock level always NONE try { lockAll(objs, _fc.getWriteLockLevel(), _fc.getLockTimeout(), call); } finally { endOperation(); } } public void lockAll(Collection objs, int level, int timeout, OpCallbacks call) { if (objs.isEmpty()) return; if (objs.size() == 1) { lock(objs.iterator().next(), level, timeout, call); return; } beginOperation(true); try { assertActiveTransaction(); Collection sms = new LinkedHashSet(objs.size()); Object obj; StateManagerImpl sm; for (Iterator itr = objs.iterator(); itr.hasNext();) { obj = itr.next(); if (obj == null) continue; sm = getStateManagerImpl(obj, true); if ((processArgument(OpCallbacks.OP_LOCK, obj, sm, call) & OpCallbacks.ACT_RUN) == 0) continue; if (sm != null && sm.isPersistent()) sms.add(sm); } _lm.lockAll(sms, level, timeout, null); for (Iterator itr = sms.iterator(); itr.hasNext();) itr.next().readLocked(level, level); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { endOperation(); } } ////////////// // Connection ////////////// public boolean cancelAll() { // this method does not lock, since we want to allow a different // thread to be able to cancel on a locked-up persistence manager assertOpen(); try { // if we're flushing, have to set rollback only -- do this before we // attempt to cancel, because otherwise the cancel might case the // transaction to complete before we have a chance to set the // rollback only flag if ((_flags & FLAG_STORE_FLUSHING) != 0) setRollbackOnlyInternal(new UserException()); return _store.cancelAll(); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new StoreException(re); } } public Object getConnection() { assertOpen(); if (!_conf.supportedOptions().contains (OpenJPAConfiguration.OPTION_DATASTORE_CONNECTION)) throw new UnsupportedException(_loc.get("conn-not-supported")); return _store.getClientConnection(); } public boolean hasConnection() { assertOpen(); return (_flags & FLAG_RETAINED_CONN) != 0; } /** * Tell store to retain connection if we haven't already. */ private void retainConnection() { if ((_flags & FLAG_RETAINED_CONN) == 0) { _store.retainConnection(); _flags |= FLAG_RETAINED_CONN; } } /** * Tell store to release connection if we have retained one. */ private void releaseConnection() { if ((_flags & FLAG_RETAINED_CONN) != 0) { _store.releaseConnection(); _flags &= ~FLAG_RETAINED_CONN; } } ///////// // Cache ///////// public Collection getManagedObjects() { beginOperation(false); try { return new ManagedObjectCollection(getManagedStates()); } finally { endOperation(); } } public Collection getTransactionalObjects() { beginOperation(false); try { return new ManagedObjectCollection(getTransactionalStates()); } finally { endOperation(); } } public Collection getPendingTransactionalObjects() { beginOperation(false); try { return new ManagedObjectCollection (getPendingTransactionalStates()); } finally { endOperation(); } } public Collection getDirtyObjects() { beginOperation(false); try { return new ManagedObjectCollection(getDirtyStates()); } finally { endOperation(); } } public boolean getOrderDirtyObjects() { return _orderDirty; } public void setOrderDirtyObjects(boolean order) { _orderDirty = order; } /** * Return a copy of all managed state managers. */ protected Collection getManagedStates() { return _cache.copy(); } /** * Return a copy of all transactional state managers. */ protected Collection getTransactionalStates() { if (!hasTransactionalObjects()) { // return a new empty set. Entities may be added by TransactionListeners return new LinkedHashSet(); } return _transCache.copy(); } /** * Whether or not there are any transactional objects in the current * persistence context. If there are any instances with untracked state, * this method will cause those instances to be scanned. */ private boolean hasTransactionalObjects() { _cache.dirtyCheck(); return _transCache != null; } /** * Return a copy of all dirty state managers. */ protected Collection getDirtyStates() { if (!hasTransactionalObjects()) return Collections.EMPTY_SET; return _transCache.copyDirty(); } /** * Return a copy of all state managers which will become * transactional upon the next transaction. */ protected Collection getPendingTransactionalStates() { if (_pending == null) return Collections.EMPTY_SET; return new LinkedHashSet(_pending); } /** * Set the cached StateManager for the instance that had the given oid. * This method must not be called multiple times for new instances. * * @param id the id previously used by the instance * @param sm the state manager for the instance; if the state * manager is transient, we'll stop managing the instance; * if it has updated its oid, we'll re-cache under the new oid * @param status one of our STATUS constants describing why we're * setting the state manager */ protected void setStateManager(Object id, StateManagerImpl sm, int status) { lock(); try { switch (status) { case STATUS_INIT: // Only reset the flushed flag is this is a new instance. if (sm.isNew() && _compat.getResetFlushFlagForCascadePersist()) {// OPENJPA-2051 _flags &= ~FLAG_FLUSHED; } _cache.add(sm); break; case STATUS_TRANSIENT: _cache.remove(id, sm); break; case STATUS_OID_ASSIGN: assignObjectId(_cache, id, sm); break; case STATUS_COMMIT_NEW: _cache.commitNew(id, sm); break; default: throw new InternalException(); } } finally { unlock(); } } /** * Notify the broker that the given state manager should * be added to the set of instances involved in the current transaction. */ void addToTransaction(StateManagerImpl sm) { // we only add clean instances now; dirty instances are added in // the setDirty callback if (sm.isDirty()) return; lock(); try { if (!hasTransactionalObjects()) _transCache = new TransactionalCache(_orderDirty); _transCache.addClean(sm); } finally { unlock(); } } /** * Notify the persistence manager that the given state manager should * be removed from the set of instances involved in the current transaction. */ void removeFromTransaction(StateManagerImpl sm) { lock(); try { if (_transCache != null) // intentional direct access; we don't want to recompute // dirtiness while removing instances from the transaction _transCache.remove(sm); if (_derefCache != null && !sm.isPersistent()) _derefCache.remove(sm); } finally { unlock(); } } /** * Notification that the given instance has been dirtied. This * notification is given when an object first transitions to a dirty state, * and every time the object is modified by the user thereafter. */ void setDirty(StateManagerImpl sm, boolean firstDirty) { if (sm.isPersistent()) _flags |= FLAG_FLUSH_REQUIRED; if (_savepoints != null && !_savepoints.isEmpty()) { if (_savepointCache == null) _savepointCache = new HashSet(); _savepointCache.add(sm); } if (firstDirty && sm.isTransactional()) { lock(); try { // cache dirty instance if (!hasTransactionalObjects()) _transCache = new TransactionalCache(_orderDirty); _transCache.addDirty(sm); // also record that the class is dirty if (sm.isNew()) { if (_persistedClss == null) _persistedClss = new HashSet>(); _persistedClss.add(sm.getMetaData().getDescribedType()); } else if (sm.isDeleted()) { if (_deletedClss == null) _deletedClss = new HashSet>(); _deletedClss.add(sm.getMetaData().getDescribedType()); } else { if (_updatedClss == null) _updatedClss = new HashSet>(); _updatedClss.add(sm.getMetaData().getDescribedType()); } // if tracking changes and this instance wasn't already dirty, // add to changed set; we use this for detecting instances that // enter the transaction during pre store if ((_flags & FLAG_PRESTORING) != 0) { if (_transAdditions == null) _transAdditions = new HashSet(); _transAdditions.add(sm); } } finally { unlock(); } } } /** * Notify the broker that the given state manager should * be added to the set of instances that will become transactional * on the next transaction */ void addToPendingTransaction(StateManagerImpl sm) { lock(); try { if (_pending == null) _pending = new HashSet(); _pending.add(sm); } finally { unlock(); } } /** * Notify the persistence manager that the given state manager should * be removed from the set of instances involved in the next transaction. */ void removeFromPendingTransaction(StateManagerImpl sm) { lock(); try { if (_pending != null) _pending.remove(sm); if (_derefCache != null && !sm.isPersistent()) _derefCache.remove(sm); } finally { unlock(); } } /** * Add a dereferenced dependent object to the persistence manager's cache. * On flush, these objects will be deleted. */ void addDereferencedDependent(StateManagerImpl sm) { lock(); try { // if we're in the middle of flush and introducing more derefs // via instance callbacks, add them to the special additions set if ((_flags & FLAG_DEREFDELETING) != 0) { if (_derefAdditions == null) _derefAdditions = new HashSet(); _derefAdditions.add(sm); } else { if (_derefCache == null) _derefCache = new HashSet(); _derefCache.add(sm); } } finally { unlock(); } } /** * Remove the given previously dereferenced dependent object from the * cache. It is now referenced. */ void removeDereferencedDependent(StateManagerImpl sm) { lock(); try { boolean removed = false; if (_derefAdditions != null) removed = _derefAdditions.remove(sm); if (!removed && (_derefCache == null || !_derefCache.remove(sm))) throw new InvalidStateException(_loc.get("not-derefed", Exceptions.toString(sm.getManagedInstance()))). setFailedObject(sm.getManagedInstance()). setFatal(true); } finally { unlock(); } } public void dirtyType(Class cls) { if (cls == null) return; beginOperation(false); try { if (_updatedClss == null) _updatedClss = new HashSet>(); _updatedClss.add(cls); } finally { endOperation(); } } public Collection getPersistedTypes() { if (_persistedClss == null || _persistedClss.isEmpty()) return Collections.EMPTY_SET; return Collections.unmodifiableCollection(_persistedClss); } public Collection getUpdatedTypes() { if (_updatedClss == null || _updatedClss.isEmpty()) return Collections.EMPTY_SET; return Collections.unmodifiableCollection(_updatedClss); } public Collection getDeletedTypes() { if (_deletedClss == null || _deletedClss.isEmpty()) return Collections.EMPTY_SET; return Collections.unmodifiableCollection(_deletedClss); } /////////// // Closing /////////// public boolean isClosed() { return _closed; } public boolean isCloseInvoked() { return _closed || (_flags & FLAG_CLOSE_INVOKED) != 0; } public void close() { beginOperation(false); try { // throw an exception if closing in an active local trans if (!_managed && (_flags & FLAG_ACTIVE) != 0) throw new InvalidStateException(_loc.get("active")); // only close if not active; if active managed trans wait // for completion _flags |= FLAG_CLOSE_INVOKED; if ((_flags & FLAG_ACTIVE) == 0) free(); } finally { endOperation(); } } /** * Free the resources used by this persistence manager. */ protected void free() { RuntimeException err = null; if ((_autoDetach & DETACH_CLOSE) != 0) { try { detachAllInternal(_call); } catch (RuntimeException re) { err = re; } } _sync = null; _userObjects = null; _cache.clear(); _transCache = null; _persistedClss = null; _updatedClss = null; _deletedClss = null; _derefCache = null; _pending = null; _loader = null; _transEventManager = null; _lifeEventManager = null; OpenJPASavepoint save; while (_savepoints != null && !_savepoints.isEmpty()) { save = (OpenJPASavepoint) _savepoints.remove(_savepoints.size() - 1); save.release(false); } _savepoints = null; _savepointCache = null; if (_queries != null) { for (Iterator itr = _queries.iterator(); itr.hasNext();) { try { ((Query) itr.next()).closeResources(); } catch (RuntimeException re) { } } _queries = null; } if (_extents != null) { Extent e; for (Iterator itr = _extents.iterator(); itr.hasNext();) { e = (Extent) itr.next(); try { e.closeAll(); } catch (RuntimeException re) { } } _extents = null; } try { releaseConnection(); } catch (RuntimeException re) {} _lm.close(); _store.close(); if (_instm != null) { _instm.stop(InstrumentationLevel.BROKER, this); } _flags = 0; _closed = true; if (_log.isTraceEnabled()) _closedException = new IllegalStateException(); _factory.releaseBroker(this); if (err != null) throw err; } /////////////////// // Synchronization /////////////////// public void lock() { if (_lock != null) _lock.lock(); } public void unlock() { if (_lock != null) _lock.unlock(); } //////////////////// // State management //////////////////// public Object newInstance(Class cls) { assertOpen(); if (!cls.isInterface() && Modifier.isAbstract(cls.getModifiers())) throw new UnsupportedOperationException(_loc.get ("new-abstract", cls).getMessage()); // 1.5 doesn't initialize classes without a true Class.forName if (!PCRegistry.isRegistered(cls)) { try { Class.forName(cls.getName(), true, AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(cls))); } catch (Throwable t) { } } if (_repo.getMetaData(cls, getClassLoader(), false) == null) throw new IllegalArgumentException( _loc.get("no-interface-metadata", cls.getName()).getMessage()); try { return PCRegistry.newInstance(cls, null, false); } catch (IllegalStateException ise) { IllegalArgumentException iae = new IllegalArgumentException(ise.getMessage()); iae.setStackTrace(ise.getStackTrace()); throw iae; } } public Object getObjectId(Object obj) { assertOpen(); if (ImplHelper.isManageable(obj)) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(obj, _conf); if (pc != null) { if (pc.pcGetStateManager() == null) { // If the statemanager is null the call to pcFetchObjectId always returns null. Create a new object // id. return ApplicationIds.create(pc, _repo.getMetaData(pc.getClass(), null, true)); } return pc.pcFetchObjectId(); } } return null; } public int getLockLevel(Object o) { assertOpen(); if (o == null) return LockLevels.LOCK_NONE; OpenJPAStateManager sm = getStateManager(o); if (sm == null) return LockLevels.LOCK_NONE; return getLockManager().getLockLevel(sm); } public Object getVersion(Object obj) { assertOpen(); if (ImplHelper.isManageable(obj)) return (ImplHelper.toPersistenceCapable(obj, _conf)).pcGetVersion(); return null; } public boolean isDirty(Object obj) { assertOpen(); if (ImplHelper.isManageable(obj)) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(obj, _conf); return pc.pcIsDirty(); } return false; } public boolean isTransactional(Object obj) { assertOpen(); if (ImplHelper.isManageable(obj)) return (ImplHelper.toPersistenceCapable(obj, _conf)) .pcIsTransactional(); return false; } public boolean isPersistent(Object obj) { assertOpen(); if (ImplHelper.isManageable(obj)) return (ImplHelper.toPersistenceCapable(obj, _conf)). pcIsPersistent(); return false; } public boolean isNew(Object obj) { assertOpen(); if (ImplHelper.isManageable(obj)) return (ImplHelper.toPersistenceCapable(obj, _conf)).pcIsNew(); return false; } public boolean isDeleted(Object obj) { assertOpen(); if (ImplHelper.isManageable(obj)) return (ImplHelper.toPersistenceCapable(obj, _conf)).pcIsDeleted(); return false; } public boolean isDetached(Object obj) { return isDetached(obj, true); } /** * This method makes a best effort to determine if the provided object is detached. * * @param obj * @param find * - If true, as a last resort this method will check whether or not the provided object exists in the * DB. If it is in the DB, the provided object is detached. * @return - True if the provided obj is detached, false otherwise. */ public boolean isDetached(Object obj, boolean find) { if (!(ImplHelper.isManageable(obj))) return false; PersistenceCapable pc = ImplHelper.toPersistenceCapable(obj, _conf); if (pc.pcGetStateManager() instanceof DetachedStateManager) return true; Boolean detached = pc.pcIsDetached(); if (detached != null) return detached.booleanValue(); // last resort: instance is detached if it has a store record ClassMetaData meta = _repo.getMetaData(ImplHelper.getManagedInstance(pc).getClass(), _loader, true); Object oid = ApplicationIds.create(pc, meta); if (oid == null) return false; if(!find){ return false; } return find(oid, null, EXCLUDE_ALL, null, 0) != null; } public OpenJPAStateManager getStateManager(Object obj) { assertOpen(); return getStateManagerImpl(obj, false); } /** * Return the state manager for the given instance, or null. * * @param assertThisContext if true, thow an exception if the given * object is managed by another broker */ protected StateManagerImpl getStateManagerImpl(Object obj, boolean assertThisContext) { if (ImplHelper.isManageable(obj)) { PersistenceCapable pc = ImplHelper.toPersistenceCapable(obj, _conf); BrokerImpl pcBroker = (BrokerImpl)pc.pcGetGenericContext(); if (pcBroker == this || isFromWriteBehindCallback()) return (StateManagerImpl) pc.pcGetStateManager(); if (assertThisContext && pcBroker != null) throw new UserException(_loc.get("not-managed", Exceptions.toString(obj))).setFailedObject(obj); } return null; } /** * Return the state manager for the given oid. * * @param allowNew if true, objects made persistent in the current * transaction will be included in the search; if * multiple new objects match the given oid, it is * undefined which will be returned */ protected StateManagerImpl getStateManagerImplById(Object oid, boolean allowNew) { return _cache.getById(oid, allowNew); } /** * Return the given instance as a {@link PersistenceCapable}. * If the instance is not manageable throw the proper exception. */ protected PersistenceCapable assertPersistenceCapable(Object obj) { if (obj == null) return null; if (ImplHelper.isManageable(obj)) return ImplHelper.toPersistenceCapable(obj, _conf); // check for different instances of the PersistenceCapable interface // and throw a better error that mentions the class loaders Class[] intfs = obj.getClass().getInterfaces(); for (int i = 0; intfs != null && i < intfs.length; i++) { if (intfs[i].getName().equals(PersistenceCapable.class.getName())) { throw new UserException(_loc.get("pc-loader-different", Exceptions.toString(obj), AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction( PersistenceCapable.class)), AccessController.doPrivileged( J2DoPrivHelper.getClassLoaderAction(intfs[i])))) .setFailedObject(obj); } } // not enhanced throw new UserException(_loc.get("pc-cast", Exceptions.toString(obj))).setFailedObject(obj); } ///////// // Utils ///////// /** * Throw an exception if the context is closed. The exact message and * content of the exception varies whether TRACE is enabled or not. */ public void assertOpen() { if (_closed) { if (_closedException == null) // TRACE not enabled throw new InvalidStateException(_loc.get("closed-notrace")) .setFatal(true); else { OpenJPAException e = new InvalidStateException( _loc.get("closed"), _closedException).setFatal(true); e.setCause(_closedException); throw e; } } } public void assertActiveTransaction() { if ((_flags & FLAG_ACTIVE) == 0) throw new NoTransactionException(_loc.get("not-active")); } /** * Throw exception if a transaction-related operation is attempted and * no transaction is active. */ private void assertTransactionOperation() { if ((_flags & FLAG_ACTIVE) == 0) throw new InvalidStateException(_loc.get("not-active")); } public void assertNontransactionalRead() { if ((_flags & FLAG_ACTIVE) == 0 && !_nontransRead) throw new InvalidStateException(_loc.get("non-trans-read")); } public void assertWriteOperation() { if ((_flags & FLAG_ACTIVE) == 0 && (!_nontransWrite || (_autoDetach & DETACH_NONTXREAD) != 0)) throw new NoTransactionException(_loc.get("write-operation")); } /** * Return an object not found exception containing nested exceptions * for all of the given failed objects. */ private static ObjectNotFoundException newObjectNotFoundException (Collection failed) { Throwable[] t = new Throwable[failed.size()]; int idx = 0; for (Iterator itr = failed.iterator(); itr.hasNext(); idx++) t[idx] = new ObjectNotFoundException(itr.next()); return new ObjectNotFoundException(failed, t); } //////////////////////////////// // FindCallbacks implementation //////////////////////////////// public Object processArgument(Object oid) { return oid; } public Object processReturn(Object oid, OpenJPAStateManager sm) { return (sm == null) ? null : sm.getManagedInstance(); } private void writeObject(ObjectOutputStream out) throws IOException { assertOpen(); lock(); try { if (isActive()) { if (!getOptimistic()) throw new InvalidStateException( _loc.get("cant-serialize-pessimistic-broker")); if (hasFlushed()) throw new InvalidStateException( _loc.get("cant-serialize-flushed-broker")); if (hasConnection()) throw new InvalidStateException( _loc.get("cant-serialize-connected-broker")); } try { _isSerializing = true; out.writeObject(_factory.getPoolKey()); out.defaultWriteObject(); } finally { _isSerializing = false; } } finally { unlock(); } } private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { Object factoryKey = in.readObject(); AbstractBrokerFactory factory = AbstractBrokerFactory.getPooledFactoryForKey(factoryKey); // this needs to happen before defaultReadObject so that it's // available for calls to broker.getConfiguration() during // StateManager deserialization _conf = factory.getConfiguration(); _repo = _conf.getMetaDataRepositoryInstance(); in.defaultReadObject(); factory.initializeBroker(_managed, _connRetainMode, this, true); // re-initialize the lock if needed. setMultithreaded(_multithreaded); // force recreation of set _operatingDirty = true; initializeOperatingSet(); if (isActive() && _runtime instanceof LocalManagedRuntime) ((LocalManagedRuntime) _runtime).begin(); } /** * Whether or not this broker is in the midst of being serialized. * * @since 1.1.0 */ boolean isSerializing() { return _isSerializing; } /** * @return The value of openjpa.ConnectionFactoryProperties.PrintParameters. Default is false. */ public boolean getPrintParameters() { return _printParameters; } /** * Transactional cache that holds soft refs to clean instances. */ static class TransactionalCache implements Set, Serializable { private final boolean _orderDirty; private Set _dirty = null; private Set _clean = null; public TransactionalCache(boolean orderDirty) { _orderDirty = orderDirty; } /** * Return a copy of all transactional state managers. */ public Collection copy() { if (isEmpty()) { // Transaction Listeners may add entities to the transaction. return new LinkedHashSet(); } // size may not be entirely accurate due to refs expiring, so // manually copy each object; doesn't matter this way if size too // big by some Set copy = new LinkedHashSet(size()); if (_dirty != null) for (Iterator itr = _dirty.iterator(); itr.hasNext();) copy.add(itr.next()); if (_clean != null) for (Iterator itr = _clean.iterator(); itr.hasNext();) copy.add(itr.next()); return copy; } /** * Return a copy of all dirty state managers. */ public Collection copyDirty() { if (_dirty == null || _dirty.isEmpty()) return Collections.EMPTY_SET; return new LinkedHashSet(_dirty); } /** * Transfer the given instance from the dirty cache to the clean cache. */ public void flushed(StateManagerImpl sm) { if (sm.isDirty() && _dirty != null && _dirty.remove(sm)) addCleanInternal(sm); } /** * Add the given instance to the clean cache. */ public void addClean(StateManagerImpl sm) { if (addCleanInternal(sm) && _dirty != null) _dirty.remove(sm); } private boolean addCleanInternal(StateManagerImpl sm) { if (_clean == null) _clean = new ReferenceHashSet(ReferenceHashSet.SOFT); return _clean.add(sm); } /** * Add the given instance to the dirty cache. */ public void addDirty(StateManagerImpl sm) { if (_dirty == null) { if (_orderDirty) _dirty = MapBackedSet.decorate(new LinkedMap()); else _dirty = new HashSet(); } if (_dirty.add(sm)) removeCleanInternal(sm); } /** * Remove the given instance from the cache. */ public boolean remove(StateManagerImpl sm) { return removeCleanInternal(sm) || (_dirty != null && _dirty.remove(sm)); } private boolean removeCleanInternal(StateManagerImpl sm) { return _clean != null && _clean.remove(sm); } public Iterator iterator() { IteratorChain chain = new IteratorChain(); if (_dirty != null && !_dirty.isEmpty()) chain.addIterator(_dirty.iterator()); if (_clean != null && !_clean.isEmpty()) chain.addIterator(_clean.iterator()); return chain; } public boolean contains(Object obj) { return (_dirty != null && _dirty.contains(obj)) || (_clean != null && _clean.contains(obj)); } public boolean containsAll(Collection coll) { for (Iterator itr = coll.iterator(); itr.hasNext();) if (!contains(itr.next())) return false; return true; } public void clear() { if (_dirty != null) _dirty = null; if (_clean != null) _clean = null; } public boolean isEmpty() { return (_dirty == null || _dirty.isEmpty()) && (_clean == null || _clean.isEmpty()); } public int size() { int size = 0; if (_dirty != null) size += _dirty.size(); if (_clean != null) size += _clean.size(); return size; } public boolean add(Object obj) { throw new UnsupportedOperationException(); } public boolean addAll(Collection coll) { throw new UnsupportedOperationException(); } public boolean remove(Object obj) { throw new UnsupportedOperationException(); } public boolean removeAll(Collection coll) { throw new UnsupportedOperationException(); } public boolean retainAll(Collection c) { throw new UnsupportedOperationException(); } public Object[] toArray() { throw new UnsupportedOperationException(); } public Object[] toArray(Object[] arr) { throw new UnsupportedOperationException(); } } /** * Unique id for state managers of new datastore instances without assigned * object ids. */ public static class StateManagerId implements Serializable { public static final String STRING_PREFIX = "openjpasm:"; private static long _generator = 0; private final int _bhash; private final long _id; public static StateManagerId newInstance(Broker b) { return new StateManagerId(System.identityHashCode(b), _generator++); } private StateManagerId(int bhash, long id) { _bhash = bhash; _id = id; } public StateManagerId(String str) { str = str.substring(STRING_PREFIX.length()); int idx = str.indexOf(':'); _bhash = Integer.parseInt(str.substring(0, idx)); _id = Long.parseLong(str.substring(idx + 1)); } public boolean equals(Object other) { if (other == this) return true; if ((other == null) || (other.getClass() != this.getClass())) return false; StateManagerId sid = (StateManagerId) other; return _bhash == sid._bhash && _id == sid._id; } public int hashCode() { return (int) (_id ^ (_id >>> 32)); } public String toString() { return STRING_PREFIX + _bhash + ":" + _id; } } /** * Collection type that holds state managers but whose interface deals * with the corresponding managed objects. */ private static class ManagedObjectCollection extends AbstractCollection { private final Collection _states; public ManagedObjectCollection(Collection states) { _states = states; } public Collection getStateManagers() { return _states; } public int size() { return _states.size(); } public Iterator iterator() { return new Iterator() { private final Iterator _itr = _states.iterator(); public boolean hasNext() { return _itr.hasNext(); } public Object next() { return ((OpenJPAStateManager) _itr.next()). getManagedInstance(); } public void remove() { throw new UnsupportedException(); } }; } } /** * Assign the object id to the cache. Exception will be * thrown if the id already exists in the cache. */ protected void assignObjectId(Object cache, Object id, StateManagerImpl sm) { ((ManagedCache) cache).assignObjectId(id, sm); } /** * This method makes sure we don't already have the instance cached */ protected void checkForDuplicateId(Object id, Object obj, ClassMetaData meta) { FieldMetaData[] pks = meta.getPrimaryKeyFields(); if (pks != null && pks.length == 1 && pks[0].getValueStrategy() == ValueStrategies.AUTOASSIGN) { return; } StateManagerImpl other = getStateManagerImplById(id, false); if (other != null && !other.isDeleted() && !other.isNew()) throw new ObjectExistsException(_loc.get("cache-exists", obj.getClass().getName(), id)).setFailedObject(obj); } public boolean getCachePreparedQuery() { lock(); try { return _cachePreparedQuery && _conf.getQuerySQLCacheInstance() != null; } finally { unlock(); } } public void setCachePreparedQuery(boolean flag) { lock(); try { _cachePreparedQuery = flag; } finally { unlock(); } } public boolean getCacheFinderQuery() { lock(); try { return _cacheFinderQuery && _conf.getFinderCacheInstance() != null; } finally { unlock(); } } public void setCacheFinderQuery(boolean flag) { lock(); try { _cachePreparedQuery = flag; } finally { unlock(); } } public boolean isFromWriteBehindCallback() { return _fromWriteBehindCallback; } /** * Return the 'JTA' connectionFactoryName */ public String getConnectionFactoryName() { return _connectionFactoryName; } /** * Set the 'JTA' ConnectionFactoryName. Input will be trimmed to null before being stored. */ public void setConnectionFactoryName(String connectionFactoryName) { this._connectionFactoryName = StringUtils.trimToNull(connectionFactoryName); } /** * Return the 'NonJTA' ConnectionFactoryName. */ public String getConnectionFactory2Name() { return _connectionFactory2Name; } /** * Set the 'NonJTA' ConnectionFactoryName. Input will be trimmed to null before being stored. */ public void setConnectionFactory2Name(String connectionFactory2Name) { this._connectionFactory2Name = StringUtils.trimToNull(connectionFactory2Name); } /** * Return the 'JTA' ConnectionFactory, looking it up from JNDI if needed. * * @return the JTA connection factory or null if connectionFactoryName is blank. */ public Object getConnectionFactory() { if(StringUtils.isNotBlank(_connectionFactoryName)) { return Configurations.lookup(_connectionFactoryName, "openjpa.ConnectionFactory", _log ); } else { return null; } } /** * Return the 'NonJTA' ConnectionFactory, looking it up from JNDI if needed. * * @return the NonJTA connection factory or null if connectionFactoryName is blank. */ public Object getConnectionFactory2() { if(StringUtils.isNotBlank(_connectionFactory2Name)) { return Configurations.lookup(_connectionFactory2Name, "openjpa.ConnectionFactory2", _log); } else { return null; } } public boolean isCached(List oids) { BitSet loaded = new BitSet(oids.size()); //check L1 cache first for (int i = 0; i < oids.size(); i++) { Object oid = oids.get(i); if (_cache.getById(oid, false) != null) { loaded.set(i); } } if(loaded.cardinality()==oids.size()){ return true; } return _store.isCached(oids, loaded); }; public boolean getAllowReferenceToSiblingContext() { return _allowReferenceToSiblingContext; } public void setAllowReferenceToSiblingContext(boolean allow) { _allowReferenceToSiblingContext = allow; } protected boolean isFlushing() { return ((_flags & FLAG_FLUSHING) != 0); } public boolean getPostLoadOnMerge() { return _postLoadOnMerge; } public void setPostLoadOnMerge(boolean allow) { _postLoadOnMerge = allow; } /** * Asserts consistencey of given automatic detachment option value. */ private void assertAutoDetachValue(int value) { if (((value & AutoDetach.DETACH_NONE) != 0) && (value != AutoDetach.DETACH_NONE)) { throw new UserException(_loc.get("detach-none-exclusive", toAutoDetachString(value))); } } /** * Generates a user-readable String from the given integral value of AutoDetach options. */ private String toAutoDetachString(int value) { List result = new ArrayList(); for (int i = 0; i < AutoDetach.values.length; i++) { if ((value & AutoDetach.values[i]) != 0) { result.add(AutoDetach.names[i]); } } return Arrays.toString(result.toArray(new String[result.size()])); } private boolean operatingAdd(Object o) { _operatingDirty = true; return _operating.add(o); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/0000755000000000000000000000000012133327270024236 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/package.html0000644000000000000000000000162112133327270026517 0ustar

    JPA Query Language Support

    Allow any spec or store to use JPQL.

    openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/SimpleNode.java0000644000000000000000000000221012133327270027133 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.jpql; /** * Base node implementation for all JPQL nodes. Subclasses will be * generated as part of the JavaCC process. * * @author Marc Prud'hommeaux * @nojavadoc */ public class SimpleNode extends JPQLExpressionBuilder.JPQLNode { SimpleNode(JPQL parser, int id) { super(parser, id); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLParser.java0000644000000000000000000000576212133327270027036 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.jpql; import org.apache.openjpa.kernel.ExpressionStoreQuery; import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.kernel.exps.ExpressionParser; import org.apache.openjpa.kernel.exps.QueryExpressions; import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; /** * Parser for JPQL queries. * * @author Marc Prud'hommeaux * @nojavadoc */ public class JPQLParser implements ExpressionParser { private static final Localizer _loc = Localizer.forPackage(JPQLParser.class); public static final String LANG_JPQL = "javax.persistence.JPQL"; public Object parse(String ql, ExpressionStoreQuery query) { if (query.getContext().getParameterDeclaration() != null) throw new UserException(_loc.get("param-decs-invalid")); try { return new JPQLExpressionBuilder.ParsedJPQL(ql); } catch (ParseException e) { throw new ParseException(_loc.get("jpql-parse-error", ql, e.getMessage()).getMessage(), e); } } public void populate(Object parsed, ExpressionStoreQuery query) { if (!(parsed instanceof JPQLExpressionBuilder.ParsedJPQL)) throw new ClassCastException(parsed == null ? null + "" : parsed.getClass().getName()); ((JPQLExpressionBuilder.ParsedJPQL) parsed).populate(query); } public QueryExpressions eval(Object parsed, ExpressionStoreQuery query, ExpressionFactory factory, ClassMetaData candidate) { try { return new JPQLExpressionBuilder(factory, query, parsed). getQueryExpressions(); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new UserException(_loc.get("bad-jpql", parsed), e); } } public Value[] eval(String[] vals, ExpressionStoreQuery query, ExpressionFactory factory, ClassMetaData candidate) { return null; } public String getLanguage() { return JPQLParser.LANG_JPQL; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder0000644000000000000000000025635512133327270030336 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.jpql; import java.io.PrintStream; import java.io.Serializable; import java.lang.reflect.Field; import java.math.BigDecimal; import java.sql.Time; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.Stack; import java.util.TreeSet; import org.apache.openjpa.conf.Compatibility; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.ExpressionStoreQuery; import org.apache.openjpa.kernel.FillStrategy; import org.apache.openjpa.kernel.QueryContext; import org.apache.openjpa.kernel.QueryOperations; import org.apache.openjpa.kernel.ResultShape; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.kernel.exps.AbstractExpressionBuilder; import org.apache.openjpa.kernel.exps.Context; import org.apache.openjpa.kernel.exps.Expression; import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.kernel.exps.Literal; import org.apache.openjpa.kernel.exps.Parameter; import org.apache.openjpa.kernel.exps.Path; import org.apache.openjpa.kernel.exps.QueryExpressions; import org.apache.openjpa.kernel.exps.Resolver; import org.apache.openjpa.kernel.exps.Subquery; import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.lib.util.Localizer.Message; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.UserException; /** * Builder for JPQL expressions. This class takes the query parsed * in {@link JPQL} and converts it to an expression tree using * an {@link ExpressionFactory}. Public for unit testing purposes. * * @author Marc Prud'hommeaux * @author Patrick Linskey * @nojavadoc */ public class JPQLExpressionBuilder extends AbstractExpressionBuilder implements JPQLTreeConstants { private static final int VAR_PATH = 1; private static final int VAR_ERROR = 2; private static final Localizer _loc = Localizer.forPackage (JPQLExpressionBuilder.class); private final Stack contexts = new Stack(); private OrderedMap> parameterTypes; private int aliasCount = 0; private boolean inAssignSubselectProjection = false; private boolean hasParameterizedInExpression = false; /** * Constructor. * * @param factory the expression factory to use * @param query used to resolve variables, parameters, * and class names used in the query * @param parsedQuery the parsed query */ public JPQLExpressionBuilder(ExpressionFactory factory, ExpressionStoreQuery query, Object parsedQuery) { super(factory, query.getResolver()); contexts.push(new Context(parsedQuery instanceof ParsedJPQL ? (ParsedJPQL) parsedQuery : parsedQuery instanceof String ? getParsedQuery((String) parsedQuery) : null, null, null)); if (ctx().parsed == null) throw new InternalException(parsedQuery + ""); } protected Localizer getLocalizer() { return _loc; } protected ClassLoader getClassLoader() { // we don't resolve in the context of anything but ourselves return getClass().getClassLoader(); } protected ParsedJPQL getParsedQuery() { return ctx().parsed; } protected ParsedJPQL getParsedQuery(String jpql) { return new ParsedJPQL(jpql); } private void setCandidate(ClassMetaData cmd, String schemaAlias) { addAccessPath(cmd); if (cmd != null) ctx().meta = cmd; if (schemaAlias != null) ctx().schemaAlias = schemaAlias; } private String nextAlias() { return "jpqlalias" + (++aliasCount); } protected ClassMetaData resolveClassMetaData(JPQLNode node) { // handle looking up alias names String schemaName = assertSchemaName(node); ClassMetaData cmd = getClassMetaData(schemaName, false); if (cmd != null) return cmd; // we might be referencing a collection field of a subquery's parent if (isPath(node)) { Path path = getPath(node); FieldMetaData fmd = path.last(); cmd = getFieldType(fmd); if (cmd == null && fmd.isElementCollection()) cmd = fmd.getDefiningMetaData(); return cmd; } // now run again to throw the correct exception return getClassMetaData(schemaName, true); } private ClassMetaData getClassMetaData(String alias, boolean assertValid) { ClassLoader loader = getClassLoader(); MetaDataRepository repos = resolver.getConfiguration(). getMetaDataRepositoryInstance(); // first check for the alias ClassMetaData cmd = repos.getMetaData(alias, loader, false); if (cmd != null) return cmd; // now check for the class name; this is not technically permitted // by the JPA spec, but is required in order to be able to execute // JPQL queries from other facades (like JDO) that do not have // the concept of entity names or aliases Class c = resolver.classForName(alias, null); if (c != null) cmd = repos.getMetaData(c, loader, assertValid); else if (assertValid) cmd = repos.getMetaData(alias, loader, false); if (cmd == null && assertValid) { String close = repos.getClosestAliasName(alias); if (close != null) throw parseException(EX_USER, "not-schema-name-hint", new Object[]{ alias, close, repos.getAliasNames() }, null); else throw parseException(EX_USER, "not-schema-name", new Object[]{ alias, repos.getAliasNames() }, null); } return cmd; } private Class getCandidateType() { return getCandidateMetaData().getDescribedType(); } private ClassMetaData getCandidateMetaData() { if (ctx().meta != null) return ctx().meta; ClassMetaData cls = getCandidateMetaData(root()); if (cls == null) throw parseException(EX_USER, "not-schema-name", new Object[]{ root() }, null); setCandidate(cls, null); return cls; } protected ClassMetaData getCandidateMetaData(JPQLNode node) { // examing the node to find the candidate query // ### this should actually be the primary SELECT instance // resolved against the from variable declarations JPQLNode from = node.findChildByID(JJTFROMITEM, true); if (from == null) { // OPENJPA-15 allow subquery without a FROMITEM if (node.id == JJTSUBSELECT) { from = node.findChildByID(JJTFROM, true); } else { throw parseException(EX_USER, "no-from-clause", null, null); } } for (int i = 0; i < from.children.length; i++) { JPQLNode n = from.children[i]; if (n.id == JJTABSTRACTSCHEMANAME) { // we simply return the first abstract schema child // as resolved into a class ClassMetaData cmd = resolveClassMetaData(n); if (cmd != null) return cmd; // not a schema: treat it as a class String cls = assertSchemaName(n); if (cls == null) throw parseException(EX_USER, "not-schema-name", new Object[]{ root() }, null); return getClassMetaData(cls, true); } // OPENJPA-15 support subquery's from clause do not start with // identification_variable_declaration() if (node.id == JJTSUBSELECT) { if (n.id == JJTINNERJOIN) { n = n.getChild(0); } if (n.id == JJTPATH) { Path path = getPath(n); FieldMetaData fmd = path.last(); ClassMetaData cmd = getFieldType(fmd); if (cmd == null && fmd.isElementCollection()) cmd = fmd.getDefiningMetaData(); if (cmd != null) { return cmd; } else { throw parseException(EX_USER, "no-alias", new Object[]{ n }, null); } } } } return null; } protected String currentQuery() { return ctx().parsed == null || root().parser == null ? null : root().parser.jpql; } QueryExpressions getQueryExpressions() { QueryExpressions exps = new QueryExpressions(); exps.setContexts(contexts); evalQueryOperation(exps); Expression filter = null; Expression from = ctx().from; if (from == null) from = evalFromClause(root().id == JJTSELECT); filter = and(from, filter); filter = and(evalWhereClause(), filter); filter = and(evalSelectClause(exps), filter); exps.filter = filter == null ? factory.emptyExpression() : filter; evalGroupingClause(exps); evalHavingClause(exps); evalFetchJoins(exps); evalSetClause(exps); evalOrderingClauses(exps); if (parameterTypes != null) exps.parameterTypes = parameterTypes; exps.accessPath = getAccessPath(); exps.hasInExpression = this.hasParameterizedInExpression; // verify parameters are consistent. validateParameters(); return exps; } private Expression and(Expression e1, Expression e2) { return e1 == null ? e2 : e2 == null ? e1 : factory.and(e1, e2); } private static String assemble(JPQLNode node) { return assemble(node, ".", 0); } /** * Assemble the children of the specific node by appending each * child, separated by the delimiter. */ private static String assemble(JPQLNode node, String delimiter, int last) { StringBuilder result = new StringBuilder(); JPQLNode[] parts = node.children; for (int i = 0; parts != null && i < parts.length - last; i++) result.append(result.length() > 0 ? delimiter : ""). append(parts[i].text); return result.toString(); } private Expression assignSubselectProjection(JPQLNode node, QueryExpressions exps) { inAssignSubselectProjection = true; exps.projections = new Value[1]; exps.projectionClauses = new String[1]; exps.projectionAliases = new String[1]; Value val = getValue(node); exps.projections[0] = val; exps.projectionClauses[0] = projectionClause(node.id == JJTSCALAREXPRESSION ? firstChild(node) : node); inAssignSubselectProjection = false; return null; } /** * Assign projections for NEW contructor in selection list. * Example: SELECT NEW Person(p.name) FROM Person p WHERE ... */ private Expression assignProjections(JPQLNode parametersNode, QueryExpressions exps, List projections, List projectionClauses, List projectionAliases) { int count = parametersNode.getChildCount(); Expression exp = null; for (int i = 0; i < count; i++) { JPQLNode parent = parametersNode.getChild(i); JPQLNode node = firstChild(parent); JPQLNode aliasNode = parent.children.length > 1 ? right(parent) : null; Value proj = getValue(node); String alias = aliasNode != null ? aliasNode.text : projectionClause(node.id == JJTSCALAREXPRESSION ? firstChild(node) : node); if (aliasNode != null) proj.setAlias(alias); projections.add(proj); projectionClauses.add(alias); projectionAliases.add(alias); } return exp; } private void evalProjectionsResultShape(JPQLNode selectionsNode, QueryExpressions exps, List projections, List projectionClauses, List projectionAliases) { int count = selectionsNode.getChildCount(); Class resultClass = null; ResultShape resultShape = null; if (count > 1) { // muti-selection resultClass = Object[].class; resultShape = new ResultShape(resultClass, new FillStrategy.Array(Object[].class)); } for (int i = 0; i < count; i++) { JPQLNode parent = selectionsNode.getChild(i); JPQLNode node = firstChild(parent); if (node.id == JJTCONSTRUCTOR) { // build up the fully-qualified result class name by // appending together the components of the children String resultClassName = assemble(left(node)); Class constructor = resolver.classForName(resultClassName, null); if (constructor == null) { // try resolve it again using simple name int n = left(node).getChildCount(); String baseName = left(node).getChild(n-1).text; constructor = resolver.classForName(baseName, null); } if (constructor == null) throw parseException(EX_USER, "no-constructor", new Object[]{ resultClassName }, null); List terms = new ArrayList(); List aliases = new ArrayList(); List clauses = new ArrayList(); // now assign the arguments to the select clause as the projections assignProjections(right(node), exps, terms, aliases, clauses); FillStrategy fill = new FillStrategy.NewInstance(constructor); ResultShape cons = new ResultShape(constructor, fill); for (Value val : terms) { Class type = val.getType(); cons.nest(new ResultShape(type, new FillStrategy.Assign(), type.isPrimitive())); } if (count == 1) { resultClass = constructor; resultShape = cons; } else resultShape.nest(cons); projections.addAll(terms); projectionAliases.addAll(aliases); projectionClauses.addAll(clauses); } else { JPQLNode aliasNode = parent.children.length > 1 ? right(parent) : null; Value proj = getValue(node); String alias = aliasNode != null ? aliasNode.text : projectionClause(node.id == JJTSCALAREXPRESSION ? firstChild(node) : node); if (aliasNode != null) proj.setAlias(alias); projections.add(proj); projectionClauses.add(alias); projectionAliases.add(alias); Class type = proj.getType(); ResultShape projShape = new ResultShape(type, new FillStrategy.Assign(), type.isPrimitive()); if (count == 1) resultShape = projShape; else resultShape.nest(projShape); } } exps.shape = resultShape; exps.resultClass = resultClass; } private String projectionClause(JPQLNode node) { switch (node.id) { case JJTTYPE: return projectionClause(firstChild(node)); default: return assemble(node); } } private void evalQueryOperation(QueryExpressions exps) { // determine whether we want to select, delete, or update if (root().id == JJTSELECT || root().id == JJTSUBSELECT) exps.operation = QueryOperations.OP_SELECT; else if (root().id == JJTDELETE) exps.operation = QueryOperations.OP_DELETE; else if (root().id == JJTUPDATE) exps.operation = QueryOperations.OP_UPDATE; else throw parseException(EX_UNSUPPORTED, "unrecognized-operation", new Object[]{ root() }, null); } private void evalGroupingClause(QueryExpressions exps) { // handle GROUP BY clauses JPQLNode groupByNode = root().findChildByID(JJTGROUPBY, false); if (groupByNode == null) return; int groupByCount = groupByNode.getChildCount(); exps.grouping = new Value[groupByCount]; for (int i = 0; i < groupByCount; i++) { JPQLNode node = groupByNode.getChild(i); Value val = getValue(node); if (val instanceof Path) { FieldMetaData fmd = ((Path) val).last(); if (fmd != null && fmd.getValue().getTypeMetaData() != null && fmd.getValue().isEmbedded()) throw parseException(EX_USER, "cant-groupby-embeddable", new Object[]{ node.getChildCount() > 1 ? assemble(node) : node.text }, null); } exps.grouping[i] = val; } } private void evalHavingClause(QueryExpressions exps) { // handle HAVING clauses JPQLNode havingNode = root().findChildByID(JJTHAVING, false); if (havingNode == null) return; exps.having = getExpression(onlyChild(havingNode)); } private void evalOrderingClauses(QueryExpressions exps) { // handle ORDER BY clauses JPQLNode orderby = root().findChildByID(JJTORDERBY, false); if (orderby != null) { int ordercount = orderby.getChildCount(); exps.ordering = new Value[ordercount]; exps.orderingClauses = new String[ordercount]; exps.orderingAliases = new String[ordercount]; exps.ascending = new boolean[ordercount]; for (int i = 0; i < ordercount; i++) { JPQLNode node = orderby.getChild(i); JPQLNode firstChild = firstChild(node); exps.ordering[i] = getValue(firstChild); exps.orderingClauses[i] = assemble(firstChild); exps.orderingAliases[i] = firstChild.text; // ommission of ASC/DESC token implies ascending exps.ascending[i] = node.getChildCount() <= 1 || lastChild(node).id == JJTASCENDING ? true : false; } // check if order by select item result alias for (int i = 0; i < ordercount; i++) { if (exps.orderingClauses[i] != null && !exps.orderingClauses[i].equals("")) continue; for (int j = 0; j < exps.projections.length; j++) { if (exps.projectionAliases[j].equalsIgnoreCase( exps.orderingAliases[i])) { exps.ordering[i] = exps.projections[j]; break; } } } } } private Expression evalSelectClause(QueryExpressions exps) { if (exps.operation != QueryOperations.OP_SELECT) return null; JPQLNode selectNode = root(); JPQLNode selectClause = selectNode. findChildByID(JJTSELECTCLAUSE, false); if (selectClause != null && selectClause.hasChildID(JJTDISTINCT)) exps.distinct = QueryExpressions.DISTINCT_TRUE | QueryExpressions.DISTINCT_AUTO; else exps.distinct = QueryExpressions.DISTINCT_FALSE; // handle SELECT clauses JPQLNode expNode = selectNode. findChildByID(JJTSELECTEXPRESSIONS, true); if (expNode == null) { return null; } int selectCount = expNode.getChildCount(); JPQLNode selectChild = firstChild(expNode); if (selectClause.parent.id == JJTSUBSELECT) { exps.distinct &= ~QueryExpressions.DISTINCT_AUTO; return assignSubselectProjection(onlyChild(selectChild), exps); } // if we are selecting just one thing and that thing is the // schema's alias, then do not treat it as a projection if (selectCount == 1 && selectChild != null && selectChild.getChildCount() == 1 && onlyChild(selectChild) != null) { JPQLNode child = onlyChild(selectChild); if (child.id == JJTSCALAREXPRESSION) child = onlyChild(child); if (assertSchemaAlias().equalsIgnoreCase(child.text)) { return null; } } // JPQL does not filter relational joins for projections exps.distinct &= ~QueryExpressions.DISTINCT_AUTO; exps.projections = new Value[selectCount]; List projections = new ArrayList(); List aliases = new ArrayList(); List clauses = new ArrayList(); evalProjectionsResultShape(expNode, exps, projections, aliases, clauses); exps.projections = projections.toArray(new Value[projections.size()]); exps.projectionAliases = aliases.toArray(new String[aliases.size()]); exps.projectionClauses = clauses.toArray(new String[clauses.size()]); return null; } private String assertSchemaAlias() { String alias = ctx().schemaAlias; if (alias == null) throw parseException(EX_USER, "alias-required", new Object[]{ ctx().meta }, null); return alias; } protected Expression evalFetchJoins(QueryExpressions exps) { Expression filter = null; // handle JOIN FETCH Set joins = null; Set innerJoins = null; JPQLNode[] outers = root().findChildrenByID(JJTOUTERFETCHJOIN); for (int i = 0; outers != null && i < outers.length; i++) (joins == null ? joins = new TreeSet() : joins). add(getPath(onlyChild(outers[i])).last().getFullName(false)); JPQLNode[] inners = root().findChildrenByID(JJTINNERFETCHJOIN); for (int i = 0; inners != null && i < inners.length; i++) { String path = getPath(onlyChild(inners[i])).last() .getFullName(false); (joins == null ? joins = new TreeSet() : joins).add(path); (innerJoins == null ? innerJoins = new TreeSet() : innerJoins).add(path); } if (joins != null) exps.fetchPaths = (String[]) joins. toArray(new String[joins.size()]); if (innerJoins != null) exps.fetchInnerPaths = (String[]) innerJoins. toArray(new String[innerJoins.size()]); return filter; } protected void evalSetClause(QueryExpressions exps) { // handle SET field = value JPQLNode[] nodes = root().findChildrenByID(JJTUPDATEITEM); for (int i = 0; nodes != null && i < nodes.length; i++) { Path path = getPath(firstChild(nodes[i])); if (path.last().getValue().getEmbeddedMetaData() != null) throw parseException(EX_USER, "cant-bulk-update-embeddable", new Object[]{assemble(firstChild(nodes[i]))}, null); JPQLNode lastChild = lastChild(nodes[i]); Value val = (lastChild.children == null) ? null : getValue(onlyChild(lastChild)); exps.putUpdate(path, val); } } private Expression evalWhereClause() { // evaluate the WHERE clause JPQLNode whereNode = root().findChildByID(JJTWHERE, false); if (whereNode == null) return null; return (Expression) eval(whereNode); } private Expression evalFromClause(boolean needsAlias) { // build up the alias map in the FROM clause JPQLNode from = root().findChildByID(JJTFROM, false); if (from == null) throw parseException(EX_USER, "no-from-clause", null, null); return evalFromClause(from, needsAlias); } private Expression evalFromClause(JPQLNode from, boolean needsAlias) { Expression exp = null; for (int i = 0; i < from.children.length; i++) { JPQLNode node = from.children[i]; if (node.id == JJTFROMITEM) exp = evalFromItem(exp, node, needsAlias); else if (node.id == JJTOUTERJOIN) exp = addJoin(node, false, exp); else if (node.id == JJTINNERJOIN) exp = addJoin(node, true, exp); else if (node.id == JJTINNERFETCHJOIN) ; // we handle inner fetch joins in the evalFetchJoins() method else if (node.id == JJTOUTERFETCHJOIN) ; // we handle outer fetch joins in the evalFetchJoins() method else throw parseException(EX_USER, "not-schema-name", new Object[]{ node }, null); } return exp; } private Expression getSubquery(String alias, Path path, Expression exp) { Value var = getVariable(alias, true); // this bind is for validateMapPath to resolve alias Expression bindVar = factory.bindVariable(var, path); FieldMetaData fmd = path.last(); ClassMetaData candidate = getFieldType(fmd); if (candidate == null && fmd.isElementCollection()) candidate = fmd.getDefiningMetaData(); setCandidate(candidate, alias); Context subContext = ctx(); Subquery subquery = ctx().getSubquery(); if (subquery == null){ subquery = factory.newSubquery(candidate, true, alias); subContext.setSubquery(subquery); } else { subquery.setSubqAlias(alias); } Path subpath = factory.newPath(subquery); subpath.setSchemaAlias(path.getCorrelationVar()); subpath.setMetaData(candidate); subquery.setMetaData(candidate); if (fmd.isElementCollection()) exp = and(exp, bindVar); else exp = and(exp, factory.equal(path, subpath)); return exp; } /** * Adds a join condition to the given expression. * * @param node the node to check * @param inner whether or not the join should be an inner join * @param exp an existing expression to AND, or null if none * @return the Expression with the join condition added */ private Expression addJoin(JPQLNode node, boolean inner, Expression exp) { // the type will be the declared type for the field JPQLNode firstChild = firstChild(node); Path path = null; if (firstChild.id == JJTQUALIFIEDPATH) path = (Path) getQualifiedPath(firstChild); else path = getPath(firstChild, false, inner); JPQLNode alias = node.getChildCount() >= 2 ? right(node) : null; // OPENJPA-15 support subquery's from clause do not start with // identification_variable_declaration() if (inner && ctx().getParent() != null && ctx().schemaAlias == null) { return getSubquery(alias.text, path, exp); } return addJoin(path, alias, exp); } private Expression addJoin(Path path, JPQLNode aliasNode, Expression exp) { FieldMetaData fmd = path.last(); if (fmd == null) throw parseException(EX_USER, "path-no-meta", new Object[]{ path, null }, null); String alias = aliasNode != null ? aliasNode.text : nextAlias(); Value var = getVariable(alias, true); var.setMetaData(getFieldType(fmd)); Expression join = null; // if the variable is already bound, get the var's value and // do a regular contains with that boolean bound = isBound(var); if (bound) { var = getValue(aliasNode, VAR_PATH); } else { bind(var); join = and(join, factory.bindVariable(var, path)); } if (!fmd.isTypePC()) // multi-valued relation { if (bound) join = and(join, factory.contains(path, var)); setImplicitContainsTypes(path, var, CONTAINS_TYPE_ELEMENT); } return and(exp, join); } private Expression evalFromItem(Expression exp, JPQLNode node, boolean needsAlias) { ClassMetaData cmd = resolveClassMetaData(firstChild(node)); String alias = null; if (node.getChildCount() < 2) { if (needsAlias) throw parseException(EX_USER, "alias-required", new Object[]{ cmd }, null); } else { alias = right(node).text; JPQLNode left = left(node); addSchemaToContext(alias, cmd); // check to see if the we are referring to a path in the from // clause, since we might be in a subquery against a collection if (isPath(left)) { Path path = getPath(left); return getSubquery(alias, path, exp); } else { // we have an alias: bind it as a variable Value var = getVariable(alias, true); var.setMetaData(cmd); bind(var); } } // ### we assign the first FROMITEM instance we see as // the global candidate, which is incorrect: we should // instead be mapping this to the SELECTITEM to see // which is the desired candidate if (ctx().schemaAlias == null) setCandidate(cmd, alias); else addAccessPath(cmd); return exp; } protected boolean isDeclaredVariable(String name) { // JPQL doesn't support declaring variables return false; } /** * Check to see if the specific node is a path (vs. a schema name) */ boolean isPath(JPQLNode node) { if (node.getChildCount() < 2) return false; final String name = firstChild(node).text; if (name == null) return false; // handle the case where the class name is the alias // for the candidate (we don't use variables for this) if (getMetaDataForAlias(name) != null) return true; if (!isSeenVariable(name)) return false; final Value var = getVariable(name, false); if (var != null) return isBound(var); return false; } private static ClassMetaData getFieldType(FieldMetaData fmd) { if (fmd == null) return null; ClassMetaData cmd = null; ValueMetaData vmd; if ((vmd = fmd.getElement()) != null) cmd = vmd.getDeclaredTypeMetaData(); else if ((vmd = fmd.getKey()) != null) cmd = vmd.getDeclaredTypeMetaData(); else if ((vmd = fmd.getValue()) != null) cmd = vmd.getDeclaredTypeMetaData(); if (cmd == null || cmd.getDescribedType() == Object.class) cmd = fmd.getDeclaredTypeMetaData(); return cmd; } /** * Identification variables in JPQL are case insensitive, so lower-case * all variables we are going to bind. */ protected Value getVariable(String id, boolean bind) { if (id == null) return null; if (bind && getDefinedVariable(id) == null) return createVariable(id, bind); return super.getVariable(id.toLowerCase(), bind); } protected Value getDefinedVariable(String id) { return ctx().getVariable(id); } protected boolean isSeenVariable(String var) { Context c = ctx().findContext(var); if (c != null) return true; return false; } /** * Returns the class name using the children of the JPQLNode. */ private String assertSchemaName(JPQLNode node) { if (node.id != JJTABSTRACTSCHEMANAME) throw parseException(EX_USER, "not-identifer", new Object[]{ node }, null); return assemble(node); } private void checkEmbeddable(Value val) { checkEmbeddable(val, currentQuery()); } public static void checkEmbeddable(Value val, String currentQuery) { Path path = val instanceof Path ? (Path) val : null; if (path == null) return; FieldMetaData fmd = path.last(); if (fmd == null) return; ValueMetaData vm = fmd.isElementCollection() ? fmd.getElement() : fmd.getValue(); if (vm.getEmbeddedMetaData() != null) { //throw parseException(EX_USER, "bad-predicate", // new Object[]{ currentQuery() }, null); String argStr = _loc.get("bad-predicate", new Object[] {fmd.getName()}).getMessage(); Message msg = _loc.get("parse-error", argStr, currentQuery); throw new UserException(msg, null); } } /** * Recursive helper method to evaluate the given node. */ private Object eval(JPQLNode node) { Value val1 = null; Value val2 = null; Value val3 = null; boolean not = node.not; switch (node.id) { case JJTSCALAREXPRESSION: return eval(onlyChild(node)); case JJTTYPE: return getType(onlyChild(node)); case JJTTYPELITERAL: return getTypeLiteral(node); case JJTCLASSNAME: return getPathOrConstant(node); case JJTCASE: return eval(onlyChild(node)); case JJTSIMPLECASE: return getSimpleCaseExpression(node); case JJTGENERALCASE: return getGeneralCaseExpression(node); case JJTWHEN: return getWhenCondition(node); case JJTWHENSCALAR: return getWhenScalar(node); case JJTCOALESCE: return getCoalesceExpression(node); case JJTNULLIF: return getNullIfExpression(node); case JJTWHERE: // top-level WHERE clause return getExpression(onlyChild(node)); case JJTBOOLEANLITERAL: return factory.newLiteral("true".equalsIgnoreCase (node.text) ? Boolean.TRUE : Boolean.FALSE, Literal.TYPE_BOOLEAN); case JJTINTEGERLITERAL: // use BigDecimal because it can handle parsing exponents BigDecimal intlit = new BigDecimal (node.text.endsWith("l") || node.text.endsWith("L") ? node.text.substring(0, node.text.length() - 1) : node.text). multiply(new BigDecimal(negative(node))); return factory.newLiteral(Long.valueOf(intlit.longValue()), Literal.TYPE_NUMBER); case JJTDECIMALLITERAL: BigDecimal declit = new BigDecimal (node.text.endsWith("d") || node.text.endsWith("D") || node.text.endsWith("f") || node.text.endsWith("F") ? node.text.substring(0, node.text.length() - 1) : node.text). multiply(new BigDecimal(negative(node))); return factory.newLiteral(declit, Literal.TYPE_NUMBER); case JJTSTRINGLITERAL: case JJTTRIMCHARACTER: case JJTESCAPECHARACTER: return factory.newLiteral(trimQuotes(node.text), Literal.TYPE_SQ_STRING); case JJTSTRINGLITERAL2: return factory.newLiteral(trimDoubleQuotes(node.text), Literal.TYPE_SQ_STRING); case JJTPATTERNVALUE: return eval(firstChild(node)); case JJTNAMEDINPUTPARAMETER: return getParameter(onlyChild(node).text, false, false); case JJTPOSITIONALINPUTPARAMETER: return getParameter(node.text, true, false); case JJTCOLLECTIONPARAMETER: JPQLNode child = onlyChild(node); boolean positional = child.id == JJTPOSITIONALINPUTPARAMETER; if (!positional) child = onlyChild(child); return getParameter(child.text, positional, true); case JJTOR: // x OR y return factory.or(getExpression(left(node)), getExpression(right(node))); case JJTAND: // x AND y return and(getExpression(left(node)), getExpression(right(node))); case JJTEQUALS: // x = y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, null); return factory.equal(val1, val2); case JJTNOTEQUALS: // x <> y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, null); return factory.notEqual(val1, val2); case JJTLESSTHAN: // x < y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, null); return factory.lessThan(val1, val2); case JJTLESSOREQUAL: // x <= y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, null); return factory.lessThanEqual(val1, val2); case JJTGREATERTHAN: // x > y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, null); return factory.greaterThan(val1, val2); case JJTGREATEROREQUAL: // x >= y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, null); return factory.greaterThanEqual(val1, val2); case JJTADD: // x + y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, TYPE_NUMBER); return factory.add(val1, val2); case JJTSUBTRACT: // x - y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, TYPE_NUMBER); return factory.subtract(val1, val2); case JJTMULTIPLY: // x * y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, TYPE_NUMBER); return factory.multiply(val1, val2); case JJTDIVIDE: // x / y val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, TYPE_NUMBER); return factory.divide(val1, val2); case JJTBETWEEN: // x.field [NOT] BETWEEN 5 AND 10 val1 = getValue(child(node, 0, 3)); val2 = getValue(child(node, 1, 3)); val3 = getValue(child(node, 2, 3)); setImplicitTypes(val1, val2, null); setImplicitTypes(val1, val3, null); return evalNot(not, and(factory.greaterThanEqual(val1, val2), factory.lessThanEqual(val1, val3))); case JJTIN: // x.field [NOT] IN ('a', 'b', 'c') // TYPE(x...) [NOT] IN (entityTypeLiteral1,...) Expression inExp = null; Iterator inIterator = node.iterator(); // the first child is the path JPQLNode first = inIterator.next(); val1 = getValue(first); while (inIterator.hasNext()) { JPQLNode next = inIterator.next(); if (first.id == JJTTYPE && next.id == JJTTYPELITERAL) val2 = getTypeLiteral(next); else val2 = getValue(next); if (val2 instanceof Parameter) { hasParameterizedInExpression = true; } // special case for IN () or // IN () if (useContains(not, val1, val2, node)) return evalNot(not, factory.contains(val2, val1)); // this is currently a sequence of OR expressions, since we // do not have support for IN expressions setImplicitTypes(val1, val2, null); if (isVerticalTypeInExpr(val1, node) && not) { if (inExp == null) inExp = factory.notEqual(val1, val2); else inExp = factory.and(inExp, factory.notEqual(val1, val2)); } else { if (inExp == null) inExp = factory.equal(val1, val2); else inExp = factory.or(inExp, factory.equal(val1, val2)); } } // we additionally need to add in a "NOT NULL" clause, since // the IN behavior that is expected by the CTS also expects // to filter our NULLs if (isVerticalTypeInExpr(val1, node)) return inExp; else return and(evalNot(not, inExp), factory.notEqual(val1, factory.getNull())); case JJTISNULL: // x.field IS [NOT] NULL val1 = getValue(onlyChild(node)); checkEmbeddable(val1); if (not) return factory.notEqual (val1, factory.getNull()); else return factory.equal (val1, factory.getNull()); case JJTPATH: return getPathOrConstant(node); case JJTIDENTIFIER: case JJTIDENTIFICATIONVARIABLE: return getIdentifier(node); case JJTQUALIFIEDPATH: return getQualifiedPath(node); case JJTQUALIFIEDIDENTIFIER: // KEY(e), VALUE(e), ENTRY(e) return getQualifiedIdentifier(node); case JJTGENERALIDENTIFIER: // KEY(e), VALUE(e) if (node.parent.parent.id == JJTWHERE || node.parent.id == JJTGROUPBY) return getGeneralIdentifier(onlyChild(node), true); return getQualifiedIdentifier(onlyChild(node)); case JJTNOT: return factory.not(getExpression(onlyChild(node))); case JJTLIKE: // field LIKE '%someval%' val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitType(val1, TYPE_STRING); setImplicitType(val2, TYPE_STRING); // look for an escape character beneath the node String escape = null; JPQLNode escapeNode = right(node). findChildByID(JJTESCAPECHARACTER, true); if (escapeNode != null) escape = trimQuotes(onlyChild(escapeNode).text); if (not) return factory.notMatches(val1, val2, "_", "%", escape); else return factory.matches(val1, val2, "_", "%", escape); case JJTISEMPTY: return evalNot(not, factory.isEmpty(getValue(onlyChild(node)))); case JJTSIZE: return factory.size(getValue(onlyChild(node))); case JJTINDEX: return factory.index(getValue(onlyChild(node))); case JJTUPPER: val1 = getValue(onlyChild(node)); setImplicitType(val1, TYPE_STRING); return factory.toUpperCase(val1); case JJTLOWER: return factory.toLowerCase(getStringValue(onlyChild(node))); case JJTLENGTH: return factory.stringLength(getStringValue(onlyChild(node))); case JJTABS: return factory.abs(getNumberValue(onlyChild(node))); case JJTSQRT: return factory.sqrt(getNumberValue(onlyChild(node))); case JJTMOD: val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitTypes(val1, val2, TYPE_NUMBER); return factory.mod(val1, val2); case JJTTRIM: // TRIM([[where] [char] FROM] field) val1 = getValue(lastChild(node)); setImplicitType(val1, TYPE_STRING); Boolean trimWhere = null; JPQLNode firstTrimChild = firstChild(node); if (node.getChildCount() > 1) { trimWhere = firstTrimChild.id == JJTTRIMLEADING ? Boolean.TRUE : firstTrimChild.id == JJTTRIMTRAILING ? Boolean.FALSE : null; } Value trimChar; // if there are 3 children, then we know the trim // char is the second node if (node.getChildCount() == 3) trimChar = getValue(secondChild(node)); // if there are two children, then we need to check to see // if the first child is a leading/trailing/both node, // or the trim character node else if (node.getChildCount() == 2 && firstTrimChild.id != JJTTRIMLEADING && firstTrimChild.id != JJTTRIMTRAILING && firstTrimChild.id != JJTTRIMBOTH) trimChar = getValue(firstChild(node)); // othwerwise, we default to trimming the space character else trimChar = factory.newLiteral(" ", Literal.TYPE_STRING); return factory.trim(val1, trimChar, trimWhere); case JJTCONCAT: val1 = getValue(left(node)); val2 = getValue(right(node)); setImplicitType(val1, TYPE_STRING); setImplicitType(val2, TYPE_STRING); return factory.concat(val1, val2); case JJTSUBSTRING: // Literals are forced to be Integers because PostgreSQL rejects Longs in SUBSTRING parameters. // This however does not help if an expression like 1+1 is passed as parameter. val1 = getValue(firstChild(node)); JPQLNode child2 = secondChild(node); if (child2.id == JJTINTEGERLITERAL) { val2 = getIntegerValue(child2); } else { val2 = getValue(child2); } if (node.getChildCount() == 3) { JPQLNode child3 = thirdChild(node); if (child3.id == JJTINTEGERLITERAL) { val3 = getIntegerValue(child3); } else { val3 = getValue(child3); } } setImplicitType(val1, TYPE_STRING); setImplicitType(val2, Integer.TYPE); if (node.children.length == 3) setImplicitType(val3, Integer.TYPE); return convertSubstringArguments(factory, val1, val2, val3); case JJTLOCATE: Value locatePath = getValue(firstChild(node)); Value locateSearch = getValue(secondChild(node)); Value locateFromIndex = null; // Literals are forced to be Integers because PostgreSQL rejects Longs in POSITION parameters. // This however does not help if an expression like 1+1 is passed as parameter. if (node.getChildCount() > 2) { // optional start index arg JPQLNode child3 = thirdChild(node); if (child3.id == JJTINTEGERLITERAL) { locateFromIndex = getIntegerValue(child3); } else locateFromIndex = getValue(child3); } setImplicitType(locatePath, TYPE_STRING); setImplicitType(locateSearch, TYPE_STRING); if (locateFromIndex != null) setImplicitType(locateFromIndex, Integer.TYPE); return factory.indexOf(locateSearch, locateFromIndex == null ? locatePath : factory.newArgumentList(locatePath, locateFromIndex)); case JJTAGGREGATE: // simply pass-through while asserting a single child return eval(onlyChild(node)); case JJTCOUNT: JPQLNode c = lastChild(node); if (c.id == JJTIDENTIFIER) // count(e) return factory.count(getPath(node, false, true)); return factory.count(getValue(c)); case JJTMAX: return factory.max(getNumberValue(onlyChild(node))); case JJTMIN: return factory.min(getNumberValue(onlyChild(node))); case JJTSUM: return factory.sum(getNumberValue(onlyChild(node))); case JJTAVERAGE: return factory.avg(getNumberValue(onlyChild(node))); case JJTDISTINCTPATH: return factory.distinct(getValue(onlyChild(node))); case JJTEXISTS: return factory.isNotEmpty((Value) eval(onlyChild(node))); case JJTANY: return factory.any((Value) eval(onlyChild(node))); case JJTALL: return factory.all((Value) eval(onlyChild(node))); case JJTSUBSELECT: return getSubquery(node); case JJTMEMBEROF: val1 = getValue(left(node), VAR_PATH); val2 = getValue(right(node), VAR_PATH); checkEmbeddable(val2); setImplicitContainsTypes(val2, val1, CONTAINS_TYPE_ELEMENT); return evalNot(not, factory.contains(val2, val1)); case JJTCURRENTDATE: return factory.getCurrentDate(Date.class); case JJTCURRENTTIME: return factory.getCurrentTime(Time.class); case JJTCURRENTTIMESTAMP: return factory.getCurrentTimestamp(Timestamp.class); case JJTSELECTEXTENSION: assertQueryExtensions("SELECT"); return eval(onlyChild(node)); case JJTGROUPBYEXTENSION: assertQueryExtensions("GROUP BY"); return eval(onlyChild(node)); case JJTORDERBYEXTENSION: assertQueryExtensions("ORDER BY"); return eval(onlyChild(node)); case JJTDATELITERAL: return factory.newLiteral(node.text, Literal.TYPE_DATE); case JJTTIMELITERAL: return factory.newLiteral(node.text, Literal.TYPE_TIME); case JJTTIMESTAMPLITERAL: return factory.newLiteral(node.text, Literal.TYPE_TIMESTAMP); default: throw parseException(EX_FATAL, "bad-tree", new Object[]{ node }, null); } } private boolean useContains(boolean not, Value val1, Value val2, JPQLNode node) { if (isVerticalTypeInExpr(val1, node) && not) return false; else return (!(val2 instanceof Literal) && node.getChildCount() == 2); } private boolean isVerticalTypeInExpr(Value val, JPQLNode node) { if (node.id != JJTIN) return false; return factory.isVerticalType(val); } private Value getIntegerValue(JPQLNode node) { BigDecimal bigdec = new BigDecimal (node.text.endsWith("l") || node.text.endsWith("L") ? node.text.substring(0, node.text.length() - 1) : node.text). multiply(new BigDecimal(negative(node))); return factory.newLiteral(Integer.valueOf(bigdec.intValue()), Literal.TYPE_NUMBER); } /** * Converts JPQL substring() function to OpenJPA ExpressionFactory * substring() arguments. * * @param val1 the original String * @param val2 the 1-based start index as per JPQL substring() semantics * @param val3 the length of the returned string as per JPQL semantics * */ public static Value convertSubstringArguments(ExpressionFactory factory, Value val1, Value val2, Value val3) { if (val3 != null) return factory.substring(val1, factory.newArgumentList(val2, val3)); else return factory.substring(val1, val2); } private void assertQueryExtensions(String clause) { OpenJPAConfiguration conf = resolver.getConfiguration(); switch(conf.getCompatibilityInstance().getJPQL()) { case Compatibility.JPQL_WARN: // check if we've already warned for this query-factory combo StoreContext ctx = resolver.getQueryContext().getStoreContext(); String query = currentQuery(); if (ctx.getBroker() != null && query != null) { String key = getClass().getName() + ":" + query; BrokerFactory factory = ctx.getBroker().getBrokerFactory(); Object hasWarned = factory.getUserObject(key); if (hasWarned != null) break; else factory.putUserObject(key, Boolean.TRUE); } Log log = conf.getLog(OpenJPAConfiguration.LOG_QUERY); if (log.isWarnEnabled()) log.warn(_loc.get("query-extensions-warning", clause, currentQuery())); break; case Compatibility.JPQL_STRICT: throw new ParseException(_loc.get("query-extensions-error", clause, currentQuery()).getMessage()); case Compatibility.JPQL_EXTENDED: break; default: throw new IllegalStateException( "Compatibility.getJPQL() == " + conf.getCompatibilityInstance().getJPQL()); } } public void setImplicitTypes(Value val1, Value val2, Class expected) { String currQuery = currentQuery(); setImplicitTypes(val1, val2, expected, resolver, parameterTypes, currQuery); } public static void setImplicitTypes(Value val1, Value val2, Class expected, Resolver resolver, OrderedMap> parameterTypes, String currentQuery) { AbstractExpressionBuilder.setImplicitTypes(val1, val2, expected, resolver); // as well as setting the types for conversions, we also need to // ensure that any parameters are declared with the correct type, // since the JPA spec expects that these will be validated Parameter param = val1 instanceof Parameter ? (Parameter) val1 : val2 instanceof Parameter ? (Parameter) val2 : null; Path path = val1 instanceof Path ? (Path) val1 : val2 instanceof Path ? (Path) val2 : null; // we only check for parameter-to-path comparisons if (param == null || path == null || parameterTypes == null) return; FieldMetaData fmd = path.last(); if (fmd == null) return; if (expected == null) checkEmbeddable(path, currentQuery); Class type = path.getType(); if (type == null) return; Object paramKey = param.getParameterKey(); if (paramKey == null) return; // make sure we have already declared the parameter if (parameterTypes.containsKey(paramKey)) parameterTypes.put(paramKey, type); } private Value getStringValue(JPQLNode node) { return getTypeValue(node, TYPE_STRING); } private Value getNumberValue(JPQLNode node) { return getTypeValue(node, TYPE_NUMBER); } private Value getTypeValue(JPQLNode node, Class implicitType) { Value val = getValue(node); setImplicitType(val, implicitType); return val; } private Value getSubquery(JPQLNode node) { final boolean subclasses = true; // parse the subquery ParsedJPQL parsed = new ParsedJPQL(node.parser.jpql, node); Context subContext = new Context(parsed, null, ctx()); contexts.push(subContext); ClassMetaData candidate = getCandidateMetaData(node); Subquery subq = subContext.getSubquery(); if (subq == null) { subq = factory.newSubquery(candidate, subclasses, nextAlias()); subContext.setSubquery(subq); } subq.setMetaData(candidate); // evaluate from clause for resolving variables defined in subquery JPQLNode from = node.getChild(1); subContext.from = evalFromClause(from, true); try { QueryExpressions subexp = getQueryExpressions(); subq.setQueryExpressions(subexp); if (subexp.projections.length > 0) checkEmbeddable(subexp.projections[0]); return subq; } finally { // remove the subquery parse context contexts.pop(); } } /** * Creates and records the names and order of parameters. The parameters are * identified by a key with its type preserved. The second argument * determines whether the first argument is used as-is or converted to * an Integer as parameter key. * * @param the text as it appears in the parsed node * @param positional if true the first argument is converted to an integer * @param isCollectionValued true for collection-valued parameters */ private Parameter getParameter(String id, boolean positional, boolean isCollectionValued) { if (parameterTypes == null) parameterTypes = new OrderedMap>(); Object paramKey = positional ? Integer.parseInt(id) : id; if (!parameterTypes.containsKey(paramKey)) parameterTypes.put(paramKey, TYPE_OBJECT); ClassMetaData meta = null; int index; if (positional) { try { // indexes in JPQL are 1-based, as opposed to 0-based in // the core ExpressionFactory index = Integer.parseInt(id) - 1; } catch (NumberFormatException e) { throw parseException(EX_USER, "bad-positional-parameter", new Object[]{ id }, e); } if (index < 0) throw parseException(EX_USER, "bad-positional-parameter", new Object[]{ id }, null); } else { index = parameterTypes.indexOf(id); } Parameter param = isCollectionValued ? factory.newCollectionValuedParameter(paramKey, TYPE_OBJECT) : factory.newParameter(paramKey, TYPE_OBJECT); param.setMetaData(meta); param.setIndex(index); return param; } /** * Checks to see if we should evaluate for a NOT expression. */ private Expression evalNot(boolean not, Expression exp) { return not ? factory.not(exp) : exp; } /** * Trim off leading and trailing single-quotes, and then * replace any internal '' instances with ' (since repeating the * quote is the JPQL mechanism of escaping a single quote). */ private String trimQuotes(String str) { if (str == null || str.length() <= 1) return str; if (str.startsWith("'") && str.endsWith("'")) str = str.substring(1, str.length() - 1); int index = -1; while ((index = str.indexOf("''", index + 1)) != -1) str = str.substring(0, index + 1) + str.substring(index + 2); return str; } /** * Trim off leading and trailing double-quotes. */ private String trimDoubleQuotes(String str) { if (str == null || str.length() <= 1) return str; if (str.startsWith("\"") && str.endsWith("\"")) str = str.substring(1, str.length() - 1); return str; } /** * An IntegerLiteral and DecimalLiteral node will * have a child node of Negative if it is negative: * if so, this method returns -1, else it returns 1. */ private short negative(JPQLNode node) { if (node.children != null && node.children.length == 1 && firstChild(node).id == JJTNEGATIVE) return -1; else return 1; } private Value getIdentifier(JPQLNode node) { final String name = node.text; final Value val = getVariable(name, false); ClassMetaData cmd = getMetaDataForAlias(name); if (cmd != null) { // handle the case where the class name is the alias // for the candidate (we don't use variables for this) Value thiz = null; if (ctx().subquery == null || ctx().getSchema(name.toLowerCase()) == null) { if (ctx().subquery != null && inAssignSubselectProjection) thiz = factory.newPath(ctx().subquery); else thiz = factory.getThis(); } else { thiz = factory.newPath(ctx().subquery); } ((Path)thiz).setSchemaAlias(name); thiz.setMetaData(cmd); return thiz; } else if (val instanceof Path) { return (Path) val; } else if (val instanceof Value) { if (val.isVariable()) { // can be an entity type literal Class c = resolver.classForName(name, null); if (c != null) { Value lit = factory.newTypeLiteral(c, Literal.TYPE_CLASS); Class candidate = getCandidateType(); ClassMetaData can = getClassMetaData(candidate.getName(), false); ClassMetaData meta = getClassMetaData(name, false); if (candidate.isAssignableFrom(c)) lit.setMetaData(meta); else lit.setMetaData(can); return lit; } } return (Value) val; } throw parseException(EX_USER, "unknown-identifier", new Object[]{ name }, null); } private Path validateMapPath(JPQLNode node, JPQLNode id) { Path path = (Path) getValue(id); FieldMetaData fld = path.last(); if (fld == null && ctx().subquery != null) { Value var = getVariable(id.text, false); if (var != null) { path = factory.newPath(var); fld = path.last(); } } if (fld != null) { // validate the field is of type java.util.Map if (fld.getDeclaredTypeCode() != JavaTypes.MAP) { String oper = "VALUE"; if (node.id == JJTENTRY) oper = "ENTRY"; else if (node.id == JJTKEY) oper = "KEY"; throw parseException(EX_USER, "bad-qualified-identifier", new Object[]{ id.text, oper}, null); } } else throw parseException(EX_USER, "unknown-type", new Object[]{ id.text}, null); return path; } private Value getGeneralIdentifier(JPQLNode node, boolean verifyEmbeddable) { JPQLNode id = onlyChild(node); Path path = validateMapPath(node, id); if (node.id == JJTKEY) path = (Path) factory.getKey(path); FieldMetaData fld = path.last(); ClassMetaData meta = fld.getKey().getTypeMetaData(); if (verifyEmbeddable && (node.id == JJTKEY && meta != null && fld.getKey().isEmbedded()) || (node.id == JJTVALUE && fld.isElementCollection() && fld.getElement().getEmbeddedMetaData() != null)) { // check basic type if (node.parent.parent.id == JJTGROUPBY) throw parseException(EX_USER, "cant-groupby-key-value-embeddable", new Object[]{ node.id == JJTVALUE ? "VALUE" : "KEY", id.text }, null); else throw parseException(EX_USER, "bad-general-identifier", new Object[]{ node.id == JJTVALUE ? "VALUE" : "KEY", id.text }, null); } return path; } private Value getQualifiedIdentifier(JPQLNode node) { JPQLNode id = onlyChild(node); Path path = validateMapPath(node, id); if (node.id == JJTVALUE) return path; Value value = getValue(id); if (node.id == JJTKEY) return factory.mapKey(path, value); else return factory.mapEntry(path, value); } private Path getQualifiedPath(JPQLNode node) { return getQualifiedPath(node, false, true); } private Path getQualifiedPath(JPQLNode node, boolean pcOnly, boolean inner) { int nChild = node.getChildCount(); JPQLNode firstChild = firstChild(node); JPQLNode id = firstChild.id == JJTKEY ? onlyChild(firstChild) : firstChild; Path path = validateMapPath(firstChild, id); if (firstChild.id == JJTIDENTIFIER) return getPath(node); FieldMetaData fld = path.last(); path = (Path) factory.getKey(path); ClassMetaData meta = fld.getKey().getTypeMetaData(); if (meta == null) throw parseException(EX_USER, "bad-qualified-path", new Object[]{ id.text }, null); path.setMetaData(meta); // walk through the children and assemble the path boolean allowNull = !inner; for (int i = 1; i < nChild; i++) { path = (Path) traversePath(path, node.children[i].text, pcOnly, allowNull); // all traversals but the first one will always be inner joins allowNull = false; } return path; } private Value getTypeLiteral(JPQLNode node) { JPQLNode type = onlyChild(node); final String name = type.text; final Value val = getVariable(name, false); if (val instanceof Value && val.isVariable()) { Class c = resolver.classForName(name, null); if (c != null) { Value typeLit = factory.newTypeLiteral(c, Literal.TYPE_CLASS); typeLit.setMetaData(getClassMetaData(name, false)); return typeLit; } } throw parseException(EX_USER, "not-type-literal", new Object[]{ name }, null); } private Value getPathOrConstant(JPQLNode node) { // first check to see if the path is an enum or static field, and // if so, load it String className = assemble(node, ".", 1); Class c = resolver.classForName(className, null); if (c != null) { String fieldName = lastChild(node).text; int type = (c.isEnum() ? Literal.TYPE_ENUM : Literal.TYPE_UNKNOWN); try { Field field = c.getField(fieldName); Object value = field.get(null); return factory.newLiteral(value, type); } catch (NoSuchFieldException nsfe) { if (node.inEnumPath) throw parseException(EX_USER, "no-field", new Object[]{ c.getName(), fieldName }, nsfe); else return getPath(node, false, true); } catch (Exception e) { throw parseException(EX_USER, "unaccessible-field", new Object[]{ className, fieldName }, e); } } else { return getPath(node, false, true); } } /** * Process type_discriminator * type_discriminator ::= * TYPE(general_identification_variable | * single_valued_object_path_expression | * input_parameter ) */ private Value getType(JPQLNode node) { switch (node.id) { case JJTIDENTIFIER: return factory.type(getValue(node)); case JJTNAMEDINPUTPARAMETER: return factory.type(getParameter(node.text, false, false)); case JJTPOSITIONALINPUTPARAMETER: return factory.type(getParameter(node.text, true, false)); case JJTGENERALIDENTIFIER: return factory.type(getQualifiedIdentifier(onlyChild(node))); default: // TODO: enforce jpa2.0 spec rules. // A single_valued_object_field is designated by the name of // an association field in a one-to-one or many-to-one relationship // or a field of embeddable class type. // The type of a single_valued_object_field is the abstract schema // type of the related entity or embeddable class Value path = getPath(node, false, true); return factory.type(path); } } private Path getPath(JPQLNode node) { return getPath(node, false, true); } private Path getPath(JPQLNode node, boolean pcOnly, boolean inner) { // resolve the first element against the aliases map ... // i.e., the path "SELECT x.id FROM SomeClass x where x.id > 10" // will need to have "x" in the alias map in order to resolve Path path = null; final String name = firstChild(node).text; final Value val = getVariable(name, false); // handle the case where the class name is the alias // for the candidate (we don't use variables for this) if (name.equalsIgnoreCase(ctx().schemaAlias)) { if (ctx().subquery != null) { path = factory.newPath(ctx().subquery); path.setMetaData(ctx().subquery.getMetaData()); } else { path = factory.newPath(); path.setMetaData(ctx().meta); } } else if (getMetaDataForAlias(name) != null) path = newPath(null, getMetaDataForAlias(name)); else if (val instanceof Path) path = (Path) val; else if (val.getMetaData() != null) path = newPath(val, val.getMetaData()); else throw parseException(EX_USER, "path-invalid", new Object[]{ assemble(node), name }, null); path.setSchemaAlias(name); // walk through the children and assemble the path boolean allowNull = !inner; for (int i = 1; i < node.children.length; i++) { if (path.isXPath()) { for (int j = i; j getDeclaredVariableType(String name) { ClassMetaData cmd = getMetaDataForAlias(name); if (cmd != null) return cmd.getDescribedType(); if (name != null && name.equals(ctx().schemaAlias)) return getCandidateType(); // JPQL has no declared variables return null; } /** * Returns an Expression for the given node by eval'ing it. */ private Expression getExpression(JPQLNode node) { Object exp = eval(node); // check for boolean values used as expressions if (!(exp instanceof Expression)) return factory.asExpression((Value) exp); return (Expression) exp; } /** * Returns a Simple Case Expression for the given node by eval'ing it. */ private Value getSimpleCaseExpression(JPQLNode node) { Object caseOperand = eval(node.getChild(0)); int nChild = node.getChildCount(); Object val = eval(lastChild(node)); Object exp[] = new Expression[nChild - 2]; for (int i = 1; i < nChild - 1; i++) exp[i-1] = eval(node.children[i]); return factory.simpleCaseExpression((Value) caseOperand, (Expression[]) exp, (Value) val); } /** * Returns a General Case Expression for the given node by eval'ing it. */ private Value getGeneralCaseExpression(JPQLNode node) { int nChild = node.getChildCount(); Object val = eval(lastChild(node)); Object exp[] = new Expression[nChild - 1]; for (int i = 0; i < nChild - 1; i++) exp[i] = (Expression) eval(node.children[i]); return factory.generalCaseExpression((Expression[]) exp, (Value) val); } private Expression getWhenCondition(JPQLNode node) { Object exp = eval(firstChild(node)); Object val = eval(secondChild(node)); return factory.whenCondition((Expression) exp, (Value) val); } private Expression getWhenScalar(JPQLNode node) { Object val1 = eval(firstChild(node)); Object val2 = eval(secondChild(node)); return factory.whenScalar((Value) val1, (Value) val2); } private Value getCoalesceExpression(JPQLNode node) { int nChild = node.getChildCount(); Object vals[] = new Value[nChild]; for (int i = 0; i < nChild; i++) vals[i] = eval(node.children[i]); return factory.coalesceExpression((Value[]) vals); } private Value getNullIfExpression(JPQLNode node) { Object val1 = eval(firstChild(node)); Object val2 = eval(secondChild(node)); return factory.nullIfExpression((Value) val1, (Value) val2); } private Value getValue(JPQLNode node) { if (node.id == JJTQUALIFIEDIDENTIFIER) return getQualifiedIdentifier(onlyChild(node)); return getValue(node, VAR_PATH); } private Path newPath(Value val, ClassMetaData meta) { Path path = val == null ? factory.newPath() : factory.newPath(val); if (meta != null) path.setMetaData(meta); return path; } /** * Returns a Value for the given node by eval'ing it. */ private Value getValue(JPQLNode node, int handleVar) { Value val = (Value) eval(node); // determined how to evaluate a variable if (!val.isVariable()) return val; else if (handleVar == VAR_PATH && !(val instanceof Path)) return newPath(val, val.getMetaData()); else if (handleVar == VAR_ERROR) throw parseException(EX_USER, "unexpected-var", new Object[]{ node.text }, null); else return val; } //////////////////////////// // Parse Context Management //////////////////////////// private Context ctx() { return contexts.peek(); } private JPQLNode root() { return ctx().parsed.root; } private ClassMetaData getMetaDataForAlias(String alias) { for (int i = contexts.size() - 1; i >= 0; i--) { Context context = contexts.get(i); if (alias.equalsIgnoreCase(context.schemaAlias)) return context.meta; } return null; } protected void addSchemaToContext(String id, ClassMetaData meta) { ctx().addSchema(id.toLowerCase(), meta); } protected void addVariableToContext(String id, Value var) { ctx().addVariable(id, var); } protected Value getVariable(String var) { Context c = ctx(); Value v = c.getVariable(var); if (v != null) return v; if (c.getParent() != null) return c.getParent().findVariable(var); return null; } //////////////////////////// // Node traversal utilities //////////////////////////// private JPQLNode onlyChild(JPQLNode node) throws UserException { JPQLNode child = firstChild(node); if (node.children.length > 1) throw parseException(EX_USER, "multi-children", new Object[]{ node, Arrays.asList(node.children) }, null); return child; } /** * Returns the left node (the first of the children), and asserts * that there are exactly two children. */ private JPQLNode left(JPQLNode node) { return child(node, 0, 2); } /** * Returns the right node (the second of the children), and asserts * that there are exactly two children. */ private JPQLNode right(JPQLNode node) { return child(node, 1, 2); } private JPQLNode child(JPQLNode node, int childNum, int assertCount) { if (node.children.length != assertCount) throw parseException(EX_USER, "wrong-child-count", new Object[]{ Integer.valueOf(assertCount), node, Arrays.asList(node.children) }, null); return node.children[childNum]; } private JPQLNode firstChild(JPQLNode node) { if (node.children == null || node.children.length == 0) throw parseException(EX_USER, "no-children", new Object[]{ node }, null); return node.children[0]; } private static JPQLNode secondChild(JPQLNode node) { return node.children[1]; } private static JPQLNode thirdChild(JPQLNode node) { return node.children[2]; } private static JPQLNode lastChild(JPQLNode node) { return lastChild(node, 0); } /** * The Nth from the last child. E.g., * lastChild(1) will return the second-to-the-last child. */ private static JPQLNode lastChild(JPQLNode node, int fromLast) { return node.children[node.children.length - (1 + fromLast)]; } /** * Base node that will be generated by the JPQLExpressionBuilder; base * class of the {@link SimpleNode} that is used by {@link JPQL}. * * @author Marc Prud'hommeaux * @see Node * @see SimpleNode */ @SuppressWarnings("serial") protected abstract static class JPQLNode implements Node, Serializable { final int id; final JPQL parser; JPQLNode parent; JPQLNode[] children; String text; boolean not = false; boolean inEnumPath = false; public JPQLNode(JPQL parser, int id) { this.id = id; this.parser = parser; this.inEnumPath = parser.inEnumPath; } public void jjtOpen() { } public void jjtClose() { } JPQLNode[] findChildrenByID(int id) { Collection set = new LinkedHashSet(); findChildrenByID(id, set); return set.toArray(new JPQLNode[set.size()]); } private void findChildrenByID(int id, Collection set) { for (int i = 0; children != null && i < children.length; i++) { if (children[i].id == id) set.add(children[i]); children[i].findChildrenByID(id, set); } } boolean hasChildID(int id) { return findChildByID(id, false) != null; } JPQLNode findChildByID(int id, boolean recurse) { for (int i = 0; children != null && i < children.length; i++) { JPQLNode child = children[i]; if (child.id == id) return children[i]; if (recurse) { JPQLNode found = child.findChildByID(id, recurse); if (found != null) return found; } } // not found return null; } public void jjtSetParent(Node parent) { this.parent = (JPQLNode) parent; } public Node jjtGetParent() { return this.parent; } public void jjtAddChild(Node n, int i) { if (children == null) { children = new JPQLNode[i + 1]; } else if (i >= children.length) { JPQLNode c[] = new JPQLNode[i + 1]; System.arraycopy(children, 0, c, 0, children.length); children = c; } children[i] = (JPQLNode) n; } public Node jjtGetChild(int i) { return children[i]; } public int getChildCount() { return jjtGetNumChildren(); } public JPQLNode getChild(int index) { return (JPQLNode) jjtGetChild(index); } public Iterator iterator() { return Arrays.asList(children).iterator(); } public int jjtGetNumChildren() { return (children == null) ? 0 : children.length; } void setText(String text) { this.text = text; } void setToken(Token t) { setText(t.image); } public String toString() { return JPQLTreeConstants.jjtNodeName[this.id]; } public String toString(String prefix) { return prefix + toString(); } /** * Debugging method. * * @see #dump(java.io.PrintStream,String) */ public void dump(String prefix) { dump(System.out, prefix); } public void dump() { dump(" "); } /** * Debugging method to output a parse tree. * * @param out the stream to which to write the debugging info * @param prefix the prefix to write out before lines */ public void dump(PrintStream out, String prefix) { dump(out, prefix, false); } public void dump(PrintStream out, String prefix, boolean text) { out.println(toString(prefix) + (text && this.text != null ? " [" + this.text + "]" : "")); if (children != null) { for (int i = 0; i < children.length; ++i) { JPQLNode n = (JPQLNode) children[i]; if (n != null) { n.dump(out, prefix + " ", text); } } } } } /** * Public for unit testing purposes. * @nojavadoc */ @SuppressWarnings("serial") public static class ParsedJPQL implements Serializable { // This is only ever used during parse; when ParsedJPQL instances // are serialized, they will have already been parsed. private final transient JPQLNode root; private final String query; // cache of candidate type data. This is stored here in case this // parse tree is reused in a context that does not know what the // candidate type is already. private Class _candidateType; ParsedJPQL(String jpql) { this(jpql, parse(jpql)); } ParsedJPQL(String query, JPQLNode root) { this.root = root; this.query = query; } private static JPQLNode parse(String jpql) { if (jpql == null) jpql = ""; try { return (JPQLNode) new JPQL(jpql).parseQuery(); } catch (Error e) { // special handling for Error subclasses, which the // parser may sometimes (unfortunately) throw throw new UserException(_loc.get("parse-error", new Object[]{ e.toString(), jpql })); } } void populate(ExpressionStoreQuery query) { QueryContext ctx = query.getContext(); // if the owning query's context does not have // any candidate class, then set it here if (ctx.getCandidateType() == null) { if (_candidateType == null) _candidateType = new JPQLExpressionBuilder (null, query, this).getCandidateType(); ctx.setCandidateType(_candidateType, true); } } /** * Public for unit testing purposes. */ public Class getCandidateType() { return _candidateType; } public String toString () { return this.query; } } // throws an exception if there are numeric parameters which do not start with 1. private void validateParameters() { if (parameterTypes == null || parameterTypes.isEmpty()) { return; } boolean numericParms = false; boolean namedParms = false; for (Object key : parameterTypes.keySet()) { if (key instanceof Number) { if (namedParms) { throw new UserException(_loc.get("mixed-parameter-types", resolver.getQueryContext() .getQueryString(), parameterTypes.keySet().toString())); } numericParms = true; } else { if (numericParms) { throw new UserException(_loc.get("mixed-parameter-types", resolver.getQueryContext() .getQueryString(), parameterTypes.keySet().toString())); } namedParms = true; } } if (numericParms) { if (!parameterTypes.keySet().contains(1)) { throw new UserException(_loc.get("missing-positional-parameter", resolver.getQueryContext() .getQueryString(), parameterTypes.keySet().toString())); } } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SavepointFieldManager.java0000644000000000000000000001715312133327272030353 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.io.ObjectOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.BitSet; import java.util.Collection; import java.util.Date; import java.util.Map; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.ProxyManager; /** * FieldManager type used to store information for savepoint rollback. * * @author Steve Kim * @since 0.3.4 */ class SavepointFieldManager extends ClearFieldManager implements Serializable { private static final Localizer _loc = Localizer.forPackage (SavepointFieldManager.class); private final StateManagerImpl _sm; private final BitSet _loaded; private final BitSet _dirty; private final BitSet _flush; private final PCState _state; private transient PersistenceCapable _copy; private final Object _version; private final Object _loadVersion; // used to track field value during store/fetch cycle private Object _field = null; private int[] _copyField = null; private BitSet _mutable; /** * Constructor. Provide instance to save and indicate whether * to copy persistent fields. Transactional fields will be * copied regardless of copy setting. */ public SavepointFieldManager(StateManagerImpl sm, boolean copy) { _sm = sm; _state = _sm.getPCState(); _dirty = (BitSet) _sm.getDirty().clone(); _flush = (BitSet) _sm.getFlushed().clone(); _loaded = (BitSet) _sm.getLoaded().clone(); FieldMetaData[] fields = _sm.getMetaData().getFields(); for (int i = 0; i < _loaded.length(); i++) { if (!_loaded.get(i)) continue; if (copy || fields[i].getManagement() == FieldMetaData.MANAGE_TRANSACTIONAL) { if (_copy == null) _copy = _sm.getPersistenceCapable().pcNewInstance (_sm, true); storeField(fields[i]); } else _loaded.clear(i); } // we need to proxy the fields so that we can track future changes // from this savepoint forward for PNew instances' mutable fields _sm.proxyFields(false, false); _version = _sm.getVersion (); _loadVersion = _sm.getLoadVersion (); } /** * Return the state manager that this manager is associated with. */ public StateManagerImpl getStateManager() { return _sm; } public Object getVersion() { return _version; } public Object getLoadVersion() { return _loadVersion; } /** * Return the persistence capable copy holding the savepoint field values. */ public PersistenceCapable getCopy() { return _copy; } /** * Return the saved {@link PCState} */ public PCState getPCState() { return _state; } /** * Return the fields stored in this manager. */ public BitSet getLoaded() { return _loaded; } /** * Return the dirty fields during the saved state. */ public BitSet getDirty() { return _dirty; } /** * Return the flushed fields during the saved state. */ public BitSet getFlushed() { return _flush; } /** * Store the data for the given field. */ public void storeField(FieldMetaData field) { switch (field.getDeclaredTypeCode()) { case JavaTypes.DATE: case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.OBJECT: if (_mutable == null) _mutable = new BitSet(_sm.getMetaData().getFields().length); _mutable.set(field.getIndex()); } if (_mutable == null || !_mutable.get(field.getIndex())) { // immutable fields can just be copied over if (_copyField == null) _copyField = new int[1]; _copyField[0] = field.getIndex(); _copy.pcCopyFields(_sm.getPersistenceCapable(), _copyField); } else { _sm.provideField(_sm.getPersistenceCapable(), this, field.getIndex()); _sm.replaceField(_copy, this, field.getIndex()); } } /** * Restore the given field. If this method returns true, then you need * to use this field manager to replace the given field in the state * manager's instance. */ public boolean restoreField(int field) { if (!_loaded.get(field)) return false; if (_mutable != null && _mutable.get(field)) return true; // copy the saved field over if (_copyField == null) _copyField = new int[1]; _copyField[0] = field; _sm.getPersistenceCapable().pcCopyFields(_copy, _copyField); return false; } public Object fetchObjectField(int field) { // return the copied field during save, or a null value during restore Object val = _field; _field = null; return val; } public void storeObjectField(int field, Object curVal) { // copy mutable fields ProxyManager proxy = _sm.getContext().getConfiguration(). getProxyManagerInstance(); FieldMetaData fmd = _sm.getMetaData().getField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.ARRAY: _field = proxy.copyArray(curVal); break; case JavaTypes.COLLECTION: _field = proxy.copyCollection((Collection) curVal); break; case JavaTypes.MAP: _field = proxy.copyMap((Map) curVal); break; case JavaTypes.DATE: _field = proxy.copyDate((Date) curVal); break; case JavaTypes.OBJECT: _field = proxy.copyCustom(curVal); if (_field == null) _field = curVal; break; default: _field = curVal; } // if we couldn't get a copy of the sco, act like it wasn't saved // should throw an exception if (curVal != null && _field == null) throw new InternalException(_loc.get("no-savepoint-copy", fmd)); } private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); _sm.writePC(oos, _copy); } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); _copy = _sm.readPC(ois); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/InverseManager.java0000644000000000000000000003536412133327272027056 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.datacache.DataCacheManager; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.InvalidStateException; /** * Class which manages inverse relations before flushing * to the datastore. Ensures that inverse fields are set. * Currently limited to managing PC and Collection-type relations. * * @author Steve Kim */ public class InverseManager implements Configurable { private static final Localizer _loc = Localizer.forPackage(InverseManager.class); protected static final Object NONE = new Object(); protected DataCacheManager _mgr; /** * Constant representing the {@link #ACTION_MANAGE} action */ public static final int ACTION_MANAGE = 0; /** * Constant representing the {@link #ACTION_WARN} action */ public static final int ACTION_WARN = 1; /** * Constant representing the {@link #ACTION_EXCEPTION} action */ public static final int ACTION_EXCEPTION = 2; private boolean _manageLRS = false; private int _action = ACTION_MANAGE; private Log _log; /** * Return whether to manage LRS fields. */ public boolean getManageLRS() { return _manageLRS; } /** * Set whether to false LRS relations. Defaults to false. */ public void setManageLRS(boolean manage) { _manageLRS = manage; } /** * Return the action constant to use during relationship checking. * Defaults to {@link #ACTION_MANAGE}. */ public int getAction() { return _action; } /** * Set the action constant to use during relationship checking. * Defaults to {@link #ACTION_MANAGE}. */ public void setAction(int action) { _action = action; } /** * Set the action string to use during relationship checking. * Options include manage, exception, warn. * This method is primarily for string-based automated configuration. */ public void setAction(String action) { if ("exception".equals(action)) _action = ACTION_EXCEPTION; else if ("warn".equals(action)) _action = ACTION_WARN; else if ("manage".equals(action)) _action = ACTION_MANAGE; else throw new IllegalArgumentException(action); } public void startConfiguration() { } public void endConfiguration() { } public void setConfiguration(Configuration conf) { _log = conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); _mgr = ((OpenJPAConfiguration)conf).getDataCacheManagerInstance(); } /** * Correct relations from the given dirty field to inverse instances. * Field fmd of the instance managed by sm has * value value. Ensure that all inverses relations from * value are consistent with this. */ public void correctRelations(OpenJPAStateManager sm, FieldMetaData fmd, Object value) { if (fmd.getDeclaredTypeCode() != JavaTypes.PC && ((fmd.getDeclaredTypeCode() != JavaTypes.COLLECTION && fmd.getDeclaredTypeCode() != JavaTypes.MAP) || fmd.getElement().getDeclaredTypeCode() != JavaTypes.PC)) return; // ignore LRS fields if (!getManageLRS() && fmd.isLRS()) return; FieldMetaData[] inverses = fmd.getInverseMetaDatas(); if (inverses.length == 0) return; // clear any restorable relations clearInverseRelations(sm, fmd, inverses, value); if (value != null) { StoreContext ctx = sm.getContext(); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.PC: createInverseRelations(ctx, sm.getManagedInstance(), value, fmd, inverses); break; case JavaTypes.COLLECTION: for (Iterator itr = ((Collection) value).iterator(); itr.hasNext();) createInverseRelations(ctx, sm.getManagedInstance(), itr.next(), fmd, inverses); break; } } } /** * Create the inverse relations for all the given inverse fields. * A relation exists from fromRef to toRef; this * method creates the inverses. */ protected void createInverseRelations(StoreContext ctx, Object fromRef, Object toRef, FieldMetaData fmd, FieldMetaData[] inverses) { OpenJPAStateManager other = ctx.getStateManager(toRef); if (other == null || other.isDeleted()) return; boolean owned; for (int i = 0; i < inverses.length; i++) { if (!getManageLRS() && inverses[i].isLRS()) continue; // if this is the owned side of the relation and has not yet been // loaded, no point in setting it now, cause it'll have the correct // value the next time it is loaded after the flush owned = fmd == inverses[i].getMappedByMetaData() && _action == ACTION_MANAGE && !isLoaded(other, inverses[i].getIndex()); switch (inverses[i].getDeclaredTypeCode()) { case JavaTypes.PC: if (!owned || inverses[i].getCascadeDelete() == ValueMetaData.CASCADE_AUTO) storeField(other, inverses[i], NONE, fromRef); break; case JavaTypes.COLLECTION: if (!owned || inverses[i].getElement().getCascadeDelete() == ValueMetaData.CASCADE_AUTO) addToCollection(other, inverses[i], fromRef); break; } } } /** * Return whether the given field is loaded for the given instance. */ private boolean isLoaded(OpenJPAStateManager sm, int field) { if (sm.getLoaded().get(field)) return true; // if the field isn't loaded in the state manager, it still might be // loaded in the data cache, in which case we still have to correct // it to keep the cache in sync DataCache cache = _mgr.selectCache(sm); if (cache == null) return false; // can't retrieve an embedded object directly, so always assume the // field is loaded and needs to be corrected if (sm.isEmbedded()) return true; PCData pc = cache.get(sm.getObjectId()); if (pc == null) return false; return pc.isLoaded(field); } /** * Remove all relations between the initial value of fmd for * the instance managed by sm and its inverses. Relations * shared with newValue can be left intact. */ protected void clearInverseRelations(OpenJPAStateManager sm, FieldMetaData fmd, FieldMetaData[] inverses, Object newValue) { // don't bother clearing unflushed new instances if (sm.isNew() && !sm.getFlushed().get(fmd.getIndex())) return; if (fmd.getDeclaredTypeCode() == JavaTypes.PC) { Object initial = sm.fetchInitialField(fmd.getIndex()); clearInverseRelations(sm, initial, fmd, inverses); } else { Object obj = sm.fetchInitialField(fmd.getIndex()); Collection initial = null; if (obj instanceof Collection) initial = (Collection) obj; else if (obj instanceof Map) initial = ((Map)obj).values(); if (initial == null) return; // clear all relations not also in the new value Collection coll = null; if (newValue instanceof Collection) coll = (Collection) newValue; else if (newValue instanceof Map) coll = ((Map)newValue).values(); Object elem; for (Iterator itr = initial.iterator(); itr.hasNext();) { elem = itr.next(); if (coll == null || !coll.contains(elem)) clearInverseRelations(sm, elem, fmd, inverses); } } } /** * Clear all inverse the relations from val to the instance * managed by sm. */ protected void clearInverseRelations(OpenJPAStateManager sm, Object val, FieldMetaData fmd, FieldMetaData[] inverses) { if (val == null) return; OpenJPAStateManager other = sm.getContext().getStateManager(val); if (other == null || other.isDeleted()) return; boolean owned; for (int i = 0; i < inverses.length; i++) { if (!getManageLRS() && inverses[i].isLRS()) continue; // if this is the owned side of the relation and has not yet been // loaded, no point in setting it now, cause it'll have the correct // value the next time it is loaded after the flush owned = fmd == inverses[i].getMappedByMetaData() && _action == ACTION_MANAGE && !isLoaded(other, inverses[i].getIndex()); switch (inverses[i].getDeclaredTypeCode()) { case JavaTypes.PC: if (!owned || inverses[i].getCascadeDelete() == ValueMetaData.CASCADE_AUTO) storeNull(other, inverses[i], sm.getManagedInstance()); break; case JavaTypes.COLLECTION: if (!owned || inverses[i].getElement().getCascadeDelete() == ValueMetaData.CASCADE_AUTO) removeFromCollection(other, inverses[i], sm.getManagedInstance()); break; } } } /** * Store null value at the given field. Verify that the given compare * value is the value being nulled. Pass NONE for no comparison. */ protected void storeNull(OpenJPAStateManager sm, FieldMetaData fmd, Object compare) { storeField(sm, fmd, compare, null); } /** * Store a given value at the given field. Compare the given * argument if not NONE. */ protected void storeField(OpenJPAStateManager sm, FieldMetaData fmd, Object compare, Object val) { Object oldValue = sm.fetchObjectField(fmd.getIndex()); if (oldValue == val) return; if (compare != NONE && oldValue != compare) return; switch (_action) { case ACTION_MANAGE: sm.settingObjectField(sm.getPersistenceCapable(), fmd.getIndex(), oldValue, val, OpenJPAStateManager.SET_USER); break; case ACTION_WARN: warnConsistency(sm, fmd); break; case ACTION_EXCEPTION: throwException(sm, fmd); default: throw new IllegalStateException(); } } /** * Remove the given instance from the collection. */ protected void removeFromCollection(OpenJPAStateManager sm, FieldMetaData fmd, Object val) { Collection coll = (Collection) sm.fetchObjectField(fmd.getIndex()); if (coll != null) { switch (_action) { case ACTION_MANAGE: remove: for (int i = 0; coll.remove(val); i++) if (i == 0 && coll instanceof Set) break remove; break; case ACTION_WARN: if (coll.contains(val)) warnConsistency(sm, fmd); break; case ACTION_EXCEPTION: if (coll.contains(val)) throwException(sm, fmd); break; default: throw new IllegalStateException(); } } } /** * Add the given value to the collection at the selected field. */ protected void addToCollection(OpenJPAStateManager sm, FieldMetaData fmd, Object val) { Collection coll = (Collection) sm.fetchObjectField(fmd.getIndex()); if (coll == null) { coll = (Collection) sm.newFieldProxy(fmd.getIndex()); sm.storeObjectField(fmd.getIndex(), coll); } if (!coll.contains(val)) { switch (_action) { case ACTION_MANAGE: coll.add(val); break; case ACTION_WARN: warnConsistency(sm, fmd); break; case ACTION_EXCEPTION: throwException(sm, fmd); default: throw new IllegalStateException(); } } } /** * Log an inconsistency warning */ protected void warnConsistency(OpenJPAStateManager sm, FieldMetaData fmd) { if (_log.isWarnEnabled()) _log.warn(_loc.get("inverse-consistency", fmd, sm.getId(), sm.getContext())); } /** * Throw an inconsistency exception */ protected void throwException(OpenJPAStateManager sm, FieldMetaData fmd) { throw new InvalidStateException(_loc.get("inverse-consistency", fmd, sm.getId(), sm.getContext())).setFailedObject (sm.getManagedInstance()).setFatal(true); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java0000644000000000000000000010132512133327272030341 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.kernel.exps.AbstractExpressionVisitor; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.Constant; import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.kernel.exps.ExpressionParser; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.kernel.exps.InMemoryExpressionFactory; import org.apache.openjpa.kernel.exps.Path; import org.apache.openjpa.kernel.exps.QueryExpressions; import org.apache.openjpa.kernel.exps.Resolver; import org.apache.openjpa.kernel.exps.StringContains; import org.apache.openjpa.kernel.exps.Subquery; import org.apache.openjpa.kernel.exps.Val; import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.kernel.exps.WildcardMatch; import org.apache.openjpa.lib.rop.ListResultObjectProvider; import org.apache.openjpa.lib.rop.RangeResultObjectProvider; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.UserException; /** * Implementation of an expression-based query, which can handle * String-based query expressions such as JPQL and JDOQL. * This implementation is suitable for in-memory operation. * Override the following methods to also support datastore operation: *
      *
    • Override {@link #supportsDataStoreExecution} to return * true.
    • *
    • Override {@link #executeQuery}, {@link #executeDelete}, and * {@link #executeUpdate} to execute the query against the data store. * Keep in mind that the parameters passed to this method might be in use * by several threads in different query instances. Thus components like * the expression factory must either be thread safe, or this method must * synchronize on them.
    • *
    • Override {@link #getDataStoreActions} to return a representation of * the actions that will be taken on the data store. For use in visual * tools.
    • *
    • Override {@link #getExpressionFactory} to return a factory for creating * expressions in the datastore's language. The factory must be cachable.
    • *
    * * @author Abe White */ public class ExpressionStoreQuery extends AbstractStoreQuery { private static final Localizer _loc = Localizer.forPackage (ExpressionStoreQuery.class); // maintain support for a couple of deprecated extensions private static final FilterListener[] _listeners = new FilterListener[]{ new StringContains(), new WildcardMatch(), }; protected final ExpressionParser _parser; protected transient Object _parsed; /** * Construct a query with a parser for the language. */ public ExpressionStoreQuery(ExpressionParser parser) { _parser = parser; } /** * Resolver used in parsing. */ public Resolver getResolver() { return new Resolver() { public Class classForName(String name, String[] imports) { return ctx.classForName(name, imports); } public FilterListener getFilterListener(String tag) { return ctx.getFilterListener(tag); } public AggregateListener getAggregateListener(String tag) { return ctx.getAggregateListener(tag); } public OpenJPAConfiguration getConfiguration() { return ctx.getStoreContext().getConfiguration(); } public QueryContext getQueryContext() { return ctx; } }; } /** * Allow direct setting of parsed state for facades that do parsing. * The facade should call this method twice: once with the query string, * and again with the parsed state. */ public boolean setQuery(Object query) { _parsed = query; return true; } public FilterListener getFilterListener(String tag) { for (int i = 0; i < _listeners.length; i++) if (_listeners[i].getTag().equals(tag)) return _listeners[i]; return null; } public Object newCompilation() { if (_parsed != null) return _parsed; return _parser.parse(ctx.getQueryString(), this); } public Object getCompilation() { return _parsed; } public void populateFromCompilation(Object comp) { _parser.populate(comp, this); } public void invalidateCompilation() { _parsed = null; } public boolean supportsInMemoryExecution() { return true; } public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs) { return new InMemoryExecutor(this, meta, subs, _parser, ctx.getCompilation(), new InMemoryExpressionFactory()); } public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs) { return new DataStoreExecutor(this, meta, subs, _parser, ctx.getCompilation()); } //////////////////////// // Methods for Override //////////////////////// /** * Execute the given expression against the given candidate extent. * * @param ex current executor * @param base the base type the query should match * @param types the independent candidate types * @param subclasses true if subclasses should be included in the results * @param facts the expression factory used to build the query for * each base type * @param parsed the parsed query values * @param params parameter values, or empty array * @param range result range * @return a provider for matching objects */ protected ResultObjectProvider executeQuery(Executor ex, ClassMetaData base, ClassMetaData[] types, boolean subclasses, ExpressionFactory[] facts, QueryExpressions[] parsed, Object[] params, Range range) { throw new UnsupportedException(); } /** * Execute the given expression against the given candidate extent * and delete the instances. * * @param ex current executor * @param base the base type the query should match * @param types the independent candidate types * @param subclasses true if subclasses should be included in the results * @param facts the expression factory used to build the query for * each base type * @param parsed the parsed query values * @param params parameter values, or empty array * @return a number indicating the number of instances deleted, * or null to execute the delete in memory */ protected Number executeDelete(Executor ex, ClassMetaData base, ClassMetaData[] types, boolean subclasses, ExpressionFactory[] facts, QueryExpressions[] parsed, Object[] params) { return null; } /** * Execute the given expression against the given candidate extent * and updates the instances. * * @param ex current executor * @param base the base type the query should match * @param types the independent candidate types * @param subclasses true if subclasses should be included in the results * @param facts the expression factory used to build the query for * each base type * @param parsed the parsed query values * @param params parameter values, or empty array * @return a number indicating the number of instances updated, * or null to execute the update in memory. */ protected Number executeUpdate(Executor ex, ClassMetaData base, ClassMetaData[] types, boolean subclasses, ExpressionFactory[] facts, QueryExpressions[] parsed, Object[] params) { return null; } /** * Return the commands that will be sent to the datastore in order * to execute the query, typically in the database's native language. * * @param base the base type the query should match * @param types the independent candidate types * @param subclasses true if subclasses should be included in the results * @param facts the expression factory used to build the query for * each base type * @param parsed the parsed query values * @param params parameter values, or empty array * @param range result range * @return a textual description of the query to execute */ protected String[] getDataStoreActions(ClassMetaData base, ClassMetaData[] types, boolean subclasses, ExpressionFactory[] facts, QueryExpressions[] parsed, Object[] params, Range range) { return StoreQuery.EMPTY_STRINGS; } /** * Return the assignable types for the given metadata whose expression * trees must be compiled independently. */ protected ClassMetaData[] getIndependentExpressionCandidates (ClassMetaData type, boolean subclasses) { return new ClassMetaData[]{ type }; } /** * Return an {@link ExpressionFactory} to use to create an expression to * be executed against an extent. Each factory will be used to compile * one filter only. The factory must be cachable. */ protected ExpressionFactory getExpressionFactory(ClassMetaData type) { throw new UnsupportedException(); } /** * Provides support for queries that hold query information * in a {@link QueryExpressions} instance. * * @author Marc Prud'hommeaux */ public static abstract class AbstractExpressionExecutor extends AbstractExecutor implements Executor { /** * Return the query expressions for one candidate type, or die if none. */ private QueryExpressions assertQueryExpression() { QueryExpressions[] exp = getQueryExpressions(); if (exp == null || exp.length < 1) throw new InvalidStateException(_loc.get("no-expressions")); return exp[0]; } /** * Throw proper exception if given value is a collection/map/array. */ protected void assertNotContainer(Value val, StoreQuery q) { // variables represent container elements, not the container itself if (val.isVariable()) return; Class type; if (val instanceof Path) { FieldMetaData fmd = ((Path) val).last(); type = (fmd == null) ? val.getType() : fmd.getDeclaredType(); } else type = val.getType(); switch (JavaTypes.getTypeCode(type)) { case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: throw new UserException(_loc.get("container-projection", q.getContext().getQueryString())); } } public final void validate(StoreQuery q) { QueryExpressions exps = assertQueryExpression(); ValidateGroupingExpressionVisitor.validate(q.getContext(), exps); } public void getRange(StoreQuery q, Object[] params, Range range) { QueryExpressions exps = assertQueryExpression(); if (exps.range.length == 0) return; if (exps.range.length == 2 && exps.range[0] instanceof Constant && exps.range[1] instanceof Constant) { try { range.start = ((Number) ((Constant) exps.range[0]). getValue(params)).longValue(); range.end = ((Number) ((Constant) exps.range[1]). getValue(params)).longValue(); return; } catch (ClassCastException cce) { // fall through to exception below } catch (NullPointerException npe) { // fall through to exception below } } throw new UserException(_loc.get("only-range-constants", q.getContext().getQueryString())); } public final Class getResultClass(StoreQuery q) { return assertQueryExpression().resultClass; } public final ResultShape getResultShape(StoreQuery q) { return assertQueryExpression().shape; } public final boolean[] getAscending(StoreQuery q) { return assertQueryExpression().ascending; } public final String getAlias(StoreQuery q) { return assertQueryExpression().alias; } public final String[] getProjectionAliases(StoreQuery q) { return assertQueryExpression().projectionAliases; } public Class[] getProjectionTypes(StoreQuery q) { return null; } public final int getOperation(StoreQuery q) { return assertQueryExpression().operation; } public final boolean isAggregate(StoreQuery q) { return assertQueryExpression().isAggregate(); } public final boolean isDistinct(StoreQuery q) { return assertQueryExpression().isDistinct(); } public final boolean hasGrouping(StoreQuery q) { return assertQueryExpression().grouping.length > 0; } public final OrderedMap> getOrderedParameterTypes(StoreQuery q) { return assertQueryExpression().parameterTypes; } /** * Creates a Object[] from the values of the given user parameters. */ public Object[] toParameterArray(StoreQuery q, Map userParams) { if (userParams == null || userParams.isEmpty()) return StoreQuery.EMPTY_OBJECTS; OrderedMap> paramTypes = getOrderedParameterTypes(q); Object[] arr = new Object[userParams.size()]; int base = positionalParameterBase(userParams.keySet()); for(Entry> entry : paramTypes.entrySet()){ Object key = entry.getKey(); int idx = (key instanceof Integer) ? ((Integer)key).intValue() - base : paramTypes.indexOf(key); if (idx >= arr.length || idx < 0) throw new UserException(_loc.get("gap-query-param", new Object[]{q.getContext().getQueryString(), key, userParams.size(), userParams})); Object value = userParams.get(key); validateParameterValue(key, value, (Class)entry.getValue()); arr[idx] = value; } return arr; } /** * Return the base (generally 0 or 1) to use for positional parameters. */ private static int positionalParameterBase(Collection params) { int low = Integer.MAX_VALUE; Object obj; int val; for (Iterator itr = params.iterator(); itr.hasNext();) { obj = itr.next(); if (!(obj instanceof Number)) return 0; // use 0 base when params are mixed types val = ((Number) obj).intValue(); if (val == 0) return val; if (val < low) low = val; } return low; } private static void validateParameterValue(Object key, Object value, Class expected) { if (expected == null) return; if (value == null) { if (expected.isPrimitive()) throw new UserException(_loc.get("null-primitive-param", key, expected)); } else { Class actual = value.getClass(); boolean strict = true; if (!Filters.canConvert(actual, expected, strict)) throw new UserException(_loc.get("param-value-mismatch", new Object[]{key, expected, value, actual})); } } public final Map getUpdates(StoreQuery q) { return assertQueryExpression().updates; } public final ClassMetaData[] getAccessPathMetaDatas(StoreQuery q) { QueryExpressions[] exps = getQueryExpressions(); if (exps.length == 1) return exps[0].accessPath; List metas = null; for (int i = 0; i < exps.length; i++) metas = Filters.addAccessPathMetaDatas(metas, exps[i].accessPath); if (metas == null) return StoreQuery.EMPTY_METAS; return (ClassMetaData[]) metas.toArray (new ClassMetaData[metas.size()]); } public boolean isPacking(StoreQuery q) { return false; } /** * Throws an exception if select or having clauses contain * non-aggregate, non-grouped paths. */ private static class ValidateGroupingExpressionVisitor extends AbstractExpressionVisitor { private final QueryContext _ctx; private boolean _grouping = false; private Set _grouped = null; private Value _agg = null; /** * Throw proper exception if query does not meet validation. */ public static void validate(QueryContext ctx, QueryExpressions exps) { if (exps.grouping.length == 0) return; ValidateGroupingExpressionVisitor visitor = new ValidateGroupingExpressionVisitor(ctx); visitor._grouping = true; for (int i = 0; i < exps.grouping.length; i++) exps.grouping[i].acceptVisit(visitor); visitor._grouping = false; if (exps.having != null) { Class cls = exps.having.getClass(); if (cls.getName().endsWith("Expression")) cls = cls.getSuperclass(); Object value2 = null; Method getValue2 = null; try { getValue2 = cls.getMethod("getValue2"); getValue2.setAccessible(true); value2 = getValue2.invoke(exps.having, (Object[]) null); } catch (NoSuchMethodException name) { // skip } catch (IllegalAccessException iae) { // skip } catch (InvocationTargetException ite) { // skip } if (value2 != null && value2 instanceof Subquery) ; // complex having with subquery, validation is performed by DBMS else exps.having.acceptVisit(visitor); } for (int i = 0; i < exps.projections.length; i++) exps.projections[i].acceptVisit(visitor); } public ValidateGroupingExpressionVisitor(QueryContext ctx) { _ctx = ctx; } public void enter(Value val) { if (_grouping) { if (val instanceof Path) { if (_grouped == null) _grouped = new HashSet(); _grouped.add(val); } } else if (_agg == null) { if (val.isAggregate()) _agg = val; else if (val instanceof Path && (_grouped == null || !_grouped.contains(val))) { throw new UserException(_loc.get("bad-grouping", _ctx.getCandidateType(), _ctx.getQueryString())); } } } public void exit(Value val) { if (val == _agg) _agg = null; } } } /** * Runs the expression query in memory. */ public static class InMemoryExecutor extends AbstractExpressionExecutor implements Executor, Serializable { private final ClassMetaData _meta; private final boolean _subs; private final InMemoryExpressionFactory _factory; private final QueryExpressions[] _exps; private final Class[] _projTypes; public InMemoryExecutor(ExpressionStoreQuery q, ClassMetaData candidate, boolean subclasses, ExpressionParser parser, Object parsed, InMemoryExpressionFactory factory) { _meta = candidate; _subs = subclasses; _factory = factory; _exps = new QueryExpressions[] { parser.eval(parsed, q, _factory, _meta) }; if (_exps[0].projections.length == 0) _projTypes = StoreQuery.EMPTY_CLASSES; else { AssertNoVariablesExpressionVisitor novars = new AssertNoVariablesExpressionVisitor(q.getContext()); _projTypes = new Class[_exps[0].projections.length]; for (int i = 0; i < _exps[0].projections.length; i++) { _projTypes[i] = _exps[0].projections[i].getType(); assertNotContainer(_exps[0].projections[i], q); _exps[0].projections[i].acceptVisit(novars); } for (int i = 0; i < _exps[0].grouping.length; i++) _exps[0].grouping[i].acceptVisit(novars); } } public QueryExpressions[] getQueryExpressions() { return _exps; } public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, Range range) { // execute in memory for candidate collection; // also execute in memory for transactional extents Collection coll = q.getContext().getCandidateCollection(); Iterator itr; if (coll != null) itr = coll.iterator(); else itr = q.getContext().getStoreContext(). extentIterator(_meta.getDescribedType(), _subs, q.getContext().getFetchConfiguration(), q.getContext().getIgnoreChanges()); // find matching objects List results = new ArrayList(); StoreContext ctx = q.getContext().getStoreContext(); try { Object obj; while (itr.hasNext()) { obj = itr.next(); if (_factory.matches(_exps[0], _meta, _subs, obj, ctx, params)) results.add(obj); } } finally { ImplHelper.close(itr); } // group results results = _factory.group(_exps[0], results, ctx, params); // apply having to filter groups if (_exps[0].having != null) { List matches = new ArrayList(results.size()); Collection c; itr = results.iterator(); while (itr.hasNext()) { c = (Collection) itr.next(); if (_factory.matches(_exps[0], c, ctx, params)) matches.add(c); } results = matches; } // apply projections, order results, and filter duplicates results = _factory.project(_exps[0], results, ctx, params); results = _factory.order(_exps[0], results, ctx, params); results = _factory.distinct(_exps[0], coll == null, results); ResultObjectProvider rop = new ListResultObjectProvider(results); if (range.start != 0 || range.end != Long.MAX_VALUE) rop = new RangeResultObjectProvider(rop, range.start,range.end); return rop; } public String[] getDataStoreActions(StoreQuery q, Object[] params, Range range) { // in memory queries have no datastore actions to perform return StoreQuery.EMPTY_STRINGS; } public Object getOrderingValue(StoreQuery q, Object[] params, Object resultObject, int orderIndex) { // if this is a projection, then we have to order on something // we selected if (_exps[0].projections.length > 0) { String ordering = _exps[0].orderingClauses[orderIndex]; for (int i = 0; i < _exps[0].projectionClauses.length; i++) if (ordering.equals(_exps[0].projectionClauses[i])) return ((Object[]) resultObject)[i]; throw new InvalidStateException(_loc.get ("merged-order-with-result", q.getContext().getLanguage(), q.getContext().getQueryString(), ordering)); } // use the parsed ordering expression to extract the ordering value Val val = (Val) _exps[0].ordering[orderIndex]; return val.evaluate(resultObject, resultObject, q.getContext(). getStoreContext(), params); } public Class[] getProjectionTypes(StoreQuery q) { return _projTypes; } /** * Throws an exception if a variable is found. */ private static class AssertNoVariablesExpressionVisitor extends AbstractExpressionVisitor { private final QueryContext _ctx; public AssertNoVariablesExpressionVisitor(QueryContext ctx) { _ctx = ctx; } public void enter(Value val) { if (!val.isVariable()) return; throw new UnsupportedException(_loc.get("inmem-agg-proj-var", _ctx.getCandidateType(), _ctx.getQueryString())); } } } /** * The DataStoreExecutor executes the query against the * implementation's overridden {@link #executeQuery} method. * * @author Marc Prud'hommeaux */ public static class DataStoreExecutor extends AbstractExpressionExecutor implements Executor, Serializable { private ClassMetaData _meta; private ClassMetaData[] _metas; private boolean _subs; private ExpressionParser _parser; private ExpressionFactory[] _facts; private QueryExpressions[] _exps; private Class[] _projTypes; private Value[] _inMemOrdering; public DataStoreExecutor(ExpressionStoreQuery q, ClassMetaData meta, boolean subclasses, ExpressionParser parser, Object parsed) { _metas = q.getIndependentExpressionCandidates(meta, subclasses); if (_metas.length == 0) throw new UserException(_loc.get("query-unmapped", meta)); _meta = meta; _subs = subclasses; _parser = parser; _facts = new ExpressionFactory[_metas.length]; for (int i = 0; i < _facts.length; i++) _facts[i] = q.getExpressionFactory(_metas[i]); _exps = new QueryExpressions[_metas.length]; for (int i = 0; i < _exps.length; i++) _exps[i] = parser.eval(parsed, q, _facts[i], _metas[i]); if (_exps[0].projections.length == 0) _projTypes = StoreQuery.EMPTY_CLASSES; else { _projTypes = new Class[_exps[0].projections.length]; for (int i = 0; i < _exps[0].projections.length; i++) { assertNotContainer(_exps[0].projections[i], q); _projTypes[i] = _exps[0].projections[i].getType(); } } } public QueryExpressions[] getQueryExpressions() { return _exps; } public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, Range range) { range.lrs &= !isAggregate(q) && !hasGrouping(q); return ((ExpressionStoreQuery) q).executeQuery(this, _meta, _metas, _subs, _facts, _exps, params, range); } public Number executeDelete(StoreQuery q, Object[] params) { try { Number num = ((ExpressionStoreQuery) q).executeDelete(this, _meta, _metas, _subs, _facts, _exps, params); if (num == null) return q.getContext().deleteInMemory(q, this, params); return num; } finally { for (ClassMetaData cmd : getAccessPathMetaDatas(q)) { DataCache cache = cmd.getDataCache(); if (cache != null && cache.getEvictOnBulkUpdate()) { cache.removeAll(cmd.getDescribedType(), true); } } } } public Number executeUpdate(StoreQuery q, Object[] params) { try { Number num = ((ExpressionStoreQuery) q).executeUpdate(this, _meta, _metas, _subs, _facts, _exps, params); if (num == null) return q.getContext().updateInMemory(q, this, params); return num; } finally { for (ClassMetaData cmd : getAccessPathMetaDatas(q)) { DataCache cache = cmd.getDataCache(); if (cache != null && cache.getEvictOnBulkUpdate()) { cache.removeAll(cmd.getDescribedType(), true); } } } } public String[] getDataStoreActions(StoreQuery q, Object[] params, Range range) { return ((ExpressionStoreQuery) q).getDataStoreActions(_meta, _metas, _subs, _facts, _exps, params, range); } public Object getOrderingValue(StoreQuery q, Object[] params, Object resultObject, int orderIndex) { // if this is a projection, then we have to order on something // we selected if (_exps[0].projections.length > 0) { String ordering = _exps[0].orderingClauses[orderIndex]; for (int i = 0; i < _exps[0].projectionClauses.length; i++) if (ordering.equals(_exps[0].projectionClauses[i])) return ((Object[]) resultObject)[i]; throw new InvalidStateException(_loc.get ("merged-order-with-result", q.getContext().getLanguage(), q.getContext().getQueryString(), ordering)); } // need to parse orderings? synchronized (this) { if (_inMemOrdering == null) { ExpressionFactory factory = new InMemoryExpressionFactory(); _inMemOrdering = _parser.eval(_exps[0].orderingClauses, (ExpressionStoreQuery) q, factory, _meta); } if (_inMemOrdering == null) _inMemOrdering = _exps[0].ordering; } // use the parsed ordering expression to extract the ordering value Val val = (Val) _inMemOrdering[orderIndex]; return val.evaluate(resultObject, resultObject, q.getContext().getStoreContext(), params); } public Class[] getProjectionTypes(StoreQuery q) { return _projTypes; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/HollowState.java0000644000000000000000000000505412133327272026406 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a hollow instance that exists in the data store, but whose * state has not been loaded and who is not active in the current transaction * (if any). This may be the state of instances returned on ID lookups or by * traversing relations, and the state of persistent instances outside of * transactions (unless the retainValues flag is set in the Broker). * * @author Abe White */ @SuppressWarnings("serial") class HollowState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.clearFields(); context.clearSavedFields(); context.setDirty(false); } PCState delete(StateManagerImpl context) { context.preDelete(); return PDELETED; } PCState transactional(StateManagerImpl context) { return PCLEAN; } PCState release(StateManagerImpl context) { return TRANSIENT; } PCState beforeRead(StateManagerImpl context, int field) { return PCLEAN; } PCState beforeOptimisticRead(StateManagerImpl context, int field) { return PNONTRANS; } PCState beforeNontransactionalRead(StateManagerImpl context, int field) { return PNONTRANS; } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return PDIRTY; } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return PDIRTY; } PCState beforeNontransactionalWrite(StateManagerImpl context, int field, boolean mutate) { return PNONTRANS; } boolean isPersistent() { return true; } public String toString() { return "Hollow"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerFactory.java0000644000000000000000000001200712133327272026711 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.util.Map; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.util.Closeable; /** * Factory for {@link Broker} instances. * * @author Abe White * @since 0.4.0 */ public interface BrokerFactory extends Serializable, Closeable { /** * Return the configuration for this factory. */ public OpenJPAConfiguration getConfiguration(); /** * Return properties describing this runtime. */ public Map getProperties(); /** * Return all of the supported properties as a set of keys. If a property * has multiple keys, all keys will be returned. * * @since 2.0.0 */ public Set getSupportedProperties(); /** * Put the specified key-value pair into the map of user objects. */ public Object putUserObject(Object key, Object val); /** * Get the value for the specified key from the map of user objects. */ public Object getUserObject(Object key); /** * Return a broker with default settings. */ public Broker newBroker(); /** * Return a broker using the given credentials and in the given * transaction and connection retain mode, optionally finding * existing broker in the global transaction. */ public Broker newBroker(String user, String pass, boolean managed, int connRetainMode, boolean findExisting); /** * Return a new broker using the supplied *
      *
    • credentials
    • *
    • transaction management mode
    • *
    • connectionRetainMode
    • *
    • connectionFactories
    • *
    * * @param user Username to use when obtaining a connection. Will be ignored if a connection factory is * obtained from JNDI. * @param pass Password to use when obtaining a connection. Will be ignored if a connection factory is * obtained from JNDI. * @param managed Whether managed transactions will be used by this Broker * @param connRetainMode {@link ConnectionRetainMode} * @param findExisting Whether the internal pool of brokers should be used. * @param cfName JTA ConnectionFactory to use * @param cf2Name Non-JTA ConnectionFactory to use. * @return A Broker which matches the provided criteria. */ public Broker newBroker(String user, String pass, boolean managed, int connRetainMode, boolean findExisting, String cfName, String cf2Name); /** * Register a listener for lifecycle-related events on the specified * classes. If the classes are null, all events will be propagated to * the listener. The listener will be passed on to all new brokers. * * @since 0.3.3 */ public void addLifecycleListener(Object listener, Class[] classes); /** * Remove a listener for lifecycle-related events. * * @since 0.3.3 */ public void removeLifecycleListener(Object listener); /** * Register a listener for transaction-related events on the specified * classes. It will be registered with all {@link Broker}s created * from this instance moving forward. * * @since 1.0.0 */ public void addTransactionListener(Object listener); /** * Remove a listener for transaction-related events. It will no longer * be registered with new {@link Broker}s created from this instance. * * @since 1.0.0 */ public void removeTransactionListener(Object listener); /** * Close the factory. */ public void close(); /** * Returns true if this broker factory is closed. */ public boolean isClosed(); /** * Synchronizes on an internal lock. */ public void lock(); /** * Release the internal lock. */ public void unlock (); /** * assert that this broker is open. If the broker has been closed an IllegalStateException will be thrown * with information on when the broker was closed. */ public void assertOpen(); /** * This method is invoked AFTER a BrokerFactory has been instantiated. */ public void postCreationCallback(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ResultPacker.java0000644000000000000000000003473112133327272026551 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; /** * Helper class to pack results into the result class set on the query. * * @author Abe White * @author Patrick Linskey * @nojavadoc */ public class ResultPacker { private static final Localizer _loc = Localizer.forPackage (ResultPacker.class); private static final Set> _stdTypes = new HashSet>(); static { _stdTypes.add(Object[].class); _stdTypes.add(Object.class); _stdTypes.add(Map.class); _stdTypes.add(HashMap.class); _stdTypes.add(Character.class); _stdTypes.add(Boolean.class); _stdTypes.add(Byte.class); _stdTypes.add(Short.class); _stdTypes.add(Integer.class); _stdTypes.add(Long.class); _stdTypes.add(Float.class); _stdTypes.add(Double.class); _stdTypes.add(String.class); _stdTypes.add(BigInteger.class); _stdTypes.add(BigDecimal.class); _stdTypes.add(Date.class); _stdTypes.add(java.sql.Date.class); _stdTypes.add(java.sql.Time.class); _stdTypes.add(java.sql.Timestamp.class); _stdTypes.add(Calendar.class); _stdTypes.add(GregorianCalendar.class); } private final Class _resultClass; private final String[] _aliases; private final Member[] _sets; private final Method _put; private final Constructor _constructor; /** * Protected constructor to bypass this implementation but allow extension. */ protected ResultPacker() { _resultClass = null; _aliases = null; _sets = null; _put = null; _constructor = null; } /** * Constructor for result class without a projection. */ public ResultPacker(Class candidate, String alias, Class resultClass) { this(candidate, null, new String[]{ alias }, resultClass); } /** * Constructor for standard projection. * * @param types the projection value types * @param aliases the alias for each projection value * @param resultClass the class to pack into */ public ResultPacker(Class[] types, String[] aliases, Class resultClass) { this(null, types, aliases, resultClass); } /** * Internal constructor. */ private ResultPacker(Class candidate, Class[] types, String[] aliases, Class resultClass) { _aliases = aliases; if (candidate == resultClass || isInterface(resultClass, candidate) ||(types != null && types.length == 1 && types[0] == resultClass) || resultClass.isArray()) { _resultClass = resultClass; _sets = null; _put = null; _constructor = null; } else if (resultClass.isPrimitive()) { assertConvertable(candidate, types, resultClass); _resultClass = Filters.wrap(resultClass); _sets = null; _put = null; _constructor = null; } else if (!_stdTypes.contains(_resultClass = resultClass)) { // check for a constructor that matches the projection types Constructor cons = null; if (types != null && types.length > 0) { try { cons = _resultClass.getConstructor(types); } catch (NoSuchMethodException nsme) { } } _constructor = cons; if (cons == null) { Method[] methods = _resultClass.getMethods(); Field[] fields = _resultClass.getFields(); _put = findPut(methods); _sets = new Member[aliases.length]; Class type; for (int i = 0; i < _sets.length; i++) { type = (types == null) ? candidate : types[i]; _sets[i] = findSet(aliases[i], type, fields, methods); if (_sets[i] == null && _put == null) throw new UserException(_loc.get("cant-set", resultClass, aliases[i], types == null ? null : Arrays.asList(types))); } } else { _sets = null; _put = null; } } else { if (resultClass != Map.class && resultClass != HashMap.class && resultClass != Object[].class) assertConvertable(candidate, types, resultClass); _sets = null; _put = null; _constructor = null; } } boolean isInterface(Class intf, Class actual) { if (actual != null) { Class[] intfs = actual.getInterfaces(); for (Class c : intfs) { if (c == intf) return true; } } return false; } /** * Ensure that conversion is possible. */ private void assertConvertable(Class candidate, Class[] types, Class resultClass) { Class c = (types == null) ? candidate : types[0]; if ((types != null && types.length != 1) || (c != null && c != Object.class && !Filters.canConvert(c, resultClass, true))) throw new UserException(_loc.get("cant-convert-result", c, resultClass)); } /** * Pack the given object into an instance of the query's result class. */ public Object pack(Object result) { if (_resultClass == result.getClass()) return result; // special cases for efficient basic types where we want to avoid // creating an array for call to general pack method below if (_resultClass == Object.class) return result; if (_resultClass == Object[].class) return new Object[]{ result }; if (_resultClass == HashMap.class || _resultClass == Map.class) { HashMap map = new HashMap(1, 1F); map.put(_aliases[0], result); return map; } // primitive or simple type? if (_constructor == null && _sets == null) return Filters.convert(result, _resultClass); // this is some complex case, so worth it to create the array and // use the general pack method return packUserType(new Object[]{ result }); } /** * Pack the given array into an instance of the query's result class. */ public Object pack(Object[] result) { if (result == null || result.length == 0) return null; // special cases for object arrays and maps if (_resultClass == Object[].class) { // the result might contain extra data at the end if (result.length > _aliases.length) { Object[] trim = new Object[_aliases.length]; System.arraycopy(result, 0, trim, 0, trim.length); return trim; } return result; } if (_resultClass.isArray()) { Class elementType = _resultClass.getComponentType(); Object castResult = Array.newInstance(elementType, result.length); for (int i = 0; i < result.length; i++) Array.set(castResult, i, elementType.cast(result[i])); return castResult; } if (_resultClass == Object.class) return result[0]; if (_resultClass == HashMap.class || _resultClass == Map.class) { Map map = new HashMap(result.length); for (int i = 0; i < _aliases.length; i++) map.put(_aliases[i], result[i]); return map; } // primitive or simple type? if (_sets == null && _constructor == null) return Filters.convert(result[0], _resultClass); // must be a user-defined type return packUserType(result); } /** * Pack the given result into the user-defined result class. */ private Object packUserType(Object[] result) { try { // use the constructor first, if we have one if (_constructor != null) return _constructor.newInstance(result); Object user = AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(_resultClass)); for (int i = 0; i < _aliases.length; i++) { if (_sets[i] instanceof Method) { Method meth = (Method) _sets[i]; meth.invoke(user, new Object[]{ Filters.convert (result[i], meth.getParameterTypes()[0]) }); } else if (_sets[i] instanceof Field) { Field field = (Field) _sets[i]; field.set(user, Filters.convert(result[i], field.getType())); } else if (_put != null) { _put.invoke(user, new Object[]{ _aliases[i], result[i] }); } } return user; } catch (OpenJPAException ke) { throw ke; } catch (PrivilegedActionException pae) { throw new UserException(_loc.get("pack-instantiation-err", _resultClass), pae.getException()); } catch (InstantiationException ie) { throw new UserException(_loc.get("pack-instantiation-err", _resultClass), ie); } catch (Exception e) { throw new UserException(_loc.get("pack-err", _resultClass), e); } } /** * Return the set method for the given property. */ private static Member findSet(String alias, Class type, Field[] fields, Method[] methods) { if (StringUtils.isEmpty(alias)) return null; if (type == Object.class) type = null; // check public fields first Field field = null; for (int i = 0; i < fields.length; i++) { // if we find a field with the exact name, either return it // if it's the right type or give up if it's not if (fields[i].getName().equals(alias)) { if (type == null || Filters.canConvert(type, fields[i].getType(), true)) return fields[i]; break; } // otherwise if we find a field with the right name but the // wrong case, record it and if we don't find an exact match // for a field or setter we'll use it if (field == null && fields[i].getName().equalsIgnoreCase(alias) && (type == null || Filters.canConvert(type, fields[i].getType(), true))) field = fields[i]; } // check setter methods String setName = "set" + StringUtils.capitalize(alias); Method method = null; boolean eqName = false; Class[] params; for (int i = 0; i < methods.length; i++) { if (!methods[i].getName().equalsIgnoreCase(setName)) continue; params = methods[i].getParameterTypes(); if (params.length != 1) continue; if (type != null && params[0] == Object.class) { // we found a generic object setter; now see if the name // is an exact match, and if so record this setter. if we // don't find an exact type match later, we'll use it. if // the names are not an exact match, only record this setter // if we haven't found any others that match at all if (methods[i].getName().equals(setName)) { eqName = true; method = methods[i]; } else if (method == null) method = methods[i]; } else if (type == null || Filters.canConvert(type, params[0], true)) { // we found a setter with the right type; now see if the name // is an exact match. if so, return the setter. if not, // record the setter only if we haven't found a generic one // with an exact name match if (methods[i].getName().equals(setName)) return methods[i]; if (method == null || !eqName) method = methods[i]; } } // if we have an exact method name match, return it; otherwise favor // an inexact field to an inexact method if (eqName || field == null) return method; return field; } /** * Return the put method if one exists. */ private static Method findPut(Method[] methods) { Class[] params; for (int i = 0; i < methods.length; i++) { if (!methods[i].getName().equals("put")) continue; params = methods[i].getParameterTypes(); if (params.length == 2 && params[0] == Object.class && params[1] == Object.class) return methods[i]; } return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/EDeletedState.java0000644000000000000000000000360112133327272026611 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an embedded instance that has been deleted in the current * transaction. * * @author Abe White */ @SuppressWarnings("serial") class EDeletedState extends PCState { PCState commit(StateManagerImpl context) { return TRANSIENT; } PCState commitRetain(StateManagerImpl context) { return TRANSIENT; } PCState rollback(StateManagerImpl context) { return TRANSIENT; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return ENONTRANS; } PCState nontransactional(StateManagerImpl context) { return error("dirty", context); } PCState release(StateManagerImpl context) { return TRANSIENT; } boolean isTransactional() { return true; } public boolean isPersistent() { return true; } boolean isDeleted() { return true; } boolean isDirty() { return true; } public String toString() { return "Embedded-Deleted"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/NoneLockManager.java0000644000000000000000000000307012133327272027140 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * A lock manager that does not perform any locking. * * @author Marc Prud'hommeaux */ public class NoneLockManager extends AbstractLockManager { public void lock(OpenJPAStateManager sm, int level, int timeout, Object context) { // Duplicate code in the 2 lock methods to enforce proper action // and avoid unexpected behavior due to method override. sm.setLock(Boolean.TRUE); } public void refreshLock(OpenJPAStateManager sm, int level, int timeout, Object context) { sm.setLock(Boolean.TRUE); } public void release(OpenJPAStateManager sm) { sm.setLock(null); } public int getLockLevel(OpenJPAStateManager sm) { return LOCK_NONE; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/RestoreState.java0000644000000000000000000000242112133327272026560 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * State restore constants. * * @author Abe White * @since 0.4.0 */ public interface RestoreState { /** * Do not restore any state on rollback. */ public static final int RESTORE_NONE = 0; /** * Restore immutable state on rollback; clear mutable state. */ public static final int RESTORE_IMMUTABLE = 1; /** * Restore all state on rollback. */ public static final int RESTORE_ALL = 2; } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNewFlushedDeletedState.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNewFlushedDeletedState.ja0000644000000000000000000000467112133327272030272 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an instance that was made persistent within the * current transaction, flushed, and subsequently deleted. * * @author Patrick Linskey */ @SuppressWarnings("serial") class PNewFlushedDeletedState extends PCState { PCState flush(StateManagerImpl context) { return PNEWFLUSHEDDELETEDFLUSHED; } PCState commit(StateManagerImpl context) { return TRANSIENT; } PCState commitRetain(StateManagerImpl context) { return TRANSIENT; } PCState rollback(StateManagerImpl context) { return TRANSIENT; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return TRANSIENT; } PCState persist(StateManagerImpl context) { return PNEW; } PCState nontransactional(StateManagerImpl context) { return error("deleted", context); } PCState release(StateManagerImpl context) { return error("deleted", context); } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } boolean isTransactional() { return true; } boolean isPersistent() { return true; } boolean isNew() { return true; } boolean isDeleted() { return true; } boolean isDirty() { return true; } public String toString() { return "Persistent-New-Flushed-Deleted"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ConnectionRetainModes.java0000644000000000000000000000270012133327272030366 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Connection retain mode constants. * * @author Abe White * @since 0.4.0 */ public interface ConnectionRetainModes { /** * Constant indicating that connections will be obtained as needed. */ public static final int CONN_RETAIN_DEMAND = 0; /** * Constant indicating that connections will be retained for the life * of each transaction. */ public static final int CONN_RETAIN_TRANS = 1; /** * Constant indicating that each broker will retain a single connection * that it will use for its lifespan. */ public static final int CONN_RETAIN_ALWAYS = 2; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Broker.java0000644000000000000000000005520712133327272025372 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Collection; import java.util.Map; import java.util.Set; import javax.transaction.Synchronization; import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.event.CallbackModes; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.RuntimeExceptionTranslator; /** * The broker is the primary interface into the OpenJPA runtime. Each broker * maintains an independent object cache and an independent transactional * context. * * @since 0.4.0 * @author Abe White */ public interface Broker extends Synchronization, Closeable, StoreContext, ConnectionRetainModes, DetachState, LockLevels, RestoreState, AutoClear, AutoDetach, CallbackModes { /** * Set the broker's behavior for implicit actions such as flushing, * automatic detachment, and exceptions thrown by managed instances outside * a broker operation. A broker's implicit behavior can only be set once; * after the first invocation with non-null arguments, * subsequent invocations of this method are ignored. */ public void setImplicitBehavior(OpCallbacks call, RuntimeExceptionTranslator ex); /** * Return the factory that produced this broker. */ public BrokerFactory getBrokerFactory(); /** * Return the connection retain mode for this broker. */ public int getConnectionRetainMode(); /** * Return the managed runtime in use. */ public ManagedRuntime getManagedRuntime(); /** * Return the inverse manager in use. * * @since 0.3.2 */ public InverseManager getInverseManager(); /** * Whether the broker or its managed instances are used in a multithreaded * environment. */ public boolean getMultithreaded(); /** * Whether the broker or its managed instances are used in a multithreaded * environment. */ public void setMultithreaded(boolean multi); /** * Whether to take into account changes in the transaction when executing * a query or iterating an extent. */ public boolean getIgnoreChanges(); /** * Whether to take into account changes in the transaction when executing * a query or iterating an extent. */ public void setIgnoreChanges(boolean ignore); /** * Whether to allow nontransactional access to persistent state. */ public boolean getNontransactionalRead(); /** * Whether to allow nontransactional access to persistent state. */ public void setNontransactionalRead(boolean read); /** * Whether to allow nontransactional changes to persistent state. */ public boolean getNontransactionalWrite(); /** * Whether to allow nontransactional changes to persistent state. */ public void setNontransactionalWrite(boolean write); /** * Whether to restore an object's original state on rollback. */ public int getRestoreState(); /** * Whether to restore an object's original state on rollback. */ public void setRestoreState(int restore); /** * Whether to use optimistic transactional semantics. */ public boolean getOptimistic(); /** * Whether to use optimistic transactional semantics. */ public void setOptimistic(boolean opt); /** * Whether objects retain their persistent state on transaction commit. */ public boolean getRetainState(); /** * Whether objects retain their persistent state on transaction commit. */ public void setRetainState(boolean retain); /** * Whether objects clear when entering transactions. */ public int getAutoClear(); /** * Whether objects clear when entering transactions. */ public void setAutoClear(int clear); /** * Whether to check for a global transaction upon every managed, * non-transactional operation. Defaults to false. */ public boolean getSyncWithManagedTransactions(); /** * Whether to check for a global transaction upon every managed, * non-transactional operation. Defaults to false. */ public void setSyncWithManagedTransactions(boolean resync); /** * Bit flags marked in {@link AutoDetach} which indicate when persistent * managed objects should be automatically detached in-place. */ public int getAutoDetach(); /** * Bit flags marked in {@link AutoDetach} which indicate when persistent * managed objects should be automatically detached in-place. */ public void setAutoDetach(int flags); /** * Bit flags marked in {@link AutoDetach} which indicate when persistent * managed objects should be automatically detached in-place. */ public void setAutoDetach(int flag, boolean on); /** * Retrieve the current properties for this broker Some of these properties * may have been changed from the original configuration. * * @return the changed properties * * @since 2.0.0 */ public Map getProperties(); /** * Return the supported properties for this broker as property keys. If a * property has multiple keys, all keys will be returned. * * @since 2.0.0 */ public Set getSupportedProperties(); /** * Whether to treat relations to detached instances during persist * operations as new or as pseudo-hollow instances. */ public boolean isDetachedNew(); /** * Whether to treat relations to detached instances as new. */ public void setDetachedNew(boolean isNew); /** * Whether to also evict an object from the store cache when it is * evicted through this broker. */ public boolean getEvictFromDataCache(); /** * Whether to also evict an object from the store cache when it is * evicted through this broker. */ public void setEvictFromDataCache(boolean evict); /** * Put the specified key-value pair into the map of user objects. Use * a value of null to remove the key. * * @since 0.3.2 */ public Object putUserObject(Object key, Object val); /** * Get the value for the specified key from the map of user objects. * * @since 0.3.2 */ public Object getUserObject(Object key); /** * Register a listener for transaction-related events. * * @since 0.2.5 */ public void addTransactionListener(Object listener); /** * Remove a listener for transaction-related events. * * @since 0.2.5 */ public void removeTransactionListener(Object listener); /** * Gets an umodifiable collection of currently registered lsteners. * * @since 2.0.0 */ public Collection getTransactionListeners(); /** * The callback mode for handling exceptions from transaction event * listeners. */ public int getTransactionListenerCallbackMode(); /** * The callback mode for handling exceptions from transaction event * listeners. */ public void setTransactionListenerCallbackMode(int mode); /** * Register a listener for lifecycle-related events on the specified * classes. If the classes are null, all events will be propagated to * the listener. * * @since 0.3.3 */ public void addLifecycleListener(Object listener, Class[] classes); /** * Remove a listener for lifecycle-related events. * * @since 0.3.3 */ public void removeLifecycleListener(Object listener); /** * Return the lifecycle event manager associated with the broker. */ public LifecycleEventManager getLifecycleEventManager(); /** * The callback mode for handling exceptions from lifecycle event listeners. */ public int getLifecycleListenerCallbackMode(); /** * The callback mode for handling exceptions from lifecycle event listeners. */ public void setLifecycleListenerCallbackMode(int mode); /** * Affirms if this receiver is caching prepared queries. * * @since 2.0.0 */ public boolean getCachePreparedQuery(); /** * Sets whether this receiver will cache prepared queries during its * lifetime. The cache configured at BrokerFactory level is not affected by * setting it inactive for this receiver. * * @since 2.0.0 */ public void setCachePreparedQuery(boolean flag); /** * Begin a transaction. */ public void begin(); /** * Commit the current transaction. */ public void commit(); /** * Rollback the current transaction. */ public void rollback(); /** * Attempt to synchronize with a current managed transaction, returning * true if successful, false if no managed transaction is active. */ public boolean syncWithManagedTransaction(); /** * Issue a commit and then start a new transaction. This is identical to: *
     broker.commit (); broker.begin ();
         * 
    except that the broker's internal atomic lock is utilized, * so this method can be safely executed from multiple threads. * * @see #commit() * @see #begin() * @since 0.2.4 */ public void commitAndResume(); /** * Issue a rollback and then start a new transaction. This is identical to: *
     broker.rollback (); broker.begin ();
         * 
    except that the broker's internal atomic lock is utilized, * so this method can be safely executed from multiple threads. * * @see #rollback() * @see #begin() * @since 0.2.4 */ public void rollbackAndResume(); /** * Return whether the current transaction has been marked for rollback. */ public boolean getRollbackOnly(); /** * Mark the current transaction for rollback. */ public void setRollbackOnly(); /** * Mark the current transaction for rollback with the specified cause * of the rollback. * * @since 0.9.7 */ public void setRollbackOnly(Throwable cause); /** * Returns the Throwable that caused the transaction to be * marked for rollback. * * @return the Throwable, or null if none was given * * @since 0.9.7 */ public Throwable getRollbackCause(); /** * Set a transactional savepoint where operations after this savepoint * will be rolled back. */ public void setSavepoint(String name); /** * Rollback the current transaction to the last savepoint. * Savepoints set after this one will become invalid. */ public void rollbackToSavepoint(); /** * Rollback the current transaction to the given savepoint name. * Savepoints set after this one will become invalid. */ public void rollbackToSavepoint(String name); /** * Release the last set savepoint and any resources associated with it. * The given savepoint and any set after it will become invalid. */ public void releaseSavepoint(); /** * Release the savepoint and any resources associated with it. * The given savepoint and any set after it will become invalid. */ public void releaseSavepoint(String name); /** * Flush all transactional instances to the data store. This method may * set the rollback only flag on the current transaction if it encounters * an error. * * @since 0.2.5 */ public void flush(); /** * Run pre-flush actions on transactional objects, including * persistence-by-reachability, inverse relationship management, * deletion of dependent instances, and instance callbacks. * Transaction listeners are not invoked. * * @since 0.3.3 */ public void preFlush(); /** * Validate the changes made in this transaction, reporting any optimistic * violations, constraint violations, etc. In a datastore transaction or * a flushed optimistic transaction, this method will act just like * {@link #flush}. In an optimistic transaction that has not yet begun a * datastore-level transaction, however, it will only report exceptions * that would occur on flush, without retaining any datastore resources. */ public void validateChanges(); /** * Persist the given object. */ public void persist(Object obj, OpCallbacks call); /** * Persist the given objects. */ public void persistAll(Collection objs, OpCallbacks call); /** * Make the given instance persistent. Unlike other persist operations, * this method does not immediately cascade to fields marked * {@link ValueMetaData#CASCADE_IMMEDIATE}. * * @param pc the instance to persist * @param id the id to give the state manager; may be null for default * @return the state manager for the newly persistent instance */ public OpenJPAStateManager persist(Object pc, Object id, OpCallbacks call); /** * Delete the given object. */ public void delete(Object pc, OpCallbacks call); /** * Delete the given objects. */ public void deleteAll(Collection objs, OpCallbacks call); /** * Release the given object from management. This operation is not * recursive. */ public void release(Object pc, OpCallbacks call); /** * Release the given objects from management. This operation is not * recursive. */ public void releaseAll(Collection objs, OpCallbacks call); /** * Refresh the state of the given object. */ public void refresh(Object pc, OpCallbacks call); /** * Refresh the state of the given objects. */ public void refreshAll(Collection objs, OpCallbacks call); /** * Evict the given object. */ public void evict(Object pc, OpCallbacks call); /** * Evict the given objects. */ public void evictAll(Collection objs, OpCallbacks call); /** * Evict all clean objects. */ public void evictAll(OpCallbacks call); /** * Evict all persistent-clean and persistent-nontransactional * instances in the given {@link Extent}. */ public void evictAll(Extent extent, OpCallbacks call); /** * Detach all objects in place. A flush will be performed before * detaching the entities. */ public void detachAll(OpCallbacks call); /** * Detach all objects in place, with the option of performing a * flush before doing the detachment. * @param call Persistence operation callbacks * @param flush boolean value to indicate whether to perform a * flush before detaching the entities (true, do the flush; * false, don't do the flush) */ public void detachAll(OpCallbacks call, boolean flush); /** * Detach the specified object from the broker. * * @param pc the instance to detach * @return the detached instance */ public Object detach(Object pc, OpCallbacks call); /** * Detach the specified objects from the broker. The objects returned can * be manipulated and re-attached with {@link #attachAll}. The * detached instances will be unmanaged copies of the specified parameters, * and are suitable for serialization and manipulation outside * of a OpenJPA environment. When detaching instances, only fields * in the current {@link FetchConfiguration} will be traversed. Thus, * to detach a graph of objects, relations to other persistent * instances must either be in the default-fetch-group, * or in the current custom {@link FetchConfiguration}. * * @param objs the instances to detach * @return the detached instances */ public Object[] detachAll(Collection objs, OpCallbacks call); /** * Import the specified detached object into the broker. * * @param pc instance to import * @return the re-attached instance * @param copyNew whether to copy new instances */ public Object attach(Object pc, boolean copyNew, OpCallbacks call); /** * Import the specified objects into the broker. Instances that were * previously detached from this or another broker will have their * changed merged into the persistent instances. Instances that * are new will be persisted as new instances. * * @param objs array of instances to import * @return the re-attached instances * @param copyNew whether to copy new instances */ public Object[] attachAll(Collection objs, boolean copyNew, OpCallbacks call); /** * Create a new instance of type cls. If cls is * an interface or an abstract class whose abstract methods follow the * JavaBeans convention, this method will create a concrete implementation * according to the metadata that defines the class. * Otherwise, if cls is a managed type, this will return an * instance of the specified class. * * @throws IllegalArgumentException if cls is not a managed * type or interface. */ public Object newInstance(Class cls); /** * Returns true if obj is a detached object * (one that can be reattached to a {@link Broker} via a call to * {@link Broker#attach}); otherwise returns false. */ public boolean isDetached(Object obj); /** * Return an extent of the given class, optionally including subclasses. */ public Extent newExtent(Class cls, boolean subs); /** * Create a new query from the given data, with the given candidate class * and language. */ public Query newQuery(String language, Class cls, Object query); /** * Create a new query in the given language. */ public Query newQuery(String language, Object query); /** * Returns a {@link Seq} for the datastore identity values of the * specified persistent class, or null if the class' identity cannot be * represented as a sequence. */ public Seq getIdentitySequence(ClassMetaData meta); /** * Returns a {@link Seq} for the generated values of the specified * field, or null if the field is not generated. */ public Seq getValueSequence(FieldMetaData fmd); /** * Ensure that the given instance is locked at the given lock level. * * @param pc the object to lock * @param level the lock level to use * @param timeout the number of milliseconds to wait for the lock before * giving up, or -1 for no limit * @since 0.3.1 */ public void lock(Object pc, int level, int timeout, OpCallbacks call); /** * Ensure that the given instance is locked at the current lock level, as * set in the {@link FetchConfiguration} for the broker. * * @since 0.3.1 */ public void lock(Object pc, OpCallbacks call); /** * Ensure that the given instances are locked at the given lock level. * * @param objs the objects to lock * @param level the lock level to use * @param timeout the number of milliseconds to wait for the lock before * giving up, or -1 for no limit * @since 0.3.1 */ public void lockAll(Collection objs, int level, int timeout, OpCallbacks call); /** * Ensure that the given instances are locked at the current lock level, as * set in the {@link FetchConfiguration} for the broker. * * @since 0.3.1 */ public void lockAll(Collection objs, OpCallbacks call); /** * Cancel all pending data store statements. If statements are cancelled * while a flush is in progress, the transaction rollback only flag will * be set. * * @return true if any statements were cancelled, false otherwise * @since 0.3.1 */ public boolean cancelAll(); /** * Mark the given class as dirty within the current transaction. * * @since 0.3.0 */ public void dirtyType(Class cls); /** * Begin a logical operation. This indicates to the broker the * granularity of an operation which may require pre/post operation * side-effects, such as non-tx detach. * Will lock the broker until the {@link #endOperation} is called. * * @param syncTrans whether instances may be loaded/modified during * this operation requiring a re-check of global tx * @return whether this is the outermost operation on the stack */ public boolean beginOperation(boolean syncTrans); /** * End a logical operation. This indicates to the broker the * granularity of an operation which may require pre/post operation * side-effects, such as non-tx detach. Unlocks the given broker. * * @return whether this is the outermost operation on the stack */ public boolean endOperation(); /** * Whether the broker is closed. */ public boolean isClosed(); /** * Whether {@link #close} has been invoked, though the broker might * remain open until the current managed transaction completes. */ public boolean isCloseInvoked(); /** * Close the broker. */ public void close(); /** * Throw an exception if this broker has been closed. */ public void assertOpen(); /** * Throw an exception if there is no active transaction. */ public void assertActiveTransaction(); /** * Throw an exception if there is no transaction active and * nontransactional reading is not enabled. */ public void assertNontransactionalRead (); /** * Throw an exception if a write operation is not permitted (there is * no active transaction and nontransactional writing is not enabled). */ public void assertWriteOperation (); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/TDirtyState.java0000644000000000000000000000413512133327272026360 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a transient instance that is participating in the current * transaction, and has been modified. * * @author Abe White */ @SuppressWarnings("serial") class TDirtyState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.saveFields(false); context.setLoaded(true); context.setDirty(true); } PCState commit(StateManagerImpl context) { return TCLEAN; } PCState commitRetain(StateManagerImpl context) { return TCLEAN; } PCState rollback(StateManagerImpl context) { return TCLEAN; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return TCLEAN; } PCState persist(StateManagerImpl context) { return (context.getBroker().isActive()) ? PNEW : PNONTRANSNEW; } PCState delete(StateManagerImpl context) { return error("transient", context); } PCState nontransactional(StateManagerImpl context) { return error("dirty", context); } boolean isTransactional() { return true; } boolean isDirty() { return true; } public String toString() { return "Transient-Dirty"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PDeletedState.java0000644000000000000000000000474712133327272026640 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a persistent instance that has been deleted in the current * transaction. * * @author Abe White */ @SuppressWarnings("serial") class PDeletedState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.saveFields(false); } PCState flush(StateManagerImpl context) { return PDELETEDFLUSHED; } PCState commit(StateManagerImpl context) { return TRANSIENT; } PCState commitRetain(StateManagerImpl context) { return TRANSIENT; } PCState rollback(StateManagerImpl context) { return HOLLOW; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return PNONTRANS; } PCState nontransactional(StateManagerImpl context) { return error("deleted", context); } PCState persist(StateManagerImpl context) { return (context.getDirty().length() > 0) ? PDIRTY : PCLEAN; } PCState release(StateManagerImpl context) { return error("deleted", context); } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return error("deleted", context); } boolean isTransactional() { return true; } boolean isPersistent() { return true; } boolean isDeleted() { return true; } boolean isDirty() { return true; } public String toString() { return "Persistent-Deleted"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNonTransDirtyState.java0000644000000000000000000000370212133327272030036 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a persistent instance that has been dirtied outside of * transaction. This state is only reachable only if the * RetainNontransactional property is set. * * @author Steve Kim */ @SuppressWarnings("serial") class PNonTransDirtyState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.saveFields(false); } PCState delete(StateManagerImpl context) { context.preDelete(); return PNONTRANSDELETED; } PCState transactional(StateManagerImpl context) { return PDIRTY; } PCState release(StateManagerImpl context) { return error("dirty", context); } PCState evict(StateManagerImpl context) { return HOLLOW; } PCState afterNontransactionalRefresh() { return PNONTRANS; } boolean isPendingTransactional() { return true; } boolean isPersistent() { return true; } boolean isDirty() { return true; } public String toString() { return "Persistent-Notransactional-Dirty"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DataCacheRetrieveMode.java0000644000000000000000000000213612133327272030247 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * DataCache Retrieve Modes. */ public enum DataCacheRetrieveMode { /** * Retrieve objects from the DataCache if a DataCache is enabled. */ USE, /** * Ignore the DataCache and fetch data directly from the database. */ BYPASS, } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4HexSeq.java0000644000000000000000000000350112133327272026746 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.lib.util.UUIDGenerator; import org.apache.openjpa.meta.ClassMetaData; /** * Sequence for generating 32-character hex Type 4 UUID strings. * * @author Jeremy Bauer */ public class UUIDType4HexSeq implements Seq { private static final UUIDType4HexSeq _instance = new UUIDType4HexSeq(); private String _last = null; /** * Return the singleton instance. */ public static UUIDType4HexSeq getInstance() { return _instance; } /** * Hide constructor. */ private UUIDType4HexSeq() { } public void setType(int type) { } public synchronized Object next(StoreContext ctx, ClassMetaData meta) { _last = UUIDGenerator.nextHex(UUIDGenerator.TYPE4); return _last; } public synchronized Object current(StoreContext ctx, ClassMetaData meta) { return _last; } public void allocate(int additional, StoreContext ctx, ClassMetaData meta) { } public void close() { } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/EDirtyState.java0000644000000000000000000000452312133327272026342 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an embedded instance that is participating in the current * transaction, and has been modified. * * @author Abe White */ @SuppressWarnings("serial") class EDirtyState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.saveFields(false); } void beforeFlush(StateManagerImpl context, boolean logical, OpCallbacks call) { context.preFlush(logical, call); } PCState commit(StateManagerImpl context) { return TRANSIENT; } PCState commitRetain(StateManagerImpl context) { return ENONTRANS; } PCState rollback(StateManagerImpl context) { return TRANSIENT; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return ENONTRANS; } PCState delete(StateManagerImpl context) { context.preDelete(); return EDELETED; } PCState nontransactional(StateManagerImpl context) { return error("dirty", context); } PCState release(StateManagerImpl context) { return TRANSIENT; } PCState afterRefresh() { return ECLEAN; } PCState afterOptimisticRefresh() { return ENONTRANS; } boolean isTransactional() { return true; } public boolean isPersistent() { return true; } boolean isDirty() { return true; } public String toString() { return "Embedded-Dirty"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FillStrategy.java0000644000000000000000000002333012133327272026547 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import org.apache.openjpa.enhance.Reflection; import org.apache.openjpa.lib.util.Localizer; /** * A strategy to fill data into a {@link ResultShape}. *
    * Available strategy implementations can fill by invoking constructor, setting array elements, direct assignment, * invoking put(key,value)-style method on Map or factory-constructed instance. * * @author Pinaki Poddar * * @since 2.0.0 * */ public interface FillStrategy { static final Localizer _loc = Localizer.forPackage(FillStrategy.class); T fill(Object[] data, Class[] types, String[] aliases); /** * Fills an array of given type. * * @param must be an array type. */ public static class Array implements FillStrategy { private final Class cls; public Array(Class arrayCls) { if (arrayCls == null || !arrayCls.isArray()) throw new IllegalArgumentException(_loc.get("fill-bad-array", arrayCls).getMessage()); this.cls = arrayCls.getComponentType(); } public T fill(Object[] values, Class[] types, String[] aliases) { Object array = java.lang.reflect.Array.newInstance(cls, values.length); System.arraycopy(values, 0, array, 0, values.length); return (T)array; } } /** * Construct and populate an instance by invoking the put method * with each alias as key and element of the given array of values. * * The instance is a created by the no-argument constructor of the declaring class of the given method. */ public static class Map implements FillStrategy { private final Method putMethod; public Map(Method put) { if (put == null || put.getParameterTypes().length != 2) throw new IllegalArgumentException(_loc.get("fill-bad-put", put).getMessage()); putMethod = put; } public T fill(Object[] values, Class[] types, String[] aliases) { int i = 0; try { Object map = putMethod.getDeclaringClass().newInstance(); for (i = 0; i < values.length; i++) putMethod.invoke(map, aliases[i], values[i]); return (T)map; } catch (InvocationTargetException t) { throw new RuntimeException(_loc.get("fill-map-error", putMethod, aliases[i], values[i]).getMessage(), t.getTargetException()); } catch (Exception e) { throw new RuntimeException(_loc.get("fill-map-error", putMethod, aliases[i], values[i]).getMessage(), e); } } } /** * Construct and populate an instance by the given constructor and arguments. */ public static class NewInstance implements FillStrategy { private Constructor cons; private Class cls; public NewInstance(Constructor cons) { this.cons = cons; } public NewInstance(Class cls) { this.cls = cls; } /** * Finds a constructor of the given class with given argument types. */ Constructor findConstructor(Class cls, Class[] types) { try { return cls.getConstructor(types); } catch (Exception e) { Constructor[] constructors = cls.getConstructors(); for (Constructor cons : constructors) { Class[] paramTypes = cons.getParameterTypes(); boolean match = false; if (paramTypes.length == types.length) { for (int i = 0; i < paramTypes.length; i++) { match = paramTypes[i].isAssignableFrom(Filters.wrap(types[i])); if (!match) break; } } if (match) { return (Constructor)cons; } } } throw new RuntimeException(_loc.get("fill-ctor-none", cls, Arrays.toString(types)).getMessage()); } public T fill(Object[] values, Class[] types, String[] aliases) { if (cons == null) { cons = findConstructor(cls, types); } try { for (int i = 0; i < values.length; i++) { values[i] = Filters.convert(values[i], types[i]); } return cons.newInstance(values); } catch (Exception e) { throw new RuntimeException(_loc.get("fill-ctor-error", cons, Arrays.toString(values), Arrays.toString(types)).getMessage(), e); } } } /** * Create and populate a bean by invoking setter methods identified by alias name with each array * element value as argument. */ public static class Bean implements FillStrategy { private final Class cls; private Method[] setters; public Bean(Class cls) { this.cls = cls; } public T fill(Object[] values, Class[] types, String[] aliases) { int i = 0; try { if (setters == null) { setters = new Method[values.length]; } T bean = cls.newInstance(); for (i = 0; i < values.length; i++) { if (setters[i] == null) { setters[i] = Reflection.findSetter(cls, aliases[i], false); if (setters[i] == null) throw new RuntimeException(_loc.get("fill-bean-setter", cls, aliases[i]).getMessage()); } setters[i].invoke(bean, Filters.convert(values[i], types[i])); } return bean; } catch (InvocationTargetException t) { throw new RuntimeException(_loc.get("fill-bean-error", setters[i], values[i], types[i]).getMessage(), t.getTargetException()); } catch (Exception e) { throw new RuntimeException(_loc.get("fill-bean-error", setters[i], values[i], types[i]).getMessage(), e); } } } /** * Populate an instance by simply assigning the 0-th element of the input values. */ public static class Assign implements FillStrategy { public T fill(Object[] values, Class[] types, String[] aliases) { try { return (T)values[0]; } catch (Exception e) { throw new RuntimeException(_loc.get("fill-assign-error", Arrays.toString(values), Arrays.toString(types)).getMessage(), e); } } } /** * Populate an instance created by given factory using a given put(key,value) method. * If the first argument of the given put method is integer then fill the values * by index else fill the values with alias key. */ public static class Factory implements FillStrategy { final ObjectFactory factory; final Method putMethod; final boolean isArray; public Factory(ObjectFactory factory, Method put) { this.factory = factory; this.putMethod = put; if (put == null || put.getParameterTypes().length != 2) throw new IllegalArgumentException(_loc.get("fill-factory-bad-put", put).getMessage()); Class keyType = putMethod.getParameterTypes()[0]; this.isArray = keyType == int.class || keyType == Integer.class; } public T fill(Object[] values, Class[] types, String[] aliases) { int i = 0; Object key = null; T result = factory.newInstance(); try { for (i = 0; i < values.length; i++) { key = isArray ? i : aliases[i]; putMethod.invoke(result, key, Filters.convert(values[i], types[i])); } return result; } catch (InvocationTargetException t) { throw new RuntimeException(_loc.get("fill-factory-error", new Object[]{putMethod, key, values[i], types[i]}).getMessage(), t.getTargetException()); } catch (Exception e) { throw new RuntimeException(_loc.get("fill-factory-error", new Object[]{putMethod, key, values[i], types[i]}).getMessage(), e); } } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingSeq.java0000644000000000000000000000717212133327272026660 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.util.RuntimeExceptionTranslator; /////////////////////////////////////////////////////////////// // NOTE: when adding a public API method, be sure to add it to // JDO and JPA facades! /////////////////////////////////////////////////////////////// /** * Delegating sequence that can also perform exception translation for use * in facades. * * @author Abe White * @nojavadoc */ public class DelegatingSeq implements Seq { private final Seq _seq; private final DelegatingSeq _del; private final RuntimeExceptionTranslator _trans; /** * Constructor; supply delegate. */ public DelegatingSeq(Seq seq) { this(seq, null); } /** * Constructor; supply delegate and exception translator. */ public DelegatingSeq(Seq seq, RuntimeExceptionTranslator trans) { _seq = seq; if (seq instanceof DelegatingSeq) _del = (DelegatingSeq) seq; else _del = null; _trans = trans; } /** * Return the direct delegate. */ public Seq getDelegate() { return _seq; } /** * Return the native delegate. */ public Seq getInnermostDelegate() { return (_del == null) ? _seq : _del.getInnermostDelegate(); } public int hashCode() { return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingSeq) other = ((DelegatingSeq) other).getInnermostDelegate(); return getInnermostDelegate().equals(other); } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public void setType(int type) { try { _seq.setType(type); } catch (RuntimeException re) { throw translate(re); } } public Object next(StoreContext ctx, ClassMetaData meta) { try { return _seq.next(ctx, meta); } catch (RuntimeException re) { throw translate(re); } } public Object current(StoreContext ctx, ClassMetaData meta) { try { return _seq.current(ctx, meta); } catch (RuntimeException re) { throw translate(re); } } public void allocate(int additional, StoreContext ctx, ClassMetaData meta) { try { _seq.allocate(additional, ctx, meta); } catch (RuntimeException re) { throw translate(re); } } public void close() { try { _seq.close(); } catch (RuntimeException re) { throw translate(re); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java0000644000000000000000000007531312133327272030143 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.IOException; import java.io.ObjectOutput; import java.io.Serializable; import java.util.BitSet; import java.util.Collection; import java.util.Map; import org.apache.openjpa.conf.Compatibility; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.lib.util.Localizer; import java.util.concurrent.locks.ReentrantLock; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FetchGroup; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.Proxy; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.ImplHelper; /** * Internal state manager for detached instances. Does not fully * implement {@link OpenJPAStateManager} contract to allow for serialization. * * @author Steve Kim * @nojavadoc */ public class DetachedStateManager extends AttachStrategy implements OpenJPAStateManager, Serializable { private static final long serialVersionUID = 4112223665584731100L; private static final Localizer _loc = Localizer.forPackage (DetachedStateManager.class); private final PersistenceCapable _pc; private final boolean _embedded; private final boolean _access; private final BitSet _loaded; private final BitSet _dirty; private final Object _oid; private final Object _version; private final ReentrantLock _lock; private final boolean _useDSFForUnproxy; // old releases will default to FALSE, which is the old behavior /** * Constructor. * * @param pc the managed instance * @param sm the instance's state manager * @param load the set of detached field indexes * @param access whether to allow access to unloaded fields * @param multithreaded whether the instance will be used concurrently * by multiple threads */ public DetachedStateManager(PersistenceCapable pc, OpenJPAStateManager sm, BitSet load, boolean access, boolean multithreaded) { _pc = pc; _embedded = sm.isEmbedded(); _loaded = load; _access = access; if (!sm.isFlushed()) _dirty = (BitSet) sm.getDirty().clone(); else _dirty = new BitSet(_loaded.length()); _oid = sm.fetchObjectId(); _version = sm.getVersion(); if (multithreaded) _lock = new ReentrantLock(); else _lock = null; if (sm.getContext() != null && sm.getContext().getConfiguration() != null) { Compatibility compat = sm.getContext().getConfiguration().getCompatibilityInstance(); if (compat != null && !compat.getIgnoreDetachedStateFieldForProxySerialization()) _useDSFForUnproxy = true; // new 2.0 behavior else _useDSFForUnproxy = false; } else _useDSFForUnproxy = false; } ///////////////////////////////// // AttachStrategy implementation ///////////////////////////////// public Object attach(AttachManager manager, Object toAttach, ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit) { BrokerImpl broker = manager.getBroker(); StateManagerImpl sm; if (_embedded) { if (_dirty.length () > 0) owner.dirty(ownerMeta.getFieldMetaData().getIndex()); sm = (StateManagerImpl) broker.embed(_pc, _oid, owner, ownerMeta); ImplHelper.toPersistenceCapable(toAttach, broker.getConfiguration()) .pcReplaceStateManager(this); } else { PCState state = (_dirty.length() > 0) ? PCState.PDIRTY : PCState.PCLEAN; sm = (StateManagerImpl) broker.copy(this, state); } PersistenceCapable pc = sm.getPersistenceCapable(); manager.setAttachedCopy(toAttach, pc); manager.fireBeforeAttach(toAttach, meta); // pre-load for efficiency: current field values for restore, dependent // for delete FieldMetaData[] fields = sm.getMetaData().getFields(); int restore = broker.getRestoreState(); boolean postLoadOnMerge = broker.getPostLoadOnMerge(); if (_dirty.length() > 0 || postLoadOnMerge) { BitSet load = new BitSet(fields.length); if (postLoadOnMerge && broker.getLifecycleEventManager().hasLoadListeners(pc, meta)) { // load all fields // this will automatically lead to invoking the PostLoad lifecycle event // when the last field got set // @see StateManagerImpl#postLoad(String, FetchConfiguration) load.set(0, fields.length); } else { for (int i = 0; i < fields.length; i++) { if (!_dirty.get(i)) continue; switch (fields[i].getDeclaredTypeCode()) { case JavaTypes.ARRAY: case JavaTypes.COLLECTION: if (restore == RestoreState.RESTORE_ALL || fields[i].getElement().getCascadeDelete() == ValueMetaData.CASCADE_AUTO) load.set(i); break; case JavaTypes.MAP: if (restore == RestoreState.RESTORE_ALL || fields[i].getElement().getCascadeDelete() == ValueMetaData.CASCADE_AUTO || fields[i].getKey().getCascadeDelete() == ValueMetaData.CASCADE_AUTO) load.set(i); break; default: if (restore != RestoreState.RESTORE_NONE || fields[i].getCascadeDelete() == ValueMetaData.CASCADE_AUTO) load.set(i); } } } if (!postLoadOnMerge) { // prevent PostLoad callbacks even for the load operation sm.setPostLoadCallback(false); } FetchConfiguration fc = broker.getFetchConfiguration(); sm.loadFields(load, fc, fc.getWriteLockLevel(), null); } Object origVersion = sm.getVersion(); sm.setVersion(_version); BitSet loaded = sm.getLoaded(); int set = StateManager.SET_ATTACH; sm.setPostLoadCallback(false); for (int i = 0; i < fields.length; i++) { if (!_loaded.get(i)) continue; // don't reload already loaded non-mutable objects if (!_dirty.get(i) && loaded.get(i) && ignoreLoaded(fields[i])) continue; provideField(i); switch (fields[i].getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: if (_dirty.get(i)) sm.settingBooleanField(pc, i, (loaded.get(i)) && sm.fetchBooleanField(i), longval == 1, set); else sm.storeBooleanField(i, longval == 1); break; case JavaTypes.BYTE: if (_dirty.get(i)) sm.settingByteField(pc, i, (!loaded.get(i)) ? (byte) 0 : sm.fetchByteField(i), (byte) longval, set); else sm.storeByteField(i, (byte) longval); break; case JavaTypes.CHAR: if (_dirty.get(i)) sm.settingCharField(pc, i, (!loaded.get(i)) ? (char) 0 : sm.fetchCharField(i), (char) longval, set); else sm.storeCharField(i, (char) longval); break; case JavaTypes.INT: if (_dirty.get(i)) sm.settingIntField(pc, i, (!loaded.get(i)) ? 0 : sm.fetchIntField(i), (int) longval, set); else sm.storeIntField(i, (int) longval); break; case JavaTypes.LONG: if (_dirty.get(i)) sm.settingLongField(pc, i, (!loaded.get(i)) ? 0L : sm.fetchLongField(i), longval, set); else sm.storeLongField(i, longval); break; case JavaTypes.SHORT: if (_dirty.get(i)) sm.settingShortField(pc, i, (!loaded.get(i)) ? (short) 0 : sm.fetchShortField(i), (short) longval, set); else sm.storeShortField(i, (short) longval); break; case JavaTypes.FLOAT: if (_dirty.get(i)) sm.settingFloatField(pc, i, (!loaded.get(i)) ? 0F : sm.fetchFloatField(i), (float) dblval, set); else sm.storeFloatField(i, (float) dblval); break; case JavaTypes.DOUBLE: if (_dirty.get(i)) sm.settingDoubleField(pc, i, (!loaded.get(i)) ? 0D : sm.fetchDoubleField(i), dblval, set); else sm.storeDoubleField(i, dblval); break; case JavaTypes.STRING: if (_dirty.get(i)) sm.settingStringField(pc, i, (!loaded.get(i)) ? null : sm.fetchStringField(i), (String) objval, set); else sm.storeStringField(i, (String) objval); objval = null; break; case JavaTypes.PC: case JavaTypes.PC_UNTYPED: if (fields[i].getCascadeAttach() == ValueMetaData .CASCADE_NONE) { // Use the attached copy of the object, if available PersistenceCapable cpy = manager.getAttachedCopy(objval); if (cpy != null) { objval = cpy; } else { objval = getReference(manager, objval, sm, fields[i]); } } else { PersistenceCapable toPC = null; if (objval != null && fields[i].isEmbeddedPC()) toPC = ImplHelper.toPersistenceCapable(objval, broker.getConfiguration()); objval = manager.attach(objval, toPC, sm, fields[i], false); } if (_dirty.get(i)) sm.settingObjectField(pc, i, (!loaded.get(i)) ? null : sm.fetchObjectField(i), objval, set); else sm.storeObjectField(i, objval); objval = null; break; case JavaTypes.COLLECTION: Collection coll = (Collection) objval; objval = null; if (coll != null) coll = attachCollection(manager, coll, sm, fields[i]); if (_dirty.get(i)) sm.settingObjectField(pc, i, (!loaded.get(i)) ? null : sm.fetchObjectField(i), coll, set); else sm.storeObjectField(i, coll); break; case JavaTypes.MAP: Map map = (Map) objval; objval = null; if (map != null) map = attachMap(manager, map, sm, fields[i]); if (_dirty.get(i)) sm.settingObjectField(pc, i, (!loaded.get(i)) ? null : sm.fetchObjectField(i), map, set); else sm.storeObjectField(i, map); break; default: if (_dirty.get(i)) sm.settingObjectField(pc, i, (!loaded.get(i)) ? null : sm.fetchObjectField(i), objval, set); else sm.storeObjectField(i, objval); objval = null; } } sm.setPostLoadCallback(true); pc.pcReplaceStateManager(sm); // if we were clean at least make sure a version check is done to // prevent using old state if (!sm.isVersionCheckRequired() && broker.isActive() && _version != origVersion && (origVersion == null || broker.getStoreManager().compareVersion(sm, _version, origVersion) != StoreManager.VERSION_SAME)) { broker.transactional(sm.getManagedInstance(), false, manager.getBehavior()); } return sm.getManagedInstance(); } protected Object getDetachedObjectId(AttachManager manager, Object toAttach) { return _oid; } void provideField(int field) { _pc.pcProvideField(field); } protected void provideField(Object toAttach, StateManagerImpl sm, int field) { provideField(field); } /** * Ignore if the field is not dirty but loaded */ protected static boolean ignoreLoaded(FieldMetaData fmd) { switch (fmd.getTypeCode()) { case JavaTypes.BOOLEAN: case JavaTypes.BOOLEAN_OBJ: case JavaTypes.BYTE: case JavaTypes.BYTE_OBJ: case JavaTypes.INT: case JavaTypes.INT_OBJ: case JavaTypes.LONG: case JavaTypes.LONG_OBJ: case JavaTypes.SHORT: case JavaTypes.SHORT_OBJ: case JavaTypes.DOUBLE: case JavaTypes.DOUBLE_OBJ: case JavaTypes.FLOAT: case JavaTypes.FLOAT_OBJ: case JavaTypes.CHAR: case JavaTypes.CHAR_OBJ: case JavaTypes.STRING: return true; } return false; } /////////////////////////////// // StateManager implementation /////////////////////////////// public Object getGenericContext() { return null; } public Object getPCPrimaryKey(Object oid, int field) { throw new UnsupportedOperationException(); } public StateManager replaceStateManager(StateManager sm) { return sm; } public Object getVersion() { return _version; } public void setVersion(Object version) { throw new UnsupportedException(); } public boolean isDirty() { return _dirty.length() != 0; } public boolean isTransactional() { return false; } public boolean isPersistent() { return false; } public boolean isNew() { return false; } public boolean isDeleted() { return false; } public boolean isDetached() { return true; } public boolean isVersionUpdateRequired() { return false; } public boolean isVersionCheckRequired() { return false; } public void dirty(String field) { // should we store ClassMetaData? throw new UnsupportedException(); } public Object fetchObjectId() { return _oid; } public void accessingField(int idx) { if (!_access && !_loaded.get(idx)) // do not access the pc fields by implictly invoking _pc.toString() // may cause infinite loop if again tries to access unloaded field throw new IllegalStateException(_loc.get("unloaded-detached", Exceptions.toString(_pc)).getMessage()); } public boolean serializing() { return false; } public boolean writeDetached(ObjectOutput out) throws IOException { out.writeObject(_pc.pcGetDetachedState()); out.writeObject(this); return false; } public void proxyDetachedDeserialized(int idx) { lock(); try { _pc.pcProvideField(idx); if (objval instanceof Proxy) ((Proxy) objval).setOwner(this, idx); objval = null; } finally { unlock(); } } public void settingBooleanField(PersistenceCapable pc, int idx, boolean cur, boolean next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); longval = next ? 1 : 0; pc.pcReplaceField(idx); } finally { unlock(); } } public void settingCharField(PersistenceCapable pc, int idx, char cur, char next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); longval = next; pc.pcReplaceField(idx); } finally { unlock(); } } public void settingByteField(PersistenceCapable pc, int idx, byte cur, byte next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); longval = next; pc.pcReplaceField(idx); } finally { unlock(); } } public void settingShortField(PersistenceCapable pc, int idx, short cur, short next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); longval = next; pc.pcReplaceField(idx); } finally { unlock(); } } public void settingIntField(PersistenceCapable pc, int idx, int cur, int next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); longval = next; pc.pcReplaceField(idx); } finally { unlock(); } } public void settingLongField(PersistenceCapable pc, int idx, long cur, long next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); longval = next; pc.pcReplaceField(idx); } finally { unlock(); } } public void settingFloatField(PersistenceCapable pc, int idx, float cur, float next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); dblval = next; pc.pcReplaceField(idx); } finally { unlock(); } } public void settingDoubleField(PersistenceCapable pc, int idx, double cur, double next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); dblval = next; pc.pcReplaceField(idx); } finally { unlock(); } } public void settingStringField(PersistenceCapable pc, int idx, String cur, String next, int set) { accessingField(idx); if (cur == next || (cur != null && cur.equals(next)) || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); objval = next; pc.pcReplaceField(idx); } finally { unlock(); objval = null; } } public void settingObjectField(PersistenceCapable pc, int idx, Object cur, Object next, int set) { accessingField(idx); if (cur == next || !_loaded.get(idx)) return; lock(); try { _dirty.set(idx); objval = next; pc.pcReplaceField(idx); } finally { unlock(); objval = null; } } public void providedBooleanField(PersistenceCapable pc, int idx, boolean cur) { longval = cur ? 1 : 0; } public void providedCharField(PersistenceCapable pc, int idx, char cur) { longval = cur; } public void providedByteField(PersistenceCapable pc, int idx, byte cur) { longval = cur; } public void providedShortField(PersistenceCapable pc, int idx, short cur) { longval = cur; } public void providedIntField(PersistenceCapable pc, int idx, int cur) { longval = cur; } public void providedLongField(PersistenceCapable pc, int idx, long cur) { longval = cur; } public void providedFloatField(PersistenceCapable pc, int idx, float cur) { dblval = cur; } public void providedDoubleField(PersistenceCapable pc, int idx, double cur) { dblval = cur; } public void providedStringField(PersistenceCapable pc, int idx, String cur) { objval = cur; } public void providedObjectField(PersistenceCapable pc, int idx, Object cur) { objval = cur; } public boolean replaceBooleanField(PersistenceCapable pc, int idx) { return longval == 1; } public char replaceCharField(PersistenceCapable pc, int idx) { return (char) longval; } public byte replaceByteField(PersistenceCapable pc, int idx) { return (byte) longval; } public short replaceShortField(PersistenceCapable pc, int idx) { return (short) longval; } public int replaceIntField(PersistenceCapable pc, int idx) { return (int) longval; } public long replaceLongField(PersistenceCapable pc, int idx) { return longval; } public float replaceFloatField(PersistenceCapable pc, int idx) { return (float) dblval; } public double replaceDoubleField(PersistenceCapable pc, int idx) { return dblval; } public String replaceStringField(PersistenceCapable pc, int idx) { String str = (String) objval; objval = null; return str; } public Object replaceObjectField(PersistenceCapable pc, int idx) { Object ret = objval; objval = null; return ret; } ////////////////////////////////////// // OpenJPAStateManager implementation ////////////////////////////////////// public void initialize(Class forType, PCState state) { throw new UnsupportedOperationException(); } public void load(FetchConfiguration fetch) { throw new UnsupportedOperationException(); } public Object getManagedInstance() { return _pc; } public PersistenceCapable getPersistenceCapable() { return _pc; } public ClassMetaData getMetaData() { throw new UnsupportedOperationException(); } public OpenJPAStateManager getOwner() { throw new UnsupportedOperationException(); } public int getOwnerIndex() { throw new UnsupportedOperationException(); } public boolean isEmbedded() { return _embedded; } public boolean isFlushed() { throw new UnsupportedOperationException(); } public boolean isFlushedDirty() { throw new UnsupportedOperationException(); } public boolean isProvisional() { throw new UnsupportedOperationException(); } public BitSet getLoaded() { return _loaded; } public BitSet getDirty() { return _dirty; } /** * Should DetachedStateField be used by Proxies to determine when to remove * $proxy wrappers during serialization. * @since 2.0.0 */ public boolean getUseDSFForUnproxy() { return _useDSFForUnproxy; } public BitSet getFlushed() { throw new UnsupportedOperationException(); } public BitSet getUnloaded(FetchConfiguration fetch) { throw new UnsupportedOperationException(); } public Object newProxy(int field) { throw new UnsupportedOperationException(); } public Object newFieldProxy(int field) { throw new UnsupportedOperationException(); } public boolean isDefaultValue(int field) { throw new UnsupportedOperationException(); } public StoreContext getContext() { return null; } public PCState getPCState() { throw new UnsupportedOperationException(); } public Object getObjectId() { return _oid; } public void setObjectId(Object oid) { throw new UnsupportedOperationException(); } public boolean assignObjectId(boolean flush) { return true; } public Object getId() { return getObjectId(); } public Object getLock() { throw new UnsupportedOperationException(); } public void setLock(Object lock) { throw new UnsupportedOperationException(); } public void setNextVersion(Object version) { throw new UnsupportedOperationException(); } public Object getImplData() { throw new UnsupportedOperationException(); } public Object setImplData(Object data, boolean cacheable) { throw new UnsupportedOperationException(); } public boolean isImplDataCacheable() { return false; } public Object getImplData(int field) { throw new UnsupportedOperationException(); } public Object setImplData(int field, Object data) { throw new UnsupportedOperationException(); } public boolean isImplDataCacheable(int field) { throw new UnsupportedOperationException(); } public Object getIntermediate(int field) { throw new UnsupportedOperationException(); } public void setIntermediate(int field, Object data) { throw new UnsupportedOperationException(); } public void removed(int field, Object removed, boolean key) { dirty(field); } public boolean beforeRefresh(boolean all) { throw new UnsupportedOperationException(); } public void dirty(int field) { lock(); try { _dirty.set(field); } finally { unlock(); } } public void storeBoolean(int field, boolean extVal) { throw new UnsupportedOperationException(); } public void storeByte(int field, byte extVal) { throw new UnsupportedOperationException(); } public void storeChar(int field, char extVal) { throw new UnsupportedOperationException(); } public void storeInt(int field, int extVal) { throw new UnsupportedOperationException(); } public void storeShort(int field, short extVal) { throw new UnsupportedOperationException(); } public void storeLong(int field, long extVal) { throw new UnsupportedOperationException(); } public void storeFloat(int field, float extVal) { throw new UnsupportedOperationException(); } public void storeDouble(int field, double extVal) { throw new UnsupportedOperationException(); } public void storeString(int field, String extVal) { throw new UnsupportedOperationException(); } public void storeObject(int field, Object extVal) { throw new UnsupportedOperationException(); } public void store(int field, Object extVal) { throw new UnsupportedOperationException(); } public void storeField(int field, Object value) { throw new UnsupportedOperationException(); } public boolean fetchBoolean(int field) { throw new UnsupportedOperationException(); } public byte fetchByte(int field) { throw new UnsupportedOperationException(); } public char fetchChar(int field) { throw new UnsupportedOperationException(); } public short fetchShort(int field) { throw new UnsupportedOperationException(); } public int fetchInt(int field) { throw new UnsupportedOperationException(); } public long fetchLong(int field) { throw new UnsupportedOperationException(); } public float fetchFloat(int field) { throw new UnsupportedOperationException(); } public double fetchDouble(int field) { throw new UnsupportedOperationException(); } public String fetchString(int field) { throw new UnsupportedOperationException(); } public Object fetchObject(int field) { throw new UnsupportedOperationException(); } public Object fetch(int field) { throw new UnsupportedOperationException(); } public Object fetchField(int field, boolean transitions) { throw new UnsupportedOperationException(); } public Object fetchInitialField(int field) { throw new UnsupportedOperationException(); } public void setRemote(int field, Object value) { throw new UnsupportedOperationException(); } public void lock() { if (_lock != null) _lock.lock(); } public void unlock() { if (_lock != null) _lock.unlock(); } @Override public boolean isDelayed(int field) { return false; } @Override public void setDelayed(int field, boolean delay) { throw new UnsupportedOperationException(); } @Override public void loadDelayedField(int field) { throw new UnsupportedOperationException(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/TLoadedState.java0000644000000000000000000000266212133327272026460 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a temporarily managed transient instance whose fields * are loaded for the purpose of field inspection such * as for cascades. This state should be released as soon as inspection * is complete. * * @author Steve Kim */ @SuppressWarnings("serial") class TLoadedState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.setLoaded(true); } PCState release(StateManagerImpl context) { return TRANSIENT; } public String toString() { return "Transient-Loaded"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCState.java0000644000000000000000000003527012133327272025447 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.ObjectStreamException; import java.io.Serializable; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.InvalidStateException; /** * Base class for all lifecycle states. Each instance is managed by * a {@link OpenJPAStateManager}, which in turn keeps a reference to its current * state. * The state governs the behavior of the instance during all lifecycle * events. The class itself is stateless, and is provided its context * on each method call. This base class provides no-op implementations * of all methods and maintains static singelton shared references to each * possible state. * * @author Abe White */ @SuppressWarnings("serial") public class PCState implements Serializable { /** * Persistent-New */ public static final PCState PNEW = new PNewState(); /** * Persistent-Clean */ public static final PCState PCLEAN = new PCleanState(); /** * Persistent-Dirty */ public static final PCState PDIRTY = new PDirtyState(); /** * Persistent-Deleted */ public static final PCState PDELETED = new PDeletedState(); /** * Persistent-New-Deleted */ public static final PCState PNEWDELETED = new PNewDeletedState(); /** * Persistent-New-Provisional */ public static final PCState PNEWPROVISIONAL = new PNewProvisionalState(); /** * Persistent-Nontransactinoal */ public static final PCState PNONTRANS = new PNonTransState(); /** * Persistent-Dirty-Nontransactinoal */ public static final PCState PNONTRANSDIRTY = new PNonTransDirtyState(); /** * Persistent-New-Nontransactional */ public static final PCState PNONTRANSNEW = new PNonTransNewState(); /** * Persistent-Deleted-Nontransactional */ public static final PCState PNONTRANSDELETED = new PNonTransDeletedState(); /** * Hollow; exists in data store */ public static final PCState HOLLOW = new HollowState(); /** * Transient; unmanaged instance */ public static final PCState TRANSIENT = new TransientState(); /** * Transient-Clean */ public static final PCState TCLEAN = new TCleanState(); /** * Transient-Dirty */ public static final PCState TDIRTY = new TDirtyState(); /** * Transient-Loaded */ public static final PCState TLOADED = new TLoadedState(); /** * Embedded-Copy */ public static final PCState ECOPY = new ECopyState(); /** * Embedded-Clean */ public static final PCState ECLEAN = new ECleanState(); /** * Embedded-Dirty */ public static final PCState EDIRTY = new EDirtyState(); /** * Embedded-Deleted */ public static final PCState EDELETED = new EDeletedState(); /** * Embedded-Nontransactional */ public static final PCState ENONTRANS = new ENonTransState(); /** * Persistent-New-Flushed-Deleted */ public static final PCState PNEWFLUSHEDDELETED = new PNewFlushedDeletedState(); /** * Persistent-New-Flushed-Deleted-Flushed */ public static final PCState PNEWFLUSHEDDELETEDFLUSHED = new PNewFlushedDeletedFlushedState(); /** * Persistent-Deleted-Flushed */ public static final PCState PDELETEDFLUSHED = new PDeletedFlushedState(); private static Localizer _loc = Localizer.forPackage(PCState.class); /** * Called when this state is first assigned to the given state manager. */ void initialize(StateManagerImpl context, PCState previousState) { } /** * Called before the state is flushed. */ void beforeFlush(StateManagerImpl context, boolean logical, OpCallbacks call) { } /** * Perform any actions necessary and return the proper lifecycle * state on fush. Returns the this pointer by default. */ PCState flush(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on transaction commit. Returns the this pointer by default. */ PCState commit(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on transaction commit with the retainValues flag set. * Returns the this pointer by default. */ PCState commitRetain(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on transaction rollback. * Returns the this pointer by default. */ PCState rollback(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on transaction rollback with the restoreValues flag set. * Returns the this pointer by default. */ PCState rollbackRestore(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on a call to {@link Broker#persist} with the given instance. * Returns the this pointer by default. Note: this method * is not called for embedded states, and is only called when an * existing managed instance is the target of a persist call. */ PCState persist(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on a call to {@link Broker#delete} with the given instance. * Returns the this pointer by default. */ PCState delete(StateManagerImpl context) { return this; } /** * Return the state to transition to after making no longer provisional. * Returns the this pointer by default. */ PCState nonprovisional(StateManagerImpl context, boolean logical, OpCallbacks call) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on a call to {@link StoreContext#nontransactional} with the given * instance. Returns the this pointer by default. */ PCState nontransactional(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on a call to {@link StoreContext#nontransactional} with the given * instance. Returns the this pointer by default. */ PCState transactional(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on a call to {@link Broker#makeTransient} with the given instance. * Returns the this pointer by default. */ PCState release(StateManagerImpl context) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * on a call to {@link Broker#evict} with the given instance. * Returns the this pointer by default. */ PCState evict(StateManagerImpl context) { return this; } /** * Return the state to transition to after refresh. The context is * not given because no actions should be taken. */ PCState afterRefresh() { return this; } /** * Return the state to transition to after refresh. The context is * not given because no actions should be taken. */ PCState afterOptimisticRefresh() { return this; } /** * Return the state to transition to after refresh. The context is * not given because no actions should be taken. */ PCState afterNontransactionalRefresh() { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * prior to the state of the given instance being read within * an active transaction. The given field number can be -1 if it is * a general object read. Returns the this pointer by default. */ PCState beforeRead(StateManagerImpl context, int field) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * prior to the state of the given instance being read outside of * an active transaction. The given field number can be -1 if it is * a general object read. Returns the this pointer by default. */ PCState beforeNontransactionalRead(StateManagerImpl context, int field) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * prior to the state of the given instance being read in an optimistic * transaction. The given field number can be -1 if it is * a general object read. Returns the this pointer by default. */ PCState beforeOptimisticRead(StateManagerImpl context, int field) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * prior to the state of the given instance being written within * an active transaction. The mutate parameter tells if it is a * direct mutation on an SCO field. * Returns the this pointer by default. */ PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * prior to the state of the given instance being written within * an optimistic transaction. The mutate parameter tells if it is a * direct mutation on an SCO field. * Returns the this pointer by default. */ PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return this; } /** * Perform any actions necesssary and return the proper lifecycle state * prior to the state of the given instance being written outside of * an active transaction. The mutate parameter tells if it is a * direct mutation on an SCO field. * Returns the this pointer by default. */ PCState beforeNontransactionalWrite(StateManagerImpl context, int field, boolean mutate) { return this; } /** * Return whether this is a transactional state. * Returns false by default. */ boolean isTransactional() { return false; } /** * Return whether this is a persistent state. * Returns false by default. */ boolean isPersistent() { return false; } /** * Return whether this is a new state. * Returns false by default. */ boolean isNew() { return false; } /** * Return whether this is a deleted state. * Returns false by default. */ boolean isDeleted() { return false; } /** * Return whether this is a dirty state. * Returns false by default. */ boolean isDirty() { return false; } /** * Return whether this is a state that will become transactional * upon the begin of the next transaction. * Returns false by default. */ boolean isPendingTransactional() { return false; } /** * Return whether this is a state that will become transient * at the end of the next transaction. * Returns false by default. */ boolean isProvisional() { return false; } /** * Whether this state requires a version check when being flushed, * assuming the system is configured for version checks. */ boolean isVersionCheckRequired(StateManagerImpl context) { return false; } /** * Throw an error with a localized message identified by the given key. */ PCState error(String key, StateManagerImpl context) { throw new InvalidStateException(_loc.get(key)). setFailedObject(context.getManagedInstance()); } protected Object readResolve() throws ObjectStreamException { if (this instanceof PNewState) return PNEW; if (this instanceof PCleanState) return PCLEAN; if (this instanceof PDirtyState) return PDIRTY; if (this instanceof PDeletedState) return PDELETED; if (this instanceof PNewDeletedState) return PNEWDELETED; if (this instanceof PNewProvisionalState) return PNEWPROVISIONAL; if (this instanceof PNonTransState) return PNONTRANS; if (this instanceof PNonTransDirtyState) return PNONTRANSDIRTY; if (this instanceof PNonTransNewState) return PNONTRANSNEW; if (this instanceof PNonTransDeletedState) return PNONTRANSDELETED; if (this instanceof HollowState) return HOLLOW; if (this instanceof TransientState) return TRANSIENT; if (this instanceof TCleanState) return TCLEAN; if (this instanceof TDirtyState) return TDIRTY; if (this instanceof ECopyState) return ECOPY; if (this instanceof ECleanState) return ECLEAN; if (this instanceof EDirtyState) return EDIRTY; if (this instanceof EDeletedState) return EDELETED; if (this instanceof ENonTransState) return ENONTRANS; if (this instanceof PNewFlushedDeletedState) return PNEWFLUSHEDDELETED; if (this instanceof PNewFlushedDeletedFlushedState) return PNEWFLUSHEDDELETEDFLUSHED; if (this instanceof PDeletedFlushedState) return PDELETEDFLUSHED; throw new InternalException (); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java0000644000000000000000000011127112133327272025550 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.security.AccessController; import java.security.PrivilegedActionException; import java.sql.Time; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; import org.apache.openjpa.enhance.Reflection; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.UserException; import serp.util.Strings; /** * Helper methods for dealing with query filters. * * @author Abe White * @nojavadoc */ public class Filters { private static final BigDecimal ZERO_BIGDECIMAL = new BigDecimal(0D); private static final BigInteger ZERO_BIGINTEGER = new BigInteger("0"); private static final int OP_ADD = 0; private static final int OP_SUBTRACT = 1; private static final int OP_MULTIPLY = 2; private static final int OP_DIVIDE = 3; private static final int OP_MOD = 4; private static final Localizer _loc = Localizer.forPackage(Filters.class); /** * Return the correct wrapper type for the given class. */ public static Class wrap(Class c) { if (!c.isPrimitive()) return c; if (c == int.class) return Integer.class; if (c == float.class) return Float.class; if (c == double.class) return Double.class; if (c == long.class) return Long.class; if (c == boolean.class) return Boolean.class; if (c == short.class) return Short.class; if (c == byte.class) return Byte.class; if (c == char.class) return Character.class; return c; } /** * Return the correct primitive type for the given class, if it is a * wrapper. */ public static Class unwrap(Class c) { if (c.isPrimitive() || c == String.class) return c; if (c == Integer.class) return int.class; if (c == Float.class) return float.class; if (c == Double.class) return double.class; if (c == Long.class) return long.class; if (c == Boolean.class) return boolean.class; if (c == Short.class) return short.class; if (c == Byte.class) return byte.class; if (c == Character.class) return char.class; return c; } /** * Given two types, return type they should both be converted * to before performing any operations between them. */ public static Class promote(Class c1, Class c2) { if (c1 == c2) return unwrap(c1); Class w1 = wrap(c1); Class w2 = wrap(c2); if (w1 == w2) return unwrap(c1); // not numbers? boolean w1Number = Number.class.isAssignableFrom(w1); boolean w2Number = Number.class.isAssignableFrom(w2); if (!w1Number || !w2Number) { // the only non-numeric promotion we do is string to char, // or from char/string to number if (!w1Number) { if (w2Number && (w1 == Character.class || w1 == String.class)) return (w2 == Byte.class || w2 == Short.class) ? Integer.class : unwrap(c2); if (!w2Number && w1 == Character.class && w2 == String.class) return String.class; if (w2Number) return unwrap(c2); } if (!w2Number) { if (w1Number && (w2 == Character.class || w2 == String.class)) return (w1 == Byte.class || w1 == Short.class) ? Integer.class : unwrap(c1); if (!w1Number && w2 == Character.class && w1 == String.class) return String.class; if (w1Number) return unwrap(c1); } // if neither are numbers, use least-derived of the two. if neither // is assignable from the other but one is a standard type, assume // the other can be converted to that standard type if (!w1Number && !w2Number) { if (w1 == Object.class) return unwrap(c2); if (w2 == Object.class) return unwrap(c1); if (w1.isAssignableFrom(w2)) return unwrap(c1); if (w2.isAssignableFrom(w1)) return unwrap(c2); if (isNonstandardType(w1)) return (isNonstandardType(w2)) ? Object.class : unwrap(c2); if (isNonstandardType(w2)) return (isNonstandardType(w1)) ? Object.class : unwrap(c1); } return Object.class; } if (w1 == BigDecimal.class || w2 == BigDecimal.class) return BigDecimal.class; if (w1 == BigInteger.class) { if (w2 == Float.class || w2 == Double.class) return BigDecimal.class; return BigInteger.class; } if (w2 == BigInteger.class) { if (w1 == Float.class || w1 == Double.class) return BigDecimal.class; return BigInteger.class; } if (w1 == Double.class || w2 == Double.class) return double.class; if (w1 == Float.class || w2 == Float.class) return float.class; if (w1 == Long.class || w2 == Long.class) return long.class; return int.class; } /** * Return whether the given type is not a standard persistent type. */ private static boolean isNonstandardType(Class c) { switch (JavaTypes.getTypeCode(c)) { case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.PC: case JavaTypes.PC_UNTYPED: case JavaTypes.OID: case JavaTypes.OBJECT: return true; default: return false; } } /** * Return whether an instance of the first class can be converted to * an instance of the second. */ public static boolean canConvert(Class c1, Class c2, boolean strict) { if (c1 == c2) return true; c1 = wrap(c1); c2 = wrap(c2); if (c2.isAssignableFrom(c1)) return true; boolean c1Number = Number.class.isAssignableFrom(c1); boolean c2Number = Number.class.isAssignableFrom(c2); if (c1Number && c2Number) return true; if ((c1Number && (c2 == Character.class || (!strict && c2 == String.class))) || (c2Number && (c1 == Character.class || (!strict && c1 == String.class)))) return true; if (c1 == String.class && c2 == Character.class) return true; if (c2 == String.class) return !strict; if (c1 == String.class && isTemporalType(c2)) return true; if ((c1 == java.util.Date.class ||c1 == java.sql.Time.class) && c2 == java.sql.Timestamp.class) return false; if ((c1 == java.util.Date.class ||c1 == java.sql.Timestamp.class) && c2 == java.sql.Time.class) return false; if (isTemporalType(c1) && isTemporalType(c2)) return true; return false; } /** * Convert the given value to match the given (presumably a setter) method argument type. * * @param o given value * @param method a presumably setter method * * @return the same value if the method does not have one and only one input argument. */ public static Object convertToMatchMethodArgument(Object o, Method method) { if (method == null || method.getParameterTypes().length != 1) { return o; } return convert(o, method.getParameterTypes()[0], true); } public static Object convert(Object o, Class type) { return convert(o, type, false); } /** * Convert the given value to the given type. */ public static Object convert(Object o, Class type, boolean strictNumericConversion) { if (o == null) return null; if (o.getClass() == type) return o; type = wrap(type); if (type.isAssignableFrom(o.getClass())) return o; // the non-numeric conversions we do are to string, or from // string/char to number, or calendar/date // String to Boolean // String to Integer boolean num = o instanceof Number; if (!num) { if (type == String.class) return o.toString(); else if (type == Boolean.class && o instanceof String) return Boolean.valueOf(o.toString()); else if (type == Integer.class && o instanceof String) try { return new Integer(o.toString()); } catch (NumberFormatException e) { throw new ClassCastException(_loc.get("cant-convert", o, o.getClass(), type).getMessage()); } else if (type == Character.class) { String str = o.toString(); if (str != null && str.length() == 1) return Character.valueOf(str.charAt(0)); } else if (Calendar.class.isAssignableFrom(type) && o instanceof Date) { Calendar cal = Calendar.getInstance(); cal.setTime((Date) o); return cal; } else if (Date.class.isAssignableFrom(type) && o instanceof Calendar) { return ((Calendar) o).getTime(); } else if (Number.class.isAssignableFrom(type)) { Integer i = null; if (o instanceof Character) { i = Integer.valueOf((Character)o); } else if (o instanceof String && ((String) o).length() == 1) i = Integer.valueOf(((String)o)); if (i != null) { if (type == Integer.class) return i; num = true; } } else if (o instanceof String && isJDBCTemporalSyntax(o.toString())) { try { Object temporal = parseJDBCTemporalSyntax(o.toString()); if (temporal != null && type.isAssignableFrom(temporal.getClass())) return temporal; } catch (IllegalArgumentException e) { } } else if (o instanceof String && type.isEnum()) { return Enum.valueOf((Class)type, o.toString()); } } if (!num) throw new ClassCastException(_loc.get("cant-convert", o, o.getClass(), type).getMessage()); if (type == Integer.class && allowNumericConversion(o.getClass(), type, strictNumericConversion)) { return ((Number) o).intValue(); } else if (type == Float.class && allowNumericConversion(o.getClass(), type, strictNumericConversion)) { return Float.valueOf(((Number) o).floatValue()); } else if (type == Double.class) { return Double.valueOf(((Number) o).doubleValue()); } else if (type == Long.class && allowNumericConversion(o.getClass(), type, strictNumericConversion)) { return ((Number) o).longValue(); } else if (type == BigDecimal.class) { // the BigDecimal constructor doesn't handle the // "NaN" string version of Double.NaN and Float.NaN, nor // does it handle infinity; we need to instead use the Double // and Float versions, despite wanting to cast it to BigDecimal double dval = ((Number) o).doubleValue(); if (Double.isNaN(dval) || Double.isInfinite(dval)) return Double.valueOf(dval); float fval = ((Number) o).floatValue(); if (Float.isNaN(fval) || Float.isInfinite(fval)) return Float.valueOf(fval); return new BigDecimal(o.toString()); } else if (type == BigInteger.class) { return new BigInteger(o.toString()); } else if (type == Short.class && allowNumericConversion(o.getClass(), type, strictNumericConversion)) { return Short.valueOf(((Number) o).shortValue()); } else if (type == Byte.class && allowNumericConversion(o.getClass(), type, strictNumericConversion)) { return Byte.valueOf(((Number) o).byteValue()); } else if (type == Character.class) { return (char) ((Number) o).intValue(); } else if (!strictNumericConversion) { return ((Number) o).intValue(); } else { throw new ClassCastException(_loc.get("cant-convert", o, o.getClass(), type).getMessage()); } } private static boolean allowNumericConversion(Class actual, Class target, boolean strict) { if (!strict || actual == target) return true; if (actual == Byte.class) return false; if (actual == Double.class) return target == Float.class; if (actual == Float.class) return target == Double.class; if (actual == Integer.class) return target == Long.class || target == Short.class; if (actual == Long.class) return target == Integer.class || target == Short.class; if (actual == Short.class) return target == Long.class || target == Integer.class; return false; } /** * Add the given values. */ public static Object add(Object o1, Class c1, Object o2, Class c2) { return op(o1, c1, o2, c2, OP_ADD); } /** * Subtract the given values. */ public static Object subtract(Object o1, Class c1, Object o2, Class c2) { return op(o1, c1, o2, c2, OP_SUBTRACT); } /** * Multiply the given values. */ public static Object multiply(Object o1, Class c1, Object o2, Class c2) { return op(o1, c1, o2, c2, OP_MULTIPLY); } /** * Divide the given values. */ public static Object divide(Object o1, Class c1, Object o2, Class c2) { return op(o1, c1, o2, c2, OP_DIVIDE); } /** * Mod the given values. */ public static Object mod(Object o1, Class c1, Object o2, Class c2) { return op(o1, c1, o2, c2, OP_MOD); } /** * Perform the given operation on two numbers. */ private static Object op(Object o1, Class c1, Object o2, Class c2, int op) { Class promote = promote(c1, c2); if (promote == int.class) { int n1 = (o1 == null) ? 0 : ((Number) o1).intValue(); int n2 = (o2 == null) ? 0 : ((Number) o2).intValue(); return op(n1, n2, op); } if (promote == float.class) { float n1 = (o1 == null) ? 0F : ((Number) o1).floatValue(); float n2 = (o2 == null) ? 0F : ((Number) o2).floatValue(); return op(n1, n2, op); } if (promote == double.class) { double n1 = (o1 == null) ? 0D : ((Number) o1).doubleValue(); double n2 = (o2 == null) ? 0D : ((Number) o2).doubleValue(); return op(n1, n2, op); } if (promote == long.class) { long n1 = (o1 == null) ? 0L : ((Number) o1).longValue(); long n2 = (o2 == null) ? 0L : ((Number) o2).longValue(); return op(n1, n2, op); } if (promote == BigDecimal.class) { BigDecimal n1 = (o1 == null) ? ZERO_BIGDECIMAL : (BigDecimal) convert(o1, promote); BigDecimal n2 = (o2 == null) ? ZERO_BIGDECIMAL : (BigDecimal) convert(o2, promote); return op(n1, n2, op); } if (promote == BigInteger.class) { BigInteger n1 = (o1 == null) ? ZERO_BIGINTEGER : (BigInteger) convert(o1, promote); BigInteger n2 = (o2 == null) ? ZERO_BIGINTEGER : (BigInteger) convert(o2, promote); return op(n1, n2, op); } // default to int int n1 = (o1 == null) ? 0 : ((Number) o1).intValue(); int n2 = (o2 == null) ? 0 : ((Number) o2).intValue(); return op(n1, n2, op); } /** * Return the result of a mathematical operation. */ private static Object op(int n1, int n2, int op) { int tot; switch (op) { case OP_ADD: tot = n1 + n2; break; case OP_SUBTRACT: tot = n1 - n2; break; case OP_MULTIPLY: tot = n1 * n2; break; case OP_DIVIDE: tot = n1 / n2; break; case OP_MOD: tot = n1 % n2; break; default: throw new InternalException(); } return tot; } /** * Return the result of a mathematical operation. */ private static Object op(float n1, float n2, int op) { float tot; switch (op) { case OP_ADD: tot = n1 + n2; break; case OP_SUBTRACT: tot = n1 - n2; break; case OP_MULTIPLY: tot = n1 * n2; break; case OP_DIVIDE: tot = n1 / n2; break; case OP_MOD: tot = n1 % n2; break; default: throw new InternalException(); } return Float.valueOf(tot); } /** * Return the result of a mathematical operation. */ private static Object op(double n1, double n2, int op) { double tot; switch (op) { case OP_ADD: tot = n1 + n2; break; case OP_SUBTRACT: tot = n1 - n2; break; case OP_MULTIPLY: tot = n1 * n2; break; case OP_DIVIDE: tot = n1 / n2; break; case OP_MOD: tot = n1 % n2; break; default: throw new InternalException(); } return Double.valueOf(tot); } /** * Return the result of a mathematical operation. */ private static Object op(long n1, long n2, int op) { long tot; switch (op) { case OP_ADD: tot = n1 + n2; break; case OP_SUBTRACT: tot = n1 - n2; break; case OP_MULTIPLY: tot = n1 * n2; break; case OP_DIVIDE: tot = n1 / n2; break; case OP_MOD: tot = n1 % n2; break; default: throw new InternalException(); } return tot; } /** * Return the result of a mathematical operation. */ private static Object op(BigDecimal n1, BigDecimal n2, int op) { switch (op) { case OP_ADD: return n1.add(n2); case OP_SUBTRACT: return n1.subtract(n2); case OP_MULTIPLY: return n1.multiply(n2); case OP_DIVIDE: int scale = Math.max(n1.scale(), n2.scale()); return n1.divide(n2, scale, BigDecimal.ROUND_HALF_UP); case OP_MOD: throw new UserException(_loc.get("mod-bigdecimal")); default: throw new InternalException(); } } /** * Return the result of a mathematical operation. */ private static Object op(BigInteger n1, BigInteger n2, int op) { switch (op) { case OP_ADD: return n1.add(n2); case OP_SUBTRACT: return n1.subtract(n2); case OP_MULTIPLY: return n1.multiply(n2); case OP_DIVIDE: return n1.divide(n2); default: throw new InternalException(); } } /** * Parses the given declarations into a list of type, name, type, name... * Returns null if no declarations. Assumes declaration is not an empty * string and is already trimmed (valid assumptions given the checks made * in our setters). * * @param decType the type of declaration being parsed, for use in * error messages */ public static List parseDeclaration(String dec, char split, String decType) { if (dec == null) return null; // watch for common mixups between commas and semis char bad = (char) 0; if (split == ',') bad = ';'; else if (split == ';') bad = ','; char sentinal = ' '; char cur; int start = 0; boolean skipSpace = false; List results = new ArrayList(6); for (int i = 0; i < dec.length(); i++) { cur = dec.charAt(i); if (cur == bad) throw new UserException(_loc.get("bad-dec", dec, decType)); if (cur == ' ' && skipSpace) { start++; continue; } skipSpace = false; if (cur != sentinal) continue; // if looking for spaces, look for split char, or vice versa sentinal = (sentinal == ' ') ? split : ' '; results.add(dec.substring(start, i).trim()); start = i + 1; skipSpace = true; } // add last token, if any if (start < dec.length()) results.add(dec.substring(start)); // if not an even number of elements, something is wrong if (results.isEmpty() || results.size() % 2 != 0) throw new UserException(_loc.get("bad-dec", dec, decType)); return results; } /** * Split the given expression list into distinct expressions. Assumes the * given string is not null or of zero length and is already trimmed * (valid assumptions given the checks in our setters and before * this method call). */ public static List splitExpressions(String str, char split, int expected) { if (str == null) return null; List exps = null; int parenDepth = 0; int begin = 0, pos = 0; boolean escape = false; boolean string = false; boolean nonspace = false; char quote = 0; for (char c; pos < str.length(); pos++) { c = str.charAt(pos); if (c == '\\') { escape = !escape; continue; } if (escape) { escape = false; continue; } switch (c) { case '\'': case '"': if (string && quote == c) string = false; else if (!string) { quote = c; string = true; } nonspace = true; break; case '(': if (!string) parenDepth++; nonspace = true; break; case ')': if (!string) parenDepth--; nonspace = true; break; case ' ': case '\t': case '\n': case '\r': if (c == split && !string && parenDepth == 0 && nonspace) { if (exps == null) exps = new ArrayList(expected); exps.add(str.substring(begin, pos).trim()); begin = pos + 1; nonspace = false; } break; default: if (c == split && !string && parenDepth == 0) { if (exps == null) exps = new ArrayList(expected); exps.add(str.substring(begin, pos).trim()); begin = pos + 1; } nonspace = true; } escape = false; } if (exps == null) { exps = Collections.singletonList(str); return exps; } // add last expression and return array String last = str.substring(begin).trim(); if (last.length() > 0) exps.add(last); return exps; } /** * Add the given access path metadatas to the full path list, making sure * to maintain only base metadatas in the list. The given list may be null. */ public static List addAccessPathMetaDatas(List metas, ClassMetaData[] path) { if (path == null || path.length == 0) return metas; // create set of base class metadatas in access path if (metas == null) metas = new ArrayList(); int last = metas.size(); // for every element in the path of this executor, compare it // to already-gathered elements to see if it should replace // a subclass in the list or should be added as a new base; // at least it's n^2 of a small n... ClassMetaData meta; boolean add; for (int i = 0; i < path.length; i++) { add = true; for (int j = 0; add && j < last; j++) { meta = metas.get(j); if (meta.getDescribedType().isAssignableFrom(path[i].getDescribedType())) { // list already contains base class add = false; } else if (path[i].getDescribedType().isAssignableFrom(meta.getDescribedType())) { // this element replaces its subclass add = false; metas.set(j, path[i]); } } // if no base class of current path element already in // list and path element didn't replace a subclass in the // list, then add it now as a new base if (add) metas.add(path[i]); } return metas; } /** * Convert the user-given hint value to an aggregate listener. * The hint can be an aggregate listener instance or class name. */ public static AggregateListener hintToAggregateListener(Object hint, ClassLoader loader) { if (hint == null) return null; if (hint instanceof AggregateListener) return (AggregateListener) hint; Exception cause = null; if (hint instanceof String) { try { return (AggregateListener) AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(Class.forName((String) hint, true, loader))); } catch (Exception e) { if (e instanceof PrivilegedActionException) e = ((PrivilegedActionException) e).getException(); cause = e; } } throw new UserException(_loc.get("bad-agg-listener-hint", hint, hint.getClass())).setCause(cause); } /** * Convert the user-given hint value to an array of aggregate listeners. * The hint can be an aggregate listener, aggregate listener array, * collection, or comma-separated class names. */ public static AggregateListener[] hintToAggregateListeners(Object hint, ClassLoader loader) { if (hint == null) return null; if (hint instanceof AggregateListener[]) return (AggregateListener[]) hint; if (hint instanceof AggregateListener) return new AggregateListener[]{ (AggregateListener) hint }; if (hint instanceof Collection) { Collection c = (Collection) hint; return c.toArray(new AggregateListener[c.size()]); } Exception cause = null; if (hint instanceof String) { String[] clss = Strings.split((String) hint, ",", 0); AggregateListener[] aggs = new AggregateListener[clss.length]; try { for (int i = 0; i < clss.length; i++) aggs[i] = (AggregateListener) AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction( Class.forName(clss[i], true, loader))); return aggs; } catch (Exception e) { if (e instanceof PrivilegedActionException) e = ((PrivilegedActionException) e).getException(); cause = e; } } throw new UserException(_loc.get("bad-agg-listener-hint", hint, hint.getClass())).setCause(cause); } /** * Convert the user-given hint value to a filter listener. * The hint can be a filter listener instance or class name. */ public static FilterListener hintToFilterListener(Object hint, ClassLoader loader) { if (hint == null) return null; if (hint instanceof FilterListener) return (FilterListener) hint; Exception cause = null; if (hint instanceof String) { try { return (FilterListener) AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction( Class.forName((String) hint, true, loader))); } catch (Exception e) { if (e instanceof PrivilegedActionException) e = ((PrivilegedActionException) e).getException(); cause = e; } } throw new UserException(_loc.get("bad-filter-listener-hint", hint, hint.getClass())).setCause(cause); } /** * Convert the user-given hint value to an array of filter listeners. * The hint can be a filter listener, filter listener array, * collection, or comma-separated class names. */ public static FilterListener[] hintToFilterListeners(Object hint, ClassLoader loader) { if (hint == null) return null; if (hint instanceof FilterListener[]) return (FilterListener[]) hint; if (hint instanceof FilterListener) return new FilterListener[]{ (FilterListener) hint }; if (hint instanceof Collection) { Collection c = (Collection) hint; return c.toArray(new FilterListener[c.size()]); } Exception cause = null; if (hint instanceof String) { String[] clss = Strings.split((String) hint, ",", 0); FilterListener[] filts = new FilterListener[clss.length]; try { for (int i = 0; i < clss.length; i++) filts[i] = (FilterListener) AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction( Class.forName(clss[i], true, loader))); return filts; } catch (Exception e) { if (e instanceof PrivilegedActionException) e = ((PrivilegedActionException) e).getException(); cause = e; } } throw new UserException(_loc.get("bad-filter-listener-hint", hint, hint.getClass())).setCause(cause); } /** * Return the value of the property named by the hint key. */ public static Object hintToGetter(Object target, String hintKey) { if (target == null || hintKey == null) return null; Method getter = Reflection.findGetter(target.getClass(), hintKey, true); return Reflection.get(target, getter); } /** * Set the value of the property named by the hint key. */ public static void hintToSetter(Object target, String hintKey, Object value) { if (target == null || hintKey == null) return; Method setter = Reflection.findSetter(target.getClass(), hintKey, true); if (value instanceof String) { if ("null".equals(value)) value = null; else { try { value = Strings.parse((String) value, setter.getParameterTypes()[0]); } catch (Exception e) { throw new UserException(_loc.get("bad-setter-hint-arg", hintKey, value, setter.getParameterTypes()[0])). setCause(e); } } } Reflection.set(target, setter, value); } /** * Parses the given string assuming it is a JDBC key expression. Extracts the * data portion and based on the key, calls static java.sql.Date/Time/Timestamp.valueOf(String) * method to convert to a java.sql.Date/Time/Timestamp instance. */ public static Object parseJDBCTemporalSyntax(String s) { s = clip(s.trim(), "{", "}", true); if (s.startsWith("ts")) { return java.sql.Timestamp.valueOf(clip(s.substring(2).trim(), "'", "'", false)); } else if (s.startsWith("d")) { return java.sql.Date.valueOf(clip(s.substring(1).trim(), "'", "'", false)); } else if (s.startsWith("t")) { return java.sql.Time.valueOf(clip(s.substring(2).trim(), "'", "'", false)); } else { return null; } } /** * Affirms if the given String is enclosed in {}. * */ public static boolean isJDBCTemporalSyntax(String s) { if (s != null) { s = s.trim(); } return s != null && s.startsWith("{") && s.endsWith("}"); } /** * Removes the first and last string if they are the terminal sequence in the given string. * * @param s a string to be examined * @param first the characters in the beginning of the given string * @param last the characters in the end of the given string * @param fail if true throws exception if the given string does not have the given terminal sequences. * @return the string with terminal sequences removed. */ public static String clip(String s, String first, String last, boolean fail) { if (s == null) return s; if (s.startsWith(first) && s.endsWith(last)) { return s.substring(first.length(), s.length()-last.length()).trim(); } if (fail) { throw new IllegalArgumentException(s + " is not valid escape syntax for JDBC"); } return s; } /** * Affirms if the given class is Data, Time or Timestamp. */ public static boolean isTemporalType(Class c) { return c != null && (Date.class.isAssignableFrom(c) || Time.class.isAssignableFrom(c) || Timestamp.class.isAssignableFrom(c) || Calendar.class.isAssignableFrom(c)); } public static Object getDefaultForNull(Class nType) { if (nType == Long.class) return Long.valueOf(0); if (nType == Integer.class) return Integer.valueOf(0); if (nType == Double.class) return Double.valueOf(0.0); if (nType == Float.class) return new Float(0.0); if (nType == Short.class) return Short.valueOf((short)0); return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCleanState.java0000644000000000000000000000451012133327272026300 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a persistent instance that is participating in the current * transaction, but has not yet been modified. * * @author Abe White */ @SuppressWarnings("serial") class PCleanState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { if (previous == null) return; context.setDirty(false); } PCState commit(StateManagerImpl context) { return HOLLOW; } PCState commitRetain(StateManagerImpl context) { return PNONTRANS; } PCState rollback(StateManagerImpl context) { return HOLLOW; } PCState rollbackRestore(StateManagerImpl context) { return PNONTRANS; } PCState delete(StateManagerImpl context) { context.preDelete(); return PDELETED; } PCState nontransactional(StateManagerImpl context) { return PNONTRANS; } PCState release(StateManagerImpl context) { return TRANSIENT; } PCState evict(StateManagerImpl context) { return HOLLOW; } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return PDIRTY; } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return PDIRTY; } boolean isTransactional() { return true; } boolean isPersistent() { return true; } public String toString() { return "Persistent-Clean"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/LockLevels.java0000644000000000000000000000235412133327272026204 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Standard object lock levels. * * @author Abe White * @since 0.4.0 */ public interface LockLevels { /** * No lock. Value of 0. */ public static final int LOCK_NONE = 0; /** * Generic read lock level. Value of 10. */ public static final int LOCK_READ = 10; /** * Generic write lock level. Value of 20. */ public static final int LOCK_WRITE = 20; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java0000644000000000000000000035147412133327272027350 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.IOException; import java.io.NotSerializableException; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.TimeZone; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.enhance.DynamicPersistenceCapable; import org.apache.openjpa.enhance.FieldManager; import org.apache.openjpa.enhance.ManagedInstanceProvider; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.RedefinitionHelper; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.event.LifecycleEvent; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FetchGroup; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.UpdateStrategies; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.meta.ValueStrategies; import org.apache.openjpa.util.ApplicationIds; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.ObjectNotFoundException; import org.apache.openjpa.util.OpenJPAId; import org.apache.openjpa.util.ProxyManager; import org.apache.openjpa.util.RuntimeExceptionTranslator; import org.apache.openjpa.util.UserException; /** * Implementation of the {@link OpenJPAStateManager} interface for use * with this runtime. Each state manager manages the state of a single * persistence capable instance. The state manager is also responsible for * all communications about the instance to the {@link StoreManager}. * The state manager uses the State pattern in both its interaction with * the governed instance and its interaction with the broker. * In its interactions with the persistence capable instance, it uses the * {@link FieldManager} interface. Similarly, when interacting with the * broker, it uses the {@link PCState} singleton that represents * the current lifecycle state of the instance. * * @author Abe White */ public class StateManagerImpl implements OpenJPAStateManager, Serializable { public static final int LOAD_FGS = 0; public static final int LOAD_ALL = 1; public static final int LOAD_SERIALIZE = 2; private static final int FLAG_SAVE = 2 << 0; private static final int FLAG_DEREF = 2 << 1; private static final int FLAG_LOADED = 2 << 2; private static final int FLAG_READ_LOCKED = 2 << 3; private static final int FLAG_WRITE_LOCKED = 2 << 4; private static final int FLAG_OID_ASSIGNED = 2 << 5; private static final int FLAG_LOADING = 2 << 6; private static final int FLAG_PRE_DELETING = 2 << 7; private static final int FLAG_FLUSHED = 2 << 8; private static final int FLAG_PRE_FLUSHED = 2 << 9; private static final int FLAG_FLUSHED_DIRTY = 2 << 10; private static final int FLAG_IMPL_CACHE = 2 << 11; private static final int FLAG_INVERSES = 2 << 12; private static final int FLAG_NO_UNPROXY = 2 << 13; private static final int FLAG_VERSION_CHECK = 2 << 14; private static final int FLAG_VERSION_UPDATE = 2 << 15; private static final int FLAG_DETACHING = 2 << 16; private static final int FLAG_EMBED_DEREF = 2 << 17; private static final Localizer _loc = Localizer.forPackage(StateManagerImpl.class); // information about the instance private transient PersistenceCapable _pc = null; protected transient ClassMetaData _meta = null; protected BitSet _loaded = null; // Care needs to be taken when accessing these fields as they will can be null if no fields are // dirty, or have been flushed. private BitSet _dirty = null; private BitSet _flush = null; private BitSet _delayed = null; private int _flags = 0; // id is the state manager identity; oid is the persistent identity. oid // may be null for embedded and transient-transactional objects or new // instances that haven't been assigned an oid. id is reassigned to oid // on successful oid assignment (or flush completion if assignment is // during flush) private Object _id = null; private Object _oid = null; // the managing persistence manager and lifecycle state private transient BrokerImpl _broker; // this is serialized specially protected PCState _state = PCState.TRANSIENT; // the current and last loaded version indicators, and the lock object protected Object _version = null; protected Object _loadVersion = null; private Object _lock = null; private int _readLockLevel = -1; private int _writeLockLevel = -1; // delegates when providing/replacing instance data private SingleFieldManager _single = null; private SaveFieldManager _saved = null; private FieldManager _fm = null; // impldata; field impldata and intermediate data share the same array private Object _impl = null; protected Object[] _fieldImpl = null; // information about the owner of this instance, if it is embedded private StateManagerImpl _owner = null; // for embeddable object from query result private Object _ownerId = null; private int _ownerIndex = -1; private List _mappedByIdFields = null; private transient ReentrantLock _instanceLock = null; /** *

    set to false to prevent the postLoad method from * sending lifecycle callback events.

    *

    Callbacks are enabled by default */ private boolean postLoadCallback = true; /** * Constructor; supply id, type metadata, and owning persistence manager. */ protected StateManagerImpl(Object id, ClassMetaData meta, BrokerImpl broker) { _id = id; _meta = meta; _broker = broker; _single = new SingleFieldManager(this, broker); if (broker.getMultithreaded()) _instanceLock = new ReentrantLock(); if (_meta.getIdentityType() == ClassMetaData.ID_UNKNOWN && !_meta.isEmbeddable()) throw new UserException(_loc.get("meta-unknownid", _meta)); } /** * Create a new StateManager instance based on the StateManager provided. A * new PersistenceCapable instance will be created and associated with the * new StateManager. All fields will be copied into the ne PC instance as * well as the dirty, loaded, and flushed bitsets. * * @param sm A statemanager instance which will effectively be cloned. */ public StateManagerImpl(StateManagerImpl sm) { this(sm, sm.getPCState()); } /** * Create a new StateManager instance, optionally overriding the state * (FLUSHED, DELETED, etc) of the underlying PersistenceCapable instance). * * @param sm * A statemanager instance which will effectively be cloned. * @param newState * The new state of the underlying persistence capable object. */ public StateManagerImpl(StateManagerImpl sm, PCState newState) { this(sm.getId(), sm.getMetaData(), sm.getBroker()); PersistenceCapable origPC = sm.getPersistenceCapable(); _pc = origPC.pcNewInstance(sm, false); int[] fields = new int[sm.getMetaData().getFields().length]; for (int i = 0; i < fields.length; i++) { fields[i] = i; } _pc.pcCopyFields(origPC, fields); _pc.pcReplaceStateManager(this); _state = newState; // clone the field bitsets. _dirty=(BitSet)sm.getDirty().clone(); _loaded = (BitSet)sm.getLoaded().clone(); _flush = (BitSet) sm.getFlushed().clone(); _version = sm.getVersion(); _oid = sm.getObjectId(); _id = sm.getId(); // more data may need to be copied. } /** * Set the owning state and field if this is an embedded instance. */ void setOwner(StateManagerImpl owner, ValueMetaData ownerMeta) { _owner = owner; _ownerIndex = ownerMeta.getFieldMetaData().getIndex(); } /** * Whether this state manager is in the middle of a load. */ boolean isLoading() { return (_flags & FLAG_LOADING) > 0; } /** * Whether this state manager is in the middle of a load initiated * by outside code; for any internal methods that cause loading, the * loading flag is set automatically. */ void setLoading(boolean loading) { if (loading) _flags |= FLAG_LOADING; else _flags &= ~FLAG_LOADING; } /** * Set or reset the lifecycle state of the managed instance. If the * transactional state of the instance changes, it will be enlisted/ * delisted from the current transaction as necessary. The given * state will be initialized after being set. If the given state * is the same as the current state, this method will have no effect. */ private void setPCState(PCState state) { if (_state == state) return; PCState prev = _state; lock(); try { // notify the store manager that we're changing states; can veto _broker.getStoreManager().beforeStateChange(this, _state, state); // replace state boolean wasDeleted = _state.isDeleted(); boolean wasDirty = _state.isDirty(); boolean wasPending = _state.isPendingTransactional(); _state = state; // enlist/delist from transaction if (_state.isTransactional()) { _broker.addToTransaction(this); if (_state.isDeleted() != wasDeleted) _broker.setDirty(this, !wasDirty || isFlushed()); else if (_state.isDirty() && !wasDirty) _broker.setDirty(this, true); } else if (!wasPending && _state.isPendingTransactional()) _broker.addToPendingTransaction(this); else if (wasPending && !_state.isPendingTransactional()) _broker.removeFromPendingTransaction(this); else _broker.removeFromTransaction(this); _state.initialize(this, prev); if (_state.isDeleted() && !wasDeleted) fireLifecycleEvent(LifecycleEvent.AFTER_DELETE); } finally { unlock(); } } ////////////////////////////////////// // OpenJPAStateManager implementation ////////////////////////////////////// public void initialize(Class cls, PCState state) { // check to see if our current object id instance is the // correct id type for the specified class; this is for cases // when we have an application id hierarchy and we had set the // metadata to a superclass id -- the subclass' id may be a // different class, so we need to reset it if (_meta.getDescribedType() != cls) { ClassMetaData sub = _meta.getRepository().getMetaData (cls, _broker.getClassLoader(), true); if (_oid != null) { if (_meta.getIdentityType() == ClassMetaData.ID_DATASTORE) _oid = _broker.getStoreManager().copyDataStoreId(_oid, sub); else if (_meta.isOpenJPAIdentity()) _oid = ApplicationIds.copy(_oid, sub); else if (sub.getObjectIdType() != _meta.getObjectIdType()) { Object[] pkFields = ApplicationIds.toPKValues(_oid, _meta); _oid = ApplicationIds.fromPKValues(pkFields, sub); } } _meta = sub; } PersistenceCapable inst = PCRegistry.newInstance(cls, this, _oid, true); if (inst == null) { // the instance was null: check to see if the instance is // abstract (as can sometimes be the case when the // class discriminator strategy is not configured correctly) if (Modifier.isAbstract(cls.getModifiers())) throw new UserException(_loc.get("instantiate-abstract", cls.getName(), _oid)); throw new InternalException(); } initialize(inst, state); } /** * Initialize with the given instance and state. */ protected void initialize(PersistenceCapable pc, PCState state) { if (pc == null) throw new UserException(_loc.get("init-null-pc", _meta)); if (pc.pcGetStateManager() != null && pc.pcGetStateManager() != this) throw new UserException(_loc.get("init-sm-pc", Exceptions.toString(pc))).setFailedObject(pc); pc.pcReplaceStateManager(this); FieldMetaData[] fmds = _meta.getFields(); _loaded = new BitSet(fmds.length); // mark primary key and non-persistent fields as loaded for(int i : _meta.getPkAndNonPersistentManagedFmdIndexes()){ _loaded.set(i); } _mappedByIdFields = _meta.getMappyedByIdFields(); // record whether there are any managed inverse fields if (_broker.getInverseManager() != null && _meta.hasInverseManagedFields()) _flags |= FLAG_INVERSES; pc.pcSetDetachedState(null); _pc = pc; if (_oid instanceof OpenJPAId) ((OpenJPAId) _oid).setManagedInstanceType(_meta.getDescribedType()); // initialize our state and add ourselves to the broker's cache setPCState(state); if ( _oid == null || _broker.getStateManagerImplById(_oid, false) == null) { _broker.setStateManager(_id, this, BrokerImpl.STATUS_INIT); } if (state == PCState.PNEW) fireLifecycleEvent(LifecycleEvent.AFTER_PERSIST); // if this is a non-tracking PC, add a hard ref to the appropriate data // sets and give it an opportunity to make a state snapshot. if (!isIntercepting()) { saveFields(true); if (!isNew()) RedefinitionHelper.assignLazyLoadProxies(this); } } /** * Whether or not data access in this instance is intercepted. This differs * from {@link ClassMetaData#isIntercepting()} in that it checks for * property access + subclassing in addition to the redefinition / * enhancement checks. * * @since 1.0.0 */ public boolean isIntercepting() { if (getMetaData().isIntercepting()) return true; // TODO:JRB Intercepting if (AccessCode.isProperty(getMetaData().getAccessType()) && _pc instanceof DynamicPersistenceCapable) return true; return false; } /** * Fire the given lifecycle event to all listeners. */ private boolean fireLifecycleEvent(int type) { if (type == LifecycleEvent.AFTER_PERSIST && _broker.getConfiguration().getCallbackOptionsInstance().getPostPersistCallbackImmediate()) { fetchObjectId(); } return _broker.fireLifecycleEvent(getManagedInstance(), null, _meta, type); } public void load(FetchConfiguration fetch) { load(fetch, LOAD_FGS, null, null, false); } /** * Load the state of this instance based on the given fetch configuration * and load mode. Return true if any data was loaded, false otherwise. */ protected boolean load(FetchConfiguration fetch, int loadMode, BitSet exclude, Object sdata, boolean forWrite) { if (!forWrite && (!isPersistent() || (isNew() && !isFlushed()) || isDeleted())) return false; // if any fields being loaded, do state transitions for read BitSet fields = getUnloadedInternal(fetch, loadMode, exclude); boolean active = _broker.isActive(); if (!forWrite && fields != null) beforeRead(-1); // call load even if no fields are being loaded, because it takes // care of checking if the DFG is loaded, making sure version info // is loaded, etc int lockLevel = calculateLockLevel(active, forWrite, fetch); boolean ret = loadFields(fields, fetch, lockLevel, sdata); obtainLocks(active, forWrite, lockLevel, fetch, sdata); return ret; } public Object getManagedInstance() { if (_pc instanceof ManagedInstanceProvider) return ((ManagedInstanceProvider) _pc).getManagedInstance(); else return _pc; } public PersistenceCapable getPersistenceCapable() { return _pc; } public ClassMetaData getMetaData() { return _meta; } public OpenJPAStateManager getOwner() { return _owner; } public int getOwnerIndex() { return _ownerIndex; } public void setOwner(Object oid) { _ownerId = oid; } public boolean isEmbedded() { // _owner may not be set if embed object is from query result return _owner != null || _state instanceof ENonTransState; } public boolean isFlushed() { return (_flags & FLAG_FLUSHED) > 0; } public boolean isFlushedDirty() { return (_flags & FLAG_FLUSHED_DIRTY) > 0; } public BitSet getLoaded() { return _loaded; } public BitSet getUnloaded(FetchConfiguration fetch) { // collect fields to load from data store based on fetch configuration BitSet fields = getUnloadedInternal(fetch, LOAD_FGS, null); return (fields == null) ? new BitSet(0) : fields; } /** * Internal version of {@link OpenJPAStateManager#getUnloaded} that avoids * creating an empty bit set by returning null when there are no unloaded * fields. */ private BitSet getUnloadedInternal(FetchConfiguration fetch, int mode, BitSet exclude) { if (exclude == StoreContext.EXCLUDE_ALL) return null; BitSet fields = null; FieldMetaData[] fmds = _meta.getFields(); boolean load; for (int i = 0; i < fmds.length; i++) { if (_loaded.get(i) || (exclude != null && exclude.get(i))) continue; switch (mode) { case LOAD_SERIALIZE: load = !fmds[i].isTransient(); break; case LOAD_FGS: load = fetch == null || fetch.requiresFetch(fmds[i]) != FetchConfiguration.FETCH_NONE; break; default: // LOAD_ALL load = true; } if (load) { if (fields == null) fields = new BitSet(fmds.length); fields.set(i); } } return fields; } public StoreContext getContext() { return _broker; } /** * Managing broker. */ BrokerImpl getBroker() { return _broker; } public Object getId() { return _id; } public Object getObjectId() { StateManagerImpl sm = this; while (sm.getOwner() != null) sm = (StateManagerImpl) sm.getOwner(); if (sm.isEmbedded() && sm.getOwner() == null) return sm._ownerId; return sm._oid; } public void setObjectId(Object oid) { _oid = oid; if (_pc != null && oid instanceof OpenJPAId) ((OpenJPAId) oid).setManagedInstanceType(_meta.getDescribedType()); } public StateManagerImpl getObjectIdOwner() { StateManagerImpl sm = this; while (sm.getOwner() != null) sm = (StateManagerImpl) sm.getOwner(); return sm; } public boolean assignObjectId(boolean flush) { lock(); try { return assignObjectId(flush, false); } finally { unlock(); } } /** * Ask store manager to assign our oid, optionally flushing and * optionally recaching on the new oid. */ boolean assignObjectId(boolean flush, boolean preFlushing) { if (_oid != null || isEmbedded() || !isPersistent()) return true; if (_broker.getStoreManager().assignObjectId(this, preFlushing)) { if (!preFlushing) assertObjectIdAssigned(true); } else if (flush) _broker.flush(); else return false; return true; } /** * Make sure we were assigned an oid, and perform actions to make it * permanent. * * @param recache whether to recache ourself on the new oid */ private void assertObjectIdAssigned(boolean recache) { if (!isNew() || isDeleted() || isProvisional() || (_flags & FLAG_OID_ASSIGNED) != 0) return; if (_oid == null) { if (_meta.getIdentityType() == ClassMetaData.ID_DATASTORE) throw new InternalException(Exceptions.toString (getManagedInstance())); _oid = ApplicationIds.create(_pc, _meta); } Object orig = _id; _id = _oid; if (recache) { try { _broker.setStateManager(orig, this, BrokerImpl.STATUS_OID_ASSIGN); } catch (RuntimeException re) { _id = orig; _oid = null; throw re; } } _flags |= FLAG_OID_ASSIGNED; } /** * Assign the proper generated value to the given field based on its * value-strategy. */ private boolean assignField(int field, boolean preFlushing) { OpenJPAStateManager sm = this; while (sm != null && sm.isEmbedded()) sm = sm.getOwner(); if (sm == null) return false; if (!sm.isNew() || sm.isFlushed() || sm.isDeleted()) return false; // special-case oid fields, which require us to look inside the oid // object FieldMetaData fmd = _meta.getField(field); if (fmd.getDeclaredTypeCode() == JavaTypes.OID) { // try to shortcut if possible if (_oid != null || isEmbedded() || !isPersistent()) return true; // check embedded fields of oid for value strategy + default value FieldMetaData[] pks = fmd.getEmbeddedMetaData().getFields(); OpenJPAStateManager oidsm = null; boolean assign = false; for (int i = 0; !assign && i < pks.length; i++) { if (pks[i].getValueStrategy() == ValueStrategies.NONE) continue; if (oidsm == null) oidsm = new ObjectIdStateManager(fetchObjectField(field), this, fmd); assign = oidsm.isDefaultValue(i); } return assign && assignObjectId(!preFlushing, preFlushing); } // Just return if there's no value generation strategy if (fmd.getValueStrategy() == ValueStrategies.NONE) return false; // Throw exception if field already has a value assigned. // @GeneratedValue overrides POJO initial values and setter methods if (!fmd.isValueGenerated() && !isDefaultValue(field)) throw new InvalidStateException(_loc.get( "existing-value-override-excep", fmd.getFullName(false))); // for primary key fields, assign the object id and recache so that // to the user, so it looks like the oid always matches the pk fields if (fmd.isPrimaryKey() && !isEmbedded()) return assignObjectId(!preFlushing, preFlushing); // for other fields just assign the field or flush if needed if (_broker.getStoreManager().assignField(this, field, preFlushing)) { fmd.setValueGenerated(true); return true; } if (!preFlushing) _broker.flush(); return !preFlushing; } public Object getLock() { return _lock; } public void setLock(Object lock) { _lock = lock; } public Object getVersion() { return _version; } public void setVersion(Object version) { _loadVersion = version; assignVersionField(version); } Object getLoadVersion() { return _loadVersion; } public void setNextVersion(Object version) { assignVersionField(version); } private void assignVersionField(Object version) { _version = version; FieldMetaData vfield = _meta.getVersionField(); if (vfield != null) store(vfield.getIndex(), JavaTypes.convert(version, vfield.getTypeCode())); } public PCState getPCState() { return _state; } public synchronized Object getImplData() { return _impl; } public synchronized Object setImplData(Object data, boolean cacheable) { Object old = _impl; _impl = data; if (cacheable && data != null) _flags |= FLAG_IMPL_CACHE; else _flags &= ~FLAG_IMPL_CACHE; return old; } public boolean isImplDataCacheable() { return (_flags & FLAG_IMPL_CACHE) != 0; } public Object getImplData(int field) { return getExtraFieldData(field, true); } public Object setImplData(int field, Object data) { return setExtraFieldData(field, data, true); } public synchronized boolean isImplDataCacheable(int field) { if (_fieldImpl == null || !_loaded.get(field)) return false; if (_meta.getField(field).usesImplData() != null) return false; int idx = _meta.getExtraFieldDataIndex(field); return idx != -1 && _fieldImpl[idx] != null; } public Object getIntermediate(int field) { return getExtraFieldData(field, false); } public void setIntermediate(int field, Object data) { setExtraFieldData(field, data, false); } /** * Return the data from the proper index of the extra field data array. */ protected synchronized Object getExtraFieldData(int field, boolean isLoaded) { // only return the field data if the field is in the right loaded // state; otherwise we might return intermediate for impl data or // vice versa if (_fieldImpl == null || _loaded.get(field) != isLoaded) return null; int idx = _meta.getExtraFieldDataIndex(field); return (idx == -1) ? null : _fieldImpl[idx]; } /** * Set the data from to proper index of the extra field data array. */ private synchronized Object setExtraFieldData(int field, Object data, boolean loaded) { int idx = _meta.getExtraFieldDataIndex(field); if (idx == -1) throw new InternalException(String.valueOf(_meta.getField(field))); Object old = (_fieldImpl == null) ? null : _fieldImpl[idx]; if (data != null) { // cannot set if field in wrong loaded state if (_loaded.get(field) != loaded) throw new InternalException(String.valueOf(_meta.getField (field))); // set data if (_fieldImpl == null) _fieldImpl = new Object[_meta.getExtraFieldDataLength()]; _fieldImpl[idx] = data; } else if (_fieldImpl != null && _loaded.get(field) == loaded) _fieldImpl[idx] = null; return old; } public Object fetch(int field) { Object val = fetchField(field, false); return _meta.getField(field).getExternalValue(val, _broker); } public Object fetchField(int field, boolean transitions) { FieldMetaData fmd = _meta.getField(field); if (fmd == null) throw new UserException(_loc.get("no-field", String.valueOf(field), getManagedInstance().getClass())). setFailedObject(getManagedInstance()); // do normal state transitions if (!fmd.isPrimaryKey() && transitions) accessingField(field); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.STRING: return fetchStringField(field); case JavaTypes.OBJECT: return fetchObjectField(field); case JavaTypes.BOOLEAN: return (fetchBooleanField(field)) ? Boolean.TRUE : Boolean.FALSE; case JavaTypes.BYTE: return Byte.valueOf(fetchByteField(field)); case JavaTypes.CHAR: return Character.valueOf(fetchCharField(field)); case JavaTypes.DOUBLE: return Double.valueOf(fetchDoubleField(field)); case JavaTypes.FLOAT: return Float.valueOf(fetchFloatField(field)); case JavaTypes.INT: return fetchIntField(field); case JavaTypes.LONG: return fetchLongField(field); case JavaTypes.SHORT: return Short.valueOf(fetchShortField(field)); default: return fetchObjectField(field); } } public void store(int field, Object val) { val = _meta.getField(field).getFieldValue(val, _broker); storeField(field, val); } public void storeField(int field, Object val) { storeField(field, val, this); } /** *

    Checks whether or not _pc is dirty. In the cases where * field tracking is not happening (see below), this method will do a * state comparison to find whether _pc is dirty, and will * update this instance with this information. In the cases where field * tracking is happening, this method is a no-op.

    * *

    Fields are tracked for all classes that are run through the OpenJPA * enhancer prior to or during deployment, and all classes (enhanced or * unenhanced) in a Java 6 environment or newer.

    * *

    In a Java 5 VM or older: *
    - instances of unenhanced classes that use * property access and obey the property access limitations are tracked * when the instances are loaded from the database by OpenJPA, and are * not tracked when the instances are created by application code. *
    - instances of unenhanced classes that use field access are * never tracked.

    * * @since 1.0.0 */ public void dirtyCheck() { if (!needsDirtyCheck()) return; SaveFieldManager saved = getSaveFieldManager(); if (saved == null) throw new InternalException(_loc.get("no-saved-fields", getMetaData().getDescribedType().getName())); FieldMetaData[] fmds = getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) { // pk and version fields cannot be mutated; don't mark them // as such. ##### validate? if (!fmds[i].isPrimaryKey() && !fmds[i].isVersion() && _loaded.get(i)) { if (!saved.isFieldEqual(i, fetch(i))) { dirty(i); } } } } private boolean needsDirtyCheck() { if (isIntercepting()) return false; if (isDeleted()) return false; if (isNew() && !isFlushed()) return false; return true; } public Object fetchInitialField(int field) { FieldMetaData fmd = _meta.getField(field); if (_broker.getRestoreState() == RestoreState.RESTORE_NONE && ((_flags & FLAG_INVERSES) == 0 || fmd.getInverseMetaDatas().length == 0)) throw new InvalidStateException(_loc.get("restore-unset")); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.DATE: case JavaTypes.CALENDAR: case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.OBJECT: // if we're not saving mutable types, throw an exception if (_broker.getRestoreState() != RestoreState.RESTORE_ALL && ((_flags & FLAG_INVERSES) == 0 || fmd.getInverseMetaDatas().length == 0)) throw new InvalidStateException(_loc.get ("mutable-restore-unset")); } lock(); try { if (_saved == null || !_loaded.get(field) || !isFieldDirty(field)) return fetchField(field, false); // if the field is dirty but we never loaded it, we can't restore it if (_saved.getUnloaded().get(field)) throw new InvalidStateException(_loc.get("initial-unloaded", fmd)); provideField(_saved.getState(), _single, field); return fetchField(_single, fmd); } finally { unlock(); } } /** * Fetch the specified field from the specified field manager, wrapping it * in an object if it's a primitive. A field should be provided to the * field manager before this call is made. */ private static Object fetchField(FieldManager fm, FieldMetaData fmd) { int field = fmd.getIndex(); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: return (fm.fetchBooleanField(field)) ? Boolean.TRUE : Boolean.FALSE; case JavaTypes.BYTE: return Byte.valueOf(fm.fetchByteField(field)); case JavaTypes.CHAR: return Character.valueOf(fm.fetchCharField(field)); case JavaTypes.DOUBLE: return Double.valueOf(fm.fetchDoubleField(field)); case JavaTypes.FLOAT: return Float.valueOf(fm.fetchFloatField(field)); case JavaTypes.INT: return fm.fetchIntField(field); case JavaTypes.LONG: return fm.fetchLongField(field); case JavaTypes.SHORT: return Short.valueOf(fm.fetchShortField(field)); case JavaTypes.STRING: return fm.fetchStringField(field); default: return fm.fetchObjectField(field); } } public void setRemote(int field, Object value) { lock(); try { Boolean stat = dirty(field, Boolean.FALSE, false); storeField(field, value, _single); replaceField(_pc, _single, field); postDirty(stat); } finally { unlock(); } } //////////////////////// // Lifecycle operations //////////////////////// /** * Notification that the object is about to be accessed. * * @param field the field number being read, or -1 if not a single * field read */ void beforeRead(int field) { // allow unmediated reads of primary key fields if (field != -1 && _meta.getField(field).isPrimaryKey()) return; if (_broker.isActive() && !_broker.isTransactionEnding()) { if (_broker.getOptimistic()) setPCState(_state.beforeOptimisticRead(this, field)); else setPCState(_state.beforeRead(this, field)); } else if (_broker.getNontransactionalRead()) setPCState(_state.beforeNontransactionalRead(this, field)); else throw new InvalidStateException(_loc.get("non-trans-read")). setFailedObject(getManagedInstance()); } /** * Delegates to the current state. * * @see PCState#beforeFlush */ void beforeFlush(int reason, OpCallbacks call) { _state.beforeFlush(this, reason == BrokerImpl.FLUSH_LOGICAL, call); } /** * Delegates to the current state. * * @see PCState#flush */ void afterFlush(int reason) { // nothing happens when we flush non-persistent states if (!isPersistent()) return; if (reason != BrokerImpl.FLUSH_ROLLBACK && reason != BrokerImpl.FLUSH_LOGICAL) { // analyze previous state for later boolean wasNew = isNew(); boolean wasFlushed = isFlushed(); boolean wasDeleted = isDeleted(); boolean needPostUpdate = !(wasNew && !wasFlushed) && (ImplHelper.getUpdateFields(this) != null); // all dirty fields were flushed, we are referencing the _dirty BitSet directly here // because we don't want to instantiate it if we don't have to. if (_dirty != null) { getFlushed().or(_dirty); } // important to set flushed bit after calling _state.flush so // that the state can tell whether this is the first flush setPCState(_state.flush(this)); _flags |= FLAG_FLUSHED; _flags &= ~FLAG_FLUSHED_DIRTY; _flags &= ~FLAG_VERSION_CHECK; _flags &= ~FLAG_VERSION_UPDATE; // if this was an inc flush during which we had our identity // assigned, tell the broker to cache us under our final oid if (reason == BrokerImpl.FLUSH_INC) assertObjectIdAssigned(true); // if this object was stored with preFlush, do post-store callback if ((_flags & FLAG_PRE_FLUSHED) > 0) fireLifecycleEvent(LifecycleEvent.AFTER_STORE); // do post-update as needed if (wasNew && !wasFlushed) fireLifecycleEvent(LifecycleEvent.AFTER_PERSIST_PERFORMED); else if (wasDeleted) fireLifecycleEvent(LifecycleEvent.AFTER_DELETE_PERFORMED); else if (needPostUpdate) // updates and new-flushed with changes fireLifecycleEvent(LifecycleEvent.AFTER_UPDATE_PERFORMED); } else if (reason == BrokerImpl.FLUSH_ROLLBACK) { // revert to last loaded version and original oid assignVersionField(_loadVersion); if (isNew() && (_flags & FLAG_OID_ASSIGNED) == 0) _oid = null; } _flags &= ~FLAG_PRE_FLUSHED; } /** * Delegates to the current state after checking the value * of the RetainState flag. * * @see PCState#commit * @see PCState#commitRetain */ void commit() { // release locks before oid updated releaseLocks(); // update version and oid information setVersion(_version); _flags &= ~FLAG_FLUSHED; _flags &= ~FLAG_FLUSHED_DIRTY; Object orig = _id; assertObjectIdAssigned(false); boolean wasNew = isNew() && !isDeleted() && !isProvisional(); if (_broker.getRetainState()) setPCState(_state.commitRetain(this)); else setPCState(_state.commit(this)); // ask the broker to re-cache us if we were new previously if (wasNew) _broker.setStateManager(orig, this, BrokerImpl.STATUS_COMMIT_NEW); } /** * Delegates to the current state after checking the value * of the RetainState flag. * * @see PCState#rollback * @see PCState#rollbackRestore */ void rollback() { // release locks releaseLocks(); _flags &= ~FLAG_FLUSHED; _flags &= ~FLAG_FLUSHED_DIRTY; afterFlush(BrokerImpl.FLUSH_ROLLBACK); if (_broker.getRestoreState() != RestoreState.RESTORE_NONE) setPCState(_state.rollbackRestore(this)); else setPCState(_state.rollback(this)); } /** * Rollback state of the managed instance to the given savepoint. */ void rollbackToSavepoint(SavepointFieldManager savepoint) { _state = savepoint.getPCState(); BitSet loaded = savepoint.getLoaded(); for (int i = 0, len = loaded.length(); i < len; i++) { if (loaded.get(i) && savepoint.restoreField(i)) { provideField(savepoint.getCopy(), savepoint, i); replaceField(_pc, savepoint, i); } } _loaded = loaded; _dirty = savepoint.getDirty(); _flush = savepoint.getFlushed(); _version = savepoint.getVersion(); _loadVersion = savepoint.getLoadVersion(); } /** * Delegates to the current state. * * @see PCState#persist * @see Broker#persist */ void persist() { setPCState(_state.persist(this)); } /** * Delegates to the current state. * * @see PCState#delete * @see Broker#delete */ void delete() { setPCState(_state.delete(this)); } /** * Delegates to the current state. * * @see PCState#nontransactional * @see Broker#nontransactional */ void nontransactional() { setPCState(_state.nontransactional(this)); } /** * Delegates to the current state. * * @see PCState#transactional * @see Broker#transactional */ void transactional() { setPCState(_state.transactional(this)); } /** * Delegates to the current state. * * @see PCState#nonprovisional */ void nonprovisional(boolean logical, OpCallbacks call) { setPCState(_state.nonprovisional(this, logical, call)); } /** * Delegates to the current state. * * @see PCState#release * @see Broker#release */ void release(boolean unproxy) { release(unproxy, false); } void release(boolean unproxy, boolean force) { // optimization for detach-in-place special case when fields are // already (un)proxied correctly if (!unproxy) _flags |= FLAG_NO_UNPROXY; try { if (force) setPCState(PCState.TRANSIENT); else setPCState(_state.release(this)); } finally { _flags &= ~FLAG_NO_UNPROXY; } } /** * Delegates to the current state. * * @see PCState#evict * @see Broker#evict */ void evict() { setPCState(_state.evict(this)); } /** * Gather relations reachable from values using * {@link ValueMetaData#CASCADE_IMMEDIATE}. */ void gatherCascadeRefresh(OpCallbacks call) { FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (!_loaded.get(i)) continue; if (fmds[i].getCascadeRefresh() == ValueMetaData.CASCADE_IMMEDIATE || fmds[i].getKey().getCascadeRefresh() == ValueMetaData.CASCADE_IMMEDIATE || fmds[i].getElement().getCascadeRefresh() == ValueMetaData.CASCADE_IMMEDIATE) { _single.storeObjectField(i, fetchField(i, false)); _single.gatherCascadeRefresh(call); _single.clear(); } } } public boolean beforeRefresh(boolean refreshAll) { // note: all logic placed here rather than in the states for // optimization; this method public b/c used by remote package // nothing to do for non persistent or new unflushed instances if (!isPersistent() || (isNew() && !isFlushed())) return false; lock(); try { // if dirty need to clear fields if (isDirty()) { clearFields(); return true; } // if some fields have been loaded but the instance is out of // date or this is part of a refreshAll() and we don't want to // take the extra hit to see if the instance is out of date, clear if (_loaded.length() > 0 && (refreshAll || isEmbedded() || !syncVersion(null))) { Object version = _version; clearFields(); // if syncVersion just replaced the version, reset it if (!refreshAll && !isEmbedded()) setVersion(version); return true; } return false; } finally { unlock(); } } /** * Perform state transitions after refresh. This method is only * called if {@link #beforeRefresh} returns true. */ void afterRefresh() { lock(); try { // transition to clean or nontransactional depending on trans status if (!_broker.isActive()) setPCState(_state.afterNontransactionalRefresh()); else if (_broker.getOptimistic()) setPCState(_state.afterOptimisticRefresh()); else setPCState(_state.afterRefresh()); } finally { unlock(); } } /** * Mark this object as a dereferenced dependent object. */ void setDereferencedDependent(boolean deref, boolean notify) { if (!deref && (_flags & FLAG_DEREF) > 0) { if (notify) _broker.removeDereferencedDependent(this); _flags &= ~FLAG_DEREF; } else if (deref && (_flags & FLAG_DEREF) == 0) { _flags |= FLAG_DEREF; if (notify) _broker.addDereferencedDependent(this); } } void setDereferencedEmbedDependent(boolean deref) { if (!deref && (_flags & FLAG_EMBED_DEREF) > 0) { _flags &= ~FLAG_EMBED_DEREF; } else if (deref && (_flags & FLAG_EMBED_DEREF) == 0) { _flags |= FLAG_EMBED_DEREF; } } public boolean getDereferencedEmbedDependent() { return ((_flags & FLAG_EMBED_DEREF) == 0 ? false : true); } /////////// // Locking /////////// /** * Notification that we've been read-locked. Pass in the level at which * we were locked and the level at which we should write lock ourselves * on dirty. */ void readLocked(int readLockLevel, int writeLockLevel) { // make sure object is added to transaction so lock will get // cleared on commit/rollback if (readLockLevel != LockLevels.LOCK_NONE) transactional(); _readLockLevel = readLockLevel; _writeLockLevel = writeLockLevel; _flags |= FLAG_READ_LOCKED; _flags &= ~FLAG_WRITE_LOCKED; } /** * Return the lock level to use when loading state. */ private int calculateLockLevel(boolean active, boolean forWrite, FetchConfiguration fetch) { if (!active) return LockLevels.LOCK_NONE; if (fetch == null) fetch = _broker.getFetchConfiguration(); if (_readLockLevel == -1) _readLockLevel = fetch.getReadLockLevel(); if (_writeLockLevel == -1) _writeLockLevel = fetch.getWriteLockLevel(); return (forWrite) ? _writeLockLevel : _readLockLevel; } /** * Make sure we're locked at the given level. */ private void obtainLocks(boolean active, boolean forWrite, int lockLevel, FetchConfiguration fetch, Object sdata) { if (!active) return; // if we haven't been locked yet, lock now at the given level int flag = (forWrite) ? FLAG_WRITE_LOCKED : FLAG_READ_LOCKED; if ((_flags & flag) == 0) { // make sure object is added to transaction so lock will get // cleared on commit/rollback if (lockLevel != LockLevels.LOCK_NONE) transactional(); if (fetch == null) fetch = _broker.getFetchConfiguration(); _broker.getLockManager().lock(this, lockLevel, fetch.getLockTimeout(), sdata); _flags |= FLAG_READ_LOCKED; _flags |= flag; } } /** * Release locks. */ private void releaseLocks() { if (_lock != null) _broker.getLockManager().release(this); _readLockLevel = -1; _writeLockLevel = -1; _flags &= ~FLAG_READ_LOCKED; _flags &= ~FLAG_WRITE_LOCKED; } //////////////////////////////////////////// // Implementation of StateManager interface //////////////////////////////////////////// /** * @return whether or not unloaded fields should be closed. */ public boolean serializing() { // if the broker is in the midst of a serialization, then no special // handling should be performed on the instance, and no subsequent // load should happen if (_broker.isSerializing()) return false; try { if (_meta.isDetachable()) return DetachManager.preSerialize(this); load(_broker.getFetchConfiguration(), LOAD_SERIALIZE, null, null, false); return false; } catch (RuntimeException re) { throw translate(re); } } public boolean writeDetached(ObjectOutput out) throws IOException { BitSet idxs = new BitSet(_meta.getFields().length); lock(); try { boolean detsm = DetachManager.writeDetachedState(this, out, idxs); if (detsm) _flags |= FLAG_DETACHING; FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].isTransient()) continue; provideField(_pc, _single, i); _single.serialize(out, !idxs.get(i)); _single.clear(); } return true; } catch (RuntimeException re) { throw translate(re); } finally { _flags &= ~FLAG_DETACHING; unlock(); } } public void proxyDetachedDeserialized(int idx) { // we don't serialize state manager impls throw new InternalException(); } public boolean isTransactional() { // special case for TCLEAN, which we want to appear non-trans to // internal code, but which publicly should be transactional return _state == PCState.TCLEAN || _state.isTransactional(); } public boolean isPendingTransactional() { return _state.isPendingTransactional(); } public boolean isProvisional() { return _state.isProvisional(); } public boolean isPersistent() { return _state.isPersistent(); } public boolean isNew() { return _state.isNew(); } public boolean isDeleted() { return _state.isDeleted(); } public boolean isDirty() { return _state.isDirty(); } public boolean isDetached() { return (_flags & FLAG_DETACHING) != 0; } public Object getGenericContext() { return _broker; } public Object fetchObjectId() { try { if (hasGeneratedKey() && _state instanceof PNewState && _oid == null) return _oid; assignObjectId(true); if (_oid == null || !_broker.getConfiguration(). getCompatibilityInstance().getCopyObjectIds()) return _oid; if (_meta.getIdentityType() == ClassMetaData.ID_DATASTORE) return _broker.getStoreManager().copyDataStoreId(_oid, _meta); return ApplicationIds.copy(_oid, _meta); } catch (RuntimeException re) { throw translate(re); } } private boolean hasGeneratedKey() { FieldMetaData[] pkFields = _meta.getPrimaryKeyFields(); for (int i = 0; i < pkFields.length; i++) { if (pkFields[i].getValueStrategy() == ValueStrategies.AUTOASSIGN) return true; } return false; } public Object getPCPrimaryKey(Object oid, int field) { FieldMetaData fmd = _meta.getField(field); Object pk = ApplicationIds.get(oid, fmd); if (pk == null) return null; ClassMetaData relmeta = fmd.getDeclaredTypeMetaData(); pk = ApplicationIds.wrap(relmeta, pk); if (relmeta.getIdentityType() == ClassMetaData.ID_DATASTORE && fmd.getObjectIdFieldTypeCode() == JavaTypes.LONG) pk = _broker.getStoreManager().newDataStoreId(pk, relmeta); else if (relmeta.getIdentityType() == ClassMetaData.ID_APPLICATION && fmd.getObjectIdFieldType() != relmeta.getObjectIdType()) pk = ApplicationIds.fromPKValues(new Object[] { pk }, relmeta); return _broker.find(pk, false, null); } public byte replaceFlags() { // we always use load required so that we can detect when objects // are touched for locking or making transactional return PersistenceCapable.LOAD_REQUIRED; } public StateManager replaceStateManager(StateManager sm) { return sm; } public void accessingField(int field) { // possibly change state try { // If this field is loaded, and not a PK field allow pass through // TODO -- what about version fields? Could probably UT this if(_loaded.get(field) && !_meta.getField(field).isPrimaryKey()) return; beforeRead(field); beforeAccessField(field); } catch (RuntimeException re) { throw translate(re); } } public boolean isDelayed(int field) { if (_delayed == null) { return false; } return _delayed.get(field); } public void setDelayed(int field, boolean delay) { if (_delayed == null) { _delayed = new BitSet(); } if (delay) { _delayed.set(field); } else { _delayed.clear(field); } } /** * Loads a delayed access field. * @param field */ public void loadDelayedField(int field) { if (!isDelayed(field)) { return; } try { beforeRead(field); } catch (RuntimeException re) { throw translate(re); } lock(); try { boolean active = _broker.isActive(); int lockLevel = calculateLockLevel(active, false, null); BitSet fields = new BitSet(); fields.set(field); if (!_broker.getStoreManager().load(this, fields, _broker.getFetchConfiguration(), lockLevel, null)) { throw new ObjectNotFoundException(_loc.get("del-instance", _meta.getDescribedType(), _oid)). setFailedObject(getManagedInstance()); } // Cleared the delayed bit _delayed.clear(field); obtainLocks(active, false, lockLevel, null, null); } catch (RuntimeException re) { throw translate(re); } finally { unlock(); } } /** * Load the given field before access. */ protected void beforeAccessField(int field) { lock(); try { boolean active = _broker.isActive(); int lockLevel = calculateLockLevel(active, false, null); if (!_loaded.get(field)) loadField(field, lockLevel, false, true); else assignField(field, false); obtainLocks(active, false, lockLevel, null, null); } catch (RuntimeException re) { throw translate(re); } finally { unlock(); } } public void dirty(String field) { FieldMetaData fmd = _meta.getField(field); if (fmd == null) throw translate(new UserException(_loc.get("no-field", field, ImplHelper.getManagedInstance(_pc).getClass())) .setFailedObject(getManagedInstance())); dirty(fmd.getIndex(), null, true); } public void dirty(int field) { dirty(field, null, true); } private boolean isEmbeddedNotUpdatable() { // embeddable object returned from query result is not uptable return (_owner == null && _ownerId != null); } /** * Make the given field dirty. * * @param mutate if null, may be an SCO mutation; if true, is certainly * a mutation (or at least treat as one) * @return {@link Boolean#FALSE} if this instance was already dirty, * null if it was dirty but not since flush, and * {@link Boolean#TRUE} if it was not dirty */ private Boolean dirty(int field, Boolean mutate, boolean loadFetchGroup) { boolean locked = false; boolean newFlush = false; boolean clean = false; try { FieldMetaData fmd = _meta.getField(field); if (!isNew() || isFlushed()) { if (fmd.getUpdateStrategy() == UpdateStrategies.RESTRICT) throw new InvalidStateException(_loc.get ("update-restrict", fmd)); if (fmd.getUpdateStrategy() == UpdateStrategies.IGNORE) return Boolean.FALSE; } if (isEmbedded()) { if (isEmbeddedNotUpdatable()) throw new UserException(_loc.get ("cant-update-embed-in-query-result")).setFailedObject (getManagedInstance()); else // notify owner of change _owner.dirty(_ownerIndex, Boolean.TRUE, loadFetchGroup); } // is this a direct mutation of an sco field? if (mutate == null) { switch (fmd.getDeclaredTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.ARRAY: case JavaTypes.DATE: case JavaTypes.CALENDAR: case JavaTypes.OBJECT: mutate = Boolean.TRUE; break; case JavaTypes.PC: mutate = (fmd.isEmbedded()) ? Boolean.TRUE : Boolean.FALSE; break; default: mutate = Boolean.FALSE; // not sco } } // possibly change state boolean active = _broker.isActive(); clean = !_state.isDirty(); // intentional direct access // fire event fast before state change. if (clean) fireLifecycleEvent(LifecycleEvent.BEFORE_DIRTY); if (active) { if (_broker.getOptimistic()) setPCState(_state.beforeOptimisticWrite(this, field, mutate.booleanValue())); else setPCState(_state.beforeWrite(this, field, mutate.booleanValue())); } else if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT) { if (isPersistent() && !_broker.getNontransactionalWrite()) throw new InvalidStateException(_loc.get ("non-trans-write")).setFailedObject (getManagedInstance()); setPCState(_state.beforeNontransactionalWrite(this, field, mutate.booleanValue())); } if ((_flags & FLAG_FLUSHED) != 0) { newFlush = (_flags & FLAG_FLUSHED_DIRTY) == 0; _flags |= FLAG_FLUSHED_DIRTY; } lock(); locked = true; // note that the field is in need of flushing again, and tell the // broker too clearFlushField(field); _broker.setDirty(this, newFlush && !clean); // save the field for rollback if needed saveField(field); // dirty the field and mark loaded; load fetch group if needed int lockLevel = calculateLockLevel(active, true, null); if (!isFieldDirty(field)) { setLoaded(field, true); setFieldDirty(field); // make sure the field's fetch group is loaded if (loadFetchGroup && isPersistent() && fmd.getManagement() == fmd.MANAGE_PERSISTENT) loadField(field, lockLevel, true, true); } obtainLocks(active, true, lockLevel, null, null); } catch (RuntimeException re) { throw translate(re); } finally { if (locked) unlock(); } if (clean) return Boolean.TRUE; if (newFlush) { // this event can be fired later cause we're already dirty. fireLifecycleEvent(LifecycleEvent.BEFORE_DIRTY_FLUSHED); return null; } return Boolean.FALSE; } /** * Fire post-dirty events after field value changes. * * @param status return value from {@link #dirty(int, Boolean, boolean)} */ private void postDirty(Boolean status) { if (Boolean.TRUE.equals(status)) fireLifecycleEvent(LifecycleEvent.AFTER_DIRTY); else if (status == null) fireLifecycleEvent(LifecycleEvent.AFTER_DIRTY_FLUSHED); } public void removed(int field, Object removed, boolean key) { if (removed == null) return; try { // dereference dependent fields, delete embedded FieldMetaData fmd = _meta.getField(field); ValueMetaData vmd = (key) ? fmd.getKey() : fmd.getElement(); if (vmd.isEmbeddedPC()) _single.delete(vmd, removed, null); else if (vmd.getCascadeDelete() == ValueMetaData.CASCADE_AUTO) _single.dereferenceDependent(removed); } catch (RuntimeException re) { throw translate(re); } } public Object newProxy(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return newFieldProxy(field); switch (fmd.getTypeCode()) { case JavaTypes.DATE: if (fmd.getDeclaredType() == java.sql.Date.class) return new java.sql.Date(System.currentTimeMillis()); if (fmd.getDeclaredType() == java.sql.Timestamp.class) return new java.sql.Timestamp(System.currentTimeMillis()); if (fmd.getDeclaredType() == java.sql.Time.class) return new java.sql.Time(System.currentTimeMillis()); return new Date(); case JavaTypes.CALENDAR: return Calendar.getInstance(); case JavaTypes.COLLECTION: return new ArrayList(); case JavaTypes.MAP: return new HashMap(); } return null; } public Object newFieldProxy(int field) { FieldMetaData fmd = _meta.getField(field); ProxyManager mgr = _broker.getConfiguration(). getProxyManagerInstance(); Object init = fmd.getInitializer(); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.DATE: return mgr.newDateProxy(fmd.getDeclaredType()); case JavaTypes.CALENDAR: return mgr.newCalendarProxy(fmd.getDeclaredType(), init instanceof TimeZone ? (TimeZone) init : null); case JavaTypes.COLLECTION: return mgr.newCollectionProxy(fmd.getProxyType(), fmd.getElement().getDeclaredType(), init instanceof Comparator ? (Comparator) init : null, _broker.getConfiguration().getCompatibilityInstance().getAutoOff()); case JavaTypes.MAP: return mgr.newMapProxy(fmd.getProxyType(), fmd.getKey().getDeclaredType(), fmd.getElement().getDeclaredType(), init instanceof Comparator ? (Comparator) init : null, _broker.getConfiguration().getCompatibilityInstance().getAutoOff()); } return null; } public boolean isDefaultValue(int field) { lock(); try { _single.clear(); provideField(_pc, _single, field); boolean ret = _single.isDefaultValue(); _single.clear(); return ret; } finally { unlock(); } } ///////////////////////////////////////////////////////// // Record that the field is dirty (which might load DFG) ///////////////////////////////////////////////////////// public void settingBooleanField(PersistenceCapable pc, int field, boolean curVal, boolean newVal, int set) { if (set != SET_REMOTE) { if (newVal == curVal && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeBooleanField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingByteField(PersistenceCapable pc, int field, byte curVal, byte newVal, int set) { if (set != SET_REMOTE) { if (newVal == curVal && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeByteField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingCharField(PersistenceCapable pc, int field, char curVal, char newVal, int set) { if (set != SET_REMOTE) { if (newVal == curVal && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeCharField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingDoubleField(PersistenceCapable pc, int field, double curVal, double newVal, int set) { if (set != SET_REMOTE) { if (newVal == curVal && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeDoubleField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingFloatField(PersistenceCapable pc, int field, float curVal, float newVal, int set) { if (set != SET_REMOTE) { if (newVal == curVal && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeFloatField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingIntField(PersistenceCapable pc, int field, int curVal, int newVal, int set) { if (set != SET_REMOTE) { if (newVal == curVal && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeIntField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingLongField(PersistenceCapable pc, int field, long curVal, long newVal, int set) { if (set != SET_REMOTE) { if (newVal == curVal && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeLongField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingObjectField(PersistenceCapable pc, int field, Object curVal, Object newVal, int set) { if (set != SET_REMOTE) { FieldMetaData fmd = _meta.getField(field); if (_loaded.get(field)) { if (newVal == curVal) return; // only compare new to old values if the comparison is going to // be cheap -- don't compare collections, maps, UDTs switch (fmd.getDeclaredTypeCode()) { case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.PC_UNTYPED: break; case JavaTypes.PC: if (_meta.getField(field).isPrimaryKey()) { // this field is a derived identity //if (newVal != null && newVal.equals(curVal)) // return; //else { if (curVal != null && newVal != null && curVal instanceof PersistenceCapable && newVal instanceof PersistenceCapable) { PersistenceCapable curPc = (PersistenceCapable) curVal; PersistenceCapable newPc = (PersistenceCapable) newVal; if (curPc.pcFetchObjectId().equals(newPc.pcFetchObjectId())) return; } //} } else break; default: if (newVal != null && newVal.equals(curVal)) return; } } else { // if this is a dependent unloaded field, make sure to load // it now if (fmd.getCascadeDelete() == ValueMetaData.CASCADE_AUTO || fmd.getKey().getCascadeDelete() == ValueMetaData.CASCADE_AUTO || fmd.getElement().getCascadeDelete() == ValueMetaData.CASCADE_AUTO) curVal = fetchObjectField(field); } assertNoPrimaryKeyChange(field); if (fmd.getDeclaredTypeCode() == JavaTypes.OID) assertNotManagedObjectId(newVal); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); if (set != SET_REMOTE) { _single.storeObjectField(field, curVal); _single.unproxy(); _single.dereferenceDependent(); _single.clear(); } _single.storeObjectField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingShortField(PersistenceCapable pc, int field, short curVal, short newVal, int set) { if (set != SET_REMOTE) { if (newVal == curVal && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeShortField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } public void settingStringField(PersistenceCapable pc, int field, String curVal, String newVal, int set) { if (set != SET_REMOTE) { if (StringUtils.equals(newVal, curVal) && _loaded.get(field)) return; assertNoPrimaryKeyChange(field); } lock(); try { Boolean stat = dirty(field, Boolean.FALSE, set == SET_USER); _single.storeStringField(field, newVal); replaceField(pc, _single, field); postDirty(stat); } finally { unlock(); } } /** * Disallows changing primary key fields for instances. */ private void assertNoPrimaryKeyChange(int field) { if (_oid != null && _meta.getField(field).isPrimaryKey()) throw translate(new InvalidStateException(_loc.get ("change-identity")).setFailedObject(getManagedInstance())); } /** * Disallows setting an object id field to a managed instance. */ void assertNotManagedObjectId(Object val) { if (val != null && (ImplHelper.toPersistenceCapable(val, getContext().getConfiguration())).pcGetGenericContext()!= null) throw translate(new InvalidStateException(_loc.get ("managed-oid", Exceptions.toString(val), Exceptions.toString(getManagedInstance()))). setFailedObject(getManagedInstance())); } //////////////////////////// // Delegate to FieldManager //////////////////////////// public void providedBooleanField(PersistenceCapable pc, int field, boolean curVal) { _fm.storeBooleanField(field, curVal); } public void providedByteField(PersistenceCapable pc, int field, byte curVal) { _fm.storeByteField(field, curVal); } public void providedCharField(PersistenceCapable pc, int field, char curVal) { _fm.storeCharField(field, curVal); } public void providedDoubleField(PersistenceCapable pc, int field, double curVal) { _fm.storeDoubleField(field, curVal); } public void providedFloatField(PersistenceCapable pc, int field, float curVal) { _fm.storeFloatField(field, curVal); } public void providedIntField(PersistenceCapable pc, int field, int curVal) { _fm.storeIntField(field, curVal); } public void providedLongField(PersistenceCapable pc, int field, long curVal) { _fm.storeLongField(field, curVal); } public void providedObjectField(PersistenceCapable pc, int field, Object curVal) { _fm.storeObjectField(field, curVal); } public void providedShortField(PersistenceCapable pc, int field, short curVal) { _fm.storeShortField(field, curVal); } public void providedStringField(PersistenceCapable pc, int field, String curVal) { _fm.storeStringField(field, curVal); } public boolean replaceBooleanField(PersistenceCapable pc, int field) { return _fm.fetchBooleanField(field); } public byte replaceByteField(PersistenceCapable pc, int field) { return _fm.fetchByteField(field); } public char replaceCharField(PersistenceCapable pc, int field) { return _fm.fetchCharField(field); } public double replaceDoubleField(PersistenceCapable pc, int field) { return _fm.fetchDoubleField(field); } public float replaceFloatField(PersistenceCapable pc, int field) { return _fm.fetchFloatField(field); } public int replaceIntField(PersistenceCapable pc, int field) { return _fm.fetchIntField(field); } public long replaceLongField(PersistenceCapable pc, int field) { return _fm.fetchLongField(field); } public Object replaceObjectField(PersistenceCapable pc, int field) { return _fm.fetchObjectField(field); } public short replaceShortField(PersistenceCapable pc, int field) { return _fm.fetchShortField(field); } public String replaceStringField(PersistenceCapable pc, int field) { return _fm.fetchStringField(field); } ////////////////////////////////// // Implementation of FieldManager ////////////////////////////////// public boolean fetchBoolean(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchBooleanField(field); Object val = fetchField(field, false); return ((Boolean) fmd.getExternalValue(val, _broker)).booleanValue(); } public boolean fetchBooleanField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchBooleanField(field); } finally { unlock(); } } public byte fetchByte(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchByteField(field); Object val = fetchField(field, false); return ((Number) fmd.getExternalValue(val, _broker)).byteValue(); } public byte fetchByteField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchByteField(field); } finally { unlock(); } } public char fetchChar(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchCharField(field); Object val = fetchField(field, false); return ((Character) fmd.getExternalValue(val, _broker)).charValue(); } public char fetchCharField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchCharField(field); } finally { unlock(); } } public double fetchDouble(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchDoubleField(field); Object val = fetchField(field, false); return ((Number) fmd.getExternalValue(val, _broker)).doubleValue(); } public double fetchDoubleField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchDoubleField(field); } finally { unlock(); } } public float fetchFloat(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchFloatField(field); Object val = fetchField(field, false); return ((Number) fmd.getExternalValue(val, _broker)).floatValue(); } public float fetchFloatField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchFloatField(field); } finally { unlock(); } } public int fetchInt(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchIntField(field); Object val = fetchField(field, false); return ((Number) fmd.getExternalValue(val, _broker)).intValue(); } public int fetchIntField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchIntField(field); } finally { unlock(); } } public long fetchLong(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchLongField(field); Object val = fetchField(field, false); return ((Number) fmd.getExternalValue(val, _broker)).longValue(); } public long fetchLongField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchLongField(field); } finally { unlock(); } } public Object fetchObject(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchObjectField(field); Object val = fetchField(field, false); return fmd.getExternalValue(val, _broker); } public Object fetchObjectField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchObjectField(field); } finally { unlock(); } } public short fetchShort(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchShortField(field); Object val = fetchField(field, false); return ((Number) fmd.getExternalValue(val, _broker)).shortValue(); } public short fetchShortField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchShortField(field); } finally { unlock(); } } public String fetchString(int field) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) return fetchStringField(field); Object val = fetchField(field, false); return (String) fmd.getExternalValue(val, _broker); } public String fetchStringField(int field) { lock(); try { if (!_loaded.get(field)) loadField(field, LockLevels.LOCK_NONE, false, false); provideField(_pc, _single, field); return _single.fetchStringField(field); } finally { unlock(); } } public void storeBoolean(int field, boolean externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeBooleanField(field, externalVal); else { Object val = (externalVal) ? Boolean.TRUE : Boolean.FALSE; storeField(field, fmd.getFieldValue(val, _broker)); } } public void storeBooleanField(int field, boolean curVal) { lock(); try { _single.storeBooleanField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeByte(int field, byte externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeByteField(field, externalVal); else storeField(field, fmd.getFieldValue(Byte.valueOf(externalVal), _broker)); } public void storeByteField(int field, byte curVal) { lock(); try { _single.storeByteField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeChar(int field, char externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeCharField(field, externalVal); else storeField(field, fmd.getFieldValue(Character.valueOf(externalVal), _broker)); } public void storeCharField(int field, char curVal) { lock(); try { _single.storeCharField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeDouble(int field, double externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeDoubleField(field, externalVal); else storeField(field, fmd.getFieldValue(Double.valueOf(externalVal), _broker)); } public void storeDoubleField(int field, double curVal) { lock(); try { _single.storeDoubleField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeFloat(int field, float externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeFloatField(field, externalVal); else storeField(field, fmd.getFieldValue(Float.valueOf(externalVal), _broker)); } public void storeFloatField(int field, float curVal) { lock(); try { _single.storeFloatField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeInt(int field, int externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeIntField(field, externalVal); else storeField(field, fmd.getFieldValue(externalVal, _broker)); } public void storeIntField(int field, int curVal) { lock(); try { _single.storeIntField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeLong(int field, long externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeLongField(field, externalVal); else storeField(field, fmd.getFieldValue(externalVal, _broker)); } public void storeLongField(int field, long curVal) { lock(); try { _single.storeLongField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeObject(int field, Object externalVal) { FieldMetaData fmd = _meta.getField(field); externalVal = fmd.order(externalVal); if (!fmd.isExternalized()) storeObjectField(field, externalVal); else storeField(field, fmd.getFieldValue(externalVal, _broker)); } public void storeObjectField(int field, Object curVal) { lock(); try { _single.storeObjectField(field, curVal); _single.proxy(true, false); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeShort(int field, short externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeShortField(field, externalVal); else storeField(field, fmd.getFieldValue(Short.valueOf(externalVal), _broker)); } public void storeShortField(int field, short curVal) { lock(); try { _single.storeShortField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } public void storeString(int field, String externalVal) { FieldMetaData fmd = _meta.getField(field); if (!fmd.isExternalized()) storeStringField(field, externalVal); else storeField(field, fmd.getFieldValue(externalVal, _broker)); } public void storeStringField(int field, String curVal) { lock(); try { _single.storeStringField(field, curVal); replaceField(_pc, _single, field); setLoaded(field, true); postLoad(field, null); } finally { unlock(); } } /** * Store the given field value into the given field manager. */ private void storeField(int field, Object val, FieldManager fm) { FieldMetaData fmd = _meta.getField(field); if (fmd == null) throw new UserException(_loc.get("no-field-index", String.valueOf(field), _meta.getDescribedType())). setFailedObject(getManagedInstance()); switch (fmd.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: boolean bool = val != null && ((Boolean) val).booleanValue(); fm.storeBooleanField(field, bool); break; case JavaTypes.BYTE: byte b = (val == null) ? 0 : ((Number) val).byteValue(); fm.storeByteField(field, b); break; case JavaTypes.CHAR: char c = (val == null) ? 0 : ((Character) val).charValue(); fm.storeCharField(field, c); break; case JavaTypes.DOUBLE: double d = (val == null) ? 0 : ((Number) val).doubleValue(); fm.storeDoubleField(field, d); break; case JavaTypes.FLOAT: float f = (val == null) ? 0 : ((Number) val).floatValue(); fm.storeFloatField(field, f); break; case JavaTypes.INT: int i = (val == null) ? 0 : ((Number) val).intValue(); fm.storeIntField(field, i); break; case JavaTypes.LONG: long l = (val == null) ? 0 : ((Number) val).longValue(); fm.storeLongField(field, l); break; case JavaTypes.SHORT: short s = (val == null) ? 0 : ((Number) val).shortValue(); fm.storeShortField(field, s); break; case JavaTypes.STRING: fm.storeStringField(field, (String) val); break; default: fm.storeObjectField(field, val); } } ///////////// // Utilities ///////////// /** * Erase the fact that this instance has been flushed. */ void eraseFlush() { _flags &= ~FLAG_FLUSHED; _flags &= ~FLAG_FLUSHED_DIRTY; _flush = null; } /** * Records that all instance fields are/are not loaded. * Primary key and non-persistent fields are not affected. */ void setLoaded(boolean val) { FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (!fmds[i].isPrimaryKey() && fmds[i].getManagement() == fmds[i].MANAGE_PERSISTENT) setLoaded(i, val); } if (!val) { _flags &= ~FLAG_LOADED; setDirty(false); } else _flags |= FLAG_LOADED; } /** * Records that all instance fields are/are not dirty, * and changes the flags of the instance accordingly. */ void setDirty(boolean val) { FieldMetaData[] fmds = _meta.getFields(); boolean update = !isNew() || isFlushed(); for (int i = 0; i < fmds.length; i++) { if (val && (!update || fmds[i].getUpdateStrategy() != UpdateStrategies.IGNORE)) setFieldDirty(i); else if (!val) { // we never consider clean fields flushed; this also takes // care of clearing the flushed fields on commit/rollback clearFlushField(i); clearDirty(i); } } if (val) _flags |= FLAG_LOADED; } /** * Executes pre-clear callbacks, clears all managed fields, and calls the * {@link #setLoaded} method with a value of false. Primary key fields * are not cleared. */ void clearFields() { if (!isIntercepting()) return; fireLifecycleEvent(LifecycleEvent.BEFORE_CLEAR); // unproxy all fields unproxyFields(); lock(); try { // clear non-pk fields FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (!fmds[i].isPrimaryKey() && fmds[i].getManagement() == FieldMetaData.MANAGE_PERSISTENT) replaceField(_pc, ClearFieldManager.getInstance(), i); } // forget version info and impl data so we re-read next time setLoaded(false); _version = null; _loadVersion = null; if (_fieldImpl != null) Arrays.fill(_fieldImpl, null); } finally { unlock(); } fireLifecycleEvent(LifecycleEvent.AFTER_CLEAR); } /** * Record that we should save any fields that change from this point * forward. */ void saveFields(boolean immediate) { if (_broker.getRestoreState() == RestoreState.RESTORE_NONE && (_flags & FLAG_INVERSES) == 0) return; _flags |= FLAG_SAVE; if (immediate) { for (int i = 0, len = _loaded.length(); i < len; i++) saveField(i); _flags &= ~FLAG_SAVE; // OPENJPA-659 // record a saved field manager even if no field is currently loaded // as existence of a SaveFieldManager is critical for a dirty check if (_saved == null) _saved = new SaveFieldManager(this, getPersistenceCapable(), getDirty()); } } /** * If the field isn't already saved, saves the currently loaded field * state of the instance. The saved values can all be restored via * {@link #restoreFields}. */ private void saveField(int field) { if ((_flags & FLAG_SAVE) == 0) return; // if this is a managed inverse field, load it so we're sure to have // the original value if (!_loaded.get(field) && ((_flags & FLAG_INVERSES) != 0 && _meta.getField(field).getInverseMetaDatas().length > 0)) loadField(field, LockLevels.LOCK_NONE, false, false); // don't bother creating the save field manager if we're not going to // save the old field value anyway if (_saved == null) { if (_loaded.get(field)) _saved = new SaveFieldManager(this, null, getDirty()); else return; } // copy the field to save field manager; if the field is not directly // copyable, immediately provide and replace it via the save field // manager, which will copy the mutable value to prevent by-ref mods if (_saved.saveField(field)) { provideField(_pc, _saved, field); replaceField(_saved.getState(), _saved, field); } } /** * Notification that the state will not need to be rolled back * to that of the last call to {@link #saveFields}. */ void clearSavedFields() { if (isIntercepting()) { _flags &= ~FLAG_SAVE; _saved = null; } } public SaveFieldManager getSaveFieldManager() { return _saved; } /** * Rollback the state of the instance to the saved state from the * last call to {@link #saveFields}, or to default values if never saved. */ void restoreFields() { lock(); try { if (_saved == null) { if ((_flags & FLAG_SAVE) == 0) clearFields(); else // only unloaded fields were dirtied _loaded.andNot(_loaded); } // we direct state transitions based on our own getRestoreState // method, but to decide whether to actually rollback field // values, we consult the broker for the user's setting else if (_broker.getRestoreState() != RestoreState.RESTORE_NONE) { // rollback all currently-loaded fields for (int i = 0, len = _loaded.length(); i < len; i++) if (_loaded.get(i) && _saved.restoreField(i)) replaceField(_pc, _saved, i); // rollback loaded set _loaded.andNot(_saved.getUnloaded()); } } finally { unlock(); } } /** * Replaces all second class object fields with fresh proxied instances * containing the same information as the originals. *
    * Note: Proxying is bypassed if {@link AutoDetach#DETACH_NONE} option is set. */ void proxyFields(boolean reset, boolean replaceNull) { if (getBroker().getAutoDetach() == AutoDetach.DETACH_NONE) return; // we only replace nulls if the runtime can't differentiate between // null and empty containers. we replace nulls in this case to // maintain consistency whether values are being retained or not if (replaceNull) replaceNull = !_broker.getConfiguration().supportedOptions(). contains(OpenJPAConfiguration.OPTION_NULL_CONTAINER); lock(); try { for (FieldMetaData fmd : _meta.getProxyFields()) { int index = fmd.getIndex(); // only reload if dirty if (_loaded.get(index) && isFieldDirty(index)) { provideField(_pc, _single, index); if (_single.proxy(reset, replaceNull)) { replaceField(_pc, _single, index); } else { _single.clear(); } } } } finally { unlock(); } } /** * Unproxy all fields. */ void unproxyFields() { if ((_flags & FLAG_NO_UNPROXY) != 0) return; lock(); try { for (int i = 0, len = _loaded.length(); i < len; i++) { provideField(_pc, _single, i); _single.unproxy(); _single.releaseEmbedded(); _single.clear(); } } finally { unlock(); } } /** * Get ready for a flush. Persists all persistence-capable object fields, * and checks for illegal null values. Also assigns oids and field values * for all strategies that don't require flushing. */ void preFlush(boolean logical, OpCallbacks call) { if ((_flags & FLAG_PRE_FLUSHED) != 0) return; if (isPersistent()) { fireLifecycleEvent(LifecycleEvent.BEFORE_STORE); // BEFORE_PERSIST is handled during Broker.persist and Broker.attach if (isDeleted()) fireLifecycleEvent(LifecycleEvent.BEFORE_DELETE); else if (!(isNew() && !isFlushed()) && (ImplHelper.getUpdateFields(this) != null)) fireLifecycleEvent(LifecycleEvent.BEFORE_UPDATE); _flags |= FLAG_PRE_FLUSHED; } lock(); try { if (!logical) assignObjectId(false, true); for (int i = 0, len = _meta.getFields().length; i < len; i++) { if ((logical || !assignField(i, true)) && !isFieldFlushed(i) && isFieldDirty(i)) { provideField(_pc, _single, i); if (_single.preFlush(logical, call)) replaceField(_pc, _single, i); else _single.clear(); } } dirtyCheck(); } finally { unlock(); } } /** * Make callbacks for deletion. */ void preDelete() { // set a flag while call pre delete callback so that user can't // get into infinite recursion by calling delete(this) // within his callback method if ((_flags & FLAG_PRE_DELETING) == 0) { _flags |= FLAG_PRE_DELETING; try { fireLifecycleEvent(LifecycleEvent.BEFORE_DELETE); } finally { _flags &= ~FLAG_PRE_DELETING; } } } /** * Cascade deletes and dereference dependent fields. */ void cascadeDelete(OpCallbacks call) { FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].getCascadeDelete() != ValueMetaData.CASCADE_NONE || fmds[i].getKey().getCascadeDelete() != ValueMetaData.CASCADE_NONE || fmds[i].getElement().getCascadeDelete() != ValueMetaData.CASCADE_NONE) { _single.storeObjectField(i, fetchField(i, false)); _single.delete(call); _single.clear(); } } } /** * Called after an instance is persisted by a user through the broker. * Cascades the persist operation to fields marked * {@link ValueMetaData#CASCADE_IMMEDIATE}. */ void cascadePersist(OpCallbacks call) { FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (!_loaded.get(i)) continue; if (fmds[i].getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE || fmds[i].getKey().getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE || fmds[i].getElement().getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE) { _single.storeObjectField(i, fetchField(i, false)); _single.persist(call); _single.clear(); } } } /** * Load the given field set from the data store into the instance. * Return true if any data is loaded, false otherwise. */ boolean loadFields(BitSet fields, FetchConfiguration fetch, int lockLevel, Object sdata) { // can't load version field from store if (fields != null) { FieldMetaData vfield = _meta.getVersionField(); if (vfield != null) fields.clear(vfield.getIndex()); } boolean ret = false; setLoading(true); try { // if any fields given, load them int len = (fields == null) ? 0 : fields.length(); if (len > 0) { if (fetch == null) fetch = _broker.getFetchConfiguration(); if (!_broker.getStoreManager().load(this, fields, fetch, lockLevel, sdata)) { throw new ObjectNotFoundException(_loc.get("del-instance", _meta.getDescribedType(), _oid)). setFailedObject(getManagedInstance()); } ret = true; } // make sure version information has been set; version info must // always be set after the first state load or set (which is why // we do this even if no fields were loaded -- could be that this // method is being called after a field is set) // If the _loadVersion field is null AND the version field has been loaded, skip calling sync version. // This indicates that the DB has a null value for the version column. FieldMetaData versionMeta = _meta != null ? _meta.getVersionField() : null; if (_loadVersion == null && (versionMeta != null && !_loaded.get(versionMeta.getIndex()))) { syncVersion(sdata); ret = ret || _loadVersion != null; } } finally { setLoading(false); } // see if the dfg is now loaded; do this regardless of whether we // loaded any fields, cause may already have been loaded by // StoreManager during initialization postLoad(-1, fetch); return ret; } /** * Load the given field's fetch group; the field itself may already be * loaded if it is being set by the user. */ protected void loadField(int field, int lockLevel, boolean forWrite, boolean fgs) { FetchConfiguration fetch = _broker.getFetchConfiguration(); FieldMetaData fmd = _meta.getField(field); BitSet fields = null; // if this is a dfg field or we need to load our dfg, do so if (fgs && (_flags & FLAG_LOADED) == 0) fields = getUnloadedInternal(fetch, LOAD_FGS, null); // check for load fetch group String lfg = fmd.getLoadFetchGroup(); boolean lfgAdded = false; if (lfg != null) { FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (!_loaded.get(i) && (i == field || fmds[i].isInFetchGroup(lfg))) { if (fields == null) fields = new BitSet(fmds.length); fields.set(i); } } // relation field is loaded with the load-fetch-group // but this addition must be reverted once the load is over if (!fetch.hasFetchGroup(lfg)) { fetch.addFetchGroup(lfg); lfgAdded = true; } } else if (fmd.isInDefaultFetchGroup() && fields == null) { // no load group but dfg: add dfg fields if we haven't already fields = getUnloadedInternal(fetch, LOAD_FGS, null); } else if (!_loaded.get(fmd.getIndex())) { // no load group or dfg: load individual field if (fields == null) fields = new BitSet(); fields.set(fmd.getIndex()); } // call this method even if there are no unloaded fields; loadFields // takes care of things like loading version info and setting PC flags try { loadFields(fields, fetch, lockLevel, null); } finally { if (lfgAdded) fetch.removeFetchGroup(lfg); } } /** * Helper method to provide the given field number to the given * field manager. */ void provideField(PersistenceCapable pc, FieldManager store, int field) { if (pc != null) { FieldManager beforeFM = _fm; _fm = store; pc.pcProvideField(field); // Retaining original FM because of the possibility of reentrant calls if (beforeFM != null) _fm = beforeFM; } } /** * Helper method to replace the given field number to the given * field manager. */ void replaceField(PersistenceCapable pc, FieldManager load, int field) { FieldManager beforeFM = _fm; _fm = load; pc.pcReplaceField(field); // Retaining original FM because of the possibility of reentrant calls if (beforeFM != null) _fm = beforeFM; } /** * Mark the field as loaded or unloaded. */ private void setLoaded(int field, boolean isLoaded) { // don't continue if loaded state is already correct; otherwise we // can end up clearing _fieldImpl when we shouldn't if (_loaded.get(field) == isLoaded) return; // if loading, clear intermediate data; if unloading, clear impl data if (_fieldImpl != null) { int idx = _meta.getExtraFieldDataIndex(field); if (idx != -1) _fieldImpl[idx] = null; } if (isLoaded) _loaded.set(field); else _loaded.clear(field); } /** * Set to false to prevent the postLoad method from * sending lifecycle callback events. */ public void setPostLoadCallback(boolean enabled) { this.postLoadCallback = enabled; } /** * Perform post-load steps, including the post load callback. * We have to check the dfg after all field loads because it might be * loaded in multiple steps when paging is involved; the initial load * might exclude some fields which are then immediately loaded in a * separate step before being returned to the user. * * @param field the field index that was loaded, or -1 to indicate * that a group of possibly unknown fields was loaded */ private void postLoad(int field, FetchConfiguration fetch) { // no need for postLoad callback? if ((_flags & FLAG_LOADED) != 0) return; // in the middle of a group load, after which this method will be // called again? if (field != -1 && isLoading()) return; // no listeners? LifecycleEventManager mgr = _broker.getLifecycleEventManager(); if (mgr == null || !mgr.isActive(_meta) || !mgr.hasLoadListeners(getManagedInstance(), _meta)) return; if (fetch == null) fetch = _broker.getFetchConfiguration(); // is this field a post-load field? if (field != -1) { FieldMetaData fmd = _meta.getField(field); if (fmd.isInDefaultFetchGroup() && fetch.hasFetchGroup(FetchGroup.NAME_DEFAULT) && postLoad(FetchGroup.NAME_DEFAULT, fetch)) return; String[] fgs = fmd.getCustomFetchGroups(); for (int i = 0; i < fgs.length; i++) if (fetch.hasFetchGroup(fgs[i]) && postLoad(fgs[i], fetch)) return; } else { for (Iterator itr = fetch.getFetchGroups().iterator(); itr.hasNext();) { if (postLoad((String) itr.next(), fetch)) return; } } } /** * Perform post-load actions if the given fetch group is a post-load group * and is fully loaded. */ private boolean postLoad(String fgName, FetchConfiguration fetch) { FetchGroup fg = _meta.getFetchGroup(fgName); if (fg == null || !fg.isPostLoad()) return false; FieldMetaData[] fmds = _meta.getFields(); for (int i = 0; i < fmds.length; i++) if (!_loaded.get(i) && fmds[i].isInFetchGroup(fgName)) return false; _flags |= FLAG_LOADED; if (postLoadCallback) _broker.fireLifecycleEvent(getManagedInstance(), fetch, _meta, LifecycleEvent.AFTER_LOAD); return true; } /** * Synchronize our version object with the datastore. */ private boolean syncVersion(Object sdata) { return _broker.getStoreManager().syncVersion(this, sdata); } /** * Returns whether this instance needs a version check. */ public boolean isVersionCheckRequired() { // explicit flag for version check if ((_flags & FLAG_VERSION_CHECK) != 0) return true; if (!_broker.getOptimistic() && !_broker.getConfiguration(). getCompatibilityInstance().getNonOptimisticVersionCheck()) return false; return _state.isVersionCheckRequired(this); } /** * Set whether this instance requires a version check on the next flush. */ void setCheckVersion(boolean versionCheck) { if (versionCheck) _flags |= FLAG_VERSION_CHECK; else _flags &= ~FLAG_VERSION_CHECK; } /** * Returns whether this instance needs a version update. */ public boolean isVersionUpdateRequired() { return (_flags & FLAG_VERSION_UPDATE) > 0; } /** * Set whether this instance requires a version update on the next flush. */ void setUpdateVersion(boolean versionUpdate) { if (versionUpdate) _flags |= FLAG_VERSION_UPDATE; else _flags &= ~FLAG_VERSION_UPDATE; } /** * Translate the given exception based on the broker's implicit behavior. * Translation only occurs if the exception is initiated by a user action * on an instance, and therefore will not be caught and translated by the * broker. */ protected RuntimeException translate(RuntimeException re) { RuntimeExceptionTranslator trans = _broker.getInstanceExceptionTranslator(); return (trans == null) ? re : trans.translate(re); } /** * Lock the state manager if the multithreaded option is set. */ protected void lock() { if (_instanceLock != null) _instanceLock.lock(); } /** * Unlock the state manager. */ protected void unlock () { if (_instanceLock != null) _instanceLock.unlock(); } private void writeObject(ObjectOutputStream oos) throws IOException { oos.writeObject(_broker); oos.defaultWriteObject(); oos.writeObject(_meta.getDescribedType()); writePC(oos, _pc); } /** * Write pc to oos, handling internal-form * serialization. pc must be of the same type that this * state manager manages. * * @since 1.1.0 */ void writePC(ObjectOutputStream oos, PersistenceCapable pc) throws IOException { if (!Serializable.class.isAssignableFrom(_meta.getDescribedType())) throw new NotSerializableException(_meta.getDescribedType().getName()); oos.writeObject(pc); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { _broker = (BrokerImpl) in.readObject(); in.defaultReadObject(); // we need to store the class before the pc instance so that we can // create _meta before calling readPC(), which relies on _meta being // non-null when reconstituting ReflectingPC instances. Sadly, this // penalizes the serialization footprint of non-ReflectingPC SMs also. Class managedType = (Class) in.readObject(); _meta = _broker.getConfiguration().getMetaDataRepositoryInstance() .getMetaData(managedType, null, true); _pc = readPC(in); } /** * Converts the deserialized o to a {@link PersistenceCapable} * instance appropriate for storing in _pc. * * @since 1.1.0 */ PersistenceCapable readPC(ObjectInputStream in) throws ClassNotFoundException, IOException { Object o = in.readObject(); if (o == null) return null; PersistenceCapable pc; if (!(o instanceof PersistenceCapable)) pc = ImplHelper.toPersistenceCapable(o, this); else pc = (PersistenceCapable) o; pc.pcReplaceStateManager(this); return pc; } public List getMappedByIdFields() { return _mappedByIdFields; } public boolean requiresFetch(FieldMetaData fmd) { return (_broker.getFetchConfiguration().requiresFetch(fmd) != FetchConfiguration.FETCH_NONE); } public void setPc(PersistenceCapable pc) { _pc = pc; } public void setBroker(BrokerImpl ctx) { _broker = ctx; } public BitSet getFlushed() { if (_flush == null) { _flush = new BitSet(_meta.getFields().length); } return _flush; } private boolean isFieldFlushed(int index) { if (_flush == null) { return false; } return _flush.get(index); } /** * Will clear the bit at the specified if the _flush BetSet has been created. */ private void clearFlushField(int index) { if (_flush != null) { getFlushed().clear(index); } } public BitSet getDirty() { if (_dirty == null) { _dirty = new BitSet(_meta.getFields().length); } return _dirty; } private boolean isFieldDirty(int index) { if (_dirty == null) { return false; } return _dirty.get(index); } private void setFieldDirty(int index) { getDirty().set(index); } /** * Will clear the bit at the specified index if the _dirty BetSet has been created. */ private void clearDirty(int index) { if (_dirty != null) { getDirty().clear(index); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractStoreQuery.java0000644000000000000000000001473112133327272027751 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Map; import org.apache.commons.collections.map.LinkedMap; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.kernel.exps.QueryExpressions; import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.UnsupportedException; /** * Abstract {@link StoreQuery} that implements most methods as no-ops. * * @author Abe White * @since 0.4.0 */ @SuppressWarnings("serial") public abstract class AbstractStoreQuery implements StoreQuery { protected QueryContext ctx = null; public QueryContext getContext() { return ctx; } public void setContext(QueryContext ctx) { this.ctx = ctx; } public boolean setQuery(Object query) { return false; } public FilterListener getFilterListener(String tag) { return null; } public AggregateListener getAggregateListener(String tag) { return null; } public Object newCompilationKey() { return null; } public Object newCompilation() { return null; } public Object getCompilation() { return null; } public void populateFromCompilation(Object comp) { } public void invalidateCompilation() { } public boolean supportsDataStoreExecution() { return false; } public boolean supportsInMemoryExecution() { return false; } public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs) { throw new InternalException(); } public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs) { throw new InternalException(); } public boolean supportsAbstractExecutors() { return false; } public boolean requiresCandidateType() { return true; } public boolean requiresParameterDeclarations() { return true; } public boolean supportsParameterDeclarations() { return true; } public Object evaluate(Object value, Object ob, Object[] params, OpenJPAStateManager sm) { throw new UnsupportedException(); } /** * Abstract {@link Executor} that implements most methods as no-ops. */ public static abstract class AbstractExecutor implements Executor { public Number executeDelete(StoreQuery q, Object[] params) { try { return q.getContext().deleteInMemory(q, this, params); } finally { for (ClassMetaData cmd : getAccessPathMetaDatas(q)) { DataCache cache = cmd.getDataCache(); if (cache != null && cache.getEvictOnBulkUpdate()) { cache.removeAll(cmd.getDescribedType(), true); } } } } public Number executeUpdate(StoreQuery q, Object[] params) { try { return q.getContext().updateInMemory(q, this, params); } finally { for (ClassMetaData cmd : getAccessPathMetaDatas(q)) { DataCache cache = cmd.getDataCache(); if (cache != null && cache.getEvictOnBulkUpdate()) { cache.removeAll(cmd.getDescribedType(), true); } } } } public String[] getDataStoreActions(StoreQuery q, Object[] params, Range range) { return EMPTY_STRINGS; } public void validate(StoreQuery q) { } public QueryExpressions[] getQueryExpressions() { return null; } public ResultShape getResultShape(StoreQuery q) { return null; } public void getRange(StoreQuery q, Object[] params, Range range) { } public Object getOrderingValue(StoreQuery q, Object[] params, Object resultObject, int orderIndex) { return null; } public boolean[] getAscending(StoreQuery q) { return EMPTY_BOOLEANS; } public boolean isPacking(StoreQuery q) { return false; } public String getAlias(StoreQuery q) { return null; } public String[] getProjectionAliases(StoreQuery q) { return EMPTY_STRINGS; } public Class[] getProjectionTypes(StoreQuery q) { return EMPTY_CLASSES; } public ClassMetaData[] getAccessPathMetaDatas(StoreQuery q) { return EMPTY_METAS; } public int getOperation(StoreQuery q) { return OP_SELECT; } public boolean isAggregate(StoreQuery q) { return false; } public boolean isDistinct(StoreQuery q) { return false; } public boolean hasGrouping(StoreQuery q) { return false; } public OrderedMap> getOrderedParameterTypes(StoreQuery q) { return EMPTY_ORDERED_PARAMS; } public LinkedMap getParameterTypes(StoreQuery q) { LinkedMap result = new LinkedMap(); result.putAll(getOrderedParameterTypes(q)); return result; } public Class getResultClass(StoreQuery q) { return null; } public Map getUpdates(StoreQuery q) { return null; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNewState.java0000644000000000000000000000502512133327272026011 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an instance that was made persistent within the * current transaction. * * @author Abe White */ @SuppressWarnings("serial") class PNewState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { if (previous == null) return; context.setLoaded(true); context.setDirty(true); context.saveFields(false); } void beforeFlush(StateManagerImpl context, boolean logical, OpCallbacks call) { context.preFlush(logical, call); } PCState commit(StateManagerImpl context) { return HOLLOW; } PCState commitRetain(StateManagerImpl context) { return PNONTRANS; } PCState rollback(StateManagerImpl context) { return TRANSIENT; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return TRANSIENT; } PCState delete(StateManagerImpl context) { context.preDelete(); if (context.isFlushed()) return PNEWFLUSHEDDELETED; return PNEWDELETED; } PCState nontransactional(StateManagerImpl context) { return error("new", context); } PCState release(StateManagerImpl context) { return error("new", context); } boolean isVersionCheckRequired(StateManagerImpl context) { return context.isFlushedDirty(); } boolean isTransactional() { return true; } boolean isPersistent() { return true; } boolean isNew() { return true; } boolean isDirty() { return true; } public String toString() { return "Persistent-New"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractLockManager.java0000644000000000000000000000451012133327272030004 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Collection; import java.util.Iterator; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.log.Log; /** * Abstract {@link LockManager} implementation. * * @author Marc Prud'hommeaux */ public abstract class AbstractLockManager implements LockManager { /** * The context against which this LockManager is operating. */ protected StoreContext ctx; /** * Runtime log to write locking messages to. */ protected Log log; public void setContext(StoreContext ctx) { this.ctx = ctx; this.log = ctx.getConfiguration().getLog (OpenJPAConfiguration.LOG_RUNTIME); } public StoreContext getContext() { return ctx; } /** * Delegates to {@link LockManager#lock} with each element of the collection */ public void lockAll(Collection sms, int level, int timeout, Object context) { for (Iterator itr = sms.iterator(); itr.hasNext();) lock((OpenJPAStateManager) itr.next(), level, timeout, context); } /** * Does nothing by default. */ public void beginTransaction() { } /** * Does nothing by default. */ public void endTransaction() { } /** * Does nothing by default. */ public void close () { } /** * Default not to skip relation field to maintain PessimisticLockManager semantics. */ public boolean skipRelationFieldLock() { return false; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryContext.java0000644000000000000000000001776012133327272026622 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Collection; import java.util.Map; import org.apache.commons.collections.map.LinkedMap; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.Constant; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; /** * A query execution context. * * @author Abe White * @since 0.4.0 */ public interface QueryContext { /** * Return the query for this context. Note that the query will be * unavailable in remote contexts, and this method may throw an exception * to that effect. */ public Query getQuery(); /** * The persistence context for the query. */ public StoreContext getStoreContext(); /** * Return the fetch configuration for this query. */ public FetchConfiguration getFetchConfiguration(); /** * Returns the operation that this query will be expected to perform. * * @see QueryOperations * @since 0.4.0 */ public int getOperation(); /** * The query language. */ public String getLanguage(); /** * The query string. */ public String getQueryString(); /** * Return the candidate collection, or null if an * extent was specified instead of a collection. */ public Collection getCandidateCollection(); /** * Return the class of the objects that this query will return, * or null if this information is not available / not relevant. */ public Class getCandidateType(); /** * Whether query results will include subclasses of the candidate class. */ public boolean hasSubclasses(); /** * Set the candidate type. */ public void setCandidateType(Class cls, boolean subs); /** * Whether the query has been marked read-only. */ public boolean isReadOnly(); /** * Whether the query has been marked read-only. */ public void setReadOnly(boolean readOnly); /** * The unique flag. */ public boolean isUnique(); /** * Specify that the query will return only 1 * result, rather than a collection. The execute method will return null * if the query result size is 0. * * @since 0.3.0 */ public void setUnique(boolean unique); /** * Affirms if this query results are distinct instance(s). * * @since 2.0.0 */ public boolean isDistinct(); /** * Scope of a mapping from the result data to its object representation. */ public Class getResultMappingScope(); /** * Name of a mapping from the result data to its object representation. */ public String getResultMappingName(); /** * Name and scope of a mapping from the result data to its object * representation. */ public void setResultMapping(Class scope, String name); /** * Returns the result class that has been set through * {@link #setResultType}, or null if none. */ public Class getResultType(); /** * Specify the type of object in which the result of evaluating this query. * * @since 0.3.0 */ public void setResultType(Class cls); /** * Return the 0-based start index for the returned results. */ public long getStartRange(); /** * Return the 0-based exclusive end index for the returned results, * or {@link Long#MAX_VALUE} for no limit. */ public long getEndRange(); /** * Set the range of results to return. * * @param start 0-based inclusive start index * @param end 0-based exclusive end index, or * {@link Long#MAX_VALUE} for no limit * @since 0.3.2 */ public void setRange(long start, long end); /** * The parameter declaration. */ public String getParameterDeclaration(); /** * Declared parameters, for query languages that use them. */ public void declareParameters(String params); /** * Return a map of parameter name to type for this query. The returned * map will iterate in the order that the parameters were declared or, * if they're implicit, used. */ public OrderedMap> getOrderedParameterTypes(); /** * Return a map of parameter name to type for this query. The returned * map will iterate in the order that the parameters were declared or, * if they're implicit, used. */ @Deprecated public LinkedMap getParameterTypes(); /** * If this query is a bulk update, return a map of the * {@link FieldMetaData}s to {@link Constant}s. */ public Map getUpdates(); /** * Whether to ignore changes in the current transaction. */ public boolean getIgnoreChanges(); /** * Return the query's compilation state. */ public Object getCompilation(); /** * If this query is not a projection but places candidate results into a * result class under an alias, return that alias. */ public String getAlias(); /** * If this query is a projection, return the projection aliases. */ public String[] getProjectionAliases(); /** * If this query is a projection, return the projection types. */ public Class[] getProjectionTypes(); /** * Return true if the query is an aggregate. */ public boolean isAggregate(); /** * Return true if the query uses grouping. */ public boolean hasGrouping(); /** * Return the classes that affect this query. */ public ClassMetaData[] getAccessPathMetaDatas(); /** * Return the filter listener for the given tag, or null. */ public FilterListener getFilterListener(String tag); /** * Return the filter listener for the given tag, or null. */ public AggregateListener getAggregateListener(String tag); /** * The set of filter listeners. */ public Collection getFilterListeners(); /** * The set of aggregate listeners. */ public Collection getAggregateListeners(); /** * Helper method to delete the objects found by executing a query on * the given executor. */ public Number deleteInMemory(StoreQuery q, StoreQuery.Executor ex, Object[] params); /** * Helper method to update the objects found by executing a query on * the given executor. */ public Number updateInMemory(StoreQuery q, StoreQuery.Executor ex, Object[] params); /** * Helper method to instantiate the class with the given name, taking * into account the query's candidate package, automatic imports, and * the given imports (if any). Returns null if the type cannot be found. */ public Class classForName(String name, String[] imports); /** * Synchronize on the query's internal lock. */ public void lock (); /** * Unlock the query's internal lock. */ public void unlock(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PDirtyState.java0000644000000000000000000000473712133327272026364 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a persistent instance that is participating in the current * transaction, and has been modified. * * @author Abe White */ @SuppressWarnings("serial") class PDirtyState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.saveFields(false); } void beforeFlush(StateManagerImpl context, boolean logical, OpCallbacks call) { context.preFlush(logical, call); } PCState commit(StateManagerImpl context) { return HOLLOW; } PCState commitRetain(StateManagerImpl context) { return PNONTRANS; } PCState rollback(StateManagerImpl context) { return HOLLOW; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return PNONTRANS; } PCState delete(StateManagerImpl context) { context.preDelete(); return PDELETED; } PCState nontransactional(StateManagerImpl context) { return error("dirty", context); } PCState release(StateManagerImpl context) { return error("dirty", context); } boolean isVersionCheckRequired(StateManagerImpl context) { return !context.isFlushed() || context.isFlushedDirty(); } PCState afterRefresh() { return PCLEAN; } PCState afterOptimisticRefresh() { return PNONTRANS; } boolean isTransactional() { return true; } boolean isPersistent() { return true; } boolean isDirty() { return true; } public String toString() { return "Persistent-Dirty"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/LocalManagedRuntime.java0000644000000000000000000001504112133327272030011 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import javax.transaction.NotSupportedException; import javax.transaction.Status; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.xa.XAResource; import org.apache.openjpa.ee.AbstractManagedRuntime; import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.StoreException; import org.apache.openjpa.util.UserException; /** * Uses a local implementation of the {@link TransactionManager} interface. * This manager is valid only for a single {@link Broker}. * It duplicates non-managed transaction control. * * @author Abe White */ class LocalManagedRuntime extends AbstractManagedRuntime implements ManagedRuntime, TransactionManager, Transaction { private static final Localizer _loc = Localizer.forPackage (LocalManagedRuntime.class); private Synchronization _broker = null; private Synchronization _factorySync = null; private boolean _active = false; private Throwable _rollbackOnly = null; /** * Constructor. Provide broker that will be requesting managed * transaction info. */ public LocalManagedRuntime(Broker broker) { _broker = broker; } public TransactionManager getTransactionManager() { return this; } public synchronized void begin() { if (_active) throw new InvalidStateException(_loc.get("active")); _active = true; } public synchronized void commit() { if (!_active) throw new InvalidStateException(_loc.get("not-active")); // try to invoke before completion in preparation for commit RuntimeException err = null; if (_rollbackOnly == null) { try { _broker.beforeCompletion(); if (_factorySync != null) _factorySync.beforeCompletion(); } catch (RuntimeException re) { _rollbackOnly = re; err = re; } } else // previously marked rollback only err = new StoreException(_loc.get("marked-rollback")). setCause(_rollbackOnly).setFatal(true); if (_rollbackOnly == null) { try { _broker.afterCompletion(Status.STATUS_COMMITTED); notifyAfterCompletion(Status.STATUS_COMMITTED); } catch (RuntimeException re) { if (err == null) err = re; } } // if we haven't managed to commit, rollback if (_active) { try { rollback(); } catch (RuntimeException re) { if (err == null) err = re; } } // throw the first exception we encountered, if any if (err != null) throw err; } public synchronized void rollback() { if (!_active) throw new InvalidStateException(_loc.get("not-active")); // rollback broker RuntimeException err = null; try { _broker.afterCompletion(Status.STATUS_ROLLEDBACK); } catch (RuntimeException re) { err = re; } // rollback synch, even if broker throws exception try { notifyAfterCompletion(Status.STATUS_ROLLEDBACK); } catch (RuntimeException re) { if (err == null) err = re; } if (err != null) throw err; } /** * Notifies the factory sync that the transaction has ended with * the given status. Clears all transaction state regardless * of any exceptions during the callback. */ private void notifyAfterCompletion(int status) { _active = false; try { if (_factorySync != null) _factorySync.afterCompletion(status); } finally { _rollbackOnly = null; _factorySync = null; } } public synchronized void setRollbackOnly() { setRollbackOnly(new UserException()); } public void setRollbackOnly(Throwable cause) { _rollbackOnly = cause; } public Throwable getRollbackCause() { return _rollbackOnly; } public synchronized int getStatus() { if (_rollbackOnly != null) return Status.STATUS_MARKED_ROLLBACK; if (_active) return Status.STATUS_ACTIVE; return Status.STATUS_NO_TRANSACTION; } public Transaction getTransaction() { return this; } public void resume(Transaction tobj) throws SystemException { throw new SystemException(NotSupportedException.class.getName()); } public void setTransactionTimeout(int sec) throws SystemException { throw new SystemException(NotSupportedException.class.getName()); } public Transaction suspend() throws SystemException { throw new SystemException(NotSupportedException.class.getName()); } public boolean delistResource(XAResource xaRes, int flag) throws SystemException { throw new SystemException(NotSupportedException.class.getName()); } public boolean enlistResource(XAResource xaRes) throws SystemException { throw new SystemException(NotSupportedException.class.getName()); } public synchronized void registerSynchronization(Synchronization sync) { if (sync == _broker) return; if (_factorySync != null) throw new InternalException(); _factorySync = sync; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/0000755000000000000000000000000012133327270024247 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Divide.java0000644000000000000000000000241012133327270026313 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; /** * Value produced by one value being divided by another. * * @author Abe White */ class Divide extends MathVal { /** * Constructor. Provide the values to divide. */ public Divide(Val val1, Val val2) { super(val1, val2); } protected Object operate(Object o1, Class c1, Object o2, Class c2) { return Filters.divide(o1, c1, o2, c2); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Param.java0000644000000000000000000000334512133327270026157 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Represents a parameter. * * @author Abe White */ class Param extends Val implements Parameter { private Object _key = null; private Class _type = null; private int _index = -1; /** * Constructor. Provide parameter name and type. */ public Param(Object key, Class type) { _key = key; _type = type; } public Object getParameterKey() { return _key; } public Class getType() { return _type; } public void setImplicitType(Class type) { _type = type; } public void setIndex(int index) { _index = index; } public Object getValue(Object[] params) { return params[_index]; } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return getValue(params); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Concat.java0000644000000000000000000000411112133327270026316 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Concatenate two strings together. * * @author Marc Prud'hommeaux */ class Concat extends Val { private final Val _val; private final Val _args; /** * Constructor. Provide target string and the arguments to the * indexOf method. */ public Concat(Val val, Val args) { _val = val; _args = args; } public Class getType() { return String.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object str = _val.eval(candidate, orig, ctx, params); StringBuilder cat = new StringBuilder(str.toString()); Object arg = _args.eval(candidate, orig, ctx, params); if (arg instanceof Object[]) { for (int i = 0; i < ((Object[]) arg).length; i++) cat.append((((Object[]) arg)[i]).toString()); } else cat.append(arg.toString()); return cat.toString(); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); _args.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/SubQ.java0000644000000000000000000000413212133327270025764 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UnsupportedException; /** * An in-memory representation of a {@link Subquery}. Currently * subqueries aren't supported for in-memory use. * * @author Abe White */ class SubQ extends Val implements Subquery { private static final Localizer _loc = Localizer.forPackage(Subquery.class); private final String _alias; private String _subqAlias = null; private Class _type = null; public SubQ(String alias) { _alias = alias; _subqAlias = alias; } public Object getSelect() { return null; } public String getCandidateAlias() { return _alias; } public void setSubqAlias(String subqAlias) { _subqAlias = subqAlias; } public String getSubqAlias() { return _subqAlias; } public void setQueryExpressions(QueryExpressions q) { } public Class getType() { return _type; } public void setImplicitType(Class type) { _type = type; } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { throw new UnsupportedException(_loc.get("in-mem-subquery")); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Any.java0000644000000000000000000000346312133327270025647 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.math.BigDecimal; import java.math.BigInteger; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UnsupportedException; /** * In-memory Any implementation. Currently unsupported since * in-memory subqueries are not supported. * * @author Marc Prud'hommeaux */ class Any extends UnaryMathVal { private static final Localizer _loc = Localizer.forPackage(Any.class); public Any(Val val) { super(val); } protected Class getType(Class c) { Class wrap = Filters.wrap(c); if (wrap == Integer.class || wrap == Float.class || wrap == Double.class || wrap == Long.class || wrap == BigDecimal.class || wrap == BigInteger.class) return c; return int.class; } protected Object operate(Object o, Class c) { throw new UnsupportedException(_loc.get("in-mem-subquery")); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Size.java0000644000000000000000000000255612133327270026034 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Map; /** * Returns the count of a collection. * * @author Marc Prud'hommeaux */ class Size extends UnaryMathVal { public Size(Val val) { super(val); } protected Class getType(Class c) { return int.class; } protected Object operate(Object o, Class c) { if (o instanceof Collection) return ((Collection) o).size(); if (o instanceof Map) return ((Map) o).size(); return (o == null) ? 0 : 1; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/TypeLit.java0000644000000000000000000000351212133327270026505 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * Represents a type literal. * * @author Catalina Wei */ class TypeLit extends Val implements Literal { private Object _val; private final int _ptype; /** * Constructor. Provide constant value. */ public TypeLit(Object val, int ptype) { _val = val; _ptype = ptype; } public Object getValue() { return _val; } public void setValue(Object val) { _val = val; } public int getParseType() { return _ptype; } public Object getValue(Object[] parameters) { return _val; } public Class getType() { return (_val == null) ? Object.class : _val.getClass(); } public void setImplicitType(Class type) { _val = Filters.convert(_val, type); } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _val; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionVisitor.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionVisitor.jav0000644000000000000000000000256712133327270030502 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Visits nodes of a query expression tree. * * @author Abe White */ public interface ExpressionVisitor { /** * Enter an expression. The expression will then invoke visits on its * components. */ public void enter(Expression exp); /** * Leave an expression. */ public void exit(Expression exp); /** * Enter a value. The value will then invoke visits on its components. */ public void enter(Value val); /** * Leave a value. */ public void exit(Value val); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java0000644000000000000000000000504212133327270026007 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.XMLMetaData; /** * A path represents a traversal into fields of a candidate object. * Equivalent paths should compare equal. * * @author Abe White */ public interface Path extends Value { /** * Traverse into the given field of the current object, and update * the current object to that field value. * * @param nullTraversal if true, allow traversal through a null field */ public void get(FieldMetaData field, boolean nullTraversal); /** * Return the last field in the path, or null if the path does not * not contain a final field. */ public FieldMetaData last(); /** * Traverse into the given field that maps to xml column, and update * the current object to that field value. * * @param fmd field maps to xml column * @param meta associated xml mapping */ public void get(FieldMetaData fmd, XMLMetaData meta); /** * Traverse into the gevin xpath name of the current object, and update * the current object to that xpath field. * * @param meta * @param name */ public void get(XMLMetaData meta, String name); /** * Return the current XPath's xmlmapping metadata. * @return Return xmlmapping */ public XMLMetaData getXmlMapping(); /** * Set the schema alias (the identification variable) * this path is begin with. * @param schemaAlias */ public void setSchemaAlias(String schemaAlias); public String getSchemaAlias(); public void setSubqueryContext(Context context, String correlationVar); public String getCorrelationVar(); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/EndsWithExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/EndsWithExpression.ja0000644000000000000000000000243512133327270030374 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Expression that compares two others. * * @author Abe White */ class EndsWithExpression extends CompareExpression { /** * Constructor. Supply values to compare. */ public EndsWithExpression(Val val1, Val val2) { super(val1, val2); } protected boolean compare(Object o1, Object o2) { if (o1 == null || o2 == null) return false; return o1.toString().endsWith(o2.toString()); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/package.html0000644000000000000000000000153312133327270026532 0ustar

    OpenJPA Expression Tree

    openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Null.java0000644000000000000000000000233312133327270026025 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Represents the null constant. * * @author Abe White */ class Null extends Val { public Class getType() { return Object.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Index.java0000644000000000000000000000264112133327270026164 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UnsupportedException; /** * Returns the index of a value within a collection/map. * * @author Catalina Wei */ class Index extends UnaryMathVal { private static final Localizer _loc = Localizer.forPackage(Index.class); /** * Constructor. */ public Index(Val val) { super(val); } public Class getType(Class c) { return int.class; } protected Object operate(Object o, Class c) { throw new UnsupportedException(_loc.get("in-mem-index")); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/IsEmptyExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/IsEmptyExpression.jav0000644000000000000000000000441212133327270030424 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Map; import org.apache.openjpa.kernel.StoreContext; /** * Expression to test for an empty Collection. * * @author Abe White */ class IsEmptyExpression extends Exp { private final Val _val; /** * Constructor. Provide collection/map value to test. */ public IsEmptyExpression(Val val) { _val = val; } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object obj = _val.eval(candidate, orig, ctx, params); if (obj == null) return true; if (obj instanceof Collection) return ((Collection) obj).isEmpty(); if (obj instanceof Map) return ((Map) obj).isEmpty(); return false; } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { Collection c = _val.eval(candidates, null, ctx, params); if (c == null || c.isEmpty()) return false; Object obj = c.iterator().next(); if (obj == null) return true; if (obj instanceof Collection) return ((Collection) obj).isEmpty(); if (obj instanceof Map) return ((Map) obj).isEmpty(); return false; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AggregateVal.java0000644000000000000000000000531412133327270027446 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Collections; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * An aggregate of some value. * * @author Abe White */ abstract class AggregateVal extends Val { private static final Localizer _loc = Localizer.forPackage (AggregateVal.class); private final Val _val; /** * Constructor. Supply value to aggregate. */ public AggregateVal(Val val) { _val = val; } public boolean isAggregate() { return true; } public Class getType() { return getType(_val.getType()); } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { if (candidate == null) candidate = Collections.EMPTY_LIST; // allow aggregates to be used in filter expressions so long as a // collection is passed in if (candidate instanceof Collection) return eval((Collection) candidate, orig, ctx, params). iterator().next(); throw new UserException(_loc.get("agg-in-filter")); } protected Collection eval(Collection candidates, Object orig, StoreContext ctx, Object[] params) { Collection args = _val.eval(candidates, orig, ctx, params); return Collections.singleton(operate(args, _val.getType())); } /** * Return the type of this aggregate based on the value type. */ protected abstract Class getType(Class c); /** * Aggregate the given values. */ protected abstract Object operate(Collection os, Class c); public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AggregateListener.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AggregateListener.jav0000644000000000000000000000474612133327270030360 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.io.Serializable; import java.util.Collection; import org.apache.openjpa.kernel.StoreContext; /** * An aggregate listener aggregates data produced by an ExpressionQuery. * * @author Abe White * @author Patrick Linskey */ public interface AggregateListener extends Serializable { /** * Return the tag that this listener listens for. */ public String getTag(); /** * Return whether this function expects to act on arguments. Some * function may not need arguments; for example, a function to count the * number of objects that match a given filter might be of the form: * count(). */ public boolean expectsArguments(); /** * Return the value of this aggregate. * * @param args for each candidate, the value of the arguments to * the function; will be null if this aggregate does * not expect an argument; if this function has * multiple arguments, each element will be an array * @param argClasses the expected class of each argument element * @param candidates the candidate objects being evaluated * @param ctx the persistence context * @return the value of the aggregate * @throws org.apache.openjpa.util.UserException if this aggregate does not * support in-memory operation */ public Object evaluate(Collection args, Class[] argClasses, Collection candidates, StoreContext ctx); /** * Return the expected type of the result of this listener. * * @param argClasses the expected classes of the argument, or null if * no arguments */ public Class getType(Class[] argClasses); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Trim.java0000644000000000000000000000467012133327270026034 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Trims leading, trailing, or both charactes from a String. * * @author Marc Prud'hommeaux */ class Trim extends Val { private final Val _val; private final Val _trimChar; private final Boolean _where; /** * Constructor. Provide value to upper-case. */ public Trim(Val val, Val trimChar, Boolean where) { _val = val; _trimChar = trimChar; _where = where; } public Class getType() { return String.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object eval = _val.eval(candidate, orig, ctx, params); if (eval == null) return null; String toTrim = _trimChar.eval(candidate, orig, ctx, params). toString(); String str = eval.toString(); // null indicates both, TRUE indicates leading if (_where == null || Boolean.TRUE.equals(_where)) { while (str.startsWith(toTrim)) str = str.substring(toTrim.length()); } // null indicates both, FALSE indicates trailing if (_where == null || Boolean.FALSE.equals(_where)) { while (str.endsWith(toTrim)) str = str.substring(0, str.length() - toTrim.length()); } return str; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); _trimChar.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CurrentDate.java0000644000000000000000000000305112133327270027331 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Date; import org.apache.openjpa.kernel.StoreContext; /** * Represents the current date. * * @author Marc Prud'hommeaux */ class CurrentDate extends Val { private final Class _type; public CurrentDate(Class type) { _type = type; } public Class getType() { return _type; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { try { _type.getConstructor(long.class).newInstance(System.currentTimeMillis()); } catch (Exception e) { return new Date(); } return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java0000644000000000000000000001514112133327270030464 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Stack; import org.apache.openjpa.kernel.QueryOperations; import org.apache.openjpa.kernel.ResultShape; import org.apache.openjpa.kernel.StoreQuery; import org.apache.openjpa.kernel.exps.Context; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; /** * Struct to hold the state of a parsed expression query. * * @author Abe White * @since 0.3.2 * @nojavadoc */ @SuppressWarnings("serial") public class QueryExpressions implements Serializable { public static final int DISTINCT_AUTO = 2 << 0; public static final int DISTINCT_TRUE = 2 << 1; public static final int DISTINCT_FALSE = 2 << 2; public static final Value[] EMPTY_VALUES = new Value[0]; /** * Map of {@link FieldMetaData},{@link Value} for update statements. */ public Map updates = Collections.emptyMap(); public int distinct = DISTINCT_AUTO; public String alias = null; public Value[] projections = EMPTY_VALUES; public String[] projectionClauses = StoreQuery.EMPTY_STRINGS; public String[] projectionAliases = StoreQuery.EMPTY_STRINGS; public Class resultClass = null; public Expression filter = null; public Value[] grouping = EMPTY_VALUES; public String[] groupingClauses = StoreQuery.EMPTY_STRINGS; public Expression having = null; public Value[] ordering = EMPTY_VALUES; public boolean[] ascending = StoreQuery.EMPTY_BOOLEANS; public String[] orderingClauses = StoreQuery.EMPTY_STRINGS; public String[] orderingAliases = StoreQuery.EMPTY_STRINGS; public OrderedMap> parameterTypes = StoreQuery.EMPTY_ORDERED_PARAMS; public int operation = QueryOperations.OP_SELECT; public ClassMetaData[] accessPath = StoreQuery.EMPTY_METAS; public String[] fetchPaths = StoreQuery.EMPTY_STRINGS; public String[] fetchInnerPaths = StoreQuery.EMPTY_STRINGS; public Value[] range = EMPTY_VALUES; private Boolean _aggregate = null; private Stack _contexts = null; public Object state; public ResultShape shape; public boolean hasInExpression; /** * Set reference to the JPQL query contexts. * @param contexts */ public void setContexts(Stack contexts) { _contexts = contexts; } /** * Returns the current JPQL query context. * @return */ public Context ctx() { return _contexts.peek(); } /** * Whether this is an aggregate results. */ public boolean isAggregate() { if (projections.length == 0) return false; if (_aggregate == null) _aggregate = (AggregateExpressionVisitor.isAggregate(projections)) ? Boolean.TRUE : Boolean.FALSE; return _aggregate.booleanValue(); } public boolean isDistinct() { return distinct != DISTINCT_FALSE; } /** * Gets the fields that are bound to parameters. * * @return empty if the query has no filtering condition or no parameters. */ public List getParameterizedFields() { return ParameterExpressionVisitor.collectParameterizedFields(filter); } /** * Add an update. */ public void putUpdate(Path path, Value val) { if (updates == Collections.EMPTY_MAP) updates = new LinkedHashMap(); updates.put(path, val); } /** * Visitor to determine whether our projections are aggregates. */ private static class AggregateExpressionVisitor extends AbstractExpressionVisitor { private Value _sub = null; private boolean _agg = false; /** * Return whether the given values include projections. */ public static boolean isAggregate(Value[] vals) { if (vals.length == 0) return false; AggregateExpressionVisitor v = new AggregateExpressionVisitor(); for (int i = 0; i < vals.length && !v._agg; i++) vals[i].acceptVisit(v); return v._agg; } public void enter(Value val) { if (_agg) return; if (_sub == null) { if (val.isAggregate()) _agg = true; } else if (val instanceof Subquery) _sub = val; } public void exit(Value val) { if (val == _sub) _sub = null; } } /** * Visits the expression tree to find the parameter nodes. * @author Pinaki Poddar * */ private static class ParameterExpressionVisitor extends AbstractExpressionVisitor { private FieldMetaData _parameterized; private List _collected = new ArrayList(); /** * Enters the current node. */ public void enter(Value val) { if (val instanceof Parameter) { if (_parameterized != null) { _collected.add(_parameterized); } } else if (val instanceof Path) { _parameterized = ((Path)val).last(); } else { _parameterized = null; } } public static List collectParameterizedFields(Expression e) { if (e == null) { return Collections.emptyList(); } ParameterExpressionVisitor visitor = new ParameterExpressionVisitor(); e.acceptVisit(visitor); return visitor._collected; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/SimpleCase.java0000644000000000000000000000722212133327270027142 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * An in-memory representation of a simple case expression * * @author Catalina Wei */ public class SimpleCase extends Val { private final Val _caseOperand; private final Exp[] _exp; private final Val _val; SimpleCase(Val caseOperand, Exp[] exp, Val val) { _caseOperand = caseOperand; _exp = exp; _val = val; } @Override protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object o1 = _caseOperand.eval(candidate, orig, ctx, params); for (int i = 0; i < _exp.length; i++) { Object o2 = ((WhenScalar) _exp[i]).getVal1(). eval(candidate, orig, ctx, params); if (o1 != null && o2 != null) { Class c = Filters.promote(o1.getClass(), o2.getClass()); o1 = Filters.convert(o1, c); o2 = Filters.convert(o2, c); } if (compare(o1, o2)) return ((WhenScalar) _exp[i]).getVal2(). eval(candidate, orig, ctx, params); else continue; } return _val.eval(candidate, orig, ctx, params); } protected Object eval(Object candidate,StoreContext ctx, Object[] params) { Object o1 = _caseOperand.eval(candidate, null, ctx, params); for (int i = 0; i < _exp.length; i++) { Object o2 = ((WhenScalar) _exp[i]).getVal1(). eval(candidate, null, ctx, params); if (o1 != null && o2 != null) { Class c = Filters.promote(o1.getClass(), o2.getClass()); o1 = Filters.convert(o1, c); o2 = Filters.convert(o2, c); } if (compare(o1, o2)) return ((WhenScalar) _exp[i]).getVal2(). eval(candidate, null, ctx, params); else continue; } return _val.eval(candidate, null, ctx, params); } /** * Compare the two values. */ protected boolean compare(Object o1, Object o2) { return (o1 == null && o2 == null) || (o1 != null && o1.equals(o2)); } public Class getType() { Class c1 = _val.getType(); for (int i = 0; i < _exp.length; i++) { Class c2 = ((WhenScalar) _exp[i]).getVal1().getType(); c1 = Filters.promote(c1, c2); } return c1; } public void setImplicitType(Class type) { } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _caseOperand.acceptVisit(visitor); for (int i = 0; i < _exp.length; i++) _exp[i].acceptVisit(visitor); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionParser.java0000644000000000000000000000422612133327270030432 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.io.Serializable; import org.apache.openjpa.kernel.ExpressionStoreQuery; import org.apache.openjpa.meta.ClassMetaData; /** * Parser for query languages that will be used by a {@link ExpressionQuery}. * A QueryParser is responsible for translating from some string-based query * language into {@link Expression}s. Parsers should be stateless. * * @author Marc Prud'hommeaux * @nojavadoc */ public interface ExpressionParser extends Serializable { /** * Return a string key describing the language that this instance parses. */ public String getLanguage(); /** * Return a parsed intermediate form of the given query string. */ public Object parse(String ql, ExpressionStoreQuery query); /** * Use the parsed query form to set information such as candidate type, * result type, etc that was encoded in the query string. */ public void populate(Object parsed, ExpressionStoreQuery query); /** * Parse the given query string. */ public QueryExpressions eval(Object parsed, ExpressionStoreQuery query, ExpressionFactory factory, ClassMetaData candidate); /** * Parse the given value clauses. */ public Value[] eval(String[] vals, ExpressionStoreQuery query, ExpressionFactory factory, ClassMetaData candidate); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/WhenCondition.java0000644000000000000000000000254012133327270027663 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; public class WhenCondition extends Exp { private final Exp _exp; private final Val _val; /** * Constructor. */ WhenCondition(Exp exp, Val val) { _exp = exp; _val = val; } public Exp getExp() { return _exp; } public Val getVal() { return _val; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _exp.acceptVisit(visitor); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Coalesce.java0000644000000000000000000000530612133327270026634 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * An in-memory representation of a coalesce expression * * @author Catalina Wei */ public class Coalesce extends Val { private final Val[] _val; /** * Constructor. */ Coalesce(Val[] val) { _val = val; } @Override protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { for (int i = 0; i < _val.length-1; i++) { Object o1 = _val[i].eval(candidate, orig, ctx, params); if (o1 != null) return o1; else continue; } return _val[_val.length-1].eval(candidate, orig, ctx, params); } protected Object eval(Object candidate, StoreContext ctx, Object[] params) { for (int i = 0; i < _val.length-1; i++) { Object o1 = _val[i].eval(candidate, null, ctx, params); if (o1 != null) return o1; else continue; } return _val[_val.length-1].eval(candidate, null, ctx, params); } /** * Compare the two values. */ protected boolean compare(Object o1, Object o2) { return (o1 == null && o2 == null) || (o1 != null && o1.equals(o2)); } public Val[] getVal() { return _val; } public Class getType() { Class c1 = _val[0].getType(); for (int i = 1; i < _val.length; i++) { Class c2 = _val[i].getType(); c1 = Filters.promote(c1, c2); } return c1; } public void setImplicitType(Class type) { } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); for (int i = 0; i < _val.length; i++) _val[i].acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Constant.java0000644000000000000000000000212212133327270026700 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Interface for any query constant value. * * @author Marc Prud'hommeaux */ public interface Constant { /** * Return the value for this constant given the specified parameters. */ public Object getValue(Object[] parameters); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Context.java0000644000000000000000000001373312133327270026545 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.ParsedJPQL; import org.apache.openjpa.meta.ClassMetaData; /** * JPQL / Criteria Query Context * @since 2.0 * */ public class Context implements Serializable { public final ParsedJPQL parsed; public ClassMetaData meta; public String schemaAlias; public Subquery subquery; public Expression from = null; public Context cloneFrom = null; private final Context parent; private List subsels = null; private Object select = null; protected int aliasCount = -1; private Map variables = new HashMap(); private Map schemas = new HashMap(); public Context(ParsedJPQL parsed, Subquery subquery, Context parent) { this.parsed = parsed; this.subquery = subquery; this.parent = parent; if (subquery != null) { this.select = subquery.getSelect(); parent.addSubselContext(this); } } public void setSubquery(Subquery subquery) { this.subquery = subquery; this.select = subquery.getSelect(); parent.addSubselContext(this); } public ClassMetaData meta() { return meta; } public String schemaAlias() { return schemaAlias; } public Subquery subquery() { return subquery; } /** * Returns next table alias to be created. * @return */ public int nextAlias() { Context p = this; while (p.subquery != null) { p = p.parent; } p.aliasCount++; return p.aliasCount; } /** * Reset alias count for prepared query cache * */ public void resetAliasCount() { Context p = this; while (p.subquery != null) { p = p.parent; } p.aliasCount = -1; } /** * Register the select for this context. * @param select */ public void setSelect(Object select) { this.select = select; } /** * Returns the select associated with this context. * @return */ public Object getSelect() { return select; } /** * Register the subquery context in this context. * @param sub */ public void addSubselContext(Context sub) { if (sub == null) return; if (subsels == null) subsels = new ArrayList(); subsels.add(sub); } /** * Returns the subquery context. * @return */ public List getSubselContexts() { return subsels; } /** * Returns the subquery in this context. * @return */ public Subquery getSubquery() { return subquery; } public Context getParent() { return parent; } public void addVariable(String id, Value var) { variables.put(id.toLowerCase(), var); } public Map getVariables() { return variables; } public void setVariables(Map variables) { this.variables = variables; } public void addSchema(String id, ClassMetaData meta) { schemas.put(id.toLowerCase(), meta); } public ClassMetaData getSchema(String id) { if (id != null) return schemas.get(id.toLowerCase()); return null; } public Map getSchemas() { return schemas; } public void setSchemas(Map schemas) { this.schemas = schemas; } /** * Given an alias and return its associated variable. * @param alias * @return */ public Value getVariable(String alias) { Value variable = alias == null ? null : variables.get(alias.toLowerCase()); return variable; } /** * Given an alias find the context of its associated * variable where it is defined. * @param alias * @return */ public Context findContext(String alias) { Value var = getVariable(alias); if (var != null) return this; for (Context p = parent; p != null; ) { var = p.getVariable(alias); if (var != null) return p; p = p.parent; } if (subsels != null) { for (Context subsel : subsels) { if (subsel != null) { var = subsel.getVariable(alias); if (var != null) return subsel; } } } return null; } /** * Given an alias find the variable in JPQL contexts. * @param alias * @return */ public Value findVariable(String alias) { Value var = getVariable(alias); if (var != null) return var; for (Context p = parent; p != null; ) { var = p.getVariable(alias); if (var != null) return var; p = p.parent; } return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Exp.java0000644000000000000000000000457512133327270025661 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import org.apache.openjpa.kernel.StoreContext; /** * An in-memory representation of an {@link Expression}. * * @author Abe White */ public class Exp implements Expression { /** * Evaluate the expression for the given candidate. */ public final boolean evaluate(Object candidate, Object orig, StoreContext ctx, Object[] params) { try { return eval(candidate, candidate, ctx, params); } catch (ClassCastException cce) { return false; } catch (NullPointerException npe) { return false; } } /** * Evaluate the expression for the given candidate group. */ public final boolean evaluate(Collection candidates, StoreContext ctx, Object[] params) { try { return eval(candidates, ctx, params); } catch (ClassCastException cce) { return false; } catch (NullPointerException npe) { return false; } } /** * Evaluate the expression for the given context candidate and original * candidate. */ protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return true; } /** * Evaluate the expression for the given group. */ protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { return true; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Distinct.java0000644000000000000000000000412612133327270026676 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import org.apache.openjpa.kernel.StoreContext; /** * A distinct set of the specified values. * * @author Marc Prud'hommeaux */ class Distinct extends Val { private final Val _val; /** * Constructor. Supply value to aggregate. */ public Distinct(Val val) { _val = val; } public Class getType() { return Collection.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { if (candidate == null) candidate = Collections.EMPTY_LIST; Collection arg = candidate instanceof Collection ? (Collection) candidate : Collections.singleton(candidate); return eval(arg, orig, ctx, params).iterator().next(); } protected Collection eval(Collection candidates, Object orig, StoreContext ctx, Object[] params) { Collection args = _val.eval(candidates, orig, ctx, params); return new HashSet(args); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/WhenScalar.java0000644000000000000000000000255012133327270027143 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; public class WhenScalar extends Exp { private final Val _val1; private final Val _val2; /** * Constructor. */ WhenScalar(Val val1, Val val2) { _val1 = val1; _val2 = val2; } public Val getVal1() { return _val1; } public Val getVal2() { return _val2; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val1.acceptVisit(visitor); _val2.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Resolver.java0000644000000000000000000000400312133327270026710 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.QueryContext; /** * A Resolver is used to resolve listeners and class or entity names * that appear in a query. * * @author Abe White * @nojavadoc */ public interface Resolver { /** * Resolve the type represented by the given class name. This will * test the type against the namespace of the Query and the declared * imports, and will properly handle primitives and java.lang types * as well. Returns null if the name does not match a known type. */ public Class classForName(String name, String[] imports); /** * Return the filter listener for the given tag, or null if none. */ public FilterListener getFilterListener(String tag); /** * Return the function listener for the given tag, or null if none. */ public AggregateListener getAggregateListener(String tag); /** * Return the OpenJPA configuration. */ public OpenJPAConfiguration getConfiguration (); /** * The {@link QueryContext} for which this resolver was created * * @since 1.1.0 */ public QueryContext getQueryContext(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Sum.java0000644000000000000000000000341712133327270025663 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Iterator; import org.apache.openjpa.kernel.Filters; /** * Sum values. * * @author Abe White */ class Sum extends AggregateVal { /** * Constructor. Provide the value to sum. */ public Sum(Val val) { super(val); } protected Class getType(Class c) { Class wrap = Filters.wrap(c); if (wrap == Integer.class || wrap == Short.class || wrap == Byte.class) return long.class; return c; } protected Object operate(Collection os, Class c) { if (os.isEmpty()) return null; Class type = getType(c); Object sum = Filters.convert(0, type); Object cur; for (Iterator itr = os.iterator(); itr.hasNext();) { cur = itr.next(); if (cur != null) sum = Filters.add(sum, type, cur, c); } return sum; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/MathVal.java0000644000000000000000000000417412133327270026454 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * Value produced by a mathematical operation on two values. * * @author Abe White */ abstract class MathVal extends Val { private final Val _val1; private final Val _val2; /** * Constructor. Provide the values to operate on. */ public MathVal(Val val1, Val val2) { _val1 = val1; _val2 = val2; } public Class getType() { Class c1 = _val1.getType(); Class c2 = _val2.getType(); return Filters.promote(c1, c2); } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object o1 = _val1.eval(candidate, orig, ctx, params); Object o2 = _val2.eval(candidate, orig, ctx, params); return operate(o1, _val1.getType(), o2, _val2.getType()); } /** * Return the result of this mathematical operation on the two values. */ protected abstract Object operate(Object o1, Class c1, Object o2, Class c2); public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val1.acceptVisit(visitor); _val2.acceptVisit(visitor); visitor.exit(this); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ContainsExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ContainsExpression.ja0000644000000000000000000000521312133327270030422 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Collections; import org.apache.openjpa.kernel.StoreContext; /** * Tests that a Collection contains a value. * * @author Abe White */ class ContainsExpression extends Exp { private final Val _val1; private final Val _val2; /** * Constructor. * * @param val1 the container value * @param val2 the containee to test */ public ContainsExpression(Val val1, Val val2) { _val1 = val1; _val2 = val2; } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object obj = _val1.eval(candidate, orig, ctx, params); Collection coll = getCollection(obj); return coll != null && !coll.isEmpty() && coll.contains(_val2.eval(candidate, orig, ctx, params)); } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { Collection coll = _val1.eval(candidates, null, ctx, params); if (coll == null || coll.isEmpty()) return false; coll = getCollection(coll.iterator().next()); if (coll == null || coll.isEmpty()) return false; Collection coll2 = _val2.eval(candidates, null, ctx, params); if (coll2 == null || coll2.isEmpty()) return false; return coll.contains(coll2.iterator().next()); } /** * Return the container collection for the given value. */ protected Collection getCollection(Object obj) { return obj instanceof Collection ? (Collection) obj : Collections.singleton(obj); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val1.acceptVisit(visitor); _val2.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Subquery.java0000644000000000000000000000262612133327270026737 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Query value representing a subquery. * * @author Abe White * @since 0.3.2 */ public interface Subquery extends Value { /** * Return the candidate alias for this subquery. */ public String getCandidateAlias(); /* * Set the candidate alias for this subquery. */ public void setSubqAlias(String subqAlias); /* * Return the subqAlias */ public String getSubqAlias(); /** * Set the parsed subquery. */ public void setQueryExpressions(QueryExpressions query); public Object getSelect(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Parameter.java0000644000000000000000000000221712133327270027034 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * A query parameter. * * @author Abe White * @nojavadoc */ public interface Parameter extends Value, Constant { /** * Set the index of this parameter. */ public void setIndex(int index); /** * Returns the key of the parameter. */ public Object getParameterKey(); } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ContainsKeyExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ContainsKeyExpression0000644000000000000000000000254112133327270030503 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Map; /** * Tests that a Map key set contains a value. * * @author Abe White */ class ContainsKeyExpression extends ContainsExpression { /** * Constructor. * * @param val1 the container value * @param val2 the containee to test */ public ContainsKeyExpression(Val val1, Val val2) { super(val1, val2); } protected Collection getCollection(Object obj) { return (obj == null) ? null : ((Map) obj).keySet(); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/LessThanEqualExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/LessThanEqualExpressi0000644000000000000000000000245212133327270030431 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Expression that compares two others. * * @author Abe White */ class LessThanEqualExpression extends CompareExpression { /** * Constructor. Supply values to compare. */ public LessThanEqualExpression(Val val1, Val val2) { super(val1, val2); } protected boolean compare(Object o1, Object o2) { if (!(o1 instanceof Comparable)) return false; return ((Comparable) o1).compareTo(o2) <= 0; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GetMapValue.java0000644000000000000000000000321512133327270027265 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Map; import org.apache.openjpa.kernel.StoreContext; /** * Returns the value of the specified key in a Map. * * @author Marc Prud'hommeaux */ class GetMapValue extends Val { private final Val _map; private final Val _arg; /** * Constructor. Provide value to upper-case. */ public GetMapValue(Val map, Val arg) { _map = map; _arg = arg; } public boolean isVariable() { return false; } public Class getType() { return Object.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return ((Map) _map.eval(candidate, orig, ctx, params)). get(_arg.eval(candidate, orig, ctx, params)); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ToLowerCase.java0000644000000000000000000000311412133327270027300 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Lower-case a string. * * @author Abe White */ class ToLowerCase extends Val { private final Val _val; /** * Constructor. Provide value to upper-case. */ public ToLowerCase(Val val) { _val = val; } public Class getType() { return String.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _val.eval(candidate, orig, ctx, params).toString().toLowerCase(); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/EqualExpression.java0000644000000000000000000000237212133327270030245 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Expression that compares two others. * * @author Abe White */ class EqualExpression extends CompareExpression { /** * Constructor. Supply values to compare. */ public EqualExpression(Val val1, Val val2) { super(val1, val2); } protected boolean compare(Object o1, Object o2) { return (o1 == null && o2 == null) || (o1 != null && o1.equals(o2)); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Literal.java0000644000000000000000000000336212133327270026512 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Interface for any literal value. * * @author Abe White * @nojavadoc */ public interface Literal extends Value, Constant { public static final int TYPE_UNKNOWN = 0; public static final int TYPE_NUMBER = 1; public static final int TYPE_BOOLEAN = 2; public static final int TYPE_STRING = 3; public static final int TYPE_SQ_STRING = 4; // single-quoted string public static final int TYPE_CLASS = 5; public static final int TYPE_ENUM = 6; public static final int TYPE_COLLECTION = 7; public static final int TYPE_DATE = 8; public static final int TYPE_TIME = 9; public static final int TYPE_TIMESTAMP = 10; /** * The value of this literal. */ public Object getValue(); /** * The value of this literal. */ public void setValue(Object val); /** * The type the literal was parsed as. */ public int getParseType(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Avg.java0000644000000000000000000000333012133327270025626 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Iterator; import org.apache.openjpa.kernel.Filters; /** * Average values. * * @author Abe White */ class Avg extends AggregateVal { /** * Constructor. Provide the value to average. */ public Avg(Val val) { super(val); } protected Class getType(Class c) { return c; } protected Object operate(Collection os, Class c) { if (os.isEmpty()) return null; Object sum = Filters.convert(0, c); Object cur; int size = 0; for (Iterator itr = os.iterator(); itr.hasNext();) { cur = itr.next(); if (cur == null) continue; sum = Filters.add(sum, c, cur, c); size++; } if (size == 0) return null; return Filters.divide(sum, c, size, int.class); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CompareExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CompareExpression.jav0000644000000000000000000000526712133327270030431 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * Expression that compares two others. * * @author Abe White */ abstract class CompareExpression extends Exp { private final Val _val1; private final Val _val2; /** * Constructor. Supply values to compare. */ public CompareExpression(Val val1, Val val2) { _val1 = val1; _val2 = val2; } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object o1 = _val1.eval(candidate, orig, ctx, params); Object o2 = _val2.eval(candidate, orig, ctx, params); if (o1 != null && o2 != null) { Class c = Filters.promote(o1.getClass(), o2.getClass()); o1 = Filters.convert(o1, c); o2 = Filters.convert(o2, c); } return compare(o1, o2); } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { Collection c1 = _val1.eval(candidates, null, ctx, params); Collection c2 = _val2.eval(candidates, null, ctx, params); Object o1 = (c1 == null || c1.isEmpty()) ? null : c1.iterator().next(); Object o2 = (c2 == null || c2.isEmpty()) ? null : c2.iterator().next(); if (o1 != null && o2 != null) { Class c = Filters.promote(o1.getClass(), o2.getClass()); o1 = Filters.convert(o1, c); o2 = Filters.convert(o2, c); } return compare(o1, o2); } /** * Compare the two values. */ protected abstract boolean compare(Object o1, Object o2); public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val1.acceptVisit(visitor); _val2.acceptVisit(visitor); visitor.exit(this); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GreaterThanEqualExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GreaterThanEqualExpre0000644000000000000000000000246012133327270030374 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Expression that compares two others. * * @author Abe White */ class GreaterThanEqualExpression extends CompareExpression { /** * Constructor. Supply values to compare. */ public GreaterThanEqualExpression(Val val1, Val val2) { super(val1, val2); } protected boolean compare(Object o1, Object o2) { if (!(o1 instanceof Comparable)) return false; return ((Comparable) o1).compareTo(o2) >= 0; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/MatchesExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/MatchesExpression.jav0000644000000000000000000000515712133327270030425 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.SimpleRegex; import serp.util.Strings; /** * Expression that compares two others. * * @author Abe White */ class MatchesExpression extends CompareExpression { private static final Localizer _loc = Localizer.forPackage( MatchesExpression.class); private final String _single; private final String _multi; private final boolean _affirmation; /** * Constructor. Supply values to compare. */ public MatchesExpression(Val val1, Val val2, String single, String multi, String escape, boolean affirmation) { super(val1, val2); _single = single; _multi = multi; if (escape != null) throw new IllegalArgumentException(_loc.get( "escape-for-inmem-query-not-supported").getMessage()); _affirmation = affirmation; } protected boolean compare(Object o1, Object o2) { if (o1 == null || o2 == null) return false; // case insensitive? String str = o2.toString(); int idx = str.indexOf("(?i)"); boolean uncase = false; if (idx != -1) { uncase = true; if (idx + 4 < str.length()) str = str.substring(0, idx) + str.substring(idx + 4); else str = str.substring(0, idx); } // now translate from the single and multi character escape // sequences into an escape that conforms to the regexp syntax str = Strings.replace(str, _multi, ".*"); str = Strings.replace(str, _single, "."); SimpleRegex re = new SimpleRegex(str, uncase); boolean matches = re.matches(o1.toString()); return _affirmation ? matches : !matches; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Min.java0000644000000000000000000000277212133327270025645 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Iterator; /** * Find the min. * * @author Abe White */ class Min extends AggregateVal { /** * Constructor. Provide the value to minimize. */ public Min(Val val) { super(val); } protected Class getType(Class c) { return c; } protected Object operate(Collection os, Class c) { Comparable min = null; Comparable cur; for (Iterator itr = os.iterator(); itr.hasNext();) { cur = (Comparable) itr.next(); if (cur != null && (min == null || min.compareTo(cur) > 0)) min = cur; } return min; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ContainsValueExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ContainsValueExpressi0000644000000000000000000000255612133327270030500 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Map; /** * Tests that a Map value collection contains a value. * * @author Abe White */ class ContainsValueExpression extends ContainsExpression { /** * Constructor. * * @param val1 the container value * @param val2 the containee to test */ public ContainsValueExpression(Val val1, Val val2) { super(val1, val2); } protected Collection getCollection(Object obj) { return (obj == null) ? null : ((Map) obj).values(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Count.java0000644000000000000000000000262412133327270026206 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Iterator; /** * Count non-null values. * * @author Abe White */ class Count extends AggregateVal { /** * Constructor. Provide the value to count. */ public Count(Val val) { super(val); } protected Class getType(Class c) { return long.class; } protected Object operate(Collection os, Class c) { long count = 0; for (Iterator itr = os.iterator(); itr.hasNext();) if (itr.next() != null) count++; return count; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BindKeyVariableExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BindKeyVariableExpres0000644000000000000000000000263612133327270030363 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Map; /** * {@link BindVariableExpression} for map key sets. * * @author Abe White */ class BindKeyVariableExpression extends BindVariableExpression { /** * Constructor. * * @param var the bound variable * @param val the value the variable is bound to */ public BindKeyVariableExpression(BoundVariable var, Val val) { super(var, val); } protected Collection getCollection(Object values) { Map map = (Map) values; return (map == null) ? null : map.keySet(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBui0000644000000000000000000004671012133327270030465 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.StringDistance; import org.apache.openjpa.lib.util.Localizer.Message; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.XMLMetaData; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.UserException; import serp.util.Strings; /** * Abstract base class to help build expressions. Provides * generic language-independent support for variable resolution, * path traversal, and error messages. * * @author Marc Prud'hommeaux * @nojavadoc */ public abstract class AbstractExpressionBuilder { // used for error messages protected static final int EX_USER = 0; protected static final int EX_FATAL = 1; protected static final int EX_UNSUPPORTED = 2; // common implicit type settings public static final Class TYPE_OBJECT = Object.class; public static final Class TYPE_STRING = String.class; public static final Class TYPE_CHAR_OBJ = Character.class; public static final Class TYPE_NUMBER = Number.class; public static final Class TYPE_COLLECTION = Collection.class; public static final Class TYPE_MAP = Map.class; // contains types for setImplicitTypes public static final int CONTAINS_TYPE_ELEMENT = 1; public static final int CONTAINS_TYPE_KEY = 2; public static final int CONTAINS_TYPE_VALUE = 3; private static final Localizer _loc = Localizer.forPackage (AbstractExpressionBuilder.class); protected final Resolver resolver; protected ExpressionFactory factory; private final Set _accessPath = new HashSet(); private Map _seenVars = null; private Set _boundVars = null; /** * Constructor. * * @param factory the expression factory to use * @param resolver used to resolve variables, parameters, and class * names used in the query */ public AbstractExpressionBuilder(ExpressionFactory factory, Resolver resolver) { this.factory = factory; this.resolver = resolver; } /** * Returns the class loader that should be used for resolving * class names (in addition to the resolver in the query). */ protected abstract ClassLoader getClassLoader(); /** * Create a proper parse exception for the given reason. */ protected OpenJPAException parseException(int e, String token, Object[] args, Exception nest) { String argStr; if (args == null) argStr = getLocalizer().get(token).getMessage(); else argStr = getLocalizer().get(token, args).getMessage(); Message msg = _loc.get("parse-error", argStr, currentQuery()); switch (e) { case EX_FATAL: throw new InternalException(msg, nest); case EX_UNSUPPORTED: throw new UnsupportedException(msg, nest); default: throw new UserException(msg, nest); } } /** * Register the specified metadata as being in the query's access path. */ protected ClassMetaData addAccessPath(ClassMetaData meta) { _accessPath.add(meta); return meta; } /** * Return the recorded query access path. */ protected ClassMetaData[] getAccessPath() { return (ClassMetaData[]) _accessPath.toArray (new ClassMetaData[_accessPath.size()]); } /** * Return true if the given variable has been bound. */ protected boolean isBound(Value var) { return _boundVars != null && _boundVars.contains(var); } /** * Record that the given variable is bound. */ protected void bind(Value var) { if (_boundVars == null) _boundVars = new HashSet(); _boundVars.add(var); } /** * Returns a value for the given id. */ protected Value getVariable(String id, boolean bind) { // check for already constructed var if (isSeenVariable(id)) return getVariable(id); return createVariable(id, bind); } protected Value createVariable(String id, boolean bind) { // create and cache var Class type = getDeclaredVariableType(id); // add this type to the set of classes in the filter's access path ClassMetaData meta = null; if (type == null) type = TYPE_OBJECT; else meta = getMetaData(type, false); if (meta != null) { addAccessPath(meta); addSchemaToContext(id, meta); } Value var = null; if (bind) var = factory.newBoundVariable(id, type); else var = factory.newUnboundVariable(id, type); var.setMetaData(meta); if (_seenVars == null) _seenVars = new HashMap(); _seenVars.put(id, var); addVariableToContext(id, var); return var; } /** * Validate that all unbound variables are of a PC type. If not, assume * that the user actually made a typo that we took for an implicit * unbound variable. */ protected void assertUnboundVariablesValid() { if (_seenVars == null) return; Value var; for (Map.Entry entry : _seenVars.entrySet()) { var = entry.getValue(); if (var.getMetaData() == null && !isBound(var) && !isDeclaredVariable(entry.getKey())) { throw parseException(EX_USER, "not-unbound-var", new Object[]{ entry.getKey() }, null); } } } /** * Returns whether the specified variable name has been explicitly * declared. Note all query languages necessarily support declaring * variables. * * @param id the variable to check * @return true if the variabe has been explicitely declared */ protected abstract boolean isDeclaredVariable(String id); /** * Return whether the given id has been used as a variable. */ protected boolean isSeenVariable(String id) { return _seenVars != null && _seenVars.containsKey(id); } /** * Convenience method to get metadata for the given type. */ protected ClassMetaData getMetaData(Class c, boolean required) { return getMetaData(c, required, getClassLoader()); } /** * Convenience method to get metadata for the given type. */ protected ClassMetaData getMetaData(Class c, boolean required, ClassLoader loader) { return resolver.getConfiguration().getMetaDataRepositoryInstance(). getMetaData(c, loader, required); } /** * Traverse the given field in the given path. */ protected Value traversePath(Path path, String field) { return traversePath(path, field, false, false); } protected Value traverseXPath(Path path, String field) { XMLMetaData meta = path.getXmlMapping(); if (meta.getFieldMapping(field) == null) { throw parseException(EX_USER, "no-field", new Object[]{ meta.getType(), field }, null); } else { // collection-valued xpath is not allowed int type = meta.getFieldMapping(field).getTypeCode(); switch (type) { case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: throw new UserException(_loc.get("collection-valued-path", field)); } } path.get(meta, field); return path; } /** * Traverse the given field in the given path. */ protected Value traversePath(Path path, String field, boolean pcOnly, boolean allowNull) { ClassMetaData meta = path.getMetaData(); if (meta == null) throw parseException(EX_USER, "path-no-meta", new Object[]{ field, path.getType() }, null); FieldMetaData fmd = meta.getField(field); if (fmd == null) { Object val = traverseStaticField(meta.getDescribedType(), field); if (val == null) { if (isMultiValuedTraversalAttempt(path, field)) { throw parseException(EX_USER, "multi-valued-travesal", new Object[]{field, path.last()}, null); } String[] all = meta.getFieldNames(); Class cls = meta.getDescribedType(); throw parseException(EX_USER, "no-field", new Object[] {field, cls.getSimpleName(), StringDistance.getClosestLevenshteinDistance(field, all), cls.getName(), Arrays.toString(all)}, null); } return factory.newLiteral(val, Literal.TYPE_UNKNOWN); } if (fmd.isEmbedded()) meta = fmd.getEmbeddedMetaData(); else meta = fmd.getDeclaredTypeMetaData(); if (meta != null) { addAccessPath(meta); path.setMetaData(meta); } else { // xmlsupport xpath XMLMetaData xmlmeta = fmd.getRepository().getXMLMetaData(fmd.getDeclaredType()); if (xmlmeta != null) { path.get(fmd, xmlmeta); return path; } } if (meta != null || !pcOnly) path.get(fmd, allowNull); return path; } /** * Return a constant containing the value of the given static field. */ protected Object traverseStaticField(Class cls, String field) { try { return cls.getField(field).get(null); } catch (Exception e) { // count not locate the field: return null return null; } } private boolean isMultiValuedTraversalAttempt(Path path, String field) { if (path == null) return false; if (path.last() == null) return false; if (path.last().getElement() == null) return false; if (path.last().getElement().getDeclaredTypeMetaData() == null) return false; if (path.last().getElement().getDeclaredTypeMetaData().getField(field) == null) return false; return true; } /** * Returns the type of the named variable if it has been declared. */ protected abstract Class getDeclaredVariableType(String name); /** * Set the implicit types of the given values based on the fact that * they're used together, and based on the operator type. */ protected void setImplicitTypes(Value val1, Value val2, Class expected) { setImplicitTypes(val1, val2, expected, resolver); } protected static void setImplicitTypes(Value val1, Value val2, Class expected, Resolver resolver) { Class c1 = val1.getType(); Class c2 = val2.getType(); boolean o1 = c1 == TYPE_OBJECT; boolean o2 = c2 == TYPE_OBJECT; if (o1 && !o2) { val1.setImplicitType(c2); if (val1.getMetaData() == null && !val1.isXPath()) val1.setMetaData(val2.getMetaData()); } else if (!o1 && o2) { val2.setImplicitType(c1); if (val2.getMetaData() == null && !val1.isXPath()) val2.setMetaData(val1.getMetaData()); } else if (o1 && o2 && expected != null) { // we never expect a pc type, so don't bother with metadata val1.setImplicitType(expected); val2.setImplicitType(expected); } else if (isNumeric(val1.getType()) != isNumeric(val2.getType())) { if (resolver.getConfiguration().getCompatibilityInstance(). getQuotedNumbersInQueries()) convertTypesQuotedNumbers(val1, val2); else convertTypes(val1, val2); } } /** * Perform conversions to make values compatible. */ public static void convertTypes(Value val1, Value val2) { Class t1 = val1.getType(); Class t2 = val2.getType(); // allow string-to-char conversions if (t1 == TYPE_STRING && (Filters.wrap(t2) == TYPE_CHAR_OBJ && !(val2 instanceof Path))) { val2.setImplicitType(String.class); return; } if (t2 == TYPE_STRING && (Filters.wrap(t1) == TYPE_CHAR_OBJ) && !(val1 instanceof Path)) { val1.setImplicitType(String.class); return; } // if the non-numeric side is a string of length 1, cast it // to a character if (t1 == TYPE_STRING && val1 instanceof Literal && ((String) ((Literal) val1).getValue()).length() == 1) { val1.setImplicitType(Character.class); return; } if (t2 == TYPE_STRING && val2 instanceof Literal && ((String) ((Literal) val2).getValue()).length() == 1) { val2.setImplicitType(Character.class); return; } // error String left; String right; if (val1 instanceof Path && ((Path) val1).last() != null) left = _loc.get("non-numeric-path", ((Path) val1).last(). getName(), t1.getName()).getMessage(); else left = _loc.get("non-numeric-value", t1.getName()).getMessage(); if (val2 instanceof Path && ((Path) val2).last() != null) right = _loc.get("non-numeric-path", ((Path) val2).last(). getName(), t2.getName()).getMessage(); else right = _loc.get("non-numeric-value", t2.getName()).getMessage(); throw new UserException(_loc.get("non-numeric-comparison", left, right)); } /** * Perform conversions to make values compatible. */ public static void convertTypesQuotedNumbers(Value val1, Value val2) { Class t1 = val1.getType(); Class t2 = val2.getType(); // if we're comparing to a single-quoted string, convert // the value according to the 3.1 rules. if (t1 == TYPE_STRING && val1 instanceof Literal && ((Literal) val1).getParseType() == Literal.TYPE_SQ_STRING) { String s = (String) ((Literal) val1).getValue(); if (s.length() > 1) { ((Literal) val1).setValue(s.substring(0, 1)); val1.setImplicitType(Character.TYPE); } } if (t2 == TYPE_STRING && val2 instanceof Literal && ((Literal) val2).getParseType() == Literal.TYPE_SQ_STRING) { String s = (String) ((Literal) val2).getValue(); if (s.length() > 1) { ((Literal) val2).setValue(s.substring(0, 1)); val2.setImplicitType(Character.TYPE); } } // if we're comparing to a double-quoted string, convert the // value directly to a number if (t1 == TYPE_STRING && val1 instanceof Literal && ((Literal) val1).getParseType() == Literal.TYPE_STRING) { String s = (String) ((Literal) val1).getValue(); ((Literal) val1).setValue(Strings.parse(s, Filters.wrap(t2))); val1.setImplicitType(t2); } if (t2 == TYPE_STRING && val2 instanceof Literal && ((Literal) val2).getParseType() == Literal.TYPE_STRING) { String s = (String) ((Literal) val2).getValue(); ((Literal) val2).setValue(Strings.parse(s, Filters.wrap(t1))); val2.setImplicitType(t1); } } /** * Return true if given class can be used as a number. */ public static boolean isNumeric(Class type) { type = Filters.wrap(type); return Number.class.isAssignableFrom(type) || type == Character.TYPE || type == TYPE_CHAR_OBJ; } /** * Set the implicit types of the given values based on the fact that * the first is supposed to contain the second. */ protected void setImplicitContainsTypes(Value val1, Value val2, int op) { if (val1.getType() == TYPE_OBJECT) { if (op == CONTAINS_TYPE_ELEMENT) val1.setImplicitType(Collection.class); else val1.setImplicitType(Map.class); } if (val2.getType() == TYPE_OBJECT && val1 instanceof Path) { FieldMetaData fmd = ((Path) val1).last(); ClassMetaData meta; if (fmd != null) { if (op == CONTAINS_TYPE_ELEMENT || op == CONTAINS_TYPE_VALUE) { val2.setImplicitType(fmd.getElement().getDeclaredType()); meta = fmd.getElement().getDeclaredTypeMetaData(); if (meta != null) { val2.setMetaData(meta); addAccessPath(meta); } } else { val2.setImplicitType(fmd.getKey().getDeclaredType()); meta = fmd.getKey().getDeclaredTypeMetaData(); if (meta != null) { val2.setMetaData(meta); addAccessPath(meta); } } } } } /** * Set the implicit type of the given value to the given class. */ protected static void setImplicitType(Value val, Class expected) { // we never expect a pc type, so no need to worry about metadata if (val.getType() == TYPE_OBJECT) val.setImplicitType(expected); } /** * Used for obtaining the {@link Localizer} to use for translating * error messages. */ protected abstract Localizer getLocalizer(); /** * Returns the current string being parsed; used for error messages. */ protected abstract String currentQuery (); /** * Register the schema alias to the current JPQL query context. * @param alias * @param meta */ protected abstract void addSchemaToContext(String alias, ClassMetaData meta); /** * Register the variable associated with the schema alias (id) to * the current JPQL query context. * @param id * @param var */ protected abstract void addVariableToContext(String id, Value var); /** * Returns the variable associated with the schema alias (id). * @param id * @return */ protected abstract Value getVariable(String id); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Lit.java0000644000000000000000000000347212133327270025650 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * Represents a literal. * * @author Abe White */ class Lit extends Val implements Literal { private Object _val; private final int _ptype; /** * Constructor. Provide constant value. */ public Lit(Object val, int ptype) { _val = val; _ptype = ptype; } public Object getValue() { return _val; } public void setValue(Object val) { _val = val; } public int getParseType() { return _ptype; } public Object getValue(Object[] parameters) { return _val; } public Class getType() { return (_val == null) ? Object.class : _val.getClass(); } public void setImplicitType(Class type) { _val = Filters.convert(_val, type); } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _val; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Expression.java0000644000000000000000000000222112133327270027246 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.io.Serializable; /** * Interface for a set of conditions that must be met for the query * to be true. * * @author Abe White */ public interface Expression extends Serializable { /** * Accept a visit from a tree visitor. */ public void acceptVisit(ExpressionVisitor visitor); } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BindValueVariableExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BindValueVariableExpr0000644000000000000000000000265312133327270030356 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Map; /** * {@link BindVariableExpression} for map value collections. * * @author Abe White */ class BindValueVariableExpression extends BindVariableExpression { /** * Constructor. * * @param var the bound variable * @param val the value the variable is bound to */ public BindValueVariableExpression(BoundVariable var, Val val) { super(var, val); } protected Collection getCollection(Object values) { Map map = (Map) values; return (map == null) ? null : map.values(); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/NotEqualExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/NotEqualExpression.ja0000644000000000000000000000240112133327270030370 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Expression that compares two others. * * @author Abe White */ class NotEqualExpression extends CompareExpression { /** * Constructor. Supply values to compare. */ public NotEqualExpression(Val val1, Val val2) { super(val1, val2); } protected boolean compare(Object o1, Object o2) { return (o1 == null && o2 != null) || (o1 != null && !o1.equals(o2)); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/StringLength.java0000644000000000000000000000344312133327270027526 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Returns the number of characters in the String. * * @author Marc Prud'hommeaux */ class StringLength extends Val { private final Val _val; private Class _cast = null; /** * Constructor. Provide value to upper-case. */ public StringLength(Val val) { _val = val; } public Class getType() { if (_cast != null) return _cast; return int.class; } public void setImplicitType(Class type) { _cast = type; } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object eval = _val.eval(candidate, orig, ctx, params); if (eval == null) return 0; return eval.toString().length(); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionVisitor.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionVis0000644000000000000000000000227412133327270030504 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * No-op abstract visitor meant for easy extension. * * @author Abe White * @nojavadoc */ public abstract class AbstractExpressionVisitor implements ExpressionVisitor { public void enter(Expression exp) { } public void exit(Expression exp) { } public void enter(Value val) { } public void exit(Value val) { } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AndExpression.java0000644000000000000000000000376612133327270027710 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import org.apache.openjpa.kernel.StoreContext; /** * An expression that AND's two others together. * * @author Abe White */ class AndExpression extends Exp { private final Exp _exp1; private final Exp _exp2; /** * Constructor. Supply expressions to combine. */ public AndExpression(Exp exp1, Exp exp2) { _exp1 = exp1; _exp2 = exp2; } public Exp getExpression1() { return _exp1; } public Exp getExpression2() { return _exp2; } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _exp1.evaluate(candidate, orig, ctx, params) && _exp2.evaluate(candidate, orig, ctx, params); } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { return _exp1.evaluate(candidates, ctx, params) && _exp2.evaluate(candidates, ctx, params); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _exp1.acceptVisit(visitor); _exp2.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Add.java0000644000000000000000000000237012133327270025604 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; /** * Value produced by two values being added together. * * @author Abe White */ class Add extends MathVal { /** * Constructor. Provide the values to add. */ public Add(Val val1, Val val2) { super(val1, val2); } protected Object operate(Object o1, Class c1, Object o2, Class c2) { return Filters.add(o1, c1, o2, c2); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Args.java0000644000000000000000000000476612133327270026023 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.ArrayList; import java.util.List; import org.apache.openjpa.kernel.StoreContext; /** * A list of arguments to a multi-argument function. * * @author Abe White */ class Args extends Val implements Arguments { private final List _args = new ArrayList(3); /** * Constructor. Supply values being combined. */ public Args(Value val1, Value val2) { this(new Value[]{val1, val2}); } public Args(Value...values) { if (values == null) { return; } for (Value v : values) { if (v instanceof Args) { _args.addAll(((Args)v)._args); } else { _args.add(v); } } } public Value[] getValues() { return _args.toArray(new Value[_args.size()]); } public Class getType() { return Object[].class; } public Class[] getTypes() { Class[] c = new Class[_args.size()]; for (int i = 0; i < _args.size(); i++) c[i] = ((Val) _args.get(i)).getType(); return c; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object[] vals = new Object[_args.size()]; for (int i = 0; i < _args.size(); i++) vals[i] = ((Val) _args.get(i)).eval(candidate, orig, ctx, params); return vals; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); for (int i = 0; i < _args.size(); i++) ((Val) _args.get(i)).acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ToUpperCase.java0000644000000000000000000000313112133327270027302 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Upper-case a string. * * @author Abe White */ class ToUpperCase extends Val { private final Val _val; /** * Constructor. Provide value to upper-case. */ public ToUpperCase(Val val) { _val = val; } public Class getType() { return String.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _val.eval(candidate, orig, ctx, params).toString(). toUpperCase(); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Sqrt.java0000644000000000000000000000242712133327270026050 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Take the square root of a number. * * @author Abe White */ class Sqrt extends UnaryMathVal { /** * Constructor. Provide the number whose square root to calculate. */ public Sqrt(Val val) { super(val); } protected Class getType(Class c) { return double.class; } protected Object operate(Object o, Class c) { return Double.valueOf(Math.sqrt(((Number) o).doubleValue())); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java0000644000000000000000000001466412133327270027616 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; import org.apache.commons.lang.ObjectUtils; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.XMLMetaData; import org.apache.openjpa.util.ImplHelper; /** * A path represents a traversal into fields of a candidate object. * * @author Abe White */ public class CandidatePath extends Val implements Path { protected LinkedList _actions = null; protected String _correlationVar = null; /** * Traverse into the given field of the current object, and update * the current object to that field value. */ public void get(FieldMetaData field, boolean nullTraversal) { if (_actions == null) _actions = new LinkedList(); _actions.add(new Traversal(field, nullTraversal)); } public Class getType() { if (_actions == null) return getCandidateType(); Object last = _actions.getLast(); if (last instanceof Class) return (Class) last; FieldMetaData fmd = ((Traversal) last).field; return fmd.getDeclaredType(); } protected Class getCandidateType() { ClassMetaData meta = getMetaData(); if (meta == null) return Object.class; return meta.getDescribedType(); } public void setImplicitType(Class type) { } public FieldMetaData last() { if (_actions == null) return null; ListIterator itr = _actions.listIterator(_actions.size()); Object prev; while (itr.hasPrevious()) { prev = itr.previous(); if (prev instanceof Traversal) return ((Traversal) prev).field; } return null; } /** * Cast this path to the given type. */ public void castTo(Class type) { if (_actions == null) _actions = new LinkedList(); _actions.add(type); } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { if (_actions == null) return candidate; Object action; OpenJPAStateManager sm; Broker tmpBroker = null; for (Iterator itr = _actions.iterator(); itr.hasNext();) { action = itr.next(); // fail on null value if (candidate == null) { if (action instanceof Traversal && ((Traversal) action).nullTraversal) return null; throw new NullPointerException(); } // check that the cast is valid if (action instanceof Class) { candidate = Filters.convert(candidate, (Class) action); continue; } // make sure we can access the instance; even non-pc vals might // be proxyable sm = null; tmpBroker = null; if (ImplHelper.isManageable(candidate)) sm = (OpenJPAStateManager) (ImplHelper.toPersistenceCapable( candidate, ctx.getConfiguration())). pcGetStateManager(); if (sm == null) { tmpBroker = ctx.getBroker(); tmpBroker.transactional(candidate, false, null); sm = tmpBroker.getStateManager(candidate); } try { // get the specified field value and switch candidate Traversal traversal = (Traversal) action; candidate = sm.fetchField(traversal.field.getIndex(), true); } finally { // transactional does not clear the state, which is // important since tmpCandidate might be also managed by // another broker if it's a proxied non-pc instance if (tmpBroker != null) tmpBroker.nontransactional(sm.getManagedInstance(), null); } } return candidate; } public int hashCode() { return (_actions == null) ? 0 : _actions.hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (!(other instanceof CandidatePath)) return false; return ObjectUtils.equals(_actions, ((CandidatePath) other)._actions); } /** * Represents a traversal through a field. */ public static class Traversal { public final FieldMetaData field; public final boolean nullTraversal; private Traversal(FieldMetaData field, boolean nullTraversal) { this.field = field; this.nullTraversal = nullTraversal; } public int hashCode() { return field.hashCode(); } public boolean equals(Object other) { if (other == this) return true; return ((Traversal) other).field.equals(field); } } public void get(FieldMetaData fmd, XMLMetaData meta) { } public void get(XMLMetaData meta, String name) { } public XMLMetaData getXmlMapping() { return null; } public void setSchemaAlias(String schemaAlias) { } public String getSchemaAlias() { return null; } public void setSubqueryContext(Context conext, String correlationVar) { } public String getCorrelationVar() { return _correlationVar; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/FilterListener.java0000644000000000000000000000700212133327270030044 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.io.Serializable; import org.apache.openjpa.kernel.StoreContext; /** * A filter listener extends expression filters with custom functionality. * * @author Steve Kim * @author Abe White */ public interface FilterListener extends Serializable { /** * Return the tag that this extension listens for. */ public String getTag(); /** * Return true if this extension expects arguments to act on. Some * extensions may not need arguments; for example, an extension to * switch a string to upper case might be of the form: * field.ext:toUpperCase (). */ public boolean expectsArguments(); /** * Return true if this extension expects a target to act on. Some * extensions act on a field or object value; others stand alone. * field.ext:toUpperCase () acts on the target * field but has no arguments, while another possible form, * ext:toUpperCase (field) has no target but does have an * argument. */ public boolean expectsTarget(); /** * Evaluate the given expression. This method is used when * evaluating in-memory expressions. The method used when evaluating * data store expressions will change depending on the data store in use. * * @param target the target object / field value to act on; will be * null if this extension does not expect a target * @param targetClass the expected class of the target; given in case * the target evaluates to null and typing is needed * @param args the values of the arguments given in the filter; * will be null if this extension does not expect an argument * @param argClasses the expected classes of the arguments; given in case * an argument evaluates to null and typing is needed * @param candidate the candidate object being evaluated * @param ctx the persistence context * @return the value of the extension for this candidate; if * this extension is an expression, this method should * return {@link Boolean#TRUE} or {@link Boolean#FALSE} * @throws org.apache.openjpa.util.UserException if this extension does not * support in-memory operation */ public Object evaluate(Object target, Class targetClass, Object[] args, Class[] argClasses, Object candidate, StoreContext ctx); /** * Return the expected type of the result of this listener. * * @param targetClass the expected class of the target, or null if no target * @param argClasses the expected classes of the arguments, or null if * no arguments */ public Class getType(Class targetClass, Class[] argClasses); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java0000644000000000000000000000756612133327270025652 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Map; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.meta.ClassMetaData; /** * An in-memory representation of a {@link Value}. * * @author Abe White * @nojavadoc */ public abstract class Val implements Value { private ClassMetaData _meta = null; private String _alias = null; /** * Return this value as a projection on the given candidate. */ public final Object evaluate(Object candidate, Object orig, StoreContext ctx, Object[] params) { try { return eval(candidate, candidate, ctx, params); } catch (NullPointerException npe) { return null; } catch (ClassCastException cce) { return null; } } /** * Return this value as an aggregate projection on the given group * of candidates. */ public final Object evaluate(Collection candidates, Object orig, StoreContext ctx, Object[] params) { try { Collection c = eval(candidates, orig, ctx, params); if (c.isEmpty()) return null; return c.iterator().next(); } catch (NullPointerException npe) { return null; } catch (ClassCastException cce) { return null; } } /** * Return this value for the given candidate. */ protected abstract Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params); /** * Return a list of values resulting from evaluating each given * candidate. By default, this implementation invokes * {@link #eval(Object,Object,StoreContext,Map)} for * each instance and packs the return value into a new list. Aggregates * should override. */ protected Collection eval(Collection candidates, Object orig, StoreContext ctx, Object[] params) { Collection ret = new ArrayList(candidates.size()); Object candidate; for (Iterator itr = candidates.iterator(); itr.hasNext();) { candidate = itr.next(); ret.add(evaluate(candidate, (orig == null) ? candidate : orig, ctx, params)); } return ret; } public ClassMetaData getMetaData() { return _meta; } public void setMetaData(ClassMetaData meta) { _meta = meta; } public boolean isVariable() { return false; } public boolean isAggregate() { return false; } public boolean isXPath() { return false; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); visitor.exit(this); } public String getAlias() { return _alias; } public void setAlias(String alias) { _alias = alias; } public Value getSelectAs() { return _alias != null ? this : null; } public Path getPath() { return null; } public String getName() { return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/WildcardMatch.java0000644000000000000000000000455012133327270027624 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.util.SimpleRegex; /** * Tests if the target matches the wildcard expression given in the * argument. The wildcard '?' is used to represent any single character, * while '*' is used to represent any series of 0 or more characters. * Examples:
    * "address.street.ext:wildcardMatch (\"?ain*reet\")" * * * @deprecated Use matches() instead. * @nojavadoc */ public class WildcardMatch implements FilterListener { public static final String TAG = "wildcardMatch"; public String getTag() { return TAG; } public boolean expectsArguments() { return true; } public boolean expectsTarget() { return true; } public Object evaluate(Object target, Class targetClass, Object[] args, Class[] argClasses, Object candidate, StoreContext ctx) { if (target == null || args[0] == null) return Boolean.FALSE; // create a regexp for the wildcard expression by subbing '.' for '?' // and '.*' for '*' String wild = args[0].toString().replace('?', '.'); for (int st = 0, i; (i = wild.indexOf("*", st)) != -1; st = i + 3) wild = wild.substring(0, i) + "." + wild.substring(i); SimpleRegex re = new SimpleRegex(wild, false); return (re.matches(target.toString())) ? Boolean.TRUE : Boolean.FALSE; } public Class getType(Class targetClass, Class[] argClasses) { return boolean.class; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CollectionParam.java0000644000000000000000000000342612133327270030173 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Represents a collection valued input parameter. * * @author Catalina Wei */ class CollectionParam extends Val implements Parameter { private Object _key = null; private Class _type = null; private int _index = -1; /** * Constructor. Provide parameter name and type. */ public CollectionParam(Object name, Class type) { _key = name; _type = type; } public Object getParameterKey() { return _key; } public Class getType() { return _type; } public void setImplicitType(Class type) { _type = type; } public void setIndex(int index) { _index = index; } public Object getValue(Object[] params) { return params[_index]; } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return getValue(params); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/NotExpression.java0000644000000000000000000000322112133327270027730 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import org.apache.openjpa.kernel.StoreContext; /** * An expression that NOT's another. * * @author Abe White */ class NotExpression extends Exp { private final Exp _exp; /** * Constructor. Supply expression to negate. */ public NotExpression(Exp exp) { _exp = exp; } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return !_exp.evaluate(candidate, orig, ctx, params); } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { return !_exp.evaluate(candidates, ctx, params); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _exp.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/UnaryMathVal.java0000644000000000000000000000372212133327270027471 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Value produced by a mathematical operation on one value. * * @author Abe White */ abstract class UnaryMathVal extends Val { private final Val _val; /** * Constructor. Provide the value to operate on. */ public UnaryMathVal(Val val) { _val = val; } public Class getType() { return getType(_val.getType()); } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object o1 = _val.eval(candidate, orig, ctx, params); return operate(o1, _val.getType()); } /** * Return the type of this value based on the numeric type being operated * on. */ protected abstract Class getType(Class c); /** * Return the result of this mathematical operation on the given value. */ protected abstract Object operate(Object o, Class c); public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Arguments.java0000644000000000000000000000206412133327270027061 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Multiple arguments to a function call. * * @author Abe White */ public interface Arguments extends Value { /** * Return the values that make up the arguments. */ public Value[] getValues(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/All.java0000644000000000000000000000346412133327270025631 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.math.BigDecimal; import java.math.BigInteger; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UnsupportedException; /** * In-memory All implementation. Currently unsupported since * in-memory subqueries are not supported. * * @author Marc Prud'hommeaux */ class All extends UnaryMathVal { private static final Localizer _loc = Localizer.forPackage(All.class); public All(Val val) { super(val); } protected Class getType(Class c) { Class wrap = Filters.wrap(c); if (wrap == Integer.class || wrap == Float.class || wrap == Double.class || wrap == Long.class || wrap == BigDecimal.class || wrap == BigInteger.class) return c; return int.class; } protected Object operate(Object o, Class c) { throw new UnsupportedException(_loc.get("in-mem-subquery")); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/OrExpression.java0000644000000000000000000000356512133327270027563 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import org.apache.openjpa.kernel.StoreContext; /** * An expression that OR's two others together. * * @author Abe White */ class OrExpression extends Exp { private final Exp _exp1; private final Exp _exp2; /** * Constructor. Supply expressions to combine. */ public OrExpression(Exp exp1, Exp exp2) { _exp1 = exp1; _exp2 = exp2; } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _exp1.evaluate(candidate, orig, ctx, params) || _exp2.evaluate(candidate, orig, ctx, params); } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { return _exp1.evaluate(candidates, ctx, params) || _exp2.evaluate(candidates, ctx, params); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _exp1.acceptVisit(visitor); _exp2.acceptVisit(visitor); visitor.exit(this); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/StartsWithExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/StartsWithExpression.0000644000000000000000000000244312133327270030447 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Expression that compares two others. * * @author Abe White */ class StartsWithExpression extends CompareExpression { /** * Constructor. Supply values to compare. */ public StartsWithExpression(Val val1, Val val2) { super(val1, val2); } protected boolean compare(Object o1, Object o2) { if (o1 == null || o2 == null) return false; return o1.toString().startsWith(o2.toString()); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BindVariableExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BindVariableExpressio0000644000000000000000000000542612133327270030425 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import org.apache.openjpa.kernel.StoreContext; /** * Binds a variable to a collection. * * @author Abe White */ class BindVariableExpression extends Exp { private final BoundVariable _var; private final Val _val; /** * Constructor. * * @param var the bound variable * @param val the value the variable is bound to */ public BindVariableExpression(BoundVariable var, Val val) { _var = var; _val = val; } public BoundVariable getVariable() { return _var; } /** * Return the possible values that variable can take. */ public Collection getVariableValues(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object values = _val.eval(candidate, orig, ctx, params); return getCollection(values); } /** * Return a collection for the given object, produced by * eval'ing the value of this expression. Simply casts * the object to a collection by default. */ protected Collection getCollection(Object values) { return (Collection) values; } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { // if the collection is empty no possible variable evals to true Collection vals = getVariableValues(candidate, orig, ctx, params); if (vals == null || vals.isEmpty()) return false; return true; } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { if (candidates == null || candidates.isEmpty()) return false; Object obj = candidates.iterator().next(); return eval(obj, obj, ctx, params); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _var.acceptVisit(visitor); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Substring.java0000644000000000000000000000427612133327270027103 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Take the substring of a string. * * @author Abe White */ class Substring extends Val { private final Val _val; private final Val _args; /** * Constructor. Provide value to take substring of and arguments to * substring method. */ public Substring(Val val, Val args) { _val = val; _args = args; } public Class getType() { return String.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object str = _val.eval(candidate, orig, ctx, params); Object arg = _args.eval(candidate, orig, ctx, params); if (arg instanceof Object[]) { Object[] args = (Object[]) arg; int start = ((Number) args[0]).intValue() - 1; int length = ((Number) args[1]).intValue(); String string = str == null ? "" : str.toString(); return string.substring(start, Math.min(start + length, string.length())); } return str.toString().substring(((Number) arg).intValue() - 1); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); _args.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Max.java0000644000000000000000000000277212133327270025647 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Iterator; /** * Find the max. * * @author Abe White */ class Max extends AggregateVal { /** * Constructor. Provide the value to maximize. */ public Max(Val val) { super(val); } protected Class getType(Class c) { return c; } protected Object operate(Collection os, Class c) { Comparable max = null; Comparable cur; for (Iterator itr = os.iterator(); itr.hasNext();) { cur = (Comparable) itr.next(); if (cur != null && (max == null || max.compareTo(cur) < 0)) max = cur; } return max; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFac0000644000000000000000000006252612133327270030436 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Set; import org.apache.commons.lang.ObjectUtils; import org.apache.openjpa.kernel.Extent; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.UserException; /** * Expression factory implementation that can be used to execute queries * in memory. * * @author Abe White * @nojavadoc */ public class InMemoryExpressionFactory implements ExpressionFactory { private static final Value NULL = new Null(); private static final Object UNIQUE = new Object(); // list of unbound variables in this query private List _unbounds = null; /** * Tests whether the given candidate matches the given type and this * expression. */ public boolean matches(QueryExpressions exps, ClassMetaData type, boolean subs, Object candidate, StoreContext ctx, Object[] params) { // ignore candidates of the wrong type if (candidate == null) return false; if (!subs && candidate.getClass() != type.getDescribedType()) return false; if (subs && !type.getDescribedType().isAssignableFrom (candidate.getClass())) return false; // evaluate the expression for all possible combinations of values // of the unbound variables; the candidate matches if any combination // matches return matches((Exp) exps.filter, candidate, ctx, params, 0); } /** * Recursive method to evaluate the expression for all possible * combinations of unbound variables. This method simulates a sequence * of embedded procedural loops over the extents of all variables in the * unbounds list. */ protected boolean matches(Exp exp, Object candidate, StoreContext ctx, Object[] params, int i) { // base case: all variables have been aliased; evaluate for current // values if (_unbounds == null || i == _unbounds.size()) return exp.evaluate(candidate, candidate, ctx, params); // grab the extent for this variable UnboundVariable var = _unbounds.get(i); Iterator itr = ctx.extentIterator(var.getType(), true, null, false); try { // if the extent was empty, then alias the variable to null if (!itr.hasNext()) { var.setValue(null); return matches(exp, candidate, ctx, params, i + 1); } // try every value, short-circuiting on match while (itr.hasNext()) { // set the variable to each extent value and recurse var.setValue(itr.next()); if (matches(exp, candidate, ctx, params, i + 1)) return true; } // no match return false; } finally { ImplHelper.close(itr); } } /** * Group the list of matches into a list of lists. */ public List group(QueryExpressions exps, List matches, StoreContext ctx, Object[] params) { if (matches == null || matches.isEmpty() || exps.grouping.length == 0) return matches; // to form groups we first order on the grouping criteria matches = order(exps, exps.grouping, false, matches, ctx, params); // now we combine all results whose values for each grouping clause // are the same, relying on the fact that these values will already be // together due to the sorting Object[] prevs = new Object[exps.grouping.length]; Arrays.fill(prevs, UNIQUE); Object[] curs = new Object[exps.grouping.length]; List grouped = new ArrayList(); List group = null; Object pc; boolean eq; for (Iterator itr = matches.iterator(); itr.hasNext();) { pc = itr.next(); eq = true; for (int i = 0; i < exps.grouping.length; i++) { curs[i] = ((Val) exps.grouping[i]).evaluate(pc, pc, ctx, params); eq = eq && ObjectUtils.equals(prevs[i], curs[i]); } // if this object's grouping values differ from the prev, // start a new group if (!eq) { if (group != null) grouped.add(group); group = new ArrayList(); } group.add(pc); System.arraycopy(curs, 0, prevs, 0, curs.length); } // add the last group formed if (group != null) grouped.add(group); return grouped; } /** * Return true if the given group matches the having expression. */ public boolean matches(QueryExpressions exps, Collection group, StoreContext ctx, Object[] params) { if (group == null || group.isEmpty()) return false; if (exps.having == null) return true; // evaluate the expression for all possible combinations of values // of the unbound variables; the group matches if any combination // matches return matches((Exp) exps.having, group, ctx, params, 0); } /** * Recursive method to evaluate the expression for all possible * combinations of unbound variables. This method simulates a sequence * of embedded procedural loops over the extents of all variables in the * unbounds list. */ private boolean matches(Exp exp, Collection group, StoreContext ctx, Object[] params, int i) { // base case: all variables have been aliased; evaluate for current // values if (_unbounds == null || i == _unbounds.size()) return exp.evaluate(group, ctx, params); // grab the extent for this variable UnboundVariable var = _unbounds.get(i); Extent extent = ctx.getBroker().newExtent(var.getType(), true); Iterator itr = extent.iterator(); try { // if the extent was empty, then alias the variable to null if (!itr.hasNext()) { var.setValue(null); return matches(exp, group, ctx, params, i + 1); } // try every value, short-circuiting on match while (itr.hasNext()) { // set the variable to each extent value and recurse var.setValue(itr.next()); if (matches(exp, group, ctx, params, i + 1)) return true; } // no match return false; } finally { ImplHelper.close(itr); } } /** * Create the projections for the given results. */ public List project(QueryExpressions exps, List matches, StoreContext ctx, Object[] params) { if (exps.projections.length == 0) return matches; // if an ungrouped aggregate, evaluate the whole matches list if (exps.grouping.length == 0 && exps.isAggregate()) { Object[] projection = project(matches, exps, true, ctx, params); return Arrays.asList(new Object[]{ projection }); } // evaluate each candidate List projected = new ArrayList(matches.size()); for (Iterator itr = matches.iterator(); itr.hasNext();) projected.add(project(itr.next(), exps, exps.grouping.length > 0, ctx, params)); return projected; } /** * Generate a projection on the given candidate. */ private Object[] project(Object candidate, QueryExpressions exps, boolean agg, StoreContext ctx, Object[] params) { Object[] projection = new Object[exps.projections.length + exps.ordering.length]; // calcualte result values Object result = null; for (int i = 0; i < exps.projections.length; i++) { if (agg) result = ((Val) exps.projections[i]).evaluate((Collection) candidate, null, ctx, params); else result = ((Val) exps.projections[i]).evaluate(candidate, candidate, ctx, params); projection[i] = result; } // tack on ordering values boolean repeat; for (int i = 0; i < exps.ordering.length; i++) { // already selected as a result? repeat = false; for (int j = 0; !repeat && j < exps.projections.length; j++) { if (exps.orderingClauses[i].equals(exps.projectionClauses[j])) { result = projection[j]; repeat = true; } } // not selected as result; calculate value if (!repeat) { if (agg) result = ((Val) exps.ordering[i]).evaluate((Collection) candidate, null, ctx, params); else result = ((Val) exps.ordering[i]).evaluate(candidate, candidate, ctx, params); } projection[i + exps.projections.length] = result; } return projection; } /** * Order the given list of matches on the given value. */ public List order(QueryExpressions exps, List matches, StoreContext ctx, Object[] params) { return order(exps, exps.ordering, true, matches, ctx, params); } /** * Order the given list of matches on the given value. * * @param projected whether projections have been applied to the matches yet */ private List order(QueryExpressions exps, Value[] orderValues, boolean projected, List matches, StoreContext ctx, Object[] params) { if (matches == null || matches.isEmpty() || orderValues == null || orderValues.length == 0) return matches; int results = (projected) ? exps.projections.length : 0; boolean[] asc = (projected) ? exps.ascending : null; int idx; for (int i = orderValues.length - 1; i >= 0; i--) { // if this is a projection, then in project() we must have selected // the ordering value already after the projection values idx = (results > 0) ? results + i : -1; Collections.sort(matches, new OrderValueComparator((Val) orderValues[i], asc == null || asc[i], idx, ctx, params)); } return matches; } /** * Filter the given list of matches, removing duplicate entries. */ public List distinct(QueryExpressions exps, boolean fromExtent, List matches) { if (matches == null || matches.isEmpty()) return matches; // no need to do distinct if not instructed to, or if these are // candidate objects from an extent int len = exps.projections.length; if ((exps.distinct & exps.DISTINCT_TRUE) == 0 || (fromExtent && len == 0)) return matches; Set seen = new HashSet(matches.size()); List distinct = null; Object cur; Object key; for (ListIterator li = matches.listIterator(); li.hasNext();) { cur = li.next(); key = (len > 0 && cur != null) ? new ArrayKey((Object[]) cur) : cur; if (seen.add(key)) { // key hasn't been seen before; if we've created a distinct // list, keep adding to it if (distinct != null) distinct.add(cur); } else if (distinct == null) { // we need to copy the matches list because the distinct list // will be different (we've come across a non-unique key); add // all the elements we've skipped over so far distinct = new ArrayList(matches.size()); distinct.addAll(matches.subList(0, li.previousIndex())); } } return (distinct == null) ? matches : distinct; } public Expression emptyExpression() { return new Exp(); } public Expression asExpression(Value v) { return new ValExpression((Val) v); } public Expression equal(Value v1, Value v2) { return new EqualExpression((Val) v1, (Val) v2); } public Expression notEqual(Value v1, Value v2) { return new NotEqualExpression((Val) v1, (Val) v2); } public Expression lessThan(Value v1, Value v2) { return new LessThanExpression((Val) v1, (Val) v2); } public Expression greaterThan(Value v1, Value v2) { return new GreaterThanExpression((Val) v1, (Val) v2); } public Expression lessThanEqual(Value v1, Value v2) { return new LessThanEqualExpression((Val) v1, (Val) v2); } public Expression greaterThanEqual(Value v1, Value v2) { return new GreaterThanEqualExpression((Val) v1, (Val) v2); } public Expression isEmpty(Value v1) { return new IsEmptyExpression((Val) v1); } public Expression isNotEmpty(Value v1) { return not(isEmpty(v1)); } public Expression contains(Value v1, Value v2) { return new ContainsExpression((Val) v1, (Val) v2); } public Expression containsKey(Value v1, Value v2) { return new ContainsKeyExpression((Val) v1, (Val) v2); } public Expression containsValue(Value v1, Value v2) { return new ContainsValueExpression((Val) v1, (Val) v2); } public Value getMapValue(Value map, Value arg) { return new GetMapValue((Val) map, (Val) arg); } public Expression isInstance(Value v1, Class c) { return new InstanceofExpression((Val) v1, c); } public Expression and(Expression exp1, Expression exp2) { if (exp1 instanceof BindVariableExpression) return new BindVariableAndExpression((BindVariableExpression) exp1, (Exp) exp2); return new AndExpression((Exp) exp1, (Exp) exp2); } public Expression or(Expression exp1, Expression exp2) { return new OrExpression((Exp) exp1, (Exp) exp2); } public Expression not(Expression exp) { return new NotExpression((Exp) exp); } public Expression bindVariable(Value var, Value val) { return new BindVariableExpression((BoundVariable) var, (Val) val); } public Expression bindKeyVariable(Value var, Value val) { return new BindKeyVariableExpression((BoundVariable) var, (Val) val); } public Expression bindValueVariable(Value var, Value val) { return new BindValueVariableExpression((BoundVariable) var, (Val) val); } public Expression endsWith(Value v1, Value v2) { return new EndsWithExpression((Val) v1, (Val) v2); } public Expression matches(Value v1, Value v2, String single, String multi, String esc) { return new MatchesExpression((Val) v1, (Val) v2, single, multi, esc, true); } public Expression notMatches(Value v1, Value v2, String single, String multi, String esc) { return new MatchesExpression((Val) v1, (Val) v2, single, multi, esc, false); } public Expression startsWith(Value v1, Value v2) { return new StartsWithExpression((Val) v1, (Val) v2); } public Subquery newSubquery(ClassMetaData candidate, boolean subs, String alias) { return new SubQ(alias); } public Path newPath() { return new CandidatePath(); } public Path newPath(Value val) { return new ValuePath((Val) val); } public Literal newLiteral(Object val, int parseType) { return new Lit(val, parseType); } public Literal newTypeLiteral(Object val, int parseType) { return new TypeLit(val, parseType); } public Value getThis() { return new This(); } public Value getNull() { return NULL; } public Value getCurrentDate(Class dateType) { return new CurrentDate(dateType); } public Value getCurrentTime(Class dateType) { return new CurrentDate(dateType); } public Value getCurrentTimestamp(Class dateType) { return new CurrentDate(dateType); } public Parameter newParameter(Object name, Class type) { return new Param(name, type); } public Parameter newCollectionValuedParameter(Object name, Class type) { return new CollectionParam(name, type); } public Value newExtension(FilterListener listener, Value target, Value arg) { return new Extension(listener, (Val) target, (Val) arg); } public Value newAggregate(AggregateListener listener, Value arg) { return new Aggregate(listener, (Val) arg); } public Arguments newArgumentList(Value val1, Value val2) { return new Args(val1, val2); } public Arguments newArgumentList(Value... values) { return new Args(values); } public Value newUnboundVariable(String name, Class type) { UnboundVariable var = new UnboundVariable(type); if (_unbounds == null) _unbounds = new ArrayList(3); _unbounds.add(var); return var; } public Value newBoundVariable(String name, Class type) { return new BoundVariable(type); } public Value cast(Value val, Class cls) { if (val instanceof CandidatePath) ((CandidatePath) val).castTo(cls); else if (val instanceof BoundVariable) ((BoundVariable) val).castTo(cls); else val = new Cast((Val) val, cls); return val; } public Value add(Value val1, Value val2) { return new Add((Val) val1, (Val) val2); } public Value subtract(Value val1, Value val2) { return new Subtract((Val) val1, (Val) val2); } public Value multiply(Value val1, Value val2) { return new Multiply((Val) val1, (Val) val2); } public Value divide(Value val1, Value val2) { return new Divide((Val) val1, (Val) val2); } public Value mod(Value val1, Value val2) { return new Mod((Val) val1, (Val) val2); } public Value abs(Value val) { return new Abs((Val) val); } public Value indexOf(Value val1, Value val2) { return new IndexOf((Val) val1, (Val) val2); } public Value concat(Value val1, Value val2) { return new Concat((Val) val1, (Val) val2); } public Value stringLength(Value str) { return new StringLength((Val) str); } public Value trim(Value str, Value trimChar, Boolean where) { return new Trim((Val) str, (Val) trimChar, where); } public Value sqrt(Value val) { return new Sqrt((Val) val); } public Value substring(Value val1, Value val2) { return new Substring((Val) val1, (Val) val2); } public Value toUpperCase(Value val) { return new ToUpperCase((Val) val); } public Value toLowerCase(Value val) { return new ToLowerCase((Val) val); } public Value avg(Value val) { return new Avg((Val) val); } public Value count(Value val) { return new Count((Val) val); } public Value distinct(Value val) { return new Distinct((Val) val); } public Value max(Value val) { return new Max((Val) val); } public Value min(Value val) { return new Min((Val) val); } public Value sum(Value val) { return new Sum((Val) val); } public Value any(Value val) { return new Any((Val) val); } public Value all(Value val) { return new All((Val) val); } public Value size(Value val) { return new Size((Val) val); } public Value index(Value val) { return new Index((Val) val); } public Value type(Value val) { return new Type((Val) val); } public Value mapEntry(Value key, Value val) { throw new UnsupportedException("not implemented yet"); } public Value mapKey(Value key, Value val) { throw new UnsupportedException("not implemented yet"); } public Value getKey(Value val) { throw new UnsupportedException("not implemented yet"); } public Value getObjectId(Value val) { return new GetObjectId((Val) val); } /** * Key that implements hashCode and equals methods for object arrays. */ private static class ArrayKey { private final Object[] _arr; public ArrayKey(Object[] arr) { _arr = arr; } public int hashCode() { int rs = 17; for (int i = 0; i < _arr.length; i++) rs = 37 * rs + ((_arr[i] == null) ? 0 : _arr[i].hashCode()); return rs; } public boolean equals(Object other) { if (other == this) return true; if (other == null) return false; Object[] arr = ((ArrayKey) other)._arr; if (_arr.length != arr.length) return false; for (int i = 0; i < _arr.length; i++) if (!ObjectUtils.equals(_arr[i], arr[i])) return false; return true; } } /** * Comparator that uses the result of eval'ing a Value to sort on. Null * values are placed last if sorting in ascending order, first if * descending. */ private static class OrderValueComparator implements Comparator { private final StoreContext _ctx; private final Val _val; private final boolean _asc; private final int _idx; private final Object[] _params; private OrderValueComparator(Val val, boolean asc, int idx, StoreContext ctx, Object[] params) { _ctx = ctx; _val = val; _asc = asc; _idx = idx; _params = params; } public int compare(Object o1, Object o2) { if (_idx != -1) { o1 = ((Object[]) o1)[_idx]; o2 = ((Object[]) o2)[_idx]; } else { o1 = _val.evaluate(o1, o1, _ctx, _params); o2 = _val.evaluate(o2, o2, _ctx, _params); } if (o1 == null && o2 == null) return 0; if (o1 == null) return (_asc) ? 1 : -1; if (o2 == null) return (_asc) ? -1 : 1; if (o1 instanceof Boolean && o2 instanceof Boolean) { int i1 = ((Boolean) o1).booleanValue() ? 1 : 0; int i2 = ((Boolean) o2).booleanValue() ? 1 : 0; return i1 - i2; } try { if (_asc) return ((Comparable) o1).compareTo(o2); return ((Comparable) o2).compareTo(o1); } catch (ClassCastException cce) { Localizer loc = Localizer.forPackage (InMemoryExpressionFactory.class); throw new UserException(loc.get("not-comp", o1, o2)); } } } public Value generalCaseExpression(Expression[] exp, Value val) { Exp[] exps = new Exp[exp.length]; for (int i = 0; i < exp.length; i++) exps[i] = (Exp) exp[i]; return new GeneralCase(exps, (Val) val); } public Value simpleCaseExpression(Value caseOperand, Expression[] exp, Value val) { Exp[] exps = new Exp[exp.length]; for (int i = 0; i < exp.length; i++) exps[i] = (Exp) exp[i]; return new SimpleCase((Val) caseOperand, exps, (Val) val); } public Expression whenCondition(Expression exp, Value val) { return new WhenCondition((Exp) exp, (Val) val); } public Expression whenScalar(Value val1, Value val2) { return new WhenScalar((Val) val1, (Val) val2); } public Value coalesceExpression(Value[] val) { Val[] vals = new Val[val.length]; for (int i = 0; i < val.length; i++) vals[i] = (Val) val[i]; return new Coalesce(vals); } public Value nullIfExpression(Value val1, Value val2) { return new NullIf((Val) val1, (Val) val2); } public Value newFunction(String functionName, Class resultType, Value... args) { throw new AbstractMethodError(); } public boolean isVerticalType(Value val) { return false; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ValExpression.java0000644000000000000000000000351412133327270027717 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import org.apache.openjpa.kernel.StoreContext; /** * Boolean value used as an expression. * * @author Abe White */ class ValExpression extends Exp { private final Val _val; /** * Constructor. Supply value. */ public ValExpression(Val val) { _val = val; } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object o = _val.eval(candidate, orig, ctx, params); return o != null && ((Boolean) o).booleanValue(); } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { Collection c = _val.eval(candidates, null, ctx, params); Object o = (c == null || c.isEmpty()) ? null : c.iterator().next(); return o != null && ((Boolean) o).booleanValue(); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Abs.java0000644000000000000000000000430512133327270025621 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.math.BigDecimal; import java.math.BigInteger; import org.apache.openjpa.kernel.Filters; /** * Take the absolute value of a number. */ class Abs extends UnaryMathVal { /** * Constructor. Provide the number whose absolute value to calculate. */ public Abs(Val val) { super(val); } protected Class getType(Class c) { Class wrap = Filters.wrap(c); if (wrap == Integer.class || wrap == Float.class || wrap == Double.class || wrap == Long.class || wrap == BigDecimal.class || wrap == BigInteger.class) return Filters.unwrap(c); return int.class; } protected Object operate(Object o, Class c) { c = Filters.wrap(c); if (c == Integer.class) return Math.abs(((Number) o).intValue()); if (c == Float.class) return Float.valueOf(Math.abs(((Number) o).floatValue())); if (c == Double.class) return Double.valueOf(Math.abs(((Number) o).doubleValue())); if (c == Long.class) return Math.abs(((Number) o).longValue()); if (c == BigDecimal.class) return ((BigDecimal) o).abs(); if (c == BigInteger.class) return ((BigInteger) o).abs(); // default to int return Math.abs(((Number) o).intValue()); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Extension.java0000644000000000000000000000544412133327270027075 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * A value produced from evaluating a custom extension. * * @author Abe White */ class Extension extends Val { private final FilterListener _listener; private final Val _target; private final Val _arg; /** * Constructor. Supply filter listener, its target value, and * its argument value, if any. */ public Extension(FilterListener listener, Val target, Val arg) { _listener = listener; _target = target; _arg = arg; } public Class getType() { Class targetClass = (_target == null) ? null : _target.getType(); return _listener.getType(targetClass, getArgTypes()); } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object target = null; Class targetClass = null; if (_target != null) { target = _target.eval(candidate, orig, ctx, params); targetClass = _target.getType(); } Object arg = null; if (_arg != null) arg = _arg.eval(candidate, orig, ctx, params); return _listener.evaluate(target, targetClass, getArgs(arg), getArgTypes(), candidate, ctx); } private Class[] getArgTypes() { if (_arg == null) return null; if (_arg instanceof Args) return ((Args) _arg).getTypes(); return new Class[]{ _arg.getType() }; } private Object[] getArgs(Object arg) { if (arg == null) return null; if (_arg instanceof Args) return (Object[]) arg; return new Object[]{ arg }; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); if (_target != null) _target.acceptVisit(visitor); if (_arg != null) _arg.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/StringContains.java0000644000000000000000000000357712133327270030073 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Tests if the target contains the given argument. The argument must be * a constant. * Examples:
    * "address.street.ext:stringContains (\"main\")" * * * @deprecated Use matches() instead. * @nojavadoc */ public class StringContains implements FilterListener { public static final String TAG = "stringContains"; public String getTag() { return TAG; } public boolean expectsArguments() { return true; } public boolean expectsTarget() { return true; } public Object evaluate(Object target, Class targetClass, Object[] args, Class[] argClasses, Object candidate, StoreContext ctx) { if (target == null || args[0] == null) return Boolean.FALSE; if (target.toString().indexOf(args[0].toString()) != -1) return Boolean.TRUE; return Boolean.FALSE; } public Class getType(Class targetClass, Class[] argClasses) { return boolean.class; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java0000644000000000000000000000467312133327270026200 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.io.Serializable; import org.apache.openjpa.meta.ClassMetaData; /** * Interface for any non-operator in a query filter, including * constants, variables, and object fields. * * @author Abe White */ public interface Value extends Serializable { /** * Return the expected type for this value, or Object if * the type is unknown. */ public Class getType(); /** * Set the implicit type of the value, based on how it is used in the * filter. This method is only called on values who return * Object from {@link #getType}. */ public void setImplicitType(Class type); /** * Return true if this value is a variable. */ public boolean isVariable(); /** * Return true if this value is an aggregate. */ public boolean isAggregate(); /** * Return true if this value is an XML Path. */ public boolean isXPath(); /** * Return any associated persistent type. */ public ClassMetaData getMetaData(); /** * Associate a persistent type with this value. */ public void setMetaData(ClassMetaData meta); /** * Accept a visit from a tree visitor. */ public void acceptVisit(ExpressionVisitor visitor); /** * Return select item alias */ public String getAlias(); /** * Set select item alias */ public void setAlias(String alias); /** * Return 'this' concrete class if alias is set, otherwise null */ public Value getSelectAs(); public Path getPath(); public String getName(); } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BindVariableAndExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BindVariableAndExpres0000644000000000000000000000563312133327270030335 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Iterator; import org.apache.openjpa.kernel.StoreContext; /** * Any contains(var) expression must be followed by at least one * AND clause using the variable 'var'. This expression type represents * one of those and AND clauses. It is responsible for evaluating the * right subexpression for every possible value of the variable. * * @author Abe White */ class BindVariableAndExpression extends AndExpression { /** * Constructor. Provide expression binding the variable and the * expression it is AND'd with. */ public BindVariableAndExpression(BindVariableExpression var, Exp exp) { super(var, exp); } protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { // execute the tree for every element in the variable's collection; // the variable is aliased to the current element before each // iteration so that variable paths within the tree can // use the current value; the expression is true if true for any // value of the collection // if the collection is empty it cannot contain any variable BindVariableExpression bind = (BindVariableExpression) getExpression1(); Collection vals = bind.getVariableValues(candidate, orig, ctx, params); if (vals == null || vals.isEmpty()) return false; // the subtree is true if true for any variable in the collection BoundVariable var = bind.getVariable(); for (Iterator itr = vals.iterator(); itr.hasNext();) { if (!var.setValue(itr.next())) continue; if (getExpression2().evaluate(candidate, orig, ctx, params)) return true; } return false; } protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { if (candidates == null || candidates.isEmpty()) return false; Object obj = candidates.iterator().next(); return eval(obj, obj, ctx, params); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Cast.java0000644000000000000000000000430112133327270026002 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * Represents a cast. * * @author Abe White */ class Cast extends Val { private final Val _val; private final Class _cast; /** * Constructor. Provide value to cast and type to cast to. */ public Cast(Val val, Class cast) { _val = val; _cast = cast; } public Class getType() { return _cast; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return Filters.convert(_val.eval(candidate, orig, ctx, params), _cast); } protected Collection eval(Collection candidates, Object orig, StoreContext ctx, Object[] params) { Collection res = _val.eval(candidates, orig, ctx, params); if (res == null || res.isEmpty()) return res; Collection casts = new ArrayList(res.size()); for (Iterator itr = res.iterator(); itr.hasNext();) casts.add(Filters.convert(itr.next(), _cast)); return casts; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GeneralCase.java0000644000000000000000000000565112133327270027272 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.util.Localizer; /** * An in-memory representation of a general case expression * * @author Catalina Wei */ class GeneralCase extends Val { private static final Localizer _loc = Localizer.forPackage( GeneralCase.class); private final Exp[] _exp; private final Val _val; public GeneralCase(Exp[] exp, Val val) { _exp = exp; _val = val; } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { for (int i = 0; i < _exp.length; i++) { boolean compare = ((WhenCondition) _exp[i]).getExp(). eval(candidate, orig, ctx, params); if (compare) return ((WhenCondition) _exp[i]).getVal(). eval(candidate, orig, ctx, params); else continue; } return _val.eval(candidate, orig, ctx, params); } protected Object eval(Object candidate,StoreContext ctx, Object[] params) { for (int i = 0; i < _exp.length; i++) { boolean compare = ((WhenCondition) _exp[i]).getExp(). eval(candidate, null, ctx, params); if (compare) return ((WhenCondition) _exp[i]).getVal(). eval(candidate, null, ctx, params); else continue; } return _val.eval(candidate, null, ctx, params); } public Class getType() { Class c1 = _val.getType(); for (int i = 0; i < _exp.length; i++) { Class c2 = ((WhenCondition) _exp[i]).getVal().getType(); c1 = Filters.promote(c1, c2); } return c1; } public void setImplicitType(Class type) { } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); for (int i = 0; i < _exp.length; i++) _exp[i].acceptVisit(visitor); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Multiply.java0000644000000000000000000000242212133327270026731 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; /** * Value produced by two values being multiplied together. * * @author Abe White */ class Multiply extends MathVal { /** * Constructor. Provide the values to multiply. */ public Multiply(Val val1, Val val2) { super(val1, val2); } protected Object operate(Object o1, Class c1, Object o2, Class c2) { return Filters.multiply(o1, c1, o2, c2); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.jav0000644000000000000000000003423112133327270030443 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Date; import org.apache.openjpa.meta.ClassMetaData; /** * The ExpressionFactory must be implemented by a particular runtime * to form {@link Expression}s in its native query language. * * @author Abe White * @nojavadoc */ public interface ExpressionFactory { /** * Return a blank expression; this is used when the filter is empty. */ public Expression emptyExpression(); /** * Return the given value as an expression. */ public Expression asExpression(Value bool); /** * Return an expression representing the given condition. */ public Expression equal(Value v1, Value v2); /** * Return an expression representing the given condition. */ public Expression notEqual(Value v1, Value v2); /** * Return an expression representing the given condition. */ public Expression lessThan(Value v1, Value v2); /** * Return an expression representing the given condition. */ public Expression greaterThan(Value v1, Value v2); /** * Return an expression representing the given condition. */ public Expression lessThanEqual(Value v1, Value v2); /** * Return an expression representing the given condition. */ public Expression greaterThanEqual(Value v1, Value v2); /** * Return an expression representing the given condition. */ public Expression isEmpty(Value target); /** * Return an expression representing the given condition. */ public Expression isNotEmpty(Value target); /** * Return an expression representing the given condition. */ public Expression contains(Value coll, Value arg); /** * Return an expression representing the given condition. */ public Expression containsKey(Value map, Value arg); /** * Return an expression representing the given condition. */ public Expression containsValue(Value map, Value arg); /** * Return an expression representing the given condition. */ public Value getMapValue(Value map, Value arg); /** * Return whether the first value is an instance of the given class. */ public Expression isInstance(Value obj, Class c); /** * Return the two expressions AND'd together. */ public Expression and(Expression exp1, Expression exp2); /** * Return the two expressions OR'd together. */ public Expression or(Expression exp1, Expression exp2); /** * Return the inverse of this expression. */ public Expression not(Expression exp); /** * Bind the given variable to the given collection value. */ public Expression bindVariable(Value var, Value coll); /** * Bind the given variable to the key set of the given map value. */ public Expression bindKeyVariable(Value var, Value map); /** * Bind the given variable to the value set of the given map value. */ public Expression bindValueVariable(Value var, Value map); /** * Return whether the first string ends with the second. */ public Expression endsWith(Value str1, Value str2); /** * Return whether the string matches the matching pattern. * * @param str the value to compare * @param regexp the pattern against which to compare * @param single the token that signifies a single-character match * @param multi the token that signifies a multi-character match * @param escape the escape token that escapes the matching tokens */ public Expression matches(Value str, Value regexp, String single, String multi, String escape); /** * Return whether the string does not match the given pattern. * * @param str the value to compare * @param regexp the pattern against which to compare * @param single the token that signifies a single-character match * @param multi the token that signifies a multi-character match * @param escape the escape token that escapes the matching tokens */ public Expression notMatches(Value str, Value regexp, String single, String multi, String escape); /** * Return whether the first string starts with the second. */ public Expression startsWith(Value str1, Value str2); /** * Returns the number of characters in the String value. */ public Value stringLength(Value str); /** * Trims the specified specified trimChar from the specified value. * * @param str the value from which to trim * @param trimChar the characters to trim off * @param where which side of the String to trim: null * indicates both sides, true indicates * leading, and false indicates trailing */ public Value trim(Value str, Value trimChar, Boolean where); /** * Return a subquery. Paths for the candidates of the subquery are * created with {@link #newPath(Value)}, passing in the subquery as the * value. * * @param candidate the candidate class of the subquery * @param subs whether the query includes subclasses * @param alias the alias given to the query candidate class */ public Subquery newSubquery(ClassMetaData candidate, boolean subs, String alias); /** * Return a value representing a path which will consist * of a chain of 1 or more field names starting in the namespace of the * candidate class.
    Example: parent.address.city */ public Path newPath(); /** * Return a value representing a path which will consist * of a chain of 1 or more field names starting in the namespace of the * given value.
    Example: var.address.city */ public Path newPath(Value val); /** * Return a value representing the given constant, which will be * a {@link Number}, {@link String}, or {@link Boolean} instance. */ public Literal newLiteral(Object val, int parseType); /** * Return a value representing this. */ public Value getThis(); /** * Return a value representing null. */ public Value getNull(); /** * Return a value representing the current date. */ public Value getCurrentDate(Class dateType); /** * Return a value representing the current time. */ public Value getCurrentTime(Class timeType); /** * Return a value representing the current timestamp. */ public Value getCurrentTimestamp(Class timestampType); /** * Return a value representing a parameter for the given value. The * type may be Object if the parameter is not declared. */ public Parameter newParameter(Object name, Class type); /** * Return a value representing a collection-valued parameter. The * type may be Object if the parameter is not declared. */ public Parameter newCollectionValuedParameter(Object name, Class type); /** * Return the value of the given extension. */ public Value newExtension(FilterListener listener, Value target, Value args); /** * Return the value of the given function. */ public Value newAggregate(AggregateListener listener, Value args); /** * Return a function argument list consisting of the given values, either * of which may itself be an argument list. */ public Arguments newArgumentList(Value arg1, Value arg2); /** * Return a function argument list consisting of the given values, any * of which may itself be an argument list. */ public Arguments newArgumentList(Value... values); /** * Return an unbound variable. This method will only be called once for * a given named unbound variable. The type may be Object * if the variable is not declared. */ public Value newUnboundVariable(String name, Class type); /** * This method will be called only once per variable bound in a * contains clause, and the returned value will be reused * for any further instances of the variable in subexpression of the * filter string. The type may be Object if the variable is * not declared. */ public Value newBoundVariable(String name, Class type); /** * Cast the value to the given class. */ public Value cast(Value obj, Class cls); /** * Return a value representing the two values added together. */ public Value add(Value num1, Value num2); /** * Return a value representing the second value subtracted from the first. */ public Value subtract(Value num1, Value num2); /** * Return a value representing the two values multiplied together. */ public Value multiply(Value num1, Value num2); /** * Return a value representing the first value divided by the first one. */ public Value divide(Value num1, Value num2); /** * Return a value representing the first value mod'd by the second one. */ public Value mod(Value num1, Value num2); /** * Return a value representing the absolute value of the given one. */ public Value abs(Value num); /** * Return a value representing the indexOf (LOCATE in JPQL) function on * the given target with the given args. * The optional second argument is one-based. */ public Value indexOf(Value str, Value args); /** * Return a value representing the concatenation of * the given target with the given args. */ public Value concat(Value str, Value args); /** * Return the square root of the given value. */ public Value sqrt(Value num); /** * Return a value representing the substring function on * the given target with the given args. Unlike as with {@link String#substring}, * the start index is one-based, and the second argument is the length. */ public Value substring(Value str, Value args); /** * Return the upper case of the given value. */ public Value toUpperCase(Value str); /** * Return the upper case of the given value. */ public Value toLowerCase(Value str); /** * Return the average of the given value for all matches. */ public Value avg(Value num); /** * Return the count of the given value for all matches. */ public Value count(Value obj); /** * Return the max of the given value for all matches. */ public Value max(Value num); /** * Return the max of the given value for all matches. */ public Value min(Value num); /** * Return the max of the given value for all matches. */ public Value sum(Value num); /** * Return an expression representing the given condition. * * @since 0.4.0.0 */ public Value any(Value target); /** * Return an expression representing the given condition. * * @since 0.4.0.0 */ public Value all(Value target); /** * Return an expression representing the given condition. * * @since 0.4.0.0 */ public Value size(Value target); /** * Return an index/position of the given value within a collection/map. * * @since 2.0.0 */ public Value index(Value target); /** * Return the type/class of the given value. * * @since 2.0.0 */ public Value type(Value target); /** * Return the map entry of the given value. * * @since 2.0.0 */ public Value mapEntry(Value key, Value val); /** * Return the map key of the given value */ public Value mapKey(Value key, Value val); /** * Path navigation thru map key */ public Value getKey(Value val); /** * Return distinct values of the given value. This is typically used * within aggregates, for example: max(distinct(path)) * * @since 0.4.0.0 */ public Value distinct (Value obj); /** * Return the object id of the given value. */ public Value getObjectId (Value val); /** * Return a simple case expression */ public Value simpleCaseExpression(Value caseOperand, Expression[] exp, Value val); /** * Return a general case expression */ public Value generalCaseExpression(Expression[] exp, Value val); /** * Return a when condidional clause */ public Expression whenCondition(Expression exp, Value val); /** * Return a when scalar_expression clause */ public Expression whenScalar(Value val1, Value val2); /** * Return a coalesce expression */ public Value coalesceExpression(Value[] val); /** * Return a nullif expression */ public Value nullIfExpression(Value val1, Value val2); /** * Return a value representing the given constant, which will be * a {@link Number}, {@link String}, or {@link Boolean} instance. */ public Literal newTypeLiteral(Object val, int parseType); /** * Return a value representing the given datastore function with the given arguments. */ public Value newFunction(String functionName, Class resultType, Value... args); /** * Return true if the Value is a Type expression and the Type uses joined table strategy. */ public boolean isVerticalType(Value val); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Subtract.java0000644000000000000000000000242512133327270026704 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; /** * Value produced by one value being subtracted from another. * * @author Abe White */ class Subtract extends MathVal { /** * Constructor. Provide the values to subtract. */ public Subtract(Val val1, Val val2) { super(val1, val2); } protected Object operate(Object o1, Class c1, Object o2, Class c2) { return Filters.subtract(o1, c1, o2, c2); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/This.java0000644000000000000000000000237012133327270026023 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Represents the 'this' ptr in a filter. * * @author Abe White */ class This extends Val { public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return orig; } public Class getType() { return getMetaData().getDescribedType(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/UnboundVariable.java0000644000000000000000000000362012133327270030173 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Represents an unbound variable. When the query is evaluated, * expressions containing unbound variables will be * executed once for every element in the type's extent. * * @author Abe White */ class UnboundVariable extends Val { private Class _type = null; private Object _val = null; /** * Constructor. Provide variable name and type. */ public UnboundVariable(Class type) { _type = type; } public boolean isVariable() { return true; } public Class getType() { return _type; } public void setImplicitType(Class type) { _type = type; } /** * Set the variable's current value. Expressions can be evaluated * for every possible object in the extent of each unbound variable * when looking for a match. */ public void setValue(Object value) { _val = value; } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _val; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GreaterThanExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GreaterThanExpression0000644000000000000000000000244512133327270030463 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Expression that compares two others. * * @author Abe White */ class GreaterThanExpression extends CompareExpression { /** * Constructor. Supply values to compare. */ public GreaterThanExpression(Val val1, Val val2) { super(val1, val2); } protected boolean compare(Object o1, Object o2) { if (!(o1 instanceof Comparable)) return false; return ((Comparable) o1).compareTo(o2) > 0; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Mod.java0000644000000000000000000000237212133327270025635 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; /** * Value produced by one value being mod'd by another. * * @author Abe White */ class Mod extends MathVal { /** * Constructor. Provide the values to mod. */ public Mod(Val val1, Val val2) { super(val1, val2); } protected Object operate(Object o1, Class c1, Object o2, Class c2) { return Filters.mod(o1, c1, o2, c2); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Aggregate.java0000644000000000000000000000572312133327270027007 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Collections; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * A value produced from evaluating a result aggregate. * * @author Abe White */ class Aggregate extends Val { private static final Localizer _loc = Localizer.forPackage(Aggregate.class); private final AggregateListener _listener; private final Val _arg; /** * Constructor. Supply aggregate listener and its argument value, if any. */ public Aggregate(AggregateListener listener, Val arg) { _listener = listener; _arg = arg; } public boolean isAggregate() { return true; } public Class getType() { return _listener.getType(getArgTypes()); } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { if (candidate == null) candidate = Collections.EMPTY_LIST; // allow aggregates to be used in filter expressions so long as a // collection is passed in if (candidate instanceof Collection) return eval((Collection) candidate, orig, ctx, params). iterator().next(); throw new UserException(_loc.get("agg-in-filter")); } protected Collection eval(Collection candidates, Object orig, StoreContext ctx, Object[] params) { Collection args = null; if (_arg != null) args = _arg.eval(candidates, orig, ctx, params); Object agg = _listener.evaluate(args, getArgTypes(), candidates, ctx); return Collections.singleton(agg); } private Class[] getArgTypes() { if (_arg == null) return null; if (_arg instanceof Args) return ((Args) _arg).getTypes(); return new Class[]{ _arg.getType() }; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); if (_arg != null) _arg.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/IndexOf.java0000644000000000000000000000413612133327270026452 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Find the index of one string within another. * Index is 1-based. * * @author Abe White */ class IndexOf extends Val { private final Val _val; private final Val _args; /** * Constructor. Provide target string and the arguments to the * indexOf method. */ public IndexOf(Val val, Val args) { _val = val; _args = args; } public Class getType() { return int.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object str = _val.eval(candidate, orig, ctx, params); Object arg = _args.eval(candidate, orig, ctx, params); int idx; if (arg instanceof Object[]) { Object[] args = (Object[]) arg; idx = str.toString().indexOf(args[0].toString(), ((Number) args[1]).intValue() - 1) + 1; } else idx = str.toString().indexOf(arg.toString()) + 1; return idx; } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); _args.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/NullIf.java0000644000000000000000000000560412133327270026310 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * An in-memory representation of a nullif expression * * @author Catalina Wei */ public class NullIf extends Val { private final Val _val1; private final Val _val2; /** * Constructor. */ NullIf(Val val1, Val val2) { _val1 = val1; _val2 = val2; } @Override protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { Object o1 = _val1.eval(candidate, orig, ctx, params); Object o2 = _val2.eval(candidate, orig, ctx, params); if (o1 != null && o2 != null) { Class c = Filters.promote(o1.getClass(), o2.getClass()); o1 = Filters.convert(o1, c); o2 = Filters.convert(o2, c); } if (compare(o1, o2)) return null; else return o1; } protected Object eval(Object candidate, StoreContext ctx, Object[] params) { Object o1 = _val1.eval(candidate, null, ctx, params); Object o2 = _val2.eval(candidate, null, ctx, params); if (o1 != null && o2 != null) { Class c = Filters.promote(o1.getClass(), o2.getClass()); o1 = Filters.convert(o1, c); o2 = Filters.convert(o2, c); } if (compare(o1, o2)) return null; else return o1; } /** * Compare the two values. */ protected boolean compare(Object o1, Object o2) { return (o1 == null && o2 == null) || (o1 != null && o1.equals(o2)); } public Val getVal1() { return _val1; } public Val getVal2() { return _val2; } public Class getType() { return _val1.getType(); } public void setImplicitType(Class type) { } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val1.acceptVisit(visitor); _val2.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/BoundVariable.java0000644000000000000000000000456712133327270027643 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Represents a bound variable. Variables are aliased to the * collection that is stated to contain them in the query. * When the query is evaluated, expressions containing variables will be * executed once for every element in the collection. * * @author Abe White */ class BoundVariable extends Val { private Class _type = null; private Object _val = null; /** * Constructor. Provide variable name and type. */ public BoundVariable(Class type) { _type = type; } /** * Set the value this variable should take for the current iteration. * * @return false if the type is incompatible with the variable's * declared type */ public boolean setValue(Object value) { if (value != null && !_type.isAssignableFrom(value.getClass())) return false; _val = value; return true; } public boolean isVariable() { return true; } public Class getType() { return _type; } public void setImplicitType(Class type) { _type = type; } /** * Cast this value to the given type. */ public void castTo(Class type) { // incompatible types? if (!_type.isAssignableFrom(type) && !type.isAssignableFrom(_type)) throw new ClassCastException(_type.getName()); _type = type; } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _val; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ValuePath.java0000644000000000000000000000320612133327270027004 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Represents a path that begins with a variable or parameter. * * @author Abe White */ class ValuePath extends CandidatePath { private final Val _val; /** * Constructor. Supply context value. */ public ValuePath(Val val) { _val = val; } public Class getCandidateType() { return _val.getType(); } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { // evaluate with the value's value return super.eval(_val.eval(candidate, orig, ctx, params), orig, ctx, params); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GetObjectId.java0000644000000000000000000000312012133327270027231 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import org.apache.openjpa.kernel.StoreContext; /** * Get the oid of an object. * * @author Abe White */ class GetObjectId extends Val { private final Val _val; /** * Constructor. Provide value whose oid to extract. */ public GetObjectId(Val val) { _val = val; } public Class getType() { return Object.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return ctx.getObjectId(_val.eval(candidate, orig, ctx, params)); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Type.java0000644000000000000000000000323512133327270026036 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import java.util.Map; import org.apache.openjpa.kernel.StoreContext; /** * Returns the entity type. * * @author Catalina Wei */ class Type extends Val { private final Val _val; /** * Constructor. Provide target string and the arguments to the * indexOf method. */ public Type(Val val) { _val = val; } public Class getType() { return Class.class; } public void setImplicitType(Class type) { } protected Object eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { _val.eval(candidate, orig, ctx, params); return _val.getType(); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InstanceofExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InstanceofExpression.0000644000000000000000000000412012133327270030416 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; import java.util.Collection; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.StoreContext; /** * Tests whether a value is an instance of a class. * * @author Abe White */ class InstanceofExpression extends Exp { private final Val _val; private final Class _cls; /** * Constructor; supply value and class. */ public InstanceofExpression(Val val, Class cls) { _val = val; _cls = Filters.wrap(cls); } /** * Evaluate the expression for the given context candidate and original * candidate. */ protected boolean eval(Object candidate, Object orig, StoreContext ctx, Object[] params) { return _cls.isInstance(_val.eval(candidate, orig, ctx, params)); } /** * Evaluate the expression for the given group. */ protected boolean eval(Collection candidates, StoreContext ctx, Object[] params) { Collection c = _val.eval(candidates, null, ctx, params); Object o = (c == null || c.isEmpty()) ? null : c.iterator().next(); return _cls.isInstance(o); } public void acceptVisit(ExpressionVisitor visitor) { visitor.enter(this); _val.acceptVisit(visitor); visitor.exit(this); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/LessThanExpression.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/LessThanExpression.ja0000644000000000000000000000243712133327270030372 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel.exps; /** * Expression that compares two others. * * @author Abe White */ class LessThanExpression extends CompareExpression { /** * Constructor. Supply values to compare. */ public LessThanExpression(Val val1, Val val2) { super(val1, val2); } protected boolean compare(Object o1, Object o2) { if (!(o1 instanceof Comparable)) return false; return ((Comparable) o1).compareTo(o2) < 0; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PDeletedFlushedState.java0000644000000000000000000000255412133327272030145 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a persistent instance that has been deleted in the current * transaction, and that has been flushed to the database. * * @author Patrick Linskey */ @SuppressWarnings("serial") class PDeletedFlushedState extends PDeletedState { PCState flush(StateManagerImpl context) { return this; } PCState persist(StateManagerImpl context) { context.eraseFlush(); return PNEW; } public String toString() { return "Persistent-Deleted-Flushed"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java0000644000000000000000000004302412133327272026601 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.UserException; /** * Represents a set of managed objects and their environment. * * @since 0.4.0 * @author Abe White */ public interface StoreContext { /** * Marker bitset to indicate that all field loads should be excluded in * the find methods of this interface. */ public static final BitSet EXCLUDE_ALL = new BitSet(0); public static final int OID_NOVALIDATE = 2 << 0; public static final int OID_NODELETED = 2 << 1; public static final int OID_COPY = 2 << 2; public static final int OID_ALLOW_NEW = 2 << 3; /** * Return the broker for this context, if possible. Note that a broker * will be unavailable in remote contexts, and this method may return null. */ public Broker getBroker(); /** * Return the configuration associated with this context. */ public OpenJPAConfiguration getConfiguration(); /** * Return the (mutable) fetch configuration for loading objects from this * context. */ public FetchConfiguration getFetchConfiguration(); /** * Pushes a new fetch configuration that inherits from the current * fetch configuration onto a stack, and makes the new configuration * the active one. * * @since 1.1.0 * @return the new fetch configuration */ public FetchConfiguration pushFetchConfiguration(); /** * Pushes the fetch configuration argument onto a stack, and makes the new configuration * the active one. * * @since 2.1.1 * @return the new fetch configuration */ public FetchConfiguration pushFetchConfiguration(FetchConfiguration fc); /** * Pops the fetch configuration from the top of the stack, making the * next one down the active one. This returns void to avoid confusion, * since fetch configurations tend to be used in method-chaining * patterns often. * * @since 1.1.0 * @throws UserException if the fetch configuration stack is empty */ public void popFetchConfiguration(); /** * Return the current thread's class loader at the time this context * was obtained. */ public ClassLoader getClassLoader(); /** * Return the lock manager in use. */ public LockManager getLockManager(); /** * Return the store manager in use. This will be a wrapper around the * native store manager, which you can retrieve via * {@link DelegatingStoreManager#getInnermostDelegate}. */ public DelegatingStoreManager getStoreManager(); /** * Return the connection user name. */ public String getConnectionUserName(); /** * Return the connection password. */ public String getConnectionPassword(); /** * Return the instance for the given oid/object , or null if not * found in the L1 cache. * * @param oid the object's id * @return the cached object, or null if not cached */ public Object findCached(Object oid, FindCallbacks call); /** * Find the persistence object with the given oid. If * validate is true, the broker will check the store * for the object, and return null if it does not exist. If * validate is false, this method never returns null. The * broker will either return its cached instance, attempt to create a * hollow instance, or throw an ObjectNotFoundException if * unable to return a hollow instance. * * @param validate if true, validate that the instance exists in the * store and load fetch group fields, otherwise return * any cached or hollow instance */ public Object find(Object oid, boolean validate, FindCallbacks call); /** * Return the objects with the given oids. * * @param oids the oids of the objects to return * @return the objects that were looked up, in the same order as the oids * parameter * @see #find(Object,boolean,FindCallbacks) */ public Object[] findAll(Collection oids, boolean validate, FindCallbacks call); /** * Return the object with the given oid. If present, the * cached instance will be returned. Otherwise, the instance will be * initialized through the store as usual; however, in this case * the store will be passed the given execution data, and the * system will load the object according to the given fetch configuration * (or the context's configuration, if the given one is null). * Fields can optionally be excluded from required loading using the * exclude mask. By default this method does not find new * unflushed instances, validates, and does not throw an exception * if a cached instance has been deleted concurrently. These options * are controllable through the given OID_XXX flags. */ public Object find(Object oid, FetchConfiguration fetch, BitSet exclude, Object edata, int flags); /** * Return the objects with the given oids. * * @see #find(Object,FetchConfiguration,BitSet,Object,int) */ public Object[] findAll(Collection oids, FetchConfiguration fetch, BitSet exclude, Object edata, int flags); /** * Return an iterator over all instances of the given type. The iterator * should be closed with {@link org.apache.openjpa.util.ImplHelper#close} * when no longer needed. This method delegates to * {@link StoreManager#executeExtent}. */ public Iterator extentIterator(Class cls, boolean subs, FetchConfiguration fetch, boolean ignoreChanges); /** * Immediately load the given object's persistent fields. One might * use this action to make sure that an instance's fields are loaded * before transitioning it to transient. Note that this action is not * recursive. Any related objects that are loaded will not necessarily * have their fields loaded. Unmanaged target is ignored. * * @param fgOnly indicator as to whether to retrieve only fields * in the current fetch groups, or all fields * @see #retrieve */ public void retrieve(Object pc, boolean fgOnly, OpCallbacks call); /** * Retrieve the given objects' persistent state. Unmanaged targets are * ignored. * * @param fgOnly indicator as to whether to retrieve only fields * @see #retrieve */ public void retrieveAll(Collection objs, boolean fgOnly, OpCallbacks call); /** * Make the given instance embedded. * * @param obj the instance to embed; may be null to create a new instance * @param id the id to give the embedded state manager; may be * null for default * @param owner the owning state manager * @param ownerMeta the value in which the object is embedded * @return the state manager for the embedded instance */ public OpenJPAStateManager embed(Object obj, Object id, OpenJPAStateManager owner, ValueMetaData ownerMeta); /** * Return the application or datastore identity class the given persistent * class uses for object ids. */ public Class getObjectIdType(Class cls); /** * Create a new object id instance from the given value. * * @param cls the persistent class that uses this identity value * @param val an object id instance, stringified object id, or primary * key value */ public Object newObjectId(Class cls, Object val); /** * Return the set of classes that have been made persistent in the current * transaction. * * @since 0.3.4 */ public Collection> getPersistedTypes(); /** * Return the set of classes that have been deleted in the current * transaction. * * @since 0.3.4 */ public Collection> getDeletedTypes(); /** * Return the set of classes for objects that have been modified * in the current transaction. * * @since 0.3.4 */ public Collection> getUpdatedTypes(); /** * Return a list of all managed instances. */ public Collection getManagedObjects(); /** * Return a list of current transaction instances. */ public Collection getTransactionalObjects(); /** * Return a list of instances which will become transactional upon * the next transaction. */ public Collection getPendingTransactionalObjects(); /** * Return a list of current dirty instances. */ public Collection getDirtyObjects(); /** * Whether to maintain the order in which objects are dirtied for * {@link #getDirtyObjects}. Default is the store manager's decision. */ public boolean getOrderDirtyObjects(); /** * Whether to maintain the order in which objects are dirtied for * {@link #getDirtyObjects}. Default is the store manager's decision. */ public void setOrderDirtyObjects(boolean order); /** * Return the state manager for the given instance. Includes objects * made persistent in the current transaction. If obj is not * a managed type or is managed by another context, throw an exception. */ public OpenJPAStateManager getStateManager(Object obj); /** * Return the lock level of the specified object. */ public int getLockLevel(Object obj); /** * Returns the current version indicator for o. */ public Object getVersion(Object obj); /** * Return whether the given object is dirty. */ public boolean isDirty(Object obj); /** * Return whether the given object is transactional. */ public boolean isTransactional(Object obj); /** * Make the given object transactional. * * @param pc instance to make transactional * @param updateVersion if true, the instance's version will be * incremented at the next flush */ public void transactional(Object pc, boolean updateVersion, OpCallbacks call); /** * Make the given objects transactional. * * @param objs instances to make transactional * @param updateVersion if true, the instance's version will be * incremented at the next flush */ public void transactionalAll(Collection objs, boolean updateVersion, OpCallbacks call); /** * Make the given object non-transactional. */ public void nontransactional(Object pc, OpCallbacks call); /** * Make the given objects nontransactional. */ public void nontransactionalAll(Collection objs, OpCallbacks call); /** * Return whether the given object is persistent. */ public boolean isPersistent(Object obj); /** * Return whether the given object is a newly-created instance registered * with broker. */ public boolean isNew(Object obj); /** * Return whether the given object is deleted. */ public boolean isDeleted(Object obj); /** * Return the oid of the given instance. */ public Object getObjectId(Object obj); /** * Detach mode constant to determine which fields are part of the * detached graph. Defaults to {@link DetachState#DETACH_LOADED}. */ public int getDetachState(); /** * Detach mode constant to determine which fields are part of the * detached graph. Defaults to {@link DetachState#DETACH_LOADED}. */ public void setDetachState(int mode); /** * Whether objects accessed during this transaction will be added to the * store cache. Defaults to true. * * @since 0.3.4 */ public boolean getPopulateDataCache(); /** * Whether to populate the store cache with objects used by this * transaction. Defaults to true. * * @since 0.3.4 */ public void setPopulateDataCache(boolean cache); /** * Whether memory usage is reduced during this transaction at the expense * of tracking changes at the type level instead of the instance level, * resulting in more aggressive cache invalidation. * * @since 1.0.0 */ public boolean isTrackChangesByType(); /** * If a large number of objects will be created, modified, or deleted * during this transaction setting this option to true will reduce memory * usage if you perform periodic flushes by tracking changes at the type * level instead of the instance level, resulting in more aggressive cache * invalidation. Upon transaction commit the data cache will have to * more aggressively flush objects. The store cache will have to flush * instances of objects for each class of object modified during the * transaction. A side benefit of large transaction mode is that smaller * update messages can be used for * {@link org.apache.openjpa.event.RemoteCommitEvent}s. Defaults to false. * * @since 1.0.0 */ public void setTrackChangesByType(boolean largeTransaction); /** * Whether this context is using managed transactions. */ public boolean isManaged(); /** * Whether a logical transaction is active. */ public boolean isActive(); /** * Whether a data store transaction is active. */ public boolean isStoreActive(); /** * Begin a data store transaction. */ public void beginStore(); /** * Whether the broker has a dedicated connection based on the configured * connection retain mode and transaction status. */ public boolean hasConnection(); /** * Return the connection in use by the context, or a new connection if none. */ public Object getConnection(); /** * Synchronizes on an internal lock if the * Multithreaded flag is set to true. Make sure to call * {@link #unlock} in a finally clause of the same method. */ public void lock (); /** * Releases the internal lock. */ public void unlock (); /** * Return the 'JTA' connectionFactoryName */ public String getConnectionFactoryName(); /** * Set the 'JTA' ConnectionFactoryName. */ public void setConnectionFactoryName(String connectionFactoryName); /** * Return the 'NonJTA' ConnectionFactoryName. */ public String getConnectionFactory2Name(); /** * Set the 'NonJTA' ConnectionFactoryName. */ public void setConnectionFactory2Name(String connectionFactory2Name); /** * Return the 'JTA' ConnectionFactory, looking it up from JNDI if needed. * * @return the JTA connection factory or null if connectionFactoryName is blank. */ public Object getConnectionFactory(); /** * Return the 'NonJTA' ConnectionFactory, looking it up from JNDI if needed. * * @return the NonJTA connection factory or null if connectionFactoryName is blank. */ public Object getConnectionFactory2(); /** * Indicate whether the oid can be found in the StoreContext's L1 cache or in the StoreManager cache. * @param oid List of ObjectIds for PersistenceCapables which may be found in memory. * @return true if the oid is available in memory (cached) otherwise false. * @since 2.0.0. */ public boolean isCached(List oid); /** * Affirms if this context will allow its managed instances to refer instances * that are managed by other contexts. * Note: Some specification (such as JPA) does not warranty predictable * behavior when strict group-like property of a persistent context (where managed * instances can only refer to instances managed by the same context). * Please be aware of consequences when the flag is set to true. * * @since 2.1 */ public void setAllowReferenceToSiblingContext(boolean flag); /** * Affirms if this context will allow its managed instances to refer instances * that are managed by other contexts. * * @return false by default. * * @since 2.1 */ public boolean getAllowReferenceToSiblingContext(); /** * Set to true if the merge operation should trigger * a @PostLoad lifecycle event. * @param allow PostLoad lifecycle events to be triggered on a merge operation */ public void setPostLoadOnMerge(boolean allow); /** * Force sending a @PostLoad lifecycle event while merging. * * @return false by default * * @since 2.2 */ public boolean getPostLoadOnMerge(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DataCacheStoreMode.java0000644000000000000000000000264212133327272027560 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * DataCache Store modes */ public enum DataCacheStoreMode { /** * Store updates, inserts and deletes in the DataCache. The DataCache will * not be refreshed when data is read from the database. */ USE, /** * Write updates, inserts and deletes directly to the database. The * DataCache will not be aware of these changes and may need to be * refreshed. */ BYPASS, /** * Store updates, inserts and deletes in the DataCache. Entities which are * read from the database will be refreshed in the DataCache. */ REFRESH } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCResultObjectProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCResultObjectProvider.jav0000644000000000000000000000272212133327272030342 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.lib.rop.ResultObjectProvider; /** * Variant of {@link ResultObjectProvider} that populates a * {@link OpenJPAStateManager} object in an application-defined manner. * Implementations of this interface can be used to customize data loading. * * @author Patrick Linskey * @see AbstractPCResultObjectProvider */ public interface PCResultObjectProvider extends ResultObjectProvider { /** * Initializes the state manager. * * @see StoreManager#initialize */ public void initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch) throws Exception; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ObjectFactory.java0000644000000000000000000000213412133327272026673 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * An interface to create objects that are used by result processing. * @see FillStrategy.Factory * * @author Pinaki Poddar * @since 2.0.0 * * @param the type created by this factory. * */ public interface ObjectFactory { public T newInstance(); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.jav0000644000000000000000000001352012133327272030350 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import java.util.Collection; import java.util.List; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; /** * Base class for store manager decorators that delegate to another * store manager for some operations. * * @author Abe White */ public abstract class DelegatingStoreManager implements StoreManager { private final StoreManager _store; private final DelegatingStoreManager _del; /** * Constructor. Supply delegate. */ public DelegatingStoreManager(StoreManager store) { _store = store; if (store instanceof DelegatingStoreManager) _del = (DelegatingStoreManager) _store; else _del = null; } /** * Return the wrapped store manager. */ public StoreManager getDelegate() { return _store; } /** * Return the base underlying native store manager. */ public StoreManager getInnermostDelegate() { return (_del == null) ? _store : _del.getInnermostDelegate(); } public int hashCode() { return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingStoreManager) other = ((DelegatingStoreManager) other).getInnermostDelegate(); return getInnermostDelegate().equals(other); } public void setContext(StoreContext ctx) { _store.setContext(ctx); } public void beginOptimistic() { _store.beginOptimistic(); } public void rollbackOptimistic() { _store.rollbackOptimistic(); } public void begin() { _store.begin(); } public void commit() { _store.commit(); } public void rollback() { _store.rollback(); } public boolean exists(OpenJPAStateManager sm, Object context) { return _store.exists(sm, context); } public boolean syncVersion(OpenJPAStateManager sm, Object context) { return _store.syncVersion(sm, context); } public boolean initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch, Object context) { return _store.initialize(sm, state, fetch, context); } public boolean load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch, int lockLevel, Object context) { return _store.load(sm, fields, fetch, lockLevel, context); } public Collection loadAll(Collection sms, PCState state, int load, FetchConfiguration fetch, Object context) { return _store.loadAll(sms, state, load, fetch, context); } public void beforeStateChange(OpenJPAStateManager sm, PCState fromState, PCState toState) { _store.beforeStateChange(sm, fromState, toState); } public Collection flush(Collection sms) { return _store.flush(sms); } public boolean assignObjectId(OpenJPAStateManager sm, boolean preFlush) { return _store.assignObjectId(sm, preFlush); } public boolean assignField(OpenJPAStateManager sm, int field, boolean preFlush) { return _store.assignField(sm, field, preFlush); } public Class getManagedType(Object oid) { return _store.getManagedType(oid); } public Class getDataStoreIdType(ClassMetaData meta) { return _store.getDataStoreIdType(meta); } public Object copyDataStoreId(Object oid, ClassMetaData meta) { return _store.copyDataStoreId(oid, meta); } public Object newDataStoreId(Object oidVal, ClassMetaData meta) { return _store.newDataStoreId(oidVal, meta); } public Object getClientConnection() { return _store.getClientConnection(); } public void retainConnection() { _store.retainConnection(); } public void releaseConnection() { _store.releaseConnection(); } public ResultObjectProvider executeExtent(ClassMetaData meta, boolean subclasses, FetchConfiguration fetch) { return _store.executeExtent(meta, subclasses, fetch); } public StoreQuery newQuery(String language) { return _store.newQuery(language); } public FetchConfiguration newFetchConfiguration() { return _store.newFetchConfiguration(); } public void close() { _store.close(); } public int compareVersion(OpenJPAStateManager state, Object v1, Object v2) { return _store.compareVersion(state, v1, v2); } public Seq getDataStoreIdSequence(ClassMetaData forClass) { return _store.getDataStoreIdSequence(forClass); } public Seq getValueSequence(FieldMetaData fmd) { return _store.getValueSequence(fmd); } public boolean cancelAll() { return _store.cancelAll(); } public boolean isCached(List oids, BitSet edata) { return _store.isCached(oids, edata); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Seq.java0000644000000000000000000000447712133327272024701 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.meta.ClassMetaData; /** * Internal OpenJPA sequence interface. * * @author Abe White */ public interface Seq extends Closeable { public static final int TYPE_DEFAULT = 0; public static final int TYPE_NONTRANSACTIONAL = 1; public static final int TYPE_TRANSACTIONAL = 2; public static final int TYPE_CONTIGUOUS = 3; /** * Set the type of sequence. */ public void setType(int type); /** * Return the next value in the sequence. * * @param ctx the current context * @param cls if this is a datastore identity sequence, the * persistent class the identity value is for; else null */ public Object next(StoreContext ctx, ClassMetaData cls); /** * Return the current value of the sequence, or null if not available. * * @param ctx the current context * @param cls if this is a datastore identity sequence, the * persistent class the identity value is for; else null */ public Object current(StoreContext ctx, ClassMetaData cls); /** * Allocate additional values efficiently. * * @param ctx the current context * @param cls if this is a datastore identity sequence, the * persistent class the identity value is for; else null */ public void allocate(int additional, StoreContext ctx, ClassMetaData cls); /** * Free resources used by this sequence. */ public void close (); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ClearFieldManager.java0000644000000000000000000000372612133327272027432 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * FieldManager that responds to all fetch methods with the default value * for that field; used to clear the state of managed instances. * * @author Abe White */ class ClearFieldManager extends AbstractFieldManager { private static final ClearFieldManager _single = new ClearFieldManager(); public static ClearFieldManager getInstance() { return _single; } protected ClearFieldManager() { } public boolean fetchBooleanField(int field) { return false; } public byte fetchByteField(int field) { return 0; } public char fetchCharField(int field) { return 0; } public double fetchDoubleField(int field) { return 0D; } public float fetchFloatField(int field) { return 0F; } public int fetchIntField(int field) { return 0; } public long fetchLongField(int field) { return 0L; } public Object fetchObjectField(int field) { return null; } public short fetchShortField(int field) { return 0; } public String fetchStringField(int field) { return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/TransientState.java0000644000000000000000000000307012133327272027105 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents a transient instance; this state lasts only through * the {@link #initialize} method, which immediately removes the * persistence capable instance from management by the OpenJPA runtime. * * @author Abe White */ @SuppressWarnings("serial") class TransientState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { // mark r/w ok, remove from management context.unproxyFields(); context.getPersistenceCapable().pcReplaceStateManager(null); context.getBroker().setStateManager(context.getId(), context, BrokerImpl.STATUS_TRANSIENT); } public String toString() { return "Transient"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/OpenJPASavepoint.java0000644000000000000000000000744612133327272027275 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * Represents a savepoint where operations afterwards can be rolled * back and restored to this point * * @author Steve Kim * @since 0.3.4 */ @SuppressWarnings("serial") public class OpenJPASavepoint implements Serializable { private final Broker _broker; private final String _name; private final boolean _copy; private Map _saved; /** * Constructor. Indicate whether to copy field data into memory. */ public OpenJPASavepoint(Broker broker, String name, boolean copy) { _broker = broker; _name = name; _copy = copy; } /** * Return the Broker associated with this savepoint. */ public Broker getBroker() { return _broker; } /** * Return the name for this savepoint. */ public String getName() { return _name; } /** * Whether this savepoint copies the field values of retained instances. */ public boolean getCopyFieldState() { return _copy; } /** * Return the map of states to savepoint data. */ protected Map getStates() { return _saved; } /** * Set this savepoint, saving any state for the passed-in * {@link OpenJPAStateManager}s as necessary. */ public void save(Collection states) { if (_saved != null) throw new IllegalStateException(); _saved = new HashMap((int) (states.size() * 1.33 + 1)); for (StateManagerImpl sm : states) { _saved.put(sm, new SavepointFieldManager(sm, _copy)); } } /** * Release this savepoint and any associated resources. Releases * will happen in reverse order of creation. * * @param user if true, user initiated, otherwise a side effect of * another savepoint's release/rollback */ public void release(boolean user) { _saved = null; } /** * Handle the rolled back state, returning saved data. * Subclasses should return the collection returned from this method. * * @param previous previous savepoints set in the transaction */ public Collection rollback(Collection previous) { Map saved; if (previous.isEmpty()) saved = _saved; else { // merge all changes into one collection, allowing for later // SavepointFieldManagers to replace previous ones. saved = new HashMap(); for (OpenJPASavepoint savepoint : previous) saved.putAll(savepoint.getStates()); saved.putAll(_saved); } _saved = null; return saved.values (); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryFlushModes.java0000644000000000000000000000411012133327272027230 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.conf.OpenJPAConfiguration; /** * Constants for determining when to flush before queries. * * @author Abe White * @since 0.4.0 */ public interface QueryFlushModes { /** * Constant denoting that queries should flush data to the * database automatically whenever OpenJPA determines that relevant * modifications have been made and IgnoreCache is * false. See * {@link OpenJPAConfiguration#getFlushBeforeQueries} * for more info. */ public static final int FLUSH_TRUE = 0; /** * Constant denoting that queries should never flush data * to the database automatically before executing a query, but * should instead execute queries in-memory if necessary. See * {@link OpenJPAConfiguration#getFlushBeforeQueries} for more info. */ public static final int FLUSH_FALSE = 1; /** * Constant denoting that queries should flush data to the * database automatically when OpenJPA determines that relevant * modifications have been made and the current * context already has a dedicated connection. See * {@link OpenJPAConfiguration#getFlushBeforeQueries} for more info. */ public static final int FLUSH_WITH_CONNECTION = 2; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java0000644000000000000000000004436612133327272026541 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import java.util.Collection; import java.util.List; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.ValueStrategies; /** * Interface to be implemented by data store mechanisms to interact with * this runtime. * * @author Abe White */ public interface StoreManager extends Closeable { public static final int VERSION_LATER = 1; public static final int VERSION_EARLIER = 2; public static final int VERSION_SAME = 3; public static final int VERSION_DIFFERENT = 4; public static final int FORCE_LOAD_NONE = 0; public static final int FORCE_LOAD_DFG = 1; public static final int FORCE_LOAD_REFRESH = 3; public static final int FORCE_LOAD_ALL = 2; /** * Set a reference to the corresponding context. This method * will be called before the store manager is used. The store manager * is responsible for pulling any necessary configuration data from the * context, including the transaction mode and connection retain mode. */ public void setContext(StoreContext ctx); /** * Notification that an optimistic transaction has started. This method * does not replace the {@link #begin} method, which will still be called * when a true data store transaction should begin. */ public void beginOptimistic(); /** * Notification that an optimistic transaction was rolled back before * a data store transaction ever began. */ public void rollbackOptimistic(); /** * Begin a data store transaction. After this method is called, * it is assumed that all further operations are operating in a single * transaction that can be committed or rolled back. If optimistic * transactions are in use, this method will only be called when the * system requires a transactionally consistent connection due to a * user request to flush or commit the transaction. In this case, it * is possible that the optimistic transaction does not have the latest * versions of all instances (i.e. another transaction has modified the * same instances and committed since the optimistic transaction started). * On commit, an exception must be thrown on any attempt to overwrite * data for an instance with an older version. * * @since 0.2.5 */ public void begin(); /** * Commit the current data store transaction. */ public void commit(); /** * Rollback the current data store transaction. */ public void rollback(); /** * Verify that the given instance exists in the data store; return false * if it does not. */ public boolean exists(OpenJPAStateManager sm, Object edata); /** * Verify that the given instance exists in the data store in memory; return false * if it does not. When an object is found in memory the corresponding element of * the BitSet is set to 1. */ public boolean isCached(List oids, BitSet edata); /** * Update the version information in the given state manager to the * version stored in the data store. * * @param sm the instance to check * @param edata the current execution data, or null if not * given to the calling method of the context * @return true if the instance still exists in the * datastore and is up-to-date, false otherwise */ public boolean syncVersion(OpenJPAStateManager sm, Object edata); /** * Initialize the given state manager. The object id of the * state manager will be set, and the state manager's metadata be set to * the class of the instance to load, or possibly one of its superclasses. * Initialization involves first calling the * {@link OpenJPAStateManager#initialize} method with * a new instance of the correct type constructed with the * {@link org.apache.openjpa.enhance.PCRegistry#newInstance(Class, * org.apache.openjpa.enhance.StateManager, boolean)} method * (this will reset the state manager's metadata if the actual type was a * subclass). After instance initialization, load any the fields for the * given fetch configuration that can be efficiently retrieved. If any of * the configured fields are not loaded in this method, they will be * loaded with a subsequent call to {@link #load}. If this method is * called during a data store transaction, the instance's database record * should be locked. Version information can be loaded if desired through * the {@link OpenJPAStateManager#setVersion} method. * * @param sm the instance to initialize * @param state the lifecycle state to initialize the state manager with * @param fetch configuration for how to load the instance * @param edata the current execution data, or null if not * given to the calling method of the broker * @return true if the matching instance exists in the data * store, false otherwise */ public boolean initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch, Object edata); /** * Load the given state manager. * Note that any collection or map types loaded into the state manager * will be proxied with the correct type; therefore the store manager * does not have to load the same concrete collection/map types as the * instance declares. However, array types must be consistent with the * array type stored by the persistence capable instance. If this method * is called during a data store transaction, the instance should be * locked. If the given state manager does not have its version set * already, version information can be loaded if desired through the * {@link OpenJPAStateManager#setVersion} method. * * @param sm the instance to load * @param fields set of fields to load; all field indexes in this * set must be loaded; this set is mutable * @param fetch the fetch configuration to use when loading * related objects * @param lockLevel attempt to load simple fields at this lock level; * relations should be loaded at the read lock level * of the fetch configuration * @param edata the current execution data, or null if not * given to the calling method of the broker * @return false if the object no longer exists in the * database, true otherwise */ public boolean load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch, int lockLevel, Object edata); /** * Initialize, load, or validate the existance of all of the given * objects. This method is called from various broker methods that act * on multiple objects, such as {@link StoreContext#retrieveAll}. It gives * the store manager an opportunity to efficiently batch-load data for * several objects. Each of the given state managers will be in one of * three states, each requiring a different action: *
      *
    • stateManager.getO () == null: An * uninitialized state manager. Perform the same actions as in * {@link #initialize}. *
    • load != FORCE_LOAD_NONE || stateManager.getPCState () * == PCState.HOLLOW: A hollow state manager, or one whose * fields must be loaded because this is a refresh or retrieve action. * Peform the same actions as in {@link #load}, choosing the fields * to load based on the fetch configuration, or loading all fields * if load == FORCE_LOAD_ALL. Any required fields left * unloaded will cause a subsequent invocation of {@link #load} on * the individual object in question.
    • *
    • load == FORCE_LOAD_NONE && * stateManager.getPCState () != PCState.HOLLOW: A non-hollow * state manager. Perform the same actions as in {@link #exists}, * and load additional state if desired. Non-hollow objects will only * be included outside of refresh invocations if a user calls * findAll with the validate * parameter set to true.
    • *
    * Store managers that cannot efficiently batch load can simply test * for these conditions and delegate to the proper methods. * * @param sms the state manager instances to load * @param state the lifecycle state to initialize uninitialized * state managers with; may be null if no uninitialized * instances are included in sms * @param load one of the FORCE_LOAD_* constants describing the * fields to force-load if this is a refresh or retrieve action * @param fetch the current fetch configuration to use when loading * related objects * @param edata the current execution data, or null if not * given to the calling method of the broker * @return a collection of the state manager identities for * which no data store record exists * @see org.apache.openjpa.util.ImplHelper#loadAll */ public Collection loadAll(Collection sms, PCState state, int load, FetchConfiguration fetch, Object edata); /** * Notification that the given state manager is about to change its * lifecycle state. The store manager is not required to do anything in * this method, but some back ends may need to. * * @since 0.3.0 */ public void beforeStateChange(OpenJPAStateManager sm, PCState fromState, PCState toState); /** * Flush the given state manager collection to the datastore, returning * a collection of exceptions encountered during flushing. * The given collection may include states that do not require data * store action, such as persistent-clean instances or persistent-dirty * instances that have not been modified since they were last flushed. * For datastore updates and inserts, the dirty, non-flushed fields of * each state should be flushed. New instances without an assigned object * id should be given one via {@link OpenJPAStateManager#setObjectId}. New * instances with value-strategy fields that have not been assigned yet * should have their fields set. Datastore version information should be * updated during flush, and the state manager's version indicator * updated through the {@link OpenJPAStateManager#setNextVersion} method. * The current version will roll over to this next version upon successful * commit. * * @see org.apache.openjpa.util.ApplicationIds#assign() */ public Collection flush(Collection sms); /** * Assign an object id to the given new instance. Return false if the * instance cannot be assigned an identity because a flush is required * (for example, the identity is determined by the datastore on insert). * For application identity instances, the assigned object id should be * based on field state. The implementation is responsible for using the * proper value strategy according to the instance metadata. This method * is called the first time a user requests the oid of a new instance * before flush. * * @param preFlush whether this assignment is being requested by the * system as part of pre-flush activities, and can * be ignored if it is more efficient to assign within {@link #flush} * @see org.apache.openjpa.util.ImplHelper#generateFieldValue * @see org.apache.openjpa.util.ImplHelper#generateIdentityValue * @see org.apache.openjpa.util.ApplicationIds#assign() * @since 0.3.3 */ public boolean assignObjectId(OpenJPAStateManager sm, boolean preFlush); /** * Assign a value to the given field. Return false if the value cannot * be assigned because a flush is required (for example, the field value * is determined by the datastore on insert). This method is called the * first time a user requests the value of a field with a value-strategy * on a new instance before flush. * * @param preFlush whether this assignment is being requested by the * system as part of pre-flush activities, and can * be ignored if it is more efficient to assign within {@link #flush} * @see org.apache.openjpa.util.ImplHelper#generateFieldValue * @since 0.4.0 */ public boolean assignField(OpenJPAStateManager sm, int field, boolean preFlush); /** * Return the persistent class for the given data store identity value. * If the given value is not a datastore identity object, return null. * * @since 0.3.0 */ public Class getManagedType(Object oid); /** * Return the class used by this StoreManager for datastore identity * values. The given metadata may be null, in which case the return * value should the common datastore identity class for all classes, or * null if this store manager does not use a common identity class. */ public Class getDataStoreIdType(ClassMetaData meta); /** * Copy the given object id value. Use the described type of the given * metadata, which may be a subclass of the given oid's described type. */ public Object copyDataStoreId(Object oid, ClassMetaData meta); /** * Create a new unique datastore identity for the given type from * the given oid value (presumably pk, stringified oid, or oid instance). */ public Object newDataStoreId(Object oidVal, ClassMetaData meta); /** * Return a connection to the data store suitable for client use. If * this method is called during a data store transaction, thie connection * must be transactional. If no connection is in use, this method should * create one to return. */ public Object getClientConnection(); /** * Instruct the store to retain a connection for continued use. This * will be invoked automatically based on the user's configured connection * retain mode. */ public void retainConnection(); /** * Instruct the store to release a retained connection. This * will be invoked automatically based on the user's configured connection * retain mode. */ public void releaseConnection(); /** * Cancel all pending data store statements. * * @return true if any statements cancelled, false otherwise * @since 0.3.1 */ public boolean cancelAll(); /** * Return a provider for all instances of the given candidate class, * optionally including subclasses. The given candidate may be an * unmapped type with mapped subclasses. If the provider is iterated * within a data store transaction, returned instances should be locked. */ public ResultObjectProvider executeExtent(ClassMetaData meta, boolean subclasses, FetchConfiguration fetch); /** * Return a query implementation suitable for this store. If the query * is iterated within a data store transaction, returned instances should * be locked. Return null if this store does not support native execution * of the given language. OpenJPA can execute JPQL in memory even without * back end support. * * @param language the query language */ public StoreQuery newQuery(String language); /** * Return a fetch configuration suitable for this runtime. Typically * will be or extend FetchConfigurationImpl. */ public FetchConfiguration newFetchConfiguration(); /** * Compare the two version objects. * * @param state the state manager for the object * @param v1 the first version object to compare * @param v2 the second version object to compare * @return
      *
    • {@link #VERSION_LATER} if v1 * is later than v2
    • *
    • {@link #VERSION_EARLIER} if v1 * is earlier than v2
    • *
    • {@link #VERSION_SAME} if v1 * is the same as v2
    • *
    • {@link #VERSION_DIFFERENT} if v1 * is different from v2, but the time * difference of the versions cannot be determined
    • *
    */ public int compareVersion(OpenJPAStateManager state, Object v1, Object v2); /** * Return a sequence that generates datastore identity values for the * given class. This method will only be called when the identity strategy * for the class is one of: *
      *
    • {@link ValueStrategies#NATIVE}
    • *
    • {@link ValueStrategies#AUTOASSIGN}
    • *
    • {@link ValueStrategies#INCREMENT}
    • *
    * If the identity strategy cannot be represented as a sequence, return * null. * * @since 0.4.0 */ public Seq getDataStoreIdSequence(ClassMetaData forClass); /** * Return a sequence that generates values for the given field. This * method will only be called when the value strategy for the field * is one of: *
      *
    • {@link ValueStrategies#NATIVE}
    • *
    • {@link ValueStrategies#AUTOASSIGN}
    • *
    • {@link ValueStrategies#INCREMENT}
    • *
    If the value strategy cannot be represented as a sequence, return * null. * * @since 0.4.0 */ public Seq getValueSequence(FieldMetaData forField); /** * Free any resources this store manager is using. * * @since 0.2.5 */ public void close (); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PNewProvisionalState.java0000755000000000000000000000463112133327272030244 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an instance that was made persistent via reachability within the * current transaction. * * @author Steve Kim * @author: Abe White */ @SuppressWarnings("serial") class PNewProvisionalState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.setLoaded(true); context.setDirty(true); context.saveFields(false); } PCState persist(StateManagerImpl context) { return PNEW; } PCState nonprovisional(StateManagerImpl context, boolean logical, OpCallbacks call) { context.preFlush(logical, call); return PNEW; } PCState commit(StateManagerImpl context) { return TRANSIENT; } PCState commitRetain(StateManagerImpl context) { return TRANSIENT; } PCState rollback(StateManagerImpl context) { return TRANSIENT; } PCState rollbackRestore(StateManagerImpl context) { context.restoreFields(); return TRANSIENT; } PCState delete(StateManagerImpl context) { context.preDelete(); return TRANSIENT; } PCState release(StateManagerImpl context) { return TRANSIENT; } boolean isTransactional() { return true; } boolean isPersistent() { return true; } boolean isNew() { return true; } boolean isDirty() { return true; } boolean isProvisional() { return true; } public String toString() { return "Persistent-New-Provisional"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryOperations.java0000644000000000000000000000303112133327272027303 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Query operation constants. * * @since 0.4.0 */ public interface QueryOperations { /** * Symbolic constant that indicates that this query will be * performing a select operation. * * @see QueryContext#getOperation */ public static final int OP_SELECT = 1; /** * Symbolic constant that indicates that this query will be * performing a delete operation. * * @see QueryContext#getOperation */ public static final int OP_DELETE = 2; /** * Symbolic constant that indicates that this query will be * performing a update operation. * * @see QueryContext#getOperation */ public static final int OP_UPDATE = 3; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractPCData.java0000644000000000000000000003554712133327272026733 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import org.apache.openjpa.event.OrphanedKeyAction; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.ChangeTracker; import org.apache.openjpa.util.Proxy; /** * Abstract base class which implements core PCData behavior. * * @author Patrick Linskey * @author Abe White * @nojavadoc */ public abstract class AbstractPCData implements PCData { public static final Object NULL = new Object(); private static final Object[] EMPTY_ARRAY = new Object[0]; /** * Return the loaded field mask. */ public abstract BitSet getLoaded(); /** * Create a new pcdata for holding the state of an embedded instance. */ public abstract AbstractPCData newEmbeddedPCData(OpenJPAStateManager sm); public boolean isLoaded(int field) { return getLoaded().get(field); } /** * Transform the given data value into its field value. */ protected Object toField(OpenJPAStateManager sm, FieldMetaData fmd, Object data, FetchConfiguration fetch, Object context) { if (data == null) return null; switch (fmd.getDeclaredTypeCode()) { case JavaTypes.COLLECTION: ProxyDataList c = (ProxyDataList) data; Collection c2 = (Collection) sm.newFieldProxy(fmd.getIndex()); c2 = toNestedFields(sm, fmd.getElement(), (Collection) data, fetch, context); if (c2 instanceof Proxy) { ChangeTracker ct = ((Proxy) c2).getChangeTracker(); if (ct != null) ct.setNextSequence(c.nextSequence); } return c2; case JavaTypes.MAP: Map m = (Map) data; Map m2 = (Map) sm.newFieldProxy(fmd.getIndex()); Collection keys = new ArrayList (m.size()); Collection values = new ArrayList(m.size()); for (Iterator mi = m.entrySet().iterator(); mi.hasNext();) { Map.Entry e = mi.next(); keys.add(e.getKey()); values.add(e.getValue()); } Object[] keyArray = toNestedFields(sm, fmd.getKey(), keys, fetch, context).toArray(); Object[] valueArray = toNestedFields(sm, fmd.getElement(), values, fetch, context).toArray(); for (int idx = 0; idx < keyArray.length; idx++) m2.put(keyArray[idx], valueArray[idx]); return m2; case JavaTypes.ARRAY: int length = Array.getLength(data); Object a = Array.newInstance(fmd.getElement().getDeclaredType(), length); if (length == 0) return a; if (isImmutableType(fmd.getElement())) { System.arraycopy(data, 0, a, 0, length); } else { for (int i = 0; i < length; i++) { Array.set(a, i, toNestedField(sm, fmd.getElement(), Array.get(data, i), fetch, context)); } } return a; default: return toNestedField(sm, fmd, data, fetch, context); } } /** * Transform the given data value to its field value. The data value * may be a key, value, or element of a map or collection. */ protected Object toNestedField(OpenJPAStateManager sm, ValueMetaData vmd, Object data, FetchConfiguration fetch, Object context) { if (data == null) return null; switch (vmd.getDeclaredTypeCode()) { case JavaTypes.DATE: return ((Date) data).clone(); case JavaTypes.LOCALE: return (Locale) data; case JavaTypes.PC: if (vmd.isEmbedded()) return toEmbeddedField(sm, vmd, data, fetch, context); // no break case JavaTypes.PC_UNTYPED: Object ret = toRelationField(sm, vmd, data, fetch, context); if (ret != null) return ret; OrphanedKeyAction action = sm.getContext().getConfiguration(). getOrphanedKeyActionInstance(); return action.orphan(data, sm, vmd); default: return data; } } /** * Transform the given data value to its field value. The data value * may be a key, value, or element of a map or collection. */ protected Collection toNestedFields(OpenJPAStateManager sm, ValueMetaData vmd, Collection data, FetchConfiguration fetch, Object context) { if (data == null) return null; Collection ret = new ArrayList(data.size()); switch (vmd.getDeclaredTypeCode()) { case JavaTypes.DATE: for (Iterator itr=data.iterator(); itr.hasNext();) ret.add(((Date)itr.next()).clone()); return ret; case JavaTypes.LOCALE: for (Iterator itr=data.iterator(); itr.hasNext();) ret.add((Locale) itr.next()); return ret; case JavaTypes.PC: if (vmd.isEmbedded()) { for (Iterator itr=data.iterator(); itr.hasNext();) { ret.add(toEmbeddedField(sm, vmd, itr.next(), fetch , context)); } return ret; } // no break case JavaTypes.PC_UNTYPED: Object[] r = toRelationFields(sm, data, fetch); if (r != null) { for (int i = 0; i < r.length; i++) if (r[i] != null) ret.add(r[i]); else { ret.add(sm.getContext().getConfiguration(). getOrphanedKeyActionInstance(). orphan(data, sm, vmd)); } return ret; } default: return data; } } /** * Transform the given data into a relation field value. Default * implementation assumes the data is an oid. */ protected Object toRelationField(OpenJPAStateManager sm, ValueMetaData vmd, Object data, FetchConfiguration fetch, Object context) { return sm.getContext().find(data, fetch, null, null, 0); } /** * Transform the given data into relation field values. Default * implementation assumes the data is an oid. */ protected Object[] toRelationFields(OpenJPAStateManager sm, Object data, FetchConfiguration fetch) { return sm.getContext().findAll((Collection) data, fetch, null, null, 0); } /** * Transform the given data into an embedded PC field value. Default * implementation assumes the data is an {@link AbstractPCData}. */ protected Object toEmbeddedField(OpenJPAStateManager sm, ValueMetaData vmd, Object data, FetchConfiguration fetch, Object context) { AbstractPCData pcdata = (AbstractPCData) data; OpenJPAStateManager embedded = sm.getContext().embed(null, pcdata.getId(), sm, vmd); pcdata.load(embedded, (BitSet) pcdata.getLoaded().clone(), fetch, context); return embedded.getManagedInstance(); } /** * Transform the given field value to a data value for caching. Return * {@link #NULL} if unable to cache. */ protected Object toData(FieldMetaData fmd, Object val, StoreContext ctx) { if (val == null) return null; switch (fmd.getDeclaredTypeCode()) { case JavaTypes.COLLECTION: Collection c = (Collection) val; if (c.isEmpty()) return ProxyDataList.EMPTY_LIST; ProxyDataList c2 = null; int size; for (Iterator ci = c.iterator(); ci.hasNext();) { val = toNestedData(fmd.getElement(), ci.next(), ctx); if (val == NULL) return NULL; if (c2 == null) { size = c.size(); c2 = new ProxyDataList(size); if (c instanceof Proxy) { ChangeTracker ct = ((Proxy) c).getChangeTracker(); if (ct != null) c2.nextSequence = ct.getNextSequence(); } else c2.nextSequence = size; } c2.add(val); } return c2; case JavaTypes.MAP: Map m = (Map) val; if (m.isEmpty()) return Collections.EMPTY_MAP; Map m2 = null; Map.Entry e; Object val2; for (Iterator mi = m.entrySet().iterator(); mi.hasNext();) { e = (Map.Entry) mi.next(); val = toNestedData(fmd.getKey(), e.getKey(), ctx); if (val == NULL) return NULL; val2 = toNestedData(fmd.getElement(), e.getValue(), ctx); if (val2 == NULL) return NULL; if (m2 == null) m2 = new HashMap(m.size()); m2.put(val, val2); } return m2; case JavaTypes.ARRAY: int length = Array.getLength(val); if (length == 0) return EMPTY_ARRAY; Object a; if (isImmutableType(fmd.getElement())) { a = Array.newInstance(fmd.getElement().getDeclaredType(), length); System.arraycopy(val, 0, a, 0, length); } else { Object[] data = new Object[length]; for (int i = 0; i < length; i++) { data[i] = toNestedData(fmd.getElement(), Array.get(val, i), ctx); } a = data; } return a; default: return toNestedData(fmd, val, ctx); } } /** * Return whether the declared type of the given value is immutable. */ private boolean isImmutableType(ValueMetaData element) { switch (element.getDeclaredTypeCode()) { case JavaTypes.BOOLEAN: case JavaTypes.BYTE: case JavaTypes.CHAR: case JavaTypes.DOUBLE: case JavaTypes.FLOAT: case JavaTypes.INT: case JavaTypes.LONG: case JavaTypes.SHORT: case JavaTypes.STRING: case JavaTypes.NUMBER: case JavaTypes.BOOLEAN_OBJ: case JavaTypes.BYTE_OBJ: case JavaTypes.CHAR_OBJ: case JavaTypes.DOUBLE_OBJ: case JavaTypes.FLOAT_OBJ: case JavaTypes.INT_OBJ: case JavaTypes.LONG_OBJ: case JavaTypes.SHORT_OBJ: case JavaTypes.BIGDECIMAL: case JavaTypes.BIGINTEGER: return true; default: return false; } } /** * Transform the given nested value to a cachable value. Return * {@link #NULL} if the value cannot be cached. */ protected Object toNestedData(ValueMetaData vmd, Object val, StoreContext ctx) { if (val == null) return null; switch (vmd.getDeclaredTypeCode()) { case JavaTypes.PC: if (vmd.isEmbedded()) return toEmbeddedData(val, ctx); // no break case JavaTypes.PC_UNTYPED: return toRelationData(val, ctx); case JavaTypes.DATE: if (val instanceof Proxy) return ((Proxy) val).copy(val); else return ((Date) val).clone(); case JavaTypes.LOCALE: return (Locale) val; case JavaTypes.OBJECT: if (val instanceof Proxy) return ((Proxy) val).copy(val); else return val; default: return val; } } /** * Return the value to cache for the given object. Caches its oid by * default. */ protected Object toRelationData(Object val, StoreContext ctx) { return ctx.getObjectId(val); } /** * Return the value to cache for the given embedded PC. Caches a * {@link PCData} from {@link #newEmbeddedPCData} by default. */ protected Object toEmbeddedData(Object val, StoreContext ctx) { if (ctx == null) return NULL; OpenJPAStateManager sm = ctx.getStateManager(val); if (sm == null) return NULL; // have to cache all data, so make sure it's all loaded // ### prevent loading of things that aren't cached (lobs, lrs, etc) ctx.retrieve(val, false, null); PCData pcdata = newEmbeddedPCData(sm); pcdata.store(sm); return pcdata; } /** * Tracks proxy data along with list elements. */ private static class ProxyDataList extends ArrayList { public static final ProxyDataList EMPTY_LIST = new ProxyDataList(0); public int nextSequence = 0; public ProxyDataList(int size) { super (size); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java0000644000000000000000000007731012133327272030405 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.ObjectStreamException; import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; import javax.transaction.Status; import javax.transaction.Synchronization; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import org.apache.commons.collections.set.MapBackedSet; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.kernel.AuditManager; import org.apache.openjpa.audit.Auditor; import org.apache.openjpa.conf.BrokerValue; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.conf.OpenJPAVersion; import org.apache.openjpa.datacache.DataCacheStoreManager; import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.enhance.ManagedClassSubclasser; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.event.BrokerFactoryEvent; import org.apache.openjpa.event.RemoteCommitEventManager; import org.apache.openjpa.instrumentation.InstrumentationManager; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashSet; import org.apache.openjpa.meta.MetaDataModes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; /** * Abstract implementation of the {@link BrokerFactory} * that must be subclassed for a specific runtime. * * @author Abe White */ @SuppressWarnings("serial") public abstract class AbstractBrokerFactory implements BrokerFactory { private static final Localizer _loc = Localizer.forPackage(AbstractBrokerFactory.class); // static mapping of configurations to pooled broker factories private static final Map _pool = Collections.synchronizedMap(new HashMap()); // configuration private final OpenJPAConfiguration _conf; private transient boolean _readOnly = false; private transient boolean _closed = false; private transient RuntimeException _closedException = null; private Map _userObjects = null; // internal lock: spec forbids synchronization on this object private final ReentrantLock _lock = new ReentrantLock(); // maps global transactions to associated brokers private transient ConcurrentHashMap> _transactional = new ConcurrentHashMap>(); // weak-ref tracking of open brokers private transient Set _brokers; // cache the class names loaded from the persistent classes property so // that we can re-load them for each new broker private transient Collection _pcClassNames = null; private transient Collection _pcClassLoaders = null; private transient boolean _persistentTypesLoaded = false; // lifecycle listeners to pass to each broker private transient Map[]> _lifecycleListeners = null; // transaction listeners to pass to each broker private transient List _transactionListeners = null; // key under which this instance can be stored in the broker pool // and later identified private Object _poolKey; /** * Return an internal factory pool key for the given configuration. * * @since 1.1.0 */ protected static Object toPoolKey(Map map) { Object key = Configurations.getProperty("Id", map); return ( key != null) ? key : map; } /** * Register factory in the pool under key. * * @since 1.1.0 */ protected static void pool(Object key, AbstractBrokerFactory factory) { synchronized(_pool) { _pool.put(key, factory); factory.setPoolKey(key); factory.makeReadOnly(); } } /** * Return the pooled factory matching the given key, or null * if none. The key must be of the form created by {@link #getPoolKey}. */ public static AbstractBrokerFactory getPooledFactoryForKey(Object key) { return (AbstractBrokerFactory) _pool.get(key); } /** * Constructor. Configuration must be provided on construction. */ protected AbstractBrokerFactory(OpenJPAConfiguration config) { _conf = config; _brokers = newBrokerSet(); getPcClassLoaders(); } /** * Return the configuration for this factory. */ public OpenJPAConfiguration getConfiguration() { return _conf; } public Broker newBroker() { return newBroker(_conf.getConnectionUserName(), _conf.getConnectionPassword()); } public Broker newBroker(String user, String pass) { return newBroker(user, pass, _conf.isTransactionModeManaged(), _conf.getConnectionRetainModeConstant()); } public Broker newBroker(boolean managed, int connRetainMode) { return newBroker(_conf.getConnectionUserName(), _conf.getConnectionPassword(), managed, connRetainMode); } public Broker newBroker(String user, String pass, boolean managed, int connRetainMode) { return newBroker(user, pass, managed, connRetainMode, true); } public Broker newBroker(String user, String pass, boolean managed, int connRetainMode, boolean findExisting) { return newBroker(user, pass, managed, connRetainMode, findExisting, "", ""); } public Broker newBroker(String user, String pass, boolean managed, int connRetainMode, boolean findExisting, String cf1Name, String cf2Name) { try { assertOpen(); if(StringUtils.isNotEmpty(cf1Name)) { // If the cfName has been set on the broker try looking up now. try { _conf.getConnectionFactory(); } catch(UserException ue) { // try setting the broker's CF into the configuration. _conf.setConnectionFactoryName(cf1Name); } } makeReadOnly(); Broker broker = null; if (findExisting) broker = findBroker(user, pass, managed); if (broker == null) { broker = newBrokerImpl(user, pass); broker.setConnectionFactoryName(cf1Name); broker.setConnectionFactory2Name(cf2Name); initializeBroker(managed, connRetainMode, broker, false); } return broker; } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } } void initializeBroker(boolean managed, int connRetainMode, Broker broker, boolean fromDeserialization) { assertOpen(); makeReadOnly(); DelegatingStoreManager dsm = createDelegatingStoreManager(); ((BrokerImpl) broker).initialize(this, dsm, managed, connRetainMode, fromDeserialization); if (!fromDeserialization) addListeners(broker); // if we're using remote events, register the event manager so // that it can broadcast commit notifications from the broker RemoteCommitEventManager remote = _conf.getRemoteCommitEventManager(); if (remote.areRemoteEventsEnabled()) broker.addTransactionListener(remote); loadPersistentTypes(broker.getClassLoader()); _brokers.add(broker); _conf.setReadOnly(Configuration.INIT_STATE_FROZEN); } /** * Add factory-registered lifecycle listeners to the broker. */ protected void addListeners(Broker broker) { if (_lifecycleListeners != null && !_lifecycleListeners.isEmpty()) { for (Map.Entry[]> entry : _lifecycleListeners.entrySet()) { broker.addLifecycleListener(entry.getKey(), entry.getValue()); } } if (_transactionListeners != null && !_transactionListeners.isEmpty()) { for (Iterator itr = _transactionListeners.iterator(); itr.hasNext(); ) { broker.addTransactionListener(itr.next()); } } } /** * Load the configured persistent classes list. Performed automatically * whenever a broker is created. */ public void loadPersistentTypes(ClassLoader envLoader) { // if we've loaded the persistent types and the class name list // is empty, then we can simply return. Note that there is a // potential threading scenario in which _persistentTypesLoaded is // false when read, but the work to populate _pcClassNames has // already been done. This is ok; _pcClassNames can tolerate // concurrent access, so the worst case is that the list is // persistent type data is processed multiple times, which this // algorithm takes into account. if (_persistentTypesLoaded && _pcClassNames.isEmpty()) return; // cache persistent type names if not already ClassLoader loader = _conf.getClassResolverInstance(). getClassLoader(getClass(), envLoader); Collection> toRedefine = new ArrayList>(); if (!_persistentTypesLoaded) { Collection> clss = _conf.getMetaDataRepositoryInstance(). loadPersistentTypes(false, loader, _conf.isInitializeEagerly()); if (clss.isEmpty()) _pcClassNames = Collections.emptyList(); else { Collection c = new ArrayList(clss.size()); for (Iterator> itr = clss.iterator(); itr.hasNext();) { Class cls = itr.next(); c.add(cls.getName()); if (needsSub(cls)) toRedefine.add(cls); } getPcClassLoaders().add(loader); _pcClassNames = c; } _persistentTypesLoaded = true; } else { // reload with this loader if (getPcClassLoaders().add(loader)) { for (String clsName : _pcClassNames) { try { Class cls = Class.forName(clsName, true, loader); if (needsSub(cls)) toRedefine.add(cls); } catch (Throwable t) { _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME).warn(null, t); } } } } // get the ManagedClassSubclasser into the loop ManagedClassSubclasser.prepareUnenhancedClasses(_conf, toRedefine, envLoader); } private boolean needsSub(Class cls) { return !cls.isInterface() && !PersistenceCapable.class.isAssignableFrom(cls); } public void addLifecycleListener(Object listener, Class[] classes) { lock(); try { assertOpen(); if (_lifecycleListeners == null) _lifecycleListeners = new HashMap[]>(7); _lifecycleListeners.put(listener, classes); } finally { unlock(); } } public void removeLifecycleListener(Object listener) { lock(); try { assertOpen(); if (_lifecycleListeners != null) _lifecycleListeners.remove(listener); } finally { unlock(); } } public void addTransactionListener(Object listener) { lock(); try { assertOpen(); if (_transactionListeners == null) _transactionListeners = new LinkedList(); _transactionListeners.add(listener); } finally { unlock(); } } public void removeTransactionListener(Object listener) { lock(); try { assertOpen(); if (_transactionListeners != null) _transactionListeners.remove(listener); } finally { unlock(); } } /** * Returns true if this broker factory is closed. */ public boolean isClosed() { return _closed; } public void close() { lock(); try { assertOpen(); assertNoActiveTransaction(); // remove from factory pool synchronized (_pool) { if (_pool.get(_poolKey) == this) _pool.remove(_poolKey); } // close all brokers for (Broker broker : _brokers) { // Check for null because _brokers may contain weak references if ((broker != null) && (!broker.isClosed())) broker.close(); } if(_conf.metaDataRepositoryAvailable()) { // remove metadata repository from listener list PCRegistry.removeRegisterClassListener (_conf.getMetaDataRepositoryInstance()); } _conf.close(); _closed = true; Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); if (log.isTraceEnabled()) _closedException = new IllegalStateException(); } finally { unlock(); } } /** * Subclasses should override this method to add a Platform * property listing the runtime platform, such as: * OpenJPA JDBC Edition: Oracle Database */ public Map getProperties() { // required props are VendorName and VersionNumber Map props = _conf.toProperties(true); props.put("VendorName", OpenJPAVersion.VENDOR_NAME); props.put("VersionNumber", OpenJPAVersion.VERSION_NUMBER); props.put("VersionId", OpenJPAVersion.VERSION_ID); return props; } public Set getSupportedProperties() { return _conf.getPropertyKeys(); } public Object getUserObject(Object key) { lock(); try { assertOpen(); return (_userObjects == null) ? null : _userObjects.get(key); } finally { unlock(); } } public Object putUserObject(Object key, Object val) { lock(); try { assertOpen(); if (val == null) return (_userObjects == null) ? null : _userObjects.remove(key); if (_userObjects == null) _userObjects = new HashMap(); return _userObjects.put(key, val); } finally { unlock(); } } public void lock() { _lock.lock(); } public void unlock() { _lock.unlock(); } /** * Replaces the factory with this JVMs pooled version if it exists. Also * freezes the factory. */ protected Object readResolve() throws ObjectStreamException { AbstractBrokerFactory factory = getPooledFactoryForKey(_poolKey); if (factory != null) return factory; // reset these transient fields to empty values _transactional = new ConcurrentHashMap>(); _brokers = newBrokerSet(); // turn off logging while de-serializing BrokerFactory String saveLogConfig = _conf.getLog(); _conf.setLog("none"); makeReadOnly(); // re-enable any logging which was in effect _conf.setLog(saveLogConfig); return this; } private Set newBrokerSet() { BrokerValue bv; if (_conf instanceof OpenJPAConfigurationImpl) bv = ((OpenJPAConfigurationImpl) _conf).brokerPlugin; else bv = (BrokerValue) _conf.getValue(BrokerValue.KEY); if (FinalizingBrokerImpl.class.isAssignableFrom(bv.getTemplateBrokerType(_conf))) { return MapBackedSet.decorate(new ConcurrentHashMap(), new Object() { }); } else { return new ConcurrentReferenceHashSet(ConcurrentReferenceHashSet.WEAK); } } //////////////////////// // Methods for Override //////////////////////// /** * Return a new StoreManager for this runtime. Note that the instance * returned here may be wrapped before being passed to the * {@link #newBroker} method. */ protected abstract StoreManager newStoreManager(); /** * Find a pooled broker, or return null if none. If using * managed transactions, looks for a transactional broker; * otherwise returns null by default. This method will be called before * {@link #newStoreManager} so that factory subclasses implementing * pooling can return a matching manager before a new {@link StoreManager} * is created. */ protected Broker findBroker(String user, String pass, boolean managed) { if (managed) return findTransactionalBroker(user, pass); return null; } /** * Return a broker configured with the proper settings. * By default, this method constructs a new * BrokerImpl of the class set for this factory. */ protected BrokerImpl newBrokerImpl(String user, String pass) { BrokerImpl broker = _conf.newBrokerInstance(user, pass); if (broker == null) throw new UserException(_loc.get("no-broker-class", _conf.getBrokerImpl())); return broker; } /** * Setup transient state used by this factory based on the * current configuration, which will subsequently be locked down. This * method will be called before the first broker is requested, * and will be re-called each time the factory is deserialized into a JVM * that has no configuration for this data store. */ protected void setup() { } ///////////// // Utilities ///////////// /** * Find a managed runtime broker associated with the * current transaction, or returns null if none. */ protected Broker findTransactionalBroker(String user, String pass) { Transaction trans; ManagedRuntime mr = _conf.getManagedRuntimeInstance(); Object txKey; try { trans = mr.getTransactionManager(). getTransaction(); txKey = mr.getTransactionKey(); if (trans == null || trans.getStatus() == Status.STATUS_NO_TRANSACTION || trans.getStatus() == Status.STATUS_UNKNOWN) return null; } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(e); } Collection brokers = _transactional.get(txKey); if (brokers != null) { // we don't need to synchronize on brokers since one JTA transaction // can never be active on multiple concurrent threads. for (Broker broker : brokers) { if (StringUtils.equals(broker.getConnectionUserName(), user) && StringUtils.equals(broker.getConnectionPassword(), pass)) return broker; } } return null; } /** * Configures the given broker with the current factory option settings. */ protected void configureBroker(BrokerImpl broker) { broker.setOptimistic(_conf.getOptimistic()); broker.setNontransactionalRead(_conf.getNontransactionalRead()); broker.setNontransactionalWrite(_conf.getNontransactionalWrite()); broker.setRetainState(_conf.getRetainState()); broker.setRestoreState(_conf.getRestoreStateConstant()); broker.setAutoClear(_conf.getAutoClearConstant()); broker.setIgnoreChanges(_conf.getIgnoreChanges()); broker.setMultithreaded(_conf.getMultithreaded()); broker.setAutoDetach(_conf.getAutoDetachConstant()); broker.setDetachState(_conf.getDetachStateInstance().getDetachState()); broker.setPostLoadOnMerge(_conf.getPostLoadOnMerge()); } /** * Freezes the configuration of this factory. */ public void makeReadOnly() { if (_readOnly) return; lock(); try { // check again if (_readOnly) return; _readOnly = true; Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); if (log.isInfoEnabled()) log.info(getFactoryInitializationBanner()); if (log.isTraceEnabled()) { Map props = _conf.toProperties(true); String lineSep = J2DoPrivHelper.getLineSeparator(); StringBuilder buf = new StringBuilder(); Map.Entry entry; for (Iterator> itr = props.entrySet().iterator(); itr.hasNext();) { entry = itr.next(); Object value = entry.getValue(); buf.append(entry.getKey()).append(": ") .append(value != null && value.getClass().isArray() ? Arrays.toString((Object[])value) : value); if (itr.hasNext()) buf.append(lineSep); } log.trace(_loc.get("factory-properties", buf.toString())); } // setup transient state setup(); // register the metdata repository to auto-load persistent types // and make sure types are enhanced MetaDataRepository repos = _conf.getMetaDataRepositoryInstance(); repos.setValidate(MetaDataRepository.VALIDATE_RUNTIME, true); repos.setResolve(MetaDataModes.MODE_MAPPING_INIT, true); PCRegistry.addRegisterClassListener(repos); // freeze underlying configuration and eagerly initialize to // avoid synchronization _conf.setReadOnly(Configuration.INIT_STATE_FREEZING); _conf.instantiateAll(); if (_conf.isInitializeEagerly()) _conf.setReadOnly(Configuration.INIT_STATE_FROZEN); // fire an event for all the broker factory listeners // registered on the configuration. _conf.getBrokerFactoryEventManager().fireEvent( new BrokerFactoryEvent(this, BrokerFactoryEvent.BROKER_FACTORY_CREATED)); } finally { unlock(); } } /** * Return an object to be written to the log when this broker factory * initializes. This happens after the configuration is fully loaded. */ protected Object getFactoryInitializationBanner() { return _loc.get("factory-init", OpenJPAVersion.VERSION_NUMBER); } /** * Throw an exception if the factory is closed. The exact message and * content of the exception varies whether TRACE is enabled or not. */ public void assertOpen() { if (_closed) { if (_closedException == null) // TRACE not enabled throw new InvalidStateException(_loc .get("closed-factory-notrace")); else throw new InvalidStateException(_loc.get("closed-factory")) .setCause(_closedException); } } //////////////////// // Broker utilities //////////////////// /** * Throws a {@link UserException} if a transaction is active. The thrown * exception will contain all the Brokers with active transactions as * failed objects in the nested exceptions. */ private void assertNoActiveTransaction() { Collection excs; if (_transactional.isEmpty()) return; excs = new ArrayList(_transactional.size()); for (Collection brokers : _transactional.values()) { for (Broker broker : brokers) { excs.add(new InvalidStateException(_loc.get("active")).setFailedObject(broker)); } } if (!excs.isEmpty()) throw new InvalidStateException(_loc.get("nested-exceps")). setNestedThrowables((Throwable[]) excs.toArray(new Throwable[excs.size()])); } /** * Synchronize the given broker with a managed transaction, * optionally starting one if none is in progress. * * @return true if synched with transaction, false otherwise */ boolean syncWithManagedTransaction(BrokerImpl broker, boolean begin) { Transaction trans; try { ManagedRuntime mr = broker.getManagedRuntime(); TransactionManager tm = mr.getTransactionManager(); trans = tm.getTransaction(); if (trans != null && (trans.getStatus() == Status.STATUS_NO_TRANSACTION || trans.getStatus() == Status.STATUS_UNKNOWN)) trans = null; if (trans == null && begin) { tm.begin(); trans = tm.getTransaction(); } else if (trans == null) return false; // synch broker and trans trans.registerSynchronization(broker); // we don't need to synchronize on brokers or guard against multiple // threads using the same trans since one JTA transaction can never // be active on multiple concurrent threads. Object txKey = mr.getTransactionKey(); Collection brokers = _transactional.get(txKey); if (brokers == null) { brokers = new ArrayList(2); _transactional.put(txKey, brokers); trans.registerSynchronization(new RemoveTransactionSync(txKey)); } brokers.add(broker); return true; } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new GeneralException(e); } } /** * Returns a set of all the open brokers associated with this factory. The * returned set is unmodifiable, and may contain null references. */ public Collection getOpenBrokers() { return Collections.unmodifiableCollection(_brokers); } /** * Release broker from any internal data structures. This * is invoked by broker after the broker is fully closed. * * @since 1.1.0 */ protected void releaseBroker(BrokerImpl broker) { _brokers.remove(broker); } /** * @return a key that can be used to obtain this broker factory from the * pool at a later time. * * @since 1.1.0 */ public Object getPoolKey() { return _poolKey; } /** * Set a key that can be used to obtain this broker factory from the * pool at a later time. * * @since 1.1.0 */ void setPoolKey(Object key) { _poolKey = key; } /** * Simple synchronization listener to remove completed transactions * from our cache. */ private class RemoveTransactionSync implements Synchronization { private final Object _trans; public RemoveTransactionSync(Object trans) { _trans = trans; } public void beforeCompletion() { } public void afterCompletion(int status) { _transactional.remove (_trans); } } /** * Method insures that deserialized EMF has this reference re-instantiated */ private Collection getPcClassLoaders() { if (_pcClassLoaders == null) _pcClassLoaders = new ConcurrentReferenceHashSet(ConcurrentReferenceHashSet.WEAK); return _pcClassLoaders; } /** *

    * Create a DelegatingStoreManager for use with a Broker created by this factory. * If a DataCache has been enabled a DataCacheStoreManager will be returned. *

    *

    * If no DataCache is in use an ROPStoreManager will be returned. *

    * * @return A delegating store manager suitable for the current * configuration. */ protected DelegatingStoreManager createDelegatingStoreManager() { // decorate the store manager for data caching and custom // result object providers; always make sure it's a delegating // store manager, because it's easier for users to deal with // that way StoreManager sm = newStoreManager(); DelegatingStoreManager dsm = null; if (_conf.getDataCacheManagerInstance().getSystemDataCache() != null) { dsm = new DataCacheStoreManager(sm); } dsm = new ROPStoreManager((dsm == null) ? sm : dsm); return dsm; } /** * This method is invoked AFTER a BrokerFactory has been instantiated. */ public void postCreationCallback() { Auditor auditor = _conf.getAuditorInstance(); if (auditor != null) { addTransactionListener(new AuditManager(auditor)); } if (_conf.isInitializeEagerly()) { newBroker(_conf.getConnectionUserName(), _conf.getConnectionPassword(), _conf.isConnectionFactoryModeManaged(), _conf.getConnectionRetainModeConstant(), false).close(); } // Don't catch any exceptions here because we want to fail-fast if something bad happens when we're preloading. Options o = Configurations.parseProperties(Configurations.getProperties(_conf.getMetaDataRepository())); if (MetaDataRepository.needsPreload(o) == true) { MetaDataRepository mdr = _conf.getMetaDataRepositoryInstance(); mdr.setValidate(MetaDataRepository.VALIDATE_RUNTIME, true); mdr.setResolve(MetaDataRepository.MODE_MAPPING_INIT, true); // Load persistent classes and hook in subclasser loadPersistentTypes((ClassLoader) AccessController.doPrivileged(J2DoPrivHelper .getContextClassLoaderAction())); mdr.preload(); } // Get a DataCacheManager instance up front to avoid threading concerns on first call. // _conf.getDataCacheManagerInstance(); InstrumentationManager imgr = _conf.getInstrumentationManagerInstance(); if (imgr != null) { // Start all factory level instrumentation imgr.start(InstrumentationLevel.FACTORY, this); } } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/OrderingMergedResultObjectProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/OrderingMergedResultObject0000644000000000000000000000703112133327272030441 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Comparator; import org.apache.openjpa.lib.rop.MergedResultObjectProvider; import org.apache.openjpa.lib.rop.ResultObjectProvider; /** * Merged result object provider specialization that extracts ordering * values from results for comparison. * * @author Abe White * @nojavadoc */ public class OrderingMergedResultObjectProvider extends MergedResultObjectProvider { private final StoreQuery.Executor[] _execs; private final StoreQuery _query; private final Object[] _params; private final int _orderings; public OrderingMergedResultObjectProvider(ResultObjectProvider[] rops, boolean[] asc, StoreQuery.Executor exec, StoreQuery q, Object[] params) { this(rops, asc, new StoreQuery.Executor[]{ exec }, q, params); } public OrderingMergedResultObjectProvider(ResultObjectProvider[] rops, boolean[] asc, StoreQuery.Executor[] execs, StoreQuery q, Object[] params) { super(rops, new OrderingComparator(asc)); _orderings = asc.length; _execs = execs; _query = q; _params = params; } protected Object getOrderingValue(Object val, int idx, ResultObjectProvider rop) { StoreQuery.Executor exec = (_execs.length == 1) ? _execs[0] : _execs[idx]; if (_orderings == 1) return exec.getOrderingValue(_query, _params, val, 0); Object[] ret = new Object[_orderings]; for (int i = 0; i < _orderings; i++) ret[i] = exec.getOrderingValue(_query, _params, val, i); return ret; } /** * Comparator that works on multiple ordering criteria given in an array. */ private static class OrderingComparator implements Comparator { private final boolean[] _asc; public OrderingComparator(boolean[] asc) { _asc = asc; } public int compare(Object o1, Object o2) { if (_asc.length == 1) return cmp(o1, o2, _asc[0]); Object[] arr1 = (Object[]) o1; Object[] arr2 = (Object[]) o2; int cmp; for (int i = 0; i < _asc.length; i++) { cmp = cmp(arr1[i], arr2[i], _asc[i]); if (cmp != 0) return cmp; } return 0; } private static int cmp(Object o1, Object o2, boolean asc) { if (o1 == null && o2 == null) return 0; if (o1 == null) return (asc) ? 1 : -1; if (o2 == null) return (asc) ? -1 : 1; int cmp = ((Comparable) o1).compareTo(o2); if (!asc) cmp *= -1; return cmp; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Query.java0000644000000000000000000001221212133327272025240 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.util.Collection; import java.util.Map; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.FilterListener; /** * OpenJPA query interface. * * @since 0.3.0 * @author Patrick Linskey * @author Abe White */ public interface Query extends Serializable, QueryContext, QueryOperations, QueryFlushModes { /** * The broker that generated this query. */ public Broker getBroker(); /** * The query string or template. */ public boolean setQuery(Object query); /** * Whether to ignore changes in the current transaction. */ public void setIgnoreChanges(boolean ignore); /** * Register a filter listener for the query. */ public void addFilterListener(FilterListener listener); /** * Remove a filter listener from the query. */ public void removeFilterListener(FilterListener listener); /** * Register an aggregate listener for the query. */ public void addAggregateListener(AggregateListener listener); /** * Remove an aggregate listener from the query. */ public void removeAggregateListener(AggregateListener listener); /** * Return the candidate extent, or null if a * collection was specified instead of an extent. */ public Extent getCandidateExtent(); /** * Set the candidate extent. */ public void setCandidateExtent(Extent extent); /** * Set a collection of candidates. */ public void setCandidateCollection(Collection coll); /** * Compile the query. */ public void compile(); /** * Execute. */ public Object execute(); /** * Execute with parameter map. */ public Object execute(Map params); /** * Execute with parameter array. */ public Object execute(Object[] params); /** * Deletes all of the instances that are satisfied by the query. * * @return the number of instances that were deleted */ public long deleteAll(); /** * Deletes all of the instances that are satisfied by the query. * * @param parameters the positional parameters for the query * @return the number of instances that were deleted */ public long deleteAll(Object[] parameters); /** * Deletes all of the instances that are satisfied by the query. * * @param parameterMap the named parameter map * @return the number of instances that were deleted */ public long deleteAll(Map parameterMap); /** * Performs an update of the instances that are satisfied by the query. * * @return the number of instances that were update */ public long updateAll(); /** * Performs an update of the instances that are satisfied by the query. * * @param parameters the positional parameter array * @return the number of instances that were update */ public long updateAll(Object[] parameters); /** * Performs an update of the instances that are satisfied by the query. * * @param parameterMap the named parameter map * @return the number of instances that were update */ public long updateAll(Map parameterMap); /** * Close all open query results. */ public void closeAll(); /** * Close query results that are consuming resources. Allow results that * are not consuming resources to remain open so that they continue to * function normally. */ public void closeResources(); /** * Returns a description of the commands that will be sent to * the datastore in order to execute this query. This will * typically be in the native query language of the database (e.g., SQL). * * @param params the named parameter map for the query invocation * @since 0.3.2 */ public String[] getDataStoreActions(Map params); /** * Assert that the query's broker is still open. */ public void assertOpen(); /** * Assert that the query is not read-only. */ public void assertNotReadOnly(); /** * Check that the query has not been serialized, which causes it to lose * its association with its Broker. */ public void assertNotSerialized (); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/TransferFieldManager.java0000644000000000000000000000667612133327272030177 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.enhance.FieldManager; /** * FieldManager type used to transfer a single field value. * * @author Abe White */ class TransferFieldManager implements FieldManager { protected double dblval = 0; protected long longval = 0; protected Object objval = null; protected int field = -1; public boolean fetchBooleanField(int field) { return longval == 1; } public byte fetchByteField(int field) { return (byte) longval; } public char fetchCharField(int field) { return (char) longval; } public double fetchDoubleField(int field) { return dblval; } public float fetchFloatField(int field) { return (float) dblval; } public int fetchIntField(int field) { return (int) longval; } public long fetchLongField(int field) { return longval; } public Object fetchObjectField(int field) { // don't hold onto strong ref to object Object val = objval; objval = null; return val; } public short fetchShortField(int field) { return (short) longval; } public String fetchStringField(int field) { return (String) objval; } public void storeBooleanField(int field, boolean curVal) { this.field = field; longval = (curVal) ? 1 : 0; } public void storeByteField(int field, byte curVal) { this.field = field; longval = curVal; } public void storeCharField(int field, char curVal) { this.field = field; longval = (long) curVal; } public void storeDoubleField(int field, double curVal) { this.field = field; dblval = curVal; } public void storeFloatField(int field, float curVal) { this.field = field; dblval = curVal; } public void storeIntField(int field, int curVal) { this.field = field; longval = curVal; } public void storeLongField(int field, long curVal) { this.field = field; longval = curVal; } public void storeObjectField(int field, Object curVal) { this.field = field; objval = curVal; } public void storeShortField(int field, short curVal) { this.field = field; longval = curVal; } public void storeStringField(int field, String curVal) { this.field = field; objval = curVal; } /** * Clear any held state. Fields are also cleared automatically when fetched. */ public void clear() { dblval = 0; longval = 0; objval = null; field = -1; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ECleanState.java0000644000000000000000000000450312133327272026267 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Lifecycle state. * Represents an embedded instance that is managed by a StateManager and * may be participating in the current transaction, but has not yet been * modified. * * @author Abe White */ @SuppressWarnings("serial") class ECleanState extends PCState { @Override void initialize(StateManagerImpl context, PCState previous) { context.setDirty(false); } PCState commit(StateManagerImpl context) { return TRANSIENT; } PCState commitRetain(StateManagerImpl context) { return ENONTRANS; } PCState rollback(StateManagerImpl context) { return TRANSIENT; } PCState rollbackRestore(StateManagerImpl context) { return ENONTRANS; } PCState delete(StateManagerImpl context) { context.preDelete(); return EDELETED; } PCState nontransactional(StateManagerImpl context) { return ENONTRANS; } PCState release(StateManagerImpl context) { return TRANSIENT; } PCState evict(StateManagerImpl context) { return TRANSIENT; } PCState beforeWrite(StateManagerImpl context, int field, boolean mutate) { return EDIRTY; } PCState beforeOptimisticWrite(StateManagerImpl context, int field, boolean mutate) { return EDIRTY; } boolean isTransactional() { return true; } boolean isPersistent() { return true; } public String toString() { return "Embedded-Clean"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Extent.java0000644000000000000000000000476212133327272025415 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Representation of all members of a persistent class. * * @author Abe White * @author Patrick Linskey */ public interface Extent { /** * Return the (mutable) fetch configuration for this extent. */ public FetchConfiguration getFetchConfiguration(); /** * Whether this extent will ignore changes made in the current transaction. */ public boolean getIgnoreChanges(); /** * Whether this extent will ignore changes made in the current transaction. */ public void setIgnoreChanges(boolean ignoreChanges); /** * Returns a list of all objects represented by this extent. This method * creates a {@link List} by traversing the entire iterator returned by a * call to {@link #iterator}. This means that {@link Collection#size} will * work correctly, but if the extent represents a large data set, this * method may be quite slow and may consume quite a bit of memory. */ public List list(); /** * Return an iterator over the extent members. */ public Iterator iterator(); /** * The broker that generated the extent. */ public Broker getBroker(); /** * The class of extent elements. */ public Class getElementType(); /** * Whether the extent includes subclasses. */ public boolean hasSubclasses(); /** * Close all open iterators. */ public void closeAll(); /** * Synchronizes on an internal lock. */ public void lock(); /** * Release the internal lock. */ public void unlock (); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.jav0000644000000000000000000010452512133327272030406 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.rop.EagerResultList; import org.apache.openjpa.lib.rop.ListResultObjectProvider; import org.apache.openjpa.lib.rop.ResultList; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.lib.rop.SimpleResultList; import org.apache.openjpa.lib.rop.WindowResultList; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FetchGroup; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.NoTransactionException; import org.apache.openjpa.util.UserException; /** * Allows configuration and optimization of how objects are loaded from * the data store. * * @since 0.3.0 * @author Abe White * @author Pinaki Poddar * @nojavadoc */ @SuppressWarnings("serial") public class FetchConfigurationImpl implements FetchConfiguration, Cloneable { private static final Localizer _loc = Localizer.forPackage(FetchConfigurationImpl.class); private static Map _hintSetters = new HashMap(); /** * Registers hint keys that have a corresponding setter method. * The hint keys are registered in openjpa.FetchPlan and openjpa as prefix. * Also some keys are registered in javax.persistence namespace. */ static { String[] prefixes = {"openjpa.FetchPlan", "openjpa"}; Class target = FetchConfiguration.class; populateHintSetter(target, "ExtendedPathLookup", boolean.class, prefixes); populateHintSetter(target, "FetchBatchSize", int.class, prefixes); populateHintSetter(target, "FlushBeforeQueries", int.class, prefixes); populateHintSetter(target, "LockScope", int.class, prefixes); populateHintSetter(target, "LockTimeout", int.class, prefixes); populateHintSetter(target, "setLockTimeout", "timeout", int.class, "javax.persistence.lock"); populateHintSetter(target, "MaxFetchDepth", int.class, prefixes); populateHintSetter(target, "QueryTimeout", int.class, prefixes); populateHintSetter(target, "setQueryTimeout", "timeout", int.class, "javax.persistence.query"); populateHintSetter(target, "ReadLockLevel", int.class, prefixes); populateHintSetter(target, "setReadLockLevel", "ReadLockMode", int.class, prefixes); populateHintSetter(target, "WriteLockLevel", int.class, prefixes); populateHintSetter(target, "setWriteLockLevel", "WriteLockMode", int.class, prefixes); } /** * Populate static registry of hints. * * @param target The name of the target class that will receive this hint. * @param hint the simple name of the hint without a prefix. * @param type the value argument type of the target setter method. * @param prefixes the prefixes will be added to the simple hint name. */ protected static void populateHintSetter(Class target, String hint, Class type, String...prefixes) { populateHintSetter(target, "set" + hint, hint, type, prefixes); } /** * Populate static registry of hints. * * @param target The name of the target class that will receive this hint. * @param method The name of the method in the target class that will receive this hint. * @param hint the simple name of the hint without a prefix. * @param type the value argument type of the target setter method. * @param prefixes the prefixes will be added to the simple hint name. */ protected static void populateHintSetter(Class target, String method, String hint, Class type, String...prefixes) { try { Method setter = target.getMethod(method, type); for (String prefix : prefixes) { _hintSetters.put(prefix + "." + hint, setter); } } catch (Exception e) { // should not reach throw new InternalException("setter for " + hint + " with argument " + type + " does not exist"); } } /** * Configurable state shared throughout a traversal chain. */ protected static class ConfigurationState implements Serializable { public transient StoreContext ctx = null; public int fetchBatchSize = 0; public int maxFetchDepth = 1; public boolean queryCache = true; public int flushQuery = 0; public int lockTimeout = -1; public int queryTimeout = -1; public int lockScope = LOCKSCOPE_NORMAL; public int readLockLevel = LOCK_NONE; public int writeLockLevel = LOCK_NONE; public Set fetchGroups = null; public Set fields = null; public Set> rootClasses; public Set rootInstances; public Map hints = null; public boolean fetchGroupContainsDefault = false; public boolean fetchGroupContainsAll = false; public boolean extendedPathLookup = false; public DataCacheRetrieveMode cacheRetrieveMode = DataCacheRetrieveMode.USE; public DataCacheStoreMode cacheStoreMode = DataCacheStoreMode.USE; } private final ConfigurationState _state; private FetchConfigurationImpl _parent; private String _fromField; private Class _fromType; private String _directRelationOwner; private boolean _load = true; private int _availableRecursion; private int _availableDepth; public FetchConfigurationImpl() { this(null); } protected FetchConfigurationImpl(ConfigurationState state) { _state = (state == null) ? new ConfigurationState() : state; _availableDepth = _state.maxFetchDepth; } public StoreContext getContext() { return _state.ctx; } public void setContext(StoreContext ctx) { // can't reset non-null context to another context if (ctx != null && _state.ctx != null && ctx != _state.ctx) throw new InternalException(); _state.ctx = ctx; if (ctx == null) return; // initialize to conf info OpenJPAConfiguration conf = ctx.getConfiguration(); setFetchBatchSize(conf.getFetchBatchSize()); setFlushBeforeQueries(conf.getFlushBeforeQueriesConstant()); setLockTimeout(conf.getLockTimeout()); setQueryTimeout(conf.getQueryTimeout()); clearFetchGroups(); addFetchGroups(Arrays.asList(conf.getFetchGroupsList())); setMaxFetchDepth(conf.getMaxFetchDepth()); } /** * Clone this instance. */ public Object clone() { FetchConfigurationImpl clone = newInstance(null); clone._state.ctx = _state.ctx; clone._parent = _parent; clone._fromField = _fromField; clone._fromType = _fromType; clone._directRelationOwner = _directRelationOwner; clone._load = _load; clone._availableRecursion = _availableRecursion; clone._availableDepth = _availableDepth; clone.copy(this); return clone; } /** * Return a new hollow instance. */ protected FetchConfigurationImpl newInstance(ConfigurationState state) { return new FetchConfigurationImpl(state); } public void copy(FetchConfiguration fetch) { setFetchBatchSize(fetch.getFetchBatchSize()); setMaxFetchDepth(fetch.getMaxFetchDepth()); setQueryCacheEnabled(fetch.getQueryCacheEnabled()); setFlushBeforeQueries(fetch.getFlushBeforeQueries()); setExtendedPathLookup(fetch.getExtendedPathLookup()); setLockTimeout(fetch.getLockTimeout()); setQueryTimeout(fetch.getQueryTimeout()); setLockScope(fetch.getLockScope()); clearFetchGroups(); addFetchGroups(fetch.getFetchGroups()); clearFields(); copyHints(fetch); setCacheRetrieveMode(fetch.getCacheRetrieveMode()); setCacheStoreMode(fetch.getCacheStoreMode()); addFields(fetch.getFields()); // don't use setters because require active transaction _state.readLockLevel = fetch.getReadLockLevel(); _state.writeLockLevel = fetch.getWriteLockLevel(); } void copyHints(FetchConfiguration fetch) { if (fetch instanceof FetchConfigurationImpl == false) return; FetchConfigurationImpl from = (FetchConfigurationImpl)fetch; if (from._state == null || from._state.hints == null) return; if (this._state == null) return; if (this._state.hints == null) this._state.hints = new HashMap(); this._state.hints.putAll(from._state.hints); } public int getFetchBatchSize() { return _state.fetchBatchSize; } public FetchConfiguration setFetchBatchSize(int fetchBatchSize) { if (fetchBatchSize == DEFAULT && _state.ctx != null) fetchBatchSize = _state.ctx.getConfiguration().getFetchBatchSize(); if (fetchBatchSize != DEFAULT) _state.fetchBatchSize = fetchBatchSize; return this; } public int getMaxFetchDepth() { return _state.maxFetchDepth; } public FetchConfiguration setMaxFetchDepth(int depth) { if (depth == DEFAULT && _state.ctx != null) depth = _state.ctx.getConfiguration().getMaxFetchDepth(); if (depth != DEFAULT) { _state.maxFetchDepth = depth; if (_parent == null) _availableDepth = depth; } return this; } public boolean getQueryCacheEnabled() { return _state.queryCache; } public FetchConfiguration setQueryCacheEnabled(boolean cache) { _state.queryCache = cache; return this; } public int getFlushBeforeQueries() { return _state.flushQuery; } public boolean getExtendedPathLookup() { return _state.extendedPathLookup; } public FetchConfiguration setExtendedPathLookup(boolean flag) { _state.extendedPathLookup = flag; return this; } public FetchConfiguration setFlushBeforeQueries(int flush) { if (flush != DEFAULT && flush != QueryFlushModes.FLUSH_TRUE && flush != QueryFlushModes.FLUSH_FALSE && flush != QueryFlushModes.FLUSH_WITH_CONNECTION) throw new IllegalArgumentException(_loc.get( "bad-flush-before-queries", Integer.valueOf(flush)).getMessage()); if (flush == DEFAULT && _state.ctx != null) _state.flushQuery = _state.ctx.getConfiguration(). getFlushBeforeQueriesConstant(); else if (flush != DEFAULT) _state.flushQuery = flush; return this; } public Set getFetchGroups() { if (_state.fetchGroups == null) return Collections.emptySet(); return _state.fetchGroups; } public boolean hasFetchGroup(String group) { return _state.fetchGroups != null && (_state.fetchGroups.contains(group) || _state.fetchGroups.contains(FetchGroup.NAME_ALL)); } public boolean hasFetchGroupDefault() { // Fetch group All includes fetch group Default by definition return _state.fetchGroupContainsDefault || _state.fetchGroupContainsAll; } public boolean hasFetchGroupAll() { return _state.fetchGroupContainsAll; } public FetchConfiguration addFetchGroup(String name) { if (StringUtils.isEmpty(name)) throw new UserException(_loc.get("null-fg")); lock(); try { if (_state.fetchGroups == null) _state.fetchGroups = new HashSet(); _state.fetchGroups.add(name); if (FetchGroup.NAME_ALL.equals(name)) _state.fetchGroupContainsAll = true; else if (FetchGroup.NAME_DEFAULT.equals(name)) _state.fetchGroupContainsDefault = true; } finally { unlock(); } return this; } public FetchConfiguration addFetchGroups(Collection groups) { if (groups == null || groups.isEmpty()) return this; for (String group : groups) addFetchGroup(group); return this; } public FetchConfiguration removeFetchGroup(String group) { lock(); try { if (_state.fetchGroups != null) { _state.fetchGroups.remove(group); if (FetchGroup.NAME_ALL.equals(group)) _state.fetchGroupContainsAll = false; else if (FetchGroup.NAME_DEFAULT.equals(group)) _state.fetchGroupContainsDefault = false; } } finally { unlock(); } return this; } public FetchConfiguration removeFetchGroups(Collection groups) { lock(); try { if (_state.fetchGroups != null && groups != null) for (String group : groups) removeFetchGroup(group); } finally { unlock(); } return this; } public FetchConfiguration clearFetchGroups() { lock(); try { if (_state.fetchGroups != null) { _state.fetchGroups.clear(); _state.fetchGroupContainsAll = false; _state.fetchGroupContainsDefault = true; } } finally { unlock(); } return this; } public FetchConfiguration resetFetchGroups() { clearFetchGroups(); if (_state.ctx != null) addFetchGroups(Arrays.asList(_state.ctx.getConfiguration(). getFetchGroupsList())); return this; } public Set getFields() { if (_state.fields == null) return Collections.emptySet(); return _state.fields; } public boolean hasField(String field) { return _state.fields != null && _state.fields.contains(field); } public FetchConfiguration addField(String field) { if (StringUtils.isEmpty(field)) throw new UserException(_loc.get("null-field")); lock(); try { if (_state.fields == null) _state.fields = new HashSet(); _state.fields.add(field); } finally { unlock(); } return this; } public FetchConfiguration addFields(Collection fields) { if (fields == null || fields.isEmpty()) return this; lock(); try { if (_state.fields == null) _state.fields = new HashSet(); _state.fields.addAll(fields); } finally { unlock(); } return this; } public FetchConfiguration removeField(String field) { lock(); try { if (_state.fields != null) _state.fields.remove(field); } finally { unlock(); } return this; } public FetchConfiguration removeFields(Collection fields) { lock(); try { if (_state.fields != null) _state.fields.removeAll(fields); } finally { unlock(); } return this; } public FetchConfiguration clearFields() { lock(); try { if (_state.fields != null) _state.fields.clear(); } finally { unlock(); } return this; } public DataCacheRetrieveMode getCacheRetrieveMode() { return _state.cacheRetrieveMode; } public DataCacheStoreMode getCacheStoreMode() { return _state.cacheStoreMode; } public void setCacheRetrieveMode(DataCacheRetrieveMode mode) { _state.cacheRetrieveMode = mode; } public void setCacheStoreMode(DataCacheStoreMode mode) { _state.cacheStoreMode = mode; } public int getLockTimeout() { return _state.lockTimeout; } public FetchConfiguration setLockTimeout(int timeout) { if (timeout == DEFAULT && _state.ctx != null) _state.lockTimeout = _state.ctx.getConfiguration().getLockTimeout(); else if (timeout != DEFAULT) { if (timeout < -1) { throw new IllegalArgumentException(_loc.get("invalid-timeout", timeout).getMessage()); } else { _state.lockTimeout = timeout; } } return this; } public int getQueryTimeout() { return _state.queryTimeout; } public FetchConfiguration setQueryTimeout(int timeout) { if (timeout == DEFAULT && _state.ctx != null) _state.queryTimeout = _state.ctx.getConfiguration(). getQueryTimeout(); else if (timeout != DEFAULT) { if (timeout < -1) { throw new IllegalArgumentException(_loc.get("invalid-timeout", timeout).getMessage()); } else { _state.queryTimeout = timeout; } } return this; } public int getLockScope() { return _state.lockScope; } public FetchConfiguration setLockScope(int scope) { if (scope != DEFAULT && scope != LockScopes.LOCKSCOPE_NORMAL && scope != LockScopes.LOCKSCOPE_EXTENDED) throw new IllegalArgumentException(_loc.get( "bad-lock-scope", Integer.valueOf(scope)).getMessage()); if (scope == DEFAULT ) _state.lockScope = LOCKSCOPE_NORMAL; else _state.lockScope = scope; return this; } public int getReadLockLevel() { return _state.readLockLevel; } public FetchConfiguration setReadLockLevel(int level) { if (_state.ctx == null) return this; if (level != DEFAULT && level != MixedLockLevels.LOCK_NONE && level != MixedLockLevels.LOCK_READ && level != MixedLockLevels.LOCK_OPTIMISTIC && level != MixedLockLevels.LOCK_WRITE && level != MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT && level != MixedLockLevels.LOCK_PESSIMISTIC_READ && level != MixedLockLevels.LOCK_PESSIMISTIC_WRITE && level != MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT) throw new IllegalArgumentException(_loc.get( "bad-lock-level", Integer.valueOf(level)).getMessage()); lock(); try { if (level != MixedLockLevels.LOCK_NONE) assertActiveTransaction(); if (level == DEFAULT) _state.readLockLevel = _state.ctx.getConfiguration(). getReadLockLevelConstant(); else _state.readLockLevel = level; } finally { unlock(); } return this; } public int getWriteLockLevel() { return _state.writeLockLevel; } public FetchConfiguration setWriteLockLevel(int level) { if (_state.ctx == null) return this; if (level != DEFAULT && level != MixedLockLevels.LOCK_NONE && level != MixedLockLevels.LOCK_READ && level != MixedLockLevels.LOCK_OPTIMISTIC && level != MixedLockLevels.LOCK_WRITE && level != MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT && level != MixedLockLevels.LOCK_PESSIMISTIC_READ && level != MixedLockLevels.LOCK_PESSIMISTIC_WRITE && level != MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT) throw new IllegalArgumentException(_loc.get( "bad-lock-level", Integer.valueOf(level)).getMessage()); lock(); try { assertActiveTransaction(); if (level == DEFAULT) _state.writeLockLevel = _state.ctx.getConfiguration(). getWriteLockLevelConstant(); else _state.writeLockLevel = level; } finally { unlock(); } return this; } public ResultList newResultList(ResultObjectProvider rop) { if (rop instanceof ListResultObjectProvider) return new SimpleResultList(rop); if (_state.fetchBatchSize < 0) return new EagerResultList(rop); if (rop.supportsRandomAccess()) return new SimpleResultList(rop); return new WindowResultList(rop); } /** * Throw an exception if no transaction is active. */ private void assertActiveTransaction() { if (!isActiveTransaction()) throw new NoTransactionException(_loc.get("not-active")); } private boolean isActiveTransaction() { return (_state.ctx != null && _state.ctx.isActive()); } /** * Gets the current hints set on this receiver. * The values designate the actual value specified by the caller and not the values * that may have been actually set on the state variables of this receiver. * */ public Map getHints() { if (_state.hints == null) return Collections.emptyMap(); return Collections.unmodifiableMap(_state.hints); } /** * Affirms if the given key is set as a hint. */ public boolean isHintSet(String key) { return _state.hints != null && _state.hints.containsKey(key); } /** * Removes the given keys and their hint value. */ public void removeHint(String...keys) { if (keys == null || _state.hints == null ) return; for (String key : keys) { _state.hints.remove(key); } } public Collection getSupportedHints() { return _hintSetters.keySet(); } /** * Same as setHint(key, value, value). * * @see #setHint(String, Object, Object) */ public void setHint(String key, Object value) { setHint(key, value, value); } /** * Sets the hint to the given value. * If the key corresponds to a known key, then that value is set via the setter method. * Otherwise it is put into opaque hints map. *
    * In either case, the original value is put in the hints map. * So essential difference between setting a value directly by a setter and via a hint is the memory * of this original value. *
    * The other important difference is setting lock levels. Setting of lock level via setter method needs * active transaction. But setting via hint does not. * @param key a hint key. If it is one of the statically registered hint key then the setter is called. * @param value to be set. The given value type must match the argument type of the setter, if one exists. * @param original value as specified by the caller. This value is put in the hints map. * * @exception IllegalArgumentException if the given value is not acceptable by the setter method, if one * exists corresponds the given hint key. */ public void setHint(String key, Object value, Object original) { if (key == null) return; if (_hintSetters.containsKey(key)) { Method setter = _hintSetters.get(key); String methodName = setter.getName(); try { if ("setReadLockLevel".equals(methodName) && !isActiveTransaction()) { _state.readLockLevel = (Integer)value; } else if ("setWriteLockLevel".equals(methodName) && !isActiveTransaction()) { _state.writeLockLevel = (Integer)value; } else { setter.invoke(this, Filters.convertToMatchMethodArgument(value, setter)); } } catch (Exception e) { String message = _loc.get("bad-hint-value", key, toString(value), toString(original)).getMessage(); if (e instanceof IllegalArgumentException) { throw new IllegalArgumentException(message); } throw new IllegalArgumentException(message, e); } } addHint(key, original); } private void addHint(String name, Object value) { lock(); try { if (_state.hints == null) _state.hints = new HashMap(); _state.hints.put(name, value); } finally { unlock(); } } public Object getHint(String name) { return (_state.hints == null) ? null : _state.hints.get(name); } public Object removeHint(String name) { return (_state.hints == null) ? null : _state.hints.remove(name); } public Set> getRootClasses() { if (_state.rootClasses == null) return Collections.emptySet(); return _state.rootClasses; } public FetchConfiguration setRootClasses(Collection> classes) { lock(); try { if (_state.rootClasses != null) _state.rootClasses.clear(); if (classes != null && !classes.isEmpty()) { if (_state.rootClasses == null) _state.rootClasses = new HashSet>(classes); else _state.rootClasses.addAll(classes); } } finally { unlock(); } return this; } public Set getRootInstances() { if (_state.rootInstances == null) return Collections.emptySet(); return _state.rootInstances; } public FetchConfiguration setRootInstances(Collection instances) { lock(); try { if (_state.rootInstances != null) _state.rootInstances.clear(); if (instances != null && !instances.isEmpty()) { if (_state.rootInstances == null) { _state.rootInstances = new HashSet(instances); } else { _state.rootInstances.addAll(instances); } } } finally { unlock(); } return this; } public void lock() { if (_state.ctx != null) _state.ctx.lock(); } public void unlock() { if (_state.ctx != null) _state.ctx.unlock(); } ///////////// // Traversal ///////////// public int requiresFetch(FieldMetaData fm) { if (!includes(fm)) return FETCH_NONE; Class type = fm.getRelationType(); if (type == null) return FETCH_LOAD; if (_availableDepth == 0) return FETCH_NONE; // we can skip calculating recursion depth if this is a top-level conf: // the field is in our fetch groups, so can't possibly not select if (_parent == null) return FETCH_LOAD; String fieldName = fm.getFullName(false); int rdepth = getAvailableRecursionDepth(fm, type, fieldName, false); if (rdepth != FetchGroup.DEPTH_INFINITE && rdepth <= 0) return FETCH_NONE; if (StringUtils.equals(_directRelationOwner, fieldName)) return FETCH_REF; return FETCH_LOAD; } public boolean requiresLoad() { return _load; } public FetchConfiguration traverse(FieldMetaData fm) { Class type = fm.getRelationType(); if (type == null) return this; FetchConfigurationImpl clone = newInstance(_state); clone._parent = this; clone._availableDepth = reduce(_availableDepth); clone._fromField = fm.getFullName(false); clone._fromType = type; clone._availableRecursion = getAvailableRecursionDepth(fm, type, fm.getFullName(false), true); if (StringUtils.equals(_directRelationOwner, fm.getFullName(false))) clone._load = false; else clone._load = _load; FieldMetaData owner = fm.getMappedByMetaData(); if (owner != null && owner.getTypeCode() == JavaTypes.PC) clone._directRelationOwner = owner.getFullName(false); return clone; } /** * Whether our configuration state includes the given field. */ private boolean includes(FieldMetaData fmd) { if ((hasFetchGroupDefault() && fmd.isInDefaultFetchGroup()) || hasFetchGroupAll() || hasField(fmd.getFullName(false)) || hasExtendedLookupPath(fmd)) return true; String[] fgs = fmd.getCustomFetchGroups(); for (int i = 0; i < fgs.length; i++) if (hasFetchGroup(fgs[i])) return true; return false; } private boolean hasExtendedLookupPath(FieldMetaData fmd) { return getExtendedPathLookup() && (hasField(fmd.getRealName()) || (_fromField != null && hasField(_fromField + "." + fmd.getName()))); } /** * Return the available recursion depth via the given field for the * given type. * * @param traverse whether we're traversing the field */ private int getAvailableRecursionDepth(FieldMetaData fm, Class type, String fromField, boolean traverse) { // see if there's a previous limit int avail = Integer.MIN_VALUE; for (FetchConfigurationImpl f = this; f != null; f = f._parent) { if (StringUtils.equals(f._fromField, fromField) && ImplHelper.isAssignable(f._fromType, type)) { avail = f._availableRecursion; if (traverse) avail = reduce(avail); break; } } if (avail == 0) return 0; // calculate fetch groups max ClassMetaData meta = fm.getDefiningMetaData(); int max = Integer.MIN_VALUE; if (fm.isInDefaultFetchGroup()) max = meta.getFetchGroup(FetchGroup.NAME_DEFAULT). getRecursionDepth(fm); String[] groups = fm.getCustomFetchGroups(); int cur; for (int i = 0; max != FetchGroup.DEPTH_INFINITE && i < groups.length; i++) { // ignore custom groups that are inactive in this configuration if (!this.hasFetchGroup(groups[i])) continue; cur = meta.getFetchGroup(groups[i]).getRecursionDepth(fm); if (cur == FetchGroup.DEPTH_INFINITE || cur > max) max = cur; } // reduce max if we're traversing a self-type relation if (traverse && max != Integer.MIN_VALUE && ImplHelper.isAssignable(meta.getDescribedType(), type)) max = reduce(max); // take min/defined of previous avail and fetch group max if (avail == Integer.MIN_VALUE && max == Integer.MIN_VALUE) { int def = FetchGroup.RECURSION_DEPTH_DEFAULT; return (traverse && ImplHelper.isAssignable( meta.getDescribedType(), type)) ? def - 1 : def; } if (avail == Integer.MIN_VALUE || avail == FetchGroup.DEPTH_INFINITE) return max; if (max == Integer.MIN_VALUE || max == FetchGroup.DEPTH_INFINITE) return avail; return Math.min(max, avail); } /** * Reduce the given logical depth by 1. */ private static int reduce(int d) { if (d == 0) return 0; if (d != FetchGroup.DEPTH_INFINITE) d--; return d; } ///////////////// // Debug methods ///////////////// FetchConfiguration getParent() { return _parent; } boolean isRoot() { return _parent == null; } FetchConfiguration getRoot() { return (isRoot()) ? this : _parent.getRoot(); } int getAvailableFetchDepth() { return _availableDepth; } int getAvailableRecursionDepth() { return _availableRecursion; } String getTraversedFromField() { return _fromField; } Class getTraversedFromType() { return _fromType; } List getPath() { if (isRoot()) return Collections.emptyList(); return trackPath(new ArrayList()); } List trackPath(List path) { if (_parent != null) _parent.trackPath(path); path.add(this); return path; } public String toString() { return "FetchConfiguration@" + System.identityHashCode(this) + " (" + _availableDepth + ")" + getPathString(); } private String getPathString() { List path = getPath(); if (path.isEmpty()) return ""; StringBuilder buf = new StringBuilder().append (": "); for (Iterator itr = path.iterator(); itr.hasNext();) { buf.append(itr.next().getTraversedFromField()); if (itr.hasNext()) buf.append("->"); } return buf.toString(); } protected String toString(Object o) { return o == null ? "null" : o.toString() + "[" + o.getClass().getName() + "]"; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateAttachStrategy.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateAttachStrateg0000644000000000000000000002065412133327272030405 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.ApplicationIds; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.OptimisticException; import org.apache.openjpa.util.ImplHelper; /** * Handles attaching instances with detached state. * * @nojavadoc * @author Marc Prud'hommeaux */ class DetachedStateAttachStrategy extends AttachStrategy { private static final Localizer _loc = Localizer.forPackage (DetachedStateAttachStrategy.class); protected Object getDetachedObjectId(AttachManager manager, Object toAttach) { if (toAttach == null) return null; Broker broker = manager.getBroker(); PersistenceCapable pc = ImplHelper.toPersistenceCapable(toAttach, broker.getConfiguration()); ClassMetaData meta = broker.getConfiguration(). getMetaDataRepositoryInstance().getMetaData( ImplHelper.getManagedInstance(toAttach).getClass(), broker.getClassLoader(), true); switch (meta.getIdentityType()) { case ClassMetaData.ID_DATASTORE: Object[] state = (Object[]) pc.pcGetDetachedState(); if (state == null) return null; return broker .newObjectId(toAttach.getClass(), state[0]); case ClassMetaData.ID_APPLICATION: return ApplicationIds.create(pc, meta); default: throw new InternalException(); } } protected void provideField(Object toAttach, StateManagerImpl sm, int field) { sm.provideField(ImplHelper.toPersistenceCapable(toAttach, sm.getContext().getConfiguration()), this, field); } public Object attach(AttachManager manager, Object toAttach, ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit) { BrokerImpl broker = manager.getBroker(); PersistenceCapable pc = ImplHelper.toPersistenceCapable(toAttach, manager.getBroker().getConfiguration()); Object[] state = (Object[]) pc.pcGetDetachedState(); boolean embedded = ownerMeta != null && ownerMeta.isEmbeddedPC(); int offset; StateManagerImpl sm; // state == null means this is a new instance; also, if the // state manager for the embedded instance is null, then // it should be treated as a new instance (since the // newly persisted owner may create a new embedded instance // in the constructor); fixed bug #1075. // also, if the user has attached a detached obj from somewhere // else in the graph to an embedded field that was previously null, // copy into a new embedded instance if (embedded && (state == null || into == null || broker.getStateManager(into) == null)) { if (into == null) into = pc.pcNewInstance(null, false); sm = (StateManagerImpl) broker.embed(into, null, owner, ownerMeta); into = sm.getPersistenceCapable(); } else if (state == null) { sm = persist(manager, pc, meta, ApplicationIds.create(pc, meta), explicit); into = sm.getPersistenceCapable(); } else if (!embedded && into == null) { Object id = getDetachedObjectId(manager, pc); if (id != null) into = ImplHelper.toPersistenceCapable(broker.find(id, true, null), manager.getBroker().getConfiguration()); if (into == null) { // we mark objects that were new on detach by putting an empty // extra element in their detached state array offset = meta.getIdentityType() == meta.ID_DATASTORE ? 1 : 0; boolean isNew = state.length == 3 + offset; // attempting to attach an instance that has been deleted // will throw an OVE if it was not PNEW when it was detached if (!isNew) throw new OptimisticException(_loc.get("attach-deleted", ImplHelper.getManagedInstance(pc).getClass(), id)) .setFailedObject(id); // if the instance does not exist, we assume that it was // made persistent in a new transaction, detached, and then // the transaction was rolled back; the danger is that // the instance was made persistent, detached, committed, // and then deleted, but this is an uncommon case sm = persist(manager, pc, meta, id, explicit); into = sm.getPersistenceCapable(); // nullify the state, since the new instance won't have one state = null; } else sm = manager.assertManaged(into); } else sm = manager.assertManaged(into); // mark that we attached the instance *before* we // fill in values to avoid endless recursion manager.setAttachedCopy(pc, into); meta = sm.getMetaData(); manager.fireBeforeAttach(pc, meta); offset = meta.getIdentityType() == meta.ID_DATASTORE ? 1 : 0; // assign the detached pc the same state manager as the object we're // copying into during the attach process pc.pcReplaceStateManager(sm); BitSet fields = state == null ? null : (BitSet) state[1 + offset]; try { FieldMetaData[] fmds = meta.getFields(); for (int i = 0; i < fmds.length; i++) { // only attach fields in the FG of the detached instance; new // instances get all their fields attached if (fields == null || fields.get(i)) attachField(manager, pc, sm, fmds[i], true); } } finally { pc.pcReplaceStateManager(null); } // set the next version for non-new instances that are not embedded if (state != null && !embedded) { // make sure that all the fields in the original FG are loaded // before we try to compare version if (fields != null && !fields.equals(sm.getLoaded())) { BitSet toLoad = (BitSet) fields.clone(); toLoad.andNot(sm.getLoaded()); // skip already loaded fields if (toLoad.length() > 0) sm.loadFields(toLoad, null, LockLevels.LOCK_NONE, null); //### we should calculate lock level above } Object version = state[offset]; StoreManager store = broker.getStoreManager(); switch (store.compareVersion(sm, version, sm.getVersion())) { case StoreManager.VERSION_LATER: // we have a later version: set it into the object. // lock validation will occur at commit time sm.setVersion(version); break; case StoreManager.VERSION_EARLIER: case StoreManager.VERSION_DIFFERENT: sm.setVersion(version); throw new OptimisticException(into); case StoreManager.VERSION_SAME: // no action required break; } } return ImplHelper.getManagedInstance(into); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FindCallbacks.java0000644000000000000000000000262212133327272026617 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Allows facades to control the particulars of the find operation * through callbacks. * * @author Abe White */ public interface FindCallbacks { /** * Process find argument. Throw proper * {@link org.apache.openjpa.util.OpenJPAException} for illegal value. * * @return the id to look up, or null to ignore this argument */ public Object processArgument(Object oid); /** * Process operation return value. * * @return the object to return */ public Object processReturn(Object oid, OpenJPAStateManager sm); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FinderCache.java0000644000000000000000000001223312133327272026271 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.List; import java.util.Map; import org.apache.openjpa.lib.conf.Configurable; /** * A cache to create and maintain {@link FinderQuery finder queries}. * * A finder query is a query to find instance of a given class by its primary * identity. This cache maintains finder queries by generic identifier of * parameterized type K. * * A cached query by an identifier of parameterized type K. * * A query can be cached by an identifier and value represented by parameterized * type V. Caching results in creating a new instance of FinderQuery FQ from the * value V such that FQ can be executed to return a result of parameterized type * R. A request to cache may not be successful if this cache determines the * value V to be not cachable. * * Both get() and put() operations can be controlled by the hints associated * with FetchConfiguration. * * The target database query FQ associated to a cached finder query F * may depend upon query execution context such as fetch plan or * lock group. This cache, by design, does not monitor the context or * automatically invalidate an entry when the original query F is executed * with context parameters that affect the target query FQ. * * The user must notify this receiver to invalidate a cached entry when * execution context changes in a way that will modify the resultant database * language query FQ. * * One of the built-in mechanism (available in JPA facade) is to set query hints * to either invalidate the query entirely or ignore the cached version for the * current execution. * * @see QueryHints#HINT_IGNORE_FINDER * @see QueryHints#HINT_INVALIDATE_FINDER * @see QueryHints#HINT_RECACHE_FINDER * * This cache allows customization of whether a query can be cached or not * via either explicit marking of certain classes as non-cachable (which is * irreversible) or addition/removal of exclusion patterns (which is reversible) * * @author Pinaki Poddar * * @since 2.0.0 */ public interface FinderCache extends Configurable { /** * Get the FinderQuery for the given key. * * @param key for which the finder is looked up * @param fecth may contain hints to control lookup operation * * @return FinderQuery for the given mapping. */ public FinderQuery get(K key, FetchConfiguration fetch); /** * Cache a FinderQuery for the given key and value. * * @param key for which the finder is cached. * @param value used to construct the finder query * @param fetch may contain hints to control cache operation. * * @return the finder query that has been cached. It may be newly * constructed or an existing query. If the given key-value can not be * cached, then return null. */ public FinderQuery cache(K key, V value, FetchConfiguration fetch); /** * Get a map view of the cached entries as strings. */ public Map getMapView(); /** * Remove the FinderQuery for the given key from this cache. */ public boolean invalidate(K key); /** * Marks the given key as not amenable to caching. * Explicit marking helps to avoid repeated computational cost of * determining whether finder for a key can be cached or not. * * Explicit marking can not be reversed by removal of exclusion patterns. * * @return finder query for the given class if it had been cached before. * null otherwise. */ public FinderQuery markUncachable(K key); /** * Affirms if the given key matches any of the exclusion patterns. */ public boolean isExcluded(K key); /** * Gets the excluded stringified keys. */ public List getExcludes(); /** * Adds the given pattern to the list of excluded patterns. Any existing * cache entry whose key matches the given pattern will be marked * non-cachable in a reversible manner. */ public void addExclusionPattern(String pattern); /** * Removes the given pattern from the list of excluded patterns. * Any excluded entry that matches the given pattern can now be cached * again, unless it has been marked non-cachable explicitly. */ public void removeExclusionPattern(String pattern); /** * Gets the simple statistics for executed finder queries. */ public QueryStatistics getStatistics(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDHexSeq.java0000644000000000000000000000343612133327272026027 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.lib.util.UUIDGenerator; import org.apache.openjpa.meta.ClassMetaData; /** * Sequence for generating 32-character hex UUID strings. * * @author Abe White */ public class UUIDHexSeq implements Seq { private static final UUIDHexSeq _instance = new UUIDHexSeq(); private String _last = null; /** * Return the singleton instance. */ public static UUIDHexSeq getInstance() { return _instance; } /** * Hide constructor. */ private UUIDHexSeq() { } public void setType(int type) { } public synchronized Object next(StoreContext ctx, ClassMetaData meta) { _last = UUIDGenerator.nextHex(UUIDGenerator.TYPE1); return _last; } public synchronized Object current(StoreContext ctx, ClassMetaData meta) { return _last; } public void allocate(int additional, StoreContext ctx, ClassMetaData meta) { } public void close() { } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryStatistics.java0000644000000000000000000002175312133327272027325 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.io.PrintStream; import java.io.Serializable; import java.util.Collections; import java.util.Date; import java.util.Map; import java.util.Set; import org.apache.openjpa.lib.util.concurrent.SizedConcurrentHashMap; /** * Records query execution statistics. * * Statistics can be reset. * * Gathers both accumulated statistics since start as well as statistics since * last reset. * * @since 1.3.0 * * @author Pinaki Poddar * */ public interface QueryStatistics extends Serializable { /** * Gets all the identifier keys for the cached queries. */ public Set keys(); /** * Record that the given query has been executed. */ void recordExecution(T query); /** * Record that the given query has been evicted. */ void recordEviction(T query); /** * Gets number of total query execution since last reset. */ public long getExecutionCount(); /** * Gets number of total query execution since start. */ public long getTotalExecutionCount(); /** * Gets number of executions for the given query since last reset. */ public long getExecutionCount(T query); /** * Gets number of executions for the given query since start. */ public long getTotalExecutionCount(T query); /** * Gets number of total query execution that are cached since last reset. */ public long getHitCount(); /** * Gets number of total query execution that are cached since start. */ public long getTotalHitCount(); /** * Gets number of executions for the given query that are cached since * last reset. */ public long getHitCount(T query); /** * Gets number of executions for the given query that are cached since * start. */ public long getTotalHitCount(T query); /** * Gets number of total query evictions since last reset. */ public long getEvictionCount(); /** * Gets number of total query evictions since start. */ public long getTotalEvictionCount(); /** * Gets the time of last reset. */ public Date since(); /** * Gets the time of start. */ public Date start(); /** * Clears all statistics accumulated since last reset. */ public void reset(); /** * Clears all statistics accumulated since start. */ public void clear(); /** * Dumps on the given output stream. */ public void dump(PrintStream out); /** * A default implementation. * * Maintains statistics for only a fixed number of queries. * Statistical counts are approximate and not exact (to keep thread synchorization overhead low). * */ public static class Default implements QueryStatistics { private static final int FIXED_SIZE = 1000; private static final float LOAD_FACTOR = 0.75f; private static final int CONCURRENCY = 16; private static final int ARRAY_SIZE = 3; private static final int READ = 0; private static final int HIT = 1; private static final int EVICT = 2; private long[] astat = new long[ARRAY_SIZE]; private long[] stat = new long[ARRAY_SIZE]; private Map stats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY); private Map astats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY); private Date start = new Date(); private Date since = start; public Set keys() { return stats.keySet(); } public long getExecutionCount() { return stat[READ]; } public long getTotalExecutionCount() { return astat[READ]; } public long getExecutionCount(T query) { return getCount(stats, query, READ); } public long getTotalExecutionCount(T query) { return getCount(astats, query, READ); } public long getHitCount() { return stat[HIT]; } public long getTotalHitCount() { return astat[HIT]; } public long getHitCount(T query) { return getCount(stats, query, HIT); } public long getTotalHitCount(T query) { return getCount(astats, query, HIT); } private long getCount(Map target, T query, int i) { long[] row = target.get(query); return (row == null) ? 0 : row[i]; } public Date since() { return since; } public Date start() { return start; } public synchronized void reset() { stat = new long[ARRAY_SIZE]; stats.clear(); since = new Date(); } public synchronized void clear() { astat = new long[ARRAY_SIZE]; stat = new long[ARRAY_SIZE]; stats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY); astats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY); start = new Date(); since = start; } private void addSample(T query, int index) { stat[index]++; astat[index]++; addSample(stats, query, index); addSample(astats, query, index); } private void addSample(Map target, T query, int i) { long[] row = target.get(query); if (row == null) { row = new long[ARRAY_SIZE]; } row[i]++; target.put(query, row); } public void recordExecution(T query) { if (query == null) return; boolean cached = astats.containsKey(query); addSample(query, READ); if (cached) addSample(query, HIT); } public void recordEviction(T query) { if (query == null) { return; } addSample(query, EVICT); } public void dump(PrintStream out) { String header = "Query Statistics starting from " + start; out.print(header); if (since == start) { out.println(); out.println("Total Query Execution: " + toString(astat)); out.println("\tTotal \t\tQuery"); } else { out.println(" last reset on " + since); out.println("Total Query Execution since start " + toString(astat) + " since reset " + toString(stat)); out.println("\tSince Start \tSince Reset \t\tQuery"); } int i = 0; for (T key : stats.keySet()) { i++; long[] arow = astats.get(key); if (since == start) { out.println(i + ". \t" + toString(arow) + " \t" + key); } else { long[] row = stats.get(key); out.println(i + ". \t" + toString(arow) + " \t" + toString(row) + " \t\t" + key); } } } long pct(long per, long cent) { if (cent <= 0) return 0; return (100*per)/cent; } String toString(long[] row) { return row[READ] + ":" + row[HIT] + "(" + pct(row[HIT], row[READ]) + "%)"; } public long getEvictionCount() { return stat[EVICT]; } public long getTotalEvictionCount() { return astat[EVICT]; } } /** * A do-nothing implementation. * * @author Pinaki Poddar * * @param */ public static class None implements QueryStatistics { private Date start = new Date(); private Date since = start; public void clear() { } public void dump(PrintStream out) { } public long getExecutionCount() { return 0; } public long getExecutionCount(T query) { return 0; } public long getHitCount() { return 0; } public long getHitCount(T query) { return 0; } public long getTotalExecutionCount() { return 0; } public long getTotalExecutionCount(T query) { return 0; } public long getTotalHitCount() { return 0; } public long getTotalHitCount(T query) { return 0; } public long getEvictionCount() { return 0; } public long getTotalEvictionCount() { return 0; } public Set keys() { return Collections.emptySet(); } public void recordExecution(T query) { } public void reset() { start = new Date(); since = start; } public Date since() { return since; } public Date start() { return start; } public void recordEviction(T query) { } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java0000644000000000000000000001201412133327272026246 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Standard query hint keys. */ public interface QueryHints { // These keys are directly handled in {@link QueryImpl} class. // Declaring a public static final String variable in this class will // make it register as a supported hint key // if you do not want that then annotate as {@link Reflectable(false)}. public static final String HINT_SUBCLASSES = "openjpa.Subclasses"; public static final String HINT_FILTER_LISTENER = "openjpa.FilterListener"; public static final String HINT_FILTER_LISTENERS = "openjpa.FilterListeners"; public static final String HINT_AGGREGATE_LISTENER = "openjpa.AggregateListener"; public static final String HINT_AGGREGATE_LISTENERS = "openjpa.AggregateListeners"; /** * Hint to specify the number of rows to optimize for. */ public static final String HINT_RESULT_COUNT = "openjpa.hint.OptimizeResultCount"; /** * Hints to signal that the JPQL/SQL query string contains a parameter * marker ? character. By default, the query string is parsed * to count number of parameters assuming that all ? characters * designate a bind parameter. This assumption makes the parse faster. */ public static final String HINT_PARAM_MARKER_IN_QUERY = "openjpa.hint.ParameterMarkerInQuery"; /** * A directive to invalidate any prepared SQL that might have been cached * against a JPQL query. The target SQL corresponding to a JPQL depends on * several context parameters such as fetch configuration, lock mode etc. * If a query is executed repeatedly and hence its SQL is cached for faster * execution then if any of the contextual parameters change across query * execution then the user must supply this hint to invalidate the cached * SQL query. * The alternative to monitor any such change for automatic invalidation * has a constant performance penalty for the frequent use case where a * query is repeatedly executed in different persistent context with the * same fetch plan or locking. * * @see #HINT_IGNORE_PREPARED_QUERY */ public static final String HINT_INVALIDATE_PREPARED_QUERY = "openjpa.hint.InvalidatePreparedQuery"; /** * A directive to ignore any prepared SQL that might have been cached * against a JPQL query. The target SQL corresponding to a JPQL depends on * several context parameters such as fetch configuration, lock mode etc. * If a query is executed repeatedly and hence its SQL is cached for faster * execution then if any of the contextual parameters change across query * execution then the user must supply this hint to ignore the cached * SQL query for the current execution. * This is in contrast with invalidation hint that removes the cached * version from cache altogether. * * The cached SQL is retained and subsequent execution of the same query * string without this hint will reuse the cached SQL. * * @see #HINT_INVALIDATE_PREPARED_QUERY */ public static final String HINT_IGNORE_PREPARED_QUERY = "openjpa.hint.IgnorePreparedQuery"; /** * A directive to ignore any cached finder query for find() operation. * The cached entry, if any, remains in the cache. */ public static final String HINT_IGNORE_FINDER = "openjpa.hint.IgnoreFinder"; /** * A directive to invalidate any cached finder query. */ public static final String HINT_INVALIDATE_FINDER = "openjpa.hint.InvalidateFinder"; /** * A directive to overwrite a cached finder query by a new query. */ public static final String HINT_RECACHE_FINDER = "openjpa.hint.RecacheFinder"; /** * A boolean directive to relax checking of binding parameter value and the predicate * it binds to. */ public static final String HINT_RELAX_BIND_PARAM_TYPE_CHECK = "openjpa.hint.RelaxParameterTypeChecking"; /** * A boolean directive to generate literal directly into the SQL statement instead of using position parameter, * if possible. */ public static final String HINT_USE_LITERAL_IN_SQL = "openjpa.hint.UseLiteralInSQL"; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionLockManager.java0000644000000000000000000001320012133327272027662 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * {@link LockManager} implementation that provides support * for version checking and version updating when locks are acquired. * This lock manager may be used standalone or extended for additional locking. * * @author Marc Prud'hommeaux */ public class VersionLockManager extends AbstractLockManager { private boolean _versionCheckOnReadLock = true; private boolean _versionUpdateOnWriteLock = true; private boolean _refreshing = false; /** * Returns the given instance's lock level, assuming that the state's * lock object is a number. If the given instance is embedded, traverses * to its owner. Override if lock is not stored as a number. */ public int getLockLevel(OpenJPAStateManager sm) { while (sm.getOwner() != null) sm = sm.getOwner(); Number level = (Number) sm.getLock(); return (level == null) ? LOCK_NONE : level.intValue(); } /** * Sets the given instance's lock level to the given number. Override * to store something else as the lock. */ protected void setLockLevel(OpenJPAStateManager sm, int level) { sm.setLock(level); } /** * Nulls given instance's lock object. */ public void release(OpenJPAStateManager sm) { sm.setLock(null); } /** * Delegates to {@link #lockInternal} after traversing to owning * instance (if embedded) and assuring that the instance is persistent, * is not new, and is not already locked at a higher level. After * locking, calls {@link #setLockLevel} with the given level. */ public void lock(OpenJPAStateManager sm, int level, int timeout, Object sdata) { commonLock(sm, level, timeout, sdata, !_refreshing); } public void refreshLock(OpenJPAStateManager sm, int level, int timeout, Object sdata) { try { _refreshing = true; commonLock(sm, level, timeout, sdata, false); } finally { _refreshing = false; } } private void commonLock(OpenJPAStateManager sm, int level, int timeout, Object sdata, boolean postLockVersionCheck) { if (level == LOCK_NONE) return; while (sm.getOwner() != null) sm = sm.getOwner(); int oldLevel = getLockLevel(sm); if (!sm.isPersistent() || sm.isNew() || level <= oldLevel) return; try { lockInternal(sm, level, timeout, sdata, postLockVersionCheck); } catch (RuntimeException re) { // revert lock setLockLevel(sm, oldLevel); throw re; } } /** * Marks the instance's transactional status in accordance with * the settings of {@link #getVersionCheckOnReadLock} * and {@link #getVersionUpdateOnWriteLock}. Override to perform * additional locking. * * @see StoreContext#transactional */ protected void lockInternal(OpenJPAStateManager sm, int level, int timeout, Object sdata, boolean postLockVersionCheck) { optimisticLockInternal(sm, level, timeout, sdata, postLockVersionCheck); } protected void optimisticLockInternal(OpenJPAStateManager sm, int level, int timeout, Object sdata, boolean postLockVersionCheck) { // Set lock level first to prevent infinite recursion with // transactional(..) call setLockLevel(sm, level); if (level >= LockLevels.LOCK_WRITE && _versionUpdateOnWriteLock) getContext().transactional(sm.getManagedInstance(), true, null); else if (level >= LockLevels.LOCK_READ && _versionCheckOnReadLock) getContext().transactional(sm.getManagedInstance(), false, null); } /** * Whether or not we should force a version check at commit * time when a read lock is requested in order to verify read * consistency. Defaults to true. */ public void setVersionCheckOnReadLock(boolean versionCheckOnReadLock) { _versionCheckOnReadLock = versionCheckOnReadLock; } /** * Whether or not we should force a version check at commit * time when a read lock is requested in order to verify read * consistency. Defaults to true. */ public boolean getVersionCheckOnReadLock() { return _versionCheckOnReadLock; } /** * Whether or not we should force an update to the version at commit * time when a write lock is requested. Defaults to true. */ public void setVersionUpdateOnWriteLock(boolean versionUpdateOnWriteLock) { _versionUpdateOnWriteLock = versionUpdateOnWriteLock; } /** * Whether or not we should force an update to the version at commit * time when a write lock is requested. Defaults to true. */ public boolean getVersionUpdateOnWriteLock() { return _versionUpdateOnWriteLock; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDStringSeq.java0000644000000000000000000000345412133327272026551 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import org.apache.openjpa.lib.util.UUIDGenerator; import org.apache.openjpa.meta.ClassMetaData; /** * Sequence for generating 16-character UUID strings. * * @author Abe White */ public class UUIDStringSeq implements Seq { private static final UUIDStringSeq _instance = new UUIDStringSeq(); private String _last = null; /** * Return the singleton instance. */ public static UUIDStringSeq getInstance() { return _instance; } /** * Hide constructor. */ private UUIDStringSeq() { } public void setType(int type) { } public synchronized Object next(StoreContext ctx, ClassMetaData meta) { _last = UUIDGenerator.nextString(UUIDGenerator.TYPE1); return _last; } public synchronized Object current(StoreContext ctx, ClassMetaData meta) { return _last; } public void allocate(int additional, StoreContext ctx, ClassMetaData meta) { } public void close() { } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExtentImpl.java0000644000000000000000000002420612133327272026232 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import org.apache.commons.collections.Predicate; import org.apache.commons.collections.iterators.FilterIterator; import org.apache.commons.collections.iterators.IteratorChain; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.lib.rop.ResultObjectProviderIterator; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.ReferenceHashSet; import java.util.concurrent.locks.ReentrantLock; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.OpenJPAException; /** * Representation of all members of a persistent class. * * @author Abe White * @author Patrick Linskey * @nojavadoc */ public class ExtentImpl implements Extent { private static final ClassMetaData[] EMPTY_METAS = new ClassMetaData[0]; private final Broker _broker; private final Class _type; private final boolean _subs; private final FetchConfiguration _fc; private final ReentrantLock _lock; private boolean _ignore = false; // set of open iterators private ReferenceHashSet _openItrs = null; /** * Constructor. * * @param broker the owning broker * @param type the candidate class * @param subs whether subclasses are included in the extent */ ExtentImpl(Broker broker, Class type, boolean subs, FetchConfiguration fetch) { _broker = broker; _type = type; _subs = subs; if (fetch != null) _fc = fetch; else _fc = (FetchConfiguration) broker.getFetchConfiguration().clone(); _ignore = broker.getIgnoreChanges(); if (broker.getMultithreaded()) _lock = new ReentrantLock(); else _lock = null; } public FetchConfiguration getFetchConfiguration() { return _fc; } public boolean getIgnoreChanges() { return _ignore; } public void setIgnoreChanges(boolean ignoreChanges) { _broker.assertOpen(); _ignore = ignoreChanges; } public List list() { List list = new ArrayList(); Iterator itr = iterator(); try { while (itr.hasNext()) list.add(itr.next()); return list; } finally { ImplHelper.close(itr); } } public Iterator iterator() { _broker.assertNontransactionalRead(); CloseableIterator citr = null; try { // create an iterator chain; add pnew objects if transactional CloseableIteratorChain chain = new CloseableIteratorChain(); boolean trans = !_ignore && _broker.isActive(); if (trans) chain.addIterator(new FilterNewIterator()); // add database iterators for each implementing class MetaDataRepository repos = _broker.getConfiguration(). getMetaDataRepositoryInstance(); ClassMetaData meta = repos.getMetaData(_type, _broker.getClassLoader(), false); ClassMetaData[] metas; if (meta != null && (!_subs || !meta.isManagedInterface()) && (meta.isMapped() || (_subs && meta.getMappedPCSubclassMetaDatas().length > 0))) metas = new ClassMetaData[]{ meta }; else if (_subs && (meta == null || meta.isManagedInterface())) metas = repos.getImplementorMetaDatas(_type, _broker.getClassLoader(), false); else metas = EMPTY_METAS; ResultObjectProvider rop; for (int i = 0; i < metas.length; i++) { rop = _broker.getStoreManager().executeExtent(metas[i], _subs, _fc); if (rop != null) chain.addIterator(new ResultObjectProviderIterator(rop)); } // filter deleted objects if transactional if (trans) citr = new FilterDeletedIterator(chain); else citr = chain; citr.setRemoveOnClose(this); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } lock(); try { if (_openItrs == null) _openItrs = new ReferenceHashSet(ReferenceHashSet.WEAK); _openItrs.add(citr); } finally { unlock(); } return citr; } public Broker getBroker() { return _broker; } public Class getElementType() { return _type; } public boolean hasSubclasses() { return _subs; } public void closeAll() { if (_openItrs == null) return; lock(); try { CloseableIterator citr; for (Iterator itr = _openItrs.iterator(); itr.hasNext();) { citr = (CloseableIterator) itr.next(); citr.setRemoveOnClose(null); try { citr.close(); } catch (Exception e) { } } _openItrs.clear(); } catch (OpenJPAException ke) { throw ke; } catch (RuntimeException re) { throw new GeneralException(re); } finally { unlock(); } } public void lock() { if (_lock != null) _lock.lock(); } public void unlock() { if (_lock != null) _lock.unlock(); } /** * Closeable iterator. */ private static interface CloseableIterator extends Closeable, Iterator { /** * Set the extent to remove self from on close. */ public void setRemoveOnClose(ExtentImpl extent); } /** * Closeable {@link IteratorChain}. */ private static class CloseableIteratorChain extends IteratorChain implements CloseableIterator { private ExtentImpl _extent = null; private boolean _closed = false; public boolean hasNext() { return (_closed) ? false : super.hasNext(); } public Object next() { if (_closed) throw new NoSuchElementException(); return super.next(); } public void remove() { throw new UnsupportedOperationException(); } public void setRemoveOnClose(ExtentImpl extent) { _extent = extent; } public void close() throws Exception { if (_extent != null && _extent._openItrs != null) { _extent.lock(); try { _extent._openItrs.remove(this); } finally { _extent.unlock(); } } _closed = true; for (Iterator itr = getIterators().iterator(); itr.hasNext();) ((Closeable) itr.next()).close(); } } /** * {@link FilterIterator} that skips deleted objects. */ private static class FilterDeletedIterator extends FilterIterator implements CloseableIterator, Predicate { private ExtentImpl _extent = null; private boolean _closed = false; public FilterDeletedIterator(Iterator itr) { super(itr); setPredicate(this); } public boolean hasNext() { return (_closed) ? false : super.hasNext(); } public Object next() { if (_closed) throw new NoSuchElementException(); return super.next(); } public void remove() { throw new UnsupportedOperationException(); } public void setRemoveOnClose(ExtentImpl extent) { _extent = extent; } public void close() throws Exception { if (_extent != null && _extent._openItrs != null) { _extent.lock(); try { _extent._openItrs.remove(this); } finally { _extent.unlock(); } } _closed = true; ((Closeable) getIterator()).close(); } public boolean evaluate(Object o) { return !_extent._broker.isDeleted(o); } } /** * Iterator over all new objects in this extent. This iterator is always * wrapped, so it doesn't need to keep track of whether it's closed. */ private class FilterNewIterator extends FilterIterator implements Closeable, Predicate { public FilterNewIterator() { super(_broker.getTransactionalObjects().iterator()); setPredicate(this); } public void close() { } public boolean evaluate(Object o) { if (!_broker.isNew(o)) return false; Class type = o.getClass(); if (!_subs && type != _type) return false; if (_subs && !_type.isAssignableFrom(type)) return false; return true; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java0000644000000000000000000011400512133327272027346 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; import java.util.BitSet; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.RuntimeExceptionTranslator; /////////////////////////////////////////////////////////////// // NOTE: when adding a public API method, be sure to add it to // JDO and JPA facades! /////////////////////////////////////////////////////////////// /** * Delegating broker that can also perform exception translation * for use in facades. * * @since 0.4.0 * @author Abe White * @nojavadoc */ public class DelegatingBroker implements Broker { private final Broker _broker; private final DelegatingBroker _del; private final RuntimeExceptionTranslator _trans; /** * Constructor; supply delegate. */ public DelegatingBroker(Broker broker) { this(broker, null); } /** * Constructor; supply delegate and exception translator. */ public DelegatingBroker(Broker broker, RuntimeExceptionTranslator trans) { _broker = broker; if (broker instanceof DelegatingBroker) _del = (DelegatingBroker) broker; else _del = null; _trans = trans; } /** * Return the direct delegate. */ public Broker getDelegate() { return _broker; } /** * Return the native delegate. */ public Broker getInnermostDelegate() { return (_del == null) ? _broker : _del.getInnermostDelegate(); } public int hashCode() { return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingBroker) other = ((DelegatingBroker) other).getInnermostDelegate(); return getInnermostDelegate().equals(other); } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } /** * Translate the exception with the failed object. * * @param re exception raised by the delegate. * @param failed the context that failed. * * @return the translated exception. If the given input exception had not set * the failed instance, then sets the given instance as the failed context. */ protected RuntimeException translate(RuntimeException re, Object failed) { if (re instanceof OpenJPAException) { Object o = ((OpenJPAException) re).getFailedObject(); if (o == null || "null".equals(o)) { ((OpenJPAException) re).setFailedObject(Exceptions.toString(failed)); } } return (_trans == null) ? re : _trans.translate(re); } public Broker getBroker() { return this; } public OpenJPAConfiguration getConfiguration() { try { return _broker.getConfiguration(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration getFetchConfiguration() { try { return _broker.getFetchConfiguration(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration pushFetchConfiguration() { try { return _broker.pushFetchConfiguration(); } catch (RuntimeException re) { throw translate(re); } } public FetchConfiguration pushFetchConfiguration(FetchConfiguration fc) { try { return _broker.pushFetchConfiguration(fc); } catch (RuntimeException re) { throw translate(re); } } public void popFetchConfiguration() { try { _broker.popFetchConfiguration(); } catch (RuntimeException re) { throw translate(re); } } public ClassLoader getClassLoader() { try { return _broker.getClassLoader(); } catch (RuntimeException re) { throw translate(re); } } public LockManager getLockManager() { try { return _broker.getLockManager(); } catch (RuntimeException re) { throw translate(re); } } public DelegatingStoreManager getStoreManager() { try { return _broker.getStoreManager(); } catch (RuntimeException re) { throw translate(re); } } public String getConnectionUserName() { try { return _broker.getConnectionUserName(); } catch (RuntimeException re) { throw translate(re); } } public String getConnectionPassword() { try { return _broker.getConnectionPassword(); } catch (RuntimeException re) { throw translate(re); } } public Map getProperties() { try { return _broker.getProperties(); } catch (RuntimeException re) { throw translate(re); } } public Set getSupportedProperties() { try { return _broker.getSupportedProperties(); } catch (RuntimeException re) { throw translate(re); } } public Object find(Object oid, boolean validate, FindCallbacks call) { try { return _broker.find(oid, validate, call); } catch (RuntimeException re) { throw translate(re, oid); } } public Object[] findAll(Collection oids, boolean validate, FindCallbacks call) { try { return _broker.findAll(oids, validate, call); } catch (RuntimeException re) { throw translate(re, oids); } } public Object findCached(Object oid, FindCallbacks call) { try { return _broker.findCached(oid, call); } catch (RuntimeException re) { throw translate(re, oid); } } public Object find(Object oid, FetchConfiguration fetch, BitSet exclude, Object edata, int flags) { try { return _broker.find(oid, fetch, exclude, edata, flags); } catch (RuntimeException re) { throw translate(re, oid); } } public Object[] findAll(Collection oids, FetchConfiguration fetch, BitSet exclude, Object edata, int flags) { try { return _broker.findAll(oids, fetch, exclude, edata, flags); } catch (RuntimeException re) { throw translate(re, oids); } } public Iterator extentIterator(Class cls, boolean subs, FetchConfiguration fetch, boolean ignoreChanges) { try { return _broker.extentIterator(cls, subs, fetch, ignoreChanges); } catch (RuntimeException re) { throw translate(re); } } public void retrieve(Object obj, boolean fgOnly, OpCallbacks call) { try { _broker.retrieve(obj, fgOnly, call); } catch (RuntimeException re) { throw translate(re); } } public void retrieveAll(Collection objs, boolean fgOnly, OpCallbacks call) { try { _broker.retrieveAll(objs, fgOnly, call); } catch (RuntimeException re) { throw translate(re); } } public OpenJPAStateManager embed(Object obj, Object id, OpenJPAStateManager owner, ValueMetaData ownerMeta) { try { return _broker.embed(obj, id, owner, ownerMeta); } catch (RuntimeException re) { throw translate(re); } } public Class getObjectIdType(Class cls) { try { return _broker.getObjectIdType(cls); } catch (RuntimeException re) { throw translate(re); } } public Object newObjectId(Class cls, Object val) { try { return _broker.newObjectId(cls, val); } catch (RuntimeException re) { throw translate(re); } } public Collection getManagedObjects() { try { return _broker.getManagedObjects(); } catch (RuntimeException re) { throw translate(re); } } public Collection getTransactionalObjects() { try { return _broker.getTransactionalObjects(); } catch (RuntimeException re) { throw translate(re); } } public Collection getPendingTransactionalObjects() { try { return _broker.getPendingTransactionalObjects(); } catch (RuntimeException re) { throw translate(re); } } public Collection getDirtyObjects() { try { return _broker.getDirtyObjects(); } catch (RuntimeException re) { throw translate(re); } } public boolean getOrderDirtyObjects() { try { return _broker.getOrderDirtyObjects(); } catch (RuntimeException re) { throw translate(re); } } public void setOrderDirtyObjects(boolean order) { try { _broker.setOrderDirtyObjects(order); } catch (RuntimeException re) { throw translate(re); } } public Collection getPersistedTypes() { try { return _broker.getPersistedTypes(); } catch (RuntimeException re) { throw translate(re); } } public Collection getUpdatedTypes() { try { return _broker.getUpdatedTypes(); } catch (RuntimeException re) { throw translate(re); } } public Collection getDeletedTypes() { try { return _broker.getDeletedTypes(); } catch (RuntimeException re) { throw translate(re); } } public OpenJPAStateManager getStateManager(Object obj) { try { return _broker.getStateManager(obj); } catch (RuntimeException re) { throw translate(re); } } public int getLockLevel(Object obj) { try { return _broker.getLockLevel(obj); } catch (RuntimeException re) { throw translate(re); } } public Object getVersion(Object obj) { try { return _broker.getVersion(obj); } catch (RuntimeException re) { throw translate(re); } } public boolean isDirty(Object obj) { try { return _broker.isDirty(obj); } catch (RuntimeException re) { throw translate(re); } } public boolean isTransactional(Object obj) { try { return _broker.isTransactional(obj); } catch (RuntimeException re) { throw translate(re); } } public boolean isPersistent(Object obj) { try { return _broker.isPersistent(obj); } catch (RuntimeException re) { throw translate(re); } } public boolean isNew(Object obj) { try { return _broker.isNew(obj); } catch (RuntimeException re) { throw translate(re); } } public boolean isDeleted(Object obj) { try { return _broker.isDeleted(obj); } catch (RuntimeException re) { throw translate(re); } } public Object getObjectId(Object obj) { try { return _broker.getObjectId(obj); } catch (RuntimeException re) { throw translate(re); } } public boolean isManaged() { try { return _broker.isManaged(); } catch (RuntimeException re) { throw translate(re); } } public boolean isActive() { try { return _broker.isActive(); } catch (RuntimeException re) { throw translate(re); } } public boolean isStoreActive() { try { return _broker.isStoreActive(); } catch (RuntimeException re) { throw translate(re); } } public boolean hasConnection() { try { return _broker.hasConnection(); } catch (RuntimeException re) { throw translate(re); } } public Object getConnection() { try { return _broker.getConnection(); } catch (RuntimeException re) { throw translate(re); } } public void lock() { try { _broker.lock(); } catch (RuntimeException re) { throw translate(re); } } public void unlock() { try { _broker.unlock(); } catch (RuntimeException re) { throw translate(re); } } public boolean beginOperation(boolean read) { try { return _broker.beginOperation(read); } catch (RuntimeException re) { throw translate(re); } } public boolean endOperation() { try { return _broker.endOperation(); } catch (RuntimeException re) { throw translate(re); } } public void setImplicitBehavior(OpCallbacks call, RuntimeExceptionTranslator ex) { try { _broker.setImplicitBehavior(call, ex); } catch (RuntimeException re) { throw translate(re); } } public BrokerFactory getBrokerFactory() { try { return _broker.getBrokerFactory(); } catch (RuntimeException re) { throw translate(re); } } public int getConnectionRetainMode() { try { return _broker.getConnectionRetainMode(); } catch (RuntimeException re) { throw translate(re); } } public ManagedRuntime getManagedRuntime() { try { return _broker.getManagedRuntime(); } catch (RuntimeException re) { throw translate(re); } } public InverseManager getInverseManager() { try { return _broker.getInverseManager(); } catch (RuntimeException re) { throw translate(re); } } public boolean getMultithreaded() { try { return _broker.getMultithreaded(); } catch (RuntimeException re) { throw translate(re); } } public void setMultithreaded(boolean multi) { try { _broker.setMultithreaded(multi); } catch (RuntimeException re) { throw translate(re); } } public boolean getIgnoreChanges() { try { return _broker.getIgnoreChanges(); } catch (RuntimeException re) { throw translate(re); } } public void setIgnoreChanges(boolean ignore) { try { _broker.setIgnoreChanges(ignore); } catch (RuntimeException re) { throw translate(re); } } public boolean getNontransactionalRead() { try { return _broker.getNontransactionalRead(); } catch (RuntimeException re) { throw translate(re); } } public void setNontransactionalRead(boolean read) { try { _broker.setNontransactionalRead(read); } catch (RuntimeException re) { throw translate(re); } } public boolean getNontransactionalWrite() { try { return _broker.getNontransactionalWrite(); } catch (RuntimeException re) { throw translate(re); } } public void setNontransactionalWrite(boolean write) { try { _broker.setNontransactionalWrite(write); } catch (RuntimeException re) { throw translate(re); } } public int getRestoreState() { try { return _broker.getRestoreState(); } catch (RuntimeException re) { throw translate(re); } } public void setRestoreState(int restore) { try { _broker.setRestoreState(restore); } catch (RuntimeException re) { throw translate(re); } } public boolean getOptimistic() { try { return _broker.getOptimistic(); } catch (RuntimeException re) { throw translate(re); } } public void setOptimistic(boolean opt) { try { _broker.setOptimistic(opt); } catch (RuntimeException re) { throw translate(re); } } public boolean getRetainState() { try { return _broker.getRetainState(); } catch (RuntimeException re) { throw translate(re); } } public void setRetainState(boolean retain) { try { _broker.setRetainState(retain); } catch (RuntimeException re) { throw translate(re); } } public int getAutoClear() { try { return _broker.getAutoClear(); } catch (RuntimeException re) { throw translate(re); } } public void setAutoClear(int clear) { try { _broker.setAutoClear(clear); } catch (RuntimeException re) { throw translate(re); } } public int getAutoDetach() { try { return _broker.getAutoDetach(); } catch (RuntimeException re) { throw translate(re); } } public void setAutoDetach(int flags) { try { _broker.setAutoDetach(flags); } catch (RuntimeException re) { throw translate(re); } } public void setAutoDetach(int flag, boolean on) { try { _broker.setAutoDetach(flag, on); } catch (RuntimeException re) { throw translate(re); } } public int getDetachState() { try { return _broker.getDetachState(); } catch (RuntimeException re) { throw translate(re); } } public void setDetachState(int mode) { try { _broker.setDetachState(mode); } catch (RuntimeException re) { throw translate(re); } } public boolean isDetachedNew() { try { return _broker.isDetachedNew(); } catch (RuntimeException re) { throw translate(re); } } public void setDetachedNew(boolean isNew) { try { _broker.setDetachedNew(isNew); } catch (RuntimeException re) { throw translate(re); } } public boolean getSyncWithManagedTransactions() { try { return _broker.getSyncWithManagedTransactions(); } catch (RuntimeException re) { throw translate(re); } } public void setSyncWithManagedTransactions(boolean sync) { try { _broker.setSyncWithManagedTransactions(sync); } catch (RuntimeException re) { throw translate(re); } } public boolean getEvictFromDataCache() { try { return _broker.getEvictFromDataCache(); } catch (RuntimeException re) { throw translate(re); } } public void setEvictFromDataCache(boolean evict) { try { _broker.setEvictFromDataCache(evict); } catch (RuntimeException re) { throw translate(re); } } public boolean getPopulateDataCache() { try { return _broker.getPopulateDataCache(); } catch (RuntimeException re) { throw translate(re); } } public void setPopulateDataCache(boolean cache) { try { _broker.setPopulateDataCache(cache); } catch (RuntimeException re) { throw translate(re); } } public boolean isTrackChangesByType() { try { return _broker.isTrackChangesByType(); } catch (RuntimeException re) { throw translate(re); } } public void setTrackChangesByType(boolean largeTransaction) { try { _broker.setTrackChangesByType(largeTransaction); } catch (RuntimeException re) { throw translate(re); } } public Object putUserObject(Object key, Object val) { try { return _broker.putUserObject(key, val); } catch (RuntimeException re) { throw translate(re); } } public Object getUserObject(Object key) { try { return _broker.getUserObject(key); } catch (RuntimeException re) { throw translate(re); } } public void addTransactionListener(Object listener) { try { _broker.addTransactionListener(listener); } catch (RuntimeException re) { throw translate(re); } } public void removeTransactionListener(Object listener) { try { _broker.removeTransactionListener(listener); } catch (RuntimeException re) { throw translate(re); } } public Collection getTransactionListeners() { try { return _broker.getTransactionListeners(); } catch (RuntimeException re) { throw translate(re); } } public int getTransactionListenerCallbackMode() { try { return _broker.getTransactionListenerCallbackMode(); } catch (RuntimeException re) { throw translate(re); } } public void setTransactionListenerCallbackMode(int mode) { try { _broker.setTransactionListenerCallbackMode(mode); } catch (RuntimeException re) { throw translate(re); } } public void addLifecycleListener(Object listener, Class[] classes) { try { _broker.addLifecycleListener(listener, classes); } catch (RuntimeException re) { throw translate(re); } } public void removeLifecycleListener(Object listener) { try { _broker.removeLifecycleListener(listener); } catch (RuntimeException re) { throw translate(re); } } public int getLifecycleListenerCallbackMode() { try { return _broker.getLifecycleListenerCallbackMode(); } catch (RuntimeException re) { throw translate(re); } } public void setLifecycleListenerCallbackMode(int mode) { try { _broker.setLifecycleListenerCallbackMode(mode); } catch (RuntimeException re) { throw translate(re); } } public LifecycleEventManager getLifecycleEventManager() { try { return _broker.getLifecycleEventManager(); } catch (RuntimeException re) { throw translate(re); } } public void begin() { try { _broker.begin(); } catch (RuntimeException re) { throw translate(re); } } public void commit() { try { _broker.commit(); } catch (RuntimeException re) { throw translate(re); } } public void rollback() { try { _broker.rollback(); } catch (RuntimeException re) { throw translate(re); } } public boolean syncWithManagedTransaction() { try { return _broker.syncWithManagedTransaction(); } catch (RuntimeException re) { throw translate(re); } } public void commitAndResume() { try { _broker.commitAndResume(); } catch (RuntimeException re) { throw translate(re); } } public void rollbackAndResume() { try { _broker.rollbackAndResume(); } catch (RuntimeException re) { throw translate(re); } } public void setRollbackOnly() { try { _broker.setRollbackOnly(); } catch (RuntimeException re) { throw translate(re); } } public void setRollbackOnly(Throwable cause) { try { _broker.setRollbackOnly(cause); } catch (RuntimeException re) { throw translate(re); } } public Throwable getRollbackCause() { try { return _broker.getRollbackCause(); } catch (RuntimeException re) { throw translate(re); } } public boolean getRollbackOnly() { try { return _broker.getRollbackOnly(); } catch (RuntimeException re) { throw translate(re); } } public void setSavepoint(String name) { try { _broker.setSavepoint(name); } catch (RuntimeException re) { throw translate(re); } } public void rollbackToSavepoint() { try { _broker.rollbackToSavepoint(); } catch (RuntimeException re) { throw translate(re); } } public void rollbackToSavepoint(String name) { try { _broker.rollbackToSavepoint(name); } catch (RuntimeException re) { throw translate(re); } } public void releaseSavepoint() { try { _broker.releaseSavepoint(); } catch (RuntimeException re) { throw translate(re); } } public void releaseSavepoint(String name) { try { _broker.releaseSavepoint(name); } catch (RuntimeException re) { throw translate(re); } } public void flush() { try { _broker.flush(); } catch (RuntimeException re) { throw translate(re); } } public void preFlush() { try { _broker.preFlush(); } catch (RuntimeException re) { throw translate(re); } } public void validateChanges() { try { _broker.validateChanges(); } catch (RuntimeException re) { throw translate(re); } } public void beginStore() { try { _broker.beginStore(); } catch (RuntimeException re) { throw translate(re); } } public void persist(Object obj, OpCallbacks call) { try { _broker.persist(obj, call); } catch (RuntimeException re) { throw translate(re); } } public void persistAll(Collection objs, OpCallbacks call) { try { _broker.persistAll(objs, call); } catch (RuntimeException re) { throw translate(re); } } public OpenJPAStateManager persist(Object obj, Object id, OpCallbacks call) { try { return _broker.persist(obj, id, call); } catch (RuntimeException re) { throw translate(re); } } public void delete(Object obj, OpCallbacks call) { try { _broker.delete(obj, call); } catch (RuntimeException re) { throw translate(re, obj); } } public void deleteAll(Collection objs, OpCallbacks call) { try { _broker.deleteAll(objs, call); } catch (RuntimeException re) { throw translate(re, objs); } } public void release(Object obj, OpCallbacks call) { try { _broker.release(obj, call); } catch (RuntimeException re) { throw translate(re, obj); } } public void releaseAll(Collection objs, OpCallbacks call) { try { _broker.releaseAll(objs, call); } catch (RuntimeException re) { throw translate(re, objs); } } public void refresh(Object obj, OpCallbacks call) { try { _broker.refresh(obj, call); } catch (RuntimeException re) { throw translate(re, obj); } } public void refreshAll(Collection objs, OpCallbacks call) { try { _broker.refreshAll(objs, call); } catch (RuntimeException re) { throw translate(re, objs); } } public void evict(Object obj, OpCallbacks call) { try { _broker.evict(obj, call); } catch (RuntimeException re) { throw translate(re, obj); } } public void evictAll(Collection objs, OpCallbacks call) { try { _broker.evictAll(objs, call); } catch (RuntimeException re) { throw translate(re, objs); } } public void evictAll(OpCallbacks call) { try { _broker.evictAll(call); } catch (RuntimeException re) { throw translate(re); } } public void evictAll(Extent extent, OpCallbacks call) { try { _broker.evictAll(extent, call); } catch (RuntimeException re) { throw translate(re, extent.getElementType()); } } public Object detach(Object obj, OpCallbacks call) { try { return _broker.detach(obj, call); } catch (RuntimeException re) { throw translate(re, obj); } } public Object[] detachAll(Collection objs, OpCallbacks call) { try { return _broker.detachAll(objs, call); } catch (RuntimeException re) { throw translate(re, objs); } } public void detachAll(OpCallbacks call) { try { _broker.detachAll(call); } catch (RuntimeException re) { throw translate(re); } } public void detachAll(OpCallbacks call, boolean flush) { try { _broker.detachAll(call, flush); } catch (RuntimeException re) { throw translate(re); } } public Object attach(Object obj, boolean copyNew, OpCallbacks call) { try { return _broker.attach(obj, copyNew, call); } catch (RuntimeException re) { throw translate(re, obj); } } public Object[] attachAll(Collection objs, boolean copyNew, OpCallbacks call) { try { return _broker.attachAll(objs, copyNew, call); } catch (RuntimeException re) { throw translate(re, objs); } } public void transactional(Object pc, boolean updateVersion, OpCallbacks call) { try { _broker.transactional(pc, updateVersion, call); } catch (RuntimeException re) { throw translate(re, pc); } } public void transactionalAll(Collection objs, boolean updateVersion, OpCallbacks call) { try { _broker.transactionalAll(objs, updateVersion, call); } catch (RuntimeException re) { throw translate(re, objs); } } public void nontransactional(Object pc, OpCallbacks call) { try { _broker.nontransactional(pc, call); } catch (RuntimeException re) { throw translate(re, pc); } } public void nontransactionalAll(Collection objs, OpCallbacks call) { try { _broker.nontransactionalAll(objs, call); } catch (RuntimeException re) { throw translate(re, objs); } } public Extent newExtent(Class cls, boolean subs) { try { return _broker.newExtent(cls, subs); } catch (RuntimeException re) { throw translate(re, cls); } } public Query newQuery(String language, Class cls, Object query) { try { return _broker.newQuery(language, cls, query); } catch (RuntimeException re) { throw translate(re, query); } } public Query newQuery(String language, Object query) { try { return _broker.newQuery(language, query); } catch (RuntimeException re) { throw translate(re, query); } } public Seq getIdentitySequence(ClassMetaData meta) { try { return _broker.getIdentitySequence(meta); } catch (RuntimeException re) { throw translate(re); } } public Seq getValueSequence(FieldMetaData fmd) { try { return _broker.getValueSequence(fmd); } catch (RuntimeException re) { throw translate(re); } } public void lock(Object obj, int level, int timeout, OpCallbacks call) { try { _broker.lock(obj, level, timeout, call); } catch (RuntimeException re) { throw translate(re, obj); } } public void lock(Object obj, OpCallbacks call) { try { _broker.lock(obj, call); } catch (RuntimeException re) { throw translate(re, obj); } } public void lockAll(Collection objs, int level, int timeout, OpCallbacks call) { try { _broker.lockAll(objs, level, timeout, call); } catch (RuntimeException re) { throw translate(re, objs); } } public void lockAll(Collection objs, OpCallbacks call) { try { _broker.lockAll(objs, call); } catch (RuntimeException re) { throw translate(re, objs); } } public boolean cancelAll() { try { return _broker.cancelAll(); } catch (RuntimeException re) { throw translate(re); } } public void dirtyType(Class cls) { try { _broker.dirtyType(cls); } catch (RuntimeException re) { throw translate(re); } } public void close() { try { _broker.close(); } catch (RuntimeException re) { throw translate(re); } } public boolean isClosed() { try { return _broker.isClosed(); } catch (RuntimeException re) { throw translate(re); } } public boolean isCloseInvoked() { try { return _broker.isCloseInvoked(); } catch (RuntimeException re) { throw translate(re); } } public void assertOpen() { try { _broker.assertOpen(); } catch (RuntimeException re) { throw translate(re); } } public void assertActiveTransaction() { try { _broker.assertActiveTransaction(); } catch (RuntimeException re) { throw translate(re); } } public void assertNontransactionalRead() { try { _broker.assertNontransactionalRead(); } catch (RuntimeException re) { throw translate(re); } } public void assertWriteOperation() { try { _broker.assertWriteOperation(); } catch (RuntimeException re) { throw translate(re); } } /////////////////////////////////////////////// // Implementation of Synchronization interface /////////////////////////////////////////////// public void beforeCompletion() { try { _broker.beforeCompletion(); } catch (RuntimeException re) { throw translate(re); } } public void afterCompletion(int status) { try { _broker.afterCompletion(status); } catch (RuntimeException re) { throw translate(re); } } public Object newInstance(Class cls) { try { return _broker.newInstance(cls); } catch (RuntimeException re) { throw translate(re); } } public boolean isDetached(Object obj) { try { return _broker.isDetached(obj); } catch (RuntimeException re) { throw translate(re); } } public boolean getCachePreparedQuery() { return _broker.getCachePreparedQuery(); } public void setCachePreparedQuery(boolean flag) { _broker.setCachePreparedQuery(flag); } public String getConnectionFactoryName() { return _broker.getConnectionFactoryName(); } public void setConnectionFactoryName(String connectionFactoryName) { _broker.setConnectionFactoryName(connectionFactoryName); } public String getConnectionFactory2Name() { return _broker.getConnectionFactory2Name(); } public void setConnectionFactory2Name(String connectionFactory2Name) { _broker.setConnectionFactory2Name(connectionFactory2Name); } public Object getConnectionFactory() { return _broker.getConnectionFactory(); } public Object getConnectionFactory2() { return _broker.getConnectionFactory2(); } public boolean isCached(List oid) { return _broker.isCached(oid); } public boolean getAllowReferenceToSiblingContext() { return _broker.getAllowReferenceToSiblingContext(); } public void setAllowReferenceToSiblingContext(boolean allow) { _broker.setAllowReferenceToSiblingContext(allow); } public boolean getPostLoadOnMerge() { return _broker.getPostLoadOnMerge(); } public void setPostLoadOnMerge(boolean allow) { _broker.setPostLoadOnMerge(allow); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/MixedLockLevels.java0000644000000000000000000000326712133327272027177 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.kernel; /** * Defines lock levels used for MixedLockManager. * * @author Albert Lee * @since 2.0.0 */ public interface MixedLockLevels extends LockLevels { /** * Generic optimistic read lock level. Value of 15. * */ public static final int LOCK_OPTIMISTIC = LOCK_READ + 5; /** * Generic optimistic write lock level. Value of 25. */ public static final int LOCK_OPTIMISTIC_FORCE_INCREMENT = LockLevels.LOCK_WRITE + 5; /** * Generic pessimistic read lock level. Value of 30. */ public static final int LOCK_PESSIMISTIC_READ = 30; /** * Generic pessimistic write lock level. Value of 40. */ public static final int LOCK_PESSIMISTIC_WRITE = 40; /** * Generic pessimistic force increment level. Value of 50. */ public static final int LOCK_PESSIMISTIC_FORCE_INCREMENT = 50; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/0000755000000000000000000000000012133327272022403 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/JNDIManagedRuntime.java0000644000000000000000000000463212133327272026620 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import javax.naming.Context; import javax.naming.InitialContext; import javax.transaction.TransactionManager; /** * Implementation of the {@link ManagedRuntime} interface that uses JNDI to * find the TransactionManager. * * @author Abe White */ public class JNDIManagedRuntime extends AbstractManagedRuntime implements ManagedRuntime { private String _tmLoc = "java:/TransactionManager"; private TransactionManager _tm = null; /** * Return the location of the {@link TransactionManager} in JNDI. */ public String getTransactionManagerName() { return _tmLoc; } /** * Set the location of the {@link TransactionManager} in JNDI. */ public void setTransactionManagerName(String name) { _tmLoc = name; _tm = null; // reset the cached TM } /** * Return the cached TransactionManager instance. */ public TransactionManager getTransactionManager() throws Exception { if (_tm == null) { Context ctx = new InitialContext(); try { _tm = (TransactionManager) ctx.lookup(_tmLoc); } finally { ctx.close(); } } return _tm; } public void setRollbackOnly(Throwable cause) throws Exception { // there is no generic support for setting the rollback cause getTransactionManager().getTransaction().setRollbackOnly(); } public Throwable getRollbackCause() throws Exception { // there is no generic support for setting the rollback cause return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/SunOneManagedRuntime.java0000644000000000000000000000422412133327272027300 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import java.lang.reflect.Method; import javax.transaction.TransactionManager; /** * {@link ManagedRuntime} implementation for SunONE. * * @author Marc Prud'hommeaux */ public class SunOneManagedRuntime extends AbstractManagedRuntime implements ManagedRuntime { private Method _switchMeth; private Method _txManagerMeth; public SunOneManagedRuntime() throws ClassNotFoundException, NoSuchMethodException { Class swtch = Class.forName("com.sun.enterprise.Switch"); _switchMeth = swtch.getMethod("getSwitch", (Class[]) null); _txManagerMeth = swtch.getMethod("getTransactionManager", (Class[]) null); } public TransactionManager getTransactionManager() throws Exception { // return Switch.getSwitch ().getTransactionManager (); Object sw = _switchMeth.invoke(null, (Object[]) null); return (TransactionManager) _txManagerMeth.invoke(sw, (Object[]) null); } public void setRollbackOnly(Throwable cause) throws Exception { // there is no generic support for setting the rollback cause getTransactionManager().getTransaction().setRollbackOnly(); } public Throwable getRollbackCause() throws Exception { // there is no generic support for setting the rollback cause return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/package.html0000644000000000000000000000166312133327272024672 0ustar

    OpenJPA Enterprise Extensions

    This package provides enterprise extensions to the OpenJPA runtime.

    openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/AutomaticManagedRuntime.java0000644000000000000000000002405512133327272030023 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import java.util.LinkedList; import java.util.List; import javax.transaction.NotSupportedException; import javax.transaction.SystemException; import javax.transaction.TransactionManager; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InvalidStateException; /** * Implementation of the {@link ManagedRuntime} interface that searches * through a set of known JNDI locations and method invocations to locate the * appropriate mechanism for obtaining a TransactionManager. * Built in support is provided for the following Application Servers: *
      *
    • Bluestone
    • *
    • GlassFish
    • *
    • HP Application Server
    • *
    • JBoss
    • *
    • JRun
    • *
    • OpenEJB
    • *
    • Oracle Application Server
    • *
    • Orion
    • *
    • SunONE
    • *
    • Weblogic
    • *
    • Websphere
    • *
    * * @author Marc Prud'hommeaux */ public class AutomaticManagedRuntime extends AbstractManagedRuntime implements ManagedRuntime, Configurable { private static final String [] JNDI_LOCS = new String []{ "javax.transaction.TransactionManager", // weblogic "java:/TransactionManager", // jboss, jrun, Geronimo "java:/DefaultDomain/TransactionManager", // jrun too "java:comp/pm/TransactionManager", // orion & oracle "java:comp/TransactionManager", // generic "java:appserver/TransactionManager", // GlassFish "java:pm/TransactionManager", // borland "aries:services/javax.transaction.TransactionManager", // Apache Aries }; private static final String [] METHODS = new String[]{ "com.arjuna.jta.JTA_TransactionManager.transactionManager", // hp "com.bluestone.jta.SaTransactionManagerFactory.SaGetTransactionManager", "org.openejb.OpenEJB.getTransactionManager", "com.sun.jts.jta.TransactionManagerImpl.getTransactionManagerImpl", "com.inprise.visitransact.jta.TransactionManagerImpl." + "getTransactionManagerImpl", // borland }; private static final ManagedRuntime REGISTRY; private static final WLSManagedRuntime WLS; private static final SunOneManagedRuntime SUNONE; private static final WASManagedRuntime WAS; private static final WASRegistryManagedRuntime WAS_REG; private static Localizer _loc = Localizer.forPackage (AutomaticManagedRuntime.class); static { ManagedRuntime mr = null; mr = null; try { mr = (ManagedRuntime) Class. forName("org.apache.openjpa.ee.RegistryManagedRuntime"). newInstance(); } catch (Throwable t) { // might be JTA version lower than 1.1, which doesn't have // TransactionSynchronizationRegistry } REGISTRY = mr; mr = null; try { mr = new WLSManagedRuntime(); } catch (Throwable t) { } WLS = (WLSManagedRuntime) mr; mr = null; try { mr = new SunOneManagedRuntime(); } catch (Throwable t) { } SUNONE = (SunOneManagedRuntime) mr; mr = null; try { mr = new WASManagedRuntime(); } catch (Throwable t) { } WAS = (WASManagedRuntime) mr; mr = null; try { // In a WebSphere environment the thread's current classloader might // not have access to the WebSphere APIs. However the "runtime" // classloader will have access to them. // Should not need a doPriv getting this class' classloader ClassLoader cl = AutomaticManagedRuntime.class.getClassLoader(); Class mrClass = (Class) J2DoPrivHelper .getForNameAction( WASRegistryManagedRuntime.class.getName(), true, cl).run(); mr = J2DoPrivHelper.newInstanceAction(mrClass).run(); } catch (Throwable t) { // safe to ignore } WAS_REG = (WASRegistryManagedRuntime) mr; } private Configuration _conf = null; private ManagedRuntime _runtime = null; public TransactionManager getTransactionManager() throws Exception { if (_runtime != null) return _runtime.getTransactionManager(); List errors = new LinkedList(); TransactionManager tm = null; // Try the registry extensions first so that any applicable vendor // specific extensions are used. if (WAS_REG != null) { try { tm = WAS_REG.getTransactionManager(); } catch (Throwable t) { errors.add(t); } if (tm != null) { _runtime = WAS_REG; return tm; } } // Then try the registry, which is the official way to obtain // transaction synchronication in JTA 1.1 if (REGISTRY != null) { try { tm = REGISTRY.getTransactionManager(); } catch (Throwable t) { errors.add(t); } if (tm != null) { _runtime = REGISTRY; return tm; } } if (WLS != null) { try { tm = WLS.getTransactionManager(); } catch (Throwable t) { errors.add(t); } if (tm != null) { _runtime = WLS; return tm; } } if (WAS != null) { try { WAS.setConfiguration(_conf); WAS.startConfiguration(); WAS.endConfiguration(); tm = WAS.getTransactionManager(); } catch (Throwable t) { errors.add(t); } if (tm != null) { _runtime = WAS; return tm; } } // try to find a jndi runtime JNDIManagedRuntime jmr = new JNDIManagedRuntime(); for (int i = 0; i < JNDI_LOCS.length; i++) { jmr.setTransactionManagerName(JNDI_LOCS[i]); try { tm = jmr.getTransactionManager(); } catch (Throwable t) { errors.add(t); } if (tm != null) { _runtime = jmr; return tm; } } // look for a method runtime InvocationManagedRuntime imr = new InvocationManagedRuntime(); for (int i = 0; i < METHODS.length; i++) { imr.setConfiguration(_conf); imr.setTransactionManagerMethod(METHODS[i]); try { tm = imr.getTransactionManager(); } catch (Throwable t) { errors.add(t); } if (tm != null) { _runtime = imr; return tm; } } if (SUNONE != null) { try { tm = SUNONE.getTransactionManager(); } catch (Throwable t) { errors.add(t); } if (tm != null) { _runtime = SUNONE; return tm; } } Throwable[] t = (Throwable []) errors.toArray( new Throwable [errors.size()]); throw new InvalidStateException(_loc.get("tm-not-found")). setFatal(true).setNestedThrowables(t); } public void setConfiguration(Configuration conf) { _conf = conf; } public void startConfiguration() { } public void endConfiguration() { } public void setRollbackOnly(Throwable cause) throws Exception { // check to see if the runtime is cached if (_runtime == null) getTransactionManager(); if (_runtime != null) _runtime.setRollbackOnly(cause); } public Throwable getRollbackCause() throws Exception { // check to see if the runtime is cached if (_runtime == null) getTransactionManager(); if (_runtime != null) return _runtime.getRollbackCause(); return null; } public Object getTransactionKey() throws Exception, SystemException { if(_runtime == null) getTransactionManager(); if(_runtime != null ) return _runtime.getTransactionKey(); return null; } /** * Delegate nonTransactional work to the appropriate managed runtime. If no * managed runtime is found then delegate {@link AbstractManagedRuntime}. */ public void doNonTransactionalWork(Runnable runnable) throws NotSupportedException { // Obtain a transaction manager to initialize the runtime. try { getTransactionManager(); } catch (Exception e) { NotSupportedException nse = new NotSupportedException(_loc .get("tm-unavailable", _runtime).getMessage()); nse.initCause(e); throw nse; } _runtime.doNonTransactionalWork(runnable); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/WASRegistryManagedRuntime.java0000644000000000000000000000510712133327272030255 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import com.ibm.wsspi.uow.UOWAction; import com.ibm.wsspi.uow.UOWActionException; import com.ibm.wsspi.uow.UOWException; import com.ibm.wsspi.uow.UOWManager; import com.ibm.wsspi.uow.UOWManagerFactory; /** * WASRegistryManagedRuntime provides WebSphere specific extensions to * {@link RegistryManagedRuntime}. Currently these extensions consist of using * the WebSphere UOWManager interface to submit non transactional work. */ public class WASRegistryManagedRuntime extends RegistryManagedRuntime { /** *

    * RegistryManagedRuntime cannot suspend transactions, but WebSphere * provides an interface to submit work outside of the current tran. *

    */ public void doNonTransactionalWork(Runnable runnable) throws RuntimeException, UnsupportedOperationException { try { UOWManagerFactory.getUOWManager().runUnderUOW( UOWManager.UOW_TYPE_LOCAL_TRANSACTION, false, new DelegatingUOWAction(runnable)); } catch(UOWActionException e ) { RuntimeException re = new RuntimeException(e.getMessage()); re.initCause(e); throw re; } catch(UOWException e ) { RuntimeException re = new RuntimeException(e.getMessage()); re.initCause(e); throw re; } } /** * Delegate for the WebSphere proprietary UOWAction interface. Enables a * {@link Runnable} to be passed in to the WebSphere UOWManager. */ class DelegatingUOWAction implements UOWAction { Runnable _del; public DelegatingUOWAction(Runnable delegate) { _del = delegate; } public void run() throws Exception { _del.run(); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/AbstractManagedRuntime.java0000644000000000000000000000726712133327272027646 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.openjpa.ee; import javax.transaction.InvalidTransactionException; import javax.transaction.NotSupportedException; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.GeneralException; /* * AbstractManagedRuntime.java * * Created on August 2, 2007, 2:38 PM * */ public abstract class AbstractManagedRuntime implements ManagedRuntime { private static Localizer _loc = Localizer.forPackage(AbstractManagedRuntime.class); /** * Returns a transaction key that can be used to associate transactions * and Brokers. * The default implementation returns the Transaction associated * with the current thread's transaction. * @return the transaction key */ public Object getTransactionKey() throws Exception, SystemException { return getTransactionManager().getTransaction(); } /** *

    * Do a unit of work which will execute outside of the current managed * transaction. The default implementation suspends the transaction prior to * execution, and resumes the transaction afterwards. *

    * * @param runnable * The runnable wrapper for the work that will be done. The * runnable object should be fully initialized with any state * needed to execute. * * @throws NotSupportedException * if the current transaction can not be obtained, or an error * occurs when suspending or resuming the transaction. */ public void doNonTransactionalWork(Runnable runnable) throws NotSupportedException { TransactionManager tm = null; Transaction transaction = null; try { tm = getTransactionManager(); } catch(Exception e) { NotSupportedException nse = new NotSupportedException(e.getMessage()); nse.initCause(e); throw nse; } try { transaction = tm.suspend(); } catch (Exception e) { NotSupportedException nse = new NotSupportedException( _loc.get("exc-suspend-tran", e.getClass()).getMessage()); nse.initCause(e); throw nse; } runnable.run(); try { tm.resume(transaction); } catch (Exception e) { try { transaction.setRollbackOnly(); } catch(SystemException se2) { throw new GeneralException(se2); } NotSupportedException nse = new NotSupportedException( _loc.get("exc-resume-tran", e.getClass()).getMessage()); nse.initCause(e); throw nse; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/ManagedRuntime.java0000644000000000000000000000620712133327272026153 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import javax.transaction.NotSupportedException; import javax.transaction.SystemException; import javax.transaction.TransactionManager; /** * This interface must be implemented by concrete plugins to application * servers in order to integrate the OpenJPA runtime in a managed environment. * * @author Abe White */ public interface ManagedRuntime { /** * Return the TransactionManager for the managed runtime. This * manager is used to register synchronization listeners, to * map transactional PersistenceManagers to the current transaction, * and possibly to enlist XA resources. */ public TransactionManager getTransactionManager() throws Exception; /** * Sets the rollback only flag on the current transaction. If the * TransactionManager is capable of tracking the cause of the * rollback-only flag, it will also pass along cause information. * * @param cause the Throwable that caused the transaction to be * marked for rollback, or null of none is known */ public void setRollbackOnly(Throwable cause) throws Exception; /** * Returns the Throwable that caused the current transaction to be * marked for rollback, provided that any exists. * * @return the Throwable cause, or null if none */ public Throwable getRollbackCause() throws Exception; /** * Returns a transaction key that can be used to associate transactions * and Brokers. * @return the transaction key */ public Object getTransactionKey() throws Exception, SystemException; /** *

    * Do a unit of work which will execute outside of the current managed * transaction. *

    *

    * If the runnable object encounters an exception it should be wrapped in a * RuntimeException and thrown back to the caller *

    * * @param runnable * The runnable wrapper for the work that will be done. The * runnable object should be fully initialized with any state * needed to execute. * * @throws NotSupportedException * if the transaction can not be suspended. */ public void doNonTransactionalWork(Runnable runnable) throws NotSupportedException; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/InvocationManagedRuntime.java0000644000000000000000000000626212133327272030206 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import java.lang.reflect.Method; import javax.transaction.TransactionManager; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; /** * Implementation of the {@link ManagedRuntime} interface that uses * a static method call to find the TransactionManager. * For example, to configure it to use IBM Websphere's TransactionManager, * use the method:
    * com.ibm.ejs.jts.jta.JTSXA.getTransactionManager * * @author Marc Prud'hommeaux */ public class InvocationManagedRuntime extends AbstractManagedRuntime implements ManagedRuntime, Configurable { private String _methodName = null; private String _clazz = null; private transient Method _method = null; private OpenJPAConfiguration _conf = null; /** * Return the method to invoke to get the {@link TransactionManager}. */ public String getTransactionManagerMethod() { return _methodName; } /** * Set the method to invoke to get the {@link TransactionManager}. * E.g.: com.ibm.ejs.jts.jta.JTSXA.getTransactionManager */ public void setTransactionManagerMethod(String methodName) { _clazz = methodName.substring(0, methodName.lastIndexOf('.')); _methodName = methodName.substring(methodName.lastIndexOf('.') + 1); _method = null; } public TransactionManager getTransactionManager() throws Exception { if (_method == null) { ClassLoader loader = _conf.getClassResolverInstance(). getClassLoader(getClass(), null); _method = Class.forName(_clazz, true, loader) .getMethod(_methodName, null); } return (TransactionManager) _method.invoke(null, null); } public void setConfiguration(Configuration conf) { _conf = (OpenJPAConfiguration) conf; } public void startConfiguration() { } public void endConfiguration() { } public void setRollbackOnly(Throwable cause) throws Exception { // there is no generic support for setting the rollback cause getTransactionManager().getTransaction().setRollbackOnly(); } public Throwable getRollbackCause() throws Exception { // there is no generic support for setting the rollback cause return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/WLSManagedRuntime.java0000644000000000000000000000620312133327272026535 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import java.lang.reflect.Method; import javax.transaction.Transaction; import javax.transaction.TransactionManager; /** * {@link ManagedRuntime} implementation that directly accesses the * transaction manager via WebLogic Server helper classes. * * @author Arunabh Hazarika, Patrick Linskey */ public class WLSManagedRuntime extends AbstractManagedRuntime implements ManagedRuntime { private final Method _txHelperMeth; private final Method _txManagerMeth; public WLSManagedRuntime() throws ClassNotFoundException, NoSuchMethodException { Class txHelper = Class.forName ("weblogic.transaction.TransactionHelper"); _txHelperMeth = txHelper.getMethod("getTransactionHelper", null); _txManagerMeth = txHelper.getMethod("getTransactionManager", null); } public TransactionManager getTransactionManager() throws Exception { // return TransactionHelper.getTransactionHelper (). // getTransactionManager (); Object o = _txHelperMeth.invoke(null, null); return (TransactionManager) _txManagerMeth.invoke(o, null); } public void setRollbackOnly(Throwable cause) throws Exception { Transaction transaction = getTransactionManager().getTransaction(); try { // try to use reflection to call the setRollbackOnly(Throwable) // method in weblogic.transaction.Transaction transaction.getClass(). getMethod("setRollbackOnly", new Class[] { Throwable.class }). invoke(transaction, new Object[] { cause }); } catch (Throwable e) { // some problem occurred: fall back to the traditional call transaction.setRollbackOnly(); } } public Throwable getRollbackCause() throws Exception { Transaction transaction = getTransactionManager().getTransaction(); try { // try to use reflection to call the getRollbackReason() // method in weblogic.transaction.Transaction return (Throwable) transaction.getClass(). getMethod("getRollbackReason", new Class[0]). invoke(transaction, new Object[0]); } catch (Throwable e) { // some problem occurred: just return null return null; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/OSGiManagedRuntime.java0000644000000000000000000001527012133327272026675 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import javax.transaction.TransactionManager; import org.apache.openjpa.util.InternalException; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; /** *

    Implementation of the {@link ManagedRuntime} interface that listens * for an OSGi service with interface javax.transaction.TransactionManager * to create a {@link TransactionManager} for controlling transactions.

    * *

    The support for a transaction manager is usually activated inside an OSGi * {@link BundleActivator} implementation using {@link #registerServiceListener(BundleContext)} * and {@link #deregisterServiceListener(BundleContext)}. *

    */ public class OSGiManagedRuntime extends AbstractManagedRuntime { /** * a static instance, which is managed by the ServiceListener added to the bundle * context by {@link #registerServiceListener(BundleContext)}. */ private static TransactionManager transactionManager; private static ServiceReference serviceReference; private static ServiceListener listener; private static final class Listener implements ServiceListener { final BundleContext bundleContext; // avoid the garbage collection of the OSGiManagedRuntime class itself, // by holding a reference to it. final Class clazzRef; public Listener(BundleContext bundleContext) { this.bundleContext = bundleContext; this.clazzRef = OSGiManagedRuntime.class; } @Override public void serviceChanged(ServiceEvent event) { synchronized (this.clazzRef) { switch (event.getType()) { case ServiceEvent.REGISTERED: OSGiManagedRuntime.serviceReference = event.getServiceReference(); OSGiManagedRuntime.transactionManager = (TransactionManager) this.bundleContext.getService(OSGiManagedRuntime.serviceReference); break; case ServiceEvent.UNREGISTERING: OSGiManagedRuntime.transactionManager = null; OSGiManagedRuntime.serviceReference = null; this.bundleContext.ungetService(event.getServiceReference()); break; } } } } /** *

    Register a service listener to the given bundle context by * {@link BundleContext#addServiceListener(ServiceListener,String)} with a filter * expression of (objectClass=javax.transaction.TransactionManager).

    * *

    The caller is responsible for calling * {@link #deregisterServiceListener(BundleContext)}, when * the bundle context is being stopped.

    * * @param bundle The bundle, which is currently being started. * @throws InvalidSyntaxException When the filter expression is invalid. */ public static synchronized void registerServiceListener(BundleContext bundleContext) throws InvalidSyntaxException { if (listener != null) { throw new InternalException("Another OSGi service listener has already been registered."); } listener = new Listener(bundleContext); bundleContext.addServiceListener(listener, "(" + Constants.OBJECTCLASS + "=javax.transaction.TransactionManager)"); serviceReference = bundleContext.getServiceReference("javax.transaction.TransactionManager"); if (serviceReference != null) { transactionManager = (TransactionManager)bundleContext.getService(serviceReference); } } /** * Remove a service listener previously started inside {@link #registerServiceListener(BundleContext)}. * * @param bundleContext The bundle context to call * {@link BundleContext#removeServiceListener(ServiceListener)} on. */ public static synchronized void deregisterServiceListener(BundleContext bundleContext) { try { if (serviceReference != null) { bundleContext.ungetService(serviceReference); transactionManager = null; serviceReference = null; } } finally { // assure, that the service listener is removed, whatever happens above. if (listener != null) { bundleContext.removeServiceListener(listener); listener = null; } } } /* (non-Javadoc) * @see org.apache.openjpa.ee.ManagedRuntime#getTransactionManager() */ @Override public TransactionManager getTransactionManager() throws Exception { synchronized (OSGiManagedRuntime.class) { if (transactionManager == null) { throw new InternalException("No javax.transaction.TransactionManager " + "service is currently registered as an OSGi service."); } return transactionManager; } } /* (non-Javadoc) * * @see org.apache.openjpa.ee.ManagedRuntime#setRollbackOnly(java.lang.Throwable) */ @Override public void setRollbackOnly(Throwable cause) throws Exception { // there is no generic support for setting the rollback cause getTransactionManager().getTransaction().setRollbackOnly(); } /* (non-Javadoc) * @see org.apache.openjpa.ee.ManagedRuntime#getRollbackCause() */ @Override public Throwable getRollbackCause() throws Exception { // there is no generic support for setting the rollback cause return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/WASManagedRuntime.java0000644000000000000000000003367312133327272026535 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import javax.naming.Context; import javax.naming.InitialContext; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.InvalidTransactionException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.Status; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.xa.XAResource; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.enhance.AsmAdaptor; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.NoTransactionException; import serp.bytecode.BCClass; import serp.bytecode.Project; /** * {@link ManagedRuntime} implementation that allows synchronization with a * WebSphere managed transaction. * *

    * WebSphere Application Server does not expose the TransactionManager to an * application. Instead it provides a proprietary interface to register for * synchronization and obtain transaction ids. * *

    * WASManagedRuntime provides the wrapper classes needed to interact with the * WAS proprietary interface and the OpenJPA kernel. * * @author Kevin Sutter */ public class WASManagedRuntime extends AbstractManagedRuntime implements ManagedRuntime, Configurable { private static final Localizer _loc = Localizer.forPackage(WASManagedRuntime.class); private Object _extendedTransaction = null; private Method _getGlobalId = null; private Method _registerSync = null; private OpenJPAConfiguration _conf = null; private Log _log = null; /** * Gets an extendedJTATransaction from JNDI and creates a transaction * wrapper */ public javax.transaction.TransactionManager getTransactionManager() throws Exception { return new WASTransaction(); } /** * Transaction wrapper for WebSphere. WebSphere exposes a subset of the * Transaction and TransactionManager interfaces to the customer. Any * methods which are not exposed by WebSphere will throw an * IllegalStateException to the caller. * *

    * Methods supported by WAS are *

      *
    • RegisterSynchronization
    • *
    • GetStatus
    • *
    */ class WASTransaction implements javax.transaction.TransactionManager, javax.transaction.Transaction { public int getStatus() throws SystemException { int rval; try { if (getGlobalId() != null) { rval = Status.STATUS_ACTIVE; } else { rval = Status.STATUS_NO_TRANSACTION; } } catch (Exception e) { throw new NoTransactionException(_loc .get("was-transaction-id-exception")).setCause(e); } return rval; } /** * Provides a Transaction wrapper. The transaction wrapper mayb only be * used to determine the status of the current transaction. WebSphere * does not allow direct control of container transactions. * * @return A WebSphere transaction wrapper. */ public Transaction getTransaction() throws SystemException { return this; } /** * Register for synchronization with a WebSphere managed transaction via * the extendedJTATransaction interface. */ public void registerSynchronization(Synchronization arg0) throws IllegalStateException, RollbackException, SystemException { if (_extendedTransaction != null) { try { _registerSync.invoke(_extendedTransaction, new Object[] { new WASSynchronization(arg0) }); } catch (Exception e) { throw new InvalidStateException(_loc .get("was-reflection-exception")).setCause(e); } } else { throw new InvalidStateException(_loc.get("was-lookup-error")); } } /** * Gets the GlobalTransaction ID of the WebSphere managed transaction. * If no Global Transaction is active null will be returned. * * @return Null if a global transaction is not active or if an error * occurs. byte[] id if a global transaction is active. */ private byte[] getGlobalId() { try { return (byte[]) _getGlobalId.invoke(_extendedTransaction, null); } catch (Exception e) { throw new InvalidStateException(_loc .get("was-reflection-exception")).setCause(e); } } /** * Unimplemented, WAS does not provide this level of control. Throws an * IllegalStateException */ public void begin() throws NotSupportedException, SystemException { throw new InvalidStateException(_loc.get("was-unsupported-op", "begin")); } /** * Unimplemented, WAS does not provide this level of control. Throws an * IllegalStateException */ public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException, RollbackException, SecurityException, SystemException { throw new InvalidStateException(_loc.get("was-unsupported-op", "commit")); } /** * Unimplemented, WAS does not provide this level of control. Throws an * IllegalStateException */ public void resume(Transaction arg0) throws IllegalStateException, InvalidTransactionException, SystemException { throw new InvalidStateException(_loc.get("was-unsupported-op", "resume")); } /** * Unimplemented, WAS does not provide this level of control. Log a * trace instead of throwing an exception. Rollback may be used in * some error paths, throwing another exception may result in the * original exception being lost. */ public void rollback() throws IllegalStateException, SecurityException, SystemException { if (_log.isTraceEnabled()) { _log.trace(_loc.get("was-unsupported-op", "rollback")); } } /** * Unimplemented, WAS does not provide this level of control. Log a * trace instead of throwing an exception. SetRollbackOnly may be used * in some error paths, throwing another exception may result in the * original exception being lost. */ public void setRollbackOnly() throws IllegalStateException, SystemException { if (_log.isTraceEnabled()) { _log.trace(_loc.get("was-unsupported-op", "setRollbackOnly")); } } /** * Unimplemented, WAS does not provide this level of control. Throws an * IllegalStateException */ public void setTransactionTimeout(int arg0) throws SystemException { throw new InvalidStateException(_loc.get("was-unsupported-op", "setTransactionTimeout")); } /** * Unimplemented, WAS does not provide this level of control. Throws an * IllegalStateException */ public Transaction suspend() throws SystemException { throw new InvalidStateException(_loc.get("was-unsupported-op", "suspend")); } /** * Unimplemented, WAS does not provide this level of control. Throws an * IllegalStateException */ public boolean delistResource(XAResource arg0, int arg1) throws IllegalStateException, SystemException { throw new InvalidStateException(_loc.get("was-unsupported-op", "delistResource")); } /** * Unimplemented, WAS does not provide this level of control. Throws an * IllegalStateException */ public boolean enlistResource(XAResource arg0) throws IllegalStateException, RollbackException, SystemException { throw new InvalidStateException(_loc.get("was-unsupported-op", "enlistResource")); } } /** * WASSynchronization wrapper. This class translates the WAS proprietary * synchronization callback methods to javax.transaction.Synchronization * methods. * *

    * This class implements the * com.ibm.websphere.jtaextensions.SynchronizationCallback interface. Since * SynchronizationCallback is not available at compile time we use Serp to * add the interface to the class after all classes have been compiled. * *

    * SynchronizationCallback is expected to be available whenever this class * is instantiated, therefore this class should only be used when running in * WebSphere. * * @see org.apache.openjpa.util.WASTransformer */ static class WASSynchronization { Synchronization _sync = null; WASSynchronization(Synchronization sync) { _sync = sync; } /** * AfterCompletion wrapper. Translates the WAS proprietary call to a * javax.transaction.Synchronization call. */ public void afterCompletion(int localTransactionId, byte[] globalTransactionId, boolean committed) { if (_sync != null) { if (committed) { _sync.afterCompletion(Status.STATUS_COMMITTED); } else { _sync.afterCompletion(Status.STATUS_UNKNOWN); } } } /** * BeforeCompletion wrapper. Translates WAS proprietary call to a * javax.transaction.Synchronization call. */ public void beforeCompletion(int arg0, byte[] arg1) { if (_sync != null) { _sync.beforeCompletion(); } } } /** * Caches a copy of the configuration. The configuration is used to obtain * the logger and classloader. */ public void setConfiguration(Configuration conf) { _conf = (OpenJPAConfiguration) conf; _log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); } /** * EndConfiguration stub. */ public void endConfiguration() { try { Context ctx = new InitialContext(); try { _extendedTransaction = ctx.lookup("java:comp/websphere/ExtendedJTATransaction"); } finally { ctx.close(); } Class extendedJTATransaction = Class.forName( "com.ibm.websphere.jtaextensions.ExtendedJTATransaction"); Class synchronizationCallback = Class.forName( "com.ibm.websphere.jtaextensions.SynchronizationCallback"); _registerSync = extendedJTATransaction.getMethod( "registerSynchronizationCallbackForCurrentTran", new Class[] { synchronizationCallback }); _getGlobalId = extendedJTATransaction. getMethod("getGlobalId", null); } catch (Exception e) { throw new InvalidStateException(_loc .get("was-reflection-exception"), e).setFatal(true); } } /** * StartConfiguration stub. */ public void startConfiguration() { // Nothing to do } /** * Class that will be modified */ static final String CLASS = "org.apache.openjpa.ee.WASManagedRuntime$WASSynchronization"; /** * Interface which will be added */ static final String INTERFACE = "com.ibm.websphere.jtaextensions.SynchronizationCallback"; public static void main(String[] args) throws IOException { Project project = new Project(); InputStream in = WASManagedRuntime.class.getClassLoader() .getResourceAsStream(CLASS.replace('.', '/') + ".class"); BCClass bcClass = project.loadClass(in); String [] interfaces = bcClass.getInterfaceNames(); if(interfaces != null) { for(int i = 0; i < interfaces.length; i++) { if(interfaces[i].equals(INTERFACE)) { return; } } } bcClass.declareInterface(INTERFACE); AsmAdaptor.write(bcClass); } public void setRollbackOnly(Throwable cause) throws Exception { // there is no generic support for setting the rollback cause getTransactionManager().getTransaction().setRollbackOnly(); } public Throwable getRollbackCause() throws Exception { // there is no generic support for setting the rollback cause return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ee/RegistryManagedRuntime.java0000644000000000000000000001471612133327272027710 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ee; import javax.naming.Context; import javax.naming.InitialContext; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.InvalidTransactionException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAResource; import org.apache.openjpa.lib.util.Localizer; /** * Implementation of the {@link ManagedRuntime} interface that uses * the {@link TransactionSynchronizationRegistry} interface (new in JTA 1.1) * to create a {@link TransactionManager} facade for controlling transactions. * * @author Marc Prud'hommeaux * @since 1.0.0 */ public class RegistryManagedRuntime implements ManagedRuntime { private String _registryName = "java:comp/TransactionSynchronizationRegistry"; private TransactionManagerRegistryFacade _tm = null; private static Localizer _loc = Localizer.forPackage(RegistryManagedRuntime.class); /** * Return the cached TransactionManager instance. */ public TransactionManager getTransactionManager() throws Exception { if (_tm == null) { Context ctx = new InitialContext(); try { _tm = new TransactionManagerRegistryFacade ((TransactionSynchronizationRegistry) ctx. lookup(_registryName)); } finally { ctx.close(); } } return _tm; } public void setRollbackOnly(Throwable cause) throws Exception { // there is no generic support for setting the rollback cause getTransactionManager().getTransaction().setRollbackOnly(); } public Throwable getRollbackCause() throws Exception { // there is no generic support for setting the rollback cause return null; } public void setRegistryName(String registryName) { _registryName = registryName; } public String getRegistryName() { return _registryName; } public Object getTransactionKey() throws Exception, SystemException { return _tm.getTransactionKey(); } /** * A {@link TransactionManager} and {@link Transaction} facade * that delegates the appropriate methods to the internally-held * {@link TransactionSynchronizationRegistry}. Since the * registry is not able to start or end transactions, all transaction * control methods will just throw a {@link SystemException}. * * @author Marc Prud'hommeaux */ public static class TransactionManagerRegistryFacade implements TransactionManager, Transaction { private final TransactionSynchronizationRegistry _registry; public TransactionManagerRegistryFacade (TransactionSynchronizationRegistry registry) { _registry = registry; } public Transaction getTransaction() throws SystemException { return TransactionManagerRegistryFacade.this; } public void registerSynchronization(Synchronization sync) throws RollbackException, IllegalStateException, SystemException { _registry.registerInterposedSynchronization(sync); } public void setRollbackOnly() throws IllegalStateException, SystemException { _registry.setRollbackOnly(); } public int getStatus() throws SystemException { return _registry.getTransactionStatus(); } public Object getTransactionKey() { return _registry.getTransactionKey(); } ////////////////////////////// // Unsupported methods follow ////////////////////////////// public void begin() throws NotSupportedException, SystemException { throw new NotSupportedException(); } public void commit() throws RollbackException, HeuristicMixedException, SystemException, HeuristicRollbackException, SecurityException, IllegalStateException { throw new SystemException(); } public void resume(Transaction tobj) throws InvalidTransactionException, IllegalStateException, SystemException { throw new SystemException(); } public void rollback() throws IllegalStateException, SecurityException, SystemException { throw new SystemException(); } public void setTransactionTimeout(int seconds) throws SystemException { throw new SystemException(); } public Transaction suspend() throws SystemException { throw new SystemException(); } public boolean delistResource(XAResource xaRes, int flag) throws IllegalStateException, SystemException { throw new SystemException(); } public boolean enlistResource(XAResource xaRes) throws RollbackException, IllegalStateException, SystemException { throw new SystemException(); } } /** *

    * RegistryManagedRuntime cannot suspend transactions. *

    */ public void doNonTransactionalWork(Runnable runnable) throws NotSupportedException { throw new NotSupportedException(_loc.get("tsr-cannot-suspend") .getMessage()); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/audit/0000755000000000000000000000000012133327272023120 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/audit/AuditableOperation.java0000644000000000000000000000175612133327272027547 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.audit; /** * Operations of persistent type that can be audited. * * @author Pinaki Poddar * */ public enum AuditableOperation { CREATE, UPDATE, DELETE, ALL } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/audit/Auditable.java0000644000000000000000000000257412133327272025665 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.audit; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * Annotates a persistent type for {@link Auditor audit}. *
    * A type can be audited for specific {@link AuditableOperation operations}. * By default, this annotation enables all operations. * * @author Pinaki Poddar * */ @Target({TYPE}) @Retention(RUNTIME) public @interface Auditable { AuditableOperation[] values() default AuditableOperation.ALL; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/audit/AuditLogger.java0000644000000000000000000000523112133327272026172 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.audit; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; import java.util.Arrays; import java.util.Collection; import org.apache.openjpa.kernel.Audited; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.lib.conf.Configuration; /** * A default auditor that simply prints the audited instances. * The output could be directed to a file, defaults to System.out. * * @author Pinaki Poddar * */ public class AuditLogger implements Auditor { private PrintStream _out = System.out; private String _file; @Override public void audit(Broker broker, Collection newObjects, Collection updates, Collection deletes) { for (Audited audited : newObjects) { _out.print(audited.getType() + ": [" + audited.getManagedObject() + "]"); _out.println(" Fields:" + Arrays.toString(audited.getUpdatedFields())); } for (Audited audited : updates) { _out.print(audited.getType() + ": [" + audited.getOriginalObject() + "] to [" + audited.getManagedObject() + "]"); _out.println(" Fields:" + Arrays.toString(audited.getUpdatedFields())); } for (Audited audited : deletes) { _out.print(audited.getType() + ": [" + audited.getOriginalObject() + "]"); _out.println(" Fields:" + Arrays.toString(audited.getUpdatedFields())); } } public void setFile(String file) throws FileNotFoundException { _out = new PrintStream(new FileOutputStream(_file = file), true); } public String getFile() { return _file; } public boolean isRollbackOnError() { return false; } @Override public void setConfiguration(Configuration conf) { } @Override public void startConfiguration() { } @Override public void endConfiguration() { } @Override public void close() throws Exception { if (_out != System.out) { _out.close(); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/audit/Auditor.java0000644000000000000000000000430312133327272025372 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.audit; import java.util.Collection; import org.apache.openjpa.kernel.Audited; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.util.Closeable; /** * An auditor is responsible for recoding the audited information. * OpenJPA runtime will track the auditable instances and invoke * implementation of this interface within a transaction. *
    * The user implementation of this interface is configurable via * standard OpenJPA plug-in configuration framework. * * @author Pinaki Poddar * */ public interface Auditor extends Configurable, Closeable { /** * OpenJPA runtime will invoke this method with the given parameters * within a transaction. * * @param broker the active persistence context. * @param newObjects the set of auditable objects being created. Can be empty, but never null. * @param updates the set of auditable objects being updated. Can be empty, but never null. * @param deletes the set of auditable objects being deleted. Can be empty, but never null. */ public void audit(Broker broker, Collection newObjects, Collection updates, Collection deletes); /** * Affirm if the transaction be rolled back if {@link #audit(Broker, Collection, Collection, Collection) audit} * operation fails with an exception. */ public boolean isRollbackOnError(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/0000755000000000000000000000000012133327270024670 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/package.html0000644000000000000000000000504512133327270027155 0ustar

    OpenJPA Abstract StoreManager Implementation

    This package provides some infrastructure classes to help in the creation of OpenJPA drivers for new non-relational data stores.

    To create support for a new data store:

    • Extend AbstractStoreManager following the rules outlined in its documentation.

    • Configure your org.apache.openjpa.properties file (or your resource archive configuration file) to use AbstractStoreBrokerFactory, and specify your AbstractStore extension as the org.apache.openjpa.abstractstore.AbstractStoreManager class:

      openjpa.BrokerFactory: abstractstore
      openjpa.abstractstore.AbstractStoreManager: com.xyz.MyAbstractStoreManagerSubclass

    Additionally, you can optionally extend OpenJPAConfigurationImpl to define your own configuration options, using the helper classes defined in the org.apache.openjpa.lib.conf package. To do this you must also override the AbstractStoreManager.newConfiguration method.

    For a sample of how to use this package, see the org.apache.openjpa.xmlstore abstract store implementation.

    ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreBrokerFactory.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreBroker0000644000000000000000000001336012133327270030543 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.abstractstore; import java.security.AccessController; import java.util.Map; import java.util.Properties; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.AbstractBrokerFactory; import org.apache.openjpa.kernel.Bootstrap; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.StoreManager; import org.apache.openjpa.lib.conf.ConfigurationProvider; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.conf.ProductDerivations; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * {@link BrokerFactory} implementation for use with the * {@link AbstractStoreManager}. This provides integration into the * {@link Bootstrap#getBrokerFactory()} bootstrapping mechanism, to facilitate * the process of creating a subclass of {@link AbstractStoreManager}. New * store manager implementations need not extend this class. Instead, set the * openjpa.BrokerFactory configuration property to * abstractstore, * and set the openjpa.abstractstore.AbstractStoreManager * configuration property to the full class name of your implementation. * Additionally, you can optionally create your own * BrokerFactory implementation. However, we recommend that you * use the AbstractStoreBrokerFactory, as it deals with pooling * and bootstrapping from a {@link Map} object (the strategy used by * {@link Bootstrap} to create a factory in a vendor-neutral manner). */ public class AbstractStoreBrokerFactory extends AbstractBrokerFactory { /** * The property name under which to name the concrete store manager * class for this runtime. */ private static final String PROP_ABSTRACT_STORE = "abstractstore.AbstractStoreManager"; private static final Localizer s_loc = Localizer.forPackage (AbstractStoreBrokerFactory.class); private String _storeCls = null; private String _storeProps = null; private String _platform = null; /** * Factory method for obtaining a possibly-pooled {@link BrokerFactory} * from properties. Invoked from {@link Bootstrap#getBrokerFactory()}. */ public static AbstractStoreBrokerFactory getInstance( ConfigurationProvider cp) { Object key = toPoolKey(cp.getProperties()); AbstractStoreBrokerFactory factory = (AbstractStoreBrokerFactory) getPooledFactoryForKey(key); if (factory != null) return factory; factory = newInstance(cp); factory.pool(key, factory); return factory; } /** * Factory method for constructing a {@link BrokerFactory} * from properties. Invoked from {@link Bootstrap#newBrokerFactory()}. */ public static AbstractStoreBrokerFactory newInstance (ConfigurationProvider cp) { // use a tmp store manager to get metadata about the capabilities of // this runtime Map map = cp.getProperties(); String storePlugin = (String) map.get(ProductDerivations .getConfigurationKey(PROP_ABSTRACT_STORE, map)); String storeCls = Configurations.getClassName(storePlugin); String storeProps = Configurations.getProperties(storePlugin); AbstractStoreManager store = createStoreManager(storeCls, storeProps); // populate configuration OpenJPAConfiguration conf = store.newConfiguration(); cp.setInto(conf); conf.supportedOptions().removeAll(store.getUnsupportedOptions()); // create and pool a new factory return new AbstractStoreBrokerFactory(conf, storeCls, storeProps, store.getPlatform()); } /** * Construct the factory with the given settings. */ protected AbstractStoreBrokerFactory(OpenJPAConfiguration conf, String storeCls, String storeProps, String platform) { super(conf); _storeCls = storeCls; _storeProps = storeProps; _platform = platform; } public Map getProperties() { Map props = super.getProperties(); props.put("Platform", _platform); return props; } protected StoreManager newStoreManager() { return createStoreManager(_storeCls, _storeProps); } private static AbstractStoreManager createStoreManager(String cls, String props) { AbstractStoreManager store = (AbstractStoreManager) Configurations.newInstance(cls, AccessController.doPrivileged(J2DoPrivHelper .getClassLoaderAction(AbstractStoreManager.class))); Configurations.configureInstance(store, null, props, PROP_ABSTRACT_STORE); if (store == null) throw new UserException(s_loc.get("no-store-manager", PROP_ABSTRACT_STORE)).setFatal(true); return store; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManage0000644000000000000000000005166012133327270030514 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.abstractstore; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.FetchConfigurationImpl; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.PCState; import org.apache.openjpa.kernel.Seq; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.kernel.StoreManager; import org.apache.openjpa.kernel.StoreQuery; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueStrategies; import org.apache.openjpa.util.ApplicationIds; import org.apache.openjpa.util.Id; import org.apache.openjpa.util.ImplHelper; /** * Abstract store manager implementation to ease development of custom * OpenJPA back-ends. A concrete subclass must define implementations for the * following methods: *
      *
    • {@link StoreManager#exists}
    • *
    • {@link #initialize}
    • *
    • {@link #load}
    • *
    • {@link * #flush(Collection,Collection,Collection,Collection,Collection)}
    • *
    • {@link #executeExtent}
    • *
    Additionally, subclasses should not attempt to acquire resources * until {@link #open} has been called. Store manager instances might be * created to call metadata methods such as {@link #newConfiguration} or * {@link #getUnsupportedOptions} and never opened. These instances should * not consume any data store resources. * Notes: *
      *
    • The {@link StoreManager#initialize} method is responsible * for creating new instances of objects freshly loaded from the * database. The method will be invoked with a {@link OpenJPAStateManager} * that the newly-loaded object should be associated with. To create the * new object and set up this association correctly, the implementation * should use the {@link OpenJPAStateManager#initialize} method.
    • *
    • If your data store supports some sort of transaction or * unit of work, you should override the {@link #begin}, {@link #commit}, * and {@link #rollback} methods.
    • *
    • This class provides no infrastructure support for optimistic * transactions. To provide optimistic transaction support: *
        *
      • Override {@link #beginOptimistic}, {@link #rollbackOptimistic}, * and {@link #syncVersion}.
      • *
      • Override {@link #getUnsupportedOptions} to not include {@link * OpenJPAConfiguration#OPTION_OPTIMISTIC} in the list of unsupported * options.
      • *
      • Ensure that your flush implementation sets the next * version for each modified object via the {@link * OpenJPAStateManager#setNextVersion} method.
      • *
      • If your version object does not implement {@link Comparable}, * override {@link #compareVersion}, which relies on the * {@link Comparable#compareTo} method.
      • *
    • *
    • If your data store supports a mechanism for automatically * generating and managing identity values (or if you want to * provide that facility on top of your data store), implement * the {@link #getDataStoreIdSequence} method if you want to use a * long as your datastore identity type and are * happy with OpenJPA's {@link Id} class. To use another datastore identity * type, override {@link #getManagedType}, * {@link #getDataStoreIdType}, {@link #copyDataStoreId}, and * {@link #newDataStoreId} instead. In either case, override * {@link #getUnsupportedOptions} to not include * {@link OpenJPAConfiguration#OPTION_ID_DATASTORE} in the list of * unsupported options.
    • *
    • If your data store does not support queries (or if you do * not want to convert OpenJPA's query parse tree into a * datastore-specific query), you still have two options in terms * of query execution: *
        *
      • In-memory execution: If you * execute a query against an extent or a class, OpenJPA will * automatically load the full extent of objects into memory and * execute the query in memory.
      • *
      • openjpa.MethodQL: MethodQL allows * you to use the query APIs to execute a method that finds * data in your back-end and returns that data as a * {@link org.apache.openjpa.lib.rop.ResultList}. For more details on * MethodQL, see the OpenJPA Reference Guide.
      • *
    • *
    * * @since 0.3.1 */ public abstract class AbstractStoreManager implements StoreManager { protected StoreContext ctx; public final void setContext(StoreContext ctx) { this.ctx = ctx; open(); } /** * Returns the {@link StoreContext} that this store manager is * associated with. */ public StoreContext getContext() { return ctx; } /** * No-op implementation. Ready this store manager for persistent operations. */ protected void open() { } /** * No-op implementation. Override this method to provide optimistic * locking semantics for your data store if you need notification of * the beginning of an optimistic transaction. */ public void beginOptimistic() { } /** * No-op implementation. Override this method to provide optimistic * locking semantics for your data store if you need notification of * a rollback of an optimistic transaction before {@link #begin} is invoked. */ public void rollbackOptimistic() { } /** * OpenJPA assumes that after this method is invoked, all data * accesses through this store manager will be part of a single * unit of work that can be rolled back. * This is a no-op implementation. If your data store does not * support any concept of locking or transactions, you need not * override this method. */ public void begin() { } /** * This is a no-op implementation. If your data store does not * have a concept of transactions or a unit of work, you need not * override this method. If it does, then override this method to * notify the data store that the current transaction should be committed. */ public void commit() { } /** * This is a no-op implementation. If your data store does not * have a concept of transactions or a unit of work, you need not * override this method. If it does, then override this method to * notify the data store that the current transaction should be rolled back. */ public void rollback() { } /** * Since this store manager does not provide optimistic locking * support, this method always returns true. */ public boolean syncVersion(OpenJPAStateManager sm, Object edata) { return true; } /** * This method is invoked when OpenJPA needs to load an object whose * identity is known but which has not yet been loaded from the data * store. sm is a partially-set-up state manager for this * object. The ID and least-derived type information for the instance * to load can be obtained by invoking * sm.getObjectId() and sm.getMetaData(). * * When implementing this method, load the data for this object from * the data store, determine the most-derived subclass of the newly-loaded * data, and then use the {@link OpenJPAStateManager#initialize} method to * populate sm with a new instance of the appropriate type. * Once {@link OpenJPAStateManager#initialize} has been invoked, proceed to * load field data into sm as in the {@link #load} method, by * using {@link OpenJPAStateManager#store} (or the appropriate * OpenJPAStateManager.storetype method) to put the * data into the object. */ public abstract boolean initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch, Object edata); /** * This method is invoked when OpenJPA needs to load additional data * into an object that has already been at least partially loaded by * a previous {@link #initialize} invocation. * Load data into sm by using {@link * OpenJPAStateManager#store} (or the appropriate * OpenJPAStateManager.storetype method) to put the * data into the object. */ public abstract boolean load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch, int lockLevel, Object edata); /** * This implementation just delegates to the proper singular * method ({@link StoreManager#initialize} or {@link StoreManager#load}) * depending on each state manager's state. If your data store provides * bulk loading APIs, overriding this method to be more clever may be * advantageous. */ public Collection loadAll(Collection sms, PCState state, int load, FetchConfiguration fetch, Object edata) { return ImplHelper.loadAll(sms, this, state, load, fetch, edata); } /** * Breaks down states based on the objects' current * states, and delegates to * {@link #flush(Collection,Collection,Collection,Collection,Collection)}. */ public Collection flush(Collection sms) { // break down state managers by state; initialize as empty lists; // use constants for efficiency Collection pNew = new LinkedList(); Collection pNewUpdated = new LinkedList(); Collection pNewFlushedDeleted = new LinkedList(); Collection pDirty = new LinkedList(); Collection pDeleted = new LinkedList(); for (OpenJPAStateManager sm : sms) { if (sm.getPCState() == PCState.PNEW && !sm.isFlushed()) pNew.add(sm); else if (sm.getPCState() == PCState.PNEW && sm.isFlushed()) pNewUpdated.add(sm); else if (sm.getPCState() == PCState.PNEWFLUSHEDDELETED) pNewFlushedDeleted.add(sm); else if (sm.getPCState() == PCState.PDIRTY) pDirty.add(sm); else if (sm.getPCState() == PCState.PDELETED) pDeleted.add(sm); } // no dirty instances to flush? if (pNew.isEmpty() && pNewUpdated.isEmpty() && pNewFlushedDeleted.isEmpty() && pDirty.isEmpty() && pDeleted.isEmpty()) return Collections.EMPTY_LIST; return flush(pNew, pNewUpdated, pNewFlushedDeleted, pDirty, pDeleted); } public void beforeStateChange(OpenJPAStateManager sm, PCState fromState, PCState toState) { } public boolean assignObjectId(OpenJPAStateManager sm, boolean preFlush) { ClassMetaData meta = sm.getMetaData(); if (meta.getIdentityType() == ClassMetaData.ID_APPLICATION) return ApplicationIds.assign(sm, this, preFlush); // datastore identity Object val = ImplHelper.generateIdentityValue(ctx, meta, JavaTypes.LONG); return assignDataStoreId(sm, val); } /** * Assign a new datastore identity to the given instance. This given * value may be null. */ protected boolean assignDataStoreId(OpenJPAStateManager sm, Object val) { ClassMetaData meta = sm.getMetaData(); if (val == null && meta.getIdentityStrategy() != ValueStrategies.NATIVE) return false; if (val == null) val = getDataStoreIdSequence(meta).next(ctx, meta); sm.setObjectId(newDataStoreId(val, meta)); return true; } public boolean assignField(OpenJPAStateManager sm, int field, boolean preFlush) { FieldMetaData fmd = sm.getMetaData().getField(field); Object val = ImplHelper.generateFieldValue(ctx, fmd); if (val == null) return false; sm.store(field, val); return true; } public Class getManagedType(Object oid) { if (oid instanceof Id) return ((Id) oid).getType(); return null; } public Class getDataStoreIdType(ClassMetaData meta) { return Id.class; } public Object copyDataStoreId(Object oid, ClassMetaData meta) { Id id = (Id) oid; return new Id(meta.getDescribedType(), id.getId(), id.hasSubclasses()); } public Object newDataStoreId(Object val, ClassMetaData meta) { // we use base types for all oids while (meta.getPCSuperclass() != null) meta = meta.getPCSuperclassMetaData(); return Id.newInstance(meta.getDescribedType(), val); } /** * Override to retain a dedicated connection. */ public void retainConnection() { } /** * Override to release previously-retained connection. */ public void releaseConnection() { } /** * Returns null. If your data store can provide a * distinct connection object, return it here. */ public Object getClientConnection() { return null; } /** * Create a {@link ResultObjectProvider} that can return all instances * of type, optionally including subclasses as defined * by subclasses. * The implementation of the result provider will typically execute * some sort of data store query to find all the applicable objects, loop * through the results, extracting object IDs from the data, and invoke * {@link StoreContext#find(Object,FetchConfiguration,BitSet,Object,int)} * on each OID. When invoking this method, the first argument is the OID. * The second is the given fetch configuration. The * third argument is a mask of fields to exclude from loading; it will * typically be null. The fourth argument is an object that will be passed * through to {@link #initialize} or {@link #load}, and typically will * contain the actual data to load. For example, for a JDBC-based store * manager, this might be the result set that is being iterated over. If * this argument is null, then the {@link #initialize} or * {@link #load} method will have to issue another command to the data * store in order to fetch the data to be loaded. */ public abstract ResultObjectProvider executeExtent(ClassMetaData meta, boolean subs, FetchConfiguration fetch); public StoreQuery newQuery(String language) { return null; } public FetchConfiguration newFetchConfiguration() { return new FetchConfigurationImpl(); } /** * Casts v1 and v2 to {@link Comparable}, and * invokes v1.compareTo (v2). If v1 is less * than v2, returns {@link #VERSION_EARLIER}. If the same, * returns {@link #VERSION_SAME}. Otherwise, returns {@link * #VERSION_LATER}. If either v1 or v2 are * null, returns {@link #VERSION_DIFFERENT}. */ public int compareVersion(OpenJPAStateManager state, Object v1, Object v2) { if (v1 == null || v2 == null) return VERSION_DIFFERENT; int compare = ((Comparable) v1).compareTo((Comparable) v2); if (compare < 0) return VERSION_EARLIER; if (compare == 0) return VERSION_SAME; return VERSION_LATER; } /** * Returns the system-configured sequence. To use some other sort * of datastore identifier (a GUID, string, or someting of that nature), * override {@link #getManagedType}, * {@link #getDataStoreIdType}, {@link #copyDataStoreId}, * {@link #newDataStoreId}. */ public Seq getDataStoreIdSequence(ClassMetaData forClass) { return ctx.getConfiguration().getSequenceInstance(); } /** * Returns null. */ public Seq getValueSequence(FieldMetaData forField) { return null; } /** * Returns false. If your data store supports * cancelling queries, this method should cancel any * currently-running queries and return true if any * were cancelled. */ public boolean cancelAll() { return false; } public void close() { } /** * Responsible for writing modifications happened back to the data * store. If you do not remove the * {@link OpenJPAConfiguration#OPTION_INC_FLUSH} option in * {@link #getUnsupportedOptions}, this will be called only once at the * end of a transaction. Otherwise, it may be called periodically * throughout the course of a transaction. * If this store manager supports optimistic transactions, datastore * version information should be updated during flush, and the state * manager's version indicator should be updated through the * {@link OpenJPAStateManager#setNextVersion} method. * This method will only be invoked if there are meaningful changes * to store. This differs from the behavior of {@link StoreManager#flush}, * which may be invoked with a collection of objects in states that * do not require any datastore action (for example, objects in the * transient-transactional state). * * @param pNew Objects that should be added to the store, * and that have not previously been flushed. * @param pNewUpdated New objects that have been modified since * they were initially flushed. These were * in persistentNew in an earlier flush invocation. * @param pNewFlushedDeleted New objects that have been deleted since * they were initially flushed. These were * in persistentNew in an earlier flush invocation. * @param pDirty Objects that were loaded from the data * store and have since been modified. * @param pDeleted Objects that were loaded from the data * store and have since been deleted. These * may have been in a previous flush invocation's persistentDirty list. * @return a collection of exceptions encountered during flushing. */ protected abstract Collection flush(Collection pNew, Collection pNewUpdated, Collection pNewFlushedDeleted, Collection pDirty, Collection pDeleted); /** * Return a new configuration instance for this runtime. Configuration * data is maintained at the factory level and is available to all OpenJPA * components; therefore it is a good place to maintain shared resources * such as connection pools, etc. */ protected OpenJPAConfiguration newConfiguration() { return new OpenJPAConfigurationImpl(); } /** * Returns a set of option names that this store manager does * not support. By default, returns the following: *
      *
    • {@link OpenJPAConfiguration#OPTION_OPTIMISTIC}
    • *
    • {@link OpenJPAConfiguration#OPTION_ID_DATASTORE}
    • *
    • {@link OpenJPAConfiguration#OPTION_INC_FLUSH}
    • *
    • {@link OpenJPAConfiguration#OPTION_VALUE_AUTOASSIGN}
    • *
    • {@link OpenJPAConfiguration#OPTION_VALUE_INCREMENT}
    • *
    • {@link OpenJPAConfiguration#OPTION_DATASTORE_CONNECTION}
    • *
    */ protected Collection getUnsupportedOptions() { Collection c = new HashSet(); c.add(OpenJPAConfiguration.OPTION_OPTIMISTIC); c.add(OpenJPAConfiguration.OPTION_ID_DATASTORE); c.add(OpenJPAConfiguration.OPTION_INC_FLUSH); c.add(OpenJPAConfiguration.OPTION_VALUE_AUTOASSIGN); c.add(OpenJPAConfiguration.OPTION_VALUE_INCREMENT); c.add(OpenJPAConfiguration.OPTION_DATASTORE_CONNECTION); return c; } /** * Returns a string name to identify the platform of this * store manager. Returns the class name of this store manager by default. */ protected String getPlatform () { return getClass ().getName (); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/0000755000000000000000000000000012133327272024144 5ustar ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/ValidationException.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/ValidationException.ja0000644000000000000000000000224612133327272030435 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.validation; import org.apache.openjpa.util.WrappedException; @SuppressWarnings("serial") public class ValidationException extends WrappedException { public ValidationException(RuntimeException e) { super(e); } public ValidationException(RuntimeException e, boolean fatal) { super(e); setFatal(fatal); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/ValidatingLifecycleEventManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/ValidatingLifecycleEve0000644000000000000000000001301612133327272030432 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.validation; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.event.LifecycleEvent; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.meta.ClassMetaData; /** * An extension of LifecycleEventManager which adds validation capabilities for * specific lifecycle events. Validation occurs after firing all lifecycle * events and callbacks. * */ @SuppressWarnings("serial") public class ValidatingLifecycleEventManager extends LifecycleEventManager implements Configurable { private OpenJPAConfiguration _conf = null; private Validator _validator = null; protected boolean _validationEnabled = true; /** * Constructor which accepts a reference to the validator to use. If null, * no validation will occur. * @param validator */ public ValidatingLifecycleEventManager() { super(); } /* (non-Javadoc) * @see org.apache.openjpa.lib.conf.Configurable#endConfiguration() */ public void endConfiguration() { _validator = (Validator)_conf.getValidatorInstance(); } /* (non-Javadoc) * @see org.apache.openjpa.lib.conf.Configurable#setConfiguration( * org.apache.openjpa.lib.conf.Configuration) */ public void setConfiguration(Configuration conf) { if (conf instanceof OpenJPAConfiguration) { _conf = (OpenJPAConfiguration)conf; } } /* (non-Javadoc) * @see org.apache.openjpa.lib.conf.Configurable#startConfiguration() */ public void startConfiguration() { } @Override public boolean hasUpdateListeners(Object source, ClassMetaData meta) { if (_validator == null) { return super.hasUpdateListeners(source, meta); } return _validator.validating(source, LifecycleEvent.BEFORE_UPDATE) || super.hasUpdateListeners(source, meta); } @Override public boolean hasPersistListeners(Object source, ClassMetaData meta) { if (_validator == null) { return super.hasPersistListeners(source, meta); } return _validator.validating(source, LifecycleEvent.BEFORE_PERSIST) || super.hasPersistListeners(source, meta); } @Override public boolean hasDeleteListeners(Object source, ClassMetaData meta) { if (_validator == null) { return super.hasDeleteListeners(source, meta); } return _validator.validating(source, LifecycleEvent.BEFORE_DELETE) || super.hasDeleteListeners(source, meta); } @Override public Exception[] fireEvent(Object source, ClassMetaData meta, int type) { return fireEvent(source, null, meta, type); } @Override public Exception[] fireEvent(Object source, Object related, ClassMetaData meta, int type) { // Fire all pre-validation events and handlers. Exception[] evx = super.fireEvent(source, related, meta, type); // If there are exceptions and the event manager is marked fail fast // do not validate if (evx != null && evx.length > 0 && isFailFast()) return evx; // If a validator is provided and the source object should be validated, // validate it and return any exceptions if (_validationEnabled && _validator != null && _validator.validating(source, type)) { ValidationException vex = _validator.validate(source, type); if (vex != null) { if (evx == null || evx.length == 0) { evx = new Exception[1]; evx[0] = vex; } else { // resize the exception array and add the validation // exception Exception[] vevx = new Exception[evx.length +1]; System.arraycopy(vevx, 0, evx, 0, evx.length); vevx[evx.length+1] = vex; evx = vevx; } } } return evx; } /** * Whether this LifeCycleEventManager has had at least one listener or callback * registered. Used for a quick test when firing events. * @return boolean */ @Override public boolean isActive(ClassMetaData meta) { return isValidationEnabled() || super.isActive(meta); } public boolean isValidationEnabled() { return _validationEnabled; } public boolean setValidationEnabled(boolean enabled) { boolean val = _validationEnabled; _validationEnabled = enabled; return val; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/Validator.java0000644000000000000000000000530012133327272026732 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.validation; /** * Basic validation interface which defines the contract for * event based validation. Event values are defined in LifeCycleEvent. */ public interface Validator { /** * Validates a given instance * * @param The instance to validate * @param arg0 The class, of type T to validate * @param event The event id * @return ValidationException if the validator produces one or more * constraint violations. */ public ValidationException validate(T arg0, int event); /** * Validates a property of a given instance * * @param The instance to validate * @param arg0 The class, of type T to validate * @param property The property to validate * @param event The event id * @return ValidationException if the validator produces one or more * constraint violations. */ public ValidationException validateProperty(T arg0, String property, int event); /** * Validates a value based upon the constraints applied to a given class * attribute. * @param The instance type to base validation upon * @param arg0 The class of type T to validate * @param arg1 The property to validate * @param arg2 The property value to validate * @param event The event id * @return ValidationException if the validator produces one or more * constraint violations. */ public ValidationException validateValue(Class arg0, String arg1, Object arg2, int event); /** * Method for determining whether validation is active for the given * type and event. * * @param * @param arg0 Type being validated * @param event event type * @return true if validation is active for the specified event */ public boolean validating(T arg0, int event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/AbstractValidator.java0000644000000000000000000000255012133327272030422 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.validation; /** * Abstract validation class which provides base validation methods. */ public abstract class AbstractValidator implements Validator { public abstract ValidationException validate(T arg0, int event); public abstract ValidationException validateProperty(T arg0, String property, int event); public abstract ValidationException validateValue(Class arg0, String arg1, Object arg2, int event); public boolean validating(T arg0, int event) { return false; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/ValidationUnavailableException.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/validation/ValidationUnavailableE0000644000000000000000000000262112133327272030433 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.validation; import org.apache.openjpa.util.OpenJPAException; @SuppressWarnings("serial") public class ValidationUnavailableException extends OpenJPAException { public ValidationUnavailableException(String msg) { super(msg); } public ValidationUnavailableException(String msg, RuntimeException e) { super(msg, e); } public ValidationUnavailableException(String msg, RuntimeException e, boolean fatal) { super(msg, e); setFatal(fatal); } @Override public int getType() { return UNAVAILABLE; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/0000755000000000000000000000000012133327272025255 5ustar ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/DataCacheInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/DataCacheInstrume0000644000000000000000000001001012133327272030514 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation; import java.util.Date; import java.util.Map; import org.apache.openjpa.datacache.CacheStatistics; import org.apache.openjpa.datacache.DataCacheManager; /** * Interface for providing instrumented data cache metrics and operations. */ public interface DataCacheInstrument { /** * Gets number of total read requests for the given class since last reset. */ public long getReadCount(String className); /** * Gets number of total read requests that has been found in cache for the given class since last reset. */ public long getHitCount(String className); /** * Gets number of total write requests for the given class since last reset. */ public long getWriteCount(String className); /** * Gets number of total read requests for the given class since start. */ public long getTotalReadCount(String className); /** * Gets number of total read requests that has been found in cache for the given class since start. */ public long getTotalHitCount(String className); /** * Gets number of total write requests for the given class since start. */ public long getTotalWriteCount(String className); /** * Returns the name of the cache */ public String getCacheName(); /** * Returns the hit count since cache statistics were last reset */ public long getHitCount(); /** * Returns the read count since cache statistics were last reset */ public long getReadCount(); /** * Returns the total hits since start. */ public long getTotalHitCount(); /** * Returns the total reads since start. */ public long getTotalReadCount(); /** * Returns the total writes since start. */ public long getTotalWriteCount(); /** * Returns the write count since cache statistics were last reset */ public long getWriteCount(); /** * Resets cache statistics */ public void reset(); /** * Returns date since cache statistics collection were last reset. */ public Date sinceDate(); /** * Returns date cache statistics collection started. */ public Date startDate(); /** * Returns the names of classes that are known to the cache and whether or not they are currently being cached. */ public Map listKnownTypes(); /** * Returns true if cache statistics are currently being calculated. False otherwise. */ public Boolean getStatisticsEnabled(); /** * * @param enable - If true, the cache will start collecting statistics. Else cache statistics will not be collected. */ public void collectStatistics(boolean enable); /** * This method is used to enable/disable caching for the specified className. */ public void cache(String className, boolean enable); /** * Returns the CacheStatistics for the cache. * The format for this map is: * Type(String) => Enabled(Boolean),Read(Long),Hit(Long),Write(Long) */ public Map getCacheStatistics(); /** * Clears all data from the DataCache. */ public void clear(); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/InstrumentationManagerImpl.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/InstrumentationMa0000644000000000000000000000674712133327272030677 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.conf.PluginListValue; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.instrumentation.InstrumentationProvider; /** * An implementation of an instrumentation manager. */ public class InstrumentationManagerImpl implements InstrumentationManager { public Set _providers = Collections.synchronizedSet(new HashSet()); private boolean _closed = false; /** * Initializes all providers defined for the specified configuration. * @param conf * @param providers */ public void initialize(OpenJPAConfiguration conf, PluginListValue pluginVal) { InstrumentationProvider[] providers = (InstrumentationProvider[])pluginVal.instantiate(InstrumentationProvider.class, conf); _providers.addAll(Arrays.asList(providers)); } /** * Make a provider managed. This will bind its instrumentation to * InstrumentationLevel type events (factory create/close, broker create/close). * @param provider * @param config */ public void manageProvider(InstrumentationProvider provider) { _providers.add(provider); } /** * Returns all providers as an unmodifiable set */ public Set getProviders() { return Collections.unmodifiableSet(_providers); } /** * Starts all providers at a specific level and context */ public void start(InstrumentationLevel level, Object context) { if (_providers == null || _providers.size() == 0) { return; } for (InstrumentationProvider provider : _providers) { if (!provider.isStarted()) { provider.start(); } provider.startInstruments(level, context); } } /** * Stops all providers at a specific level and context */ public void stop(InstrumentationLevel level, Object context) { if (_providers == null || _providers.size() == 0) { return; } for (InstrumentationProvider provider : _providers) { provider.stopInstruments(level, context); } } /** * Stops all providers */ public void close() throws Exception { if (_closed) { return; } for (InstrumentationProvider provider : _providers) { provider.stop(); } _closed = true; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/QueryCacheInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/QueryCacheInstrum0000644000000000000000000000605212133327272030616 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation; import java.util.Date; import java.util.Set; /** * Interface for providing instrumented data cache metrics and operations. */ public interface QueryCacheInstrument { /** * Returns number of total exec requests since start. */ public long getTotalExecutionCount(); /** * Returns number of total exec requests since start for * the specified string-ified query key. */ public long getTotalExecutionCount(String queryKey); /** * Returns number of total execution requests since last reset */ public long getExecutionCount(); /** * Returns number of total execution requests since last reset for * the specified string-ified query key. */ public long getExecutionCount(String queryKey); /** * Returns number of total read requests that have been found in cache since * last reset. */ public long getHitCount(); /** * Returns number of total read requests that have been found in cache since * last reset for the specified string-ified query key. */ public long getHitCount(String queryKey); /** * Returns number of total read requests that has been found since start. */ public long getTotalHitCount(); /** * Returns number of total read requests that has been found since start for * the specified string-ified query key. */ public long getTotalHitCount(String queryKey); /** * Resets cache statistics */ public void reset(); /** * Returns date since cache statistics collection were last reset. */ public Date sinceDate(); /** * Returns date cache statistics collection started. */ public Date startDate(); /** * Returns all the string-ified keys for query results in the cache. * @return */ public Set queryKeys(); /** * Returns number of total evictions since last reset */ public long getEvictionCount(); /** * Returns number of total eviction requests since start. */ public long getTotalEvictionCount(); /** * Returns the number of total entries in the cache. * @return entries */ public long count(); } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractQueryCacheInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractQueryCach0000644000000000000000000001454012133327272030554 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.apache.openjpa.datacache.AbstractQueryCache; import org.apache.openjpa.datacache.QueryCache; import org.apache.openjpa.datacache.QueryKey; import org.apache.openjpa.kernel.QueryStatistics; import org.apache.openjpa.lib.instrumentation.AbstractInstrument; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; /** * Provides a basic instrument implementation wrapper for the query cache. This * class can be extended to create a provider specific instrument for the * query cache. */ public abstract class AbstractQueryCacheInstrument extends AbstractInstrument implements QueryCacheInstrument { /** * Value indicating that cache statistics are not available. */ public static final long NO_STATS = -1; private QueryCache _qc; private String _configId = null; private String _configRef = null; public void setQueryCache(QueryCache qc) { _qc = qc; } public void setConfigId(String cid) { _configId = cid; } public void setContextRef(String cref) { _configRef = cref; } public String getConfigId() { return _configId; } public String getContextRef() { return _configRef; } public void setPreparedQueryCache(QueryCache qc) { _qc = qc; } private QueryStatistics getStatistics() { if (_qc == null) return null; return _qc.getStatistics(); } public long getExecutionCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getExecutionCount(); return NO_STATS; } public long getExecutionCount(String queryKey) { QueryStatistics stats = getStatistics(); if (stats != null) { QueryKey qk = findKey(queryKey); return stats.getExecutionCount(qk); } return NO_STATS; } public long getTotalExecutionCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getTotalExecutionCount(); return NO_STATS; } public long getTotalExecutionCount(String queryKey) { QueryStatistics stats = getStatistics(); if (stats != null) { QueryKey qk = findKey(queryKey); return stats.getTotalExecutionCount(qk); } return NO_STATS; } public long getHitCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getHitCount(); return NO_STATS; } public long getHitCount(String queryKey) { QueryStatistics stats = getStatistics(); if (stats != null) { QueryKey qk = findKey(queryKey); return stats.getHitCount(qk); } return NO_STATS; } public long getTotalHitCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getTotalHitCount(); return NO_STATS; } public long getTotalHitCount(String queryKey) { QueryStatistics stats = getStatistics(); if (stats != null) { QueryKey qk = findKey(queryKey); return stats.getTotalHitCount(qk); } return NO_STATS; } public void reset() { QueryStatistics stats = getStatistics(); if (stats != null) stats.reset(); } public Date sinceDate() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.since(); return null; } public Date startDate() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.start(); return null; } /** * Returns number of total evictions since last reset */ public long getEvictionCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getEvictionCount(); return NO_STATS; } /** * Returns number of total eviction requests since start. */ public long getTotalEvictionCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getTotalEvictionCount(); return NO_STATS; } /** * Returns all query keys currently tracked in the cache. * @return */ public Set queryKeys() { QueryStatistics stats = getStatistics(); if (stats != null) { Set keys = new HashSet(); for (QueryKey qk : stats.keys()) { keys.add(qk.toString()); } return keys; } return null; } private QueryKey findKey(String key) { QueryStatistics stats = getStatistics(); for (QueryKey qk : stats.keys()) { if (qk.toString().equals(key)) { return qk; } } return null; } public long count() { if (_qc == null) { return NO_STATS; } if (_qc instanceof AbstractQueryCache) { AbstractQueryCache aqc = (AbstractQueryCache)_qc; return aqc.count(); } return NO_STATS; } public InstrumentationLevel getLevel() { return InstrumentationLevel.FACTORY; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/PreparedQueryCacheInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/PreparedQueryCach0000644000000000000000000000463712133327272030561 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation; import java.util.Date; import java.util.Set; public interface PreparedQueryCacheInstrument { /** * Returns number of total exec requests since start. */ public long getTotalExecutionCount(); /** * Returns number of total exec requests since start. */ public long getTotalExecutionCount(String query); /** * Returns number of total execution requests since last reset */ public long getExecutionCount(); /** * Returns number of total execution requests since last reset */ public long getExecutionCount(String query); /** * Returns number of total read requests that have been found in cache since * last reset. */ public long getHitCount(); /** * Returns number of total read requests that have been found in cache since * last reset. */ public long getHitCount(String query); /** * Returns number of total read requests that has been found since start. */ public long getTotalHitCount(); /** * Returns number of total read requests that has been found since start. */ public long getTotalHitCount(String query); /** * Resets cache statistics */ public void reset(); /** * Returns date since cache statistics collection were last reset. */ public Date sinceDate(); /** * Returns date cache statistics collection started. */ public Date startDate(); /** * Returns all queries currently tracked in the cache. * @return */ public Set queries(); } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/InstrumentationManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/InstrumentationMa0000644000000000000000000000543412133327272030667 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.conf.PluginListValue; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.instrumentation.InstrumentationProvider; import org.apache.openjpa.lib.util.Closeable; /** * Managers of instrumentation providers must implement this interface. It * provides methods for initializing multiple providers via configuration in * addition to managing instrumentation providers and the state of the providers. */ public interface InstrumentationManager extends Closeable { /** * Used to initialize one or more providers using the supplied configuration. * @param conf the configuration to use for initialization * @param providers one or more providers as supplied via plugin list value */ public void initialize(OpenJPAConfiguration conf, PluginListValue providers); /** * Manage a given provider. This will plug the instruments managed by the * the provider into the life cycle of the manager * @param provider the instrumentation provider */ public void manageProvider(InstrumentationProvider provider); /** * Starts all instruments for all managed providers for a given level * and context. * @param level instrumentation level * @param context instrumentation context (broker, factory, config,...) */ public void start(InstrumentationLevel level, Object context); /** * Stops all instruments for all managed providers for a given level * and context. * @param level instrumentation level * @param context instrumentation context (broker, factory, config,...) */ public void stop(InstrumentationLevel broker, Object context); /** * Returns all providers managed by this manager. * @return all providers managed by this manager */ public Set getProviders(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/0000755000000000000000000000000012133327272026053 5ustar ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/DataCacheJMXInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/DataCacheJMXI0000644000000000000000000000651612133327272030273 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation.jmx; import javax.management.ObjectName; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.datacache.DataCacheManager; import org.apache.openjpa.instrumentation.AbstractDataCacheInstrument; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.util.UserException; /** * A JMX-specific instrument for the data cache */ public class DataCacheJMXInstrument extends AbstractDataCacheInstrument implements JMXInstrument, DataCacheJMXInstrumentMBean { private static Localizer _loc = Localizer.forPackage(DataCacheJMXInstrument.class); private static final String MBEAN_TYPE = "DataCache"; private ObjectName _objName = null; @Override public String getName() { return MBEAN_TYPE; } @Override public InstrumentationLevel getLevel() { return InstrumentationLevel.FACTORY; } @Override public void initialize() { Options opts = new Options(); if (getOptions() != null) { opts = Configurations.parseProperties(getOptions()); } String cacheName = opts.getProperty("name",null); OpenJPAConfiguration conf = (OpenJPAConfiguration)getProvider().getConfiguration(); DataCacheManager dcm = conf.getDataCacheManagerInstance(); DataCache dc = null; if (cacheName == null || cacheName.trim().length() == 0) { dc = dcm.getSystemDataCache(); } else { dc = dcm.getDataCache(cacheName); } if (dc == null) { throw new UserException(_loc.get("data-cache-not-found")); } setDataCache(dc); setDataCacheManager(dcm); setConfigId(conf.getId()); setContextRef(Integer.toString(System.identityHashCode(getContext()))); } public ObjectName getObjectName() { if (_objName != null) { return _objName; } try { _objName = JMXProvider.createObjectName(this, null); return _objName; } catch (Throwable t) { throw new UserException(_loc.get("unable-to-create-object-name", getName()), t); } } public void start() { getProvider().startInstrument(this); } public void stop() { getProvider().stopInstrument(this); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/DataCacheJMXInstrumentMBean.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/DataCacheJMXI0000644000000000000000000000225712133327272030271 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation.jmx; import org.apache.openjpa.instrumentation.DataCacheInstrument; /** * Simple MBean interface for providing instrumented data cache metrics * and operations. * Note: Simple MBeans require an MBean interface matching the supplied * implementation class. */ public interface DataCacheJMXInstrumentMBean extends DataCacheInstrument { } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXProvider.j0000644000000000000000000001521612133327272030404 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation.jmx; import java.lang.management.ManagementFactory; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import org.apache.openjpa.lib.instrumentation.AbstractInstrumentationProvider; import org.apache.openjpa.lib.instrumentation.Instrument; import org.apache.openjpa.util.UserException; /** * A simple MBean JMX instrumentation provider */ public class JMXProvider extends AbstractInstrumentationProvider { // Aliases for built-in JMX Instrumentation public static final String[] JMX_INSTRUMENT_ALIASES = { "DataCache", "org.apache.openjpa.instrumentation.jmx.DataCacheJMXInstrument", "QueryCache", "org.apache.openjpa.instrumentation.jmx.QueryCacheJMXInstrument", "QuerySQLCache", "org.apache.openjpa.instrumentation.jmx.PreparedQueryCacheJMXInstrument" }; /** * The MBean domain for OpenJPA */ public static final String MBEAN_DOMAIN = "org.apache.openjpa"; private Set _mbs = null; /** * Register an MBean with the mbean server. * @param mBean */ protected void registerMBean(JMXInstrument mBean) { Set mbs = getMBeanServer(); try { for (MBeanServer s : mbs) { s.registerMBean(mBean, mBean.getObjectName()); } } catch (Exception e) { throw new RuntimeException(e); } } /** * Returns the mbean server * @return */ public Set getMBeanServer() { if (_mbs == null) { _mbs = new HashSet(); // Look in both of these static methods to find all MBServers. In some environments the server returned by // the getPlatformMBeanServer() call isn't the one used by the runtime. Might be over kill by calling both, // but it shouldn't hurt anything. _mbs.addAll(MBeanServerFactory.findMBeanServer(null)); _mbs.add(ManagementFactory.getPlatformMBeanServer()); } return _mbs; } @Override public void start() { Set mbs = getMBeanServer(); try { for (MBeanServer s : mbs) { if (mbs == null || mbs.size() == 0) { throw new UserException("jmx-server-failed-creation"); } } setStarted(true); } catch (Throwable t) { throw new UserException("jmx-server-unavailable", t); } } /** * Stops all instruments registered with this provider and releases the * reference to the Platform MBean server instance. */ @Override public void stop() { if (isStarted()) { Set instruments = getInstruments(); if (instruments != null && instruments.size() > 0) { for (Instrument inst : instruments) { stopInstrument(inst); } } // The MBean server factory does appear to ref count properly so the // platform server cannot released from the factory once it is acquired. // Multiple attempts to capture and release the server will result in a // runtime exception. // MBeanServerFactory.releaseMBeanServer(getMBeanServer()); // _mbs = null; setStarted(false); } } /** * Creates an object name for the supplied instrument and key properties * @param instrument the instrument * @param props additional key properties * @return the JMX object name * @throws Exception a generic JMX-type exception */ public static ObjectName createObjectName(JMXInstrument instrument, Map props) throws Exception { // Construct the base name StringBuilder sbName = new StringBuilder(MBEAN_DOMAIN); sbName.append(":type="); sbName.append(instrument.getName()); sbName.append(",cfgid="); sbName.append(instrument.getConfigId()); sbName.append(",cfgref="); sbName.append(instrument.getContextRef()); // Add any additional key properties that were provided if (props != null && !props.isEmpty()) { for (Entry prop : props.entrySet()) { sbName.append(","); sbName.append(prop.getKey()); sbName.append("="); sbName.append(prop.getValue()); } } return new ObjectName(sbName.toString()); } /** * Start an instrument. Registers an mbean with the server. */ public void startInstrument(Instrument instrument) { if (!instrument.isStarted()) { registerMBean((JMXInstrument)instrument); instrument.setStarted(true); } } /** * Stop an instrument. Unregisters an mbean with the server. */ public void stopInstrument(Instrument instrument, boolean force) { if (instrument.isStarted() || force) { Set mbs = getMBeanServer(); try { for (MBeanServer s : mbs) { s.unregisterMBean(((JMXInstrument) instrument).getObjectName()); } instrument.setStarted(false); } catch (Exception e) { // If force, swallow the exception since the bean may not even // be registered. if (!force) { throw new UserException("cannot-stop-instrument",e); } } } } /** * Returns aliases for built-in instruments. */ @Override public String[] getInstrumentAliases() { return JMX_INSTRUMENT_ALIASES; } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/QueryCacheJMXInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/QueryCacheJMX0000644000000000000000000000557212133327272030417 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation.jmx; import javax.management.ObjectName; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.datacache.DataCacheManager; import org.apache.openjpa.datacache.QueryCache; import org.apache.openjpa.instrumentation.AbstractQueryCacheInstrument; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * A JMX-specific instrument for the query cache */ public class QueryCacheJMXInstrument extends AbstractQueryCacheInstrument implements JMXInstrument, QueryCacheJMXInstrumentMBean { private static Localizer _loc = Localizer.forPackage(QueryCacheJMXInstrument.class); private static final String MBEAN_TYPE = "QueryCache"; private ObjectName _objName = null; @Override public String getName() { return MBEAN_TYPE; } @Override public InstrumentationLevel getLevel() { return InstrumentationLevel.FACTORY; } @Override public void initialize() { OpenJPAConfiguration conf = (OpenJPAConfiguration)getProvider().getConfiguration(); DataCacheManager dcm = conf.getDataCacheManagerInstance(); QueryCache qc = dcm.getSystemQueryCache(); if (qc == null) { throw new UserException(_loc.get("query-cache-not-found")); } setQueryCache(qc); setConfigId(conf.getId()); setContextRef(Integer.toString(System.identityHashCode(getContext()))); } public ObjectName getObjectName() { if (_objName != null) { return _objName; } try { _objName = JMXProvider.createObjectName(this, null); return _objName; } catch (Throwable t) { throw new UserException(_loc.get("unable-to-create-object-name", getName()), t); } } public void start() { getProvider().startInstrument(this); } public void stop() { getProvider().stopInstrument(this); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXInstrument0000644000000000000000000000405312133327272030527 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation.jmx; import javax.management.ObjectName; import org.apache.openjpa.lib.instrumentation.Instrument; /** * Interface for JMX-specific instruments */ public interface JMXInstrument extends Instrument { /** * Returns the JMX object name for the instrument * @return */ public ObjectName getObjectName(); /** * Sets the context reference for the instrument. Required to register * the instrument under a unique id. * @param cref the context reference for the instrument */ public void setContextRef(String cref); /** * Gets the context reference for the instrument. Required to register * the instrument under a unique id. * @param cref the context reference for the instrument */ public String getContextRef(); /** * Sets the config id for the instrument. Required to register * the instrument under a unique id. * @return the config id of the instrument */ public String getConfigId(); /** * Gets the config id for the instrument. Required to register * the instrument under a unique id. * @param cid the config id of the instrument */ public void setConfigId(String cid); } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/QueryCacheJMXInstrumentMBean.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/QueryCacheJMX0000644000000000000000000000226312133327272030411 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation.jmx; import org.apache.openjpa.instrumentation.QueryCacheInstrument; /** * Simple MBean interface for providing instrumented query cache metrics * and operations. * Note: Simple MBeans require an MBean interface matching the supplied * implementation class. */ public interface QueryCacheJMXInstrumentMBean extends QueryCacheInstrument { } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/PreparedQueryCacheJMXInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/PreparedQuery0000644000000000000000000000552412133327272030574 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation.jmx; import javax.management.ObjectName; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.instrumentation.AbstractPreparedQueryCacheInstrument; import org.apache.openjpa.kernel.PreparedQueryCache; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * A JMX-specific instrument for the query cache */ public class PreparedQueryCacheJMXInstrument extends AbstractPreparedQueryCacheInstrument implements JMXInstrument, PreparedQueryCacheJMXInstrumentMBean { private static Localizer _loc = Localizer.forPackage(PreparedQueryCacheJMXInstrument.class); private static final String MBEAN_TYPE = "QuerySQLCache"; private ObjectName _objName = null; @Override public String getName() { return MBEAN_TYPE; } @Override public InstrumentationLevel getLevel() { return InstrumentationLevel.FACTORY; } @Override public void initialize() { OpenJPAConfiguration conf = (OpenJPAConfiguration)getProvider().getConfiguration(); PreparedQueryCache pqc = conf.getQuerySQLCacheInstance(); if (pqc == null) { throw new UserException(_loc.get("prep-query-cache-not-found")); } setPreparedQueryCache(pqc); setConfigId(conf.getId()); setContextRef(Integer.toString(System.identityHashCode(getContext()))); } public ObjectName getObjectName() { if (_objName != null) { return _objName; } try { _objName = JMXProvider.createObjectName(this, null); return _objName; } catch (Throwable t) { throw new UserException(_loc.get("unable-to-create-object-name", getName()), t); } } public void start() { getProvider().startInstrument(this); } public void stop() { getProvider().stopInstrument(this); } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/PreparedQueryCacheJMXInstrumentMBean.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/PreparedQuery0000644000000000000000000000201012133327272030557 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation.jmx; import org.apache.openjpa.instrumentation.PreparedQueryCacheInstrument; public interface PreparedQueryCacheJMXInstrumentMBean extends PreparedQueryCacheInstrument { } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractPreparedQueryCacheInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractPreparedQ0000644000000000000000000001103712133327272030551 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation; import java.util.Date; import java.util.Set; import org.apache.openjpa.kernel.PreparedQueryCache; import org.apache.openjpa.kernel.QueryStatistics; import org.apache.openjpa.lib.instrumentation.AbstractInstrument; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; /** * Provides a basic instrument implementation wrapper for the prepared query cache. This * class can be extended to create a provider specific instrument for the * prepared query cache. */ public abstract class AbstractPreparedQueryCacheInstrument extends AbstractInstrument implements PreparedQueryCacheInstrument { public static final long NO_STATS = -1; private PreparedQueryCache _qc; private String _configID = null; private String _configRef = null; public void setConfigId(String cid) { _configID = cid; } public void setContextRef(String cref) { _configRef = cref; } public String getConfigId() { return _configID; } public String getContextRef() { return _configRef; } public void setPreparedQueryCache(PreparedQueryCache qc) { _qc = qc; } private QueryStatistics getStatistics() { if (_qc == null) return null; return _qc.getStatistics(); } public long getExecutionCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getExecutionCount(); return NO_STATS; } public long getExecutionCount(String query) { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getExecutionCount(query); return NO_STATS; } public long getTotalExecutionCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getTotalExecutionCount(); return NO_STATS; } public long getTotalExecutionCount(String query) { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getTotalExecutionCount(query); return NO_STATS; } public long getHitCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getHitCount(); return NO_STATS; } public long getHitCount(String query) { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getHitCount(query); return NO_STATS; } public long getTotalHitCount() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getTotalHitCount(); return NO_STATS; } public long getTotalHitCount(String query) { QueryStatistics stats = getStatistics(); if (stats != null) return stats.getTotalHitCount(query); return NO_STATS; } public void reset() { QueryStatistics stats = getStatistics(); if (stats != null) stats.reset(); } public Date sinceDate() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.since(); return null; } public Date startDate() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.start(); return null; } public Set queries() { QueryStatistics stats = getStatistics(); if (stats != null) return stats.keys(); return null; } public InstrumentationLevel getLevel() { return InstrumentationLevel.FACTORY; } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractDataCacheInstrument.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractDataCache0000644000000000000000000001441512133327272030466 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.instrumentation; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.openjpa.datacache.CacheStatistics; import org.apache.openjpa.datacache.CacheStatisticsSPI; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.datacache.DataCacheManager; import org.apache.openjpa.datacache.DataCacheManagerImpl; import org.apache.openjpa.lib.instrumentation.AbstractInstrument; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; /** * Provides a basic instrument implementation wrapper for the data cache. This class can be extended to create a * provider specific instrument for the data cache. */ public abstract class AbstractDataCacheInstrument extends AbstractInstrument implements DataCacheInstrument { /** * Value indicating that cache statistics are not available. */ public static final long NO_STATS = -1; private DataCacheManager _dcm = null; private DataCache _dc = null; private String _configID = null; private String _configRef = null; public void setDataCache(DataCache dc) { _dc = dc; } public void setDataCacheManager(DataCacheManager dcm) { _dcm = dcm; } public void setConfigId(String cid) { _configID = cid; } public void setContextRef(String cref) { _configRef = cref; } public long getHitCount() { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getHitCount(); return NO_STATS; } public long getReadCount() { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getReadCount(); return NO_STATS; } public long getTotalHitCount() { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getTotalHitCount(); return NO_STATS; } public long getTotalReadCount() { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getTotalReadCount(); return NO_STATS; } public long getTotalWriteCount() { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getTotalWriteCount(); return NO_STATS; } public long getWriteCount() { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getWriteCount(); return NO_STATS; } public void reset() { CacheStatistics stats = getStatistics(); if (stats != null) stats.reset(); } public Date sinceDate() { CacheStatistics stats = getStatistics(); if (stats != null) return stats.since(); return null; } public Date startDate() { CacheStatistics stats = getStatistics(); if (stats != null) return stats.start(); return null; } public String getConfigId() { return _configID; } public String getContextRef() { return _configRef; } public String getCacheName() { if (_dc != null) return _dc.getName(); return null; } private CacheStatistics getStatistics() { if (_dc != null) { return _dc.getStatistics(); } return null; } public long getWriteCount(String c) { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getWriteCount(c); return NO_STATS; } public long getTotalWriteCount(String c) { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getTotalWriteCount(c); return NO_STATS; } public long getTotalReadCount(String c) { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getTotalReadCount(c); return NO_STATS; } public long getTotalHitCount(String c) { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getTotalHitCount(c); return NO_STATS; } public long getReadCount(String c) { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getReadCount(c); return NO_STATS; } public long getHitCount(String c) { CacheStatistics stats = getStatistics(); if (stats != null) return stats.getHitCount(c); return NO_STATS; } public InstrumentationLevel getLevel() { return InstrumentationLevel.FACTORY; } public void cache(String className, boolean enable) { if (enable) { _dcm.startCaching(className); } else { _dcm.stopCaching(className); } } public Map listKnownTypes() { return _dcm.listKnownTypes(); } public void collectStatistics(boolean enable) { CacheStatisticsSPI stats = (CacheStatisticsSPI) _dc.getStatistics(); if (enable) { stats.enable(); } else { stats.disable(); } } public Boolean getStatisticsEnabled() { CacheStatisticsSPI stats = (CacheStatisticsSPI) _dc.getStatistics(); return stats.isEnabled(); } public Map getCacheStatistics() { return _dc.getStatistics().toMap(); } public void clear() { _dc.clear(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ant/0000755000000000000000000000000012133327272022574 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ant/ApplicationIdToolTask.java0000755000000000000000000000655012133327272027651 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ant; import java.io.IOException; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.enhance.ApplicationIdTool; import org.apache.openjpa.lib.ant.AbstractTask; import org.apache.openjpa.lib.conf.ConfigurationImpl; import org.apache.openjpa.lib.util.CodeFormat; import org.apache.openjpa.lib.util.Files; /** *

    Executes the application id tool on the specified files. This task * can take the following arguments: *

      *
    • directory
    • *
    • ignoreErrors
    • *
    • name
    • *
    • suffix
    • *
    • token
    • *
    * It can also take an embedded codeFormat element with attributes * for the bean properties of the {@link CodeFormat}.

    */ public class ApplicationIdToolTask extends AbstractTask { protected ApplicationIdTool.Flags flags = new ApplicationIdTool.Flags(); protected String dirName = null; /** * Default constructor. */ public ApplicationIdToolTask() { flags.format = new CodeFormat(); } /** * Set the output directory we want the enhancer to write to. */ public void setDirectory(String dirName) { this.dirName = dirName; } /** * Set whether to ignore errors. */ public void setIgnoreErrors(boolean ignoreErrors) { flags.ignoreErrors = ignoreErrors; } /** * Set the name of the identity class; with this option you must supply * exactly one class to run on. */ public void setName(String name) { flags.name = name; } /** * Set a suffix to append to persistent classes to form their identity * class name. */ public void setSuffix(String suffix) { flags.suffix = suffix; } /** * Set the token to separate stringified primary key field values. */ public void setToken(String token) { flags.token = token; } /** * Create the embedded code format element. */ public Object createCodeFormat() { return flags.format; } protected ConfigurationImpl newConfiguration() { return new OpenJPAConfigurationImpl(); } protected void executeOn(String[] files) throws IOException, ClassNotFoundException { flags.directory = (dirName == null) ? null : Files.getFile(dirName, getClassLoader()); ApplicationIdTool.run((OpenJPAConfiguration) getConfiguration(), files, flags, getClassLoader ()); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ant/package.html0000644000000000000000000000160012133327272025052 0ustar

    OpenJPA Ant Tasks

    Ant tasks for OpenJPA tools.

    openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ant/PCEnhancerTask.java0000644000000000000000000000615012133327272026232 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ant; import java.io.IOException; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.enhance.PCEnhancer; import org.apache.openjpa.lib.ant.AbstractTask; import org.apache.openjpa.lib.conf.ConfigurationImpl; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.meta.MetaDataRepository; /** * Executes the enhancer on the specified files. This task can take * the following arguments: *
      *
    • directory
    • *
    • addDefaultConstructor
    • *
    • tmpClassLoader
    • *
    • enforcePropertyRestrictions
    • *
    */ public class PCEnhancerTask extends AbstractTask { protected PCEnhancer.Flags flags = new PCEnhancer.Flags(); protected String dirName = null; /** * Set the output directory we want the enhancer to write to. */ public void setDirectory(String dirName) { this.dirName = dirName; } /** * Set whether or not the enhancer should add a no-args constructor * to any PC that does not have a no-args constructor. */ public void setAddDefaultConstructor(boolean addDefCons) { flags.addDefaultConstructor = addDefCons; } /** * Set whether to fail if the persistent type uses property access and * bytecode analysis shows that it may be violating OpenJPA's property * access restrictions. */ public void setEnforcePropertyRestrictions(boolean fail) { flags.enforcePropertyRestrictions = fail; } /** * Set whether or not to use a default class loader for loading * the unenhanced classes. */ public void setTmpClassLoader(boolean tmpClassLoader) { flags.tmpClassLoader = tmpClassLoader; } protected ConfigurationImpl newConfiguration() { return new OpenJPAConfigurationImpl(); } protected void executeOn(String[] files) throws IOException { flags.directory = (dirName == null) ? null : Files.getFile(dirName, getClassLoader()); OpenJPAConfiguration conf = (OpenJPAConfiguration) getConfiguration(); MetaDataRepository repos = conf.newMetaDataRepositoryInstance(); PCEnhancer.run(conf, files, flags, repos, null, getClassLoader ()); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/ant/MetaDataToolTask.java0000644000000000000000000000560612133327272026607 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.ant; import java.io.IOException; import java.io.PrintWriter; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.EnumeratedAttribute; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfigurationImpl; import org.apache.openjpa.lib.ant.AbstractTask; import org.apache.openjpa.lib.conf.ConfigurationImpl; import org.apache.openjpa.lib.util.Files; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.MetaDataTool; /** * Executes the metadata tool on the specified files. This task can * take the following arguments: *
      *
    • file
    • *
    */ public class MetaDataToolTask extends AbstractTask { private static final Localizer _loc = Localizer.forPackage (MetaDataToolTask.class); protected MetaDataTool.Flags flags = new MetaDataTool.Flags(); protected String fileName = null; /** * Set the tool action. */ public void setAction(Action act) { flags.action = act.getValue(); } /** * Set the file to write the metadata to. */ public void setFile(String fileName) { this.fileName = fileName; } protected ConfigurationImpl newConfiguration() { return new OpenJPAConfigurationImpl(); } protected void executeOn(String[] files) throws IOException { ClassLoader loader = getClassLoader(); if ("stdout".equals(fileName)) flags.writer = new PrintWriter(System.out); else if ("stderr".equals(fileName)) flags.writer = new PrintWriter(System.err); else if (fileName != null) flags.file = Files.getFile(fileName, loader); if (!MetaDataTool.run((OpenJPAConfiguration) getConfiguration(), files, flags, null, loader)) throw new BuildException(_loc.get("bad-conf", "MetaDataToolTask") .getMessage()); } public static class Action extends EnumeratedAttribute { public String[] getValues() { return MetaDataTool.ACTIONS; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/0000755000000000000000000000000012133327272022737 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/package.html0000644000000000000000000000164412133327272025225 0ustar

    OpenJPA Configuration

    This package provides base OpenJPA configuration interfaces.

    openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAVersion.java0000644000000000000000000001161612133327272026411 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.io.File; import java.io.InputStream; import java.security.AccessController; import java.util.Properties; import java.util.StringTokenizer; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; /** * This class contains version information for OpenJPA. It uses * Ant's filter tokens to convert the template into a java * file with current information. * * @author Marc Prud'hommeaux, Patrick Linskey */ public class OpenJPAVersion { private static final Localizer _loc = Localizer.forPackage(OpenJPAVersion.class); public static final String VERSION_NUMBER; public static final String VERSION_ID; public static final String VENDOR_NAME = "OpenJPA"; public static final int MAJOR_RELEASE; public static final int MINOR_RELEASE; public static final int PATCH_RELEASE; public static final String RELEASE_STATUS; public static final String REVISION_NUMBER; static { Properties revisionProps = new Properties(); try { InputStream in = OpenJPAVersion.class.getResourceAsStream ("/META-INF/org.apache.openjpa.revision.properties"); if (in != null) { try { revisionProps.load(in); } finally { in.close(); } } } catch (Exception e) { } String vers = revisionProps.getProperty("openjpa.version"); if (vers == null || "".equals(vers.trim())) vers = "0.0.0"; VERSION_NUMBER = vers; StringTokenizer tok = new StringTokenizer(VERSION_NUMBER, ".-"); int major, minor, patch; try { major = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0; } catch (Exception e) { major = 0; } try { minor = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0; } catch (Exception e) { minor = 0; } try { patch = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0; } catch (Exception e) { patch = 0; } String revision = revisionProps.getProperty("revision.number"); MAJOR_RELEASE = major; MINOR_RELEASE = minor; PATCH_RELEASE = patch; RELEASE_STATUS = tok.hasMoreTokens() ? tok.nextToken("!") : ""; REVISION_NUMBER = revision; VERSION_ID = "openjpa-" + VERSION_NUMBER + "-r" + REVISION_NUMBER; } public static void main(String [] args) { System.out.println(new OpenJPAVersion().toString()); } public String toString() { StringBuilder buf = new StringBuilder(80 * 40); appendOpenJPABanner(buf); buf.append("\n"); appendProperty("os.name", buf).append("\n"); appendProperty("os.version", buf).append("\n"); appendProperty("os.arch", buf).append("\n\n"); appendProperty("java.version", buf).append("\n"); appendProperty("java.vendor", buf).append("\n\n"); buf.append("java.class.path:\n"); StringTokenizer tok = new StringTokenizer(AccessController.doPrivileged(J2DoPrivHelper .getPropertyAction("java.class.path")), File.pathSeparator); while (tok.hasMoreTokens()) { buf.append("\t").append(tok.nextToken()); buf.append("\n"); } buf.append("\n"); appendProperty("user.dir", buf); return buf.toString(); } public void appendOpenJPABanner(StringBuilder buf) { buf.append(VENDOR_NAME).append(" "); buf.append(VERSION_NUMBER); buf.append("\n"); buf.append(_loc.get("version-id")).append(": ").append(VERSION_ID); buf.append("\n"); buf.append(_loc.get("openjpa-revision")).append(": ").append(REVISION_NUMBER); buf.append("\n"); } private StringBuilder appendProperty(String prop, StringBuilder buf) { return buf.append(prop).append(": ").append( AccessController.doPrivileged(J2DoPrivHelper .getPropertyAction(prop))); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java0000644000000000000000000000476612133327272030374 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.util.Map; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.conf.PluginValue; import org.apache.openjpa.conf.CacheMarshallersValue; import org.apache.openjpa.meta.MetaDataRepository; /** * A {@link PluginValue} that interacts with the {@link CacheMarshaller} * to cache the metadata repository between executions. * * @since 1.1.0 */ public class MetaDataRepositoryValue extends PluginValue { private static final String KEY = "MetaDataRepository"; public MetaDataRepositoryValue() { super(KEY, false); String[] aliases = new String[] { "default", MetaDataRepository.class.getName() }; setAliases(aliases); setDefault(aliases[0]); setString(aliases[0]); } public Object instantiate(Class type, Configuration c, boolean fatal) { MetaDataRepository repos = null; OpenJPAConfiguration conf = (OpenJPAConfiguration) c; Object[] os = (Object[]) CacheMarshallersValue.getMarshallerById( conf, MetaDataCacheMaintenance.class.getName()) .load(); if (os != null) { repos = (MetaDataRepository) os[0]; if (os[1] != null) // It's a bit odd that we do this in MetaDataRepositoryValue. // We need to serialize all the various bits of configuration // together; maybe we can move the caching logic somewhere // else? conf.getQueryCompilationCacheInstance().putAll((Map) os[1]); } if (repos == null) return super.instantiate(type, c, fatal); else return repos; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/DetachOptions.java0000644000000000000000000001246712133327272026360 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import org.apache.openjpa.kernel.DetachState; /** * Detach options. * * @author Abe White * @nojavadoc */ public abstract class DetachOptions implements DetachState { private boolean _field = true; private boolean _transient = true; private boolean _manager = true; private boolean _access = true; private boolean _liteAutoDetach = false; private boolean _detachProxyFields = true; /** * The {@link DetachState} constant. */ public abstract int getDetachState(); /** * Whether to add a detached state field to enhanced classes. */ public boolean getDetachedStateField() { return _field; } /** * Whether to add a detached state field to enhanced classes. */ public void setDetachedStateField(boolean val) { _field = val; if (!val) _manager = false; } /** * For auto-configuration of the detached state field. Accepts values * "true", "false", or "transient". */ public void setDetachedStateField(String val) { if (val == null) return; if ("transient".equals(val)) { setDetachedStateField(true); _transient = true; } else if ("true".equals(val)) { setDetachedStateField(true); _transient = false; } else if ("false".equals(val)) { setDetachedStateField(false); _transient = false; } else throw new IllegalArgumentException("DetachedStateField=" + val); } /** * Whether to use transient detached state. */ public boolean isDetachedStateTransient() { return _transient; } /** * Whether to use transient detached state. */ public void setDetachedStateTransient(boolean val) { _transient = val; } /** * Whether to use a detached state manager on types that allow it. * Types that do not use detached state or that declare a custom detached * state field to maintain serialization compatibility will never use * a detached state manager. Defaults to true. */ public boolean getDetachedStateManager() { return _manager; } /** * Whether to use a detached state manager on types that allow it. * Types that do not use detached state or that declare a custom detached * state field to maintain serialization compatibility will never use * a detached state manager. Defaults to true. */ public void setDetachedStateManager(boolean val) { _manager = val; } /** * Whether to allow access to unloaded detached fields. This setting only * applies to instances with detached state managers. */ public boolean getAccessUnloaded() { return _access; } /** * Whether to allow access to unloaded detached fields. This setting only * applies to instances with detached state managers. */ public void setAccessUnloaded(boolean val) { _access = val; } /** * Whether to use lite detachment when auto detaching. This setting only applies when * DetachState is set to loaded. */ public void setLiteAutoDetach(boolean b) { _liteAutoDetach = b; } /** * Whether to use lite detachment when auto detaching. This setting only applies when * DetachState is set to loaded. */ public boolean getLiteAutoDetach() { return (getDetachState() & DETACH_LOADED) == 1 && _liteAutoDetach; } /** * Whether to detach proxy fields. */ public void setDetachProxyFields(boolean b) { _detachProxyFields = b; } /** * Whether to detach proxy fields. */ public boolean getDetachProxyFields() { // This property can only be set to false when using lite auto detach. if(!_liteAutoDetach){ return true; } return _detachProxyFields; } /** * Detach loaded state. */ public static class Loaded extends DetachOptions { public int getDetachState() { return DETACH_LOADED; } } /** * Public to allow reflection. */ public static class FetchGroups extends DetachOptions { public int getDetachState() { return DETACH_FGS; } } /** * Public to allow reflection. */ public static class All extends DetachOptions { public int getDetachState() { return DETACH_ALL; } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.jav0000644000000000000000000020050112133327272030245 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.util.Collection; import java.util.HashSet; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.audit.AuditLogger; import org.apache.openjpa.audit.Auditor; import org.apache.openjpa.datacache.CacheDistributionPolicy; import org.apache.openjpa.datacache.ConcurrentDataCache; import org.apache.openjpa.datacache.ConcurrentQueryCache; import org.apache.openjpa.datacache.DataCacheManager; import org.apache.openjpa.datacache.DataCacheManagerImpl; import org.apache.openjpa.datacache.PartitionedDataCache; import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.enhance.RuntimeUnenhancedClassesModes; import org.apache.openjpa.event.BrokerFactoryEventManager; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.event.OrphanedKeyAction; import org.apache.openjpa.event.RemoteCommitEventManager; import org.apache.openjpa.event.RemoteCommitProvider; import org.apache.openjpa.instrumentation.InstrumentationManager; import org.apache.openjpa.instrumentation.InstrumentationManagerImpl; import org.apache.openjpa.kernel.AutoClear; import org.apache.openjpa.kernel.BrokerImpl; import org.apache.openjpa.kernel.ConnectionRetainModes; import org.apache.openjpa.kernel.FinderCache; import org.apache.openjpa.kernel.InverseManager; import org.apache.openjpa.kernel.LockLevels; import org.apache.openjpa.kernel.LockManager; import org.apache.openjpa.kernel.PreparedQueryCache; import org.apache.openjpa.kernel.QueryFlushModes; import org.apache.openjpa.kernel.RestoreState; import org.apache.openjpa.kernel.SavepointManager; import org.apache.openjpa.kernel.Seq; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.lib.conf.BooleanValue; import org.apache.openjpa.lib.conf.ConfigurationImpl; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.conf.IntValue; import org.apache.openjpa.lib.conf.ObjectValue; import org.apache.openjpa.lib.conf.PluginListValue; import org.apache.openjpa.lib.conf.PluginValue; import org.apache.openjpa.lib.conf.ProductDerivations; import org.apache.openjpa.lib.conf.StringListValue; import org.apache.openjpa.lib.conf.StringValue; import org.apache.openjpa.lib.encryption.EncryptionProvider; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.instrumentation.InstrumentationProvider; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.meta.MetaDataFactory; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.ClassResolver; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.ProxyManager; import org.apache.openjpa.util.StoreFacadeTypeRegistry; import org.apache.openjpa.validation.ValidatingLifecycleEventManager; /** * Implementation of the {@link OpenJPAConfiguration} interface. * * @see ConfigurationImpl * @author Marc Prud'hommeaux * @author Abe White */ public class OpenJPAConfigurationImpl extends ConfigurationImpl implements OpenJPAConfiguration { // private static final Localizer _loc = Localizer.forPackage(OpenJPAConfigurationImpl.class); // cached state; some of this is created in getter methods, so make // protected in case subclasses want to access without creating protected MetaDataRepository metaRepository = null; protected RemoteCommitEventManager remoteEventManager = null; // openjpa properties public ObjectValue classResolverPlugin; public BrokerValue brokerPlugin; public ObjectValue dataCachePlugin; public ObjectValue dataCacheManagerPlugin; public ObjectValue auditorPlugin; public ObjectValue cacheDistributionPolicyPlugin; public IntValue dataCacheTimeout; public ObjectValue queryCachePlugin; public BooleanValue dynamicDataStructs; public ObjectValue managedRuntimePlugin; public BooleanValue transactionMode; public IntValue connectionRetainMode; public IntValue fetchBatchSize; public IntValue maxFetchDepth; public StringListValue fetchGroups; public IntValue flushBeforeQueries; public IntValue lockTimeout; public IntValue queryTimeout; public IntValue readLockLevel; public IntValue writeLockLevel; public ObjectValue seqPlugin; public PluginListValue filterListenerPlugins; public PluginListValue aggregateListenerPlugins; public BooleanValue retryClassRegistration; public ObjectValue proxyManagerPlugin; public StringValue connectionUserName; public StringValue connectionPassword; public PluginValue encryptionProvider; public StringValue connectionURL; public StringValue connectionDriverName; public ObjectValue connectionFactory; public StringValue connectionFactoryName; public StringValue connectionProperties; public StringValue connectionFactoryProperties; public BooleanValue connectionFactoryMode; public StringValue connection2UserName; public StringValue connection2Password; public StringValue connection2URL; public StringValue connection2DriverName; public StringValue connection2Properties; public ObjectValue connectionFactory2; public StringValue connectionFactory2Name; public StringValue connectionFactory2Properties; public BooleanValue optimistic; public IntValue autoClear; public BooleanValue retainState; public IntValue restoreState; public ObjectValue detachStatePlugin; public BooleanValue ignoreChanges; public BooleanValue nontransactionalRead; public BooleanValue nontransactionalWrite; public BooleanValue refreshFromDataCache; public BooleanValue multithreaded; public StringValue mapping; public PluginValue metaFactoryPlugin; public MetaDataRepositoryValue metaRepositoryPlugin; public ObjectValue lockManagerPlugin; public ObjectValue inverseManagerPlugin; public ObjectValue savepointManagerPlugin; public ObjectValue orphanedKeyPlugin; public ObjectValue compatibilityPlugin; public ObjectValue callbackPlugin; public QueryCompilationCacheValue queryCompilationCachePlugin; public IntValue runtimeUnenhancedClasses; public CacheMarshallersValue cacheMarshallerPlugins; public BooleanValue eagerInitialization; public PluginValue preparedQueryCachePlugin; public PluginValue finderCachePlugin; public ObjectValue specification; public StringValue validationMode; public ObjectValue validationFactory; public ObjectValue validator; public ObjectValue lifecycleEventManager; public StringValue validationGroupPrePersist; public StringValue validationGroupPreUpdate; public StringValue validationGroupPreRemove; public StringValue dataCacheMode; public BooleanValue dynamicEnhancementAgent; public ObjectValue instrumentationManager; public PluginListValue instrumentationProviders; public BooleanValue postLoadOnMerge; public BooleanValue optimizeIdCopy; // custom values public BrokerFactoryValue brokerFactoryPlugin; public RemoteCommitProviderValue remoteProviderPlugin; public AutoDetachValue autoDetach; private Collection supportedOptions = new HashSet(33); private final StoreFacadeTypeRegistry _storeFacadeRegistry = new StoreFacadeTypeRegistry(); private BrokerFactoryEventManager _brokerFactoryEventManager = new BrokerFactoryEventManager(this); private Map _peMap; //contains persistence environment-specific info private boolean _allowSetLifeCycleEventManager = true; /** * Default constructor. Attempts to load global properties. */ public OpenJPAConfigurationImpl() { this(true); } /** * Constructor. * * @param loadGlobals whether to attempt to load the global properties */ public OpenJPAConfigurationImpl(boolean loadGlobals) { this(true, loadGlobals); } /** * Constructor. * * @param derivations whether to apply product derivations * @param loadGlobals whether to attempt to load the global properties */ public OpenJPAConfigurationImpl(boolean derivations, boolean loadGlobals) { super(false); String[] aliases; classResolverPlugin = addPlugin("ClassResolver", true); aliases = new String[] { "default", "org.apache.openjpa.util.ClassResolverImpl", // deprecated alias "spec", "org.apache.openjpa.util.ClassResolverImpl", }; classResolverPlugin.setAliases(aliases); classResolverPlugin.setDefault(aliases[0]); classResolverPlugin.setString(aliases[0]); classResolverPlugin.setInstantiatingGetter("getClassResolverInstance"); brokerFactoryPlugin = new BrokerFactoryValue(); addValue(brokerFactoryPlugin); brokerPlugin = new BrokerValue(); addValue(brokerPlugin); dataCacheManagerPlugin = addPlugin("DataCacheManager", true); aliases = new String[] { "default", DataCacheManagerImpl.class.getName(), }; dataCacheManagerPlugin.setAliases(aliases); dataCacheManagerPlugin.setDefault(aliases[0]); dataCacheManagerPlugin.setString(aliases[0]); dataCacheManagerPlugin.setInstantiatingGetter("getDataCacheManager"); cacheDistributionPolicyPlugin = addPlugin("CacheDistributionPolicy", true); aliases = new String[] { "default", "org.apache.openjpa.datacache.DefaultCacheDistributionPolicy", "type-based", "org.apache.openjpa.datacache.TypeBasedCacheDistributionPolicy"}; cacheDistributionPolicyPlugin.setAliases(aliases); cacheDistributionPolicyPlugin.setDefault(aliases[0]); cacheDistributionPolicyPlugin.setString(aliases[0]); cacheDistributionPolicyPlugin.setInstantiatingGetter("getCacheDistributionPolicy"); dataCachePlugin = addPlugin("DataCache", false); aliases = new String[] { "false", null, "true", ConcurrentDataCache.class.getName(), "concurrent", ConcurrentDataCache.class.getName(), "partitioned", PartitionedDataCache.class.getName(), }; dataCachePlugin.setAliases(aliases); dataCachePlugin.setDefault(aliases[0]); dataCachePlugin.setString(aliases[0]); dataCacheTimeout = addInt("DataCacheTimeout"); dataCacheTimeout.setDefault("-1"); dataCacheTimeout.set(-1); dataCacheTimeout.setDynamic(true); queryCachePlugin = addPlugin("QueryCache", false); aliases = new String[] { "false", null, "true", ConcurrentQueryCache.class.getName(), "concurrent", ConcurrentQueryCache.class.getName(), }; queryCachePlugin.setAliases(aliases); queryCachePlugin.setDefault(aliases[0]); queryCachePlugin.setString(aliases[0]); refreshFromDataCache = addBoolean("RefreshFromDataCache"); refreshFromDataCache.setDefault("false"); refreshFromDataCache.set(false); refreshFromDataCache.setDynamic(true); dynamicDataStructs = addBoolean("DynamicDataStructs"); dynamicDataStructs.setDefault("false"); dynamicDataStructs.set(false); lockManagerPlugin = addPlugin("LockManager", false); aliases = new String[] { "none", "org.apache.openjpa.kernel.NoneLockManager", "version", "org.apache.openjpa.kernel.VersionLockManager", }; lockManagerPlugin.setAliases(aliases); lockManagerPlugin.setDefault(aliases[0]); lockManagerPlugin.setString(aliases[0]); inverseManagerPlugin = addPlugin("InverseManager", false); aliases = new String[] { "false", null, "true", "org.apache.openjpa.kernel.InverseManager", }; inverseManagerPlugin.setAliases(aliases); inverseManagerPlugin.setDefault(aliases[0]); inverseManagerPlugin.setString(aliases[0]); savepointManagerPlugin = addPlugin("SavepointManager", true); aliases = new String[] { "in-mem", "org.apache.openjpa.kernel.InMemorySavepointManager", }; savepointManagerPlugin.setAliases(aliases); savepointManagerPlugin.setDefault(aliases[0]); savepointManagerPlugin.setString(aliases[0]); savepointManagerPlugin.setInstantiatingGetter("getSavepointManagerInstance"); orphanedKeyPlugin = addPlugin("OrphanedKeyAction", true); aliases = new String[] { "log", "org.apache.openjpa.event.LogOrphanedKeyAction", "exception", "org.apache.openjpa.event.ExceptionOrphanedKeyAction", "none", "org.apache.openjpa.event.NoneOrphanedKeyAction", }; orphanedKeyPlugin.setAliases(aliases); orphanedKeyPlugin.setDefault(aliases[0]); orphanedKeyPlugin.setString(aliases[0]); orphanedKeyPlugin.setInstantiatingGetter("getOrphanedKeyActionInstance"); remoteProviderPlugin = new RemoteCommitProviderValue(); addValue(remoteProviderPlugin); transactionMode = addBoolean("TransactionMode"); aliases = new String[] { "local", "false", "managed", "true", }; transactionMode.setAliases(aliases); transactionMode.setDefault(aliases[0]); managedRuntimePlugin = addPlugin("ManagedRuntime", true); aliases = new String[] { "auto", "org.apache.openjpa.ee.AutomaticManagedRuntime", "jndi", "org.apache.openjpa.ee.JNDIManagedRuntime", "invocation", "org.apache.openjpa.ee.InvocationManagedRuntime", }; managedRuntimePlugin.setAliases(aliases); managedRuntimePlugin.setDefault(aliases[0]); managedRuntimePlugin.setString(aliases[0]); managedRuntimePlugin .setInstantiatingGetter("getManagedRuntimeInstance"); proxyManagerPlugin = addPlugin("ProxyManager", true); aliases = new String[] { "default", "org.apache.openjpa.util.ProxyManagerImpl" }; proxyManagerPlugin.setAliases(aliases); proxyManagerPlugin.setDefault(aliases[0]); proxyManagerPlugin.setString(aliases[0]); proxyManagerPlugin.setInstantiatingGetter("getProxyManagerInstance"); mapping = addString("Mapping"); metaFactoryPlugin = addPlugin("MetaDataFactory", false); metaRepositoryPlugin = (MetaDataRepositoryValue) addValue(new MetaDataRepositoryValue()); connectionFactory = addObject("ConnectionFactory"); connectionFactory.setInstantiatingGetter("getConnectionFactory"); connectionFactory2 = addObject("ConnectionFactory2"); connectionFactory2.setInstantiatingGetter("getConnectionFactory2"); // This is done because this plug-in may get initialized very lazily // when the runtime needs it for flush or a sequence. To keep it // dynamic allows it to be set even when the configuration is frozen connectionFactory.setDynamic(true); connectionFactory2.setDynamic(true); connectionUserName = addString("ConnectionUserName"); connectionUserName.addEquivalentKey("javax.persistence.jdbc.user"); connectionPassword = addString("ConnectionPassword"); connectionPassword.addEquivalentKey("javax.persistence.jdbc.password"); connectionPassword.hide(); encryptionProvider = addPlugin("EncryptionProvider",true); connectionURL = addString("ConnectionURL"); connectionURL.addEquivalentKey("javax.persistence.jdbc.url"); connectionDriverName = addString("ConnectionDriverName"); connectionDriverName.addEquivalentKey("javax.persistence.jdbc.driver"); connectionFactoryName = addString("ConnectionFactoryName"); connectionProperties = addString("ConnectionProperties"); connectionFactoryProperties = addString("ConnectionFactoryProperties"); connection2UserName = addString("Connection2UserName"); connection2Password = addString("Connection2Password"); connection2Password.hide(); connection2URL = addString("Connection2URL"); connection2DriverName = addString("Connection2DriverName"); connection2Properties = addString("Connection2Properties"); connectionFactory2Properties = addString("ConnectionFactory2Properties"); connectionFactory2Name = addString("ConnectionFactory2Name"); connectionFactoryMode = addBoolean("ConnectionFactoryMode"); aliases = new String[] { "local", "false", "managed", "true", }; connectionFactoryMode.setAliases(aliases); connectionFactoryMode.setDefault(aliases[0]); optimistic = addBoolean("Optimistic"); optimistic.setDefault("true"); optimistic.set(true); postLoadOnMerge = addBoolean("PostLoadOnMerge"); postLoadOnMerge.setDefault("false"); postLoadOnMerge.set(false); optimizeIdCopy = addBoolean("OptimizeIdCopy"); optimizeIdCopy.setDefault("false"); optimizeIdCopy.set(false); autoClear = addInt("AutoClear"); aliases = new String[] { "datastore", String.valueOf(AutoClear.CLEAR_DATASTORE), "all", String.valueOf(AutoClear.CLEAR_ALL), }; autoClear.setAliases(aliases); autoClear.setDefault(aliases[0]); autoClear.set(AutoClear.CLEAR_DATASTORE); autoClear.setAliasListComprehensive(true); retainState = addBoolean("RetainState"); retainState.setDefault("true"); retainState.set(true); restoreState = addInt("RestoreState"); aliases = new String[] { "none", String.valueOf(RestoreState.RESTORE_NONE), "false", String.valueOf(RestoreState.RESTORE_NONE), "immutable", String.valueOf(RestoreState.RESTORE_IMMUTABLE), // "true" for compat with jdo RestoreValues "true", String.valueOf(RestoreState.RESTORE_IMMUTABLE), "all", String.valueOf(RestoreState.RESTORE_ALL), }; restoreState.setAliases(aliases); restoreState.setDefault(aliases[0]); restoreState.set(RestoreState.RESTORE_IMMUTABLE); restoreState.setAliasListComprehensive(true); autoDetach = new AutoDetachValue(); addValue(autoDetach); detachStatePlugin = addPlugin("DetachState", true); aliases = new String[] { "loaded", DetachOptions.Loaded.class.getName(), "fgs", DetachOptions.FetchGroups.class.getName(), "fetch-groups", DetachOptions.FetchGroups.class.getName(), "all", DetachOptions.All.class.getName(), }; detachStatePlugin.setAliases(aliases); detachStatePlugin.setDefault(aliases[0]); detachStatePlugin.setString(aliases[0]); detachStatePlugin.setInstantiatingGetter("getDetachStateInstance"); ignoreChanges = addBoolean("IgnoreChanges"); nontransactionalRead = addBoolean("NontransactionalRead"); nontransactionalRead.setDefault("true"); nontransactionalRead.set(true); nontransactionalWrite = addBoolean("NontransactionalWrite"); multithreaded = addBoolean("Multithreaded"); fetchBatchSize = addInt("FetchBatchSize"); fetchBatchSize.setDefault("-1"); fetchBatchSize.set(-1); fetchBatchSize.setDynamic(true); maxFetchDepth = addInt("MaxFetchDepth"); maxFetchDepth.setDefault("-1"); maxFetchDepth.set(-1); fetchGroups = addStringList("FetchGroups"); fetchGroups.setDefault("default"); fetchGroups.set(new String[] { "default" }); flushBeforeQueries = addInt("FlushBeforeQueries"); aliases = new String[] { "true", String.valueOf(QueryFlushModes.FLUSH_TRUE), "false", String.valueOf(QueryFlushModes.FLUSH_FALSE), "with-connection", String.valueOf(QueryFlushModes.FLUSH_WITH_CONNECTION), }; flushBeforeQueries.setAliases(aliases); flushBeforeQueries.setDefault(aliases[0]); flushBeforeQueries.set(QueryFlushModes.FLUSH_TRUE); flushBeforeQueries.setAliasListComprehensive(true); lockTimeout = addInt("LockTimeout"); lockTimeout.addEquivalentKey("javax.persistence.lock.timeout"); lockTimeout.setDefault("-1"); lockTimeout.setDynamic(true); readLockLevel = addInt("ReadLockLevel"); aliases = new String[] { "read", String.valueOf(LockLevels.LOCK_READ), "write", String.valueOf(LockLevels.LOCK_WRITE), "none", String.valueOf(LockLevels.LOCK_NONE), }; readLockLevel.setAliases(aliases); readLockLevel.setDefault(aliases[0]); readLockLevel.set(LockLevels.LOCK_READ); readLockLevel.setAliasListComprehensive(true); writeLockLevel = addInt("WriteLockLevel"); aliases = new String[] { "read", String.valueOf(LockLevels.LOCK_READ), "write", String.valueOf(LockLevels.LOCK_WRITE), "none", String.valueOf(LockLevels.LOCK_NONE), }; writeLockLevel.setAliases(aliases); writeLockLevel.setDefault(aliases[1]); writeLockLevel.set(LockLevels.LOCK_WRITE); writeLockLevel.setAliasListComprehensive(true); seqPlugin = new SeqValue("Sequence"); seqPlugin.setInstantiatingGetter("getSequenceInstance"); addValue(seqPlugin); connectionRetainMode = addInt("ConnectionRetainMode"); aliases = new String[] { "on-demand", String.valueOf(ConnectionRetainModes.CONN_RETAIN_DEMAND), "transaction", String.valueOf(ConnectionRetainModes.CONN_RETAIN_TRANS), "always", String.valueOf(ConnectionRetainModes.CONN_RETAIN_ALWAYS), // deprecated "persistence-manager", String.valueOf(ConnectionRetainModes.CONN_RETAIN_ALWAYS), }; connectionRetainMode.setAliases(aliases); connectionRetainMode.setDefault(aliases[0]); connectionRetainMode.setAliasListComprehensive(true); connectionRetainMode.set(ConnectionRetainModes.CONN_RETAIN_DEMAND); filterListenerPlugins = addPluginList("FilterListeners"); filterListenerPlugins.setInstantiatingGetter("getFilterListenerInstances"); aggregateListenerPlugins = addPluginList("AggregateListeners"); aggregateListenerPlugins.setInstantiatingGetter("getAggregateListenerInstances"); retryClassRegistration = addBoolean("RetryClassRegistration"); compatibilityPlugin = addPlugin("Compatibility", true); aliases = new String[] { "default", Compatibility.class.getName() }; compatibilityPlugin.setAliases(aliases); compatibilityPlugin.setDefault(aliases[0]); compatibilityPlugin.setString(aliases[0]); compatibilityPlugin.setInstantiatingGetter("getCompatibilityInstance"); callbackPlugin = addPlugin("Callbacks", true); aliases = new String[] { "default", CallbackOptions.class.getName() }; callbackPlugin.setAliases(aliases); callbackPlugin.setDefault(aliases[0]); callbackPlugin.setString(aliases[0]); callbackPlugin.setInstantiatingGetter("getCallbackOptionsInstance"); queryCompilationCachePlugin = new QueryCompilationCacheValue("QueryCompilationCache"); queryCompilationCachePlugin.setInstantiatingGetter("getQueryCompilationCacheInstance"); addValue(queryCompilationCachePlugin); runtimeUnenhancedClasses = addInt("RuntimeUnenhancedClasses"); runtimeUnenhancedClasses.setAliases(new String[] { "supported", String.valueOf(RuntimeUnenhancedClassesModes.SUPPORTED), "unsupported", String.valueOf(RuntimeUnenhancedClassesModes.UNSUPPORTED), "warn", String.valueOf(RuntimeUnenhancedClassesModes.WARN), }); runtimeUnenhancedClasses.setDefault("unsupported"); runtimeUnenhancedClasses.setString("unsupported"); runtimeUnenhancedClasses.setAliasListComprehensive(true); cacheMarshallerPlugins = (CacheMarshallersValue) addValue(new CacheMarshallersValue(this)); eagerInitialization = addBoolean("InitializeEagerly"); specification = new SpecificationPlugin(this, "Specification"); addValue(specification); specification.setInstantiatingGetter("getSpecificationInstance"); queryTimeout = addInt("javax.persistence.query.timeout"); queryTimeout.setDefault("-1"); queryTimeout.setDynamic(true); lifecycleEventManager = addPlugin("LifecycleEventManager", true); aliases = new String[] { "default", LifecycleEventManager.class.getName(), "validating", ValidatingLifecycleEventManager.class.getName(), }; lifecycleEventManager.setAliases(aliases); lifecycleEventManager.setDefault(aliases[0]); lifecycleEventManager.setString(aliases[0]); lifecycleEventManager.setInstantiatingGetter("getLifecycleEventManagerInstance"); dynamicEnhancementAgent = addBoolean("DynamicEnhancementAgent"); dynamicEnhancementAgent.setDefault("true"); dynamicEnhancementAgent.set(true); instrumentationManager = addPlugin("InstrumentationManager", true); aliases = new String[] { "default", InstrumentationManagerImpl.class.getName(), }; instrumentationManager.setAliases(aliases); instrumentationManager.setDefault(aliases[0]); instrumentationManager.setString(aliases[0]); instrumentationManager.setInstantiatingGetter("getInstrumentationManager"); instrumentationProviders = addPluginList("Instrumentation"); aliases = new String[] { "jmx", "org.apache.openjpa.instrumentation.jmx.JMXProvider" }; instrumentationProviders.setAliases(aliases); instrumentationProviders.setInstantiatingGetter("getInstrumentationInstances"); auditorPlugin = addPlugin("Auditor", true); aliases = new String[] { "default", AuditLogger.class.getName(), }; auditorPlugin.setAliases(aliases); auditorPlugin.setInstantiatingGetter("getAuditorInstance"); // initialize supported options that some runtimes may not support supportedOptions.add(OPTION_NONTRANS_READ); supportedOptions.add(OPTION_OPTIMISTIC); supportedOptions.add(OPTION_ID_APPLICATION); supportedOptions.add(OPTION_ID_DATASTORE); supportedOptions.add(OPTION_TYPE_COLLECTION); supportedOptions.add(OPTION_TYPE_MAP); supportedOptions.add(OPTION_TYPE_ARRAY); supportedOptions.add(OPTION_NULL_CONTAINER); supportedOptions.add(OPTION_EMBEDDED_RELATION); supportedOptions.add(OPTION_EMBEDDED_COLLECTION_RELATION); supportedOptions.add(OPTION_EMBEDDED_MAP_RELATION); supportedOptions.add(OPTION_INC_FLUSH); supportedOptions.add(OPTION_VALUE_AUTOASSIGN); supportedOptions.add(OPTION_VALUE_INCREMENT); supportedOptions.add(OPTION_DATASTORE_CONNECTION); supportedOptions.add(OPTION_POSTLOAD_ON_MERGE); if (derivations) ProductDerivations.beforeConfigurationLoad(this); if (loadGlobals) loadGlobals(); } public Collection supportedOptions() { return supportedOptions; } /** * Get the name of the Specification only (not the version or other * information) or an empty String if not set. * */ public String getSpecification() { Specification spec = getSpecificationInstance(); return spec == null ? "" : spec.getName(); } public Specification getSpecificationInstance() { return (Specification)specification.get(); } /** * Sets Specification from the given String. * * @param spec should be encoded in the format specified in {@link * Specification}. */ public void setSpecification(String spec) { specification.setString(spec); } public void setSpecification(Specification newSpec) { specification.set(newSpec); } public void setClassResolver(String classResolver) { classResolverPlugin.setString(classResolver); } public String getClassResolver() { return classResolverPlugin.getString(); } public void setClassResolver(ClassResolver classResolver) { classResolverPlugin.set(classResolver); } public ClassResolver getClassResolverInstance() { if (classResolverPlugin.get() == null) classResolverPlugin.instantiate(ClassResolver.class, this); return (ClassResolver) classResolverPlugin.get(); } public void setBrokerFactory(String factory) { brokerFactoryPlugin.setString(factory); } public String getBrokerFactory() { return brokerFactoryPlugin.getString(); } public void setBrokerImpl(String broker) { brokerPlugin.setString(broker); } public String getBrokerImpl() { return brokerPlugin.getString(); } public BrokerImpl newBrokerInstance(String user, String pass) { BrokerImpl broker = (BrokerImpl) brokerPlugin.instantiate(BrokerImpl.class, this); if (broker != null) broker.setAuthentication(user, pass); return broker; } public void setDataCacheManager(String mgr) { dataCacheManagerPlugin.setString(mgr); } public String getDataCacheManager() { return dataCacheManagerPlugin.getString(); } public void setDataCacheManager(DataCacheManager dcm) { if (dcm != null) dcm.initialize(this, dataCachePlugin, queryCachePlugin); dataCacheManagerPlugin.set(dcm); } public DataCacheManager getDataCacheManagerInstance() { DataCacheManager dcm = (DataCacheManager) dataCacheManagerPlugin.get(); if (dcm == null) { dcm = (DataCacheManager) dataCacheManagerPlugin.instantiate(DataCacheManager.class, this); if (dcm != null) { dcm.initialize(this, dataCachePlugin, queryCachePlugin); } } return dcm; } public void setDataCache(String dataCache) { dataCachePlugin.setString(dataCache); } public String getDataCache() { return dataCachePlugin.getString(); } public void setDataCacheTimeout(int dataCacheTimeout) { this.dataCacheTimeout.set(dataCacheTimeout); } public void setDataCacheTimeout(Integer dataCacheTimeout) { if (dataCacheTimeout != null) setDataCacheTimeout(dataCacheTimeout.intValue()); } public int getDataCacheTimeout() { return dataCacheTimeout.get(); } public void setQueryCache(String queryCache) { queryCachePlugin.setString(queryCache); } public String getQueryCache() { return queryCachePlugin.getString(); } public boolean getRefreshFromDataCache() { return refreshFromDataCache.get(); } public void setRefreshFromDataCache(boolean flag) { refreshFromDataCache.set(flag); } public void setRefreshFromDataCache(Boolean flag) { if (flag != null) { refreshFromDataCache.set(flag.booleanValue()); } } public boolean getDynamicDataStructs() { return dynamicDataStructs.get(); } public void setDynamicDataStructs(boolean dynamic) { dynamicDataStructs.set(dynamic); } public void setDynamicDataStructs(Boolean dynamic) { setDynamicDataStructs(dynamic.booleanValue()); } public void setLockManager(String lockManager) { lockManagerPlugin.setString(lockManager); } public String getLockManager() { return lockManagerPlugin.getString(); } public LockManager newLockManagerInstance() { // don't validate plugin properties on instantiation because it // is likely that back ends will override defaults with their // own subclasses with new properties return (LockManager) lockManagerPlugin.instantiate(LockManager.class, this, false); } public void setInverseManager(String inverseManager) { inverseManagerPlugin.setString(inverseManager); } public String getInverseManager() { return inverseManagerPlugin.getString(); } public InverseManager newInverseManagerInstance() { return (InverseManager) inverseManagerPlugin.instantiate(InverseManager.class, this); } public void setSavepointManager(String savepointManager) { savepointManagerPlugin.setString(savepointManager); } public String getSavepointManager() { return savepointManagerPlugin.getString(); } public SavepointManager getSavepointManagerInstance() { if (savepointManagerPlugin.get() == null) savepointManagerPlugin.instantiate(SavepointManager.class, this); return (SavepointManager) savepointManagerPlugin.get(); } public void setOrphanedKeyAction(String action) { orphanedKeyPlugin.setString(action); } public String getOrphanedKeyAction() { return orphanedKeyPlugin.getString(); } public OrphanedKeyAction getOrphanedKeyActionInstance() { if (orphanedKeyPlugin.get() == null) orphanedKeyPlugin.instantiate(OrphanedKeyAction.class, this); return (OrphanedKeyAction) orphanedKeyPlugin.get(); } public void setOrphanedKeyAction(OrphanedKeyAction action) { orphanedKeyPlugin.set(action); } public void setRemoteCommitProvider(String remoteCommitProvider) { remoteProviderPlugin.setString(remoteCommitProvider); } public String getRemoteCommitProvider() { return remoteProviderPlugin.getString(); } public RemoteCommitProvider newRemoteCommitProviderInstance() { return remoteProviderPlugin.instantiateProvider(this); } public void setRemoteCommitEventManager( RemoteCommitEventManager remoteEventManager) { this.remoteEventManager = remoteEventManager; remoteProviderPlugin.configureEventManager(remoteEventManager); } public RemoteCommitEventManager getRemoteCommitEventManager() { if (remoteEventManager == null) { remoteEventManager = new RemoteCommitEventManager(this); remoteProviderPlugin.configureEventManager(remoteEventManager); } return remoteEventManager; } public void setTransactionMode(String transactionMode) { this.transactionMode.setString(transactionMode); } public String getTransactionMode() { return transactionMode.getString(); } public void setTransactionModeManaged(boolean managed) { transactionMode.set(managed); } public boolean isTransactionModeManaged() { return transactionMode.get(); } public void setManagedRuntime(String managedRuntime) { managedRuntimePlugin.setString(managedRuntime); } public String getManagedRuntime() { return managedRuntimePlugin.getString(); } public void setManagedRuntime(ManagedRuntime managedRuntime) { managedRuntimePlugin.set(managedRuntime); } public ManagedRuntime getManagedRuntimeInstance() { if (managedRuntimePlugin.get() == null) managedRuntimePlugin.instantiate(ManagedRuntime.class, this); return (ManagedRuntime) managedRuntimePlugin.get(); } public void setProxyManager(String proxyManager) { proxyManagerPlugin.setString(proxyManager); } public String getProxyManager() { return proxyManagerPlugin.getString(); } public void setProxyManager(ProxyManager proxyManager) { proxyManagerPlugin.set(proxyManager); } public ProxyManager getProxyManagerInstance() { if (proxyManagerPlugin.get() == null) proxyManagerPlugin.instantiate(ProxyManager.class, this); return (ProxyManager) proxyManagerPlugin.get(); } public void setMapping(String mapping) { this.mapping.setString(mapping); } public String getMapping() { return mapping.getString(); } public void setMetaDataFactory(String meta) { this.metaFactoryPlugin.setString(meta); } public String getMetaDataFactory() { return metaFactoryPlugin.getString(); } public MetaDataFactory newMetaDataFactoryInstance() { return (MetaDataFactory) metaFactoryPlugin.instantiate( MetaDataFactory.class, this); } public void setMetaDataRepository(String meta) { this.metaRepositoryPlugin.setString(meta); } public String getMetaDataRepository() { return metaRepositoryPlugin.getString(); } public void setMetaDataRepository(MetaDataRepository meta) { metaRepository = meta; } public MetaDataRepository getMetaDataRepositoryInstance() { if (metaRepository == null) metaRepository = newMetaDataRepositoryInstance(); return metaRepository; } public boolean metaDataRepositoryAvailable(){ return metaRepository != null; } public MetaDataRepository newMetaDataRepositoryInstance() { return (MetaDataRepository) metaRepositoryPlugin.instantiate( MetaDataRepository.class, this); } public void setConnectionUserName(String connectionUserName) { this.connectionUserName.setString(connectionUserName); } public String getConnectionUserName() { return connectionUserName.getString(); } public void setConnectionPassword(String connectionPassword) { this.connectionPassword.setString(connectionPassword); } public String getConnectionPassword() { EncryptionProvider p = getEncryptionProvider(); if(p != null) { return p.decrypt(connectionPassword.getString()); } return connectionPassword.getString(); } public void setConnectionURL(String connectionURL) { this.connectionURL.setString(connectionURL); } public String getConnectionURL() { return connectionURL.getString(); } public void setConnectionDriverName(String driverName) { this.connectionDriverName.setString(driverName); } public String getConnectionDriverName() { return connectionDriverName.getString(); } public void setConnectionProperties(String connectionProperties) { this.connectionProperties.setString(connectionProperties); } public String getConnectionProperties() { return connectionProperties.getString(); } public void setConnectionFactoryProperties( String connectionFactoryProperties) { this.connectionFactoryProperties.setString(connectionFactoryProperties); } public String getConnectionFactoryProperties() { return connectionFactoryProperties.getString(); } public String getConnectionFactoryMode() { return connectionFactoryMode.getString(); } public void setConnectionFactoryMode(String mode) { connectionFactoryMode.setString(mode); } public boolean isConnectionFactoryModeManaged() { return connectionFactoryMode.get(); } public void setConnectionFactoryModeManaged(boolean managed) { connectionFactoryMode.set(managed); } public void setConnectionFactoryName(String connectionFactoryName) { this.connectionFactoryName.setString(connectionFactoryName); } public String getConnectionFactoryName() { return connectionFactoryName.getString(); } public void setConnectionFactory(Object factory) { connectionFactory.set(factory); } public Object getConnectionFactory() { if (connectionFactory.get() == null) connectionFactory.set( lookupConnectionFactory(getConnectionFactoryName(), connectionFactory.getProperty()), true); return connectionFactory.get(); } /** * Lookup the connection factory at the given name. */ private Object lookupConnectionFactory(String name, String userKey) { name = StringUtils.trimToNull(name); if (name == null) return null; try { return Configurations.lookup(name, userKey, getLog(OpenJPAConfiguration.LOG_RUNTIME)); } catch (Exception ex) { return null; } } public void setConnection2UserName(String connection2UserName) { this.connection2UserName.setString(connection2UserName); } public String getConnection2UserName() { return connection2UserName.getString(); } public void setConnection2Password(String connection2Password) { this.connection2Password.setString(connection2Password); } public String getConnection2Password() { EncryptionProvider p = getEncryptionProvider(); if(p != null){ return p.decrypt(connection2Password.getString()); } return connection2Password.getString(); } public void setConnection2URL(String connection2URL) { this.connection2URL.setString(connection2URL); } public String getConnection2URL() { return connection2URL.getString(); } public void setConnection2DriverName(String driverName) { this.connection2DriverName.setString(driverName); } public String getConnection2DriverName() { return connection2DriverName.getString(); } public void setConnection2Properties(String connection2Properties) { this.connection2Properties.setString(connection2Properties); } public String getConnection2Properties() { return connection2Properties.getString(); } public void setConnectionFactory2Properties( String connectionFactory2Properties) { this.connectionFactory2Properties .setString(connectionFactory2Properties); } public String getConnectionFactory2Properties() { return connectionFactory2Properties.getString(); } public void setConnectionFactory2Name(String connectionFactory2Name) { this.connectionFactory2Name.setString(connectionFactory2Name); } public String getConnectionFactory2Name() { return connectionFactory2Name.getString(); } public void setConnectionFactory2(Object factory) { connectionFactory2.set(factory); } public Object getConnectionFactory2() { if (connectionFactory2.get() == null) connectionFactory2.set( lookupConnectionFactory(getConnectionFactory2Name(), connectionFactory2.getProperty()), false); return connectionFactory2.get(); } public void setOptimistic(boolean optimistic) { this.optimistic.set(optimistic); } public void setOptimistic(Boolean optimistic) { if (optimistic != null) setOptimistic(optimistic.booleanValue()); } public boolean getOptimistic() { return optimistic.get(); } public void setAutoClear(String clear) { autoClear.setString(clear); } public String getAutoClear() { return autoClear.getString(); } public void setAutoClear(int clear) { autoClear.set(clear); } public int getAutoClearConstant() { return autoClear.get(); } public void setRetainState(boolean retainState) { this.retainState.set(retainState); } public void setRetainState(Boolean retainState) { if (retainState != null) setRetainState(retainState.booleanValue()); } public boolean getRetainState() { return retainState.get(); } public void setRestoreState(String restoreState) { this.restoreState.setString(restoreState); } public String getRestoreState() { return restoreState.getString(); } public void setRestoreState(int restoreState) { this.restoreState.set(restoreState); } public int getRestoreStateConstant() { return restoreState.get(); } public void setAutoDetach(String autoDetach) { this.autoDetach.setString(autoDetach); } public String getAutoDetach() { return autoDetach.getString(); } public void setAutoDetach(int autoDetachFlags) { autoDetach.setConstant(autoDetachFlags); } public int getAutoDetachConstant() { return autoDetach.getConstant(); } public void setDetachState(String detachState) { detachStatePlugin.setString(detachState); } public String getDetachState() { return detachStatePlugin.getString(); } public void setDetachState(DetachOptions detachState) { detachStatePlugin.set(detachState); } public DetachOptions getDetachStateInstance() { if (detachStatePlugin.get() == null) detachStatePlugin.instantiate(DetachOptions.class, this); return (DetachOptions) detachStatePlugin.get(); } public void setIgnoreChanges(boolean ignoreChanges) { this.ignoreChanges.set(ignoreChanges); } public void setIgnoreChanges(Boolean ignoreChanges) { if (ignoreChanges != null) setIgnoreChanges(ignoreChanges.booleanValue()); } public boolean getIgnoreChanges() { return ignoreChanges.get(); } public void setNontransactionalRead(boolean nontransactionalRead) { this.nontransactionalRead.set(nontransactionalRead); } public void setNontransactionalRead(Boolean nontransactionalRead) { if (nontransactionalRead != null) setNontransactionalRead(nontransactionalRead.booleanValue()); } public boolean getNontransactionalRead() { return nontransactionalRead.get(); } public void setNontransactionalWrite(boolean nontransactionalWrite) { this.nontransactionalWrite.set(nontransactionalWrite); } public void setNontransactionalWrite(Boolean nontransactionalWrite) { if (nontransactionalWrite != null) setNontransactionalWrite(nontransactionalWrite.booleanValue()); } public boolean getNontransactionalWrite() { return nontransactionalWrite.get(); } public void setMultithreaded(boolean multithreaded) { this.multithreaded.set(multithreaded); } public void setMultithreaded(Boolean multithreaded) { if (multithreaded != null) setMultithreaded(multithreaded.booleanValue()); } public boolean getMultithreaded() { return multithreaded.get(); } public void setFetchBatchSize(int fetchBatchSize) { this.fetchBatchSize.set(fetchBatchSize); } public void setFetchBatchSize(Integer fetchBatchSize) { if (fetchBatchSize != null) setFetchBatchSize(fetchBatchSize.intValue()); } public int getFetchBatchSize() { return fetchBatchSize.get(); } public void setMaxFetchDepth(int maxFetchDepth) { this.maxFetchDepth.set(maxFetchDepth); } public void setMaxFetchDepth(Integer maxFetchDepth) { if (maxFetchDepth != null) setMaxFetchDepth(maxFetchDepth.intValue()); } public int getMaxFetchDepth() { return maxFetchDepth.get(); } public void setFetchGroups(String fetchGroups) { this.fetchGroups.setString(fetchGroups); } public String getFetchGroups() { return fetchGroups.getString(); } public String[] getFetchGroupsList() { return fetchGroups.get(); } public void setFetchGroups(String[] fetchGroups) { this.fetchGroups.set(fetchGroups); } public void setFlushBeforeQueries(String flush) { flushBeforeQueries.setString(flush); } public String getFlushBeforeQueries() { return flushBeforeQueries.getString(); } public void setFlushBeforeQueries(int flush) { flushBeforeQueries.set(flush); } public int getFlushBeforeQueriesConstant() { return flushBeforeQueries.get(); } public void setLockTimeout(int timeout) { lockTimeout.set(timeout); } public void setLockTimeout(Integer timeout) { if (timeout != null) setLockTimeout(timeout.intValue()); } public int getLockTimeout() { return lockTimeout.get(); } public int getQueryTimeout() { return queryTimeout.get(); } public void setQueryTimeout(int timeout) { queryTimeout.set(timeout); } public void setReadLockLevel(String level) { readLockLevel.setString(level); } public String getReadLockLevel() { return readLockLevel.getString(); } public void setReadLockLevel(int level) { readLockLevel.set(level); } public int getReadLockLevelConstant() { return readLockLevel.get(); } public void setWriteLockLevel(String level) { writeLockLevel.setString(level); } public String getWriteLockLevel() { return writeLockLevel.getString(); } public void setWriteLockLevel(int level) { writeLockLevel.set(level); } public int getWriteLockLevelConstant() { return writeLockLevel.get(); } public void setSequence(String sequence) { seqPlugin.setString(sequence); } public String getSequence() { return seqPlugin.getString(); } public void setSequence(Seq seq) { seqPlugin.set(seq); } public Seq getSequenceInstance() { if (seqPlugin.get() == null) seqPlugin.instantiate(Seq.class, this); return (Seq) seqPlugin.get(); } public void setConnectionRetainMode(String connectionRetainMode) { this.connectionRetainMode.setString(connectionRetainMode); } public String getConnectionRetainMode() { return connectionRetainMode.getString(); } public void setConnectionRetainMode(int connectionRetainMode) { this.connectionRetainMode.set(connectionRetainMode); } public int getConnectionRetainModeConstant() { return connectionRetainMode.get(); } public void setFilterListeners(String filterListeners) { filterListenerPlugins.setString(filterListeners); } public String getFilterListeners() { return filterListenerPlugins.getString(); } public void setFilterListeners(FilterListener[] listeners) { filterListenerPlugins.set(listeners); } public FilterListener[] getFilterListenerInstances() { if (filterListenerPlugins.get() == null) filterListenerPlugins.instantiate(FilterListener.class, this); return (FilterListener[]) filterListenerPlugins.get(); } public void setAggregateListeners(String aggregateListeners) { aggregateListenerPlugins.setString(aggregateListeners); } public String getAggregateListeners() { return aggregateListenerPlugins.getString(); } public void setAggregateListeners(AggregateListener[] listeners) { aggregateListenerPlugins.set(listeners); } public AggregateListener[] getAggregateListenerInstances() { if (aggregateListenerPlugins.get() == null) aggregateListenerPlugins.instantiate(AggregateListener.class, this); return (AggregateListener[]) aggregateListenerPlugins.get(); } public void setRetryClassRegistration(boolean retry) { retryClassRegistration.set(retry); } public void setRetryClassRegistration(Boolean retry) { if (retry != null) setRetryClassRegistration(retry.booleanValue()); } public boolean getRetryClassRegistration() { return retryClassRegistration.get(); } public String getCompatibility() { return compatibilityPlugin.getString(); } public void setCompatibility(String compatibility) { compatibilityPlugin.setString(compatibility); } /** * If a Compatibility instance is associated with the Specification, * we will configure this Compatibility instance instead of instantiating a * new one so that the compatibility flags set in compliance with the * Specification can be preserved. */ public Compatibility getCompatibilityInstance() { if (compatibilityPlugin.get() == null) { Specification spec = getSpecificationInstance(); Compatibility comp = spec != null ? spec.getCompatibility() : null; if (comp == null) compatibilityPlugin.instantiate(Compatibility.class, this); else compatibilityPlugin.configure(comp, this); } return (Compatibility) compatibilityPlugin.get(); } public String getCallbackOptions() { return callbackPlugin.getString(); } public void setCallbackOptions(String options) { callbackPlugin.setString(options); } public CallbackOptions getCallbackOptionsInstance() { if (callbackPlugin.get() == null) callbackPlugin.instantiate(CallbackOptions.class, this); return (CallbackOptions) callbackPlugin.get(); } public String getQueryCompilationCache() { return queryCompilationCachePlugin.getString(); } public void setQueryCompilationCache(String queryCompilationCache) { queryCompilationCachePlugin.setString(queryCompilationCache); } public Map getQueryCompilationCacheInstance() { if (queryCompilationCachePlugin.get() == null) queryCompilationCachePlugin.instantiate(Map.class, this); return (Map) queryCompilationCachePlugin.get(); } public StoreFacadeTypeRegistry getStoreFacadeTypeRegistry() { return _storeFacadeRegistry; } public BrokerFactoryEventManager getBrokerFactoryEventManager() { return _brokerFactoryEventManager; } public String getRuntimeUnenhancedClasses() { return runtimeUnenhancedClasses.getString(); } public int getRuntimeUnenhancedClassesConstant() { return runtimeUnenhancedClasses.get(); } public void setRuntimeUnenhancedClasses(int mode) { runtimeUnenhancedClasses.set(mode); } public void setRuntimeUnenhancedClasses(String mode) { runtimeUnenhancedClasses.setString(mode); } public String getCacheMarshallers() { return cacheMarshallerPlugins.getString(); } public void setCacheMarshallers(String marshallers) { cacheMarshallerPlugins.setString(marshallers); } public Map getCacheMarshallerInstances() { return cacheMarshallerPlugins.getInstancesAsMap(); } public boolean isInitializeEagerly() { return eagerInitialization.get(); } public void setInitializeEagerly(boolean retry) { eagerInitialization.set(retry); } public void setValidationMode(String mode) { validationMode.setString(mode); } public String getValidationMode() { String mode = validationMode.getString(); if (mode == null) mode = validationMode.getDefault(); return mode; } public void setValidationGroupPrePersist(String vgPrePersist) { validationGroupPrePersist.setString(vgPrePersist); } public String getValidationGroupPrePersist() { String vgPrePersist = validationGroupPrePersist.getString(); if (vgPrePersist == null) vgPrePersist = validationGroupPrePersist.getDefault(); return vgPrePersist; } public void setValidationGroupPreUpdate(String vgPreUpdate) { validationGroupPreUpdate.setString(vgPreUpdate); } public String getValidationGroupPreUpdate() { String vgPreUpdate = validationGroupPreUpdate.getString(); if (vgPreUpdate == null) vgPreUpdate = validationGroupPreUpdate.getDefault(); return vgPreUpdate; } public void setValidationGroupPreRemove(String vgPreRemove) { validationGroupPreRemove.setString(vgPreRemove); } public String getValidationGroupPreRemove() { String vgPreRemove = validationGroupPreRemove.getString(); if (vgPreRemove == null) vgPreRemove = validationGroupPreRemove.getDefault(); return vgPreRemove; } public String getInstrumentation() { return instrumentationProviders.getString(); } public void setInstrumentation(String providers) { instrumentationProviders.setString(providers); } public InstrumentationProvider[] getInstrumentationInstances() { if (instrumentationProviders.get() == null) instrumentationProviders.instantiate(InstrumentationProvider.class, this); return (InstrumentationProvider[]) instrumentationProviders.get(); } public void setInstrumentationManager(String mgr) { instrumentationManager.setString(mgr); } public String getInstrumentationManager() { return instrumentationManager.getString(); } public void setInstrumentationManager(InstrumentationManager im) { if (im != null) im.initialize(this, instrumentationProviders); instrumentationManager.set(im); } public InstrumentationManager getInstrumentationManagerInstance() { InstrumentationManager im = (InstrumentationManager) instrumentationManager.get(); if (im == null) { im = (InstrumentationManager) instrumentationManager.instantiate(InstrumentationManager.class, this); if (im != null) { im.initialize(this, instrumentationProviders); im.start(InstrumentationLevel.IMMEDIATE, this); } } return im; } public void instantiateAll() { super.instantiateAll(); getMetaDataRepositoryInstance(); getRemoteCommitEventManager(); getAuditorInstance(); cacheMarshallerPlugins.initialize(); if (isInitializeEagerly()) { getConnectionFactory(); getConnectionFactory2(); } } protected void preClose() { ImplHelper.close(metaRepository); ImplHelper.close(remoteEventManager); ImplHelper.close(getInstrumentationManagerInstance()); super.preClose(); } public Log getConfigurationLog() { return getLog(LOG_RUNTIME); } public void setQuerySQLCache(String querySQLCache) { preparedQueryCachePlugin.setString(querySQLCache); } public void setQuerySQLCache(PreparedQueryCache querySQLCache) { preparedQueryCachePlugin.set(querySQLCache); } public String getQuerySQLCache() { return preparedQueryCachePlugin.getString(); } public PreparedQueryCache getQuerySQLCacheInstance() { if (preparedQueryCachePlugin == null) return null; if (preparedQueryCachePlugin.get() == null) { preparedQueryCachePlugin.instantiate(PreparedQueryCache.class, this); } return (PreparedQueryCache)preparedQueryCachePlugin.get(); } public void setFinderCache(String finderCache) { finderCachePlugin.setString(finderCache); } public String getFinderCache() { return finderCachePlugin.getString(); } public FinderCache getFinderCacheInstance() { if (finderCachePlugin.get() == null) { finderCachePlugin.instantiate(FinderCache.class, this); } return (FinderCache)finderCachePlugin.get(); } public Object getValidationFactoryInstance() { return validationFactory.get(); } public void setValidationFactory(Object factory) { validationFactory.set(factory); } public Object getValidatorInstance() { return validator.get(); } public void setValidatorInstance(Object val) { validator.set(val); } public String getLifecycleEventManager() { return lifecycleEventManager.getString(); } public LifecycleEventManager getLifecycleEventManagerInstance() { LifecycleEventManager lem = null; if (!getCompatibilityInstance().isSingletonLifecycleEventManager() || (lem = (LifecycleEventManager)lifecycleEventManager.get()) == null) { lem = (LifecycleEventManager)lifecycleEventManager .instantiate(LifecycleEventManager.class, this); } return lem; } public void setLifecycleEventManager(String lem) { if (_allowSetLifeCycleEventManager) { _allowSetLifeCycleEventManager = false; // Only allow this to be called once even if the configuration is frozen. This can happen if a configuration // is eagerly initialized and validation is being used. lifecycleEventManager.setDynamic(true); lifecycleEventManager.setString(lem); lifecycleEventManager.setDynamic(false); } else { // If the configuration is frozen this will result in a warning message and/or an exception. lifecycleEventManager.setString(lem); } } public boolean getDynamicEnhancementAgent() { return dynamicEnhancementAgent.get(); } public void setDynamicEnhancementAgent(boolean dynamic) { dynamicEnhancementAgent.set(dynamic); } public void setEncryptionProvider(String p) { encryptionProvider.setString(p); } public EncryptionProvider getEncryptionProvider() { if (encryptionProvider.get() == null) encryptionProvider.instantiate(EncryptionProvider.class, this); return (EncryptionProvider) encryptionProvider.get(); } public void setDataCacheMode(String mode) { this.dataCacheMode.setString(mode); } public String getDataCacheMode() { return dataCacheMode.getString(); } public String getCacheDistributionPolicy() { return cacheDistributionPolicyPlugin.getString(); } public CacheDistributionPolicy getCacheDistributionPolicyInstance() { CacheDistributionPolicy policy = (CacheDistributionPolicy) cacheDistributionPolicyPlugin.get(); if (policy == null) { policy = (CacheDistributionPolicy) cacheDistributionPolicyPlugin.instantiate(CacheDistributionPolicy.class, this); } return policy; } public void setCacheDistributionPolicy(String policyPlugin) { cacheDistributionPolicyPlugin.setString(policyPlugin); } public void setCacheDistributionPolicyInstance(CacheDistributionPolicy policy) { cacheDistributionPolicyPlugin.set(policy); } public void setPersistenceEnvironment(Map peMap) { this._peMap = peMap; } public Map getPersistenceEnvironment() { return _peMap; } public Auditor getAuditorInstance() { Auditor auditor = (Auditor) auditorPlugin.get(); if (auditor == null) { auditor = (Auditor) auditorPlugin.instantiate(Auditor.class, this); } return auditor; } public void setAuditorInstance(Auditor auditor) { auditorPlugin.set(auditor); } public String getAuditor() { return auditorPlugin.getString(); } public void setAuditor(String auditor) { auditorPlugin.setString(auditor); } public boolean getPostLoadOnMerge() { return postLoadOnMerge.get(); } public void setPostLoadOnMerge(boolean postLoadOnMerge) { this.postLoadOnMerge.set(postLoadOnMerge); } public void setPostLoadOnMerge(Boolean postLoadOnMerge) { if (postLoadOnMerge != null) setPostLoadOnMerge(postLoadOnMerge.booleanValue()); } public boolean getOptimizeIdCopy() { return optimizeIdCopy.get(); } public void setOptimizeIdCopy(boolean optimizeId) { optimizeIdCopy.set(optimizeId); } public void setOptimizeIdCopy(Boolean optimizeId) { if (optimizeId != null) { setOptimizeIdCopy(optimizeId.booleanValue()); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/SeqValue.java0000644000000000000000000000330312133327272025326 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import org.apache.openjpa.kernel.TimeSeededSeq; import org.apache.openjpa.lib.conf.PluginValue; import org.apache.openjpa.meta.SequenceMetaData; /** * Value type used to represent a sequence. This type is * defined separately so that it can be used both in the global configuration * and in class metadata with the same encapsulated configuration. * * @author Abe White * @nojavadoc */ public class SeqValue extends PluginValue { private static final String[] ALIASES = new String[]{ SequenceMetaData.IMPL_TIME, TimeSeededSeq.class.getName(), SequenceMetaData.IMPL_NATIVE, TimeSeededSeq.class.getName(), // deprecated aliases "sjvm", TimeSeededSeq.class.getName(), }; public SeqValue(String prop) { super(prop, true); setAliases(ALIASES); setDefault(ALIASES[0]); setClassName(ALIASES[1]); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CallbackOptions.java0000644000000000000000000000556112133327272026661 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.io.Serializable; /** * Configurable options for callbacks. * * @author Pinaki Poddar */ public class CallbackOptions implements Serializable { private boolean _isPostPersistCallbackImmediate = false; private boolean _allowsMultipleMethodsForSameCallback = false; private boolean _allowsDuplicateListener = true; /** * Affirms if the post-persist callback is invoked as soon as a new instance * is managed. The default is false, implies that the post-persist callback * is invoked after the instance been committed or flushed to the datastore. * Defaults to false. */ public boolean getPostPersistCallbackImmediate() { return _isPostPersistCallbackImmediate; } /** * Sets if the post-persist callback is invoked as soon as a new instance * is managed. The default is false, implies that the post-persist callback * is invoked after the instance been committed or flushed to the datastore. */ public void setPostPersistCallbackImmediate(boolean flag) { _isPostPersistCallbackImmediate = flag; } /** * Flags if multiple methods of the same class can handle the same * callback event. * Defaults to false. */ public boolean getAllowsMultipleMethodsForSameCallback() { return _allowsMultipleMethodsForSameCallback; } /** * Flags if multiple methods of the same class can handle the same * callback event. */ public void setAllowsMultipleMethodsForSameCallback(boolean flag) { _allowsMultipleMethodsForSameCallback = flag; } /** * Flags if duplicate listeners are allowed to handle the same * callback event. * Defaults to true. */ public boolean getAllowsDuplicateListener() { return _allowsDuplicateListener; } /** * Flags if duplicate listeners are allowed to handle the same * callback event. */ public void setAllowsDuplicateListener(boolean flag) { _allowsDuplicateListener = flag; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshaller.java0000644000000000000000000000635512133327272026631 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; /** * Responsible for marshalling and unmarshalling objects between memory and * durable cache. * * @since 1.1.0 */ public interface CacheMarshaller { /** * Load and return an instance of the type handled by this marshaller. * If the type implements {@link Configurable}, then this method will invoke * {@link Configurable#setConfiguration}, * {@link Configurable#startConfiguration()}, and * {@link Configurable#endConfiguration()} on the instance before returning. */ public Object load(); /** * Store o into the cache. */ public void store(Object o); /** * The id that this marshaller is responsible for. * A value for this parameter is required. */ public void setId(String id); /** * The id that this marshaller is responsible for. */ public String getId(); /** * The {@link ValidationPolicy} that this marshaller should use. * A value for this parameter is required. The class will be instantiated * via the {@link org.apache.openjpa.lib.conf.Configurations} mechanism, * ensuring that if the class implements {@link Configurable} or * {@link org.apache.openjpa.lib.conf.GenericConfigurable}, it will be taken * through the appropriate lifecycle. */ public void setValidationPolicy(String policy) throws InstantiationException, IllegalAccessException; /** * Validation policies are responsible for computing whether or not a * cached data structure is valid for the current context. *

    * getValidCachedData(getCacheableData(o), conf) should * return an object equivalent to o in the expected case. *

    * Implementations of this class will often also implement * {@link Configurable} in order to receive the current * {@link Configuration}. */ public interface ValidationPolicy { /** * Returns an object that this policy considers to be valid, based * on o. If o is not valid, this method * will return null. */ public Object getValidData(Object o); /** * Return an object that the {@link CacheMarshaller} should store. */ public Object getCacheableData(Object o); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallersValue.java0000644000000000000000000000774012133327272030010 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.util.HashMap; import java.util.Map; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.conf.PluginListValue; import org.apache.openjpa.conf.NoOpCacheMarshaller; import org.apache.openjpa.lib.conf.Configuration; /** * A configuration value for handling and accessing cache marshallers. * * @since 1.1.0 */ public class CacheMarshallersValue extends PluginListValue { private static final String KEY = "CacheMarshallers"; private static final CacheMarshaller NO_OP_CACHE_MARSHALLER = new NoOpCacheMarshaller(); private static final Localizer _loc = Localizer.forPackage(CacheMarshallersValue.class); private Configuration _conf; private Map _marshallers; private boolean _initialized; public CacheMarshallersValue(Configuration conf) { super(KEY); _conf = conf; setAlias("default", CacheMarshallerImpl.class.getName()); setAlias("none", null); setDefault("none"); setString("none"); setScope(getClass()); } public Object instantiate(Class elemType, Configuration conf, boolean fatal) { CacheMarshaller[] ms = (CacheMarshaller[]) super.instantiate(elemType, conf, fatal); if (ms != null) { _marshallers = new HashMap(); for (int i = 0; i < ms.length; i++) { String mid = ms[i].getId(); if (mid != null) _marshallers.put(mid, ms[i]); } } else { _marshallers = null; } return ms; } /** * Return the {@link CacheMarshaller} to use for caching metadata of id * id. If no marshaller exists for the id, returns * {@link NoOpCacheMarshaller}. */ public CacheMarshaller getMarshallerById(String id) { initialize(); CacheMarshaller cm = (CacheMarshaller) _marshallers.get(id); if (cm == null) { if (getLog().isTraceEnabled()) getLog().trace(_loc.get("cache-marshaller-not-found", id)); return NO_OP_CACHE_MARSHALLER; } else { if (getLog().isTraceEnabled()) getLog().trace(_loc.get("cache-marshaller-found", id, cm.getClass().getName())); return cm; } } private Log getLog() { return _conf.getConfigurationLog(); } /** * Return the {@link CacheMarshaller} to use for caching metadata of id * id. If no marshaller exists for the id, returns * {@link NoOpCacheMarshaller}. */ public static CacheMarshaller getMarshallerById(Configuration c, String id){ CacheMarshallersValue v = ((OpenJPAConfigurationImpl) c).cacheMarshallerPlugins; return v.getMarshallerById(id); } public Map getInstancesAsMap() { return _marshallers; } protected synchronized void initialize() { if (!_initialized) { instantiate(CacheMarshaller.class, _conf); _initialized = true; } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataCacheMaintenance.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataCacheMaintenance.jav0000644000000000000000000001561412133327272030217 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.util.Collection; import java.util.Iterator; import java.util.Map; import org.apache.openjpa.kernel.Bootstrap; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.Query; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.conf.MapConfigurationProvider; import org.apache.openjpa.lib.conf.ConfigurationProvider; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.meta.QueryMetaData; import org.apache.openjpa.meta.SequenceMetaData; /** * Performs maintenance tasks on the metadata caches accessible via the * {@link CacheMarshaller} architecture. * * @since 1.1.0 */ public class MetaDataCacheMaintenance { private final BrokerFactory factory; private final OpenJPAConfiguration conf; private final boolean devpath; private Log log; public static void main(String[] args) { Options opts = new Options(); args = opts.setFromCmdLine(args); boolean devpath = opts.getBooleanProperty("scanDevPath", "ScanDevPath", true); ConfigurationProvider cp = new MapConfigurationProvider(opts); BrokerFactory factory = Bootstrap.newBrokerFactory(cp, null); try { MetaDataCacheMaintenance maint = new MetaDataCacheMaintenance( factory, devpath); if (args.length != 1) { usage(); return; } if ("store".equals(args[0])) maint.store(); else if ("dump".equals(args[0])) maint.dump(); else usage(); } finally { factory.close(); } } /** * @deprecated logging is routed to the logging system now. */ public MetaDataCacheMaintenance(BrokerFactory factory, boolean devpath, boolean verbose) { this(factory, devpath); } /** * @param factory The {@link BrokerFactory} for which cached metadata * should be built. * @param devpath Whether or not to scan the development environment paths * to find persistent types to store. */ public MetaDataCacheMaintenance(BrokerFactory factory, boolean devpath) { this.factory = factory; this.conf = factory.getConfiguration(); this.devpath = devpath; this.log = conf.getLog(OpenJPAConfiguration.LOG_TOOL); } public void setLog(Log log) { this.log = log; } private static int usage() { System.err.println("Usage: java MetaDataCacheMaintenance " + "[-scanDevPath t|f] [- value] store | dump"); return -1; } /** * The metadata repository for the factory that this instance was * constructed with will be serialized, along with any query * compilations etc. that have been created for the factory. */ public void store() { MetaDataRepository repos = conf.getMetaDataRepositoryInstance(); repos.setSourceMode(MetaDataRepository.MODE_ALL); Collection types = repos.loadPersistentTypes(devpath, null); for (Iterator iter = types.iterator(); iter.hasNext(); ) repos.getMetaData((Class) iter.next(), null, true); loadQueries(); log.info("The following data will be stored: "); log(repos, conf.getQueryCompilationCacheInstance()); CacheMarshallersValue.getMarshallerById(conf, getClass().getName()) .store(new Object[] { repos, conf.getQueryCompilationCacheInstance() }); } private void loadQueries() { Broker broker = factory.newBroker(); try { QueryMetaData[] qmds = conf.getMetaDataRepositoryInstance().getQueryMetaDatas(); for (int i = 0; i < qmds.length; i++) loadQuery(broker, qmds[i]); } finally { broker.close(); } } private void loadQuery(Broker broker, QueryMetaData qmd) { try { Query q = broker.newQuery(qmd.getLanguage(), null); qmd.setInto(q); q.compile(); } catch (Exception e) { if (log.isTraceEnabled()) { log.warn("Skipping named query " + qmd.getName() + ": " + e.getMessage(), e); } else { log.warn("Skipping named query " + qmd.getName() + ": " + e.getMessage()); } } } public void dump() { Object[] os = (Object[]) CacheMarshallersValue.getMarshallerById(conf, getClass().getName()) .load(); if (os == null) { log.info("No cached data was found"); return; } MetaDataRepository repos = (MetaDataRepository) os[0]; Map qcc = (Map) os[1]; log.info("The following data was found: "); log(repos, qcc); } private void log(MetaDataRepository repos, Map qcc) { ClassMetaData[] metas = repos.getMetaDatas(); log.info(" Types: " + metas.length); if (log.isTraceEnabled()) for (int i = 0; i < metas.length; i++) log.trace(" " + metas[i].getDescribedType().getName()); QueryMetaData[] qmds = repos.getQueryMetaDatas(); log.info(" Queries: " + qmds.length); if (log.isTraceEnabled()) for (int i = 0; i < qmds.length; i++) log.trace(" " + qmds[i].getName() + ": " + qmds[i].getQueryString()); SequenceMetaData[] smds = repos.getSequenceMetaDatas(); log.info(" Sequences: " + smds.length); if (log.isTraceEnabled()) for (int i = 0; i < smds.length; i++) log.trace(" " + smds[i].getName()); log.info(" Compiled queries: " + (qcc == null ? "0" : "" + qcc.size())); if (log.isTraceEnabled() && qcc != null) for (Iterator iter = qcc.keySet().iterator(); iter.hasNext(); ) log.trace(" " + iter.next()); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/NoOpCacheMarshaller.java0000644000000000000000000000242112133327272027413 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; /** * Implementation of {@link CacheMarshaller} that does nothing. * * @since 1.1.0 */ public class NoOpCacheMarshaller implements CacheMarshaller { private String id; public Object load() { return null; } public void setId(String id) { this.id = id; } public String getId() { return id; } public void setValidationPolicy(String policy) { } public void store(Object o) { } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAProductDerivation.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAProductDerivation.jav0000644000000000000000000000303512133327272030264 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import org.apache.openjpa.lib.conf.ProductDerivation; import java.util.Map; /** * Adds datastore based extension to ProductDerivation. * * @since 0.4.1 * @author Pinaki Poddar */ public interface OpenJPAProductDerivation extends ProductDerivation { public static final int TYPE_SPEC = 0; public static final int TYPE_STORE = 200; public static final int TYPE_SPEC_STORE = 300; public static final int TYPE_PRODUCT_STORE = 400; /** * Load default alias options into the given map. Each entry maps an * alias to a broker factory class name. Replace anything previously * under the desired keys. */ public void putBrokerFactoryAliases(Map aliases); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java0000644000000000000000000006602312133327272026422 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; /** * Struct encompassing backwards-compatibility options. */ public class Compatibility { /** * If a JPQL statement is not compliant with the JPA specification, * fail to parse it. * * @since 1.1.0 */ public static final int JPQL_STRICT = 0; /** * If a JPQL statement is not compliant with the JPA specification, * warn the first time that statement is parsed. * * @since 1.1.0 */ public static final int JPQL_WARN = 1; /** * Allow non-compliant extensions of JPQL. * * @since 1.1.0 */ public static final int JPQL_EXTENDED = 2; private boolean _strictIdValues = false; private boolean _hollowLookups = true; private boolean _checkStore = false; private boolean _copyIds = false; private boolean _closeOnCommit = true; private boolean _quotedNumbers = false; private boolean _nonOptimisticVersionCheck = false; private int _jpql = JPQL_WARN; private boolean _storeMapCollectionInEntityAsBlob = false; private boolean _flushBeforeDetach = false; private boolean _cascadeWithDetach = false; private boolean _useJPA2DefaultOrderColumnName = true; private boolean _copyOnDetach = false; private boolean _privatePersistentProperties = false; private boolean _autoOff = true; private boolean _superclassDiscriminatorStrategyByDefault = true; private boolean _isAbstractMappingUniDirectional = false; private boolean _isNonDefaultMappingAllowed = false; private boolean _reloadOnDetach = false; private boolean _ignoreDetachedStateFieldForProxySerialization = false; private boolean _checkDatabaseForCascadePersistToDetachedEntity = false; private boolean _overrideContextClassloader = true; private boolean _parseAnnotationsForQueryMode = true; private boolean _convertPositionalParametersToNamed = false; private boolean _useListAttributeForArrays = false; private boolean _metaFactoriesAreStrict = false; private boolean _resetFlushFlagForCascadePersist = true;//OPENJPA-2051 private boolean _singletonLifecycleEventManager = false; private boolean _filterPCRegistryClasses = false; // OPENJPA-2288 /** * Whether to require exact identity value types when creating object * ids from a class and value. Defaults to false. */ public boolean getStrictIdentityValues() { return _strictIdValues; } /** * Whether to require exact identity value types when creating object * ids from a class and value. Defaults to false. */ public void setStrictIdentityValues(boolean strictVals) { _strictIdValues = strictVals; } /** * Whether to turn collection/map tracing off in case of more number of modifications. * Defaults to true. */ public boolean getAutoOff() { return _autoOff; } /** * Whether to turn collection/map tracing off in case of more number of modifications. * Defaults to true. */ public void setAutoOff(boolean autoOff) { _autoOff = autoOff; } /** * Whether to add class criteria for super class discreminator strategy. * Defaults to false. */ public boolean getSuperclassDiscriminatorStrategyByDefault() { return _superclassDiscriminatorStrategyByDefault; } /** * Whether to add class criteria for super class discreminator strategy. * Defaults to false. */ public void setSuperclassDiscriminatorStrategyByDefault(boolean superclassDiscriminatorStrategyByDefault) { _superclassDiscriminatorStrategyByDefault = superclassDiscriminatorStrategyByDefault; } /** * Whether to interpret quoted numbers in query strings as numbers. * OpenJPA versions 0.3.1 and prior treated them as numbers; more recent * versions treat them as strings. */ public boolean getQuotedNumbersInQueries() { return _quotedNumbers; } /** * Whether to interpret quoted numbers in query strings as numbers. * OpenJPA versions 0.3.1 and prior treated them as numbers; more recent * versions treat them as strings. */ public void setQuotedNumbersInQueries(boolean quotedNumbers) { _quotedNumbers = quotedNumbers; } /** * Whether to return hollow instances to broker lookups with a * validate parameter of false. OpenJPA versions prior to * 0.4.0 did not return hollow instances without special configuration * (the ObjectLookupMode). Beginning with 0.4.0, hollow * objects are the default. */ public boolean getValidateFalseReturnsHollow() { return _hollowLookups; } /** * Whether to return hollow instances to broker lookups with a * validate parameter of false. OpenJPA versions prior to * 0.4.0 did not return hollow instances without special configuration * (the ObjectLookupMode). Beginning with 0.4.0, hollow * objects are the default. */ public void setValidateFalseReturnsHollow(boolean hollow) { _hollowLookups = hollow; } /** * Whether to check the datastore for the existence of a nontransactional * cached object in broker lookups with a validate parameter * of true. OpenJPA versions prior to 0.4.0 checked the datastore. */ public boolean getValidateTrueChecksStore() { return _checkStore; } /** * Whether to check the datastore for the existence of a nontransactional * cached object in broker lookups with a validate parameter * of true. OpenJPA versions prior to 0.4.0 checked the datastore. */ public void setValidateTrueChecksStore(boolean check) { _checkStore = check; } /** * Whether to copy identity objects before returning them to client code. * Versions of OpenJPA prior to 0.3.0 always copied identity objects. Also, * you should configure OpenJPA to copy identity objects if you mutate them * after use. */ public boolean getCopyObjectIds() { return _copyIds; } /** * Whether to copy identity objects before returning them to client code. * Versions of OpenJPA prior to 0.3.0 always copied identity objects. Also, * you should configure OpenJPA to copy identity objects if you mutate them * after use. */ public void setCopyObjectIds(boolean copy) { _copyIds = copy; } /** * Whether to close the broker when the managed transaction commits. * Versions of OpenJPA prior to 0.3.0 did not close the broker. */ public boolean getCloseOnManagedCommit() { return _closeOnCommit; } /** * Whether to close the broker when the managed transaction commits. * Versions of OpenJPA prior to 0.3.0 did not close the broker. */ public void setCloseOnManagedCommit(boolean close) { _closeOnCommit = close; } /** * Whether or not to perform a version check on instances being updated * in a datastore transaction. Version of OpenJPA prior to 0.4.1 always * forced a version check. */ public void setNonOptimisticVersionCheck(boolean nonOptimisticVersionCheck){ _nonOptimisticVersionCheck = nonOptimisticVersionCheck; } /** * Whether or not to perform a version check on instances being updated * in a datastore transaction. Version of OpenJPA prior to 0.4.1 always * forced a version check. */ public boolean getNonOptimisticVersionCheck() { return _nonOptimisticVersionCheck; } /** * Whether or not JPQL extensions are allowed. Defaults to * {@link #JPQL_STRICT}. * * @since 1.1.0 * @see #JPQL_WARN * @see #JPQL_STRICT * @see #JPQL_EXTENDED */ public int getJPQL() { return _jpql; } /** * Whether or not JPQL extensions are allowed. Possible values: "warn", * "strict", "extended". * * @since 1.1.0 * @see #JPQL_WARN * @see #JPQL_STRICT * @see #JPQL_EXTENDED */ public void setJPQL(String jpql) { if ("warn".equals(jpql)) _jpql = JPQL_WARN; else if ("strict".equals(jpql)) _jpql = JPQL_STRICT; else if ("extended".equals(jpql)) _jpql = JPQL_EXTENDED; else throw new IllegalArgumentException(jpql); } /** * Whether if map and collection in entity are stored as blob. * Defaults to false. * * @since 1.1.0 */ public boolean getStoreMapCollectionInEntityAsBlob() { return _storeMapCollectionInEntityAsBlob; } /** * Whether if map and collection in entity are stored as blob. * Defaults to false. * * @since 1.1.0 */ public void setStoreMapCollectionInEntityAsBlob(boolean storeAsBlob) { _storeMapCollectionInEntityAsBlob = storeAsBlob; } /** * Whether OpenJPA should flush changes before detaching or serializing an * entity. In JPA this is usually false, but other persistence frameworks * (ie JDO) may expect it to be true. *

    Prior to version 1.0.3 and 1.2.0 changes were always flushed. * * @since 1.0.3 * @since 1.2.0 * @return true if changes should be flushed, otherwise false. */ public boolean getFlushBeforeDetach() { return _flushBeforeDetach; } /** * Whether OpenJPA should ignore the DetachedStateField value when * determining if our Proxy classes should be removed during serialization. *

    Starting with version 2.0.0, when the DetachedStateFiled==true, the * build time $proxy classes will not be removed. *

    Prior to version 2.0.0, the DetachedStateFiled was not used and * the $proxy classes were not being removed during serialization after * the Persistence context was cleared. * * @param ignoreDSF if true the old Proxy serialization behavior will be used. * * @since 2.0.0 */ public void setIgnoreDetachedStateFieldForProxySerialization(boolean ignoreDSF) { _ignoreDetachedStateFieldForProxySerialization = ignoreDSF; } /** * Whether OpenJPA should ignore the DetachedStateField value when * determining if our Proxy classes should be removed during serialization. *

    Starting with version 2.0.0, when the DetachedStateFiled==true, the * build time $proxy classes will not be removed. *

    Prior to version 2.0.0, the DetachedStateFiled was not used and * the $proxy classes were not being removed during serialization after * the Persistence context was cleared. * * @since 2.0.0 * @return true if the old Proxy serialization will be used, otherwise false. */ public boolean getIgnoreDetachedStateFieldForProxySerialization() { return _ignoreDetachedStateFieldForProxySerialization; } public boolean getConvertPositionalParametersToNamed() { return _convertPositionalParametersToNamed; } public void setConvertPositionalParametersToNamed(boolean c) { _convertPositionalParametersToNamed = c; } /** * Whether OpenJPA should flush changes before detaching or serializing an * entity. In JPA this is usually false, but other persistence frameworks * (ie JDO) may expect it to be true. *

    Prior to version 1.0.3 and 1.2.0 changes were always flushed. * * @param beforeDetach if true changes will be flushed before detaching or * serializing an entity. * * @since 1.0.3 * @since 1.2.0 */ public void setFlushBeforeDetach(boolean beforeDetach) { _flushBeforeDetach = beforeDetach; } /** * Affirms if detached entities are copy of the managed instances. * Before this option is introduced, detached entities were by default * copies of the managed entities unless the entire cache is detached, only * then the detachment was in-place. * This option changes the default behavior such that detachment is now * in-place by default. To emulate the previous copy-on-detach behavior * set this option to true. * * If the entire cache is being detached (when the persistence context is * closed, for example), the detachement * * @since 2.0.0 */ public boolean getCopyOnDetach() { return _copyOnDetach; } /** * Sets if detached entities are copy of the managed instances. * Before this option is introduced, detached entities were by default * copies of the managed entities unless the entire cache is detached, only * then the detachment was in-place. * This option changes the default behavior such that detachment is now * in-place by default. To emulate the previous copy-on-detach behavior * set this option to true. * * @since 2.0.0 */ public void setCopyOnDetach(boolean copyOnDetach) { _copyOnDetach = copyOnDetach; } /** * Whether openjpa will always cascade on detach, regardless of the * cascade setting. * * @return true if cascade will always occur, false if cascade will only * occur if it is specified in metadata * * @since 2.0.0 */ public boolean getCascadeWithDetach() { return _cascadeWithDetach; } /** * Whether openjpa should always cascade on detach, regardless of the * cascade setting. * * @param cascadeWithDetach true if cascade should always occur, false if * it should only occur if specified in metadata * * @since 2.0.0 */ public void setCascadeWithDetach(boolean cascadeWithDetach) { _cascadeWithDetach = cascadeWithDetach; } /** * Whether OpenJPA should use the new default order column name defined * by JPA 2.0: name; "_"; "ORDER" or the pre-JPA 2.0 default name "ordr". * * @since 2.0.0 * @return true if the JPA2 default name should be used */ public boolean getUseJPA2DefaultOrderColumnName() { return _useJPA2DefaultOrderColumnName; } /** * Whether OpenJPA should use the new default order column name defined * by JPA 2.0: name; "_"; "ORDER" or the pre-JPA 2.0 default name "ordr". * * @param useJPA2 true if the JPA 2.0 default name should be used. false if * the 1.x name should be used. * * @since 2.0.0 */ public void setUseJPA2DefaultOrderColumnName(boolean useJPA2Name) { _useJPA2DefaultOrderColumnName = useJPA2Name; } /** * Whether OpenJPA allows private, non-transient properties to be * persistent. Prior to OpenJPA 2.0, if property access was used, * private properties were considered persistent. This is contrary to the * JPA specification, which states that persistent properties must be * public or protected. The default value is false. * * @since 2.0.0 * @return true if non-transient private properties should be persistent */ public boolean getPrivatePersistentProperties() { return _privatePersistentProperties; } /** * Whether OpenJPA allows private, non-transient properties to be * persistent. Prior to OpenJPA 2.0, if property access was used, * private properties were considered persistent. This is contrary to the * JPA specification, which states that persistent properties must be * public or protected. * * @param privateProps true if non-transient private properties * should be persistent * @since 2.0.0 */ public void setPrivatePersistentProperties(boolean privateProps) { _privatePersistentProperties = privateProps; } /** * Whether OpenJPA allows bi-directional relationship in the MappedSuperclass. * Prior to OpenJPA 2.0, the bi-directional relationship in the MappedSuperclass, * is not blocked. This is contrary to the JPA specification, which states that * persistent relationships defined by a mapped superclass must be * unidirectional. * * @param isAbstractMappingUniDirectional true if relationship defined in the * MappedSuperclass must be uni-directional * @since 2.0.0 */ public void setAbstractMappingUniDirectional(boolean isAbstractMappingUniDirectional) { _isAbstractMappingUniDirectional = isAbstractMappingUniDirectional; } /** * Whether OpenJPA allows bi-directional relationship in the MappedSuperclass. * Prior to OpenJPA 2.0, the bi-directional relationship in the MappedSuperclass, * is not blocked. This is contrary to the JPA specification, which states that * persistent relationships defined by a mapped superclass must be * unidirectional. The default value is false. * * @since 2.0.0 */ public boolean isAbstractMappingUniDirectional() { return _isAbstractMappingUniDirectional; } /** * Whether OpenJPA allows non-default entity relationship mapping. * Prior to OpenJPA 2.0, the non-default entity relationship mapping * is not allowed. JPA 2.0 spec relaxes this restriction. The * default value is false. * @since 2.0.0 */ public void setNonDefaultMappingAllowed(boolean isNonDefaultMappingAllowed) { _isNonDefaultMappingAllowed = isNonDefaultMappingAllowed; } /** * Whether OpenJPA allows non-default entity relationship mapping. * Prior to OpenJPA 2.0, the non-default entity relationship mapping * is not allowed. JPA 2.0 spec relaxes this restriction. The * default value is false. * @since 2.0.0 */ public boolean isNonDefaultMappingAllowed() { return _isNonDefaultMappingAllowed; } /** * Whether OpenJPA should attempt to load fields when the DetachState * option is set to loaded. This also determines whether a * redundant copy of the version field is made. Beginning in 2.0 * it defaults to false. * * @return the _reloadOnDetach * * @since 1.2.2 */ public boolean getReloadOnDetach() { return _reloadOnDetach; } /** * Whether OpenJPA should attempt to load fields when the DetachState * option is set to loaded. This also determines whether a * redundant copy of the version field is made. Beginning in 2.0 * it defaults to false. * * @param reloadOnDetach the _reloadOnDetach to set * * @since 1.2.2 */ public void setReloadOnDetach(boolean reloadOnDetach) { _reloadOnDetach = reloadOnDetach; } /** * Whether OpenJPA will check the database for an Entity when cascading a persist to another Entity. This property * only applies for the case where we are trying to cascade a persist to an Entity which doesn't have a StateManager * and we can't determine if it is detached. * * @since 2.1.1 */ public boolean getCheckDatabaseForCascadePersistToDetachedEntity(){ return _checkDatabaseForCascadePersistToDetachedEntity; } /** * Whether OpenJPA will check the database for an Entity when cascading a persist to another Entity. This property * only applies for the case where we are trying to cascade a persist to an Entity which doesn't have a StateManager * and we can't determine if it is detached. * * @since 2.1.1 */ public void setCheckDatabaseForCascadePersistToDetachedEntity(boolean b){ _checkDatabaseForCascadePersistToDetachedEntity = b; } /** * Whether to temporally override the thread's Context Classloader when processing * ORM XML documents to avoid deadlock potential with certain Classloader hierarchy * configurations. Defaults to false. */ public boolean getOverrideContextClassloader() { return _overrideContextClassloader; } /** * Whether to temporally override the thread's Context Classloader when processing * ORM XML documents to avoid deadlock potential with certain Classloader hierarchy * configurations. Defaults to false. */ public void setOverrideContextClassloader(boolean overrideContextClassloader) { _overrideContextClassloader = overrideContextClassloader; } /** * Whether OpenJPA will scan every persistent class in an XML mapping file for annotations prior to executing a * query. In practice this scan is rarely needed, but the option to enable it is present for compatibility with * prior releases. * @since 2.0.2 * @return true if the annotations should be re-parsed when resolving MetaData in MODE_QUERY. */ public boolean getParseAnnotationsForQueryMode() { return _parseAnnotationsForQueryMode; } /** * Whether OpenJPA will scan every persistent class in an XML mapping file for annotations prior to executing a * query. In practice this scan is rarely needed, but the option to enable it is present for compatibility with * prior releases. * @since 2.0.2 */ public void setParseAnnotationsForQueryMode(boolean parseAnnotationsForQueryMode) { _parseAnnotationsForQueryMode = parseAnnotationsForQueryMode; } /** * This property can be used to allow OpenJPA to use ListAttributes for all types of Arrays, not just those with the * * @PersistentCollection annotation. If the canonical metamodel classes were generated in an early version of * OpenJPA (e.g. 2.0.0, 2.0.1, or 2.1.0) it is recommended to set this property to true. If * you have generated your metamodel classes on later versions of OpenJPA (e.g. 2.2.0) you may * want to have this set to false. * @since 2.2.0 * @return true if OpenJPA will use ListAttributes for all arrays, false if OpenJPA will use ListAttributes * for only arrays which use the @PersistentCollection annotation. */ public boolean getUseListAttributeForArrays() { return _useListAttributeForArrays; } /** * This property can be used to allow OpenJPA to use ListAttributes for all types of Arrays, not just those with the * * @PersistentCollection annotation. If the canonical metamodel classes were generated in an early version of * OpenJPA (e.g. 2.0.0, 2.0.1, or 2.1.0) it is recommended to set this property to true. If * you have generated your metamodel classes on later versions of OpenJPA (e.g. 2.2.0) you may * want to have this set to false. * @since 2.2.0 * @param useListAttribute * whether OpenJPA will use ListAttributes for all arrays. */ public void setUseListAttributeForArrays(boolean useListAttribute ) { _useListAttributeForArrays = useListAttribute; } /** * Whether the MetaDataFactory and MappingFactory should be set to strict mode. If strict mode is used a * MetaDataFactory will only resolve MetaData (no JDBC mappings), and a MappingFactory will only resolve Mapping * information. * * @since 2.2.0 * @return Whether strict mode should be used. */ public boolean getMetaFactoriesAreStrict() { return _metaFactoriesAreStrict; } /** * Set whether MetaDataFactories and MappingFactories will be strictly separate. * * @since 2.2.0 * * @param metaFactoriesAreStrict * True if the MetaDataFactory should only process metadata, and the MappingFactory should only process * mappings. */ public void setMetaFactoriesAreStrict(boolean metaFactoriesAreStrict) { _metaFactoriesAreStrict = metaFactoriesAreStrict; } /** * Whether OpenJPA should reset the internal state (flush flag) when cascading a persist to another * Entity. That is, when a flush is performed, OpenJPA keep state to indicate the flush has been * performed. In certain cascade persist scenarios the fact that a flush has been performed prior to * a cascade persist can cause certain entities to not be written to the database given the prior * flush. This property, when set, will cause the flush flag to be reset in cascade scenarios. For more * details see JIRA OPENJPA-2051 * * @since 2.0.x */ public boolean getResetFlushFlagForCascadePersist(){ return _resetFlushFlagForCascadePersist; } /** * Whether OpenJPA should reset the internal state (flush flag) when cascading a persist to another * Entity. That is, when a flush is performed, OpenJPA keep state to indicate the flush has been * performed. In certain cascade persist scenarios the fact that a flush has been performed prior to * a cascade persist can cause certain entities to not be written to the database given the prior * flush. This property, when set, will cause the flush flag to be reset in cascade scenarios. For more * details see JIRA OPENJPA-2051 * * @since 2.0.x */ public void setResetFlushFlagForCascadePersist(boolean b){ _resetFlushFlagForCascadePersist = b; } /** * Returns true if life cycle event manager is a singleton configuration. */ public boolean isSingletonLifecycleEventManager() { return _singletonLifecycleEventManager; } /** * This property set whether each EntityManager has its own life cycle event manager. By default, each EntityManager only fires events to the registered listeners to the entities it manages. If the life cycle event manager is a singleton, events will be fired to listeners registered to all instances of EntityManager in the same persistence unit. */ public void setSingletonLifecycleEventManager(boolean singleton) { _singletonLifecycleEventManager = singleton; } /** * Whether the metadata processor should filter classes dispatched by the PCRegistry listener system. **/ public boolean getFilterPCRegistryClasses() { return _filterPCRegistryClasses; } /** * Whether the metadata processor should filter classes dispatched by the PCRegistry listener system. **/ public void setFilterPCRegistryClasses(boolean bool) { _filterPCRegistryClasses = bool; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallerImpl.java0000644000000000000000000002054512133327272027450 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.URL; import java.util.Enumeration; import java.util.List; import java.util.ArrayList; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InternalException; /** * Default {@link CacheMarshaller} implementation that writes data * to a specified file and reads data from a specified file or URL. * * @since 1.1.0 */ public class CacheMarshallerImpl implements CacheMarshaller, Configurable { private static final Localizer _loc = Localizer.forPackage(CacheMarshallerImpl.class); private String _id; private ValidationPolicy _validationPolicy; private OpenJPAConfiguration _conf; private Log _log; private File _outputFile; private URL _inputURL; // temporary storage for resource location specification private String _inputResourceLocation; private boolean _consumeErrors = true; public Object load() { if (_inputURL == null) { _log.trace(_loc.get("cache-marshaller-no-inputs", getId())); return null; } Object o = null; ObjectInputStream in = null; try { in = new ObjectInputStream(new BufferedInputStream( _inputURL.openStream())); o = in.readObject(); o = _validationPolicy.getValidData(o); if (o != null && o.getClass().isArray()) { Object[] array = (Object[]) o; for (int i = 0; i < array.length; i++) configure(array[i]); } else { configure(o); } if (_log.isTraceEnabled()) _log.trace(_loc.get("cache-marshaller-loaded", o == null ? null : o.getClass().getName(), _inputURL)); } catch (Exception e) { if (_consumeErrors) { if (_log.isWarnEnabled()) _log.warn(_loc.get("cache-marshaller-load-exception-ignore", _inputURL), e); } else { throw new InternalException( _loc.get("cache-marshaller-load-exception-fatal", _inputURL), e); } } finally { if (in != null) try { in.close(); } catch (IOException e) { } } return o; } private void configure(Object o) { if (o instanceof Configurable) { ((Configurable) o).setConfiguration(_conf); ((Configurable) o).startConfiguration(); ((Configurable) o).endConfiguration(); } } public void store(Object o) { if (_outputFile == null) { _log.trace(_loc.get("cache-marshaller-no-output-file", getId())); return; } OutputStream out = null; try { out = new FileOutputStream(_outputFile); ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(out)); Object toStore = _validationPolicy.getCacheableData(o); oos.writeObject(toStore); oos.flush(); out.flush(); if (_log.isTraceEnabled()) _log.trace(_loc.get("cache-marshaller-stored", o.getClass().getName(), _outputFile)); } catch (Exception e) { if (_consumeErrors) { if (_log.isWarnEnabled()) _log.warn(_loc.get("cache-marshaller-store-exception", o.getClass().getName(), _outputFile), e); } else { throw new InternalException( _loc.get("cache-marshaller-store-exception", o.getClass().getName(), _outputFile), e); } } finally { if (out != null) { try { out.close(); } catch (IOException ioe) { } } } } public void setOutputFile(File file) { _outputFile = file; } public File getOutputFile() { return _outputFile; } public void setInputURL(URL url) { _inputURL = url; } public void setInputResource(String resource) { _inputResourceLocation = resource; } public void setConsumeSerializationErrors(boolean consume) { _consumeErrors = consume; } public String getId() { return _id; } public void setId(String id) { _id = id; } public void setValidationPolicy(String policy) throws InstantiationException, IllegalAccessException { String name = Configurations.getClassName(policy); String props = Configurations.getProperties(policy); _validationPolicy = (ValidationPolicy) Configurations.newInstance(name, _conf, props, null); } public ValidationPolicy getValidationPolicy() { return _validationPolicy; } public void setConfiguration(Configuration conf) { _conf = (OpenJPAConfiguration) conf; _log = conf.getConfigurationLog(); } public void startConfiguration() { } public void endConfiguration() { if (_inputResourceLocation != null && _inputURL != null) throw new IllegalStateException( _loc.get("cache-marshaller-input-url-and-resource-specified") .getMessage()); if (_inputResourceLocation != null) setInputUrlFromResourceLocation(); if (_validationPolicy == null) throw new IllegalStateException( _loc.get("cache-marshaller-null-validation-policy", getClass().getName()).getMessage()); if (_id == null) throw new IllegalStateException( _loc.get("cache-marshaller-null-id", getClass().getName()).getMessage()); } private void setInputUrlFromResourceLocation() { try { ClassLoader cl = _conf.getClassResolverInstance() .getClassLoader(getClass(), null); List list = new ArrayList(); for (Enumeration e = cl.getResources(_inputResourceLocation); e.hasMoreElements(); ) list.add(e.nextElement()); if (list.size() > 1) { if (_consumeErrors) { if (_log.isWarnEnabled()) _log.warn(_loc.get( "cache-marshaller-multiple-resources-warn", getId(), _inputResourceLocation, list) .getMessage()); } else { throw new IllegalStateException( _loc.get("cache-marshaller-multiple-resources", getId(), _inputResourceLocation, list) .getMessage()); } } if (!list.isEmpty()) _inputURL = (URL) list.get(0); } catch (IOException ioe) { IllegalStateException ise = new IllegalStateException( _loc.get("cache-marshaller-bad-url", getId(), _inputResourceLocation).getMessage()); ise.initCause(ioe); throw ise; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/AutoDetachValue.java0000644000000000000000000000567012133327272026630 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.util.ArrayList; import java.util.List; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.lib.conf.StringListValue; /** * Value type used to represent auto detach flags. Separate to * optimize translation of Strings to bit flags. * * @author Steve Kim * @nojavadoc */ class AutoDetachValue extends StringListValue { public static final String DETACH_CLOSE = "close"; public static final String DETACH_COMMIT = "commit"; public static final String DETACH_ROLLBACK= "rollback"; public static final String DETACH_NONTXREAD = "nontx-read"; public static final String DETACH_NONE = "none"; private static String[] ALIASES = new String[]{ DETACH_CLOSE, String.valueOf(AutoDetach.DETACH_CLOSE), DETACH_COMMIT, String.valueOf(AutoDetach.DETACH_COMMIT), DETACH_NONTXREAD, String.valueOf(AutoDetach.DETACH_NONTXREAD), DETACH_ROLLBACK, String.valueOf(AutoDetach.DETACH_ROLLBACK), DETACH_NONE, String.valueOf(AutoDetach.DETACH_NONE), // for compatibility with JDO DetachAllOnCommit "true", String.valueOf(AutoDetach.DETACH_COMMIT), "false", "0", }; private int _flags; private boolean _flagsSet; public AutoDetachValue() { super("AutoDetach"); setAliases(ALIASES); setAliasListComprehensive(true); } public Class getValueType() { return String[].class; } public void setConstant(int flags) { _flags = flags; } public int getConstant() { if (!_flagsSet) { String[] vals = get(); for (int i = 0; i < vals.length; i++) _flags |= Integer.parseInt(unalias(vals[i])); _flagsSet = true; } return _flags; } protected List getAliasList() { // We do not document the numeric values and they are not // helpful to someone trying to understand the error message ArrayList list = new ArrayList(); for (int x = 0; x < ALIASES.length; x += 2) list.add(ALIASES[x]); return list; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/BrokerValue.java0000644000000000000000000000574012133327272026031 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import org.apache.openjpa.lib.conf.PluginValue; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.kernel.BrokerImpl; import org.apache.openjpa.kernel.FinalizingBrokerImpl; import org.apache.openjpa.util.InternalException; /** * Custom {@link PluginValue} that can efficiently create {@link BrokerImpl} * instances. * * @since 0.9.7 */ public class BrokerValue extends PluginValue { public static final String KEY = "BrokerImpl"; public static final String NON_FINALIZING_ALIAS = "non-finalizing"; public static final String DEFAULT_ALIAS = "default"; private BrokerImpl _templateBroker; public BrokerValue() { super(KEY, false); String[] aliases = new String[] { DEFAULT_ALIAS, FinalizingBrokerImpl.class.getName(), NON_FINALIZING_ALIAS, BrokerImpl.class.getName(), }; setAliases(aliases); setDefault(aliases[0]); setString(aliases[0]); } public Object newInstance(String clsName, Class type, Configuration conf, boolean fatal) { getTemplateBroker(clsName, type, conf, fatal); try { return _templateBroker.clone(); } catch (CloneNotSupportedException e) { throw new InternalException(e); } } public Class getTemplateBrokerType(Configuration c) { return getTemplateBroker(getClassName(), BrokerImpl.class, c, true) .getClass(); } private BrokerImpl getTemplateBroker(String clsName, Class type, Configuration conf, boolean fatal) { if (clsName == null || !clsName.equals(getClassName())) throw new IllegalArgumentException("clsName != configured value '" + getClassName() + "'"); // This is not synchronized. If there are concurrent invocations // while _templateBroker is null, we'll just end up with extra // template brokers, which will get safely garbage collected. if (_templateBroker == null) _templateBroker = (BrokerImpl) super.newInstance(clsName, type, conf, fatal); return _templateBroker; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java0000644000000000000000000015457712133327272027611 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.util.Collection; import java.util.Map; import org.apache.openjpa.audit.Auditor; import org.apache.openjpa.datacache.CacheDistributionPolicy; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.datacache.DataCacheManager; import org.apache.openjpa.datacache.DataCacheMode; import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.enhance.RuntimeUnenhancedClassesModes; import org.apache.openjpa.event.BrokerFactoryEventManager; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.event.OrphanedKeyAction; import org.apache.openjpa.event.RemoteCommitEventManager; import org.apache.openjpa.event.RemoteCommitProvider; import org.apache.openjpa.instrumentation.InstrumentationManager; import org.apache.openjpa.kernel.AutoClear; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.BrokerImpl; import org.apache.openjpa.kernel.ConnectionRetainModes; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.FinderCache; import org.apache.openjpa.kernel.InverseManager; import org.apache.openjpa.kernel.LockManager; import org.apache.openjpa.kernel.PreparedQueryCache; import org.apache.openjpa.kernel.QueryFlushModes; import org.apache.openjpa.kernel.RestoreState; import org.apache.openjpa.kernel.SavepointManager; import org.apache.openjpa.kernel.Seq; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.encryption.EncryptionProvider; import org.apache.openjpa.meta.MetaDataFactory; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.ClassResolver; import org.apache.openjpa.util.ProxyManager; import org.apache.openjpa.util.StoreFacadeTypeRegistry; /** * Defines the properties necessary to configure runtime properties and * connect to a data source. There is a 1-1 relation between a configuration * and a {@link BrokerFactory}. * All setter methods that take primitive parameters also have wrapper * setter with the appropriate primitive wrapper. This is so the interface * can be in accordance with the J2EE Connector Architecture. * * @author Marc Prud'hommeaux * @author Abe White * @see Configuration */ public interface OpenJPAConfiguration extends Configuration { /** * Name of logger for metadata-related messages: * openjpa.MetaData. */ public static final String LOG_METADATA = "openjpa.MetaData"; /** * Name of logger for enhancement-related messages: * openjpa.Enhance. */ public static final String LOG_ENHANCE = "openjpa.Enhance"; /** * Name of logger for messages from the runtime system: * openjpa.Runtime. */ public static final String LOG_RUNTIME = "openjpa.Runtime"; /** * Name of logger for query logging: * openjpa.Query. */ public static final String LOG_QUERY = "openjpa.Query"; /** * Name of logger for messages from the data cache: * openjpa.DataCache. */ public static final String LOG_DATACACHE = "openjpa.DataCache"; /** * Name of logger for messages from the development tools: * openjpa.Tool. */ public static final String LOG_TOOL = "openjpa.Tool"; /** * Option for runtimes that support nontransactional reads. */ public static final String OPTION_NONTRANS_READ = "openjpa.option.NontransactionalRead"; /** * Option for runtimes that support optimistic transactions. */ public static final String OPTION_OPTIMISTIC = "openjpa.option.Optimistic"; /** * Option for runtimes that support application identity. */ public static final String OPTION_ID_APPLICATION = "openjpa.option.ApplicationIdentity"; /** * Option for runtimes that support application identity. */ public static final String OPTION_ID_DATASTORE = "openjpa.option.DatastoreIdentity"; /** * Option for SQL support. */ public static final String OPTION_QUERY_SQL = "openjpa.option.SQL"; /** * Option for runtimes that support persistent collection fields. */ public static final String OPTION_TYPE_COLLECTION = "openjpa.option.Collection"; /** * Option for runtimes that support persistent map fields. */ public static final String OPTION_TYPE_MAP = "openjpa.option.Map"; /** * Option for runtimes that support persistent array fields. */ public static final String OPTION_TYPE_ARRAY = "openjpa.option.Array"; /** * Option for runtime that can differentiate between null and empty * container fields. */ public static final String OPTION_NULL_CONTAINER = "openjpa.option.NullContainer"; /** * Option for runtimes that support embedded relations to other * persistence capable objects. */ public static final String OPTION_EMBEDDED_RELATION = "openjpa.option.EmbeddedRelation"; /** * Option for runtimes that support collections of embedded * relations to other persistence capable objects. */ public static final String OPTION_EMBEDDED_COLLECTION_RELATION = "openjpa.option.EmbeddedCollectionRelation"; /** * Option for runtimes that support maps of embedded * relations to other persistence capable objects. */ public static final String OPTION_EMBEDDED_MAP_RELATION = "openjpa.option.EmbeddedMapRelation"; /** * Option for runtimes that support incremental flushing. */ public static final String OPTION_INC_FLUSH = "openjpa.option.IncrementalFlush"; /** * Option for runtimes that the autoassign value strategy. */ public static final String OPTION_VALUE_AUTOASSIGN = "openjpa.option.AutoassignValue"; /** * Option for runtimes that the increment value strategy. */ public static final String OPTION_VALUE_INCREMENT = "openjpa.option.IncrementValue"; /** * Option for runtimes that support returning the datastore connection. */ public static final String OPTION_DATASTORE_CONNECTION = "openjpa.option.DataStoreConnection"; /** * Option for runtimes that support returning the datastore connection * that is a JDBC Connection. */ public static final String OPTION_JDBC_CONNECTION = "openjpa.option.JDBCConnection"; /** * Option for enable fire @PostLoad events on merge operations */ public static final String OPTION_POSTLOAD_ON_MERGE = "openjpa.option.PostLoadOnMerge"; /** * Return the set of option strings supported by this runtime. This set * is mutable. */ public Collection supportedOptions(); /** * Get a name of the Specification. Specification determines various * important default behaviors. */ public String getSpecification(); /** * Get the Specification. Specification determines various important default * behaviors. * * @since 2.0.0 */ public Specification getSpecificationInstance(); /** * Set the Specification for this configuration. * Specification determines various default properties and behavior. * For example, {@link Compatibility compatibility} options during runtime. * * This change will trigger all registered Product Derivations to mutate * other configuration properties. * * @param spec fullname of the specification that possibly encodes major and * minor version information. For encoding format * @see Specification * * @since 1.1.0 */ public void setSpecification(String spec); /** * Set the Specification for this configuration. * Specification determines various default properties and behavior. * For example, {@link Compatibility compatibility} options during runtime. * * This change will trigger all registered Product Derivations to mutate * other configuration properties. * * @param spec fullname of the specification that possibly encodes major and * minor version information. For encoding format * @see Specification * * @since 2.0.0 */ public void setSpecification(Specification spec); /** * The plugin string for the {@link ClassResolver} to use for custom * class loading. */ public String getClassResolver(); /** * The plugin string for the {@link ClassResolver} to use for custom * class loading. */ public void setClassResolver(String classResolver); /** * The {@link ClassResolver} to use. */ public ClassResolver getClassResolverInstance(); /** * The {@link ClassResolver} to use. */ public void setClassResolver(ClassResolver classResolver); /** * The {@link BrokerFactory} class to use. */ public String getBrokerFactory(); /** * The {@link BrokerFactory} class to use. */ public void setBrokerFactory(String factory); /** * The plugin string of the {@link BrokerImpl} extension to create. */ public String getBrokerImpl(); /** * The plugin string of the {@link BrokerImpl} extension to create. */ public void setBrokerImpl(String broker); /** * Create a new broker instance with the configured plugin data. */ public BrokerImpl newBrokerInstance(String user, String pass); /** * The {@link DataCache} to use for level-2 data store caching. */ public String getDataCache(); /** * The {@link DataCache} to use for level-2 data store caching. */ public void setDataCache(String dataCache); /** * The data cache manager manages this configuration's cache instances. */ public String getDataCacheManager(); /** * The data cache manager manages this configuration's cache instances. */ public void setDataCacheManager(String mgr); /** * The data cache manager manages this configuration's cache instances. * The cache manager is created if it has not been set. Once the cache * manager has been set/created, all changes to caching configuration * must proceed through the cache manager. * * @since 0.3.0 */ public DataCacheManager getDataCacheManagerInstance(); /** * The data cache manager manages this configuration's cache instances. * * @since 0.3.0 */ public void setDataCacheManager(DataCacheManager manager); /** * Default data cache timeout. * * @since 0.2.5 */ public int getDataCacheTimeout(); /** * Default data cache timeout. * * @since 0.2.5 */ public void setDataCacheTimeout(int timeout); /** * Wrapper for JCA usage of {@link #setDataCacheTimeout(int)}. * * @since 0.2.5 */ public void setDataCacheTimeout(Integer timeout); /** * Gets whether entity state is to be refreshed from {@link DataCache}. * The entities are never refreshed from DataCache if lock is being applied * (e.g. in a pessimistic transaction) and hence this setting only refers * to behavior when not locking. * This flag can be used to overwrite RetrieveMode.BYPASS. * By default, however, this falg is false. * * @since 1.2.0 */ public boolean getRefreshFromDataCache(); /** * Sets whether entity state is to be refreshed from {@link DataCache}. * The entities are never refreshed from DataCache if lock is being applied * (e.g. in a pessimistic transaction) and hence this setting only refers * to behavior when not locking. * * @since 1.2.0 */ public void setRefreshFromDataCache(boolean refreshFromDataCache); /** * Sets whether entity state is to be refreshed from {@link DataCache}. * The entities are never refreshed from DataCache if lock is being applied * (e.g. in a pessimistic transaction) and hence this setting only refers * to behavior when not locking. * * @since 1.2.0 */ public void setRefreshFromDataCache(Boolean refreshFromDataCache); /** * The plugin to use for level-2 data store query caching. * * @since 0.2.5 */ public String getQueryCache(); /** * The plugin to use for level-2 data store query caching. * * @since 0.2.5 */ public void setQueryCache(String queryCache); /** * Return whether to generate dynamic data structures * where possible for cache and runtime usage. * * @since 0.3.3 */ public boolean getDynamicDataStructs(); /** * Set whether to generate dynamic data structures * where possible for cache and runtime usage. * * @since 0.3.3 */ public void setDynamicDataStructs(boolean dynamic); /** * Wrapper for JCA usage of {@link #setDynamicDataStructs(boolean)}. */ public void setDynamicDataStructs(Boolean dynamic); /** * The plugin to use for datastore lock management. * * @since 0.3.1 */ public String getLockManager(); /** * The plugin to use for datastore lock management. * * @since 0.3.1 */ public void setLockManager(String lockManager); /** * Return a new lock manager instance using the configured plugin settings. */ public LockManager newLockManagerInstance(); /** * The plugin to use for managing inverse relations. * * @since 0.3.2 */ public String getInverseManager(); /** * The plugin to use for managing inverse relations. * * @since 0.3.2 */ public void setInverseManager(String inverse); /** * Return a new inverse manager instance using the configured plugin * settings. * * @since 0.3.2 */ public InverseManager newInverseManagerInstance(); /** * The plugin to use for savepoint management. * * @since 0.3.4 */ public String getSavepointManager(); /** * The plugin to use for savepoint management. * * @since 0.3.4 */ public void setSavepointManager(String savepointManager); /** * Return the configured savepoint manager instance. */ public SavepointManager getSavepointManagerInstance(); /** * The action to take when an orphaned key is detected. * * @since 0.3.2.2 */ public String getOrphanedKeyAction(); /** * The action to take when an orphaned key is detected. * * @since 0.3.2.2 */ public void setOrphanedKeyAction(String action); /** * The action to take when an orphaned key is detected. * * @since 0.3.2.2 */ public OrphanedKeyAction getOrphanedKeyActionInstance(); /** * The action to take when an orphaned key is detected. * * @since 0.3.2.2 */ public void setOrphanedKeyAction(OrphanedKeyAction action); /** * The plugin to use for remote commit notification. * * @since 0.2.5 */ public String getRemoteCommitProvider(); /** * The plugin to use for remote commit notification. * * @since 0.2.5 */ public void setRemoteCommitProvider(String remoteCommitProvider); /** * Create a remote commit provider from the configured plugin. * * @since 0.3.0 */ public RemoteCommitProvider newRemoteCommitProviderInstance(); /** * The remote event manager that manages this configuration's remote * event listeners. * * @since 0.3.0 */ public RemoteCommitEventManager getRemoteCommitEventManager(); /** * The remote event manager that manages this configuration's remote * event listeners. * * @since 0.3.0 */ public void setRemoteCommitEventManager(RemoteCommitEventManager manager); /** * Specifies the behavior of the transaction model. Possible values are: *

      *
    • local: Perform transaction operations locally.
    • *
    • managed: Use managed environment's global * transactions.
    • *
    * * @since 0.2.5 */ public String getTransactionMode(); /** * Specifies the behavior of the transaction model. Possible values are: *
      *
    • local: Perform transaction operations locally.
    • *
    • managed: Use managed environment's global * transactions.
    • *
    * * @since 0.2.5 */ public void setTransactionMode(String mode); /** * Return whether managed transactions are being used. */ public boolean isTransactionModeManaged(); /** * Set whether managed transactions are being used. */ public void setTransactionModeManaged(boolean managed); /** * The plugin string for the {@link ManagedRuntime} to use for managed * environments. */ public String getManagedRuntime(); /** * The plugin string for the {@link ManagedRuntime} to use for managed * environments. */ public void setManagedRuntime(String managedRuntime); /** * The plugin to use for integrating with a managed runtime. */ public ManagedRuntime getManagedRuntimeInstance(); /** * The plugin to use for integrating with a managed runtime. */ public void setManagedRuntime(ManagedRuntime runtime); /** * The plugin string for the {@link ProxyManager} to use for second * class object proxies. */ public String getProxyManager(); /** * The plugin string for the {@link ProxyManager} to use for second * class object proxies. */ public void setProxyManager(String proxyManager); /** * The {@link ProxyManager} to use. */ public ProxyManager getProxyManagerInstance(); /** * The {@link ProxyManager} to use. */ public void setProxyManager(ProxyManager manager); /** * The name mapping to use for this data store. */ public String getMapping(); /** * The name mapping to use for this data store. */ public void setMapping(String mapping); /** * A plugin string describing the {@link MetaDataFactory} to use. */ public String getMetaDataFactory(); /** * A plugin string describing the {@link MetaDataFactory} to use. */ public void setMetaDataFactory(String meta); /** * Create a new {@link MetaDataFactory} to use with a repository. */ public MetaDataFactory newMetaDataFactoryInstance(); /** * A plugin string describing the {@link MetaDataRepository} to use. */ public String getMetaDataRepository(); /** * A plugin string describing the {@link MetaDataRepository} to use. */ public void setMetaDataRepository(String meta); /** * The metadata repository of managed class information. If no * repository has been set, creates one. * * @since 0.3.0 */ public MetaDataRepository getMetaDataRepositoryInstance(); /** * Returns true if a metaDataRepository has been created for this * configuration. * * @since 1.1.0 1.0.1 */ public boolean metaDataRepositoryAvailable(); /** * Create a new empty metadata repository of the configured type. */ public MetaDataRepository newMetaDataRepositoryInstance(); /** * The metadata repository of managed class information. * * @since 0.3.0 */ public void setMetaDataRepository(MetaDataRepository mdRepos); /** * The user name for the data store connection. */ public String getConnectionUserName(); /** * The user name for the data store connection. */ public void setConnectionUserName(String connectionUserName); /** * The password for the data store connection. */ public String getConnectionPassword(); /** * The password for the data store connection. */ public void setConnectionPassword(String connectionPassword); /** * The URL for the data store connection. */ public String getConnectionURL(); /** * The URL for the data store connection. */ public void setConnectionURL(String connectionURL); /** * Class name of the connection driver. */ public String getConnectionDriverName(); /** * Class name of the connection driver. */ public void setConnectionDriverName(String driverName); /** * The name for the data store connection factory. */ public String getConnectionFactoryName(); /** * The name for the data store connection factory. */ public void setConnectionFactoryName(String cfName); /** * The connection factory, possibly from JNDI. */ public Object getConnectionFactory(); /** * The connection factory. */ public void setConnectionFactory(Object factory); /** * These properties provide any additional information needed to * establish connections. */ public String getConnectionProperties(); /** * These properties provide any additional information needed to * establish connections. */ public void setConnectionProperties(String props); /** * Configuration properties for the connection factory. */ public String getConnectionFactoryProperties(); /** * Configuration properties for the connection factory. */ public void setConnectionFactoryProperties(String props); /** * The mode of the connection factory in use. Available options are: *
      *
    • local: OpenJPA controls the connections.
    • *
    • managed: Connections are automatically enlisted in * the current global transaction by an application server.
    • *
    Defaults to local. */ public String getConnectionFactoryMode(); /** * The mode of the connection factory in use. Available options are: *
      *
    • local: OpenJPA controls the connections.
    • *
    • managed: Connections are automatically enlisted in * the current global transaction by an application server.
    • *
    Defaults to local. */ public void setConnectionFactoryMode(String mode); /** * Whether connections are automatically enlisted in global transactions. */ public boolean isConnectionFactoryModeManaged(); /** * Whether connections are automatically enlisted in global transactions. */ public void setConnectionFactoryModeManaged(boolean managed); /** * The user name for the non-XA data store connection. */ public String getConnection2UserName(); /** * The user name for the non-XA data store connection. */ public void setConnection2UserName(String connectionUserName); /** * The password for the non-XA data store connection. */ public String getConnection2Password(); /** * The password for the non-XA data store connection. */ public void setConnection2Password(String connectionPassword); /** * The URL for the non-XA data store connection. */ public String getConnection2URL(); /** * The URL for the non-XA data store connection. */ public void setConnection2URL(String connectionURL); /** * Class name of the non-XA connection driver. */ public String getConnection2DriverName(); /** * Class name of the non-XA connection driver. */ public void setConnection2DriverName(String driverName); /** * The name for the second data store connection factory. */ public String getConnectionFactory2Name(); /** * The name for the second data store connection factory. */ public void setConnectionFactory2Name(String cf2Name); /** * The non-XA connection factory. */ public Object getConnectionFactory2(); /** * The non-XA connection factory. */ public void setConnectionFactory2(Object factory); /** * These properties provide any additional information needed to * establish non-XA connections. * * @since 0.3.0 */ public String getConnection2Properties(); /** * These properties provide any additional information needed to * establish non-XA connections. * * @since 0.3.0 */ public void setConnection2Properties(String props); /** * Configuration properties for the non-XA connection factory. * * @since 0.2.5 */ public String getConnectionFactory2Properties(); /** * Configuration properties for the non-XA connection factory. * * @since 0.2.5 */ public void setConnectionFactory2Properties(String props); /** * Whether to use optimistic transactions by default. */ public boolean getOptimistic(); /** * Whether to use optimistic transactions by default. */ public void setOptimistic(boolean optimistic); /** * Wrapper for JCA usage of {@link #setOptimistic(boolean)}. */ public void setOptimistic(Boolean optimistic); /** * Whether to retain state after a transaction by default. */ public boolean getRetainState(); /** * Whether to retain state after a transaction by default. */ public void setRetainState(boolean retainState); /** * Wrapper for JCA usage of {@link #setRetainState(boolean)}. */ public void setRetainState(Boolean retainState); /** * Whether instances clear their state when entering a transaction. */ public String getAutoClear(); /** * Whether instances clear their state when entering a transaction. */ public void setAutoClear(String clear); /** * Return the {@link AutoClear} constant. */ public int getAutoClearConstant(); /** * Whether instances clear their state when entering a transaction. */ public void setAutoClear(int clear); /** * Whether to restore initial state on rollback by default. */ public String getRestoreState(); /** * Whether to restore initial state on rollback by default. */ public void setRestoreState(String restoreState); /** * Return the {@link RestoreState} constant. */ public int getRestoreStateConstant(); /** * Whether to restore initial state on rollback by default. */ public void setRestoreState(int restoreState); /** * Whether changes in the current transaction are taken into account when * executing queries and iterating extents. */ public boolean getIgnoreChanges(); /** * Whether changes in the current transaction are taken into account when * executing queries and iterating extents. */ public void setIgnoreChanges(boolean ignoreChanges); /** * Wrapper for JCA usage of {@link #setIgnoreChanges(boolean)}. */ public void setIgnoreChanges(Boolean ignoreChanges); /** * A comma-separated list of events which trigger auto-detachment * in place of managed states. Possible values are: *
      *
    • commit: When the current transaction commits.
    • *
    • close: When the broker closes.
    • *
    • nontx-read: When instances are read * non-transactionally.
    • *
    */ public String getAutoDetach(); /** * A comma-separated list of events which trigger auto-detachment * in place of managed states. Possible values are: *
      *
    • commit: When the current transaction commits.
    • *
    • close: When the broker closes.
    • *
    • nontx-read: When instances are read * non-transactionally.
    • *
    */ public void setAutoDetach(String detach); /** * The {@link AutoDetach} flags. */ public int getAutoDetachConstant(); /** * The {@link AutoDetach} flags. */ public void setAutoDetach(int flags); /** * Which field values to include when detaching. */ public void setDetachState(String detachState); /** * Return the instance specified by the detach state plugin. */ public DetachOptions getDetachStateInstance(); /** * Return the instance specified by the detach state plugin. */ public void setDetachState(DetachOptions detachState); /** * Whether persistent state is accessible outside a transaction by default. */ public boolean getNontransactionalRead(); /** * Whether persistent state is accessible outside a transaction by default. */ public void setNontransactionalRead(boolean ntRead); /** * Wrapper for JCA usage of {@link #setNontransactionalRead(boolean)}. */ public void setNontransactionalRead(Boolean ntRead); /** * Whether persistent state can be modified outside a transaction by * default. */ public boolean getNontransactionalWrite(); /** * Whether persistent state can be modified outside a transaction by * default. */ public void setNontransactionalWrite(boolean ntWrite); /** * Wrapper for JCA usage of {@link #setNontransactionalWrite(boolean)}. */ public void setNontransactionalWrite(Boolean ntWrite); /** * Whether brokers or their managed objects will be used by multiple * concurrent threads. */ public boolean getMultithreaded(); /** * Whether brokers or their managed objects will be used by multiple * concurrent threads. */ public void setMultithreaded(boolean multithreaded); /** * Wrapper for JCA usage of {@link #setMultithreaded(boolean)}. */ public void setMultithreaded(Boolean multithreaded); /** * Get the size of the batch that will be pre-selected when accessing * elements in a query or relationship. Use -1 to prefetch all results. */ public int getFetchBatchSize(); /** * Set the size of the batch that will be pre-selected when accessing * elements in a query or relationship. Use -1 to prefetch all results. */ public void setFetchBatchSize(int size); /** * Wrapper for JCA usage of {@link #setFetchBatchSize(int)}. */ public void setFetchBatchSize(Integer size); /** * The maximum relation depth to traverse when eager fetching. Use * -1 for no limit. */ public int getMaxFetchDepth(); /** * The maximum relation depth to traverse when eager fetching. Use * -1 for no limit. */ public void setMaxFetchDepth(int depth); /** * Wrapper for JCA usage of {@link #setMaxFetchDepth(int)}. */ public void setMaxFetchDepth(Integer size); /** * Comma-separated list of fetch group names that will be pre-set for * all new {@link FetchConfiguration}s. * * @since 0.2.5 */ public String getFetchGroups(); /** * Comma-separated list of fetch group names that will be pre-set for * all new {@link FetchConfiguration}s. * * @since 0.2.5 */ public void setFetchGroups(String groups); /** * List of fetch group names that will be pre-set for all new * {@link FetchConfiguration}s. */ public String[] getFetchGroupsList(); /** * List of fetch group names that will be pre-set for all new * {@link FetchConfiguration}s. */ public void setFetchGroups(String[] names); /** * Returns whether or not OpenJPA should automatically flush * modifications to the data store before executing queries. * * @since 0.2.5 */ public String getFlushBeforeQueries(); /** * Sets whether or not OpenJPA should automatically flush * modifications to the data store before executing queries. * * @since 0.2.5 */ public void setFlushBeforeQueries(String flush); /** * Returns one of {@link QueryFlushModes#FLUSH_TRUE}, * {@link QueryFlushModes#FLUSH_FALSE}, or * {@link QueryFlushModes#FLUSH_WITH_CONNECTION}, as determined * by parsing the string returned by {@link #getFlushBeforeQueries}. * * @since 0.2.5 */ public int getFlushBeforeQueriesConstant(); /** * Set to one of {@link QueryFlushModes#FLUSH_TRUE}, * {@link QueryFlushModes#FLUSH_FALSE}, or * {@link QueryFlushModes#FLUSH_WITH_CONNECTION}. * * @since 0.2.5 */ public void setFlushBeforeQueries(int flushBeforeQueries); /** * The time to wait for an object lock in milliseconds, or -1 for no * timeout. * * @since 0.3.1 */ public int getLockTimeout(); /** * The time to wait for an object lock in milliseconds, or -1 for no * timeout. * * @since 0.3.1 */ public void setLockTimeout(int timeout); /** * Wrapper for JCA usage of {@link #setLockTimeout(int)}. * * @since 0.3.1 */ public void setLockTimeout(Integer timeout); /** * The time to wait for a query to execute in milliseconds, or -1 for no * timeout. * * @since 2.0.0 */ public int getQueryTimeout(); /** * The time to wait for a query to execute in milliseconds, or -1 for no * timeout. * * @since 0.3.1 */ public void setQueryTimeout(int timeout); /** * The default read lock level to use during non-optimistic transactions. * Defaults to read. * * @since 0.3.1 */ public String getReadLockLevel(); /** * The default read lock level to use during non-optimistic transactions. * Defaults to read. * * @since 0.3.1 */ public void setReadLockLevel(String level); /** * The numeric read lock level. * * @since 0.3.1 */ public int getReadLockLevelConstant(); /** * The numeric read lock level. * * @since 0.3.1 */ public void setReadLockLevel(int level); /** * The default write lock level to use during non-optimistic transactions. * Defaults to write. * * @since 0.3.1 */ public String getWriteLockLevel(); /** * The default write lock level to use during non-optimistic transactions. * Defaults to write. * * @since 0.3.1 */ public void setWriteLockLevel(String level); /** * The numeric write lock level. * * @since 0.3.1 */ public int getWriteLockLevelConstant(); /** * The numeric write lock level. * * @since 0.3.1 */ public void setWriteLockLevel(int level); /** * Plugin string for the default system {@link Seq}. */ public String getSequence(); /** * Plugin string for the default system {@link Seq}. */ public void setSequence(String sequence); /** * The default system sequence. */ public Seq getSequenceInstance(); /** * The default system sequence. */ public void setSequence(Seq sequence); /** * Specifies the behavior of the broker with respect to data store * connections. Possible values are: *
      *
    • always: Each broker obtains a single connection and * uses it until the broker is closed.
    • *
    • transaction: A connection is obtained when each * transaction begins (optimistic or datastore), and is released * when the transaction completes.
    • *
    • on-demand: Connections are obtained only when needed. * This is the default mode. It is equivalent to the previous option * when datastore transactions are used. For optimistic transactions, * though, it means that a connection will be retained only for * the duration of the data store commit process.
    • *
    * * @since 0.2.5 */ public String getConnectionRetainMode(); /** * Specifies the behavior of the broker with respect to data store * connections. Possible values are: *
      *
    • always: Each broker obtains a single connection and * uses it until the broker is closed.
    • *
    • transaction: A connection is obtained when each * transaction begins (optimistic or datastore), and is released * when the transaction completes.
    • *
    • on-demand: Connections are obtained only when needed. * This is the default mode. It is equivalent to the previous option * when datastore transactions are used. For optimistic transactions, * though, it means that a connection will be retained only for * the duration of the data store commit process.
    • *
    * * @since 0.2.5 */ public void setConnectionRetainMode(String mode); /** * Return the connection retain mode as one of the following symbolic * constants: *
      *
    • {@link ConnectionRetainModes#CONN_RETAIN_ALWAYS}
    • *
    • {@link ConnectionRetainModes#CONN_RETAIN_TRANS}
    • *
    • {@link ConnectionRetainModes#CONN_RETAIN_DEMAND}
    • *
    */ public int getConnectionRetainModeConstant(); /** * Set the connection retain mode as one of the following symbolic * constants: *
      *
    • {@link ConnectionRetainModes#CONN_RETAIN_ALWAYS}
    • *
    • {@link ConnectionRetainModes#CONN_RETAIN_TRANS}
    • *
    • {@link ConnectionRetainModes#CONN_RETAIN_DEMAND}
    • *
    */ public void setConnectionRetainMode(int mode); /** * A comma-separted list of the plugin strings of the query * {@link FilterListener}s to use. */ public String getFilterListeners(); /** * A comma-separted list of the plugin strings of the query * {@link FilterListener}s to use. */ public void setFilterListeners(String listeners); /** * Return the query filter listeners. If none have been set explicitly, * this method instantiates the listeners from the set plugin list. */ public FilterListener[] getFilterListenerInstances(); /** * Set the query filter listeners. Overrides the list of listener classes. */ public void setFilterListeners(FilterListener[] listeners); /** * A comma-separted list of the plugin strings of the query * {@link AggregateListener}s to use. */ public String getAggregateListeners(); /** * A comma-separted list of the plugin strings of the query * {@link AggregateListener}s to use. */ public void setAggregateListeners(String listeners); /** * Return the query function listeners. If none have been set explicitly, * this method instantiates the listeners from the set plugin list. */ public AggregateListener[] getAggregateListenerInstances(); /** * Set the query function listeners. Overrides the list of listener classes. */ public void setAggregateListeners(AggregateListener[] listeners); /** * Whether to warn and defer registration instead of throwing an * exception when a registered persistent class cannot be processed. * Should only be set to true in complex classloader topologies. * Defaults to false. * * @since 0.3.2.3 */ public boolean getRetryClassRegistration(); /** * Whether to warn and defer registration instead of throwing an * exception when a registered persistent class cannot be processed. * Should only be set to true in complex classloader topologies. * Defaults to false. * * @since 0.3.2.3 */ public void setRetryClassRegistration(boolean warn); /** * Wrapper for JCA usage of {@link #setRetryClassRegistration(boolean)}. * * @since 0.3.2.3 */ public void setRetryClassRegistration(Boolean warn); /** * Backwards compatibility options. */ public String getCompatibility(); /** * Backwards compatibility options. */ public void setCompatibility(String compatibility); /** * Backwards compatibility options. */ public Compatibility getCompatibilityInstance (); /** * Options for configuring callbacks as a String. * * @since 2.0.0 */ public String getCallbackOptions(); /** * Options for configuring callbacks. * * @since 2.0.0 */ public CallbackOptions getCallbackOptionsInstance(); /** * Options for configuring callbacks set as a comma-separated string value * pair. * * @since 2.0.0 */ public void setCallbackOptions(String options); /** * Configuration settings for the query compilation cache to use. * @see QueryCompilationCacheValue * @since 0.9.6 */ public String getQueryCompilationCache(); /** * Configuration settings for the query compilation cache to use. * @see QueryCompilationCacheValue * @since 0.9.6 */ public void setQueryCompilationCache(String conf); /** * Configuration settings for the query compilation cache to use. * @see QueryCompilationCacheValue * @since 0.9.6 */ public Map getQueryCompilationCacheInstance(); /** * Return the {@link StoreFacadeTypeRegistry} instance associated with this * configuration. */ public StoreFacadeTypeRegistry getStoreFacadeTypeRegistry(); /** * Return the {@link org.apache.openjpa.event.BrokerFactoryEventManager} * associated with this configuration. * * @since 1.0.0 */ public BrokerFactoryEventManager getBrokerFactoryEventManager(); /** * Specifies how OpenJPA handles unenhanced types. Possible values are: *
      *
    • supported: Runtime optimization of persistent types * is available. This is the default
    • *
    • unsupported: Runtime optimization of persistent types * is not available. An exception will be thrown if the system loads with * persistent types that are not enhanced.
    • *
    • warn: Runtime optimization of persistent types is * not available, but no exception will be thrown initially. A warning will * be logged instead. It is likely that the system will fail at a later * point. This might be suitable for environments with complex classloader * configurations.
    • *
    * * @since 1.0.0 */ public String getRuntimeUnenhancedClasses(); /** * Specifies how OpenJPA handles unenhanced types. * * @see {@link #getRuntimeUnenhancedClasses()} * @since 1.0.0 */ public void setRuntimeUnenhancedClasses(String mode); /** * Return the runtime class optimization setting as one of the * following symbolic constants: *
      *
    • {@link RuntimeUnenhancedClassesModes#SUPPORTED}
    • *
    • {@link RuntimeUnenhancedClassesModes#UNSUPPORTED}
    • *
    • {@link RuntimeUnenhancedClassesModes#WARN}
    • *
    * * @since 1.0.0 */ public int getRuntimeUnenhancedClassesConstant(); /** * Set the runtime class optimization setting as one of the * following symbolic constants: *
      *
    • {@link RuntimeUnenhancedClassesModes#SUPPORTED}
    • *
    • {@link RuntimeUnenhancedClassesModes#UNSUPPORTED}
    • *
    • {@link RuntimeUnenhancedClassesModes#WARN}
    • *
    * * @since 1.0.0 */ public void setRuntimeUnenhancedClasses(int mode); /** * Whether OpenJPA will attempt to dynamically load the enhancement agent. */ public boolean getDynamicEnhancementAgent(); /** * Sets whether OpenJPA will attempt to dynamically load the enhancement * agent. */ public void setDynamicEnhancementAgent(boolean dynamic); /** * A comma-separted list of the plugin strings specifying the * {@link CacheMarshaller}s to use. * * @since 1.1.0 */ public String getCacheMarshallers(); /** * A comma-separated list of the plugin strings specifying the * {@link CacheMarshaller}s to use. * * @since 1.1.0 */ public void setCacheMarshallers(String marshallers); /** * Return the cache marshaller listeners. * * @since 1.1.0 */ public Map getCacheMarshallerInstances(); /** * Affirms if all configured elements are initialized eagerly as opposed * to lazily on-demand. * * @since 1.3.0 */ public boolean isInitializeEagerly(); /** * Sets whether all configured elements will be initialized eagerly or * lazily on-demand. * * @since 1.3.0 */ public void setInitializeEagerly(boolean flag); /** * Return PreparedQueryCache used for caching datastore queries. * * @since 2.0.0 */ public PreparedQueryCache getQuerySQLCacheInstance(); /** * Gets the configuration of QuerySQLCache. * * @since 2.0.0 */ public String getQuerySQLCache(); /** * Sets QuerySQLCache with the given cache. * * @since 2.0.0 */ public void setQuerySQLCache(PreparedQueryCache cache); /** * Sets QuerySQLCache with the given configuration. * * @since 2.0.0 */ public void setQuerySQLCache(String config); /** * Get the cache of finder queries. * * @since 2.0.0 */ public FinderCache getFinderCacheInstance(); /** * Get the string configuration of the finder cache. * * @since 2.0.0 */ public String getFinderCache(); /** * Set the finder cache from a string configuration. * * @since 2.0.0 */ public void setFinderCache(String cache); /** * The bean validation mode to use for managed classes. * Defaults to AUTO. * * @since 2.0.0 */ public String getValidationMode(); /** * Set the bean validation mode to use for managed classes. * If not set, defaults to AUTO. * * @since 2.0.0 */ public void setValidationMode(String mode); /** * The ValidatorFactory provided by the container or application. * Defaults to null. * * @since 2.0.0 */ public Object getValidationFactoryInstance(); /** * Set the container or application provided ValidatorFactory instance. * If not set, defaults to null. * * @since 2.0.0 */ public void setValidationFactory(Object factory); /** * The Validator provided by the container or created by the runtime. * Defaults to null. * * @since 2.0.0 */ public Object getValidatorInstance(); /** * Set the container or application provided Validator instance. * If not set, defaults to null. * * @since 2.0.0 */ public void setValidatorInstance(Object val); /** * Gets the lifecycle event manager instance classname. * * @since 2.0.0 */ public String getLifecycleEventManager(); /** * Gets the lifecycle event manager instance. * * @since 2.0.0 */ public LifecycleEventManager getLifecycleEventManagerInstance(); /** * Sets the lifecycle event manager instance classname. * * @since 2.0.0 */ public void setLifecycleEventManager(String eventMgr); /** * Gets the validation groups for pre-persist * * @Since 2.0.0 */ public String getValidationGroupPrePersist(); /** * Sets the validation groups for pre-persist * * @Since 2.0.0 */ public void setValidationGroupPrePersist(String vgPrePersist); /** * Gets the validation groups for pre-update * * @Since 2.0.0 */ public String getValidationGroupPreUpdate(); /** * Sets the validation groups for pre-update * * @Since 2.0.0 */ public void setValidationGroupPreUpdate(String vgPreUpdate); /** * Gets the validation groups for pre-remove * * @Since 2.0.0 */ public String getValidationGroupPreRemove(); /** * Sets the validation groups for pre-remove * * @Since 2.0.0 */ public void setValidationGroupPreRemove(String vgPreRemove); /** * Sets the {@link EncryptionProvider}. * * @param className */ public void setEncryptionProvider(String className); /** * Gets the {@link EncryptionProvider}. * * @return EncryptionProvider */ public EncryptionProvider getEncryptionProvider(); /** * Set the {@link DataCacheMode} * * @param mode One of the Sting constants from {@link DataCacheMode} * @since 2.0.0 */ public void setDataCacheMode(String mode); /** * Return the String constant that matches the {@link DataCacheMode} * @return DataCacheMode * @since 2.0.0 */ public String getDataCacheMode(); /** * Gets the policy object that determines distribution of cached instances * across named partitions of L2 data cache. * * @return an implementation of {@link CacheDistributionPolicy}. * @since 2.0.0 */ public CacheDistributionPolicy getCacheDistributionPolicyInstance(); /** * Sets the policy object that determines distribution of cached instances * across named partitions of L2 data cache. * * @param policy a non-null implementation of {@link CacheDistributionPolicy}. * @since 2.0.0 */ public void setCacheDistributionPolicyInstance(CacheDistributionPolicy policy); /** * Gets the plug-in string that described the policy to distribute cached instances * across named partitions of L2 data cache. * * @return a plug-in string for {@link CacheDistributionPolicy}. * @since 2.0.0 */ public String getCacheDistributionPolicy(); /** * Sets the plug-in string that describes the policy to distribute cached instances * across named partitions of L2 data cache. * * @param a plug-in string for {@link CacheDistributionPolicy}. * @since 2.0.0 */ public void setCacheDistributionPolicy(String policyPlugin); /** * Gets the plug-in string that defines instrumentation providers and what * they instrument. * @return a plug-in string for the instrumentation configuration * @since 2.1.0 */ public String getInstrumentation(); /** * Sets the plug-in string that defines instrumentation providers and what * they instrument. * @param providers a plug-in string for the instrumentation configuration * @since 2.1.0 */ public void setInstrumentation(String providers); /** * Gets an instance of the instrumentation manager. The instrumentation * provides access to configured instrumentation providers and can be used * to manage them at runtime. * @return an instance of the instrumentation manager * @since 2.1.0 */ public InstrumentationManager getInstrumentationManagerInstance(); /** * Gets the singular instance of {@link Auditor} associated with this configuration. * * @since 2.2.0 */ public Auditor getAuditorInstance(); /** * Sets the singular instance of {@link Auditor} associated with this configuration. * * @since 2.2.0 */ public void setAuditorInstance(Auditor auditor); /** * Gets the plug-in string of {@link Auditor} specified in this configuration. * * @since 2.2.0 */ public String getAuditor(); /** * Sets the plug-in string of {@link Auditor} specified in this configuration. * * @since 2.2.0 */ public void setAuditor(String s); /** * Whether to send @PostLoad events on a merge operation. * @since 2.2.0 */ public boolean getPostLoadOnMerge(); /** * Whether to send @PostLoad events on a merge operation. * @since 2.2.0 */ public void setPostLoadOnMerge(boolean postLoadOnMerge); /** * Whether to send @PostLoad events on a merge operation. * @since 2.2.0 */ public void setPostLoadOnMerge(Boolean postLoadOnMerge); /** * Whether to attempt to optimize id class copy operations during the * enhancement process. Optimization is only applicable for simple id classes * that have a constructor with the proper construction parameters and * direct assignments to fields within the id class during construction. * If the optimization cannot occur, the enhancer will fallback to the * noraml behavior. * @since 2.2.0 */ public boolean getOptimizeIdCopy(); /** * Whether to attempt to optimize id class copy operations during the * enhancement process. Optimization is only applicable for simple id classes * that have a constructor with the proper construction parameters and * direct assignments to fields within the id class during construction. * If the optimization cannot occur, the enhancer will fallback to the * normal behavior. * @since 2.2.0 */ public void setOptimizeIdCopy(boolean optimizeIds); /** * Whether to attempt to optimize id class copy operations during the * enhancement process. Optimization is only applicable for simple id classes * that have a constructor with the proper construction parameters and * direct assignments to fields within the id class during construction. * If the optimization cannot occur, the enhancer will fallback to the * normal behavior. * @since 2.2.0 */ public void setOptimizeIdCopy(Boolean optimizeIds); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/SpecificationPlugin.java0000644000000000000000000001010312133327272027534 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.conf.ObjectValue; import org.apache.openjpa.lib.conf.ProductDerivations; import org.apache.openjpa.lib.conf.Value; import org.apache.openjpa.lib.conf.ValueListener; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * A plug-in for Specification that enforces certain overwriting rules. * * @author Pinaki Poddar * */ public class SpecificationPlugin extends ObjectValue implements ValueListener { private Configuration _conf; protected static final Localizer _loc = Localizer.forPackage (SpecificationPlugin.class); public SpecificationPlugin(Configuration conf, String prop) { super(prop); _conf = conf; addListener(this); } @Override public Class getValueType() { return Specification.class; } /** * Set a value from the given String after validating. * * @param str can be null to set the Specification to null. * If non-null, then the String must be in Specification format * @see Specification#create(String) */ @Override public void setString(String str) { this.set(str == null ? null : new Specification(str)); } /** * Set a value from the given object after validating. * * @param obj can be null to set the Specification to null. */ @Override public void set(Object obj) { if (obj == null) { super.set(null); return; } if (obj instanceof Specification == false) { throw new UserException(_loc.get("spec-wrong-obj", obj, obj.getClass())).setFatal(true); } validateOverwrite((Specification)obj); super.set(obj); } /** * Validates if the given Specification can overwrite the current * Specification. If the given Specification is not same as the * current one, then it is valid to overwrite. * If the given Specification is same as the current Specification then * it must have a major version number equal or less than the current one. * * @exception fatal UserException if the given Specification is same as * the current Specification but has a higher major version. * * @see Specification#equals(Object) */ protected void validateOverwrite(Specification newSpec) { Specification current = (Specification)get(); if (current != null) { Log log = _conf.getConfigurationLog(); if (!current.isSame(newSpec)) { log.warn(_loc.get("spec-different", newSpec, current)); return; } if (current.compareVersion(newSpec) < 0) { throw new UserException(_loc.get("spec-version-higher", newSpec, current)).setFatal(true); } if (current.compareVersion(newSpec) > 0) { log.warn(_loc.get("spec-version-lower", newSpec, current)); } } } public void valueChanged(Value value) { if (this.getClass().isInstance(value)) ProductDerivations.afterSpecificationSet(_conf); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.j0000644000000000000000000000751312133327272030345 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.util.Collections; import java.util.Hashtable; import java.util.Map; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.conf.PluginValue; import java.util.concurrent.ConcurrentHashMap; import org.apache.openjpa.lib.util.ParseException; import org.apache.openjpa.util.CacheMap; /** * A cache of compiled queries. * * @author Abe White * @since 0.9.6 (also existed in prior versions of Kodo) * @nojavadoc */ public class QueryCompilationCacheValue extends PluginValue { public static final String[] ALIASES = { "true", CacheMap.class.getName(), "all", ConcurrentHashMap.class.getName(), "false", null, }; public QueryCompilationCacheValue(String prop) { super(prop, true); setAliases(ALIASES); setDefault(ALIASES[0]); setClassName(ALIASES[1]); } public Object newInstance(String clsName, Class type, Configuration conf, boolean fatal) { // make sure map handles concurrency Map map; try { map = (Map) super.newInstance(clsName, type, conf, fatal); } catch (ParseException pe) { // OPENJPA256: this class differs from most plugins in that // the plugin type is the standard java interface Map.class (rather // than an openjpa-specific interface), which means that the // ClassLoader used to load the implementation will be the system // class loader; this presents a problem if OpenJPA is not in the // system classpath, so work around the problem by catching // the ParseException (which is what we wrap the // ClassNotFoundException in) and try again, this time using // this class' ClassLoader. map = (Map) super.newInstance(clsName, QueryCompilationCacheValue.class, conf, fatal); } catch (IllegalArgumentException iae) { // OPENJPA256: this class differs from most plugins in that // the plugin type is the standard java interface Map.class (rather // than an openjpa-specific interface), which means that the // ClassLoader used to load the implementation will be the system // class loader; this presents a problem if OpenJPA is not in the // system classpath, so work around the problem by catching // the IllegalArgumentException (which is what we wrap the // ClassNotFoundException in) and try again, this time using // this class' ClassLoader. map = (Map) super.newInstance(clsName, QueryCompilationCacheValue.class, conf, fatal); } if (map != null && !(map instanceof Hashtable) && !(map instanceof CacheMap) && !(map instanceof org.apache.openjpa.lib.util.concurrent.ConcurrentMap) && !(map instanceof java.util.concurrent.ConcurrentMap)) map = Collections.synchronizedMap(map); return map; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/RemoteCommitProviderValue.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/RemoteCommitProviderValue.ja0000644000000000000000000001046712133327272030377 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.event.RemoteCommitEventManager; import org.apache.openjpa.event.RemoteCommitProvider; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.conf.PluginValue; import org.apache.openjpa.lib.util.Options; /** * Value type used to represent a {@link RemoteCommitProvider}. This * plugin allows users to specify whether to transmit the ids of added objects * in the remote commit events distributed. * * @author Abe White * @nojavadoc */ public class RemoteCommitProviderValue extends PluginValue { private static final String[] ALIASES = new String[]{ "sjvm", "org.apache.openjpa.event.SingleJVMRemoteCommitProvider", "jms", "org.apache.openjpa.event.JMSRemoteCommitProvider", "tcp", "org.apache.openjpa.event.TCPRemoteCommitProvider", }; private Options _opts = null; private Boolean _transmitPersIds = null; public RemoteCommitProviderValue() { super("RemoteCommitProvider", true); setAliases(ALIASES); } public void setProperties(String props) { super.setProperties(props); _opts = null; _transmitPersIds = null; } public void setString(String str) { super.setString(str); _opts = null; _transmitPersIds = null; } /** * The cached provider. */ public RemoteCommitProvider getProvider() { return (RemoteCommitProvider) get(); } /** * The cached provider. */ public void setProvider(RemoteCommitProvider provider) { set(provider); } /** * Whether to transmit persisted object ids in remote commit events. */ public boolean getTransmitPersistedObjectIds() { return Boolean.TRUE.equals(_transmitPersIds); } /** * The cached decorators. */ public void setTransmitPersistedObjectIds(boolean transmit) { _transmitPersIds = (transmit) ? Boolean.TRUE : Boolean.FALSE; } /** * Instantiate the provider. */ public RemoteCommitProvider instantiateProvider(Configuration conf) { return instantiateProvider(conf, true); } /** * Instantiate the provider. */ public RemoteCommitProvider instantiateProvider(Configuration conf, boolean fatal) { return (RemoteCommitProvider) instantiate(RemoteCommitProvider.class, conf, fatal); } /** * Configure the remote event manager. */ public void configureEventManager(RemoteCommitEventManager mgr) { parseOptions(); if (_transmitPersIds != null) mgr.setTransmitPersistedObjectIds(_transmitPersIds.booleanValue()); } /** * Override to keep decorators out of transport configuration. */ public Object instantiate(Class type, Configuration conf, boolean fatal) { Object obj = newInstance(getClassName(), type, conf, fatal); parseOptions(); Configurations.configureInstance(obj, conf, _opts, getProperty()); set(obj, true); return obj; } private void parseOptions() { if (_opts != null) return; _opts = Configurations.parseProperties(getProperties()); String transmit = StringUtils.trimToNull(_opts.removeProperty ("transmitPersistedObjectIds", "TransmitPersistedObjectIds", null)); if (transmit != null) _transmitPersIds = Boolean.valueOf (transmit); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Specification.java0000644000000000000000000001237412133327272026371 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.text.MessageFormat; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * An immutable representation of a Specification supported by OpenJPA. * * Available via {@linkplain OpenJPAConfiguration#getSpecificationInstance()()} * for configuration that may depend on Specification version. * * @author Pinaki Poddar * */ public class Specification { private String _name = ""; private int _major = 1; private String _minor = "0"; private String _description = ""; private Compatibility _compatibility; private static Localizer _loc = Localizer.forPackage(Specification.class); /** * Construct from a String that encodes name and version fields. * * @param fullName a encoded string in the following prescribed format. * name major.minor e.g. JPA 2.0-draft * Only the 'name' field is mandatory. * 'major' version defaults to 1 and must be an integer. * 'minor' version defaults to 0 and can be a String. */ public Specification(String fullName) { try { Object[] tokens = parse(fullName); _name = tokens[0].toString(); _major = tokens.length > 1 ? Integer.parseInt(tokens[1].toString()) : 1; _minor = tokens.length > 2 ? tokens[2].toString() : "0"; } catch (Exception e) { throw new UserException(_loc.get("spec-wrong-format", fullName)); } } public String getName() { return _name; } public int getVersion() { return _major; } public String getMinorVersion() { return _minor; } public String getDescription() { return _description; } public Specification setDescription(String description) { this._description = description; return this; } /** * Affirms if the given argument is equal to this receiver. */ public boolean equals(Object other) { if (this == other) return true; if (other == null || !this.getClass().isInstance(other)) return false; Specification that = (Specification)other; return StringUtils.equals(_name, this._name) && _major == that._major && StringUtils.equals(_minor, this._minor); } /** * Affirms if the given specification has the same name of this receiver, * ignoring the case. */ public boolean isSame(Specification other) { return this == other || (other != null && _name.equalsIgnoreCase(other._name)); } /** * Affirms if the given string equals name of this receiver, ignoring the * case. */ public boolean isSame(String other) { return _name.equalsIgnoreCase(other); } /** * Compares major version number of the given Specification with this * receiver. * @return 0 if they are equal. * > 0 if this receiver is higher version. * < 0 if this receiver is lower version. */ public int compareVersion(Specification other) { return _major > other._major ? 1 : _major == other._major ? 0 : -1; } public String toString() { return _name.toUpperCase() + " " + _major + "." + _minor; } private Object[] parse(String str) { int space = str.indexOf(' '); if (space == -1) return new Object[]{str}; String name = str.substring(0,space); String version = str.substring(space+1); int dot = version.indexOf('.'); if (dot == -1) return new Object[] {name, version}; return new Object[] {name, version.substring(0,dot), version.substring(dot+1)}; } /** * Associate a compatibility object with this Specification instance * @param compatibility a Compatibility object with flags set in compliance * with this Specification instance. */ public void setCompatibility(Compatibility compatibility) { _compatibility = compatibility; } /** * Return the compatibility object associated with this Specification instance. * @return */ public Compatibility getCompatibility() { return _compatibility; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAVersionAndConfigurationTypeValidationPolicy.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAVersionAndConfigurati0000644000000000000000000000406012133327272030302 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import org.apache.openjpa.conf.CacheMarshaller.ValidationPolicy; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; /** * Compute validity based on whether or not the cached data is from the same * version of Kodo as the current install. This also checks OpenJPA version * information in case the OpenJPA jars were independently updated. * * @since 1.1.0 */ public class OpenJPAVersionAndConfigurationTypeValidationPolicy implements ValidationPolicy, Configurable { private String confClassName; public Object getCacheableData(Object o) { return new Object[] { OpenJPAVersion.VERSION_ID, confClassName, o, }; } public Object getValidData(Object o) { Object[] array = (Object[]) o; if (array.length != 3) return null; if (OpenJPAVersion.VERSION_ID.equals(array[0]) && confClassName.equals(array[1])) return array[2]; else return null; } public void setConfiguration(Configuration conf) { confClassName = conf.getClass().getName(); } public void startConfiguration() { } public void endConfiguration() { } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/conf/BrokerFactoryValue.java0000644000000000000000000000570712133327272027364 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.conf; import java.util.HashMap; import java.util.Map; import java.util.Iterator; import org.apache.openjpa.abstractstore.AbstractStoreBrokerFactory; import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.lib.conf.ConfigurationProvider; import org.apache.openjpa.lib.conf.PluginValue; import org.apache.openjpa.lib.conf.ProductDerivations; import org.apache.openjpa.lib.conf.ProductDerivation; /** * Value type used to represent the {@link BrokerFactory}. This type is * defined separately so that it can be used both in the global configuration * and in {@link org.apache.openjpa.kernel.Bootstrap} with the same * encapsulated configuration. * * @nojavadoc */ public class BrokerFactoryValue extends PluginValue { public static final String KEY = "BrokerFactory"; private static final String[] _aliases; static { Map aliases = new HashMap(); aliases.put("abstractstore", AbstractStoreBrokerFactory.class.getName()); ProductDerivation[] ds = ProductDerivations.getProductDerivations(); for (int i = 0; i < ds.length; i++) { if (ds[i] instanceof OpenJPAProductDerivation) ((OpenJPAProductDerivation) ds[i]).putBrokerFactoryAliases(aliases); } _aliases = new String[aliases.size() * 2]; int i = 0; for(Map.Entrye : aliases.entrySet()) { _aliases[i++] = e.getKey(); _aliases[i++] = e.getValue(); } } /** * Extract the value of this property if set in the given provider. */ public static Object get(ConfigurationProvider cp) { Map props = cp.getProperties(); return props.get(ProductDerivations.getConfigurationKey(KEY, props)); } /** * Set the value of this property in the given provider. */ public static void set(ConfigurationProvider cp, String value) { String key = ProductDerivations.getConfigurationKey(KEY, cp.getProperties()); cp.addProperty(key, value); } public BrokerFactoryValue() { super(KEY, false); setAliases(_aliases); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/0000755000000000000000000000000012133327272023707 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheManager.java0000644000000000000000000000746112133327272027652 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.Map; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.conf.ObjectValue; /** * Manages the system's data and query caches. You can retrieve the data cache manager from the * {@link OpenJPAConfiguration#getDataCacheManagerInstance()}. *
    * Manages zero or more individual {@link DataCache caches} or partitions. Each individual partition * is identified by a string-based identifier. * * Decides eligibility to cache for managed types. * * * @author Abe White * @author Patrick Linskey * @author Pinaki Poddar */ public interface DataCacheManager { /** * Initialize the manager, supplying the cache configuration. */ public void initialize(OpenJPAConfiguration conf, ObjectValue dataCache, ObjectValue queryCache); /** * Return the system-wide data cache, or null if caching is not enabled. */ public DataCache getSystemDataCache(); /** * Return the named data cache, or null if it does not exist. */ public DataCache getDataCache(String name); /** * Return the named data cache. If the given name is null, the default * data cache is returned. * * @param create if true, the cache will be created if it does * not already exist */ public DataCache getDataCache(String name, boolean create); /** * Return the system query cache, or null if not configured. */ public QueryCache getSystemQueryCache(); /** * Return the PCData generator if configured. */ public DataCachePCDataGenerator getPCDataGenerator(); /** * Return the runnable which schedules evictions. */ public ClearableScheduler getClearableScheduler(); /** * Select the cache where the given managed proxy instance should be cached. * This decision may override the cache returned by * {@link CacheDistributionPolicy#selectCache(OpenJPAStateManager, Object) policy} * as specified by the user. * * @param sm the managed proxy instance * @return the cache that will store the state of the given managed instance. * * @since 2.0.0 */ public DataCache selectCache(final OpenJPAStateManager sm); /** * Return the user-specific policy that suggests the cache where a managed entity state is stored. * * @since 2.0.0 */ public CacheDistributionPolicy getDistributionPolicy(); /** * Close all caches. */ public void close(); /** * Stop caching the type matching the provided class name. */ public void stopCaching(String cls); /** * Start caching the type matching the provided class name. */ public void startCaching(String cls); /** * Returns the names of classes that are known to the cache and whether or not they are currently being cached. */ public Map listKnownTypes(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryKey.java0000644000000000000000000004351612133327272026341 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.kernel.Query; import org.apache.openjpa.kernel.QueryContext; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.ImplHelper; /** * This class stores information about a particular invocation of * a query. It contains a reference to the external properties of the * query that was executed, as well as any parameters used to execute * that query, with one exception: first-class objects used as * parameter values are converted to OIDs. * * @author Patrick Linskey */ public class QueryKey implements Externalizable { // initialize the set of unmodifiable classes. This allows us // to avoid cloning collections that are not modifiable, // provided that they do not contain mutable objects. private static Collection> s_unmod = new HashSet>(); static { // handle the set types; jdk uses different classes for collection, // set, and sorted set TreeSet s = new TreeSet(); s_unmod.add(Collections.unmodifiableCollection(s).getClass()); s_unmod.add(Collections.unmodifiableSet(s).getClass()); s_unmod.add(Collections.unmodifiableSortedSet(s).getClass()); // handle the list types; jdk uses different classes for standard // and random access lists List l = new LinkedList(); s_unmod.add(Collections.unmodifiableList(l).getClass()); l = new ArrayList(0); s_unmod.add(Collections.unmodifiableList(l).getClass()); // handle the constant types s_unmod.add(Collections.EMPTY_SET.getClass()); s_unmod.add(Collections.EMPTY_LIST.getClass()); } // caching state; no need to include parameter and variable declarations // because they are implicit in the filter private String _candidateClassName; private boolean _subclasses; private Set _accessPathClassNames; private Object _query; private boolean _ignoreChanges; private Map _params; private long _rangeStart; private long _rangeEnd; // ### pcl: 2 May 2003: should this timeout take into account the // ### timeouts for classes in the access path of the query? // ### Currently, it only considers the candidate class and its // ### subclasses. Note that this value is used to decide whether // ### or not OIDs should be registered for expiration callbacks private int _timeout = -1; /** * Return a key for the given query, or null if it is not cacheable. */ public static QueryKey newInstance(Query q) { return newInstance(q, (Object[]) null); } /** * Return a key for the given query, or null if it is not cacheable. */ public static QueryKey newInstance(Query q, Object[] args) { // compile to make sure info encoded in query string is available // via API calls (candidate class, result class, etc) q.compile(); return newInstance(q, false, args, q.getCandidateType(), q.hasSubclasses(), q.getStartRange(), q.getEndRange(), null); } /** * Return a key for the given query, or null if it is not cacheable. */ public static QueryKey newInstance(Query q, Map args) { // compile to make sure info encoded in query string is available // via API calls (candidate class, result class, etc) q.compile(); return newInstance(q, false, args, q.getCandidateType(), q.hasSubclasses(), q.getStartRange(), q.getEndRange(), null); } /** * Return a key for the given query, or null if it is not cacheable. */ static QueryKey newInstance(QueryContext q, boolean packed, Object[] args, Class candidate, boolean subs, long startIdx, long endIdx, Object parsed) { QueryKey key = createKey(q, packed, candidate, subs, startIdx, endIdx, parsed); if (key != null && setParams(key, q, args)) return key; return null; } /** * Return a key for the given query, or null if it is not cacheable. */ static QueryKey newInstance(QueryContext q, boolean packed, Map args, Class candidate, boolean subs, long startIdx, long endIdx, Object parsed) { QueryKey key = createKey(q, packed, candidate, subs, startIdx, endIdx, parsed); if (key != null && (args == null || args.isEmpty() || setParams(key, q.getStoreContext(), new HashMap(args)))) return key; return null; } /** * Extract the relevant identifying information from * q. This includes information such as candidate * class, query filter, etc. */ private static QueryKey createKey(QueryContext q, boolean packed, Class candidateClass, boolean subclasses, long startIdx, long endIdx, Object parsed) { if (candidateClass == null) return null; // can only cache datastore queries if (q.getCandidateCollection() != null) return null; // no support already-packed results if (q.getResultType() != null && packed) return null; // can't cache non-serializable non-managed complex types Class[] types = q.getProjectionTypes(); for (int i = 0; i < types.length; i++) { switch (JavaTypes.getTypeCode(types[i])) { case JavaTypes.ARRAY: return null; case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.OBJECT: if (!ImplHelper.isManagedType( q.getStoreContext().getConfiguration(), types[i])) return null; break; } } // we can't cache the query if we don't know which classes are in the // access path ClassMetaData[] metas = q.getAccessPathMetaDatas(); if (metas.length == 0) return null; Set accessPathClassNames = new HashSet((int) (metas.length * 1.33 + 1)); ClassMetaData meta; for (int i = 0; i < metas.length; i++) { // since the class change framework deals with least-derived types, // record the least-derived access path types meta = metas[i]; accessPathClassNames.add(meta.getDescribedType().getName()); while (meta.getPCSuperclass() != null) { meta = meta.getPCSuperclassMetaData(); } accessPathClassNames.add(meta.getDescribedType().getName()); } // if any of the types are currently dirty, we can't cache this query StoreContext ctx = q.getStoreContext(); if (intersects(accessPathClassNames, ctx.getPersistedTypes()) || intersects(accessPathClassNames, ctx.getUpdatedTypes()) || intersects(accessPathClassNames, ctx.getDeletedTypes())) return null; // calculate the timeout for the key MetaDataRepository repos = ctx.getConfiguration(). getMetaDataRepositoryInstance(); // won't find metadata for interfaces. if (candidateClass.isInterface()) return null; meta = repos.getMetaData(candidateClass, ctx.getClassLoader(), true); int timeout = meta.getDataCacheTimeout(); if (subclasses) { metas = meta.getPCSubclassMetaDatas(); int subTimeout; for (int i = 0; i < metas.length; i++) { if (metas[i].getDataCache() == null) return null; accessPathClassNames.add(metas[i].getDescribedType().getName()); subTimeout = metas[i].getDataCacheTimeout(); if (subTimeout != -1 && subTimeout < timeout) timeout = subTimeout; } } // tests all passed; cacheable QueryKey key = new QueryKey(); key._candidateClassName = candidateClass.getName(); key._subclasses = subclasses; key._accessPathClassNames = accessPathClassNames; key._timeout = timeout; key._query = q.getQueryString(); if (key._query == null) { // this can be a criteria query key._query = parsed; } key._ignoreChanges = q.getIgnoreChanges(); key._rangeStart = startIdx; key._rangeEnd = endIdx; return key; } /** * Convert an array of arguments into the corresponding parameter * map, and do any PC to OID conversion necessary. */ private static boolean setParams(QueryKey key, QueryContext q, Object[] args) { if (args == null || args.length == 0) return true; // Create a map for the given parameters, and convert the // parameter list into a map, using the query's parameter // declaration to determine ordering etc. Map> types = q.getOrderedParameterTypes(); Map map = new HashMap((int) (types.size() * 1.33 + 1)); int idx = 0; for (Iterator iter = types.keySet().iterator(); iter.hasNext(); idx++) map.put(iter.next(), args[idx]); return setParams(key, q.getStoreContext(), map); } /** * Convert parameters to a form that is cacheable. Mutable params * will be cloned. */ private static boolean setParams(QueryKey key, StoreContext ctx, Map params) { if (params == null || params.isEmpty()) return true; Object v; for (Map.Entry e : params.entrySet()) { v = e.getValue(); if (ImplHelper.isManageable(v)) { if (!ctx.isPersistent(v) || ctx.isNew(v) || ctx.isDeleted(v)) return false; e.setValue(ctx.getObjectId(v)); } if (v instanceof Collection) { Collection c = (Collection) v; boolean contentsAreDates = false; if (c.iterator().hasNext()) { // this assumes that the collection is homogeneous Object o = c.iterator().next(); if (ImplHelper.isManageable(o)) return false; // pcl: 27 Jun 2004: if we grow this logic to // handle other mutable types that are not // known to be cloneable, we will have to add // logic to handle them. This is because we // can't just cast to Cloneable and invoke // clone(), as clone() is a protected method // in Object. if (o instanceof Date) contentsAreDates = true; // if the collection is not a known immutable // type, or if it contains mutable instances, // clone it for good measure. if (contentsAreDates || !s_unmod.contains(c.getClass())) { // copy the collection Collection copy; if (c instanceof SortedSet) copy = new TreeSet(); else if (c instanceof Set) copy = new HashSet(); else copy = new ArrayList(c.size()); if (contentsAreDates) { // must go through by hand and do the // copy, since Date is mutable. for (Iterator itr2 = c.iterator(); itr2.hasNext();) copy.add(((Date) itr2.next()).clone()); } else copy.addAll(c); e.setValue(copy); } } } else if (v instanceof Date) e.setValue(((Date) v).clone()); } key._params = params; return true; } /** * Public constructor for externalization only. */ public QueryKey() { } /** * Returns the candidate class name for this query. */ public String getCandidateTypeName() { return _candidateClassName; } /** * Return the amount of time this key is good for. */ public int getTimeout() { return _timeout; } /** * Returns true if modifications to any of the * classes in changed results in a possible * invalidation of this query; otherwise returns * false. Invalidation is possible if one or more of * the classes in this query key's access path has been changed. */ public boolean changeInvalidatesQuery(Collection> changed) { return intersects(_accessPathClassNames, changed); } /** * Whether the given set of least-derived class names intersects with * the given set of changed classes. */ private static boolean intersects(Collection names, Collection> changed) { Class sup; for (Class cls : changed) { while ((sup = PCRegistry.getPersistentSuperclass(cls)) != null) cls = sup; if (names.contains(cls.getName())) return true; } return false; } /** * Determine equality based on identifying information. Keys * created for queries that specify a candidate collection are * always not equal. */ public boolean equals(Object ob) { if (this == ob) return true; if (ob == null || getClass() != ob.getClass()) return false; QueryKey other = (QueryKey) ob; return StringUtils.equals(_candidateClassName, other._candidateClassName) && _subclasses == other._subclasses && _ignoreChanges == other._ignoreChanges && _rangeStart == other._rangeStart && _rangeEnd == other._rangeEnd && ObjectUtils.equals(_query, other._query) && ObjectUtils.equals(_params, other._params); } /** * Define a hashing algorithm corresponding to the {@link #equals} * method defined above. */ public int hashCode() { int code = 37 * 17 + _candidateClassName.hashCode(); if (_query != null) code = 37 * code + _query.hashCode(); if (_params != null) code = 37 * code + _params.hashCode(); return code; } public String toString() { StringBuilder buf = new StringBuilder(1024); buf.append(super.toString()). append("[query:[").append(_query).append("]"). append(",access path:").append(_accessPathClassNames). append(",subs:").append(_subclasses). append(",ignoreChanges:").append(_ignoreChanges). append(",startRange:").append(_rangeStart). append(",endRange:").append(_rangeEnd). append(",timeout:").append(_timeout). append("]"); return buf.toString(); } // ---------- Externalizable implementation ---------- public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(_candidateClassName); out.writeBoolean(_subclasses); out.writeObject(_accessPathClassNames); out.writeObject(_query); out.writeBoolean(_ignoreChanges); out.writeObject(_params); out.writeLong(_rangeStart); out.writeLong(_rangeEnd); out.writeInt(_timeout); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { _candidateClassName = (String) in.readObject(); _subclasses = in.readBoolean(); _accessPathClassNames = (Set) in.readObject(); _query = (String) in.readObject(); _ignoreChanges = in.readBoolean(); _params = (Map) in.readObject(); _rangeStart = in.readLong(); _rangeEnd = in.readLong (); _timeout = in.readInt (); } /** * Returns the set of the accessPathClassnames that exists in the query * @return -- Returns a set of accesspath classnames. */ public Set getAcessPathClassNames() { return this._accessPathClassNames; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCache.java0000644000000000000000000002535712133327272026363 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.BitSet; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.openjpa.lib.util.Clearable; import org.apache.openjpa.lib.util.Closeable; /** * Interface that must be implemented by any level 2 cache used by * OpenJPA. Most data caches will choose to implement the * {@link org.apache.openjpa.lib.conf.Configurable} interface as well so that * they will be given the system configuration just after construction. * Implementations should take care not to return timed out data. * * @see AbstractDataCache * @see DataCachePCData#isTimedOut * @author Patrick Linskey * @author Abe White * @author Pinaki Poddar */ public interface DataCache extends Closeable, Clearable { /** * The name of the default data cache: default */ public static final String NAME_DEFAULT = "default"; /** * Returns a string name that can be used by end-user-visible * code to identify this cache. * * @since 0.2.5.0 */ public String getName(); /** * Sets a string name to be used to identify this cache to end-user needs. * * @since 0.2.5.0 */ public void setName(String name); /** * Initialize any resources associated with the given * {@link DataCacheManager}. */ public void initialize(DataCacheManager manager); /** * Perform a batch update of the cache. Add all {@link DataCachePCData} * objects in additions and in * newUpdates, make the appropriate modifications to * all DataCachePCDatas in existingUpdates, and delete all * OIDs in deletes. * All changes made to cached data must be made via this * method. It is this method that is responsible for performing * any side-effects that should happen on meaningful cache changes. * Implementations should bear in mind that the * deletes collection may contain oids that are also * in the additions map. This is possible because it * is valid for a user to delete an object with a particular oid * and then add that object in the same batch. * * @param additions A collection of {@link DataCachePCData} objects. * These represent data that have been newly created, * and thus must be added to the cache. * @param newUpdates A collection of {@link DataCachePCData} objects. * These represent data that have been modified but * were not originally in the cache, and thus must be added to the cache. * @param existingUpdates A collection of {@link DataCachePCData} objects. * These represent data that have been modified and * were originally loaded from the cache. It is * up to the cache implementation to decide if * these values must be re-enlisted in the cache. * Some caches may return live data from {@link #get} * invocations, in which case these values need not be re-enlisted. * @param deletes A collection of object IDs that have been deleted * and must therefore be dropped from the cache. */ public void commit(Collection additions, Collection newUpdates, Collection existingUpdates, Collection deletes); /** * Returns true if this cache contains data * corresponding to oid; otherwise returns * false. */ public boolean contains(Object oid); /** * Returns the indexes of the oids in this cache. */ public BitSet containsAll(Collection oids); /** * Return the cached object for the given oid. Modifying the returned * object may or may not change the cached value; the {@link #update} * method should be used to re-cache any changed objects. * * @return the object matching the given oid, or null if none */ public DataCachePCData get(Object oid); /** * Set the cached value for the given instance. This does not * result in an update of other caches. Rather, it should only be * used for loading clean data into the cache. Meaningful changes * to the state of the cache should be made via the {@link #commit} method. * * @return The previously cached value, or null if * the value was not previously cached. See {@link Map#put} * for more information. */ public DataCachePCData put(DataCachePCData value); /** * Update the cached value for the given instance. This does * not result in an update of other caches. Rather, it should * only be used for loading clean data into the cache. Meaningful changes * to the state of the cache should be made via the {@link #commit} method. * A cache implementation may or may not return a live object * from {@link #get} invocations. If an object retrieved from a * {@link #get} operation needs to be updated, this method can be * invoked instead of invoking {@link #put}. The DataCache implementation * can then make optimizations based on how its {@link #get} method works. */ public void update(DataCachePCData value); /** * Remove the value stored under the given oid. This does * not result in an update of other caches. Rather, it * should only be used for removing data in the cache. * Meaningful changes to the state of the cache should be made * via the {@link #commit} method. * * @return The previously cached value, or null if * the oid was not previously cached. See {@link Map#remove} * for more information. */ public DataCachePCData remove(Object oid); /** * Remove the values stored under the given oids. * * @return the indexes of the removed oids * @see #remove */ public BitSet removeAll(Collection oids); /** * Evict all values of a specified type. */ public void removeAll(Class cls, boolean subclasses); /** * Remove all data from this cache. This does not result * in an update of other caches. Rather, it should only be used * for clearing the cache. Meaningful changes to the state of the * cache should be made via the {@link #commit} method. */ public void clear(); /** * Pin the value stored under oid into the cache. * This method guarantees that oid's value will not * be dropped by the caching algorithm. This method does not * affect the behavior of {@link #remove}. * * @return true if oid's value was * pinned into the cache; false if the oid is not in the cache. */ public boolean pin(Object oid); /** * Pin all oids to the cache. * * @return the indexes of the pinned oids * @see #pin */ public BitSet pinAll(Collection oids); /** * Pin all oids for the given type. * @param subs Whether to include subclasses. */ public void pinAll(Class cls, boolean subs); /** * Unpin the value stored under oid from the cache. * This method reverses a previous invocation of {@link #pin}. * This method does not remove anything from the cache; it merely * makes oid's value a candidate for flushing from the cache. * * @return true if oid's value was * unpinned from the cache; false if the * oid is not in the cache. */ public boolean unpin(Object oid); /** * Unpin all oids from the cache. * * @return the indexes of the unpinned oids * @see #unpin */ public BitSet unpinAll(Collection oids); /** * Unpin all oids associaed with the given type from the cache. * @param subs Whether to include subclasses. */ public void unpinAll(Class cls, boolean subs); /** * Obtain a write lock on the cache. */ public void writeLock(); /** * Release the write lock on the cache. */ public void writeUnlock(); /** * Add a new expiration event listener to this cache. * * @since 0.2.5.0 */ public void addExpirationListener(ExpirationListener listen); /** * Remove an expiration event listener from this cache. * * @since 0.2.5.0 */ public boolean removeExpirationListener(ExpirationListener listen); /** * Free the resources used by this cache. */ public void close (); /** * Gets objects from the caches for a given list of keys. * The returned map has the same keys as the given keys. * If the cache does not contain data for a specific key, * the returned map still contains the key with a null value. * */ public Map getAll(List keys); /** * Gets the named partition. Note that a partition itself is another cache. * * @param name name of the given partition. * * @param create if true optionally create a new partition. * * @return a partition of the given name. Or null, if either no such partition exists or can not be created. * @since 2.0.0 */ public DataCache getPartition(String name, boolean create); /** * Gets the name of the known partitions. * * @return empty set if no partition exists. * * @since 2.0.0 */ public Set getPartitionNames(); /** * Affirms if this cache maintains partitions. * * @since 2.0.0 */ public boolean isPartitioned(); /** * Returns number of read/write request and cache hit ratio data. */ public CacheStatistics getStatistics(); /** * Returns whether the the cache needs to be updated when bulk updates as executed. Defaults to true. */ public boolean getEvictOnBulkUpdate(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/package.html0000644000000000000000000000162112133327272026170 0ustar

    OpenJPA Data Cache

    OpenJPA's data and query caching frameworks.

    openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/ExpirationEvent.java0000644000000000000000000000363212133327272027702 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.EventObject; /** * An event indicating the expiration of an object from the data cache, * or an expiration of a result list from the query cache. * The source of the event will be the cache. * * @since 0.3.0 * @author Abe White */ public class ExpirationEvent extends EventObject { private final Object _key; private final boolean _expired; /** * Constructor. * * @param source the data or query cache * @param key the expired object oid or query key * @param expired true if the object was expired * naturally; else false. */ public ExpirationEvent(Object source, Object key, boolean expired) { super(source); _key = key; _expired = expired; } /** * Return the expired object id or query key. */ public Object getKey() { return _key; } /** * Return whether the expired object was expired naturally, or if * the object was explicitly removed. */ public boolean getExpired() { return _expired; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/TypesChangedEvent.java0000644000000000000000000000271012133327272030132 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.Collection; import java.util.EventObject; /** * An event indicating that instances of given persistent types have * been modified. * * @author Abe White */ public class TypesChangedEvent extends EventObject { private final Collection _types; /** * Constructor. * * @param source the data or query cache * @param types the changed types */ public TypesChangedEvent(Object source, Collection types) { super(source); _types = types; } /** * Return the expired types. */ public Collection getTypes() { return _types; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/CacheStatistics.java0000644000000000000000000001132112133327272027626 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.io.Serializable; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.openjpa.util.OpenJPAId; /** * Counts number of read/write requests and hit ratio for a cache in total and * per-class basis. * * All methods with Class as input argument treats null as * java.lang.Object. All per-class statistics depends on * determining the runtime type of the instance being cached. If it is not * possible to determine the runtime type from the given context, the statistics * is registered under generic java.lang.Object. * * @since 1.3.0 */ public interface CacheStatistics extends Serializable { /** * Gets number of total read requests since last reset. */ public long getReadCount(); /** * Gets number of total read requests that has been found in cache since * last reset. */ public long getHitCount(); /** * Gets number of total write requests since last reset. */ public long getWriteCount(); /** * Gets number of total read requests since start. */ public long getTotalReadCount(); /** * Gets number of total read requests that has been found in cache since * start. */ public long getTotalHitCount(); /** * Gets number of total write requests since start. */ public long getTotalWriteCount(); /** * Gets number of total read requests for the given class since last reset. * * @deprecated - should use getReadCount(String c) */ public long getReadCount(Class cls); /** * Gets number of total read requests for the given class since last reset. */ public long getReadCount(String c); /** * Gets number of total read requests that has been found in cache for the given class since last reset. * * @deprecated - should use getHitCount(String c) */ public long getHitCount(Class cls); /** * Gets number of total read requests that has been found in cache for the given class since last reset. */ public long getHitCount(String c); /** * Gets number of total write requests for the given class since last reset. * * @deprecated - should use getWriteCount(String c) */ public long getWriteCount(Class cls); /** * Gets number of total write requests for the given class since last reset. */ public long getWriteCount(String c); /** * Gets number of total read requests for the given class since start. * * @deprecated - should use getTotalReadCount(String c) */ public long getTotalReadCount(Class cls); /** * Gets number of total read requests for the given class since start. */ public long getTotalReadCount(String c); /** * Gets number of total read requests that has been found in cache for the given class since start. */ public long getTotalHitCount(String c); /** * Gets number of total read requests that has been found in cache for the given class since start. * * @deprecated - should use getTotalHitCount(String c) */ public long getTotalHitCount(Class cls); /** * Gets number of total write requests for the given class since start. */ public long getTotalWriteCount(String c); /** * Gets number of total write requests for the given class since start. * * @deprecated - should use getTotalWriteCount(String c) */ public long getTotalWriteCount(Class cls); /** * Gets the time of last reset. */ public Date since(); /** * Gets the time of start. */ public Date start(); /** * Clears all accumulated statistics. */ public void reset(); /** * Returns whether or not statistics will be collected. */ public boolean isEnabled(); /** * Returns the types that are known to this cache being tracked. */ public Set classNames(); public Map toMap(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCData.java0000644000000000000000000000240712133327272027367 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import org.apache.openjpa.kernel.PCData; /** * Specialized {@link PCData} implementation for data caching. * * @author Patrick Linskey */ public interface DataCachePCData extends PCData { /** * Whether this data is timed out. */ public boolean isTimedOut(); /** * Gets the original timeout of this instance. * * @return -1 for no timeout ever. */ public long getTimeOut(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/AbstractDataCache.java0000644000000000000000000004243412133327272030042 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.event.RemoteCommitEvent; import org.apache.openjpa.event.RemoteCommitListener; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.OpenJPAId; import serp.util.Strings; /** * Abstract {@link DataCache} implementation that provides various * statistics, logging, and timeout functionality common across cache * implementations. * * @author Patrick Linskey * @author Abe White */ @SuppressWarnings("serial") public abstract class AbstractDataCache extends AbstractConcurrentEventManager implements DataCache, Configurable { protected CacheStatisticsSPI _stats = new CacheStatisticsImpl(); private static final BitSet EMPTY_BITSET = new BitSet(0); private static final Localizer s_loc = Localizer.forPackage(AbstractDataCache.class); /** * The configuration set by the system. */ protected OpenJPAConfiguration conf; /** * The log to use. */ protected Log log; private String _name = null; private boolean _closed = false; private String _schedule = null; protected Set _includedTypes = new HashSet(); protected Set _excludedTypes = new HashSet(); protected boolean _evictOnBulkUpdate = true; public String getName() { return _name; } public void setName(String name) { _name = name; } public void setEnableStatistics(boolean enable){ if(enable == true){ _stats.enable(); } } public void getEnableStatistics(){ _stats.isEnabled(); } public String getEvictionSchedule() { return _schedule; } public void setEvictionSchedule(String s) { _schedule = s; } public void initialize(DataCacheManager manager) { if (_schedule != null && !"".equals(_schedule)) { ClearableScheduler scheduler = manager.getClearableScheduler(); if (scheduler != null) scheduler.scheduleEviction(this, _schedule); } // Cast here rather than add to the interface because this is a hack to support an older way of configuring if(manager instanceof DataCacheManagerImpl){ List invalidConfigured = new ArrayList(); // assert that things are configured properly if(_includedTypes!=null){ for(String s : _includedTypes){ if(_excludedTypes.contains(s)){ invalidConfigured.add(s); } } if (invalidConfigured.size() > 0) { throw new GeneralException(s_loc.get("invalid-types-excluded-types", invalidConfigured.toString())); } } ((DataCacheManagerImpl)manager).setTypes(_includedTypes, _excludedTypes); } } public void commit(Collection additions, Collection newUpdates, Collection existingUpdates, Collection deletes) { // remove all objects in deletes list removeAllInternal(deletes); // next, add all the new additions putAllInternal(additions); putAllInternal(newUpdates); // possibly add the existing updates, depending on the // semantics of the cache, as dictated by recacheUpdates() if (recacheUpdates()) putAllInternal(existingUpdates); if (log.isTraceEnabled()) { Collection addIds = new ArrayList(additions.size()); Collection upIds = new ArrayList(newUpdates.size()); Collection exIds = new ArrayList(existingUpdates.size()); for (DataCachePCData addition : additions) addIds.add(addition.getId()); for (DataCachePCData newUpdate : newUpdates) upIds.add(newUpdate.getId()); for (DataCachePCData existingUpdate : existingUpdates) exIds.add(existingUpdate.getId()); log.trace(s_loc.get("cache-commit", new Object[]{ addIds, upIds, exIds, deletes })); } } public boolean contains(Object key) { DataCachePCData o = getInternal(key); if (o != null && o.isTimedOut()) { o = null; removeInternal(key); if (log.isTraceEnabled()) log.trace(s_loc.get("cache-timeout", key)); } return o != null; } public BitSet containsAll(Collection keys) { if (keys.isEmpty()) return EMPTY_BITSET; BitSet set = new BitSet(keys.size()); int i = 0; for (Iterator iter = keys.iterator(); iter.hasNext(); i++) if (contains(iter.next())) set.set(i); return set; } public DataCachePCData get(Object key) { DataCachePCData o = getInternal(key); if (o != null && o.isTimedOut()) { o = null; removeInternal(key); if (log.isTraceEnabled()) log.trace(s_loc.get("cache-timeout", key)); } if (log.isTraceEnabled()) { if (o == null) log.trace(s_loc.get("cache-miss", key)); else log.trace(s_loc.get("cache-hit", key)); } return o; } /** * Returns the objects for the given key List. */ public Map getAll(List keys) { Map resultMap = new HashMap(keys.size()); for (Object key : keys) resultMap.put(key, get(key)); return resultMap; } public DataCachePCData put(DataCachePCData data) { DataCachePCData o = putInternal(data.getId(), data); if (log.isTraceEnabled()) log.trace(s_loc.get("cache-put", data.getId())); return (o == null || o.isTimedOut()) ? null : o; } public void update(DataCachePCData data) { if (recacheUpdates()) { putInternal(data.getId(), data); } } public DataCachePCData remove(Object key) { DataCachePCData o = removeInternal(key); if (o != null && o.isTimedOut()) o = null; if (log.isTraceEnabled()) { if (o == null) log.trace(s_loc.get("cache-remove-miss", key)); else log.trace(s_loc.get("cache-remove-hit", key)); } return o; } public BitSet removeAll(Collection keys) { if (keys.isEmpty()) return EMPTY_BITSET; BitSet set = new BitSet(keys.size()); int i = 0; for (Iterator iter = keys.iterator(); iter.hasNext(); i++) if (remove(iter.next()) != null) set.set(i); return set; } /** * Remove the objects of the given class from the cache. */ public void removeAll(Class cls, boolean subClasses) { removeAllInternal(cls, subClasses); } public boolean pin(Object key) { boolean bool = pinInternal(key); if (log.isTraceEnabled()) { if (bool) log.trace(s_loc.get("cache-pin-hit", key)); else log.trace(s_loc.get("cache-pin-miss", key)); } return bool; } public BitSet pinAll(Collection keys) { if (keys.isEmpty()) return EMPTY_BITSET; BitSet set = new BitSet(keys.size()); int i = 0; for (Iterator iter = keys.iterator(); iter.hasNext(); i++) if (pin(iter.next())) set.set(i); return set; } public void pinAll(Class cls, boolean subs) { if (log.isWarnEnabled()) log.warn(s_loc.get("cache-class-pin", getName())); } public boolean unpin(Object key) { boolean bool = unpinInternal(key); if (log.isTraceEnabled()) { if (bool) log.trace(s_loc.get("cache-unpin-hit", key)); else log.trace(s_loc.get("cache-unpin-miss", key)); } return bool; } public BitSet unpinAll(Collection keys) { if (keys.isEmpty()) return EMPTY_BITSET; BitSet set = new BitSet(keys.size()); int i = 0; for (Iterator iter = keys.iterator(); iter.hasNext(); i++) if (unpin(iter.next())) set.set(i); return set; } public void unpinAll(Class cls, boolean subs) { if (log.isWarnEnabled()) log.warn(s_loc.get("cache-class-unpin", getName())); } public void clear() { clearInternal(); if (log.isTraceEnabled()) log.trace(s_loc.get("cache-clear", getName())); } public void close() { close(true); } protected void close(boolean clear) { if (!_closed) { if (clear) clearInternal(); _closed = true; } } public boolean isClosed() { return _closed; } public void addExpirationListener(ExpirationListener listen) { addListener(listen); } public boolean removeExpirationListener(ExpirationListener listen) { return removeListener(listen); } public String toString() { return "[" + super.toString() + ":" + _name + "]"; } /** * This method is part of the {@link RemoteCommitListener} interface. If * your cache subclass relies on OpenJPA for clustering support, make it * implement RemoteCommitListener. This method will take * care of invalidating entries from remote commits. */ public void afterCommit(RemoteCommitEvent event) { if (_closed) return; if (event.getPayloadType() == RemoteCommitEvent.PAYLOAD_EXTENTS) { removeAllTypeNamesInternal(event.getUpdatedTypeNames()); removeAllTypeNamesInternal(event.getDeletedTypeNames()); } else { // drop all the committed OIDs, excepting brand // new OIDs. brand new OIDs either won't be in // the cache, or if they are, will be more up to date removeAllInternal(event.getUpdatedObjectIds()); removeAllInternal(event.getDeletedObjectIds()); } } /** * Invoke when a key is removed from this cache. Propagates the * expiration event on to all expiration listeners registered * with this class. */ protected void keyRemoved(Object key, boolean expired) { // Notify any expiration listeners of the expiration. if (hasListeners()) fireEvent(new ExpirationEvent(this, key, expired)); if (expired && log.isTraceEnabled()) log.trace(s_loc.get("cache-expired", key)); } /** * Return true if updates to data already in the * cache (either in {@link #commit} or the {@link #update}) * should be put back into the cache. Returns false by default. */ protected boolean recacheUpdates() { return false; } /** * Return the object for the given oid. */ protected abstract DataCachePCData getInternal(Object oid); /** * Add the given object to the cache, returning the old object under the * given oid. */ protected abstract DataCachePCData putInternal(Object oid, DataCachePCData pc); /** * Add all of the given objects to the cache. */ protected void putAllInternal(Collection pcs) { for (DataCachePCData pc : pcs) { putInternal(pc.getId(), pc); } } /** * Remove the object under the given oid from the cache. */ protected abstract DataCachePCData removeInternal(Object oid); /** * Evict objects in cache by class. */ protected abstract void removeAllInternal(Class cls, boolean subclasses); /** * Remove all objects under the given oids from the cache. */ protected void removeAllInternal(Collection oids) { for (Object oid : oids) removeInternal(oid); } /** * Remove all objects of the given class names from the cache. */ protected void removeAllTypeNamesInternal(Collection classNames) { Collection> classes = Caches.addTypesByName(conf, classNames, null); if (classes == null) return; for (Class cls : classes) { if (log.isTraceEnabled()) log.trace(s_loc.get("cache-removeclass", cls.getName())); removeAllInternal(cls, false); } } /** * Clear the cache. */ protected abstract void clearInternal(); /** * Pin an object to the cache. */ protected abstract boolean pinInternal(Object oid); /** * Unpin an object from the cache. */ protected abstract boolean unpinInternal(Object oid); /** * */ public DataCache getPartition(String name, boolean create) { if (StringUtils.equals(_name, name)) return this; return null; } /** * */ public Set getPartitionNames() { return Collections.emptySet(); } public boolean isPartitioned() { return false; } public CacheStatistics getStatistics() { return _stats; } // ---------- Configurable implementation ---------- public void setConfiguration(Configuration conf) { this.conf = (OpenJPAConfiguration) conf; this.log = conf.getLog(OpenJPAConfiguration.LOG_DATACACHE); } public void startConfiguration() { } public void endConfiguration() { if (_name == null) setName(NAME_DEFAULT); } // ---------- AbstractEventManager implementation ---------- protected void fireEvent(Object event, Object listener) { ExpirationListener listen = (ExpirationListener) listener; ExpirationEvent ev = (ExpirationEvent) event; try { listen.onExpire(ev); } catch (Exception e) { if (log.isWarnEnabled()) log.warn(s_loc.get("exp-listener-ex"), e); } } public Set getTypes() { return _includedTypes; } public Set getExcludedTypes() { return _excludedTypes; } public void setTypes(Set types) { _includedTypes = types; if (log.isWarnEnabled()) log.warn(s_loc.get("recommend_jpa2_caching", new Object[]{"Types", DataCacheMode.ENABLE_SELECTIVE.toString()})); } public void setTypes(String types) { _includedTypes = StringUtils.isEmpty(types) ? null : new HashSet(Arrays.asList(Strings.split(types, ";", 0))); if (log.isWarnEnabled()) log.warn(s_loc.get("recommend_jpa2_caching", new Object[]{"Types", DataCacheMode.ENABLE_SELECTIVE.toString()})); } public void setExcludedTypes(Set types) { _excludedTypes = types; if (log.isWarnEnabled()) log.warn(s_loc.get("recommend_jpa2_caching", new Object[]{"ExcludeTypes", DataCacheMode.DISABLE_SELECTIVE.toString()})); } public void setExcludedTypes(String types) { _excludedTypes = StringUtils.isEmpty(types) ? null : new HashSet(Arrays.asList(Strings.split(types, ";", 0))); if (log.isWarnEnabled()) log.warn(s_loc.get("recommend_jpa2_caching", new Object[]{"ExcludeTypes", DataCacheMode.DISABLE_SELECTIVE.toString()})); } public DataCache selectCache(OpenJPAStateManager sm) { return this; } public boolean getEvictOnBulkUpdate(){ return _evictOnBulkUpdate; } public void setEvictOnBulkUpdate(boolean b){ _evictOnBulkUpdate = b; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/Caches.java0000644000000000000000000000366612133327272025753 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; class Caches { /** * Utility to build up a set of classes from their class names * when operating outside the context of a persistence manager. * The set classes can be null, in which case a new Set will be created. */ static Set> addTypesByName(OpenJPAConfiguration conf, Collection classNames, Set> classes) { if (classNames == null || classNames.isEmpty()) return classes; ClassLoader loader = conf.getClassResolverInstance().getClassLoader(null, null); Class cls; for (String className : classNames) { try { cls = Class.forName(className, true, loader); if (classes == null) classes = new HashSet>(); classes.add(cls); } catch (Throwable t) { conf.getLog(OpenJPAConfiguration.LOG_RUNTIME).warn(null, t); } } return classes; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/AbstractQueryCache.java0000644000000000000000000004747412133327272030307 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.io.PrintStream; import java.security.AccessController; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.event.RemoteCommitEvent; import org.apache.openjpa.event.RemoteCommitListener; import org.apache.openjpa.kernel.QueryStatistics; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashSet; import org.apache.openjpa.lib.util.concurrent.SizedConcurrentHashMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.Id; /** * Abstract {@link QueryCache} implementation that provides various * statistics, logging, and timeout functionality common across cache * implementations. * * @author Patrick Linskey * @author Abe White */ public abstract class AbstractQueryCache extends AbstractConcurrentEventManager implements QueryCache, Configurable { private static final Localizer s_loc = Localizer.forPackage(AbstractQueryCache.class); private static final String TIMESTAMP = "timestamp"; public enum EvictPolicy {DEFAULT, TIMESTAMP}; /** * The configuration set by the system. */ protected OpenJPAConfiguration conf; /** * The log to use. */ protected Log log; protected ConcurrentHashMap entityTimestampMap = null; private boolean _closed = false; private String _name = null; // default evict policy public EvictPolicy evictPolicy = EvictPolicy.DEFAULT; private QueryStatistics _stats; private boolean _statsEnabled = false; public void setEnableStatistics(boolean enable){ _statsEnabled = enable; } public boolean getEnableStatistics(){ return _statsEnabled; } public QueryStatistics getStatistics() { return _stats; } public void initialize(DataCacheManager manager) { if (evictPolicy == EvictPolicy.TIMESTAMP) { entityTimestampMap = new ConcurrentHashMap(); // Get all persistence types to pre-load the entityTimestamp Map Collection perTypes = conf.getMetaDataRepositoryInstance().getPersistentTypeNames( false, AccessController.doPrivileged(J2DoPrivHelper .getContextClassLoaderAction())); // Pre-load all the entity types into the HashMap to handle // synchronization on the map efficiently for (Object o : perTypes) entityTimestampMap.put((String)o, Long.valueOf(0)); } } public void onTypesChanged(TypesChangedEvent ev) { if (evictPolicy == EvictPolicy.DEFAULT) { writeLock(); Collection keys = null; try { if (hasListeners()) fireEvent(ev); keys = keySet(); } finally { writeUnlock(); } QueryKey qk; List removes = null; for (Object o: keys) { qk = (QueryKey) o; if (qk.changeInvalidatesQuery(ev.getTypes())) { if (removes == null) removes = new ArrayList(); removes.add(qk); } } if (removes != null) removeAllInternal(removes); } else { Collection changedTypes = ev.getTypes(); HashMap changedClasses = new HashMap(); Long tstamp = Long.valueOf(System.currentTimeMillis()); for (Object o: changedTypes) { String name = ((Class) o).getName(); if(!changedClasses.containsKey(name)) { changedClasses.put(name, tstamp ); } } // Now update entity timestamp map updateEntityTimestamp(changedClasses); } } public QueryResult get(QueryKey key) { if (_statsEnabled) { _stats.recordExecution(key); } QueryResult o = getInternal(key); if (o != null && o.isTimedOut()) { o = null; removeInternal(key); if (log.isTraceEnabled()) log.trace(s_loc.get("cache-timeout", key)); } if (log.isTraceEnabled()) { if (o == null) log.trace(s_loc.get("cache-miss", key)); else log.trace(s_loc.get("cache-hit", key)); } if (_statsEnabled && o != null) { ((Default)_stats).recordHit(key); } return o; } public QueryResult put(QueryKey qk, QueryResult oids) { QueryResult o = putInternal(qk, oids); if (log.isTraceEnabled()) log.trace(s_loc.get("cache-put", qk)); return (o == null || o.isTimedOut()) ? null : o; } public QueryResult remove(QueryKey key) { QueryResult o = removeInternal(key); if (_statsEnabled) { _stats.recordEviction(key); } if (o != null && o.isTimedOut()) o = null; if (log.isTraceEnabled()) { if (o == null) log.trace(s_loc.get("cache-remove-miss", key)); else log.trace(s_loc.get("cache-remove-hit", key)); } return o; } public boolean pin(QueryKey key) { boolean bool = pinInternal(key); if (log.isTraceEnabled()) { if (bool) log.trace(s_loc.get("cache-pin-hit", key)); else log.trace(s_loc.get("cache-pin-miss", key)); } return bool; } public boolean unpin(QueryKey key) { boolean bool = unpinInternal(key); if (log.isTraceEnabled()) { if (bool) log.trace(s_loc.get("cache-unpin-hit", key)); else log.trace(s_loc.get("cache-unpin-miss", key)); } return bool; } public void clear() { clearInternal(); if (log.isTraceEnabled()) log.trace(s_loc.get("cache-clear", "")); if (_statsEnabled) { _stats.clear(); } } public void close() { close(true); } protected void close(boolean clear) { if (!_closed) { if (clear) clearInternal(); _closed = true; } } public boolean isClosed() { return _closed; } public void addTypesChangedListener(TypesChangedListener listen) { addListener(listen); } public boolean removeTypesChangedListener(TypesChangedListener listen) { return removeListener(listen); } /** * This method is part of the {@link RemoteCommitListener} interface. If * your cache subclass relies on OpenJPA for clustering support, make it * implement RemoteCommitListener. This method will take * care of invalidating entries from remote commits, by delegating to * {@link #onTypesChanged}. */ public void afterCommit(RemoteCommitEvent event) { if (_closed) return; // drop all committed classes Set classes = Caches.addTypesByName(conf, event.getPersistedTypeNames(), null); if (event.getPayloadType() == RemoteCommitEvent.PAYLOAD_EXTENTS) { classes = Caches.addTypesByName(conf, event.getUpdatedTypeNames(), classes); classes = Caches.addTypesByName(conf, event.getDeletedTypeNames(), classes); } else { classes = addTypes(event.getUpdatedObjectIds(), classes); classes = addTypes(event.getDeletedObjectIds(), classes); } if (classes != null) onTypesChanged(new TypesChangedEvent(this, classes)); } /** * Build up a set of classes for the given oids. */ private Set addTypes(Collection oids, Set classes) { if (oids.isEmpty()) return classes; if (classes == null) classes = new HashSet(); MetaDataRepository repos = conf.getMetaDataRepositoryInstance(); ClassMetaData meta; Object oid; for (Iterator itr = oids.iterator(); itr.hasNext();) { oid = itr.next(); if (oid instanceof Id) classes.add(((Id) oid).getType()); else { // ok if no metadata for oid; that just means the pc type // probably hasn't been loaded into this JVM yet, and therefore // there's no chance that it's in the cache anyway meta = repos.getMetaData(oid, null, false); if (meta != null) classes.add(meta.getDescribedType()); } } return classes; } /** * Return a threadsafe view of the keys in this cache. This collection * must be iterable without risk of concurrent modification exceptions. * It does not have to implement contains() efficiently or use set * semantics. */ protected abstract Collection keySet(); /** * Return the list for the given key. */ protected abstract QueryResult getInternal(QueryKey qk); /** * Add the given result to the cache, returning the old result under the * given key. */ protected abstract QueryResult putInternal(QueryKey qk, QueryResult oids); /** * Remove the result under the given key from the cache. */ protected abstract QueryResult removeInternal(QueryKey qk); /** * Remove all results under the given keys from the cache. */ protected void removeAllInternal(Collection qks) { for (Iterator iter = qks.iterator(); iter.hasNext();) removeInternal((QueryKey) iter.next()); } /** * Clear the cache. */ protected abstract void clearInternal(); /** * Pin an object to the cache. */ protected abstract boolean pinInternal(QueryKey qk); /** * Unpin an object from the cache. */ protected abstract boolean unpinInternal(QueryKey qk); // ---------- Configurable implementation ---------- public void setConfiguration(Configuration conf) { this.conf = (OpenJPAConfiguration) conf; this.log = conf.getLog(OpenJPAConfiguration.LOG_DATACACHE); } public void startConfiguration() { } public void endConfiguration() { _stats = _statsEnabled ? new Default() : new QueryStatistics.None(); } // ---------- AbstractEventManager implementation ---------- protected void fireEvent(Object event, Object listener) { TypesChangedListener listen = (TypesChangedListener) listener; TypesChangedEvent ev = (TypesChangedEvent) event; try { listen.onTypesChanged(ev); } catch (Exception e) { if (log.isWarnEnabled()) log.warn(s_loc.get("exp-listener-ex"), e); } } /** * Individual query results will be registered as types changed * listeners. We want such query results to be gc'd once * the only reference is held by the list of expiration listeners. */ protected Collection newListenerCollection() { return new ConcurrentReferenceHashSet (ConcurrentReferenceHashSet.WEAK); } /** * Sets the eviction policy for the query cache * @param evictPolicy -- String value that specifies the eviction policy */ public void setEvictPolicy(String evictPolicy) { if (evictPolicy.equalsIgnoreCase(TIMESTAMP)) this.evictPolicy = EvictPolicy.TIMESTAMP; } /** * Returns the evictionPolicy for QueryCache * @return -- returns a String value of evictPolicy attribute */ public EvictPolicy getEvictPolicy() { return this.evictPolicy; } /** * Updates the entity timestamp map with the current time in milliseconds * @param timestampMap -- a map that contains entityname and its last * updated timestamp */ protected void updateEntityTimestamp(Map timestampMap) { if (entityTimestampMap != null) entityTimestampMap.putAll(timestampMap); } /** * Returns a list of timestamps in the form of Long objects * which are the last updated time stamps for the given entities in the * keylist. * @param keyList -- List of entity names * @return -- Returns a list that has the timestamp for the given entities */ public List getAllEntityTimestamp(List keyList) { ArrayList tmval = null; if (entityTimestampMap != null) { for (String s: keyList) { if (entityTimestampMap.containsKey(s)) { if(tmval == null) tmval = new ArrayList(); tmval.add(entityTimestampMap.get(s)); } } } return tmval; } public void setName(String n) { _name = n; } public String getName() { return _name; } public int count() { return keySet().size(); } /** * A default implementation of query statistics for the Query result cache. * * Maintains statistics for only a fixed number of queries. * Statistical counts are approximate and not exact (to keep thread synchorization overhead low). * */ public static class Default implements QueryStatistics { private static final long serialVersionUID = -7889619105916307055L; private static final int FIXED_SIZE = 1000; private static final float LOAD_FACTOR = 0.75f; private static final int CONCURRENCY = 16; private static final int ARRAY_SIZE = 3; private static final int READ = 0; private static final int HIT = 1; private static final int EVICT = 2; private long[] astat = new long[ARRAY_SIZE]; private long[] stat = new long[ARRAY_SIZE]; private Map stats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY); private Map astats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY); private Date start = new Date(); private Date since = start; public Set keys() { return stats.keySet(); } public long getExecutionCount() { return stat[READ]; } public long getTotalExecutionCount() { return astat[READ]; } public long getExecutionCount(T query) { return getCount(stats, query, READ); } public long getTotalExecutionCount(T query) { return getCount(astats, query, READ); } public long getHitCount() { return stat[HIT]; } public long getTotalHitCount() { return astat[HIT]; } public long getHitCount(T query) { return getCount(stats, query, HIT); } public long getTotalHitCount(T query) { return getCount(astats, query, HIT); } public long getEvictionCount() { return stat[EVICT]; } public long getTotalEvictionCount() { return astat[EVICT]; } private long getCount(Map target, T query, int i) { long[] row = target.get(query); return (row == null) ? 0 : row[i]; } public Date since() { return since; } public Date start() { return start; } public synchronized void reset() { stat = new long[ARRAY_SIZE]; stats.clear(); since = new Date(); } @SuppressWarnings("unchecked") public synchronized void clear() { astat = new long[ARRAY_SIZE]; stat = new long[ARRAY_SIZE]; stats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY); astats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY); start = new Date(); since = start; } private void addSample(T query, int index) { stat[index]++; astat[index]++; addSample(stats, query, index); addSample(astats, query, index); } private void addSample(Map target, T query, int i) { long[] row = target.get(query); if (row == null) { row = new long[ARRAY_SIZE]; } row[i]++; target.put(query, row); } public void recordExecution(T query) { if (query == null) return; addSample(query, READ); } public void recordHit(T query) { addSample(query, HIT); } public void recordEviction(T query) { if (query == null) return; addSample(query, EVICT); } public void dump(PrintStream out) { String header = "Query Statistics starting from " + start; out.print(header); if (since == start) { out.println(); out.println("Total Query Execution: " + toString(astat)); out.println("\tTotal \t\tQuery"); } else { out.println(" last reset on " + since); out.println("Total Query Execution since start " + toString(astat) + " since reset " + toString(stat)); out.println("\tSince Start \tSince Reset \t\tQuery"); } int i = 0; for (T key : stats.keySet()) { i++; long[] arow = astats.get(key); if (since == start) { out.println(i + ". \t" + toString(arow) + " \t" + key); } else { long[] row = stats.get(key); out.println(i + ". \t" + toString(arow) + " \t" + toString(row) + " \t\t" + key); } } } long pct(long per, long cent) { if (cent <= 0) return 0; return (100*per)/cent; } String toString(long[] row) { return row[READ] + ":" + row[HIT] + "(" + pct(row[HIT], row[READ]) + "%)"; } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCDataImpl.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCDataImpl.jav0000644000000000000000000001547312133327272030057 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.BitSet; import org.apache.openjpa.kernel.AbstractPCData; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.PCData; import org.apache.openjpa.kernel.PCDataImpl; import org.apache.openjpa.kernel.PCState; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; /** * Specialized {@link PCData} implementation for data caching. This * implementation is properly synchronized. * * @author Patrick Linskey */ @SuppressWarnings("serial") public class DataCachePCDataImpl extends PCDataImpl implements DataCachePCData { private final long _exp; public DataCachePCDataImpl(Object oid, ClassMetaData meta) { this(oid, meta, DataCache.NAME_DEFAULT); } /** * Constructor. */ public DataCachePCDataImpl(Object oid, ClassMetaData meta, String name) { super(oid, meta, name); int timeout = meta.getDataCacheTimeout(); if (timeout > 0) _exp = System.currentTimeMillis() + timeout; else _exp = -1; } public boolean isTimedOut() { return _exp != -1 && _exp < System.currentTimeMillis(); } public long getTimeOut() { return _exp; } public synchronized Object getData(int index) { return super.getData(index); } public synchronized void setData(int index, Object val) { super.setData(index, val); } public synchronized void clearData(int index) { super.clearData(index); } public synchronized Object getImplData() { return super.getImplData(); } public synchronized void setImplData(Object val) { super.setImplData(val); } public synchronized Object getImplData(int index) { return super.getImplData(index); } public synchronized void setImplData(int index, Object val) { super.setImplData(index, val); } public synchronized Object getIntermediate(int index) { return super.getIntermediate(index); } public synchronized void setIntermediate(int index, Object val) { super.setIntermediate(index, val); } public synchronized boolean isLoaded(int index) { return super.isLoaded(index); } public synchronized void setLoaded(int index, boolean loaded) { super.setLoaded(index, loaded); } public synchronized Object getVersion() { return super.getVersion(); } public synchronized void setVersion(Object version) { super.setVersion(version); } public synchronized void store(OpenJPAStateManager sm) { super.store(sm); } public synchronized void store(OpenJPAStateManager sm, BitSet fields) { super.store(sm, fields); } /** * Store field-level information from the given state manager. * Special process of checking if the cached collection data is out of * order. */ protected void storeField(OpenJPAStateManager sm, FieldMetaData fmd) { if (fmd.getManagement() != FieldMetaData.MANAGE_PERSISTENT) return; int index = fmd.getIndex(); // if the field is a collection and has "order by" set, don't cache // it if this store is coming from a create or update (i.e., only // enlist in cache if this is coming from a database read). if (fmd.getOrders().length > 0) { if (sm.getPCState() == PCState.PNEW) return; if (sm.getPCState() == PCState.PDIRTY) { clearData(index); return; } } super.storeField(sm, fmd); // If this field is used in "order by", we need to invalidate cache // for the collection that refer to this field. if ((sm.getPCState() == PCState.PDIRTY) && fmd.isUsedInOrderBy()) { clearInverseRelationCache(sm, fmd); } } /** * Check if this field is in use of "order by" by other field collections * in inverse relation. If it is, clear the other field cache because it * could be out of order. */ protected void clearInverseRelationCache(OpenJPAStateManager sm, FieldMetaData fmd) { DataCache cache = sm.getMetaData().getDataCache(); if (cache == null) return; ClassMetaData cmd = sm.getMetaData(); FieldMetaData[] fields = cmd.getFields(); for (int i = 0; i < fields.length; i++) { FieldMetaData[] inverses = fields[i].getInverseMetaDatas(); if (inverses.length == 0) continue; for (FieldMetaData inverse : inverses) { if (inverse.getOrderDeclaration().indexOf(fmd.getName()) != -1) { Object oid = sm.getContext().getObjectId(sm.fetch(i)); DataCachePCData data = cache.get(oid); if (data instanceof DataCachePCDataImpl) { ((DataCachePCDataImpl) data).clearData(inverse.getIndex()); } } } } } protected Object toData(FieldMetaData fmd, Object val, StoreContext ctx) { // avoid caching large result set fields if (fmd.isLRS() || fmd.isStream()) return NULL; return super.toData(fmd, val, ctx); } protected Object toNestedData(ValueMetaData vmd, Object val, StoreContext ctx) { if (val == null) return null; // don't try to cache nested containers switch (vmd.getDeclaredTypeCode()) { case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.ARRAY: return NULL; default: return super.toNestedData(vmd, val, ctx); } } public AbstractPCData newEmbeddedPCData(OpenJPAStateManager sm) { return new DataCachePCDataImpl(sm.getId(), sm.getMetaData(), getCache()); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/ClearableScheduler.java0000644000000000000000000002227212133327272030270 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.security.AccessController; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.Map; import java.util.StringTokenizer; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Clearable; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.UserException; import serp.util.Strings; /** * Cron-style clearable eviction. Understands schedules based on cron format: *
  • minute hour mday month wday
  • *
  • +minute
  • * For example: * 15,30 6,19 2,10 1 2 * Would run at 15 and 30 past the 6AM and 7PM, on the 2nd and 10th * of January when its a Monday. * */ public class ClearableScheduler implements Runnable { private static final Localizer _loc = Localizer.forPackage(ClearableScheduler.class); private Map _clearables = new ConcurrentHashMap(); private boolean _stop = false; private int _interval = 1; private Log _log; private Thread _thread; public ClearableScheduler(OpenJPAConfiguration conf) { _log = conf.getLogFactory().getLog(OpenJPAConfiguration.LOG_DATACACHE); } /** * The interval time in minutes between scheduler checks. Defaults to 1. */ public int getInterval() { return _interval; } /** * The interval time in minutes between scheduler checks. Defaults to 1. */ public void setInterval(int interval) { _interval = interval; } /** * Stop the associated thread if there and stop the current runnable. */ public synchronized void stop() { _stop = true; } private boolean isStopped() { return _stop; } /** * Schedule the given Clearable for clear to be called. Starts the scheduling thread * if not started. */ public synchronized void scheduleEviction(Clearable clearable, String times) { if (times == null) return; Schedule schedule = new Schedule(times); _clearables.put(clearable, schedule); _stop = false; if (_thread == null) { _thread = AccessController.doPrivileged(J2DoPrivHelper .newDaemonThreadAction(this, _loc.get("scheduler-name") .getMessage())); _thread.start(); if (_log.isTraceEnabled()) _log.trace(_loc.get("scheduler-start", _thread.getName())); } } /** * Remove the given Clearable from scheduling. */ public synchronized void removeFromSchedule(Clearable clearable) { _clearables.remove(clearable); if (_clearables.size() == 0) stop(); } public void run() { if (_log.isTraceEnabled()) _log.trace(_loc.get("scheduler-interval", _interval + "")); Date lastRun = new Date(); DateFormat fom = new SimpleDateFormat("E HH:mm:ss"); while (!isStopped()) { try { Thread.sleep(_interval * 60 * 1000); Date now = new Date(); for(Entry entry : _clearables.entrySet()){ Clearable clearable = entry.getKey(); Schedule schedule = entry.getValue(); if (schedule.matches(lastRun, now)) { if (_log.isTraceEnabled()) _log.trace(_loc.get("scheduler-clear", clearable, fom.format(now))); evict(clearable); } } lastRun = now; } catch (Exception e) { throw new InvalidStateException(_loc.get("scheduler-fail"), e). setFatal(true); } } _log.info(_loc.get("scheduler-stop")); synchronized (this) { if (isStopped()) _thread = null; // be sure to deref the thread so it can restart } } protected void evict(Clearable cache) { cache.clear(); } /** * Simple class which represents the given time schedule. */ private static class Schedule { static final int[] WILDCARD = new int[0]; static final int[] UNITS = { Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.DAY_OF_WEEK, Calendar.HOUR_OF_DAY, Calendar.MINUTE }; final int[] month; final int[] dayOfMonth; final int[] dayOfWeek; final int[] hour; final int[] min; public Schedule(String date) { int[] tmin = null; if (date.startsWith("+")) { Calendar cal = Calendar.getInstance(); int interval = Integer.parseInt(date.substring(1)); int currMin = cal.get(Calendar.MINUTE); tmin = new int[60/interval]; for(int i = 0; i= 60 ){ temp -= 60; } tmin[i]=temp; } Arrays.sort(tmin); min = tmin; hour = WILDCARD; dayOfMonth = WILDCARD; month = WILDCARD; dayOfWeek = WILDCARD; }else{ StringTokenizer token = new StringTokenizer(date, " \t"); if (token.countTokens() != 5) throw new UserException(_loc.get("bad-count", date)).setFatal(true); try { min = parse(token.nextToken(), 0, 60); hour = parse(token.nextToken(), 0, 24); dayOfMonth = parse(token.nextToken(), 1, 31); month = parse(token.nextToken(), 1, 13); dayOfWeek = parse(token.nextToken(), 1, 8); } catch (Throwable t) { throw new UserException(_loc.get("bad-schedule", date), t).setFatal(true); } } } private int[] parse(String token, int min, int max) { if ("*".equals(token.trim())) return WILDCARD; String[] tokens = Strings.split(token, ",", 0); int [] times = new int[tokens.length]; for (int i = 0; i < tokens.length; i++) { try { times[i] = Integer.parseInt(tokens[i]); } catch (Throwable t) { throw new UserException(_loc.get("not-number", token)). setFatal(true); } if (times[i] < min || times[i] >= max) throw new UserException(_loc.get("not-range", token, String.valueOf(min), String.valueOf(max))). setFatal(true); } return times; } boolean matches(Date last, Date now) { Calendar time = Calendar.getInstance(); time.setTime(now); time.set(Calendar.SECOND, 0); time.set(Calendar.MILLISECOND, 0); int[][] all = new int[][]{ month, dayOfMonth, dayOfWeek, hour, min }; return matches(last, now, time, all, 0); } private boolean matches(Date last, Date now, Calendar time, int[][] times, int depth) { if (depth == UNITS.length) { Date compare = time.getTime(); return compare.compareTo(last) >= 0 && compare.compareTo(now) < 0; } if (times[depth] != WILDCARD) { for (int i = 0; i < times[depth].length; i++) { time.set(UNITS[depth], times[depth][i]); if (matches(last, now, time, times, depth + 1)) return true; } } return matches(last, now, time, times, depth + 1); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/TypesChangedListener.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/TypesChangedListener.ja0000644000000000000000000000216512133327272030313 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; /** * An entity that wishes to be notified when types change. * * @author Abe White * @since 0.3.0 */ public interface TypesChangedListener { /** * Notification that instances of persistent types have changed. */ public void onTypesChanged(TypesChangedEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCache.java0000644000000000000000000001150112133327272026601 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.Map; import org.apache.openjpa.kernel.QueryStatistics; import org.apache.openjpa.lib.util.Closeable; /** * Interface that must be implemented by any level 2 query cache * used by OpenJPA. These methods should be threadsafe. * Most query cache implementations will probably implement * {@link org.apache.openjpa.lib.conf.Configurable} to receive a handle to the * system configuration on construction. * * @since 0.2.5 * @author Patrick Linskey */ public interface QueryCache extends TypesChangedListener, Closeable { /** * Initialize any resources associated with the given * {@link DataCacheManager}. * * @since 0.4.1 */ public void initialize(DataCacheManager manager); /** * Return a list of oids for the given query key. This is an * unmodifiable list. * * @return The query results matching the given key, or null if none */ public QueryResult get(QueryKey qk); /** * Set the list of OIDs for the given query key. A reference * to the given list will be stored in the query cache, so the * list should not be modified after invoking this method. * * @return The previously cached value, or null if * the key was not previously cached. See {@link Map#put} * for more information. */ public QueryResult put(QueryKey qk, QueryResult oids); /** * Remove the value stored under the given query key. * This method is typically not invoked directly from outside * the QueryCache class. Instead, the cache should * be updated by implementing {@link * org.apache.openjpa.event.RemoteCommitListener}, * which will result in all queries that may be invalid being dropped. * * @return The previously cached value, or null if * the key was not previously cached. See {@link Map#remove} * for more information. */ public QueryResult remove(QueryKey qk); /** * Remove all data from this cache. */ public void clear(); /** * Pin the value stored under qk into the * cache. This method guarantees that qk's value * will not be expired if the cache exceeds its capacity. It * causes this data to be ignored when determining whether or not * the cache is full, effectively increasing the total amount of * data stored in the cache. This method does not affect the * behavior of {@link #remove} or {@link #onTypesChanged}. * * @return true if key's value was * pinned into the cache; false if the key is not in the cache. */ public boolean pin(QueryKey qk); /** * Unpin the value stored under key into the cache. * This method reverses a previous invocation of {@link #pin}. * This method does not remove anything from the cache; it merely * makes key's value a candidate for flushing from the cache. * * @return true if key's value was * unpinned from the cache; false if the * key is not in the cache. */ public boolean unpin(QueryKey qk); /** * Obtain a write lock on the cache. */ public void writeLock(); /** * Release the write lock on the cache. */ public void writeUnlock(); /** * Add a new types event listener to this cache. * * @since 0.3.3 */ public void addTypesChangedListener(TypesChangedListener listen); /** * Remove an types event listener from this cache. * * @since 0.3.3 */ public boolean removeTypesChangedListener(TypesChangedListener listen); /** * Free the resources used by this cache. */ public void close (); /** * Gets the simple statistics for query results. * If the statistics gathering is disabled, an empty statistics is returned. * @since 2.1.0 */ public QueryStatistics getStatistics(); } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DefaultCacheDistributionPolicy.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DefaultCacheDistributio0000644000000000000000000000316212133327272030366 0ustar /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.openjpa.datacache; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.meta.ClassMetaData; /** * A default implementation that selects the cache by the type of the given managed instance. * The name of the cache is determined by {@link ClassMetaData#getDataCacheName() name as specified} by * the metadata. * * @see ClassMetaData#getDataCacheName() * */ public class DefaultCacheDistributionPolicy implements CacheDistributionPolicy { public String selectCache(OpenJPAStateManager sm, Object context) { return sm.getMetaData().getDataCacheName(); } public void endConfiguration() { } public void setConfiguration(Configuration conf) { } public void startConfiguration() { } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheManagerImpl.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheManagerImpl.ja0000644000000000000000000001772412133327272030150 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.enhance.PCDataGenerator; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.conf.ObjectValue; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.ImplHelper; /** * Default data cache manager provides handle to utilities {@linkplain PCDataGenerator}, {@linkplain ClearableScheduler} * and {@linkplain CacheDistributionPolicy} for the cache operation. This implementation also determines whether a * managed type is eligible to cache. * * @author Abe White * @author Patrick Linskey * @author Pinaki Poddar */ public class DataCacheManagerImpl implements Closeable, DataCacheManager { private OpenJPAConfiguration _conf; private DataCache _cache = null; private QueryCache _queryCache = null; private DataCachePCDataGenerator _pcGenerator = null; private ClearableScheduler _scheduler = null; private CacheDistributionPolicy _policy = new DefaultCacheDistributionPolicy(); private Map _cacheable = new HashMap(); // Properties that are configured via openjpa.DataCache but need to be used here. This is here to support the 1.2 // way of doing things with openjpa.DataCache(Types=x;y;z,ExcludedTypes=a) private Set _includedTypes; private Set _excludedTypes; public void initialize(OpenJPAConfiguration conf, ObjectValue dataCache, ObjectValue queryCache) { _conf = conf; _queryCache = (QueryCache) queryCache.instantiate(QueryCache.class, conf); if (_queryCache != null) _queryCache.initialize(this); _cache = (DataCache) dataCache.instantiate(DataCache.class, conf); if (_cache == null) return; // create helpers before initializing caches if (conf.getDynamicDataStructs()) _pcGenerator = new DataCachePCDataGenerator(conf); _scheduler = new ClearableScheduler(conf); _policy = conf.getCacheDistributionPolicyInstance(); _cache.initialize(this); } public DataCache getSystemDataCache() { return getDataCache(null, false); } public DataCache getDataCache(String name) { return getDataCache(name, false); } /** * Returns the named cache. * If the given name is name or the name of the cache plugin then returns the main cache. * Otherwise, {@linkplain DataCache#getPartition(String, boolean) delegates} to the main cache * to obtain a partition. */ public DataCache getDataCache(String name, boolean create) { if (name == null || (_cache != null && name.equals(_cache.getName()))) return _cache; if (_cache != null) return _cache.getPartition(name, create); return null; } public QueryCache getSystemQueryCache() { return _queryCache; } public DataCachePCDataGenerator getPCDataGenerator() { return _pcGenerator; } public ClearableScheduler getClearableScheduler() { return _scheduler; } public void close() { ImplHelper.close(_cache); ImplHelper.close(_queryCache); if (_scheduler != null) _scheduler.stop(); } /** * Select cache for the given managed instance. * If type based verification affirms the type to be cached then the instance based policy * is called to determine the target cache. */ public DataCache selectCache(OpenJPAStateManager sm) { if (sm == null || !isCachable(sm.getMetaData())) return null; String name = _policy.selectCache(sm, null); return name == null ? null : getDataCache(name); } /** * Gets the instance-based cache distribution policy, if configured. */ public CacheDistributionPolicy getDistributionPolicy() { return _policy; } /** * Affirms if the given type is eligible for cache. */ public boolean isCachable(ClassMetaData meta) { Boolean res = _cacheable.get(meta); if(res != null){ return res; } Boolean isCachable = isCacheableByMode(meta); if (isCachable == null) { isCachable = isCacheableByType(meta); } _cacheable.put(meta, isCachable); return isCachable; } public void setTypes(Set includedTypes, Set excludedTypes){ _includedTypes = includedTypes; _excludedTypes = excludedTypes; } /** * Affirms the given class is eligible to be cached according to the cache mode * and the cache enable flag on the given metadata. * * @return TRUE or FALSE if cache mode is configured. null otherwise. */ private Boolean isCacheableByMode(ClassMetaData meta) { String mode = _conf.getDataCacheMode(); if (DataCacheMode.ALL.toString().equalsIgnoreCase(mode)) return true; if (DataCacheMode.NONE.toString().equalsIgnoreCase(mode)) return false; if (DataCacheMode.ENABLE_SELECTIVE.toString().equalsIgnoreCase(mode)) return Boolean.TRUE.equals(meta.getCacheEnabled()); if (DataCacheMode.DISABLE_SELECTIVE.toString().equalsIgnoreCase(mode)) return !Boolean.FALSE.equals(meta.getCacheEnabled()); return null; } /** * Is the given type cacheable by @DataCache annotation or openjpa.DataCache(Types/ExcludedTypes) * * @see ClassMetaData#getDataCacheName() */ private Boolean isCacheableByType(ClassMetaData meta) { if (_includedTypes != null && _includedTypes.size() > 0) { return _includedTypes.contains(meta.getDescribedType().getName()); } if (_excludedTypes != null && _excludedTypes.size() > 0) { if (_excludedTypes.contains(meta.getDescribedType().getName())) { return false; } else { // Case where Types is not set, and ExcludedTypes only has a sub set of all // Entities. return true; } } // Check for @DataCache annotations return meta.getDataCacheName() != null; } public void startCaching(String cls) { MetaDataRepository mdr = _conf.getMetaDataRepositoryInstance(); ClassMetaData cmd = mdr.getCachedMetaData(cls); _cacheable.put(cmd, Boolean.TRUE); } public void stopCaching(String cls) { MetaDataRepository mdr = _conf.getMetaDataRepositoryInstance(); ClassMetaData cmd = mdr.getCachedMetaData(cls); _cacheable.put(cmd, Boolean.FALSE); } public Map listKnownTypes() { Map res = new HashMap(); for (Entry entry : _cacheable.entrySet()) { res.put(entry.getKey().getDescribedTypeString(), entry.getValue()); } return res; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/CacheStatisticsSPI.java0000644000000000000000000000312612133327272030206 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; /** * The provider extensions to the CacheStatistics interface. */ public interface CacheStatisticsSPI extends CacheStatistics { /** * Record a new cache get. * * @param cls * - The class describing the type that is contained in the cache. * @param hit * - true for a cache hit, false otherwise */ public void newGet(Class cls, boolean hit); /** * Record a new cache put. * * @param cls * - The class describing the type that is contained in the cache. */ public void newPut(Class cls); /** * Enable statistics collection. */ public void enable(); /** * Disable statistics collection. */ public void disable(); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingQueryCache.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingQueryCache.ja0000644000000000000000000001371212133327272030244 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import org.apache.commons.lang.ObjectUtils; import org.apache.openjpa.kernel.QueryStatistics; import org.apache.openjpa.util.RuntimeExceptionTranslator; /** * Delegating query cache that can also perform exception translation for * use in facades. This cache allows its delegate to be null, in which case * it returns default values or all methods. * * @author Abe White * @since 0.4.0 * @nojavadoc */ public class DelegatingQueryCache implements QueryCache { private final QueryCache _cache; private final DelegatingQueryCache _del; private final RuntimeExceptionTranslator _trans; /** * Constructor. Supply delegate. */ public DelegatingQueryCache(QueryCache cache) { this(cache, null); } public DelegatingQueryCache(QueryCache cache, RuntimeExceptionTranslator trans) { _cache = cache; _trans = trans; if (cache instanceof DelegatingQueryCache) _del = (DelegatingQueryCache) _cache; else _del = null; } /** * Return the direct delegate. */ public QueryCache getDelegate() { return _cache; } /** * Return the native delegate. */ public QueryCache getInnermostDelegate() { return (_del == null) ? _cache : _del.getInnermostDelegate(); } public int hashCode() { return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingQueryCache) other = ((DelegatingQueryCache) other).getInnermostDelegate(); return ObjectUtils.equals(getInnermostDelegate(), other); } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public void initialize(DataCacheManager mgr) { if (_cache == null) return; try { _cache.initialize(mgr); } catch (RuntimeException re) { throw translate(re); } } public void onTypesChanged(TypesChangedEvent e) { if (_cache == null) return; try { _cache.onTypesChanged(e); } catch (RuntimeException re) { throw translate(re); } } public QueryResult get(QueryKey qk) { if (_cache == null) return null; try { return _cache.get(qk); } catch (RuntimeException re) { throw translate(re); } } public QueryResult put(QueryKey qk, QueryResult oids) { if (_cache == null) return null; try { return _cache.put(qk, oids); } catch (RuntimeException re) { throw translate(re); } } public QueryResult remove(QueryKey qk) { if (_cache == null) return null; try { return _cache.remove(qk); } catch (RuntimeException re) { throw translate(re); } } public void clear() { if (_cache == null) return; try { _cache.clear(); } catch (RuntimeException re) { throw translate(re); } } public boolean pin(QueryKey qk) { if (_cache == null) return false; try { return _cache.pin(qk); } catch (RuntimeException re) { throw translate(re); } } public boolean unpin(QueryKey qk) { if (_cache == null) return false; try { return _cache.unpin(qk); } catch (RuntimeException re) { throw translate(re); } } public void writeLock() { if (_cache == null) return; try { _cache.writeLock(); } catch (RuntimeException re) { throw translate(re); } } public void writeUnlock() { if (_cache == null) return; try { _cache.writeUnlock(); } catch (RuntimeException re) { throw translate(re); } } public void addTypesChangedListener(TypesChangedListener listen) { if (_cache == null) return; try { _cache.addTypesChangedListener(listen); } catch (RuntimeException re) { throw translate(re); } } public boolean removeTypesChangedListener(TypesChangedListener listen) { if (_cache == null) return false; try { return _cache.removeTypesChangedListener(listen); } catch (RuntimeException re) { throw translate(re); } } public void close() { if (_cache == null) return; try { _cache.close(); } catch (RuntimeException re) { throw translate(re); } } public QueryStatistics getStatistics() { if (_cache == null) return null; try { return _cache.getStatistics(); } catch (RuntimeException re) { throw translate(re); } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/CacheDistributionPolicy.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/CacheDistributionPolicy0000644000000000000000000000534512133327272030424 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.conf.Configurable; /** * A policy determines whether a given entity should be cached and if true, in which named partition of the * cache. *
    * This policy is activated for each instance if and only if the cache settings specified in metadata * such as JPA specification defined {@link Cacheable @Cacheable} annotation or OpenJPA specific * {@link org.apache.openjpa.persistence.DataCache @DataCache} annotation or configuration property * such as javax.persistence.sharedCache.mode determined the type of the instance being cachable. *
    * For example, a specific policy will never be active for when javax.persistence.sharedCache.mode * is set to NONE. *
    * Distribution Policies are configurable. So a specific policy can be configured as *
     *  <property name="openjpa.CacheDistributionPolicy" value="com.acme.FooPolicy(param1='xyz',param2=true)"/>
     * 
    * where com.acme.FooPolicy is an implementation of this interface and defines bean style setter and * getter methods for String property param1 and boolean property param2. * * @author Pinaki Poddar * * @since 2.0.0 * */ public interface CacheDistributionPolicy extends Configurable { /** * Selects the name of the cache where the given managed proxy object state be cached. * * @param sm the managed proxy object to be cached. The actual managed instance can be accessed from the proxy * instance simply as sm.getManagedInstance(). * * @param context the context of invocation. No specific semantics is attributed currently. Can be null. * * @return name of the cache or null, implying that that the instance should not be cached. */ String selectCache(OpenJPAStateManager sm, Object context); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/TypeBasedCacheDistributionPolicy.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/TypeBasedCacheDistribut0000644000000000000000000000720712133327272030336 0ustar /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.openjpa.datacache; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.meta.ClassMetaData; import serp.util.Strings; /** * A cache distribution policy based on the type of the managed objects. *
    * The policy is configured by specifying list of included or excluded types. * The lists are specified as fully-qualified persistence class names separated by semicolon. *
    * The policy checks for the given instance by its type whether the class name appears in * exclusion or inclusion lists. If the class name appears in exclusion list then the * instance is not cached. Otherwise, if an inclusion list exists and the class name appears in inclusion list * or @DataCache annotation is specified on the class meta data, then the instance is cached. * * @author Pinaki Poddar * */ public class TypeBasedCacheDistributionPolicy extends DefaultCacheDistributionPolicy implements CacheDistributionPolicy { private Set _excludedTypes; private Set _includedTypes; /** * Gets the excluded types, if configured. */ public Set getExcludedTypes() { return _excludedTypes; } /** * Sets excluded types from a semicolon separated list of type names. */ public void setExcludedTypes(String types) { _excludedTypes = parseNames(types); } /** * Gets the included types, if configured. */ public Set getIncludedTypes() { return _includedTypes; } /** * Sets included types from a semicolon separated list of type names. */ public void setIncludedTypes(String types) { _includedTypes = parseNames(types); } private Set parseNames(String types) { if (StringUtils.isEmpty(types)) return Collections.emptySet(); String[] names = Strings.split(types, ";", 0); Set set = new HashSet(); set.addAll(Arrays.asList(names)); return Collections.unmodifiableSet(set); } @Override public String selectCache(OpenJPAStateManager sm, Object context) { ClassMetaData meta = sm.getMetaData(); String className = meta.getDescribedType().getName(); if (_excludedTypes != null && _excludedTypes.contains(className)) { return null; } if (_includedTypes != null && !_includedTypes.isEmpty()) { if (_includedTypes.contains(className)) return meta.getDataCacheName(); return (meta.getDataCacheEnabled()) ? meta.getDataCacheName() : null; } else { return super.selectCache(sm, context); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/PartitionedDataCache.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/PartitionedDataCache.ja0000644000000000000000000001726112133327272030232 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.lang.reflect.Array; import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.openjpa.lib.conf.PluginListValue; import org.apache.openjpa.lib.conf.Value; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * A partitioned data cache maintains a set of partitions that are DataCache themselves. * Each of the partitioned DataCaches can be individually configured. * However, all partitions must be of the same type. By default, this cache uses * {@linkplain ConcurrentDataCache} as its partitions. *
    * This cache can be configured as a plug-in as follows: *
    * <property name='openjpa.DataCache" * value="partitioned(name=X, PartitionType=concurrent,Partitions='(name=a,cacheSize=100), * (name=b,cacheSize=200)') *
    * Notice that the individual partition properties are enclosed parentheses, separated by comma * and finally the whole property string is enclosed in single quote. * Each partition must have a non-empty name that are unique among the partitions. * The {@linkplain CacheDistributionPolicy policy} can return * the name of a partition to distribute the managed instances to be cached in respective partition. * * The above configuration will configure a partitioned cache named X with two partitions named * a and b with cache size 100 and 200 respectively. * Besides the two partitions, this cache instance itself can store data and referred by its own name * (X in the above example). *
    * * @author Pinaki Poddar * * @since 2.0.0 */ @SuppressWarnings("serial") public class PartitionedDataCache extends ConcurrentDataCache { private static final Localizer _loc = Localizer.forPackage(PartitionedDataCache.class); private Class _type = ConcurrentDataCache.class; private final List _partProperties = new ArrayList(); private final Map _partitions = new HashMap(); @Override public void initialize(DataCacheManager mgr) { super.initialize(mgr); for(DataCache part : _partitions.values()){ part.initialize(mgr); } } /** * Sets the type of the partitions. * Each partition is a DataCache itself. * * @param type the name of the type that implements {@linkplain DataCache} interface. * Aliases such as "concurrent" is also recognized. * * @throws Exception if the given type is not resolvable to a loadable type. */ public void setPartitionType(String type) throws Exception { Value value = conf.getValue("DataCache"); ClassLoader ctxLoader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction()); ClassLoader loader = conf.getClassResolverInstance().getClassLoader(null, ctxLoader); _type = (Class) AccessController.doPrivileged( J2DoPrivHelper.getForNameAction(value.unalias(type), true, loader)); } /** * Set partitions from a String configuration. * * @param parts a String of the form (p1, p2, p3) where p1, p2 etc. itself are plug-in strings * for individual Data Cache configuration. */ public void setPartitions(String parts) { _partProperties.clear(); parsePartitionProperties(parts); PluginListValue partitions = new PluginListValue("partitions"); String[] types = (String[])Array.newInstance(String.class, _partProperties.size()); Arrays.fill(types, _type.getName()); partitions.setClassNames(types); partitions.setProperties(_partProperties.toArray(new String[_partProperties.size()])); DataCache[] array = (DataCache[])partitions.instantiate(_type, conf); for (DataCache part : array) { if (part.getName() == null) throw new UserException(_loc.get("partition-cache-null-partition", parts)); if (_partitions.containsKey(part.getName())) throw new UserException(_loc.get("partition-cache-duplicate-partition", part.getName(), parts)); if (part.getName().equals(DataCache.NAME_DEFAULT)) throw new UserException(_loc.get("partition-cache-default-partition", part.getName(), parts)); _partitions.put(part.getName(), part); } } /** * Returns the individual partition configuration properties. */ public List getPartitions() { return _partProperties; } public DataCache getPartition(String name, boolean create) { return _partitions.get(name); } /** * Gets the name of the configured partitions. */ public Set getPartitionNames() { return _partitions.keySet(); } /** * Always returns true. */ public final boolean isPartitioned() { return !_partitions.isEmpty(); } public void endConfiguration() { if (!isPartitioned()) conf.getConfigurationLog().warn(_loc.get("partition-cache-no-config")); } /** * Parses property string of the form (p1),(p2),(p3) to produce a list of * p1, p2 and p3. The component strings * p1 etc. must be enclosed in parentheses and separated by comma. * plug-in string to produce a list of * * @param properties property string of the form (p1),(p2),(p3) */ private void parsePartitionProperties(String full) { String properties = new String(full); while (true) { if (properties == null) break; properties = properties.trim(); if (properties.length() == 0) break; if (properties.startsWith(",")) { properties = properties.substring(1); } else if (!_partProperties.isEmpty()) { throw new UserException(_loc.get("partition-cache-parse-error-comma", full, properties)); } if (properties.startsWith("(") && properties.endsWith(")")) { int i = properties.indexOf(")"); String p = properties.substring(1,i); // exclude the end parentheses _partProperties.add(p); if (i < properties.length()-1) { properties = properties.substring(i+1); } else { break; } } else { throw new UserException(_loc.get("partition-cache-parse-error-paren", full, properties)); } } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.j0000644000000000000000000010203712133327272030172 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.openjpa.enhance.PCDataGenerator; import org.apache.openjpa.kernel.DataCacheRetrieveMode; import org.apache.openjpa.kernel.DataCacheStoreMode; import org.apache.openjpa.kernel.DelegatingStoreManager; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.LockLevels; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.PCState; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.kernel.StoreManager; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.OpenJPAId; import org.apache.openjpa.util.OptimisticException; /** * StoreManager proxy that delegates to a data cache when possible. * * @author Patrick Linskey * @nojavadoc */ public class DataCacheStoreManager extends DelegatingStoreManager { // all the state managers changed in this transaction private Collection _inserts = null; private Map _updates = null; private Collection _deletes = null; // the owning context private StoreContext _ctx = null; private DataCacheManager _mgr = null; // pc data generator private PCDataGenerator _gen = null; /** * Constructor. * * @param sm the store manager to delegate to */ public DataCacheStoreManager(StoreManager sm) { super(sm); } public void setContext(StoreContext ctx) { _ctx = ctx; _mgr = ctx.getConfiguration().getDataCacheManagerInstance(); _gen = _mgr.getPCDataGenerator(); super.setContext(ctx); } public void begin() { super.begin(); } public void commit() { try { super.commit(); updateCaches(); } finally { _inserts = null; _updates = null; _deletes = null; } } public void rollback() { try { super.rollback(); } finally { _inserts = null; _updates = null; _deletes = null; } } /** * Evict all members of the given classes. */ private void evictTypes(Collection> classes) { if (classes.isEmpty()) return; MetaDataRepository mdr = _ctx.getConfiguration().getMetaDataRepositoryInstance(); ClassLoader loader = _ctx.getClassLoader(); DataCache cache; for (Class cls : classes) { cache = mdr.getMetaData(cls, loader, false).getDataCache(); if (cache != null && cache.getEvictOnBulkUpdate()) cache.removeAll(cls, false); } } /** * Update all caches with the committed inserts, updates, and deletes. */ private void updateCaches() { if(_ctx.getFetchConfiguration().getCacheStoreMode() != DataCacheStoreMode.BYPASS ) { // map each data cache to the modifications we need to perform Map modMap = null; if ((_ctx.getPopulateDataCache() && _inserts != null) || _updates != null || _deletes != null) modMap = new HashMap(); Modifications mods; DataCachePCData data; DataCache cache; // create pc datas for inserts if (_ctx.getPopulateDataCache() && _inserts != null) { for (OpenJPAStateManager sm : _inserts) { cache = _mgr.selectCache(sm); if (cache == null) continue; mods = getModifications(modMap, cache); data = newPCData(sm, cache); data.store(sm); mods.additions.add(new PCDataHolder(data, sm)); CacheStatistics stats = cache.getStatistics(); if (stats.isEnabled()) { ((CacheStatisticsSPI)stats).newPut(data.getType()); } } } // update pcdatas for updates if (_updates != null) { BitSet fields; OpenJPAStateManager sm; for (Map.Entry entry : _updates.entrySet()) { sm = entry.getKey(); fields = entry.getValue(); cache = _mgr.selectCache(sm); if (cache == null) { continue; } // it's ok not to clone the object that we get from the cache, // since we're inside the commit() method, so any modifications // to the underlying cache are valid. If the commit had not // already succeeded, then we'd want to clone the retrieved // object. data = cache.get(sm.getObjectId()); mods = getModifications(modMap, cache); // data should always be non-null, since the object is // dirty, but maybe it got dropped from the cache in the // interim if (data == null) { data = newPCData(sm, cache); data.store(sm); mods.newUpdates.add(new PCDataHolder(data, sm)); } else { data.store(sm, fields); mods.existingUpdates.add(new PCDataHolder(data, sm)); } CacheStatistics stats = cache.getStatistics(); if (stats.isEnabled()) { ((CacheStatisticsSPI)stats).newPut(data.getType()); } } } // remove pcdatas for deletes if (_deletes != null) { for (OpenJPAStateManager sm : _deletes) { cache = _mgr.selectCache(sm); if (cache == null) continue; mods = getModifications(modMap, cache); mods.deletes.add(sm.getObjectId()); } } // notify the caches of the changes if (modMap != null) { for (Map.Entry entry : modMap.entrySet()) { cache = entry.getKey(); mods = entry.getValue(); // make sure we're not caching old versions cache.writeLock(); try { cache.commit( transformToVersionSafePCDatas(cache, mods.additions), transformToVersionSafePCDatas(cache, mods.newUpdates), transformToVersionSafePCDatas(cache, mods.existingUpdates), mods.deletes); } finally { cache.writeUnlock(); } } } // if we were in largeTransaction mode, then we have recorded // the classes of updated/deleted objects and these now need to be // evicted if (_ctx.isTrackChangesByType()) { evictTypes(_ctx.getDeletedTypes()); evictTypes(_ctx.getUpdatedTypes()); } } } /** * Transforms a collection of {@link PCDataHolder}s that might contain * stale instances into a collection of up-to-date {@link DataCachePCData}s. */ private List transformToVersionSafePCDatas(DataCache cache, List holders) { List transformed = new ArrayList(holders.size()); Map ids = new HashMap(holders.size()); // this list could be removed if DataCache.getAll() took a Collection List idList = new ArrayList(holders.size()); int i = 0; for (PCDataHolder holder : holders) { ids.put(holder.sm.getObjectId(), i++); idList.add(holder.sm.getObjectId()); } Map pcdatas = cache.getAll(idList); for (Entry entry : pcdatas.entrySet()) { Integer index = ids.get(entry.getKey()); DataCachePCData oldpc = entry.getValue(); PCDataHolder holder = holders.get(index); if (oldpc != null && compareVersion(holder.sm, holder.sm.getVersion(), oldpc.getVersion()) == VERSION_EARLIER) continue; else transformed.add(holder.pcdata); } return transformed; } /** * Return a {@link Modifications} instance to track modifications * to the given cache, creating and caching the instance if it does * not already exist in the given map. */ private static Modifications getModifications(Map modMap, DataCache cache) { Modifications mods = (Modifications) modMap.get(cache); if (mods == null) { mods = new Modifications(); modMap.put(cache, mods); } return mods; } public boolean exists(OpenJPAStateManager sm, Object edata) { DataCache cache = _mgr.selectCache(sm); CacheStatistics stats = (cache == null) ? null : cache.getStatistics(); if (cache != null && !isLocking(null) && cache.contains(sm.getObjectId())){ if (stats != null && stats.isEnabled()) { // delay this call ONLY if stats collection is enabled Class cls = sm.getMetaData().getDescribedType(); ((CacheStatisticsSPI)stats).newGet(cls, false); } return true; } // If isLocking(null)==true && cache.contains(..) == true... probably shouldn't count? if (stats != null && stats.isEnabled()) { // delay this call ONLY if stats collection is enabled Class cls = sm.getMetaData().getDescribedType(); ((CacheStatisticsSPI)stats).newGet(cls, false); } return super.exists(sm, edata); } public boolean isCached(List oids, BitSet edata) { // If using partitioned cache, we were and still are broke. DataCache cache = _mgr.getSystemDataCache(); if (cache != null && !isLocking(null)) { // BitSet size is not consistent. for(int i = 0; i < oids.size(); i++) { Object oid = oids.get(i); // Only check the cache if we haven't found the current oid. if (edata.get(i) == false && cache.contains(oid)) { edata.set(i); } } if (edata.cardinality() == oids.size()){ return true; } } return super.isCached(oids, edata); } public boolean syncVersion(OpenJPAStateManager sm, Object edata) { DataCache cache = _mgr.selectCache(sm); FetchConfiguration fc = sm.getContext().getFetchConfiguration(); CacheStatistics stats = (cache == null) ? null : cache.getStatistics(); if (cache == null || sm.isEmbedded() || fc.getCacheRetrieveMode() == DataCacheRetrieveMode.BYPASS) { if (stats != null && stats.isEnabled()) { ((CacheStatisticsSPI) stats).newGet(sm.getMetaData().getDescribedType(), false); } return super.syncVersion(sm, edata); } DataCachePCData data; Object version = null; data = cache.get(sm.getObjectId()); if (!isLocking(null) && data != null) version = data.getVersion(); // if we have a cached version update from there if (version != null) { if (stats != null && stats.isEnabled()) { ((CacheStatisticsSPI)stats).newGet(data.getType(), true); } if (!version.equals(sm.getVersion())) { sm.setVersion(version); return false; } return true; } if(stats.isEnabled()){ Class cls = (data == null) ? sm.getMetaData().getDescribedType() : data.getType(); ((CacheStatisticsSPI) stats).newGet(cls, false); } // use data store version return super.syncVersion(sm, edata); } public boolean initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch, Object edata) { DataCache cache = _mgr.selectCache(sm); if (cache == null) { return super.initialize(sm, state, fetch, edata); } DataCachePCData data = cache.get(sm.getObjectId()); CacheStatistics stats = cache.getStatistics(); boolean fromDatabase = false; boolean alreadyCached = data != null; if (sm.isEmbedded() || fetch.getCacheRetrieveMode() == DataCacheRetrieveMode.BYPASS || fetch.getCacheStoreMode() == DataCacheStoreMode.REFRESH) { // stats -- Skipped reading from the cache, noop fromDatabase = super.initialize(sm, state, fetch, edata); } else { if (alreadyCached && !isLocking(fetch)) { if (stats.isEnabled()) { ((CacheStatisticsSPI)stats).newGet(data.getType(), true); } sm.initialize(data.getType(), state); data.load(sm, fetch, edata); } else { if (!alreadyCached) { if (stats.isEnabled()) { // Get the classname from MetaData... but this won't be right in every case. ((CacheStatisticsSPI)stats).newGet(sm.getMetaData().getDescribedType(), false); } } fromDatabase = super.initialize(sm, state, fetch, edata); } } // update cache if the result came from the database and configured to use or refresh the cache. boolean updateCache = fromDatabase && _ctx.getPopulateDataCache() && ((fetch.getCacheStoreMode() == DataCacheStoreMode.USE && !alreadyCached) || (fetch.getCacheStoreMode() == DataCacheStoreMode.REFRESH)); if (updateCache) { // It is possible that the "cacheability" of the provided SM changed after hitting the DB. This can happen // when we are operating against an Entity that is in some sort of inheritance structure. cache = _mgr.selectCache(sm); if (cache != null) { cacheStateManager(cache, sm, data); if (stats.isEnabled()) { ((CacheStatisticsSPI) stats).newPut(sm.getMetaData().getDescribedType()); } } } return fromDatabase || alreadyCached; } private void cacheStateManager(DataCache cache, OpenJPAStateManager sm, DataCachePCData data) { if (sm.isFlushed()) { return; } // make sure that we're not trying to cache an old version cache.writeLock(); try { if (data != null && compareVersion(sm, sm.getVersion(), data.getVersion()) == VERSION_EARLIER) { return; } // cache newly loaded info. It is safe to cache data frorm // initialize() because this method is only called upon // initial load of the data. boolean isNew = data == null; if (isNew) { data = newPCData(sm, cache); } data.store(sm); if (isNew) { cache.put(data); } else { cache.update(data); } } finally { cache.writeUnlock(); } } public boolean load(OpenJPAStateManager sm, BitSet fields, FetchConfiguration fetch, int lockLevel, Object edata) { DataCache cache = _mgr.selectCache(sm); boolean found = false; if (cache == null || sm.isEmbedded() || bypass(fetch, StoreManager.FORCE_LOAD_NONE)) { found = super.load(sm, fields, fetch, lockLevel, edata); updateDataCache(found, sm, fetch); return found; } CacheStatistics stats = cache.getStatistics(); DataCachePCData data = cache.get(sm.getObjectId()); if (lockLevel == LockLevels.LOCK_NONE && !isLocking(fetch) && data != null) data.load(sm, fields, fetch, edata); if (fields.length() == 0){ if (stats.isEnabled()) { Class cls = (data == null) ? sm.getMetaData().getDescribedType() : data.getType(); ((CacheStatisticsSPI)stats).newGet(cls, true); } return true; } // load from store manager; clone the set of still-unloaded fields // so that if the store manager decides to modify it it won't affect us found = super.load(sm, (BitSet) fields.clone(), fetch, lockLevel, edata); // Get new instance of cache after DB load since it may have changed updateDataCache(found, sm, fetch); return found; } /** * Updates or inserts and item into the data cache. If storeMode=USE and not in the cache, * the item is inserted. If storeMode=REFRESH the item is inserted, updated, or if found=false, * removed from the cache. * @param found whether the entity was found by the store manager * @param sm the state manager * @param fetch fetch configuration */ private void updateDataCache(boolean found, OpenJPAStateManager sm, FetchConfiguration fetch) { if (!_ctx.getPopulateDataCache() || sm == null || fetch.getCacheStoreMode() == DataCacheStoreMode.BYPASS) { return; } DataCache cache = _mgr.selectCache(sm); if (cache == null) { return; } DataCachePCData data = cache.get(sm.getObjectId()); boolean alreadyCached = data != null; if ((fetch.getCacheStoreMode() == DataCacheStoreMode.USE && !alreadyCached) || fetch.getCacheStoreMode() == DataCacheStoreMode.REFRESH) { // If not found in the DB and the item is in the cache, and not locking remove the item if (!found && data != null && !isLocking(fetch)) { cache.remove(sm.getObjectId()); return; } // Update or insert the item into the cache if (found) { cacheStateManager(cache, sm, data); CacheStatistics stats = cache.getStatistics(); if (stats.isEnabled()) { ((CacheStatisticsSPI) stats).newPut(sm.getMetaData().getDescribedType()); } } } } public Collection loadAll(Collection sms, PCState state, int load, FetchConfiguration fetch, Object edata) { if (bypass(fetch, load)) { return super.loadAll(sms, state, load, fetch, edata); } Map unloaded = null; List smList = null; Map> caches = new HashMap>(); DataCache cache; DataCachePCData data; BitSet fields; for (OpenJPAStateManager sm : sms) { cache = _mgr.selectCache(sm); if (cache == null || sm.isEmbedded()) { unloaded = addUnloaded(sm, null, unloaded); continue; } if (sm.getManagedInstance() == null || load != FORCE_LOAD_NONE || sm.getPCState() == PCState.HOLLOW) { smList = caches.get(cache); if (smList == null) { smList = new ArrayList(); caches.put(cache, smList); } smList.add(sm); } else if (!cache.contains(sm.getObjectId())) unloaded = addUnloaded(sm, null, unloaded); } for(Entry> entry : caches.entrySet()){ cache = entry.getKey(); smList = entry.getValue(); List oidList = new ArrayList(smList.size()); for (OpenJPAStateManager sm : smList) { oidList.add((OpenJPAId) sm.getObjectId()); } Map dataMap = cache.getAll(oidList); for (OpenJPAStateManager sm : smList) { data = dataMap.get(sm.getObjectId()); CacheStatistics stats = cache.getStatistics(); if (sm.getManagedInstance() == null) { if (data != null) { //### the 'data.type' access here probably needs //### to be addressed for bug 511 if (stats.isEnabled()) { ((CacheStatisticsSPI) stats).newGet(data.getType(), true); } sm.initialize(data.getType(), state); data.load(sm, fetch, edata); } else { unloaded = addUnloaded(sm, null, unloaded); if (stats.isEnabled()) { ((CacheStatisticsSPI)stats).newGet(sm.getMetaData().getDescribedType(), false); } } } else if (load != FORCE_LOAD_NONE || sm.getPCState() == PCState.HOLLOW) { data = cache.get(sm.getObjectId()); if (data != null) { // load unloaded fields fields = sm.getUnloaded(fetch); data.load(sm, fields, fetch, edata); if (fields.length() > 0){ unloaded = addUnloaded(sm, fields, unloaded); if (stats.isEnabled()) { ((CacheStatisticsSPI)stats).newGet(data.getType(), false); } }else{ if (stats.isEnabled()) { ((CacheStatisticsSPI)stats).newGet(data.getType(), true); } } } else{ unloaded = addUnloaded(sm, null, unloaded); if (stats.isEnabled()) { ((CacheStatisticsSPI)stats).newGet(sm.getMetaData().getDescribedType(), false); } } } } } if (unloaded == null) return Collections.emptyList(); // load with delegate Collection failed = super.loadAll(unloaded.keySet(), state, load, fetch, edata); if (!_ctx.getPopulateDataCache()) return failed; // for each loaded instance, merge loaded state into cached data boolean isNew; for(Map.Entry entry : unloaded.entrySet()) { OpenJPAStateManager sm = entry.getKey(); fields = entry.getValue(); cache = _mgr.selectCache(sm); if (cache == null || sm.isEmbedded() || (failed != null && failed.contains(sm.getId()))) continue; // make sure that we're not trying to cache an old version cache.writeLock(); try { data = cache.get(sm.getObjectId()); if (data != null && compareVersion(sm, sm.getVersion(), data.getVersion()) == VERSION_EARLIER) continue; isNew = data == null; if (isNew) data = newPCData(sm, cache); if (fields == null) data.store(sm); else data.store(sm, fields); if (isNew) cache.put(data); else cache.update(data); CacheStatistics stats = cache.getStatistics(); if (stats.isEnabled()) { ((CacheStatisticsSPI)stats).newPut(data.getType()); } } finally { cache.writeUnlock(); } } return failed; } /** * Helper method to add an unloaded instance to the given map. */ private static Map addUnloaded(OpenJPAStateManager sm, BitSet fields, Map unloaded) { if (unloaded == null) unloaded = new HashMap(); unloaded.put(sm, fields); return unloaded; } public Collection flush(Collection states) { Collection exceps = super.flush(states); // if there were errors evict bad instances and don't record changes if (!exceps.isEmpty()) { for (Exception e : exceps) { if (e instanceof OptimisticException) notifyOptimisticLockFailure((OptimisticException) e); } return exceps; } // if large transaction mode don't record individual changes if (_ctx.isTrackChangesByType()) return exceps; for (OpenJPAStateManager sm : states) { if (sm.getPCState() == PCState.PNEW && !sm.isFlushed()) { if (_inserts == null) { _inserts = new ArrayList(); } _inserts.add(sm); // may have been re-persisted if (_deletes != null) { _deletes.remove(sm); } } else if (_inserts != null && (sm.getPCState() == PCState.PNEWDELETED || sm.getPCState() == PCState.PNEWFLUSHEDDELETED)) { _inserts.remove(sm); } else if (sm.getPCState() == PCState.PDIRTY) { if (_updates == null) { _updates = new HashMap(); } _updates.put(sm, sm.getDirty()); } else if (sm.getPCState() == PCState.PDELETED) { if (_deletes == null) { _deletes = new HashSet(); } _deletes.add(sm); } } return Collections.emptyList(); } /** * Fire local staleness detection events from the cache the OID (if * available) that resulted in an optimistic lock exception iff the * version information in the cache matches the version information * in the state manager for the failed instance. This means that we * will evict data from the cache for records that should have * successfully committed according to the data cache but * did not. The only predictable reason that could cause this behavior * is a concurrent out-of-band modification to the database that was not * communicated to the cache. This logic makes OpenJPA's data cache * somewhat tolerant of such behavior, in that the cache will be cleaned * up as failures occur. */ private void notifyOptimisticLockFailure(OptimisticException e) { Object o = e.getFailedObject(); OpenJPAStateManager sm = _ctx.getStateManager(o); if (sm == null) return; Object oid = sm.getId(); boolean remove; // this logic could be more efficient -- we could aggregate // all the cache->oid changes, and then use DataCache.removeAll() // and less write locks to do the mutation. DataCache cache = _mgr.selectCache(sm); if (cache == null) return; cache.writeLock(); try { DataCachePCData data = cache.get(oid); if (data == null) return; switch (compareVersion(sm, sm.getVersion(), data.getVersion())) { case StoreManager.VERSION_LATER: case StoreManager.VERSION_SAME: // This tx's current version is later than or the same as // the data cache version. In this case, the commit should // have succeeded from the standpoint of the cache. Remove // the instance from cache in the hopes that the cache is // out of sync. remove = true; break; case StoreManager.VERSION_EARLIER: // This tx's current version is earlier than the data // cache version. This is a normal optimistic lock failure. // Do not clean up the cache; it probably already has the // right values, and if not, it'll get cleaned up by a tx // that fails in one of the other case statements. remove = false; break; case StoreManager.VERSION_DIFFERENT: // The version strategy for the failed object does not // store enough information to optimize for expected // failures. Clean up the cache. remove = true; break; default: // Unexpected return value. Remove to be future-proof. remove = true; break; } if (remove) // remove directly instead of via the RemoteCommitListener // since we have a write lock here already, so this is more // efficient than read-locking and then write-locking later. cache.remove(sm.getId()); } finally { cache.writeUnlock(); } // fire off a remote commit stalenesss detection event. _ctx.getConfiguration().getRemoteCommitEventManager() .fireLocalStaleNotification(oid); } /** * Create a new cacheable instance for the given state manager. */ private DataCachePCData newPCData(OpenJPAStateManager sm, DataCache cache) { ClassMetaData meta = sm.getMetaData(); if (_gen != null) return (DataCachePCData) _gen.generatePCData(sm.getObjectId(), meta); return new DataCachePCDataImpl(sm.fetchObjectId(), meta, cache.getName()); } /** * Affirms if a load operation must bypass the L2 cache. * If lock is active, always bypass. * */ boolean bypass(FetchConfiguration fetch, int load) { // Order of checks are important if (isLocking(fetch)) return true; if (_ctx.getConfiguration().getRefreshFromDataCache()) return false; if (fetch.getCacheRetrieveMode() == DataCacheRetrieveMode.BYPASS) return true; if (load == StoreManager.FORCE_LOAD_REFRESH) return true; return false; } /** * Return whether the context is locking loaded data. */ private boolean isLocking(FetchConfiguration fetch) { if (fetch == null) fetch = _ctx.getFetchConfiguration(); return fetch.getReadLockLevel() > LockLevels.LOCK_NONE; } /** * Structure used during the commit process to track cache modifications. */ private static class Modifications { public final List additions = new ArrayList(); public final List newUpdates = new ArrayList(); public final List existingUpdates = new ArrayList(); public final List deletes = new ArrayList(); } /** * Utility structure holds the tuple of cacheable instance and its corresponding state manager. * */ private static class PCDataHolder { public final DataCachePCData pcdata; public final OpenJPAStateManager sm; public PCDataHolder(DataCachePCData pcdata, OpenJPAStateManager sm) { this.pcdata = pcdata; this.sm = sm; } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/ConcurrentDataCache.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/ConcurrentDataCache.jav0000644000000000000000000001275112133327272030257 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.List; import org.apache.openjpa.event.RemoteCommitListener; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.CacheMap; /** * A {@link DataCache} implementation that is optimized for concurrent * access. When the cache fills up, values to remove from cache are chosen * randomly. Due to race conditions, it is possible that a get call might not * return a cached instance if that instance is being transferred between * internal datastructures. * * @since 0.4.0 */ public class ConcurrentDataCache extends AbstractDataCache implements RemoteCommitListener { private static final Localizer _loc = Localizer.forPackage (ConcurrentDataCache.class); private CacheMap _cache; private int _cacheSize = Integer.MIN_VALUE; private int _softRefs = Integer.MIN_VALUE; protected boolean _lru = false; /** * Returns the underlying {@link CacheMap} that this cache is using. * This is not an unmodifiable view on the map, so care should be taken * with this reference. Implementations should probably not modify the * contents of the cache, but should only use this reference to * obtain cache metrics. */ public CacheMap getCacheMap() { return _cache; } /** * Sets the maximum number of unpinned objects to keep hard * references to. If the map contains more unpinned objects than * size, then this method will result in the cache * flushing old values. */ public void setCacheSize(int size) { _cacheSize = size; } /** * Returns the maximum number of unpinned objects to keep hard * references to. */ public int getCacheSize() { return _cache.getCacheSize(); } /** * Sets the maximum number of unpinned objects to keep soft * references to. If the map contains more soft references than * size, then this method will result in the cache * flushing values. */ public void setSoftReferenceSize(int size) { _softRefs = size; } /** * Returns the maximum number of unpinned objects to keep soft * references to. Defaults to -1. */ public int getSoftReferenceSize() { return _cache.getSoftReferenceSize(); } public void initialize(DataCacheManager mgr) { super.initialize(mgr); conf.getRemoteCommitEventManager().addInternalListener(this); // Wait to instantiate _cache so that we know the proper value of _cache _cache = newCacheMap(); if (_cacheSize != Integer.MIN_VALUE) { _cache.setCacheSize(_cacheSize); } if (_softRefs != Integer.MIN_VALUE) { _cache.setSoftReferenceSize(_softRefs); } } public void unpinAll(Class cls, boolean subs) { if (log.isWarnEnabled()) log.warn(_loc.get("cache-class-unpin-all", getName())); unpinAll(_cache.getPinnedKeys()); } public void writeLock() { _cache.writeLock(); } public void writeUnlock() { _cache.writeUnlock(); } /** * Return the map to use as an internal cache; entry expirations must * invoke {@link AbstractDataCache#keyRemoved}. */ protected CacheMap newCacheMap() { CacheMap res = new CacheMap(_lru) { protected void entryRemoved(Object key, Object value, boolean expired) { keyRemoved(key, expired); } }; return res; } protected DataCachePCData getInternal(Object key) { return (DataCachePCData) _cache.get(key); } protected DataCachePCData putInternal(Object key, DataCachePCData pc) { return (DataCachePCData) _cache.put(key, pc); } protected DataCachePCData removeInternal(Object key) { return (DataCachePCData) _cache.remove(key); } protected void removeAllInternal(Class cls, boolean subs) { // The performance in this area can be improved upon, however it seems // unlikely that this method will be called in a performance intensive // environment. In any event applications can revert to the old behavior // by simply calling removeAll(). _cache.clear(); } protected void clearInternal() { _cache.clear(); } protected boolean pinInternal(Object key) { return _cache.pin(key); } protected boolean unpinInternal(Object key) { return _cache.unpin (key); } protected boolean recacheUpdates() { return true; } public void setLru(boolean l) { _lru = l; } public boolean getLru() { return _lru; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingDataCache.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingDataCache.jav0000644000000000000000000002407712133327272030204 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.BitSet; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.ObjectUtils; import org.apache.openjpa.util.RuntimeExceptionTranslator; /** * Delegating data cache that can also perform exception translation for * use in facades. This cache allows its delegate to be null, in which * case it returns default values for all operations. * * @author Abe White * @nojavadoc */ public class DelegatingDataCache implements DataCache { private static final BitSet EMPTY_BITSET = new BitSet(0); private final DataCache _cache; private final DelegatingDataCache _del; private final RuntimeExceptionTranslator _trans; /** * Constructor. Supply delegate. */ public DelegatingDataCache(DataCache cache) { this(cache, null); } public DelegatingDataCache(DataCache cache, RuntimeExceptionTranslator trans) { _cache = cache; _trans = trans; if (cache instanceof DelegatingDataCache) _del = (DelegatingDataCache) _cache; else _del = null; } /** * Return the direct delegate. */ public DataCache getDelegate() { return _cache; } /** * Return the native delegate. */ public DataCache getInnermostDelegate() { return (_del == null) ? _cache : _del.getInnermostDelegate(); } public int hashCode() { if (_cache == null) return super.hashCode(); return getInnermostDelegate().hashCode(); } public boolean equals(Object other) { if (other == this) return true; if (other instanceof DelegatingDataCache) other = ((DelegatingDataCache) other).getInnermostDelegate(); return ObjectUtils.equals(getInnermostDelegate(), other); } /** * Translate the OpenJPA exception. */ protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } public String getName() { if (_cache == null) return null; try { return _cache.getName(); } catch (RuntimeException re) { throw translate(re); } } public void setName(String name) { if (_cache == null) return; try { _cache.setName(name); } catch (RuntimeException re) { throw translate(re); } } public void initialize(DataCacheManager manager) { if (_cache == null) return; try { _cache.initialize(manager); } catch (RuntimeException re) { throw translate(re); } } public void commit(Collection additions, Collection newUpdates, Collection existingUpdates, Collection deletes) { if (_cache == null) return; try { _cache.commit(additions, newUpdates, existingUpdates, deletes); } catch (RuntimeException re) { throw translate(re); } } public boolean contains(Object oid) { if (_cache == null) return false; try { return _cache.contains(oid); } catch (RuntimeException re) { throw translate(re); } } public BitSet containsAll(Collection oids) { if (_cache == null) return EMPTY_BITSET; try { return _cache.containsAll(oids); } catch (RuntimeException re) { throw translate(re); } } public DataCachePCData get(Object oid) { if (_cache == null) return null; try { return _cache.get(oid); } catch (RuntimeException re) { throw translate(re); } } public DataCachePCData put(DataCachePCData value) { if (_cache == null) return null; try { return _cache.put(value); } catch (RuntimeException re) { throw translate(re); } } public void update(DataCachePCData value) { if (_cache == null) return; try { _cache.update(value); } catch (RuntimeException re) { throw translate(re); } } public DataCachePCData remove(Object oid) { if (_cache == null) return null; try { return _cache.remove(oid); } catch (RuntimeException re) { throw translate(re); } } public BitSet removeAll(Collection oids) { if (_cache == null) return EMPTY_BITSET; try { return _cache.removeAll(oids); } catch (RuntimeException re) { throw translate(re); } } public void removeAll(Class cls, boolean subclasses) { if (_cache == null) return; try { _cache.removeAll(cls, subclasses); } catch (RuntimeException re) { throw translate(re); } } public void clear() { if (_cache == null) return; try { _cache.clear(); } catch (RuntimeException re) { throw translate(re); } } public boolean pin(Object oid) { if (_cache == null) return false; try { return _cache.pin(oid); } catch (RuntimeException re) { throw translate(re); } } public BitSet pinAll(Collection oids) { if (_cache == null) return EMPTY_BITSET; try { return _cache.pinAll(oids); } catch (RuntimeException re) { throw translate(re); } } public void pinAll(Class cls, boolean subs) { if (_cache == null) return; try { _cache.pinAll(cls, subs); } catch (RuntimeException re) { throw translate(re); } } public boolean unpin(Object oid) { if (_cache == null) return false; try { return _cache.unpin(oid); } catch (RuntimeException re) { throw translate(re); } } public BitSet unpinAll(Collection oids) { if (_cache == null) return EMPTY_BITSET; try { return _cache.unpinAll(oids); } catch (RuntimeException re) { throw translate(re); } } public void unpinAll(Class cls, boolean subs) { if (_cache == null) return; try { _cache.unpinAll(cls, subs); } catch (RuntimeException re) { throw translate(re); } } public void writeLock() { if (_cache == null) return; try { _cache.writeLock(); } catch (RuntimeException re) { throw translate(re); } } public void writeUnlock() { if (_cache == null) return; try { _cache.writeUnlock(); } catch (RuntimeException re) { throw translate(re); } } public void addExpirationListener(ExpirationListener listen) { if (_cache == null) return; try { _cache.addExpirationListener(listen); } catch (RuntimeException re) { throw translate(re); } } public boolean removeExpirationListener(ExpirationListener listen) { if (_cache == null) return false; try { return _cache.removeExpirationListener(listen); } catch (RuntimeException re) { throw translate(re); } } public void close() { if (_cache == null) return; try { _cache.close(); } catch (RuntimeException re) { throw translate(re); } } public Map getAll(List keys) { if (_cache == null) return null; try { return _cache.getAll(keys); } catch (RuntimeException re) { throw translate(re); } } public CacheStatistics getStatistics() { return (_cache == null) ? null : _cache.getStatistics(); } public DataCache getPartition(String name, boolean create) { if (_cache == null) return null; try { return _cache.getPartition(name, create); } catch (RuntimeException re) { throw translate(re); } } public Set getPartitionNames() { if (_cache == null) return null; try { return _cache.getPartitionNames(); } catch (RuntimeException re) { throw translate(re); } } public boolean isPartitioned() { if (_cache == null) return false; try { return _cache.isPartitioned(); } catch (RuntimeException re) { throw translate(re); } } public boolean getEvictOnBulkUpdate() { if (_cache == null) return false; try { return _cache.getEvictOnBulkUpdate(); } catch (RuntimeException re) { throw translate(re); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCDataGenerator.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCDataGenerato0000644000000000000000000002211512133327272030132 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.enhance.PCDataGenerator; import org.apache.openjpa.kernel.AbstractPCData; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.ValueMetaData; import serp.bytecode.BCClass; import serp.bytecode.BCField; import serp.bytecode.BCMethod; import serp.bytecode.Code; import serp.bytecode.Instruction; import serp.bytecode.JumpInstruction; /** * A {@link PCDataGenerator} instance which generates properly * synchronized instances suitable for use in the cache. In addition, * proper timed behavior is added. * * @author Steve Kim * @since 0.3.3.0 */ public class DataCachePCDataGenerator extends PCDataGenerator { public static final String POSTFIX = "datacache"; private static final Set _synchs = new HashSet(Arrays.asList (new String []{ "getData", "setData", "clearData", "getImplData", "setImplData", "setIntermediate", "getIntermediate", "isLoaded", "setLoaded", "setVersion", "getVersion", "store" })); public DataCachePCDataGenerator(OpenJPAConfiguration conf) { super(conf); } protected String getUniqueName(Class type) { return super.getUniqueName(type) + POSTFIX; } protected void finish(DynamicPCData data, ClassMetaData meta) { int timeout = meta.getDataCacheTimeout(); if (timeout > 0) ((Timed) data).setTimeout(timeout + System.currentTimeMillis()); else ((Timed) data).setTimeout(-1); } protected void decorate(BCClass bc, ClassMetaData meta) { enhanceToData(bc); enhanceToNestedData(bc); replaceNewEmbeddedPCData(bc); addSynchronization(bc); addTimeout(bc); } private void enhanceToData(BCClass bc) { BCMethod meth = bc.declareMethod("toData", Object.class, new Class []{ FieldMetaData.class, Object.class, StoreContext.class }); Code code = meth.getCode(true); // if (fmd.isLRS ())) // return NULL; code.aload().setParam(0); code.invokevirtual().setMethod(FieldMetaData.class, "isLRS", boolean.class, null); JumpInstruction ifins = code.ifeq(); code.getstatic().setField(AbstractPCData.class, "NULL", Object.class); code.areturn(); // super.toData (fmd, val, ctx); ifins.setTarget(code.aload().setThis()); code.aload().setParam(0); code.aload().setParam(1); code.aload().setParam(2); code.invokespecial().setMethod(AbstractPCData.class, "toData", Object.class, new Class[]{ FieldMetaData.class, Object.class, StoreContext.class }); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } private void enhanceToNestedData(BCClass bc) { BCMethod meth = bc.declareMethod("toNestedData", Object.class, new Class []{ ValueMetaData.class, Object.class, StoreContext.class }); Code code = meth.getCode(true); // if (val == null) // return null; code.aload().setParam(1); JumpInstruction ifins = code.ifnonnull(); code.constant().setNull(); code.areturn(); // int type = vmd.getDeclaredTypeCode (); ifins.setTarget(code.aload().setParam(0)); code.invokeinterface().setMethod(ValueMetaData.class, "getDeclaredTypeCode", int.class, null); int local = code.getNextLocalsIndex(); code.istore().setLocal(local); // if (type != JavaTypes.COLLECTION && // type != JavaTypes.MAP && // type != JavaTypes.ARRAY) // return super.toNestedData(type, val, ctx); // else // return NULL; Collection jumps = new ArrayList(3); code.iload().setLocal(local); code.constant().setValue(JavaTypes.COLLECTION); jumps.add(code.ificmpeq()); code.iload().setLocal(local); code.constant().setValue(JavaTypes.MAP); jumps.add(code.ificmpeq()); code.iload().setLocal(local); code.constant().setValue(JavaTypes.ARRAY); jumps.add(code.ificmpeq()); code.aload().setThis(); code.aload().setParam(0); code.aload().setParam(1); code.aload().setParam(2); code.invokespecial().setMethod(AbstractPCData.class, "toNestedData", Object.class, new Class[]{ ValueMetaData.class, Object.class, StoreContext.class }); code.areturn(); setTarget(code.getstatic().setField (AbstractPCData.class, "NULL", Object.class), jumps); code.areturn(); code.calculateMaxStack(); code.calculateMaxLocals(); } private void replaceNewEmbeddedPCData(BCClass bc) { BCMethod meth = bc.declareMethod("newEmbeddedPCData", AbstractPCData.class, new Class[]{ OpenJPAStateManager.class }); Code code = meth.getCode(true); // return new DataCachePCDataImpl(sm.getObjectId(), sm.getMetaData()); code.anew().setType(DataCachePCDataImpl.class); code.dup(); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getId", Object.class, null); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getMetaData", ClassMetaData.class, null); code.invokespecial().setMethod(DataCachePCDataImpl.class, "", void.class, new Class[] { Object.class, ClassMetaData.class }); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); } private void addTimeout(BCClass bc) { bc.declareInterface(DataCachePCData.class); bc.declareInterface(Timed.class); // public boolean isTimedOut (); BCField field = addBeanField(bc, "timeout", long.class); BCMethod meth = bc.declareMethod("isTimedOut", boolean.class, null); Code code = meth.getCode(true); // if (timeout == -1) ... code.aload().setThis(); code.getfield().setField(field); code.constant().setValue(-1L); code.lcmp(); JumpInstruction ifneg = code.ifeq(); // if (timeout >= System.currentTimeMillis ()) code.aload().setThis(); code.getfield().setField(field); code.invokestatic().setMethod(System.class, "currentTimeMillis", long.class, null); code.lcmp(); JumpInstruction ifnexp = code.ifge(); // return true; code.constant().setValue(1); // ... else return false; JumpInstruction go2 = code.go2(); Instruction flse = code.constant().setValue(0); ifneg.setTarget(flse); ifnexp.setTarget(flse); go2.setTarget(code.ireturn()); code.calculateMaxStack(); code.calculateMaxLocals(); } private void addSynchronization(BCClass bc) { BCMethod[] methods = bc.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { if (methods[i].isPublic() && _synchs.contains(methods[i].getName())) methods[i].setSynchronized(true); } // add synchronized isLoaded call. // public synchronized boolean isLoaded (int field) // { // return super.isLoaded (field); // } BCMethod method = bc.declareMethod("isLoaded", boolean.class, new Class[]{ int.class }); method.setSynchronized(true); Code code = method.getCode(true); code.aload().setThis(); code.iload().setParam(0); code.invokespecial().setMethod(AbstractPCData.class, "isLoaded", boolean.class, new Class[]{ int.class }); code.calculateMaxLocals(); code.calculateMaxStack(); code.ireturn(); } /** * Simple interface to give access to expiration time. */ public static interface Timed { public void setTimeout(long time); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/ConcurrentQueryCache.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/ConcurrentQueryCache.ja0000644000000000000000000001173412133327272030325 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.Collection; import org.apache.openjpa.event.RemoteCommitListener; import org.apache.openjpa.util.CacheMap; /** * A {@link QueryCache} implementation that is optimized for concurrent * access. When the cache fill up, values to remove from the cache are chosen * randomly. Due to race conditions, it is possible that a get call might not * retur a cached instance if that instance is being transferred between * internal datastructures. * * @since 0.4.1 */ public class ConcurrentQueryCache extends AbstractQueryCache implements RemoteCommitListener { private CacheMap _cache; protected boolean _lru = false; private int _cacheSize = Integer.MIN_VALUE; private int _softRefs = Integer.MIN_VALUE; /** * Returns the underlying {@link CacheMap} that this cache is using. * This is not an unmodifiable view on the map, so care should be taken * with this reference. Implementations should probably not modify the * contents of the cache, but should only use this reference * to obtain cache metrics. Additionally, this map may contain * expired data. Removal of timed-out data is done in a lazy * fashion, so the actual size of the map may be greater than the * number of non-expired query results in cache. */ public CacheMap getCacheMap() { return _cache; } /** * Returns the maximum number of unpinned objects to keep hard * references to. */ public int getCacheSize() { return _cache.getCacheSize(); } /** * Sets the maximum number of unpinned objects to keep hard * references to. If the map contains more unpinned objects than * size, then this method will result in the cache * flushing old values. */ public void setCacheSize(int size) { _cacheSize = size; } /** * Returns the maximum number of unpinned objects to keep soft * references to. Defaults to -1. */ public int getSoftReferenceSize() { return _cache.getSoftReferenceSize(); } /** * Sets the maximum number of unpinned objects to keep soft * references to. If the map contains more soft references than * size, then this method will result in the cache * flushing values. */ public void setSoftReferenceSize(int size) { _softRefs = size; } public void initialize(DataCacheManager mgr) { super.initialize(mgr); conf.getRemoteCommitEventManager().addInternalListener(this); _cache = newCacheMap(); if (_cacheSize != Integer.MIN_VALUE) { _cache.setCacheSize(_cacheSize); } if (_softRefs != Integer.MIN_VALUE) { _cache.setSoftReferenceSize(_softRefs); } } public void writeLock() { // delegate actually does nothing, but in case that changes... _cache.writeLock(); } public void writeUnlock() { // delegate actually does nothing, but in case that changes... _cache.writeUnlock(); } /** * Return the map to use as an internal cache. */ protected CacheMap newCacheMap() { CacheMap res = new CacheMap(_lru); return res; } protected QueryResult getInternal(QueryKey qk) { return (QueryResult) _cache.get(qk); } protected QueryResult putInternal(QueryKey qk, QueryResult result) { return (QueryResult) _cache.put(qk, result); } protected QueryResult removeInternal(QueryKey qk) { return (QueryResult) _cache.remove(qk); } protected void clearInternal() { _cache.clear(); } protected boolean pinInternal(QueryKey qk) { return _cache.pin(qk); } protected boolean unpinInternal(QueryKey qk) { return _cache.unpin(qk); } protected Collection keySet() { return _cache.keySet (); } /** * Returns the eviction policy of the query cache */ public EvictPolicy getEvictPolicy() { return super.evictPolicy; } public void setLru(boolean l) { _lru = l; } public boolean getLru() { return _lru; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheMode.java0000644000000000000000000000352612133327272027162 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; public enum DataCacheMode { /** *

    All entities are cached regardless of annotations or xml configuration.

    */ ALL, /** *

    No entities are cached regardless of annotations or xml configuration.

    */ NONE, /** *

    * Only the entities which are configured to be in the cache will be * cached. Entities which do not specify whether they are cacheable will be * excluded *

    *

    * AKA opt-in. *

    */ ENABLE_SELECTIVE, /** *

    * All entities except those which are explicitly excluded will be cached. *

    *

    * AKA opt-out *

    */ DISABLE_SELECTIVE, /** *

    * Default value. In this case OpenJPA will behave as it did in previous * releases, and will take into account the includedTypes and excludedTypes * optional parameters on the openjpa.DataCache * configuration property. *

    */ UNSPECIFIED } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryResult.java0000644000000000000000000000431112133327272027055 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.ArrayList; import java.util.Collection; /** * A query result. * * @author Abe White */ @SuppressWarnings("serial") public class QueryResult extends ArrayList { private final long _ex; private long _timestamp = 0L; /** * Constructor; supply corresponding query key and result data. */ public QueryResult(QueryKey key, Collection data) { super(data); if (key.getTimeout() == -1) _ex = -1; else _ex = System.currentTimeMillis() + key.getTimeout(); } /** * Constructor to set internal data from a serializer. */ public QueryResult(Collection data, long ex) { super(data); _ex = ex; } /** * Expiration time, or -1 for no timeout. */ public long getTimeoutTime() { return _ex; } /** * Whether this data is timed out. */ public boolean isTimedOut() { return _ex != -1 && _ex < System.currentTimeMillis(); } /** * Sets the timestamp of the query result. * @param ts -- Timestamp value in long */ public void setTimestamp(long ts) { this._timestamp = ts; } /** * Returns the timestamp of the query result. * @return -- the timestamp value in long */ public long getTimestamp() { return this._timestamp; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCacheStoreQuery.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCacheStoreQuery.ja0000644000000000000000000005664112133327272030333 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.AbstractList; import java.util.ArrayList; import java.util.BitSet; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.apache.commons.collections.map.LinkedMap; import org.apache.openjpa.datacache.AbstractQueryCache.EvictPolicy; import org.apache.openjpa.kernel.DelegatingStoreManager; import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.LockLevels; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.QueryContext; import org.apache.openjpa.kernel.ResultShape; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.kernel.StoreQuery; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.kernel.exps.QueryExpressions; import org.apache.openjpa.lib.rop.ListResultObjectProvider; import org.apache.openjpa.lib.rop.ResultObjectProvider; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.ObjectNotFoundException; /** * A {@link StoreQuery} implementation that caches the OIDs involved in * the query, and can determine whether or not the query has been dirtied. * * @author Patrick Linskey * @since 0.2.5.0 */ public class QueryCacheStoreQuery implements StoreQuery { private final StoreQuery _query; private final QueryCache _cache; private StoreContext _sctx; private MetaDataRepository _repos; /** * Create a new instance that delegates to query if no * cached results are available. */ public QueryCacheStoreQuery(StoreQuery query, QueryCache cache) { _query = query; _cache = cache; } /** * Return the {@link QueryCache} that this object is associated with. */ public QueryCache getCache() { return _cache; } /** * Delegate. */ public StoreQuery getDelegate() { return _query; } /** * Look in the query cache for a result for the given query * key. Only look if this query is being executed outside a * transaction or in a transaction with IgnoreChanges set to true * or in a transaction with IgnoreChanges set to false but in which * none of the classes involved in this query have been touched. * Caching is not used when using object locking. * This is because we must obtain locks on the * data, and it is likely that making n trips to the database to * make the locks will be slower than running the query against * the database. * If the fetch configuration has query caching disabled, * then this method returns null. * Return the list if we meet the above criteria and if a list * is found for qk. Else, return * null. * This implementation means that queries against the cache * are of READ_COMMITTED isolation level. It'd be nice to support * READ_SERIALIZABLE -- to do so, we'd just return false when in * a transaction. */ private List checkCache(QueryKey qk) { if (qk == null) return null; FetchConfiguration fetch = getContext().getFetchConfiguration(); if (!fetch.getQueryCacheEnabled()) return null; if (fetch.getReadLockLevel() > LockLevels.LOCK_NONE) return null; // get the cached data QueryResult res = _cache.get(qk); if (res == null) { return null; } // this if block is invoked if the evictOnTimestamp is set to true if (_cache instanceof AbstractQueryCache) { AbstractQueryCache qcache = (AbstractQueryCache) _cache; if (qcache.getEvictPolicy() == EvictPolicy.TIMESTAMP) { Set classNames = qk.getAcessPathClassNames(); List keyList = new ArrayList(); keyList.addAll(classNames); List timestamps = qcache.getAllEntityTimestamp(keyList); long queryTS = res.getTimestamp(); if (timestamps != null) { for (Long ts: timestamps) { // if this is true we have to evict the query // from cache if (queryTS <= ts) { qcache.remove(qk); return null; } } } } } if (res.isEmpty()) { return Collections.emptyList(); } int projs = getContext().getProjectionAliases().length; if (projs == 0) { // We're only going to return the cached results if we have ALL results cached. This could be improved // in the future to be a little more intelligent. if (getContext().getStoreContext().isCached(res) == false) { return null; } } return new CachedList(res, projs != 0, _sctx); } /** * Wrap the result object provider returned by our delegate in a * caching provider. */ private ResultObjectProvider wrapResult(ResultObjectProvider rop, QueryKey key) { if (key == null) return rop; return new CachingResultObjectProvider(rop, getContext(). getProjectionAliases().length > 0, key); } /** * Copy a projection element for caching / returning. */ private static Object copyProjection(Object obj, StoreContext ctx) { if (obj == null) return null; switch (JavaTypes.getTypeCode(obj.getClass())) { case JavaTypes.STRING: case JavaTypes.BOOLEAN_OBJ: case JavaTypes.BYTE_OBJ: case JavaTypes.CHAR_OBJ: case JavaTypes.DOUBLE_OBJ: case JavaTypes.FLOAT_OBJ: case JavaTypes.INT_OBJ: case JavaTypes.LONG_OBJ: case JavaTypes.SHORT_OBJ: case JavaTypes.BIGDECIMAL: case JavaTypes.BIGINTEGER: case JavaTypes.OID: return obj; case JavaTypes.DATE: return ((Date) obj).clone(); case JavaTypes.LOCALE: return ((Locale) obj).clone(); default: if (obj instanceof CachedObjectId) return fromObjectId(((CachedObjectId) obj).oid, ctx); Object oid = ctx.getObjectId(obj); if (oid != null) return new CachedObjectId(oid); return obj; } } /** * Return the result object based on its cached oid. */ private static Object fromObjectId(Object oid, StoreContext sctx) { if (oid == null) return null; Object obj = sctx.find(oid, null, null, null, 0); if (obj == null) throw new ObjectNotFoundException(oid); return obj; } public Object writeReplace() throws ObjectStreamException { return _query; } public QueryContext getContext() { return _query.getContext(); } public void setContext(QueryContext qctx) { _query.setContext(qctx); _sctx = qctx.getStoreContext(); _repos = _sctx.getConfiguration().getMetaDataRepositoryInstance(); } public boolean setQuery(Object query) { return _query.setQuery(query); } public FilterListener getFilterListener(String tag) { return _query.getFilterListener(tag); } public AggregateListener getAggregateListener(String tag) { return _query.getAggregateListener(tag); } public Object newCompilationKey() { return _query.newCompilationKey(); } public Object newCompilation() { return _query.newCompilation(); } public Object getCompilation() { return _query.getCompilation(); } public void populateFromCompilation(Object comp) { _query.populateFromCompilation(comp); } public void invalidateCompilation() { _query.invalidateCompilation(); } public boolean supportsDataStoreExecution() { return _query.supportsDataStoreExecution(); } public boolean supportsInMemoryExecution() { return _query.supportsInMemoryExecution(); } public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs) { return _query.newInMemoryExecutor(meta, subs); } public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs) { Executor ex = _query.newDataStoreExecutor(meta, subs); return new QueryCacheExecutor(ex, meta, subs, getContext().getFetchConfiguration()); } public boolean supportsAbstractExecutors() { return _query.supportsAbstractExecutors(); } public boolean requiresCandidateType() { return _query.requiresCandidateType(); } public boolean requiresParameterDeclarations() { return _query.requiresParameterDeclarations(); } public boolean supportsParameterDeclarations() { return _query.supportsParameterDeclarations(); } public Object evaluate(Object value, Object ob, Object[] params, OpenJPAStateManager sm) { return _query.evaluate(value, ob, params, sm); } /** * Caching executor. */ private static class QueryCacheExecutor implements Executor { private final Executor _ex; private final Class _candidate; private final boolean _subs; private final FetchConfiguration _fc; public QueryCacheExecutor(Executor ex, ClassMetaData meta, boolean subs, FetchConfiguration fc) { _ex = ex; _candidate = (meta == null) ? null : meta.getDescribedType(); _subs = subs; _fc = fc; } public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, Range range) { QueryCacheStoreQuery cq = (QueryCacheStoreQuery) q; Object parsed = cq.getDelegate().getCompilation(); QueryKey key = QueryKey.newInstance(cq.getContext(), _ex.isPacking(q), params, _candidate, _subs, range.start, range.end, parsed); List cached = cq.checkCache(key); if (cached != null) return new ListResultObjectProvider(cached); ResultObjectProvider rop = _ex.executeQuery(cq.getDelegate(), params, range); if (_fc.getQueryCacheEnabled()) return cq.wrapResult(rop, key); else return rop; } public QueryExpressions[] getQueryExpressions() { return _ex.getQueryExpressions(); } /** * Clear the cached queries associated with the access path * classes in the query. This is done when bulk operations * (such as deletes or updates) are performed so that the * cache remains up-to-date. */ private void clearAccessPath(StoreQuery q) { if (q == null) return; ClassMetaData[] cmd = getAccessPathMetaDatas(q); if (cmd == null || cmd.length == 0) return; List> classes = new ArrayList>(cmd.length); for (int i = 0; i < cmd.length; i++) classes.add(cmd[i].getDescribedType()); // evict from the query cache QueryCacheStoreQuery cq = (QueryCacheStoreQuery) q; cq.getCache().onTypesChanged(new TypesChangedEvent (q.getContext(), classes)); // evict from the data cache for (int i = 0; i < cmd.length; i++) { if (cmd[i].getDataCache() != null && cmd[i].getDataCache().getEvictOnBulkUpdate()) cmd[i].getDataCache().removeAll( cmd[i].getDescribedType(), true); } } public Number executeDelete(StoreQuery q, Object[] params) { try { return _ex.executeDelete(unwrap(q), params); } finally { clearAccessPath(q); } } public Number executeUpdate(StoreQuery q, Object[] params) { try { return _ex.executeUpdate(unwrap(q), params); } finally { clearAccessPath(q); } } public String[] getDataStoreActions(StoreQuery q, Object[] params, Range range) { return EMPTY_STRINGS; } public void validate(StoreQuery q) { _ex.validate(unwrap(q)); } public void getRange(StoreQuery q, Object[] params, Range range) { _ex.getRange(q, params, range); } public Object getOrderingValue(StoreQuery q, Object[] params, Object resultObject, int orderIndex) { return _ex.getOrderingValue(unwrap(q), params, resultObject, orderIndex); } public boolean[] getAscending(StoreQuery q) { return _ex.getAscending(unwrap(q)); } public boolean isPacking(StoreQuery q) { return _ex.isPacking(unwrap(q)); } public String getAlias(StoreQuery q) { return _ex.getAlias(unwrap(q)); } public Class getResultClass(StoreQuery q) { return _ex.getResultClass(unwrap(q)); } public ResultShape getResultShape(StoreQuery q) { return _ex.getResultShape(q); } public String[] getProjectionAliases(StoreQuery q) { return _ex.getProjectionAliases(unwrap(q)); } public Class[] getProjectionTypes(StoreQuery q) { return _ex.getProjectionTypes(unwrap(q)); } public ClassMetaData[] getAccessPathMetaDatas(StoreQuery q) { return _ex.getAccessPathMetaDatas(unwrap(q)); } public int getOperation(StoreQuery q) { return _ex.getOperation(unwrap(q)); } public boolean isAggregate(StoreQuery q) { return _ex.isAggregate(unwrap(q)); } public boolean isDistinct(StoreQuery q) { return _ex.isDistinct(unwrap(q)); } public boolean hasGrouping(StoreQuery q) { return _ex.hasGrouping(unwrap(q)); } public OrderedMap> getOrderedParameterTypes(StoreQuery q) { return _ex.getOrderedParameterTypes(unwrap(q)); } public LinkedMap getParameterTypes(StoreQuery q) { return _ex.getParameterTypes(unwrap(q)); } public Object[] toParameterArray(StoreQuery q, Map userParams) { return _ex.toParameterArray(q, userParams); } public Map getUpdates(StoreQuery q) { return _ex.getUpdates(unwrap(q)); } private static StoreQuery unwrap(StoreQuery q) { return ((QueryCacheStoreQuery) q).getDelegate(); } } /** * Result list implementation for a cached query result. Package-protected * for testing. */ public static class CachedList extends AbstractList implements Serializable { private final QueryResult _res; private final boolean _proj; private final StoreContext _sctx; public CachedList(QueryResult res, boolean proj, StoreContext ctx) { _res = res; _proj = proj; _sctx = ctx; } public Object get(int idx) { if (!_proj) return fromObjectId(_res.get(idx), _sctx); Object[] cached = (Object[]) _res.get(idx); if (cached == null) return null; Object[] uncached = new Object[cached.length]; for (int i = 0; i < cached.length; i++) uncached[i] = copyProjection(cached[i], _sctx); return uncached; } public int size() { return _res.size(); } public Object writeReplace() throws ObjectStreamException { return new ArrayList(this); } } /** * A wrapper around a {@link ResultObjectProvider} that builds up a list of * all the OIDs in this list and registers that list with the * query cache. Abandons monitoring and registering if one of the classes * in the access path is modified while the query results are being loaded. */ private class CachingResultObjectProvider implements ResultObjectProvider, TypesChangedListener { private final ResultObjectProvider _rop; private final boolean _proj; private final QueryKey _qk; private final TreeMap _data = new TreeMap(); private boolean _maintainCache = true; private int _pos = -1; // used to determine list size without necessarily calling size(), // which may require a DB trip or return Integer.MAX_VALUE private int _max = -1; private int _size = Integer.MAX_VALUE; /** * Constructor. Supply delegate result provider and our query key. */ public CachingResultObjectProvider(ResultObjectProvider rop, boolean proj, QueryKey key) { _rop = rop; _proj = proj; _qk = key; _cache.addTypesChangedListener(this); } /** * Stop caching. */ private void abortCaching() { if (!_maintainCache) return; // this can be called via an event from another thread synchronized (this) { // it's important that we set this flag first so that any // subsequent calls to this object are bypassed. _maintainCache = false; _cache.removeTypesChangedListener(this); _data.clear(); } } /** * Check whether we've buffered all results, while optionally adding * the given result. */ private void checkFinished(Object obj, boolean result) { // this can be called at the same time as abortCaching via // a types changed event boolean finished = false; synchronized (this) { if (_maintainCache) { if (result) { Integer index = _pos; if (!_data.containsKey(index)) { Object cached; if (obj == null) cached = null; else if (!_proj) cached = _sctx.getObjectId(obj); else { Object[] arr = (Object[]) obj; Object[] cp = new Object[arr.length]; for (int i = 0; i < arr.length; i++) cp[i] = copyProjection(arr[i], _sctx); cached = cp; } if (cached != null) _data.put(index, cached); } } finished = _size == _data.size(); } } if (finished) { // an abortCaching call can sneak in here via onExpire; the // cache is locked during event firings, so the lock here will // wait for it (or will force the next firing to wait) _cache.writeLock(); try { // make sure we didn't abort if (_maintainCache) { QueryResult res = null; synchronized (this) { res = new QueryResult(_qk, _data.values()); res.setTimestamp(System.currentTimeMillis()); } _cache.put(_qk, res); abortCaching(); } } finally { _cache.writeUnlock(); } } } public boolean supportsRandomAccess() { return _rop.supportsRandomAccess(); } public void open() throws Exception { _rop.open(); } public Object getResultObject() throws Exception { Object obj = _rop.getResultObject(); checkFinished(obj, true); return obj; } public boolean next() throws Exception { _pos++; boolean next = _rop.next(); if (!next && _pos == _max + 1) { _size = _pos; checkFinished(null, false); } else if (next && _pos > _max) _max = _pos; return next; } public boolean absolute(int pos) throws Exception { _pos = pos; boolean valid = _rop.absolute(pos); if (!valid && _pos == _max + 1) { _size = _pos; checkFinished(null, false); } else if (valid && _pos > _max) _max = _pos; return valid; } public int size() throws Exception { if (_size != Integer.MAX_VALUE) return _size; int size = _rop.size(); _size = size; checkFinished(null, false); return size; } public void reset() throws Exception { _rop.reset(); _pos = -1; } public void close() throws Exception { abortCaching(); _rop.close(); } public void handleCheckedException(Exception e) { _rop.handleCheckedException(e); } public void onTypesChanged(TypesChangedEvent ev) { if (_qk.changeInvalidatesQuery(ev.getTypes())) abortCaching(); } } /** * Struct to recognize cached oids. */ private static class CachedObjectId implements java.io.Serializable { public final Object oid; public CachedObjectId (Object oid) { this.oid = oid; } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/CacheStatisticsImpl.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/CacheStatisticsImpl.jav0000644000000000000000000001314112133327272030311 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.openjpa.util.OpenJPAId; /** * The default CacheStatistics(SPI) implementation. */ public class CacheStatisticsImpl implements CacheStatisticsSPI { private static final long serialVersionUID = 9014495759588003166L; private static final int ARRAY_SIZE = 3; private long[] totalStat = new long[ARRAY_SIZE]; private long[] stat = new long[ARRAY_SIZE]; private Map stats = new HashMap(); private Map totalStats = new HashMap(); private Date start = new Date(); private Date since = new Date(); private boolean enabled = false; private static final int READ = 0; private static final int HIT = 1; private static final int WRITE = 2; public long getReadCount() { return stat[READ]; } public long getHitCount() { return stat[HIT]; } public long getWriteCount() { return stat[WRITE]; } public long getTotalReadCount() { return totalStat[READ]; } public long getTotalHitCount() { return totalStat[HIT]; } public long getTotalWriteCount() { return totalStat[WRITE]; } public long getReadCount(Class c) { return getReadCount(c.getName()); } public long getReadCount(String str){ return getCount(stats, str, READ); } public long getHitCount(Class c) { return getHitCount(c.getName()); } public long getHitCount(String str) { return getCount(stats, str, HIT); } public long getWriteCount(Class c) { return getWriteCount(c.getName()); } public long getWriteCount(String str) { return getCount(stats, str, WRITE); } public long getTotalReadCount(Class c) { return getTotalReadCount(c.getName()); } public long getTotalReadCount(String str) { return getCount(totalStats, str, READ); } public long getTotalHitCount(Class c) { return getTotalHitCount(c.getName()); } public long getTotalHitCount(String str) { return getCount(totalStats, str, HIT); } public long getTotalWriteCount(Class c) { return getCount(totalStats, c.getName(), WRITE); } public long getTotalWriteCount(String str) { return getCount(totalStats, str, WRITE); } public Date since() { return since; } public Date start() { return start; } public void reset() { stat = new long[ARRAY_SIZE]; stats.clear(); since = new Date(); } public boolean isEnabled() { return enabled; } public Set classNames() { return totalStats.keySet(); } public Map toMap() { Map res = new HashMap(); for(Entry s : stats.entrySet()){ res.put(s.getKey(), s.getValue()); } return res; } /** * SPI implementation */ public void enable() { enabled = true; } public void disable() { enabled = false; } public void newGet(Class cls, boolean hit) { if (!enabled) { return; } cls = (cls == null) ? Object.class : cls; String clsName = cls.getName(); addSample(clsName, READ); if (hit) { addSample(clsName, HIT); } } public void newGet(Object oid, boolean hit) { if (!enabled) { return; } if (oid instanceof OpenJPAId) { newGet(((OpenJPAId) oid).getType(), hit); } } public void newPut(Class cls) { if (!enabled) { return; } cls = (cls == null) ? Object.class : cls; addSample(cls.getName(), WRITE); } public void newPut(Object oid) { if (!enabled) { return; } if (oid instanceof OpenJPAId) { newPut(((OpenJPAId) oid).getType()); } } /** * Private worker methods. */ private void addSample(String c, int index) { stat[index]++; totalStat[index]++; addSample(stats, c, index); addSample(totalStats, c, index); } private void addSample(Map target, String c, int index) { long[] row = target.get(c); if (row == null) { row = new long[ARRAY_SIZE]; } row[index]++; target.put(c, row); } private long getCount(Map target, String c, int index) { long[] row = target.get(c); return (row == null) ? 0 : row[index]; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/ExpirationListener.java0000644000000000000000000000215212133327272030402 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.datacache; /** * An entity that wishes to be notified when cache keys expire. * * @author Abe White * @since 0.3.0 */ public interface ExpirationListener { /** * Notification that an object has expired from the cache. */ public void onExpire(ExpirationEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/0000755000000000000000000000000012133327272023133 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/BeanLifecycleCallbacks.java0000644000000000000000000000660312133327272030270 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedActionException; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * Performs a callback method on a cached bean instance. * * @author Steve Kim */ public class BeanLifecycleCallbacks extends MethodLifecycleCallbacks { private static final Localizer _loc = Localizer.forPackage (BeanLifecycleCallbacks.class); private transient Object _listener; /** * Constructor. Make the callback on an instance of the given type. * * @arg whether another argument is expected such as AfterDetach */ public BeanLifecycleCallbacks(Class cls, String method, boolean arg, Class type) { this(cls, getMethod(cls, method, arg ? new Class[]{ Object.class, type } : new Class[]{ type }), arg); } /** * Constructor. Make the callback on an instance of the given type. */ public BeanLifecycleCallbacks(Class cls, Method method, boolean arg) { super(method, arg); _listener = newListener(cls); } private Object newListener(Class cls) { try { return AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(cls)); } catch (Throwable t) { if (t instanceof PrivilegedActionException) t = ((PrivilegedActionException) t).getException(); throw new UserException(_loc.get("bean-constructor", cls.getName()), t); } } public void makeCallback(Object obj, Object rel, int eventType) throws Exception { Method callback = getCallbackMethod(); if (!callback.isAccessible()) AccessController.doPrivileged(J2DoPrivHelper.setAccessibleAction( callback, true)); if (requiresArgument()) callback.invoke(_listener, new Object[]{ obj, rel }); else callback.invoke(_listener, new Object[]{ obj }); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); Class cls = (Class) in.readObject(); _listener = newListener(cls); } public void writeExternal(ObjectOutput out) throws IOException { super.writeExternal(out); out.writeObject(_listener.getClass()); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/SingleJVMRemoteCommitProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/SingleJVMRemoteCommitProvid0000644000000000000000000000432612133327272030372 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.util.Iterator; import java.util.Set; import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashSet; /** * Single-JVM-only implementation of {@link RemoteCommitProvider} * that listens for object modifications and propagates those changes * to other SingleJVMRemoteCommitProviders in the same JVM. This is * only useful for linking together multiple factories in the same * JVM that are all loaded in the same classloader, which is a rare * circumstance. * * @author Patrick Linskey * @since 0.2.5.0 */ public class SingleJVMRemoteCommitProvider extends AbstractRemoteCommitProvider { private static Set s_providers = new ConcurrentReferenceHashSet( ConcurrentReferenceHashSet.HARD); public SingleJVMRemoteCommitProvider() { s_providers.add(this); } public void broadcast(RemoteCommitEvent event) { SingleJVMRemoteCommitProvider provider; for (Iterator iter = s_providers.iterator(); iter.hasNext();) { provider = (SingleJVMRemoteCommitProvider) iter.next(); // don't notify this object -- this provider's factory // should not be notified of commits that originated // with one of its brokers if (provider == this) continue; provider.fireEvent(event); } } public void close() { s_providers.remove(this); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/BeginTransactionListener.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/BeginTransactionListener.ja0000644000000000000000000000222412133327272030407 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Notified when transactions begin. * * @author Patrick Linskey * @author Abe White * @since 0.2.5.0 */ public interface BeginTransactionListener { /** * Notification that a transaction has begun. * * @see TransactionEvent#AFTER_BEGIN */ public void afterBegin(TransactionEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/CallbackModes.java0000644000000000000000000000310412133327272026460 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Callback handling constants. * * @author Steve Kim * @since 0.4.0 */ public interface CallbackModes { /** * Flag to stop executing callbacks on exception immediately. */ public static final int CALLBACK_FAIL_FAST = 2 << 0; /** * Flag to ignore exceptions made during callback. */ public static final int CALLBACK_IGNORE = 2 << 1; /** * Flag to log exceptions made during callback. */ public static final int CALLBACK_LOG = 2 << 2; /** * Flag to re-throw exceptions made during callback. */ public static final int CALLBACK_RETHROW = 2 << 3; /** * Flag to always rollback on a callback exception. */ public static final int CALLBACK_ROLLBACK = 2 << 4; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryListener.java0000644000000000000000000000240012133327272030254 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Interface for listening to {@link BrokerFactoryEvent} objects. Should be * registered with a {@link OpenJPAConfiguration}'s * {@link BrokerFactoryEventManager}. * * @since 1.0.0 */ public interface BrokerFactoryListener { /** * Invoked after a {@link BrokerFactory} has been fully created. * This happens after the factory has been made read-only. */ public void eventFired(BrokerFactoryEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/OrphanedKeyAction.java0000644000000000000000000000305212133327272027345 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.meta.ValueMetaData; /** * Perform an action when OpenJPA detects an orphaned key in the database. * * @author Abe White * @since 0.3.2.2 */ public interface OrphanedKeyAction { /** * Callback received when OpenJPA discovers an orphaned key. * * @param oid the orphaned key * @param sm the instance representing the record in which the * key was discovered; may be null * @param vmd the value in which the key was discovered * @return the value to load into field fmd; typically * null */ public Object orphan(Object oid, OpenJPAStateManager sm, ValueMetaData vmd); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/package.html0000644000000000000000000000206712133327272025421 0ustar

    OpenJPA Events

    This package provides some interfaces and useful implementations for OpenJPA's event notification framework. This framework allows efficient notification of object modifications and transaction changes.

    ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/AbstractTransactionListener.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/AbstractTransactionListener0000644000000000000000000000421412133327272030536 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Abstract implementation of the {@link TransactionListener} interface * that provides no-op implementations of all methods. * * @author Abe White * @since 0.3.0 */ public abstract class AbstractTransactionListener implements TransactionListener { /** * Catch-all for unhandled events. This method is called by all other * event methods if you do not override them. Does nothing by default. */ protected void eventOccurred(TransactionEvent event) { } public void afterBegin(TransactionEvent event) { eventOccurred(event); } public void beforeFlush(TransactionEvent event) { eventOccurred(event); } public void afterFlush(TransactionEvent event) { eventOccurred(event); } public void beforeCommit(TransactionEvent event) { eventOccurred(event); } public void afterCommit(TransactionEvent event) { eventOccurred(event); } public void afterRollback(TransactionEvent event) { eventOccurred(event); } public void afterStateTransitions(TransactionEvent event) { eventOccurred(event); } public void afterCommitComplete(TransactionEvent event) { eventOccurred(event); } public void afterRollbackComplete(TransactionEvent event) { eventOccurred(event); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEvent.java0000644000000000000000000000323612133327272027560 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.util.EventObject; import org.apache.openjpa.kernel.BrokerFactory; /** * Event fired when a {@link BrokerFactory} is created. * * @since 1.0.0 */ public class BrokerFactoryEvent extends EventObject { /** * Fired after a {@link BrokerFactory} has been fully created. * This happens after the factory has been made read-only. */ public static final int BROKER_FACTORY_CREATED = 0; private int eventType; public BrokerFactoryEvent(BrokerFactory brokerFactory, int eventType) { super(brokerFactory); this.eventType = eventType; } public BrokerFactory getBrokerFactory() { return (BrokerFactory) getSource(); } /** * @return one of the event type codes defined in this event class. */ public int getEventType() { return eventType; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java0000644000000000000000000006373312133327272030206 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.MetaDataDefaults; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InvalidStateException; /** * Manager that can be used to track and notify listeners on lifecycle events. * This class is optimized for event firing rather than for adding and * removing listeners, which are O(n) operations. This class also does not * maintain perfect set semantics for listeners; it is possible to wind up * having the same listener invoked multiple times for a single event if it * is added to this manager multiple times with different classes, or with * a base class and its subclass. * * @author Steve Kim * @author Abe White * @since 0.3.3 * @nojavadoc */ @SuppressWarnings("serial") public class LifecycleEventManager implements CallbackModes, Serializable { private static final Exception[] EMPTY_EXCEPTIONS = new Exception[0]; private static final Localizer _loc = Localizer.forPackage( LifecycleEventManager.class); private Map, ListenerList> _classListeners = null; private ListenerList _listeners = null; // odd-element: Listener even-element: Class[] private List _addListeners = new LinkedList(); private List _remListeners = new LinkedList(); private List _exceps = new LinkedList(); private boolean _firing = false; private boolean _fail = false; private boolean _failFast = false; private boolean _activated = false; // set to true once modified /** * Whether this LifeCycleEventManager has had at least one listener or callback * registered. Used for a quick test when firing events. * @return boolean */ public boolean isActive(ClassMetaData meta) { return _activated || meta.getLifecycleMetaData().is_activated() || meta.getRepository().is_systemListenersActivated(); } /** * Whether to fail after first exception when firing events to listeners. */ public boolean isFailFast() { return _failFast; } /** * Whether to fail after first exception when firing events to listeners. */ public void setFailFast(boolean failFast) { _failFast = failFast; } /** * Register a lifecycle listener for the given classes. If the classes * array is null, register for all classes. */ public synchronized void addListener(Object listener, Class[] classes) { if (listener == null) return; if (classes != null && classes.length == 0) return; _activated = true; if (_firing) { _addListeners.add(listener); _addListeners.add(classes); return; } if (classes == null) { if (_listeners == null) _listeners = new ListenerList(5); _listeners.add(listener); return; } if (_classListeners == null) _classListeners = new HashMap, ListenerList>(); ListenerList listeners; for (int i = 0; i < classes.length; i++) { listeners = (ListenerList) _classListeners.get(classes[i]); if (listeners == null) { listeners = new ListenerList(3); _classListeners.put(classes[i], listeners); } listeners.add(listener); } } /** * Remove the given listener. */ public synchronized void removeListener(Object listener) { if (_firing) { _remListeners.add(listener); return; } if (_listeners != null && _listeners.remove(listener)) return; if (_classListeners != null) { ListenerList listeners; for (Iterator itr = _classListeners.values().iterator(); itr.hasNext();) { listeners = (ListenerList) itr.next(); listeners.remove(listener); } } } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasPersistListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.BEFORE_PERSIST) || hasHandlers(source, meta, LifecycleEvent.AFTER_PERSIST) || hasHandlers(source, meta, LifecycleEvent.AFTER_PERSIST_PERFORMED); } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasDeleteListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.BEFORE_DELETE) || hasHandlers(source, meta, LifecycleEvent.AFTER_DELETE) || hasHandlers(source, meta, LifecycleEvent.AFTER_DELETE_PERFORMED); } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasClearListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.BEFORE_CLEAR) || hasHandlers(source, meta, LifecycleEvent.AFTER_CLEAR); } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasLoadListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.AFTER_LOAD); } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasStoreListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.BEFORE_STORE) || hasHandlers(source, meta, LifecycleEvent.AFTER_STORE); } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasUpdateListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.BEFORE_UPDATE) || hasHandlers(source, meta, LifecycleEvent.AFTER_UPDATE_PERFORMED); } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasDirtyListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.BEFORE_DIRTY) || hasHandlers(source, meta, LifecycleEvent.AFTER_DIRTY); } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasDetachListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.BEFORE_DETACH) || hasHandlers(source, meta, LifecycleEvent.AFTER_DETACH); } /** * Return whether there are listeners or callbacks for the given source. */ public boolean hasAttachListeners(Object source, ClassMetaData meta) { return hasHandlers(source, meta, LifecycleEvent.BEFORE_ATTACH) || hasHandlers(source, meta, LifecycleEvent.AFTER_ATTACH); } private boolean hasHandlers(Object source, ClassMetaData meta, int type) { return hasCallbacks(source, meta, type) || hasListeners(source, meta, type); } /** * Return true if any callbacks are registered for the given source and * event type. */ private boolean hasCallbacks(Object source, ClassMetaData meta, int type) { LifecycleCallbacks[] callbacks = meta.getLifecycleMetaData(). getCallbacks(type); if (callbacks.length == 0) return false; for (int i = 0; i < callbacks.length; i++) if (callbacks[i].hasCallback(source, type)) return true; return false; } /** * Return true if any listeners are registered for the given source and * event type. */ private boolean hasListeners(Object source, ClassMetaData meta, int type) { if (meta.getLifecycleMetaData().getIgnoreSystemListeners()) return false; if (fireEvent(null, source, null, type, _listeners, true, null) == Boolean.TRUE) return true; ListenerList system = meta.getRepository().getSystemListeners(); if (!system.isEmpty() && fireEvent(null, source, null, type, system, true, null) == Boolean.TRUE) return true; if (_classListeners != null) { Class c = source == null ? meta.getDescribedType() : source.getClass(); do { if (fireEvent(null, source, null, type, (ListenerList) _classListeners.get(c), true, null) == Boolean.TRUE) return true; c = c.getSuperclass(); } while (c != null && c != Object.class); } return false; } /** * Fire lifecycle event to all registered listeners without an argument. */ public Exception[] fireEvent(Object source, ClassMetaData meta, int type) { return fireEvent(source, null, meta, type); } /** * Fire lifecycle event to all registered listeners. */ public synchronized Exception[] fireEvent(Object source, Object related, ClassMetaData meta, int type) { boolean reentrant = _firing; _firing = true; List exceptions = (reentrant) ? new LinkedList() : _exceps; MetaDataDefaults def = meta.getRepository().getMetaDataFactory(). getDefaults(); boolean callbacks = def.getCallbacksBeforeListeners(type); if (callbacks) makeCallbacks(source, related, meta, type, exceptions); LifecycleEvent ev = (LifecycleEvent) fireEvent(null, source, related, type, _listeners, false, exceptions); if (_classListeners != null) { Class c = source == null ? meta.getDescribedType() : source.getClass(); do { ev = (LifecycleEvent) fireEvent(ev, source, related, type, (ListenerList) _classListeners.get(c), false, exceptions); c = c.getSuperclass(); } while (c != null && c != Object.class); } // make system listeners if (!meta.getLifecycleMetaData().getIgnoreSystemListeners()) { ListenerList system = meta.getRepository().getSystemListeners(); fireEvent(ev, source, related, type, system, false, exceptions); } if (!callbacks) makeCallbacks(source, related, meta, type, exceptions); // create return array before clearing exceptions Exception[] ret; if (exceptions.isEmpty()) ret = EMPTY_EXCEPTIONS; else ret = (Exception[]) exceptions.toArray (new Exception[exceptions.size()]); // if this wasn't a reentrant call, catch up with calls to add // and remove listeners made while firing if (!reentrant) { _firing = false; _fail = false; if (!_addListeners.isEmpty()) for (Iterator itr = _addListeners.iterator(); itr.hasNext();) addListener(itr.next(), (Class[]) itr.next()); if (!_remListeners.isEmpty()) for (Iterator itr = _remListeners.iterator(); itr.hasNext();) removeListener(itr.next()); _addListeners.clear(); _remListeners.clear(); _exceps.clear(); } return ret; } /** * Make callbacks, recording any exceptions in the given collection. */ private void makeCallbacks(Object source, Object related, ClassMetaData meta, int type, Collection exceptions) { // make lifecycle callbacks LifecycleCallbacks[] callbacks = meta.getLifecycleMetaData(). getCallbacks(type); for (int i = 0; !_fail && i < callbacks.length; i++) { try { callbacks[i].makeCallback(source, related, type); } catch (Exception e) { exceptions.add(e); if (_failFast) _fail = true; } } } /** * Fire an event with the given source and type to the given list of * listeners. The event may have already been constructed. */ private Object fireEvent(LifecycleEvent ev, Object source, Object rel, int type, ListenerList listeners, boolean mock, List exceptions) { if (listeners == null || !listeners.hasListeners(type)) return null; Object listener; boolean responds; for (int i = 0, size = listeners.size(); !_fail && i < size; i++) { listener = listeners.get(i); if (size == 1) responds = true; else if (listener instanceof ListenerAdapter) { responds = ((ListenerAdapter) listener).respondsTo(type); if (!responds) continue; } else { responds = false; } try { switch (type) { case LifecycleEvent.BEFORE_CLEAR: case LifecycleEvent.AFTER_CLEAR: if (responds || listener instanceof ClearListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, type); if (type == LifecycleEvent.BEFORE_CLEAR) ((ClearListener) listener).beforeClear(ev); else ((ClearListener) listener).afterClear(ev); } break; case LifecycleEvent.BEFORE_PERSIST: case LifecycleEvent.AFTER_PERSIST: if (responds || listener instanceof PersistListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, type); if (type == LifecycleEvent.BEFORE_PERSIST) ((PersistListener) listener).beforePersist(ev); else ((PersistListener) listener).afterPersist(ev); } break; case LifecycleEvent.BEFORE_DELETE: case LifecycleEvent.AFTER_DELETE: if (responds || listener instanceof DeleteListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, type); if (type == LifecycleEvent.BEFORE_DELETE) ((DeleteListener) listener).beforeDelete(ev); else ((DeleteListener) listener).afterDelete(ev); } break; case LifecycleEvent.BEFORE_DIRTY: case LifecycleEvent.AFTER_DIRTY: case LifecycleEvent.BEFORE_DIRTY_FLUSHED: case LifecycleEvent.AFTER_DIRTY_FLUSHED: if (responds || listener instanceof DirtyListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, type); switch (type) { case LifecycleEvent.BEFORE_DIRTY: ((DirtyListener) listener).beforeDirty(ev); break; case LifecycleEvent.AFTER_DIRTY: ((DirtyListener) listener).afterDirty(ev); break; case LifecycleEvent.BEFORE_DIRTY_FLUSHED: ((DirtyListener) listener) .beforeDirtyFlushed(ev); break; case LifecycleEvent.AFTER_DIRTY_FLUSHED: ((DirtyListener) listener) .afterDirtyFlushed(ev); break; } } break; case LifecycleEvent.AFTER_LOAD: case LifecycleEvent.AFTER_REFRESH: if (responds || listener instanceof LoadListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, type); if (type == LifecycleEvent.AFTER_LOAD) ((LoadListener) listener).afterLoad(ev); else ((LoadListener) listener).afterRefresh(ev); } break; case LifecycleEvent.BEFORE_STORE: case LifecycleEvent.AFTER_STORE: if (responds || listener instanceof StoreListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, type); if (type == LifecycleEvent.BEFORE_STORE) ((StoreListener) listener).beforeStore(ev); else ((StoreListener) listener).afterStore(ev); } break; case LifecycleEvent.BEFORE_DETACH: case LifecycleEvent.AFTER_DETACH: if (responds || listener instanceof DetachListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, rel, type); if (type == LifecycleEvent.BEFORE_DETACH) ((DetachListener) listener).beforeDetach(ev); else ((DetachListener) listener).afterDetach(ev); } break; case LifecycleEvent.BEFORE_ATTACH: case LifecycleEvent.AFTER_ATTACH: if (responds || listener instanceof AttachListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, rel, type); if (type == LifecycleEvent.BEFORE_ATTACH) ((AttachListener) listener).beforeAttach(ev); else ((AttachListener) listener).afterAttach(ev); } break; case LifecycleEvent.AFTER_PERSIST_PERFORMED: if (responds || listener instanceof PostPersistListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, rel, type); ((PostPersistListener) listener).afterPersistPerformed(ev); } break; case LifecycleEvent.BEFORE_UPDATE: case LifecycleEvent.AFTER_UPDATE_PERFORMED: if (responds || listener instanceof UpdateListener) { if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, rel, type); if (type == LifecycleEvent.BEFORE_UPDATE) ((UpdateListener) listener).beforeUpdate(ev); else ((UpdateListener) listener).afterUpdatePerformed(ev); } break; case LifecycleEvent.AFTER_DELETE_PERFORMED: if (responds || listener instanceof PostDeleteListener){ if (mock) return Boolean.TRUE; if (ev == null) ev = new LifecycleEvent(source, rel, type); ((PostDeleteListener) listener).afterDeletePerformed(ev); } break; default: throw new InvalidStateException(_loc.get("unknown-lifecycle-event", Integer.toString(type))); } } catch (Exception e) { exceptions.add(e); if (_failFast) _fail = true; } } return ev; } /** * Interface that facades to other lifecycle listener interfaces can * implement to choose which events to respond to based on their delegate. * This is more efficient than registering as a listener for all events * but only responding to some. */ public static interface ListenerAdapter { /** * Return whether this instance responds to the given event type from * {@link LifecycleEvent}. */ public boolean respondsTo(int eventType); } /** * Extended list that tracks what event types its elements care about. * Maintains set semantics as well. */ public static class ListenerList extends ArrayList { private int _types = 0; public ListenerList(int size) { super(size); } public ListenerList(ListenerList copy) { super(copy); _types = copy._types; } public boolean hasListeners(int type) { return (_types & (2 << type)) > 0; } public boolean add(Object listener) { if (contains(listener)) return false; super.add(listener); _types |= getEventTypes(listener); return true; } public boolean remove(Object listener) { if (!super.remove(listener)) return false; // recompute types mask _types = 0; for (int i = 0; i < size(); i++) _types |= getEventTypes(get(i)); return true; } /** * Return a mask of the event types the given listener processes. */ private static int getEventTypes(Object listener) { int types = 0; if (listener instanceof ListenerAdapter) { ListenerAdapter adapter = (ListenerAdapter) listener; for (int i = 0; i < LifecycleEvent.ALL_EVENTS.length; i++) if (adapter.respondsTo(LifecycleEvent.ALL_EVENTS[i])) types |= 2 << LifecycleEvent.ALL_EVENTS[i]; return types; } if (listener instanceof PersistListener) { types |= 2 << LifecycleEvent.BEFORE_PERSIST; types |= 2 << LifecycleEvent.AFTER_PERSIST; } if (listener instanceof ClearListener) { types |= 2 << LifecycleEvent.BEFORE_CLEAR; types |= 2 << LifecycleEvent.AFTER_CLEAR; } if (listener instanceof DeleteListener) { types |= 2 << LifecycleEvent.BEFORE_DELETE; types |= 2 << LifecycleEvent.AFTER_DELETE; } if (listener instanceof DirtyListener) { types |= 2 << LifecycleEvent.BEFORE_DIRTY; types |= 2 << LifecycleEvent.AFTER_DIRTY; types |= 2 << LifecycleEvent.BEFORE_DIRTY_FLUSHED; types |= 2 << LifecycleEvent.AFTER_DIRTY_FLUSHED; } if (listener instanceof LoadListener) { types |= 2 << LifecycleEvent.AFTER_LOAD; types |= 2 << LifecycleEvent.AFTER_REFRESH; } if (listener instanceof StoreListener) { types |= 2 << LifecycleEvent.BEFORE_STORE; types |= 2 << LifecycleEvent.AFTER_STORE; } if (listener instanceof DetachListener) { types |= 2 << LifecycleEvent.BEFORE_DETACH; types |= 2 << LifecycleEvent.AFTER_DETACH; } if (listener instanceof AttachListener) { types |= 2 << LifecycleEvent.BEFORE_ATTACH; types |= 2 << LifecycleEvent.AFTER_ATTACH; } return types; } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/FlushTransactionListener.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/FlushTransactionListener.ja0000644000000000000000000000255212133327272030450 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Notified on transaction flush. * * @author Patrick Linskey * @author Abe White * @since 0.2.5.0 */ public interface FlushTransactionListener { /** * Notification that a transaction is about to flush all object changes. * * @see TransactionEvent#BEFORE_FLUSH */ public void beforeFlush(TransactionEvent event); /** * Notification that a transaction has flushed all object changes. * * @see TransactionEvent#AFTER_FLUSH */ public void afterFlush(TransactionEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/ClearListener.java0000644000000000000000000000227612133327272026541 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Listener for when persistent state is cleared from an instance. * * @author Steve Kim * @author Abe White */ public interface ClearListener { /** * Invoked before state is cleared. */ public void beforeClear(LifecycleEvent event); /** * Invoked after state is cleared. */ public void afterClear(LifecycleEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/PostPersistListener.java0000644000000000000000000000233312133327272030004 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * @since 1.1.0 */ public interface PostPersistListener { /** * Receives notifications after a persist operation has been written to the * data store. Differs from {@link PersistListener#afterPersist} in that * the latter is called at the end of the persist() operation itself, not * after the flush. */ public void afterPersistPerformed(LifecycleEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEvent.java0000644000000000000000000001541212133327272027407 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Collection; import java.util.Collections; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * Event type to hold the IDs of additions, updates, and * deletes. This event type is also fully serializable for remote communication. * * @since 0.3.0 * @author Patrick Linskey * @author Abe White */ public class RemoteCommitEvent implements Externalizable { /** * Names of added classes, updated and deleted Object IDs. */ public static final int PAYLOAD_OIDS = 0; /** * Names of added classes, added, updated and deleted Object IDs. */ public static final int PAYLOAD_OIDS_WITH_ADDS = 1; /** * Names of added, updated, and deleted classes only. */ public static final int PAYLOAD_EXTENTS = 2; /** * The local {@link BrokerFactory} detected that local data is out of date * with the data store. Stale object IDs will be in t he updated set, * although it is possible that records were actually deleted, rather than * updated. * * @since 1.0.0 */ public static final int PAYLOAD_LOCAL_STALE_DETECTION = 3; private static final Localizer s_loc = Localizer.forPackage (RemoteCommitEvent.class); private int _payload = PAYLOAD_OIDS; private Collection _addIds = null; private Collection _addClasses = null; private Collection _updates = null; private Collection _deletes = null; /** * Constructor used during externalization. */ public RemoteCommitEvent() { } /** * Constructor. All collections will be proxied with unmodifiable views. * * @param payloadType PAYLOAD constant for type of data in this event * @param addIds set of object IDs for added instances, or null * @param addClasses set of class names for added instances * @param updates set of class names or object IDs for updated instances * @param deletes set of class names or object IDs for deleted instances */ public RemoteCommitEvent(int payloadType, Collection addIds, Collection addClasses, Collection updates, Collection deletes) { _payload = payloadType; if (addIds != null) _addIds = Collections.unmodifiableCollection(addIds); if (addClasses != null) _addClasses = Collections.unmodifiableCollection(addClasses); if (updates != null) _updates = Collections.unmodifiableCollection(updates); if (deletes != null) _deletes = Collections.unmodifiableCollection(deletes); } /** * The event PAYLOAD constant. */ public int getPayloadType() { return _payload; } /** * When the event type is PAYLOAD_OIDS_WITH_ADDS, return the set of * object IDs for added objects. This will only be callable when the * backward compatability property transmitAddObjectIds is true. */ public Collection getPersistedObjectIds() { if (_payload != PAYLOAD_OIDS_WITH_ADDS) { if (_payload == PAYLOAD_OIDS) throw new UserException(s_loc.get("no-added-oids")); throw new UserException(s_loc.get("extent-only-event")); } return (_addIds == null) ? Collections.EMPTY_LIST : _addIds; } /** * When the event type is not PAYLOAD_EXTENTS, return the set of * object IDs for updated objects. When the event type is * PAYLOAD_LOCAL_STALE_DETECTION, items in this list may actually have * been deleted from the database. */ public Collection getUpdatedObjectIds() { if (_payload == PAYLOAD_EXTENTS) throw new UserException(s_loc.get("extent-only-event")); return (_updates == null) ? Collections.EMPTY_LIST : _updates; } /** * When the event type is not PAYLOAD_EXTENTS, return the set of * object IDs for deleted objects. */ public Collection getDeletedObjectIds() { if (_payload == PAYLOAD_EXTENTS) throw new UserException(s_loc.get("extent-only-event")); return (_deletes == null) ? Collections.EMPTY_LIST : _deletes; } /** * For all event types, return the set of class names for * the classes of inserted objects. */ public Collection getPersistedTypeNames() { return (_addClasses == null) ? Collections.EMPTY_LIST : _addClasses; } /** * When the event type is PAYLOAD_EXTENTS, return the set of class * names for the classes of updated objects. */ public Collection getUpdatedTypeNames() { if (_payload != PAYLOAD_EXTENTS) throw new UserException(s_loc.get("nonextent-event")); return (_updates == null) ? Collections.EMPTY_LIST : _updates; } /** * When the event type is PAYLOAD_EXTENTS, return the set of class * names for the classes of deleted objects. */ public Collection getDeletedTypeNames() { if (_payload != PAYLOAD_EXTENTS) throw new UserException(s_loc.get("nonextent-event")); return (_deletes == null) ? Collections.EMPTY_LIST : _deletes; } public void writeExternal(ObjectOutput out) throws IOException { out.writeInt(_payload); out.writeObject(_addClasses); if (_payload == PAYLOAD_OIDS_WITH_ADDS) out.writeObject(_addIds); out.writeObject(_updates); out.writeObject(_deletes); } public void readExternal(ObjectInput in) throws IOException { try { _payload = in.readInt(); _addClasses = (Collection) in.readObject(); if (_payload == PAYLOAD_OIDS_WITH_ADDS) _addIds = (Collection) in.readObject(); _updates = (Collection) in.readObject(); _deletes = (Collection) in.readObject(); } catch (ClassNotFoundException cnfe) { // ### do something } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/LoadListener.java0000644000000000000000000000233112133327272026362 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Listener for when state is loaded into a persistent instnace. * * @author Steve Kim * @author Abe White */ public interface LoadListener { /** * Invoked after state has been loaded into the instance. */ public void afterLoad(LifecycleEvent event); /** * Invoked after state has been refreshed. */ public void afterRefresh(LifecycleEvent event); } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEventManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEventManager.j0000644000000000000000000000354612133327272030367 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.conf.OpenJPAConfiguration; /** * {@link EventManager} responsible for notifying listeners of * {@link BrokerFactoryEvent}s. * * @since 1.0.0 */ public class BrokerFactoryEventManager extends AbstractConcurrentEventManager { private static final Localizer _loc = Localizer.forPackage( BrokerFactoryEventManager.class); private final Configuration _conf; public BrokerFactoryEventManager(Configuration conf) { _conf = conf; } protected void fireEvent(Object event, Object listener) { try { BrokerFactoryEvent e = (BrokerFactoryEvent) event; ((BrokerFactoryListener) listener).eventFired(e); } catch (Exception e) { _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME).warn( _loc.get("broker-factory-listener-exception"), e); } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/DetachListener.java0000644000000000000000000000226712133327272026703 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Listener for when a persistent instance is detached. * * @author Steve Kim */ public interface DetachListener { /** * Invoked before the instance is detached. */ public void beforeDetach(LifecycleEvent event); /** * Invoked after the instance has been detached. */ public void afterDetach(LifecycleEvent event); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/ExceptionOrphanedKeyAction.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/ExceptionOrphanedKeyAction.0000644000000000000000000000300212133327272030355 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.ObjectNotFoundException; /** * Throw a {@link ObjectNotFoundException} when an orphaned key is discovered. * * @author Abe White * @since 0.3.2.2 */ public class ExceptionOrphanedKeyAction implements OrphanedKeyAction { private static final Localizer _loc = Localizer.forPackage (ExceptionOrphanedKeyAction.class); public Object orphan(Object oid, OpenJPAStateManager sm, ValueMetaData vmd) { throw new ObjectNotFoundException(_loc.get("orphaned-key", oid, vmd)); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/NoneOrphanedKeyAction.java0000644000000000000000000000232612133327272030170 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.meta.ValueMetaData; /** * Does nothing when an orphaned key is discovered. * * @author Abe White * @since 0.3.2.2 */ public class NoneOrphanedKeyAction implements OrphanedKeyAction { public Object orphan(Object oid, OpenJPAStateManager sm, ValueMetaData vmd) { return null; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/MethodLifecycleCallbacks.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/MethodLifecycleCallbacks.ja0000644000000000000000000001175512133327272030320 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.lang.reflect.Method; import java.security.AccessController; import java.util.Arrays; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * Callback adapter that invokes a callback method via reflection. * * @author Steve Kim */ public class MethodLifecycleCallbacks implements LifecycleCallbacks, Externalizable { private static final Localizer _loc = Localizer.forPackage (MethodLifecycleCallbacks.class); private transient Method _callback; private boolean _arg; /** * Constructor. Supply callback class and its callback method name. * * @arg Whether we expect a further argument such as in AfterDetach */ public MethodLifecycleCallbacks(Class cls, String method, boolean arg) { Class[] args = arg ? new Class[]{ Object.class } : null; _callback = getMethod(cls, method, args); _arg = arg; } /** * Constructor. Supply callback method. */ public MethodLifecycleCallbacks(Method method, boolean arg) { _callback = method; _arg = arg; } /** * The callback method. */ public Method getCallbackMethod() { return _callback; } /** * Returns if this callback expects another argument */ public boolean requiresArgument() { return _arg; } public boolean hasCallback(Object obj, int eventType) { return true; } public void makeCallback(Object obj, Object arg, int eventType) throws Exception { if (!_callback.isAccessible()) AccessController.doPrivileged(J2DoPrivHelper.setAccessibleAction( _callback, true)); if (_arg) _callback.invoke(obj, new Object[]{ arg }); else _callback.invoke(obj, (Object[]) null); } public String toString() { return getClass().getName() + ":" + _callback; } /** * Helper method to return the named method of the given class, throwing * the proper exception on error. */ protected static Method getMethod(Class cls, String method, Class[] args) { Class currentClass = cls; do { Method[] methods = (Method[]) AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodsAction(currentClass)); for (int i = 0; i < methods.length; i++) { if (!method.equals(methods[i].getName())) continue; if (isAssignable(methods[i].getParameterTypes(), args)) return methods[i]; } } while ((currentClass = currentClass.getSuperclass()) != null); // if we get here, no suitable method was found throw new UserException(_loc.get("method-notfound", cls.getName(), method, args == null ? null : Arrays.asList(args))); } /** * Returns true if all parameters in the from array are assignable * from the corresponding parameters of the to array. */ private static boolean isAssignable(Class[] from, Class[] to) { if (from == null) return to == null || to.length == 0; if (to == null) return from == null || from.length == 0; if (from.length != to.length) return false; for (int i = 0; i < from.length; i++) { if (from[i] != null && !from[i].isAssignableFrom(to[i])) return false; } return true; } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { Class cls = (Class) in.readObject(); String methName = (String) in.readObject(); _arg = in.readBoolean(); Class[] args = _arg ? new Class[]{ Object.class } : null; _callback = getMethod(cls, methName, args); } public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(_callback.getClass()); out.writeObject(_callback.getName()); out.writeBoolean(_arg); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/JMSRemoteCommitProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/JMSRemoteCommitProvider.jav0000644000000000000000000002342612133327272030335 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.util.Properties; import javax.jms.ExceptionListener; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.ObjectMessage; import javax.jms.Session; import javax.jms.Topic; import javax.jms.TopicConnection; import javax.jms.TopicConnectionFactory; import javax.jms.TopicPublisher; import javax.jms.TopicSession; import javax.jms.TopicSubscriber; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.GenericConfigurable; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; /** * JMS-based implementation of {@link RemoteCommitProvider} that * listens for object modifications and propagates those changes to * other RemoteCommitProviders over a JMS topic. * * @author Patrick Linskey * @since 0.2.5.0 */ public class JMSRemoteCommitProvider extends AbstractRemoteCommitProvider implements Configurable, GenericConfigurable, ExceptionListener { private static Localizer s_loc = Localizer.forPackage (JMSRemoteCommitProvider.class); private String _topicName = "topic/OpenJPACommitProviderTopic"; private String _tcfName = "java:/ConnectionFactory"; private Properties _ctxProps = null; private int _reconnectAttempts = 0; private TopicConnection _connection; private TopicSession _session; private TopicPublisher _publisher; private ClassLoader _appClassLoader; /** * Sets the JMS Topic name. Defaults to * topic/OpenJPACommitProviderTopic. */ public void setTopic(String name) { _topicName = name; } /** * Sets the JMS TopicConnectionFactory name. Defaults to * java:/ConnectionFactory. */ public void setTopicConnectionFactory(String name) { _tcfName = name; } /** * The number of times to attempt to reconnect after a JMS send exception * is detected. Defaults to 0, meaning no attempt to reconnect is made; * the exception is logged and ignored. */ public void setExceptionReconnectAttempts(int attempts) { _reconnectAttempts = attempts; } /** * Set a map of properties to pass to the {@link InitialContext} * constructor for JNDI lookups. Implementation of * {@link GenericConfigurable}. */ public void setInto(Options opts) { if (opts != null && !opts.isEmpty()) { _ctxProps = new Properties(); _ctxProps.putAll(opts); opts.clear(); } else _ctxProps = null; } /** * Returns a new {@link Context} object for use by this provider. */ protected Context newContext() throws NamingException { if (_ctxProps == null) return new InitialContext(); return new InitialContext(_ctxProps); } // ---------- RemoteCommitProvider implementation ---------- public void broadcast(RemoteCommitEvent event) { try { _publisher.publish(createMessage(event)); if (log.isTraceEnabled()) log.trace(s_loc.get("jms-sent-update", _topicName)); } catch (JMSException jmse) { if (log.isWarnEnabled()) log.warn(s_loc.get("jms-send-error", _topicName), jmse); } } public void close() { try { if (_connection != null) { _connection.close(); if (log.isInfoEnabled()) log.info(s_loc.get("jms-close-listener", _topicName)); } } catch (JMSException jmse) { if (log.isWarnEnabled()) log.warn(s_loc.get("jms-close-error", _topicName), jmse); } finally { _connection = null; } } // ---------- Configurable implementation ---------- /** * Subclasses that need to perform actions in * {@link Configurable#endConfiguration} must invoke this method. */ public void endConfiguration() { super.endConfiguration(); _appClassLoader = Thread.currentThread().getContextClassLoader(); connect(); } protected void connect() { try { Context ctx = newContext(); TopicConnectionFactory tcf = (TopicConnectionFactory) ctx.lookup(_tcfName); Topic topic = (Topic) ctx.lookup(_topicName); ctx.close(); _connection = tcf.createTopicConnection(); // false == not transacted. _session = _connection.createTopicSession (false, Session.AUTO_ACKNOWLEDGE); // create a publisher _publisher = _session.createPublisher(topic); // create a subscriber. TopicSubscriber s = _session.createSubscriber(topic, null, /* noLocal: */ true); MessageListener l = getMessageListener(); s.setMessageListener(l); _connection.start(); _connection.setExceptionListener(this); if (log.isInfoEnabled()) log.info(s_loc.get("jms-start-listener", _topicName)); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new UserException(s_loc.get("jms-provider-config", _topicName, _tcfName), e).setFatal(true); } } /* * * Returns a {@link javax.jms.MessageListener} capable of * understanding and processing messages created by {@link #createMessage}. * The listener returned by this method is responsible for * notifying the provider that a remote event has been received. */ protected MessageListener getMessageListener() { return new MessageListener() { public void onMessage(Message m) { if (!(m instanceof ObjectMessage)) { if (log.isWarnEnabled()) log.warn(s_loc.get("jms-receive-error-3", _topicName, m.getClass().getName())); return; } ClassLoader saveCls = Thread.currentThread() .getContextClassLoader(); try { if (saveCls != _appClassLoader) Thread.currentThread().setContextClassLoader( _appClassLoader); ObjectMessage om = (ObjectMessage) m; Object o = om.getObject(); if (o instanceof RemoteCommitEvent) { if (log.isTraceEnabled()) log.trace(s_loc.get("jms-received-update", _topicName)); RemoteCommitEvent rce = (RemoteCommitEvent) o; fireEvent(rce); } else { if (log.isWarnEnabled()) log.warn(s_loc.get("jms-receive-error-2", o.getClass().getName(), _topicName)); } } catch (JMSException jmse) { if (log.isWarnEnabled()) log.warn(s_loc.get("jms-receive-error-1"), jmse); } finally { if (saveCls != _appClassLoader) Thread.currentThread().setContextClassLoader(saveCls); } } }; } /** * Returns a new {@link Message} to send to the topic. This * implementation creates an {@link ObjectMessage}. */ protected Message createMessage(RemoteCommitEvent event) throws JMSException { return _session.createObjectMessage(event); } public void onException(JMSException ex) { if (log.isWarnEnabled()) log.warn(s_loc.get("jms-listener-error", _topicName), ex); if (_reconnectAttempts <= 0) return; close(); boolean connected = false; for (int i = 0; !connected && i < _reconnectAttempts; i++) { try { if (log.isInfoEnabled()) log.info(s_loc.get("jms-reconnect-attempt", _topicName, String.valueOf(i + 1))); connect(); connected = true; } catch (Exception e) { if (log.isInfoEnabled()) log.info(s_loc.get("jms-reconnect-fail", _topicName), e); try { Thread.sleep(1000); } catch (InterruptedException ie) { break; } } } if (!connected && log.isErrorEnabled()) log.error(s_loc.get("jms-cant-reconnect", _topicName, String.valueOf(_reconnectAttempts))); else if (connected && log.isInfoEnabled()) log.info(s_loc.get("jms-reconnected", _topicName)); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/StoreListener.java0000644000000000000000000000226712133327272026607 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Listener for when persistent instances are stored to the database. * * @author Steve Kim * @author Abe White */ public interface StoreListener { /** * Invoked just prior to store. */ public void beforeStore(LifecycleEvent event); /** * Invoked just after store. */ public void afterStore(LifecycleEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleListener.java0000644000000000000000000000216012133327272027402 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Interface for listening to all {@link LifecycleEvent}s. * * @author Steve Kim * @author Abe White */ public interface LifecycleListener extends PersistListener, LoadListener, StoreListener, ClearListener, DeleteListener, DirtyListener, DetachListener, AttachListener { } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitProvider.java0000644000000000000000000000463212133327272030122 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import org.apache.openjpa.lib.util.Closeable; /** * An entity that is responsible for communicating commit * notification to other {@link RemoteCommitEventManager}s. Each * event manager creates a remote commit provider, based on * the values of the openjpa.RemoteCommitProvider * configuration property. * An adapter that implements {@link TransactionListener} is * registered with each {@link org.apache.openjpa.kernel.Broker}. This adapter * invokes broadcast, which is responsible for * notifying other remote commit provider objects of the commit changes. * Upon receiving a notification from a different remote commit provider, * a provider must notify all local remote commit listeners via the * {@link RemoteCommitEventManager#fireEvent} method. * A remote commit provider must not fire remote events for * commits that originated with a local broker. * * @author Patrick Linskey * @since 0.2.5.0 */ public interface RemoteCommitProvider extends Closeable { /** * Set the "owning" remote event manager to notify when remote events * are received from remote sources. */ public void setRemoteCommitEventManager(RemoteCommitEventManager mgr); /** * Notifies other remote event managers in this JVM and on other machines * of changes to the cache. This method must not notify the * event manager associated with the broker that originated this commit. */ public void broadcast(RemoteCommitEvent event); /** * Free the resources used by this provider. */ public void close(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEvent.java0000644000000000000000000001267212133327272026707 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.util.EventObject; /** * Lifecycle event on a persistent instance. The event source * is the persistent instance whose state has changed. * * @author Steve Kim * @author Abe White * @since 0.3.3 */ public class LifecycleEvent extends EventObject { /** * Event type before an instance is made persistent */ public static final int BEFORE_PERSIST = 0; /** * Event type when an instance is made persistent */ public static final int AFTER_PERSIST = 1; /** * Event type when an instance is made persistent, after the record has * been written to the store */ public static final int AFTER_PERSIST_PERFORMED = 18; /** * Event type when an instance is loaded. */ public static final int AFTER_LOAD = 2; /** * Event type when an instance is stored. */ public static final int BEFORE_STORE = 3; /** * Event type when an instance is stored. */ public static final int AFTER_STORE = 4; /** * Event type when an instance is cleared. */ public static final int BEFORE_CLEAR = 5; /** * Event type when an instance is cleared. */ public static final int AFTER_CLEAR = 6; /** * Event type when an instance is deleted. */ public static final int BEFORE_DELETE = 7; /** * Event type when an instance is deleted. */ public static final int AFTER_DELETE = 8; /** * Event type when an instance is deleted, after the record has been * deleted from the store. */ public static final int AFTER_DELETE_PERFORMED = 19; /** * Event type when an instance is dirtied for the first time. */ public static final int BEFORE_DIRTY = 9; /** * Event type when an instance is dirtied for the first time. */ public static final int AFTER_DIRTY = 10; /** * Event type when an instance is dirtied for the first time after flush. */ public static final int BEFORE_DIRTY_FLUSHED = 11; /** * Event type when an instance is dirtied for the first time after flush. */ public static final int AFTER_DIRTY_FLUSHED = 12; /** * Event type when an instance is detached. */ public static final int BEFORE_DETACH = 13; /** * Event type when an instance is detached. */ public static final int AFTER_DETACH = 14; /** * Event type when an instance is attached. */ public static final int BEFORE_ATTACH = 15; /** * Event type when an instance is attached. */ public static final int AFTER_ATTACH = 16; /** * Event type when an instances is refreshed. */ public static final int AFTER_REFRESH = 17; /** * Event type when an instance is modified. This is not invoked for * PNEW records, but is invoked for PNEWFLUSHED. */ public static final int BEFORE_UPDATE = 20; /** * Event type when an instance is modified, after the change has been * sent to the store. This is not invoked for PNEW records, but is * invoked for PNEWFLUSHED records. */ public static final int AFTER_UPDATE_PERFORMED = 21; /** * Convenience array of all event types. */ public static final int[] ALL_EVENTS = new int[]{ BEFORE_PERSIST, AFTER_PERSIST, AFTER_PERSIST_PERFORMED, AFTER_LOAD, BEFORE_STORE, AFTER_STORE, BEFORE_CLEAR, AFTER_CLEAR, BEFORE_DELETE, AFTER_DELETE, AFTER_DELETE_PERFORMED, BEFORE_DIRTY, AFTER_DIRTY, BEFORE_DIRTY_FLUSHED, AFTER_DIRTY_FLUSHED, BEFORE_DETACH, AFTER_DETACH, BEFORE_ATTACH, AFTER_ATTACH, AFTER_REFRESH, BEFORE_UPDATE, AFTER_UPDATE_PERFORMED, }; private final int _type; private final Object _related; /** * Constructor. * * @param pc the persistent instance that triggered the event * @param type the event type */ public LifecycleEvent(Object pc, int type) { this(pc, null, type); } /** * Constructor. * * @param pc the persistent instance that triggered the event * @param type the event type * @param related the related instance such as the detached copy. */ public LifecycleEvent(Object pc, Object related, int type) { super(pc); _type = type; _related = related; } /** * Return the event type. */ public int getType() { return _type; } /** * Return the related object. */ public Object getRelated () { return _related; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/UpdateListener.java0000644000000000000000000000310212133327272026722 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * @since 1.1.0 */ public interface UpdateListener { /** * Receives notifications before an update is performed. Differs from * {@link StoreListener#beforeStore} in that the latter is called for * updated and new records, whereas this is only invoked for updated * records. */ public void beforeUpdate(LifecycleEvent event); /** * Receives notifications before an update is performed. Differs from * {@link StoreListener#afterStore} in that the latter is called for * updated and new records, whereas this is only invoked for updated * records, and that this is called after the record is actually flushed * to the store. */ public void afterUpdatePerformed(LifecycleEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitListener.java0000644000000000000000000000420512133327272030111 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import org.apache.openjpa.lib.util.Closeable; /** * An entity that wishes to be notified when Brokers * associated with remote BrokerFactories commit. * A RemoteCommitListener is not notified of commits that originated * with a Broker created from the BrokerFactory that it is * registered with. (Of course, if a listener is registered with multiple * factories, this situation might be complicated a bit.) * Usage: *
     import org.apache.openjpa.event.*;
     * import org.apache.openjpa.conf.*;
     * 
     * {@link org.apache.openjpa.conf.OpenJPAConfiguration} conf =
     *         factory.getConfiguraiton ();
     *  RemoteCommitListener l = new RemoteCommitListener () {
     * public void afterCommit ({@link RemoteCommitEvent} e) {
     * // update a Swing widget when remote brokers make
     * // changes to reference data }
     *  public void close () { } };
     *  conf.getRemoteCommitEventManager ().addListener (l);
     * 
    * * * @author Patrick Linskey * @since 0.2.5.0 */ public interface RemoteCommitListener extends Closeable { /** * Notification that a transaction associated with a different * BrokerFactory has successfully committed. */ public void afterCommit(RemoteCommitEvent event); /** * Free the resources used by this listener. */ public void close(); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/AttachListener.java0000644000000000000000000000226512133327272026715 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Listener for when a detached instance is attached. * * @author Steve Kim */ public interface AttachListener { /** * Invoked before the instance is attached. */ public void beforeAttach(LifecycleEvent event); /** * Invoked after the instance has been attached. */ public void afterAttach(LifecycleEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/TransactionListener.java0000644000000000000000000000213412133327272027771 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Interface for listening to all {@link TransactionEvent}s. * * @author Patrick Linskey * @author Abe White * @since 0.2.5.0 */ public interface TransactionListener extends BeginTransactionListener, FlushTransactionListener, EndTransactionListener { } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/PostDeleteListener.java0000644000000000000000000000237212133327272027560 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * @since 1.1.0 */ public interface PostDeleteListener { /** * Receives notifications before an update is performed. Differs from * {@link DeleteListener#afterDelete(LifecycleEvent)} in that the latter * is called after the delete operation, whereas this is called after the * delete statements have been sent to the data store. */ public void afterDeletePerformed(LifecycleEvent event); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleCallbacks.java0000644000000000000000000000256612133327272027506 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.io.Serializable; /** * A lifecycle listener that responds to callbacks rather than events. * * @author Steve Kim */ public interface LifecycleCallbacks extends Serializable { /** * Return whether the given instance has a callback for the given * event type. */ public boolean hasCallback(Object obj, int eventType); /** * Invoke the callback for the given event type on the given instance. */ public void makeCallback(Object obj, Object related, int eventType) throws Exception; } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/TransactionEvent.java0000644000000000000000000001145412133327272027272 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.util.Collection; import java.util.Collections; import java.util.EventObject; import org.apache.openjpa.kernel.Broker; /** * A transactional event. The event source is the {@link Broker} whose * transaction state changed. * * @since 0.3.0 * @author Abe White */ public class TransactionEvent extends EventObject { /** * Event type signifying that a transaction has just begun. */ public static final int AFTER_BEGIN = 0; /** * Event type signifying that changes are about to be flushed to the * datastore. This does not necessarily mean that a commit is taking place. */ public static final int BEFORE_FLUSH = 1; /** * Event type signifying that changes have been flushed to the datastore. * This event is only fired if flushing is successful. */ public static final int AFTER_FLUSH = 2; /** * Event type signifying that the transaction is about to be committed. * This will be fired before the {@link #BEFORE_FLUSH} event for the * transaction, so that you can differentiate between flushes for commits * and other flushes. */ public static final int BEFORE_COMMIT = 3; /** * Event type signifying that the transaction has committed. */ public static final int AFTER_COMMIT = 4; /** * Event type signifying that the transaction was rolled back. */ public static final int AFTER_ROLLBACK = 5; /** * Event type signifying that all state transitions have been made. */ public static final int AFTER_STATE_TRANSITIONS = 6; /** * Event type signifying that the commit has completey ended and the * transaction is no longer active. */ public static final int AFTER_COMMIT_COMPLETE = 7; /** * Event type signifying that the rollback has completey ended and the * transaction is no longer active. */ public static final int AFTER_ROLLBACK_COMPLETE = 8; private final int _type; private transient final Collection _objs; private transient final Collection _addClss; private transient final Collection _updateClss; private transient final Collection _deleteClss; /** * Constructor. * * @param broker the event source * @param type the event type * @param objs transactional objects * @param addClss classes of added instances * @param updateClss classes of updated instances * @param deleteClss classes of deleted instances */ public TransactionEvent(Broker broker, int type, Collection objs, Collection addClss, Collection updateClss, Collection deleteClss) { super(broker); _type = type; _objs = (objs == null) ? Collections.EMPTY_LIST : objs; _addClss = (addClss == null) ? Collections.EMPTY_SET : addClss; _updateClss = (updateClss == null) ? Collections.EMPTY_SET : updateClss; _deleteClss = (deleteClss == null) ? Collections.EMPTY_SET : deleteClss; } /** * Return the type of event. */ public int getType() { return _type; } /** * Return the unmodifiable set of persistence capable objects * participating in the transaction. This set will contain all dirty * objects, but may not contain clean objects. */ public Collection getTransactionalObjects() { return _objs; } /** * Return the unmodifiable the set of classes of * persistence capable objects that were created in the transaction. */ public Collection getPersistedTypes() { return _addClss; } /** * Return the unmodifiable the set of classes of * persistence capable objects that were modified in the transaction. */ public Collection getUpdatedTypes() { return _updateClss; } /** * Return the unmodifiable the set of classes of * persistence capable objects that were deleted in the transaction. */ public Collection getDeletedTypes () { return _deleteClss; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/EndTransactionListener.java0000644000000000000000000000432212133327272030421 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Notified when transactions end. * * @author Patrick Linskey * @author Abe White * @since 0.2.5.0 */ public interface EndTransactionListener { /** * Notification that the next flush is for the transaction commit. * * @see TransactionEvent#BEFORE_COMMIT */ public void beforeCommit(TransactionEvent event); /** * Notification that a transaction has successfully committed. * * @see TransactionEvent#AFTER_COMMIT */ public void afterCommit(TransactionEvent event); /** * Notification that a transaction has been rolled back. * * @see TransactionEvent#AFTER_ROLLBACK */ public void afterRollback(TransactionEvent event); /** * Notification that state transitions are complete. * * @see TransactionEvent#AFTER_STATE_TRANSITIONS */ public void afterStateTransitions(TransactionEvent event); /** * Notification that a transaction has successfully committed and * the transaction is no longer active. * * @see TransactionEvent#AFTER_COMMIT_COMPLETE */ public void afterCommitComplete(TransactionEvent event); /** * Notification that a transaction has been rolled back and * the transaction is no longer active. * * @see TransactionEvent#AFTER_ROLLBACK_COMPLETE */ public void afterRollbackComplete(TransactionEvent event); } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/AbstractRemoteCommitProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/AbstractRemoteCommitProvide0000644000000000000000000000444112133327272030502 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.util.Arrays; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; /** * Abstract implementation of {@link RemoteCommitProvider}. Obtains handles * to the event manager and log. * * @author Patrick Linskey * @since 0.2.5.0 */ public abstract class AbstractRemoteCommitProvider implements RemoteCommitProvider, Configurable { private static final Localizer _loc = Localizer.forPackage (AbstractRemoteCommitProvider.class); protected RemoteCommitEventManager eventManager; protected Log log; public void setConfiguration(Configuration config) { this.log = config.getLog(OpenJPAConfiguration.LOG_RUNTIME); } public void startConfiguration() { } public void endConfiguration() { } public void setRemoteCommitEventManager(RemoteCommitEventManager mgr) { eventManager = mgr; } /** * Fire a remote commit event via the cached event manager. */ protected void fireEvent(RemoteCommitEvent event) { Exception[] es = eventManager.fireEvent(event); if (es.length > 0 && log.isWarnEnabled()) log.warn(_loc.get("remote-listener-ex", Arrays.asList(es))); if (log.isTraceEnabled()) for (int i = 0; i < es.length; i++) log.trace(es[i]); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/PersistListener.java0000644000000000000000000000224612133327272027141 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Listener for newly-persisted instances. * * @author Steve Kim */ public interface PersistListener { /** * Invoked before an instance is persisted. */ public void beforePersist(LifecycleEvent event); /** * Invoked when an instance is persisted. */ public void afterPersist(LifecycleEvent event); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/TransactionEventManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/TransactionEventManager.jav0000644000000000000000000001110112133327272030411 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager; /** * Manager that can be used to track and notify transaction listeners * of transaction-related events. * * @author Patrick Linskey * @author Abe White * @since 0.3.0 * @nojavadoc */ public class TransactionEventManager extends AbstractConcurrentEventManager { private int _begin = 0; private int _flush = 0; private int _end = 0; public void addListener(Object listener) { super.addListener(listener); if (listener instanceof BeginTransactionListener) _begin++; if (listener instanceof FlushTransactionListener) _flush++; if (listener instanceof EndTransactionListener) _end++; } public boolean removeListener(Object listener) { if (!super.removeListener(listener)) return false; if (listener instanceof BeginTransactionListener) _begin--; if (listener instanceof FlushTransactionListener) _flush--; if (listener instanceof EndTransactionListener) _end--; return true; } /** * Whether there are any begin transaction listeners. */ public boolean hasBeginListeners() { return _begin > 0; } /** * Whether there are any flush transaction listeners. */ public boolean hasFlushListeners() { return _flush > 0; } /** * Whether there are any end transaction listeners. */ public boolean hasEndListeners() { return _end > 0; } /** * Fire the given event to all registered listeners. */ protected void fireEvent(Object event, Object listener) { TransactionEvent ev = (TransactionEvent) event; switch (ev.getType()) { case TransactionEvent.AFTER_BEGIN: if (listener instanceof BeginTransactionListener) ((BeginTransactionListener) listener).afterBegin(ev); break; case TransactionEvent.BEFORE_FLUSH: if (listener instanceof FlushTransactionListener) ((FlushTransactionListener) listener).beforeFlush(ev); break; case TransactionEvent.AFTER_FLUSH: if (listener instanceof FlushTransactionListener) ((FlushTransactionListener) listener).afterFlush(ev); break; case TransactionEvent.BEFORE_COMMIT: if (listener instanceof EndTransactionListener) ((EndTransactionListener) listener).beforeCommit(ev); break; case TransactionEvent.AFTER_COMMIT: if (listener instanceof EndTransactionListener) ((EndTransactionListener) listener).afterCommit(ev); break; case TransactionEvent.AFTER_ROLLBACK: if (listener instanceof EndTransactionListener) ((EndTransactionListener) listener).afterRollback(ev); break; case TransactionEvent.AFTER_STATE_TRANSITIONS: if (listener instanceof EndTransactionListener) ((EndTransactionListener) listener) .afterStateTransitions(ev); break; case TransactionEvent.AFTER_COMMIT_COMPLETE: if (listener instanceof EndTransactionListener) ((EndTransactionListener) listener).afterCommitComplete(ev); break; case TransactionEvent.AFTER_ROLLBACK_COMPLETE: if (listener instanceof EndTransactionListener) ((EndTransactionListener) listener) .afterRollbackComplete(ev); break; } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/DirtyListener.java0000644000000000000000000000276112133327272026605 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Listener for when a persistent instance becomes dirty. * * @author Steve Kim * @author Abe White */ public interface DirtyListener { /** * Invoked before the first change is applied. */ public void beforeDirty(LifecycleEvent event); /** * Invoked after the first change is applied. */ public void afterDirty(LifecycleEvent event); /** * Invoked before the first change is applied to a flushed instance. */ public void beforeDirtyFlushed(LifecycleEvent event); /** * Invoked after the first change is applied to a flushed instance. */ public void afterDirtyFlushed(LifecycleEvent event); } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/AbstractLifecycleListener.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/AbstractLifecycleListener.j0000644000000000000000000000546112133327272030405 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Abstract implementation of the {@link LifecycleListener} interface * which delegates events to a single method. * * @author Steve Kim * @author Abe White */ public abstract class AbstractLifecycleListener implements LifecycleListener { /** * Should be implemented to handle the specific lifecycle event. */ protected void eventOccurred(LifecycleEvent event) { } public void beforePersist(LifecycleEvent event) { eventOccurred(event); } public void afterPersist(LifecycleEvent event) { eventOccurred(event); } public void beforeClear(LifecycleEvent event) { eventOccurred(event); } public void afterClear(LifecycleEvent event) { eventOccurred(event); } public void afterLoad(LifecycleEvent event) { eventOccurred(event); } public void beforeDelete(LifecycleEvent event) { eventOccurred(event); } public void afterDelete(LifecycleEvent event) { eventOccurred(event); } public void beforeStore(LifecycleEvent event) { eventOccurred(event); } public void afterStore(LifecycleEvent event) { eventOccurred(event); } public void beforeDirty(LifecycleEvent event) { eventOccurred(event); } public void afterDirty(LifecycleEvent event) { eventOccurred(event); } public void beforeDirtyFlushed(LifecycleEvent event) { eventOccurred(event); } public void afterDirtyFlushed(LifecycleEvent event) { eventOccurred(event); } public void afterRefresh(LifecycleEvent event) { eventOccurred(event); } public void beforeDetach(LifecycleEvent event) { eventOccurred(event); } public void afterDetach(LifecycleEvent event) { eventOccurred(event); } public void beforeAttach(LifecycleEvent event) { eventOccurred(event); } public void afterAttach(LifecycleEvent event) { eventOccurred(event); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEventManager.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEventManager.ja0000644000000000000000000002036512133327272030356 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Collections; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager; import org.apache.openjpa.util.UserException; /** * Manager that can be used to track and notify * {@link RemoteCommitListener}s on remote commit events. If remote events * are enabled, this manager should be installed as a transaction listener on * all brokers so that it knows when commits are made. * * @author Patrick Linskey * @author Abe White * @since 0.3.0 */ public class RemoteCommitEventManager extends AbstractConcurrentEventManager implements EndTransactionListener, Closeable { private static final Localizer _loc = Localizer.forPackage (RemoteCommitEventManager.class); private final RemoteCommitProvider _provider; private boolean _transmitPersIds = false; /** * Constructor. Supply configuration. */ public RemoteCommitEventManager(OpenJPAConfiguration conf) { _provider = conf.newRemoteCommitProviderInstance(); if (_provider != null) { _provider.setRemoteCommitEventManager(this); } } /** * Return true if remote events are enabled. */ public boolean areRemoteEventsEnabled() { return _provider != null; } /** * Return the {@link RemoteCommitProvider} that this manager uses. * * @since 0.3.1 */ public RemoteCommitProvider getRemoteCommitProvider() { return _provider; } /** * Whether the oids of added instances will be transmitted. */ public boolean getTransmitPersistedObjectIds() { return _transmitPersIds; } /** * Whether the oids of added instances will be transmitted. */ public void setTransmitPersistedObjectIds(boolean transmit) { _transmitPersIds = transmit; } /** * Adds an OpenJPA-internal listener to this RemoteCommitEventManager. * Listeners so registered will be fired before any that are registered * via {@link #addListener}. This means that the external listeners can * rely on internal caches and data structures being up-to-date by the * time that they are invoked. * * @since 1.0.0 */ public void addInternalListener(RemoteCommitListener listen) { if (_provider == null) throw new UserException(_loc.get("no-provider")); ((List) _listeners).add(0, listen); } public void addListener(RemoteCommitListener listen) { if (_provider == null) throw new UserException(_loc.get("no-provider")); super.addListener(listen); } /** * Close this manager and all registered listeners. */ public void close() { if (_provider != null) { _provider.close(); Collection listeners = getListeners(); for (Iterator itr = listeners.iterator(); itr.hasNext();) ((RemoteCommitListener) itr.next()).close(); } } protected void fireEvent(Object event, Object listener) { RemoteCommitListener listen = (RemoteCommitListener) listener; RemoteCommitEvent ev = (RemoteCommitEvent) event; listen.afterCommit(ev); } /** * Fire an event to local listeners only notifying them of a detected * stale record. * * @since 1.0.0 */ public void fireLocalStaleNotification(Object oid) { RemoteCommitEvent ev = new RemoteCommitEvent( RemoteCommitEvent.PAYLOAD_LOCAL_STALE_DETECTION, null, null, Collections.singleton(oid), null); fireEvent(ev); } ////////////////////////////////////// // TransactionListener implementation ////////////////////////////////////// public void afterCommit(TransactionEvent event) { if (_provider != null) { RemoteCommitEvent rce = createRemoteCommitEvent(event); if (rce != null) _provider.broadcast(rce); } } /** * Create a remote commit event from the given transaction event. */ private RemoteCommitEvent createRemoteCommitEvent(TransactionEvent event) { Broker broker = (Broker) event.getSource(); int payload; Collection persIds = null; Collection addClassNames = null; Collection updates = null; Collection deletes = null; if (broker.isTrackChangesByType()) { payload = RemoteCommitEvent.PAYLOAD_EXTENTS; addClassNames = toClassNames(event.getPersistedTypes()); updates = toClassNames(event.getUpdatedTypes()); deletes = toClassNames(event.getDeletedTypes()); if (addClassNames == null && updates == null && deletes == null) return null; } else { Collection trans = event.getTransactionalObjects(); if (trans.isEmpty()) return null; payload = (_transmitPersIds) ? RemoteCommitEvent.PAYLOAD_OIDS_WITH_ADDS : RemoteCommitEvent.PAYLOAD_OIDS; Object oid; Object obj; OpenJPAStateManager sm; for (Iterator itr = trans.iterator(); itr.hasNext();) { obj = itr.next(); sm = broker.getStateManager(obj); if (sm == null || !sm.isPersistent() || !sm.isDirty()) continue; if (sm.isNew() && sm.isDeleted()) continue; oid = sm.fetchObjectId(); if (sm.isNew()) { if (_transmitPersIds) { if (persIds == null) persIds = new ArrayList(); persIds.add(oid); } if (addClassNames == null) addClassNames = new HashSet(); addClassNames.add(obj.getClass().getName()); } else if (sm.isDeleted()) { if (deletes == null) deletes = new ArrayList(); deletes.add(oid); } else { if (updates == null) updates = new ArrayList(); updates.add(oid); } } if (addClassNames == null && updates == null && deletes == null) return null; } return new RemoteCommitEvent(payload, persIds, addClassNames, updates, deletes); } /** * Transform a collection of classes to class names. */ private static Collection toClassNames(Collection clss) { if (clss.isEmpty()) return null; List names = new ArrayList(clss); for (int i = 0; i < names.size(); i++) names.set(i, ((Class) names.get(i)).getName()); return names; } public void beforeCommit(TransactionEvent event) { } public void afterRollback(TransactionEvent event) { } public void afterCommitComplete(TransactionEvent event) { } public void afterRollbackComplete(TransactionEvent event) { } public void afterStateTransitions(TransactionEvent event) { } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/DeleteListener.java0000644000000000000000000000235312133327272026711 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; /** * Listener for when a persistent instance is deleted. * * @author Steve Kim * @author Abe White */ public interface DeleteListener { /** * Invoked before the instance transferred to a deleted state. */ public void beforeDelete(LifecycleEvent event); /** * Invoked after the instance transferred to a deleted state. */ public void afterDelete(LifecycleEvent event); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/TCPRemoteCommitProvider.javaopenjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/TCPRemoteCommitProvider.jav0000644000000000000000000010330412133327272030324 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.List; import java.util.Collections; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericObjectPool; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.Serialization; import java.util.concurrent.locks.ReentrantLock; import serp.util.Strings; /** * TCP-based implementation of {@link RemoteCommitProvider} that * listens for object modifications and propagates those changes to * other RemoteCommitProviders over TCP sockets. * * @author Brian Leair * @author Patrick Linskey * @since 0.2.5.0 */ public class TCPRemoteCommitProvider extends AbstractRemoteCommitProvider implements Configurable { private static final int DEFAULT_PORT = 5636; private static final Localizer s_loc = Localizer.forPackage (TCPRemoteCommitProvider.class); private static long s_idSequence = System.currentTimeMillis(); // A map of listen ports to listeners in this JVM. We might // want to look into allowing same port, different interface -- // that is not currently possible in a single JVM. private static final Map s_portListenerMap = new HashMap(); private long _id; private byte[] _localhost; private int _port = DEFAULT_PORT; private int _maxActive = 2; private int _maxIdle = 2; private int _recoveryTimeMillis = 15000; private TCPPortListener _listener; private BroadcastQueue _broadcastQueue = new BroadcastQueue(); private final List _broadcastThreads = Collections.synchronizedList( new LinkedList()); private ArrayList _addresses = new ArrayList(); private ReentrantLock _addressesLock; public TCPRemoteCommitProvider() throws UnknownHostException { // obtain a unique ID. synchronized (TCPRemoteCommitProvider.class) { _id = s_idSequence++; } // cache the local IP address. _localhost = InetAddress.getLocalHost().getAddress(); _addressesLock = new ReentrantLock(); setNumBroadcastThreads(2); } /** * The port that this provider should listen on. */ public int getPort() { return _port; } /** * The port that this provider should listen on. Set once only. */ public void setPort(int port) { _port = port; } /** * The number of milliseconds to wait before retrying * to reconnect to a peer after it becomes unreachable. */ public void setRecoveryTimeMillis(int recoverytime) { _recoveryTimeMillis = recoverytime; } /** * The number of milliseconds to wait before retrying * to reconnect to a peer after it becomes unreachable. */ public int getRecoveryTimeMillis() { return _recoveryTimeMillis; } /** * The maximum number of sockets that this provider can * simetaneously open to each peer in the cluster. */ public void setMaxActive(int maxActive) { _maxActive = maxActive; } /** * The maximum number of sockets that this provider can * simetaneously open to each peer in the cluster. */ public int getMaxActive() { return _maxActive; } /** * The number of idle sockets that this provider can keep open * to each peer in the cluster. */ public void setMaxIdle(int maxIdle) { _maxIdle = maxIdle; } /** * The number of idle sockets that this provider can keep open * to each peer in the cluster. */ public int getMaxIdle() { return _maxIdle; } /** * The number of worker threads that are used for * transmitting packets to peers in the cluster. */ public void setNumBroadcastThreads(int numBroadcastThreads) { synchronized (_broadcastThreads) { int cur = _broadcastThreads.size(); if (cur > numBroadcastThreads) { // Notify the extra worker threads so they stop themselves // Threads will not end until they send another pk. for (int i = numBroadcastThreads; i < cur; i++) { BroadcastWorkerThread worker = (BroadcastWorkerThread) _broadcastThreads.remove(0); worker.setRunning(false); } } else if (cur < numBroadcastThreads) { // Create additional worker threads for (int i = cur; i < numBroadcastThreads; i++) { BroadcastWorkerThread wt = new BroadcastWorkerThread(); wt.setDaemon(true); wt.start(); _broadcastThreads.add(wt); } } } } /** * The number of worker threads that are used for * transmitting packets to peers in the cluster. */ public int getNumBroadcastThreads() { return _broadcastThreads.size(); } /** * Sets the list of addresses of peers to which this provider will * send events to. The peers are semicolon-separated names * list in the form of "myhost1:portA;myhost2:portB". */ public void setAddresses(String names) throws UnknownHostException { // NYI. Could look for equivalence of addresses and avoid // changing those that didn't change. _addressesLock.lock(); try { for (Iterator iter = _addresses.iterator(); iter.hasNext();) { ((HostAddress) iter.next()).close(); } String[] toks = Strings.split(names, ";", 0); _addresses = new ArrayList(toks.length); InetAddress localhost = InetAddress.getLocalHost(); String localhostName = localhost.getHostName(); for (int i = 0; i < toks.length; i++) { String host = toks[i]; String hostname; int tmpPort; int colon = host.indexOf(':'); if (colon != -1) { hostname = host.substring(0, colon); tmpPort = Integer.parseInt(host.substring(colon + 1)); } else { hostname = host; tmpPort = DEFAULT_PORT; } InetAddress tmpAddress = AccessController .doPrivileged(J2DoPrivHelper.getByNameAction(hostname)); // bleair: For each address we would rather make use of // the jdk1.4 isLinkLocalAddress () || isLoopbackAddress (). // (Though in practice on win32 they don't work anyways!) // Instead we will check hostname. Not perfect, but // it will match often enough (people will typically // use the DNS machine names and be cutting/pasting.) if (localhostName.equals(hostname)) { // This string matches the hostname for for ourselves, we // don't actually need to send ourselves messages. if (log.isTraceEnabled()) { log.trace(s_loc.get("tcp-address-asself", tmpAddress.getHostName() + ":" + tmpPort)); } } else { HostAddress newAddress = new HostAddress(host); _addresses.add(newAddress); if (log.isTraceEnabled()) { log.trace(s_loc.get("tcp-address-set", newAddress._address.getHostName() + ":" + newAddress._port)); } } } } catch (PrivilegedActionException pae) { throw (UnknownHostException) pae.getException(); } finally { _addressesLock.unlock(); } } // ---------- Configurable implementation ---------- /** * Subclasses that need to perform actions in * {@link Configurable#endConfiguration} must invoke this method. */ public void endConfiguration() { super.endConfiguration(); synchronized (s_portListenerMap) { // see if a listener exists for this port. _listener = (TCPPortListener) s_portListenerMap.get (String.valueOf(_port)); if (_listener == null || (!_listener.isRunning() && _listener._port == _port)) { try { _listener = new TCPPortListener(_port, log); _listener.listen(); s_portListenerMap.put(String.valueOf(_port), _listener); } catch (Exception e) { throw new GeneralException(s_loc.get("tcp-init-exception", String.valueOf(_port)), e).setFatal(true); } } else if (_listener.isRunning()) { if (_listener._port != _port) { // this really shouldn't be able to happen. throw new GeneralException(s_loc.get ("tcp-not-equal", String.valueOf(_port))). setFatal(true); } } else throw new InternalException(s_loc.get("tcp-listener-broken")); _listener.addProvider(this); } _addressesLock.lock(); try { HostAddress curAddress; for (Iterator iter = _addresses.iterator(); iter.hasNext();) { curAddress = (HostAddress) iter.next(); curAddress.setMaxActive(_maxActive); curAddress.setMaxIdle(_maxIdle); } } finally { _addressesLock.unlock(); } } // ---------- RemoteCommitProvider implementation ---------- // pre 3.3.4 = // 3.3 Preview = 0x1428acfd; // 3.4 = 0x1428acff; private static final long PROTOCOL_VERSION = 0x1428acff; public void broadcast(RemoteCommitEvent event) { try { // build a packet notifying other JVMs of object changes. ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeLong(PROTOCOL_VERSION); oos.writeLong(_id); oos.writeInt(_port); oos.writeObject(_localhost); oos.writeObject(event); oos.flush(); byte[] bytes = baos.toByteArray(); baos.close(); if (_broadcastThreads.isEmpty()) sendUpdatePacket(bytes); else _broadcastQueue.addPacket(bytes); } catch (IOException ioe) { if (log.isWarnEnabled()) log.warn(s_loc.get("tcp-payload-create-error"), ioe); } } /** * Sends a change notification packet to other machines in this * provider cluster. */ private void sendUpdatePacket(byte[] bytes) { _addressesLock.lock(); try { for (Iterator iter = _addresses.iterator(); iter.hasNext();) ((HostAddress) iter.next()).sendUpdatePacket(bytes); } finally { _addressesLock.unlock(); } } public void close() { if (_listener != null) _listener.removeProvider(this); // Remove Broadcast Threads then close sockets. _broadcastQueue.close(); // Wait for _broadcastThreads to get cleaned up. while(!_broadcastThreads.isEmpty()) { try { Thread.sleep(500); } catch (InterruptedException ie) { // Ignore. } } _addressesLock.lock(); try { for (Iterator iter = _addresses.iterator(); iter.hasNext();) ((HostAddress) iter.next()).close(); } finally { _addressesLock.unlock(); } } /** * Utility class to hold messages to be sent. This * allows calls to broadcast () to return without * waiting for the send to complete. */ private static class BroadcastQueue { private LinkedList _packetQueue = new LinkedList(); private boolean _closed = false; public synchronized void close() { _closed = true; notifyAll(); } public synchronized boolean isClosed() { return _closed; } public synchronized void addPacket(byte[] bytes) { _packetQueue.addLast(bytes); notify(); } /** * @return the bytes defining the packet to process, or * null if the queue is empty. */ public synchronized byte[] removePacket() throws InterruptedException { // only wait if the queue is still open. This allows processing // of events in the queue to continue, while avoiding sleeping // during shutdown. while (!_closed && _packetQueue.isEmpty()) wait(); if (_packetQueue.isEmpty()) return null; else return (byte[]) _packetQueue.removeFirst(); } } /** * Threads to broadcast packets placed in the {@link BroadcastQueue}. */ private class BroadcastWorkerThread extends Thread { private boolean _keepRunning = true; public void run() { while (_keepRunning) { try { // This will block until there is a packet to send, or // until the queue is closed. byte[] bytes = _broadcastQueue.removePacket(); if (bytes != null) sendUpdatePacket(bytes); else if (_broadcastQueue.isClosed()) _keepRunning = false; } catch (InterruptedException e) { // End the thread. break; } } remove(); } public void setRunning(boolean keepRunning) { _keepRunning = keepRunning; } private void remove() { _broadcastThreads.remove(this); } } /** * Responsible for listening for incoming packets and processing them. */ private static class TCPPortListener implements Runnable { private final Log _log; private ServerSocket _receiveSocket; private Thread _acceptThread; private Set _receiverThreads = new HashSet(); private final Set _providers = new HashSet(); /** * Cache the local IP address */ private byte[] _localhost; /** * The port that this listener should listen on. Configured * by TCPRemoteCommitProvider. */ private int _port; /** * Should be set to true once the listener is listening. */ private boolean _isRunning = false; /** * Construct a new TCPPortListener configured to use the specified port. */ private TCPPortListener(int port, Log log) throws IOException { _port = port; _log = log; try { _receiveSocket = AccessController .doPrivileged(J2DoPrivHelper.newServerSocketAction(_port)); } catch (PrivilegedActionException pae) { throw (IOException) pae.getException(); } _localhost = InetAddress.getLocalHost().getAddress(); if (_log.isTraceEnabled()) _log.info(s_loc.get("tcp-start-listener", String.valueOf(_port))); } private void listen() { _acceptThread = new Thread(this); _acceptThread.setDaemon(true); _acceptThread.start(); } /** * All providers added here will be notified of any incoming * provider messages. There will be one of these per * BrokerFactory in a given JVM. * {@link TCPRemoteCommitProvider#endConfiguration} invokes * addProvider with this upon * completion of configuration. */ private void addProvider(TCPRemoteCommitProvider provider) { synchronized (_providers) { _providers.add(provider); } } /** * Remove a provider from the list of providers to notify of * commit events. */ private synchronized void removeProvider (TCPRemoteCommitProvider provider) { synchronized (_providers) { _providers.remove(provider); // if the provider list is empty, shut down the thread. if (_providers.size() == 0) { _isRunning = false; try { _receiveSocket.close(); } catch (IOException ioe) { if (_log.isWarnEnabled()) _log.warn(s_loc.get("tcp-close-error"), ioe); } _acceptThread.interrupt(); } } } private boolean isRunning() { synchronized (_providers) { return _isRunning; } } public void run() { synchronized (_providers) { _isRunning = true; } Socket s = null; while (_isRunning) { try { s = null; // Block, waiting to accept new connection from a peer s = AccessController.doPrivileged(J2DoPrivHelper .acceptAction(_receiveSocket)); if (_log.isTraceEnabled()) { _log.trace(s_loc.get("tcp-received-connection", s.getInetAddress().getHostAddress() + ":" + s.getPort())); } ReceiveSocketHandler sh = new ReceiveSocketHandler(s); Thread receiverThread = new Thread(sh); receiverThread.setDaemon(true); receiverThread.start(); _receiverThreads.add(receiverThread); } catch (Exception e) { if (e instanceof PrivilegedActionException) e = ((PrivilegedActionException) e).getException(); if (!(e instanceof SocketException) || _isRunning) if (_log.isWarnEnabled()) _log.warn(s_loc.get("tcp-accept-error"), e); // Nominal case (InterruptedException) because close () // calls _acceptThread.interrupt (); try { if (s != null) s.close(); } catch (Exception ee) { if (_log.isWarnEnabled()) _log.warn(s_loc.get("tcp-close-error"), e); } } } // We are done listening. Interrupt any worker threads. Thread worker; for (Iterator iter = _receiverThreads.iterator(); iter.hasNext();) { worker = (Thread) iter.next(); // FYI, the worker threads are blocked // reading from the socket's InputStream. InputStreams // aren't interruptable, so this interrupt isn't // really going to be delivered until something breaks // the InputStream. worker.interrupt(); } synchronized (_providers) { try { if (_isRunning) _receiveSocket.close(); } catch (Exception e) { if (_log.isWarnEnabled()) _log.warn(s_loc.get("tcp-close-error"), e); } _isRunning = false; if (_log.isTraceEnabled()) _log.trace(s_loc.get("tcp-close-listener", _port + "")); } } /** * Utility class that acts as a worker thread to receive Events * from broadcasters. */ private class ReceiveSocketHandler implements Runnable { private InputStream _in; private Socket _s; private ReceiveSocketHandler(Socket s) { // We are the receiving end and we don't send any messages // back to the broadcaster. Turn off Nagle's so that // we will send ack packets without waiting. _s = s; try { _s.setTcpNoDelay(true); _in = new BufferedInputStream(s.getInputStream()); } catch (IOException ioe) { if (_log.isInfoEnabled()) _log.info(s_loc.get("tcp-socket-option-error"), ioe); _s = null; } catch (Exception e) { if (_log.isWarnEnabled()) _log.warn(s_loc.get("tcp-receive-error"), e); _s = null; } } public void run() { if (_s == null) return; while (_isRunning && _s != null) { try { // This will block our thread, waiting to read // the next Event-object-message. handle(_in); } catch (EOFException eof) { // EOFException raised when peer is properly // closing its end. if (_log.isTraceEnabled()) { _log.trace(s_loc.get("tcp-close-socket", _s.getInetAddress().getHostAddress() + ":" + _s.getPort())); } break; } catch (Throwable e) { if (_log.isWarnEnabled()) _log.warn(s_loc.get("tcp-receive-error"), e); break; } } // We are done receiving on this socket and this worker // thread is terminating. try { _in.close(); if (_s != null) _s.close(); } catch (IOException e) { _log.warn(s_loc.get("tcp-close-socket-error", _s.getInetAddress().getHostAddress() + ":" + _s.getPort()), e); } } /** * Process an {@link InputStream} containing objects written * by {@link TCPRemoteCommitProvider#broadcast(RemoteCommitEvent)}. */ private void handle(InputStream in) throws IOException, ClassNotFoundException { // This will block waiting for the next ObjectInputStream ois = new Serialization.ClassResolvingObjectInputStream(in); long protocolVersion = ois.readLong(); if (protocolVersion != PROTOCOL_VERSION) { if (_log.isWarnEnabled()) { _log.warn(s_loc.get("tcp-wrong-version-error", _s.getInetAddress().getHostAddress() + ":" + _s.getPort())); return; } } long senderId = ois.readLong(); int senderPort = ois.readInt(); byte[] senderAddress = (byte[]) ois.readObject(); RemoteCommitEvent rce = (RemoteCommitEvent) ois.readObject(); if (_log.isTraceEnabled()) { _log.trace(s_loc.get("tcp-received-event", _s.getInetAddress().getHostAddress() + ":" + _s.getPort())); } boolean fromSelf = senderPort == _port && Arrays.equals(senderAddress, _localhost); TCPRemoteCommitProvider provider; synchronized (_providers) { // bleair: We're iterating, but currenlty there can really // only be a single provider. for (Iterator iter = _providers.iterator(); iter.hasNext();) { provider = (TCPRemoteCommitProvider) iter.next(); if (senderId != provider._id || !fromSelf) provider.eventManager.fireEvent(rce); } } } } } /** * Utility class to store an InetAddress and an int. Not using * InetSocketAddress because it's a JDK1.4 API. This also * provides a wrapper around the socket(s) associated with this address. */ private class HostAddress { private InetAddress _address; private int _port; private long _timeLastError; // millis private boolean _isAvailable; // is peer thought to be up private int _infosIssued = 0; // limit log entries private GenericObjectPool _socketPool; // reusable open sockets /** * Construct a new host address from a string of the form * "host:port" or of the form "host". */ private HostAddress(String host) throws UnknownHostException { int colon = host.indexOf(':'); try { if (colon != -1) { _address = AccessController .doPrivileged(J2DoPrivHelper.getByNameAction(host .substring(0, colon))); _port = Integer.parseInt(host.substring(colon + 1)); } else { _address = AccessController .doPrivileged(J2DoPrivHelper.getByNameAction(host)); _port = DEFAULT_PORT; } } catch (PrivilegedActionException pae) { throw (UnknownHostException) pae.getException(); } // -1 max wait == as long as it takes _socketPool = new GenericObjectPool (new SocketPoolableObjectFactory(), _maxActive, GenericObjectPool.WHEN_EXHAUSTED_BLOCK, -1); _isAvailable = true; } private void setMaxActive(int maxActive) { _socketPool.setMaxActive(maxActive); } private void setMaxIdle(int maxIdle) { _socketPool.setMaxIdle(maxIdle); } public void close() { // Close the pool of sockets to this peer. This // will close all sockets in the pool. try { _socketPool.close(); } catch (Exception e) { if (log.isWarnEnabled()) { log.warn(s_loc.get("tcp-close-pool-error"), e); } } } private void sendUpdatePacket(byte[] bytes) { if (!_isAvailable) { long now = System.currentTimeMillis(); if (now - _timeLastError < _recoveryTimeMillis) // Not enough time has passed since the last error return; } Socket s = null; try { s = getSocket(); OutputStream os = s.getOutputStream(); os.write(bytes); os.flush(); if (log.isTraceEnabled()) { log.trace(s_loc.get("tcp-sent-update", _address.getHostAddress() + ":" + _port, String.valueOf(s.getLocalPort()))); } _isAvailable = true; _infosIssued = 0; // Return the socket to the pool; the socket is // still good. returnSocket(s); } catch (Exception e) { // There has been a problem sending to the peer. // The OS socket that was being used is can no longer // be used. if (s != null) this.closeSocket(s); this.clearAllSockets(); if (_isAvailable) { // Log a warning, the peer was up and has now gone down if (log.isWarnEnabled()) { log.warn(s_loc.get("tcp-send-error", _address.getHostAddress() + ":" + _port), e); } _isAvailable = false; // Once enough time has passed we will log another warning _timeLastError = System.currentTimeMillis(); } else { long now = System.currentTimeMillis(); if (now - _timeLastError > _recoveryTimeMillis) { if (_infosIssued < 5) { // Enough time has passed, and peer is still down _timeLastError = System.currentTimeMillis(); // We were trying to reestablish the connection, // but we failed again. Log a message, but // lower severity. This log will occur periodically // for 5 times until the peer comes back. if (log.isInfoEnabled()) { log.info(s_loc.get("tcp-send-still-error", _address.getHostAddress() + ":" + _port), e); } _infosIssued++; } } } } } private Socket getSocket() throws Exception { return (Socket) _socketPool.borrowObject(); } private void returnSocket(Socket s) throws Exception { _socketPool.returnObject(s); } private void clearAllSockets() { _socketPool.clear(); } private void closeSocket(Socket s) { // All sockets come from the pool. // This socket is no longer usable, so delete it from the // pool. try { _socketPool.invalidateObject(s); } catch (Exception e) { } } /** * Factory for pooled sockets. */ private class SocketPoolableObjectFactory implements PoolableObjectFactory { public Object makeObject() throws IOException { try { Socket s = AccessController .doPrivileged(J2DoPrivHelper.newSocketAction(_address, _port)); if (log.isTraceEnabled()) { log.trace(s_loc.get("tcp-open-connection", _address + ":" + _port, "" + s.getLocalPort())); } return s; } catch (PrivilegedActionException pae) { throw (IOException) pae.getException(); } } public void destroyObject(Object obj) { // silentClose (). try { Socket s = (Socket) obj; if (log.isTraceEnabled()) log.trace(s_loc.get("tcp-close-sending-socket", _address + ":" + _port, "" + s.getLocalPort())); s.close(); } catch (Exception e) { log.warn(s_loc.get("tcp-close-socket-error", _address.getHostAddress() + ":" + _port), e); } } public boolean validateObject(Object obj) { return true; } public void activateObject (Object value) { } public void passivateObject (Object value) { } } } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/event/LogOrphanedKeyAction.java0000644000000000000000000000660112133327272030012 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.event; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.log.LogFactoryImpl; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ValueMetaData; /** * Log a message when an orphaned key is discovered. * * @author Abe White * @since 0.3.2.2 */ public class LogOrphanedKeyAction implements OrphanedKeyAction { private static final Localizer _loc = Localizer.forPackage (LogOrphanedKeyAction.class); private String _channel = OpenJPAConfiguration.LOG_RUNTIME; private short _level = Log.WARN; /** * The channel to log to. Defaults to * org.apache.openjpa.Runtime. */ public String getChannel() { return _channel; } /** * The channel to log to. Defaults to * org.apache.openjpa.Runtime. */ public void setChannel(String channel) { _channel = channel; } /** * The level to log at. Defaults to WARN. */ public short getLevel() { return _level; } /** * The level to log at. Defaults to WARN. */ public void setLevel(short level) { _level = level; } /** * The level to log at. Defaults to WARN. */ public void setLevel(String level) { _level = LogFactoryImpl.getLevel(level); } public Object orphan(Object oid, OpenJPAStateManager sm, ValueMetaData vmd) { Log log = vmd.getRepository().getConfiguration().getLog(_channel); Object owner = (sm == null) ? null : sm.getId(); String msg = (owner == null) ? "orphaned-key" : "orphaned-key-owner"; switch (_level) { case Log.TRACE: if (log.isTraceEnabled()) log.trace(_loc.get(msg, oid, vmd, owner)); break; case Log.INFO: if (log.isInfoEnabled()) log.info(_loc.get(msg, oid, vmd, owner)); break; case Log.WARN: if (log.isWarnEnabled()) log.warn(_loc.get(msg, oid, vmd, owner)); break; case Log.ERROR: if (log.isErrorEnabled()) log.error(_loc.get(msg, oid, vmd, owner)); break; case Log.FATAL: if (log.isFatalEnabled()) log.fatal(_loc.get(msg, oid, vmd, owner)); break; } return null; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/0000755000000000000000000000000012133327272022740 5ustar openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java0000644000000000000000000002021512133327272026311 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import java.io.File; import java.io.Serializable; import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.kernel.Query; import org.apache.openjpa.kernel.QueryLanguages; import org.apache.openjpa.kernel.jpql.JPQLParser; import org.apache.openjpa.lib.meta.SourceTracker; import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.lib.xml.Commentable; /** * Holds metadata about named queries. * Information stored in this instance gets transfered to * new {@link Query} instances. * * @author Steve Kim */ public class QueryMetaData implements MetaDataModes, SourceTracker, Commentable, Serializable { private static final String[] EMPTY_KEYS = new String[0]; private static final Object[] EMPTY_VALS = new Object[0]; private final String _name; private Boolean _readOnly; private File _file; private Object _scope; private int _srcType; private int _mode = MODE_QUERY; private String _language; private Class _class; private Class _candidate; private Class _res; private String _query; private String[] _comments; private List _hintKeys; private List _hintVals; private String _resultSetMappingName; private int _lineNum; private int _colNum; private String _srcName; private boolean _convertPositionalParametersToNamed; private OrderedMap> _paramTypes; /** * Construct with the given name. */ protected QueryMetaData(String name, boolean convertPositionalParametersToNamed) { _name = name; _convertPositionalParametersToNamed = convertPositionalParametersToNamed; } /** * Return the name for this query. */ public String getName() { return _name; } /** * The class that defines this query, or null if none. */ public Class getDefiningType() { return _class; } /** * The class that defines this query, or null if none. */ public void setDefiningType(Class cls) { _class = cls; } /** * Whether the query has been marked read-only. */ public boolean isReadOnly() { return _readOnly != null && _readOnly.booleanValue(); } /** * Whether the query has been marked read-only. */ public void setReadOnly(boolean readOnly) { _readOnly = (readOnly) ? Boolean.TRUE : Boolean.FALSE; } /** * The query candidate class, or null if none. */ public Class getCandidateType() { return _candidate; } /** * The query result class, or null if none. */ public void setCandidateType(Class cls) { _candidate = cls; } /** * The query result class, or null if none. */ public Class getResultType() { return _res; } /** * The query result class, or null if none. */ public void setResultType(Class cls) { _res = cls; } /** * Return the query language. */ public String getLanguage() { return _language; } /** * Set the language for this query. */ public void setLanguage(String language) { _language = language; } /** * The full query string, or null if none. */ public String getQueryString() { return _query; } /** * The full query string, or null if none. */ public void setQueryString(String query) { if (query != null && _convertPositionalParametersToNamed && JPQLParser.LANG_JPQL.equals(_language)) { query = query.replaceAll("[\\?]", "\\:_"); } _query = query; } /** * Query hints. */ public String[] getHintKeys() { return (_hintKeys == null) ? EMPTY_KEYS : (String[]) _hintKeys.toArray(new String[_hintKeys.size()]); } /** * Query hints. */ public Object[] getHintValues() { return (_hintVals == null) ? EMPTY_VALS : _hintVals.toArray(); } /** * Add a query hint. */ public void addHint(String key, Object value) { if (_hintKeys == null) { _hintKeys = new LinkedList(); _hintVals = new LinkedList(); } _hintKeys.add(key); _hintVals.add(value); } public String getResultSetMappingName() { return _resultSetMappingName; } public void setResultSetMappingName(String setMappingName) { _resultSetMappingName = setMappingName; } /** * Set query template information into the given concrete * query instance. However, the language, query string, and * candidate class are assumed to be declared in the query * instantiation, and hints are not transferred. */ public void setInto(Query query) { if (_candidate != null) query.setCandidateType(_candidate, true); if (!StringUtils.isEmpty(_query)) query.setQuery(_query); if (_res != null) query.setResultType(_res); if (_readOnly != null) query.setReadOnly(_readOnly.booleanValue()); if (_resultSetMappingName != null) query.setResultMapping(null, _resultSetMappingName); } /** * Initialize this instance from the values held in the * specified {@link Query}. */ public void setFrom(Query query) { _language = query.getLanguage(); _candidate = query.getCandidateType(); _res = query.getResultType(); _query = query.getQueryString(); } /** * The source mode of this query. */ public int getSourceMode() { return _mode; } /** * The source mode of this query. */ public void setSourceMode(int mode) { _mode = mode; } public String toString() { return _name; } /////////////// // Commentable /////////////// public String[] getComments() { return (_comments == null) ? EMPTY_COMMENTS : _comments; } public void setComments(String[] comments) { _comments = comments; } //////////////////////////////// // SourceTracker implementation //////////////////////////////// public File getSourceFile() { return _file; } public Object getSourceScope() { return _scope; } public int getSourceType() { return _srcType; } public void setSource(File file, Object scope, int srcType, String srcName) { _file = file; _scope = scope; _srcType = srcType; _srcName = srcName; } public String getResourceName() { return (_class == null) ? _name : _class.getName () + ":" + _name; } public int getLineNumber() { return _lineNum; } public void setLineNumber(int lineNum) { _lineNum = lineNum; } public int getColNumber() { return _colNum; } public void setColNumber(int colNum) { _colNum = colNum; } public String getSourceName() { return _srcName; } public void setParamTypes(OrderedMap> paramTypes) { _paramTypes = paramTypes; } /** * @return a map of parameter name to type for this named query or null if this data hasn't been set. */ public OrderedMap> getParamTypes() { return _paramTypes; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ProxySetupStateManager.java0000644000000000000000000002255212133327272030247 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import java.io.ObjectOutput; import java.util.Calendar; import java.util.SortedMap; import java.util.SortedSet; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.InternalException; /** * Mostly-unimplemented state manager type whose sole purpose is to * check the initial value of all SCO container fields for their initialized * types and comparators. * * @author Abe White */ class ProxySetupStateManager implements StateManager { private static final Localizer _loc = Localizer .forPackage(ProxySetupStateManager.class); private Object _object = null; public void setProxyData(PersistenceCapable pc, ClassMetaData meta) { FieldMetaData[] fmds = meta.getFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].getDefiningMetaData() != meta) continue; switch (fmds[i].getDeclaredTypeCode()) { case JavaTypes.CALENDAR: pc.pcProvideField(fmds[i].getIndex()); if (_object != null) { // specified timezone fmds[i] .setInitializer(((Calendar) _object).getTimeZone()); } break; case JavaTypes.COLLECTION: pc.pcProvideField(fmds[i].getIndex()); if (_object != null) { // more specific type? if (_object.getClass() != fmds[i].getDeclaredType()) fmds[i].setProxyType(_object.getClass()); // custom comparator? if (_object instanceof SortedSet) fmds[i].setInitializer(((SortedSet) _object). comparator()); } break; case JavaTypes.MAP: pc.pcProvideField(fmds[i].getIndex()); if (_object != null) { // more specific type? if (_object.getClass() != fmds[i].getDeclaredType()) fmds[i].setProxyType(_object.getClass()); // custom comparator? if (_object instanceof SortedMap) fmds[i].setInitializer(((SortedMap) _object). comparator()); } break; } } } public Object getPCPrimaryKey(Object oid, int field) { throw new UnsupportedOperationException(); } public StateManager replaceStateManager(StateManager sm) { throw new InternalException(); } public boolean isDirty() { throw new InternalException(); } public boolean isTransactional() { throw new InternalException(); } public boolean isPersistent() { throw new InternalException(); } public boolean isNew() { throw new InternalException(); } public boolean isDeleted() { throw new InternalException(); } public boolean isDetached() { throw new InternalException(); } public Object getGenericContext() { throw new InternalException(); } public void dirty(String s) { throw new InternalException(); } public Object fetchObjectId() { throw new InternalException(); } public Object getVersion() { throw new InternalException(); } public void accessingField(int i) { throw new InternalException(); } public boolean serializing() { throw new InternalException(); } public boolean writeDetached(ObjectOutput out) { throw new InternalException(); } public void proxyDetachedDeserialized(int idx) { throw new InternalException(); } public void settingBooleanField(PersistenceCapable pc, int i, boolean b, boolean b2, int set) { throw new InternalException(); } public void settingCharField(PersistenceCapable pc, int i, char c, char c2, int set) { throw new InternalException(); } public void settingByteField(PersistenceCapable pc, int i, byte b, byte b2, int set) { throw new InternalException(); } public void settingShortField(PersistenceCapable pc, int i, short s, short s2, int set) { throw new InternalException(); } public void settingIntField(PersistenceCapable pc, int i, int i2, int i3, int set) { throw new InternalException(); } public void settingLongField(PersistenceCapable pc, int i, long l, long l2, int set) { throw new InternalException(); } public void settingFloatField(PersistenceCapable pc, int i, float f, float f2, int set) { throw new InternalException(); } public void settingDoubleField(PersistenceCapable pc, int i, double d, double d2, int set) { throw new InternalException(); } public void settingStringField(PersistenceCapable pc, int i, String s, String s2, int set) { throw new InternalException(); } public void settingObjectField(PersistenceCapable pc, int i, Object o, Object o2, int set) { throw new InternalException(); } public void providedBooleanField(PersistenceCapable pc, int i, boolean b) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "boolean")); } public void providedCharField(PersistenceCapable pc, int i, char c) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "char")); } public void providedByteField(PersistenceCapable pc, int i, byte b) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "byte")); } public void providedShortField(PersistenceCapable pc, int i, short s) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "short")); } public void providedIntField(PersistenceCapable pc, int i, int i2) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "int")); } public void providedLongField(PersistenceCapable pc, int i, long l) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "long")); } public void providedFloatField(PersistenceCapable pc, int i, float f) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "float")); } public void providedDoubleField(PersistenceCapable pc, int i, double d) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "double")); } public void providedStringField(PersistenceCapable pc, int i, String s) { throw new InternalException(_loc.get( "unexpected_proxy_sm_attribute_type", pc.getClass().getName(), "String")); } public void providedObjectField(PersistenceCapable pc, int i, Object o) { _object = o; } public boolean replaceBooleanField(PersistenceCapable pc, int i) { throw new InternalException(); } public char replaceCharField(PersistenceCapable pc, int i) { throw new InternalException(); } public byte replaceByteField(PersistenceCapable pc, int i) { throw new InternalException(); } public short replaceShortField(PersistenceCapable pc, int i) { throw new InternalException(); } public int replaceIntField(PersistenceCapable pc, int i) { throw new InternalException(); } public long replaceLongField(PersistenceCapable pc, int i) { throw new InternalException(); } public float replaceFloatField(PersistenceCapable pc, int i) { throw new InternalException(); } public double replaceDoubleField(PersistenceCapable pc, int i) { throw new InternalException(); } public String replaceStringField(PersistenceCapable pc, int i) { throw new InternalException(); } public Object replaceObjectField(PersistenceCapable pc, int i) { throw new InternalException(); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaData.java0000644000000000000000000002302112133327272026256 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import java.io.Serializable; /** * Holds metadata on a value; this could be a field value, key value, or * element value. * * @since 0.4.0 * @author Abe White */ public interface ValueMetaData extends MetaDataContext, MetaDataModes, Serializable { /** * The operation is not cascaded to this field. */ public int CASCADE_NONE = 0; /** * The operation is immediately cascaded to this field. */ public int CASCADE_IMMEDIATE = 1; /** * Use automatic cascade behavior. Persistence-by-reachability, * delete-dependent, attach-if-detached, etc. */ public int CASCADE_AUTO = 2; /** * Marker to set on {@link #setValueMappedBy} to denote that the map key * is mapped by the primary key field of the value. */ public static final String MAPPED_BY_PK = "`pk`"; /** * Return the owning field for this value. */ public FieldMetaData getFieldMetaData(); /** * The value class. */ public Class getType(); /** * The value class. */ public void setType(Class type); /** * The type code of the value class. */ public int getTypeCode(); /** * The type code of the value class. */ public void setTypeCode(int code); /** * Whether the type is a persistence capable instance. */ public boolean isTypePC(); /** * The metadata for the value class, if the type is persistent. */ public ClassMetaData getTypeMetaData(); /** * Return the declared class of the value. This can differ * from the return value of {@link #getType} if the user indicates * a different type or the value has an externalizer. */ public Class getDeclaredType(); /** * Set the declared class of the value. */ public void setDeclaredType(Class type); /** * Return the declared type code of the value. This can differ * from the return value of {@link #getTypeCode} if the user indicates * a different type or the value has an externalizer. */ public int getDeclaredTypeCode(); /** * Set the type code for the value. The type code is usually * computed automatically, but it can be useful to set it explicitly * when creating metadatas from scratch. */ public void setDeclaredTypeCode(int type); /** * Whether the type is a persistence capable instance. */ public boolean isDeclaredTypePC(); /** * Return metadata for the value's class, if the type is persistent. */ public ClassMetaData getDeclaredTypeMetaData(); /** * This attribute is a hint to the implementation to store this value * in the same structure as the class, rather than as a separate datastore * structure. Defaults to true if the field is not a collection or map * or persistence-capable object; defaults to false otherwise. * Implementations are permitted to ignore this attribute. */ public boolean isEmbedded(); /** * This attribute is a hint to the implementation to store this value * in the same structure as the class, rather than as a separate datastore * structure. Defaults to true if the field is not a collection or map * or persistence-capable objects; defaults to false otherwise. * Implementations are permitted to ignore this attribute. */ public void setEmbedded(boolean embedded); /** * Whether this is an embedded persistence capable value. */ public boolean isEmbeddedPC(); /** * The embedded class metadata for the value. */ public ClassMetaData getEmbeddedMetaData(); /** * Add embedded metadata for this value. */ public ClassMetaData addEmbeddedMetaData(); /** * Add embedded metadata for this value with the given access type */ public ClassMetaData addEmbeddedMetaData(int access); /** * Cascade behavior for delete operation. Only applies to * persistence-capable values. Options are:
    *
      *
    • CASCADE_NONE: No cascades.
    • *
    • CASCADE_IMMEDIATE: Value is deleted immediately when * the owning object is deleted.
    • *
    • CASCADE_AUTO: Value will be deleted on flush * if the owning object is deleted or if the value is removed from the * owning object, and if the value is not assigned to another relation in * the same transaction.
    • *
    */ public int getCascadeDelete(); /** * Cascade behavior for deletion. * * @see #getCascadeDelete */ public void setCascadeDelete(int cascade); /** * Cascade behavior for persist operation. Only applies to * persistence-capable values. Options are:
    *
      *
    • CASCADE_NONE: No cascades. If a transient relation * is held at flush, an error is thrown.
    • *
    • CASCADE_IMMEDIATE: Value is persisted immediately when * the owning object is persisted.
    • *
    • CASCADE_AUTO: Value will be persisted on flush.
    • *
    */ public int getCascadePersist(); /** * Cascade behavior for persist operation. * * @see #getCascadePersist */ public void setCascadePersist(int cascade); /** * Cascade behavior for attach operation. Only applies to * persistence-capable values. Options are:
    *
      *
    • CASCADE_NONE: No cascades of attach. Relation * remains detached.
    • *
    • CASCADE_IMMEDIATE: Value is attached immediately.
    • *
    */ public int getCascadeAttach(); /** * Cascade behavior for attach operation. * * @see #getCascadeAttach */ public void setCascadeAttach(int cascade); /** * Cascade behavior for detach operation. Only applies to * persistence-capable values. Options are:
    *
      *
    • CASCADE_NONE: No cascades of detach. Relation * remains attached.
    • *
    • CASCADE_IMMEDIATE: Value is detached immediately.
    • *
    */ public int getCascadeDetach(); /** * Cascade behavior for detach operation. * * @see #getCascadeDetach */ public void setCascadeDetach(int cascade); /** * Cascade behavior for refresh operation. Only applies to * persistence-capable values. Options are:
    *
      *
    • CASCADE_NONE: No cascades of refresh.
    • *
    • CASCADE_IMMEDIATE: Persistent value object is also * refreshed.
    • *
    • CASCADE_AUTO: Value will be refreshed if it is * in the current fetch groups.
    • *
    */ public int getCascadeRefresh(); /** * Cascade behavior for refresh operation. * * @see #getCascadeRefresh */ public void setCascadeRefresh(int cascade); /** * Whether this value is serialized when stored. */ public boolean isSerialized(); /** * Whether this value is serialized when stored. */ public void setSerialized(boolean serialized); /** * The field that this value shares a mapping with. Currently the only * supported use for a mapped-by value is when a map field key is * determined by a field of the persistence-capable map value. */ public String getValueMappedBy(); /** * The field that this value shares a mapping with. Currently the only * supported use for a mapped-by value is when a map field key is * determined by a field of the persistence-capable map value. */ public void setValueMappedBy(String mapped); /** * The field that this value shares a mapping with. Currently the only * supported use for a mapped-by value is when a map field key is * determined by a field of the persistence-capable map value. */ public FieldMetaData getValueMappedByMetaData(); /** * User-supplied type overriding assumed type based on field. */ public Class getTypeOverride(); /** * User-supplied type overriding assumed type based on field. */ public void setTypeOverride(Class type); /** * Resolve mode for metadata. */ public int getResolve(); /** * Resolve mode for metadata. */ public void setResolve(int mode); /** * Resolve mode for metadata. */ public void setResolve(int mode, boolean on); /** * Resolve and validate metadata. Return true if already resolved. */ public boolean resolve(int mode); /** * Copy state from the given value to this one. Do not copy mapping * information. */ public void copy(ValueMetaData vmd); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AccessCode.java0000644000000000000000000002022612133327272025601 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * Represents access styles for members of a class and field through a * 5-bit integer. *
    * * The bits designate following aspects of access style being used at class * level:
    * *
  • Bit position 0 (UNKNOWN): generally 0. All bits as zero represent * that no access style has been set. 1 denotes that the * class has no property at all and its access can not be * determined. *
  • Bit position 1 (FIELD): Field based access is default *
  • Bit position 2 (PROPERTY): Property based access is default *
  • Bit position 3 (EXPLICIT): whether explicit or implicit * Explicit access style allows members to use mixed access style, * implicit access style does not *
  • Bit position 4 (MIXED): whether all members are using the same * access style or not. Can only be set if EXPLICT bit is set. * If set, then bit 1 or 2 denotes what is the default. *
    * The same bits designate following aspects of access style being used at field * level:
    * *
  • Bit position 0 (UNKNOWN): always 0. All bits as zero represent * that no access style has been set. *
  • Bit position 1 (FIELD): Field based access is default *
  • Bit position 2 (PROPERTY): Property based access is default *
  • Bit position 3 (EXPLICIT): whether the access is explicit or implicit *
  • Bit position 4 (MIXED): not used *
    * *

    * Validation Rules for the bits:
    *

  • 1. Only one of the position 1 (FIELD) and 2 (PROPERTY) can * be set. A single bit is not used for legacy reason to cope with the access * constants used in ClassMetaData which this class now refactors to address * new behaviors specified in JPA 2.0 specification. *
  • 2. if position 3 (EXPLICIT) is set then one of position 1 * (FIELD) and 2 (PROPERTY) must be set. *
  • 3. If position 4 (MIXED) is set then the set position of either * FIELD or PROPERTY designates the default access of the * member. * * @author Pinaki Poddar * * @since 2.0.0 */ public class AccessCode { public static int UNKNOWN = 0; public static int EMPTY = 1; public static int FIELD = 2 << 0; public static int PROPERTY = 2 << 1; public static int EXPLICIT = 2 << 2; public static int MIXED = 2 << 3; private static Localizer _loc = Localizer.forPackage(AccessCode.class); /** * Affirms if the given code is valid. */ public static boolean isValidClassCode(int code) { if (code == EMPTY) return true; return (code%2 == 0 || code == EMPTY) && code >= UNKNOWN && code <= (MIXED|EXPLICIT|PROPERTY) && !(isProperty(code) && isField(code)) // both 1 & 2 can not be set && (isProperty(code) || isField(code) || isUnknown(code)) && ((isMixed(code) && isExplicit(code)) || !isMixed(code)); } public static boolean isValidFieldCode(int code) { return code%2 == 0 // code must be even && code >= UNKNOWN && code <= (EXPLICIT|PROPERTY) && !(isProperty(code) && isField(code)) && (isProperty(code) || isField(code) || isUnknown(code)); } /** * Affirms if the given code designates that members can use both * FIELD and PROPERTY based access. */ public static boolean isMixed(int code) { return (code & MIXED) != 0; } public static boolean isExplicit(int code) { return (code & EXPLICIT) != 0; } public static boolean isProperty(int code) { return (code & PROPERTY) != 0; } public static boolean isField(int code) { return (code & FIELD) != 0; } public static boolean isUnknown(int code) { return code == UNKNOWN; } public static boolean isEmpty(int code) { return code == EMPTY; } public static boolean isField(ClassMetaData meta) { return isField(meta.getAccessType()); } public static boolean isProperty(ClassMetaData meta) { return isProperty(meta.getAccessType()); } public static boolean isUnknown(ClassMetaData meta) { return isUnknown(meta.getAccessType()); } public static boolean isEmpty(ClassMetaData meta) { return isEmpty(meta.getAccessType()); } public static boolean isField(FieldMetaData meta) { return isField(meta.getAccessType()); } public static boolean isProperty(FieldMetaData meta) { return isProperty(meta.getAccessType()); } public static boolean isUnknown(FieldMetaData meta) { return isUnknown(meta.getAccessType()); } /** * Affirms if the sub class access type is compatible with super class * access style. */ public static boolean isCompatibleSuper(int subCode, int superCode) { if (isEmpty(superCode)) return true; if (isValidClassCode(subCode) && isValidClassCode(superCode)) { if (isExplicit(subCode)) return true; return subCode == superCode; } return false; } public static int mergeFieldCode(ClassMetaData meta, FieldMetaData fmd, int fCode) { int cCode = meta.getAccessType(); try { return mergeFieldCode(cCode, fCode); } catch (IllegalStateException e) { throw new UserException(_loc.get("access-illegal-merge", fmd.getFullName(false), toFieldString(fCode), toClassString(cCode))); } } /** * Merges the field access type with the class access type provided such * merge is valid. * * @return the modified class access code. * @exception if the given codes are not compatible */ public static int mergeFieldCode(int cCode, int fCode) { if (isValidClassCode(cCode) && isValidFieldCode(fCode)) { if (isUnknown(cCode)) { if (isUnknown(fCode)) return UNKNOWN; return isProperty(fCode) ? PROPERTY : FIELD; } boolean mixed = isProperty(cCode) != isProperty(fCode); if (isExplicit(cCode)) { if (mixed) { return MIXED | cCode; } else { return cCode; } } else { // default, implicit access if (fCode == cCode) return cCode; else throw new IllegalStateException( (_loc.get("access-cannot-merge", toFieldString(fCode), toClassString(cCode)).toString())); } } return cCode; } public static int getMixedCode(int cCode, int fCode) { if (isMixed(cCode) || (isProperty(cCode) == isProperty(fCode))) return cCode; return MIXED | cCode; } public static int toFieldCode(int code) { if (isProperty(code)) return PROPERTY; if (isField(code)) return FIELD; return UNKNOWN; } public static String toFieldString(int code) { if (!isValidFieldCode(code)) return "invalid code " + code; if (code == UNKNOWN) return "unknown access"; if (code == EMPTY) return "empty access"; return (isMixed(code) ? "mixed " : "") + (isExplicit(code) ? "explicit " : "implicit ") + (isField(code) ? "field" : "property") + " access"; } public static String toClassString(int code) { if (!isValidClassCode(code)) return "invalid code " + code; if (code == UNKNOWN) return "unknown access"; if (code == EMPTY) return "empty access"; return (isMixed(code) ? "mixed " : "") + (isExplicit(code) ? "explicit " : "implicit ") + (isField(code) ? "field" : "property") + " access"; } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/package.html0000644000000000000000000000201412133327272025216 0ustar

    OpenJPA Metadata

    This package provides an extendable framework for parsing and caching persistence metadata. The metadata can be accessed at both enhancement time and at runtime.

    openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataFactory.java0000644000000000000000000001365612133327272026626 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import java.io.File; import java.util.Collection; import java.util.Map; import java.util.Set; import org.apache.openjpa.lib.meta.ClassArgParser; /** * The {@link MetaDataRepository} uses implementations of this interface * to load and store metadata. Implementations need not be threadsafe. * * @author Patrick Linskey * @author Abe White * @author Pinaki Poddar */ public interface MetaDataFactory extends MetaDataModes { public static final int STORE_DEFAULT = 0; public static final int STORE_PER_CLASS = 1; public static final int STORE_VERBOSE = 2; /** * Set the repository to load metadata into. * This method will be called before use. */ public void setRepository(MetaDataRepository repos); /** * Base directory for storing metadata. May not be called. */ public void setStoreDirectory(File dir); /** * Storage mode. May not be called. */ public void setStoreMode(int store); /** * If true, I/O's must exactly obey the mode directives given, and may * not load additional information. */ public void setStrict(boolean strict); /** * Load metadata for the given class in the given mode(s). If loading * in {@link MetaDataModes#MODE_QUERY}, the class may be null. Loaded * metadata should be added directly to the repository. It should have * its source mode set appropriately via * {@link ClassMetaData#setSourceMode}. * * @param mode the mode to load metadata in: if mapping information is * stored together with metadata, then you can load mapping * data even if this mode only includes * {@link MetaDataModes#MODE_META MODE_META}, so long as * the strict property hasn't been set */ public void load(Class cls, int mode, ClassLoader envLoader); /** * Store the given metadata. * * @param mode hint about what aspects of the metadata have changed * @param output if non-null, rather than storing metadata directly, * add entries mapping each output destination such * as a File to the planned output for that * destination in string form * @return false if this factory is unable to store metadata */ public boolean store(ClassMetaData[] metas, QueryMetaData[] queries, SequenceMetaData[] seqs, int mode, Map output); /** * Drop the metadata for the given classes in the given mode(s). * * @return false if any metadata could not be dropped */ public boolean drop(Class[] cls, int mode, ClassLoader envLoader); /** * Return the metadata defaults for this factory. */ public MetaDataDefaults getDefaults(); /** * Return all persistent class names, using the metadata locations supplied * in configuration, optionally scanning the classpath. * Return null if no types are supplied and this factory is unable to scan * the classpath. This method should not be used directly by outside * code; use {@link MetaDataRepository#getPersistentTypeNames} instead. * * @see MetaDataRepository#getPersistentTypeNames * @see MetaDataRepository#loadPersistentTypes */ public Set getPersistentTypeNames(boolean devpath, ClassLoader envLoader); /** * Return the type defining the given query name, if any. */ public Class getQueryScope(String queryName, ClassLoader loader); /** * Return the type defining the given result set mapping name, if any. */ public Class getResultSetMappingScope(String resultSetMappingName, ClassLoader loader); /** * Return a properly-configured class arg parser for our expected * metadata format. */ public ClassArgParser newClassArgParser(); /** * Clear any internal caches. */ public void clear(); /** * Add any extension keys used by this instance to the given set. */ public void addClassExtensionKeys(Collection exts); /** * Add any extension keys used by this instance to the given set. */ public void addFieldExtensionKeys (Collection exts); /** * Load XMLClassMetadata for the given class. Loaded * metadata should be added directly to the repository. */ public void loadXMLMetaData(Class cls); /** * Gets the name of the meta-model class for the given fully-qualified * managed class name. * * @since 2.0.0 */ public String getMetaModelClassName(String managedClassName); /** * Gets the name of the managed class for the given fully-qualified * meta-model class name. * * @since 2.0.0 */ public String getManagedClassName(String metamodelClassName); /** * Affirms if the given class is a meta-class. * * @since 2.0.0 */ public boolean isMetaClass(Class c); /** * Gets the managed class corresponding to the given meta-class. * * @return null if the given input is not a meta-class. * * @since 2.0.0 */ public Class getManagedClass(Class c); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLClassMetaData.java0000644000000000000000000000621712133327272026640 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import java.util.HashMap; import org.apache.commons.lang.StringUtils; public class XMLClassMetaData implements XMLMetaData { private Class _type; private int _code = JavaTypes.OBJECT; private int _xmltype = XMLTYPE; private String _name = null; private String _xmlname = null; private String _xmlnamespace = null; private boolean _isXMLRootElement = false; private HashMap _fieldMap = new HashMap(); /** * Constructor. * * @param type the class that contains XmlType annotation. * @name the persistent field name that maps to xml column */ public XMLClassMetaData(Class type, String name) { _type = type; _name = name; } /** * Constructor. * * @param type the class that contains XmlType annotation. */ public XMLClassMetaData(Class type) { _type = type; } public void setName(String name) { _name = name; } public String getName() { return _name; } public void setXmlname(String name) { _xmlname = name; } public String getXmlname() { return _isXMLRootElement ? null : _xmlname; } public void setXmlnamespace(String name) { // avoid JAXB XML bind default name if (!StringUtils.equals(defaultName, name)) _xmlnamespace = name; } public String getXmlnamespace() { return _xmlnamespace; } public void setXmlRootElement(boolean isXMLRootElement) { _isXMLRootElement = isXMLRootElement; } public boolean isXmlRootElement() { return _isXMLRootElement; } public boolean isXmlElement() { return false; } public boolean isXmlAttribute() { return false; } public XMLMetaData getFieldMapping(String name) { return (XMLMetaData) _fieldMap.get(name); } public void setType(Class type) { _type = type; } public Class getType() { return _type; } public int getTypeCode() { return _code; } public void setXmltype(int type) { _xmltype = type; } public int getXmltype() { return _xmltype; } public void addField(String name, XMLMetaData field) { _fieldMap.put(name, field); } } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/Order.java0000644000000000000000000000266512133327272024667 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import java.io.Serializable; import java.util.Comparator; /** * Order a field. * * @author Abe White */ public interface Order extends Serializable { /** * Token denoting to order by the element value. */ public static final String ELEMENT = "#element"; /** * Return the name of the orderable. */ public String getName(); /** * Order direction. */ public boolean isAscending(); /** * Return a comparator for ordering by this element, or null if * the ordering is done in the datastore. */ public Comparator getComparator (); } openjpa-2.2.2.orig/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java0000644000000000000000000023577712133327272026254 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.meta; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TimeZone; import org.apache.commons.collections.comparators.ComparatorChain; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.JavaVersions; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.lib.xml.Commentable; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.MetaDataException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.ProxyManager; import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.UserException; import serp.util.Strings; /** * Metadata for a managed class field. * * @author Abe White */ @SuppressWarnings("serial") public class FieldMetaData extends Extensions implements ValueMetaData, MetaDataContext, MetaDataModes, Commentable { /** * Constant specifying that no null-value was given. */ public static final int NULL_UNSET = -1; /** * Constant specifying to use a datastore null to persist null values * in object fields. */ public static final int NULL_NONE = 0; /** * Constant specifying to use a datastore default value to persist null * values in object fields. */ public static final int NULL_DEFAULT = 1; /** * Constant specifying to throw an exception when attempting to persist * null values in object fields. */ public static final int NULL_EXCEPTION = 2; /** * Constant specifying the management level of a field. */ public static final int MANAGE_PERSISTENT = 3; /** * Constant specifying the management level of a field. */ public static final int MANAGE_TRANSACTIONAL = 1; /** * Constant specifying the management level of a field. */ public static final int MANAGE_NONE = 0; public static final int ONE_TO_ONE = 1; public static final int ONE_TO_MANY = 2; public static final int MANY_TO_ONE = 3; public static final int MANY_TO_MANY = 4; private static final Localizer _loc = Localizer.forPackage (FieldMetaData.class); private static final int DFG_FALSE = 1; private static final int DFG_TRUE = 2; private static final int DFG_EXPLICIT = 4; private static final Method DEFAULT_METHOD; static { try { DEFAULT_METHOD = Object.class.getMethod("wait", (Class[]) null); } catch (Exception e) { // shouldn't ever happen throw new InternalException(e); } } // name and type private final ValueMetaData _val; private final ValueMetaData _key; private final ValueMetaData _elem; private final ClassMetaData _owner; private final String _name; private Class _dec = null; private ClassMetaData _decMeta = null; private String _fullName = null; private String _embedFullName = null; private int _resMode = MODE_NONE; private String _mappedByIdValue = null; private int _access = AccessCode.UNKNOWN; // load/store info private String[] _comments = null; private int _listIndex = -1; //////////////////////////////////////////////////////////////////// // Note: if you add additional state, make sure to add it to copy() //////////////////////////////////////////////////////////////////// // misc info private Class _proxyClass = null; private Object _initializer = null; private boolean _transient = false; private boolean _primKey = false; private Boolean _version = null; private int _nullValue = NULL_UNSET; private int _manage = MANAGE_PERSISTENT; private int _index = -1; private int _decIndex = -1; private int _pkIndex = -1; private boolean _explicit = false; private int _dfg = 0; private Set _fgSet = null; private String[] _fgs = null; private String _lfg = null; private Boolean _lrs = null; private Boolean _stream = null; private String _extName = null; private String _factName = null; private String _extString = null; private Map _extValues = Collections.EMPTY_MAP; private Map _fieldValues = Collections.EMPTY_MAP; private Boolean _enumField = null; private Boolean _lobField = null; private Boolean _serializableField = null; private boolean _generated = false; // Members aren't serializable. Use a proxy that can provide a Member // to avoid writing the full Externalizable implementation. private MemberProvider _backingMember = null; // Members aren't serializable. Initializing _extMethod and _factMethod to // DEFAULT_METHOD is sufficient to trigger lazy population of these fields. private transient Method _extMethod = DEFAULT_METHOD; private transient Member _factMethod = DEFAULT_METHOD; // intermediate and impl data private boolean _intermediate = true; private Boolean _implData = Boolean.TRUE; // value generation private int _valStrategy = -1; private int _upStrategy = -1; private String _seqName = ClassMetaData.DEFAULT_STRING; private SequenceMetaData _seqMeta = null; // inverses private String _mappedBy = null; private FieldMetaData _mappedByMeta = null; private FieldMetaData[] _inverses = null; private String _inverse = ClassMetaData.DEFAULT_STRING; // ordering on load private Order[] _orders = null; private String _orderDec = null; // indicate if this field is used by other field as "order by" value private boolean _usedInOrderBy = false; private boolean _isElementCollection = false; private int _associationType; private boolean _persistentCollection = false; private Boolean _delayCapable = null; /** * Constructor. * * @param name the field name * @param type the field type * @param owner the owning class metadata */ protected FieldMetaData(String name, Class type, ClassMetaData owner) { _name = name; _owner = owner; _dec = null; _decMeta = null; _val = owner.getRepository().newValueMetaData(this); _key = owner.getRepository().newValueMetaData(this); _elem = owner.getRepository().newValueMetaData(this); setDeclaredType(type); } /** * Supply the backing member object; this allows us to utilize * parameterized type information if available. * Sets the access style of this receiver based on whether the given * member represents a field or getter method. */ public void backingMember(Member member) { if (member == null) return; if (Modifier.isTransient(member.getModifiers())) _transient = true; _backingMember = new MemberProvider(member); Class type; Class[] types; if (member instanceof Field) { Field f = (Field) member; type = f.getType(); types = JavaVersions.getParameterizedTypes(f); setAccessType(AccessCode.FIELD); } else { Method meth = (Method) member; type = meth.getReturnType(); types = JavaVersions.getParameterizedTypes(meth); setAccessType(AccessCode.PROPERTY); } setDeclaredType(type); if (Collection.class.isAssignableFrom(type) && _elem.getDeclaredType() == Object.class && types.length == 1) { _elem.setDeclaredType(types[0]); } else if (Map.class.isAssignableFrom(type) && types.length == 2) { if (_key.getDeclaredType() == Object.class) _key.setDeclaredType(types[0]); if (_elem.getDeclaredType() == Object.class) _elem.setDeclaredType(types[1]); } } /** * Return the backing member supplied in {@link #backingMember}. */ public Member getBackingMember() { return (_backingMember == null) ? null : _backingMember.getMember(); } /** * The metadata repository. */ public MetaDataRepository getRepository() { return _owner.getRepository(); } /** * The class that defines the metadata for this field. */ public ClassMetaData getDefiningMetaData() { return _owner; } /** * The declaring class. */ public Class getDeclaringType() { return (_dec == null) ? _owner.getDescribedType() : _dec; } /** * The declaring class. */ public void setDeclaringType(Class cls) { _dec = cls; _decMeta = null; _fullName = null; _embedFullName = null; } /** * The declaring class. */ public ClassMetaData getDeclaringMetaData() { if (_dec == null) return _owner; if (_decMeta == null) _decMeta = getRepository().getMetaData(_dec, _owner.getEnvClassLoader(), true); return _decMeta; } /** * The field name. */ public String getName() { return _name; } /** * The field name, qualified by the owning class. * @deprecated Use getFullName(boolean) instead. */ public String getFullName() { return getFullName(false); } /** * The field name, qualified by the owning class and optionally the * embedding owner's name (if any). */ public String getFullName(boolean embedOwner) { if (_fullName == null) _fullName = getDeclaringType().getName() + "." + _name; if (embedOwner && _embedFullName == null) { if (_owner.getEmbeddingMetaData() == null) _embedFullName = _fullName; else _embedFullName = _owner.getEmbeddingMetaData(). getFieldMetaData().getFullName(true) + "." + _fullName; } return (embedOwner) ? _embedFullName : _fullName; } /** * The field name, qualified by the defining class. */ public String getRealName() { // Added to support OPENJPA-704 return getDefiningMetaData().getDescribedType().getName() + "." + _name; } /** * MetaData about the field value. */ public ValueMetaData getValue() { return _val; } /** * Metadata about the key value. */ public ValueMetaData getKey() { return _key; } /** * Metadata about the element value. */ public ValueMetaData getElement() { return _elem; } /** * Return whether this field is mapped to the datastore. By default, * returns true for all persistent fields whose defining class is mapped. */ public boolean isMapped() { return _manage == MANAGE_PERSISTENT && _owner.isMapped(); } /** * The type this field was initialized with, and therefore the * type to use for proxies when loading data into this field. */ public Class getProxyType() { return (_proxyClass == null) ? getDeclaredType() : _proxyClass; } /** * The type this field was initialized with, and therefore the * type to use for proxies when loading data into this field. */ public void setProxyType(Class type) { _proxyClass = type; } /** * The initializer used by the field, or null if none. This * is additional information for initializing the field, such as * a custom {@link Comparator} used by a {@link Set} or * a {@link TimeZone} used by a {@link Calendar}. */ public Object getInitializer() { return _initializer; } /** * The initializer used by the field, or null if none. This * is additional information for initializing the field, such as * a custom {@link Comparator} used by a {@link Set} or * a {@link TimeZone} used by a {@link Calendar}. */ public void setInitializer(Object initializer) { _initializer = initializer; } /** * Return whether this is a transient field. */ public boolean isTransient() { return _transient; } /** * Return whether this is a transient field. */ public void setTransient(boolean trans) { _transient = trans; } /** * The absolute index of this persistent/transactional field. */ public int getIndex() { return _index; } /** * The absolute index of this persistent/transactional field. */ public void setIndex(int index) { _index = index; } /** * The relative index of this persistent/transactional field. */ public int getDeclaredIndex() { return _decIndex; } /** * The relative index of this persistent/transactional field. */ public void setDeclaredIndex(int index) { _decIndex = index; } /** * The index in which this field was listed in the metadata. Defaults to * -1 if this field was not listed in the metadata. */ public int getListingIndex() { return _listIndex; } /** * The index in which this field was listed in the metadata. Defaults to * -1 if this field was not listed in the metadata. */ public void setListingIndex(int index) { _listIndex = index; } /** * The absolute primary key index for this field, or -1 if not a primary * key. The first primary key field has index 0, the second index 1, etc. */ public int getPrimaryKeyIndex() { return _pkIndex; } /** * The absolute primary key index for this field, or -1 if not a primary * key. The first primary key field has index 0, the second index 1, etc. */ public void setPrimaryKeyIndex(int index) { _pkIndex = index; } /** * Return the management level for the field. Will be one of: *
      *
    • {@link #MANAGE_PERSISTENT}: the field is persistent
    • *
    • {@link #MANAGE_TRANSACTIONAL}: the field is transactional but not * persistent
    • *
    • {@link #MANAGE_NONE}: the field is not managed
    • *
    Defaults to {@link #MANAGE_PERSISTENT}. */ public int getManagement() { return _manage; } /** * Return the management level for the field. Will be one of: *
      *
    • {@link #MANAGE_PERSISTENT}: the field is persistent
    • *
    • {@link #MANAGE_TRANSACTIONAL}: the field is transactional but not * persistent
    • *
    • {@link #MANAGE_NONE}: the field is not managed
    • *
    * Defaults to {@link #MANAGE_PERSISTENT}. */ public void setManagement(int manage) { if ((_manage == MANAGE_NONE) != (manage == MANAGE_NONE)) _owner.clearFieldCache(); _manage = manage; } /** * Whether this is a primary key field. */ public boolean isPrimaryKey() { return _primKey; } /** * Whether this is a primary key field. */ public void setPrimaryKey(boolean primKey) { _primKey = primKey; } /** * For a primary key field, return the type of the corresponding object id * class field. */ public int getObjectIdFieldTypeCode() { ClassMetaData relmeta = getDeclaredTypeMetaData(); if (relmeta == null) return getDeclaredTypeCode(); if (relmeta.getIdentityType() == ClassMetaData.ID_DATASTORE) { boolean unwrap = getRepository().getMetaDataFactory().getDefaults(). isDataStoreObjectIdFieldUnwrapped(); return (unwrap) ? JavaTypes.LONG : JavaTypes.OBJECT; } if (relmeta.isOpenJPAIdentity()) return relmeta.getPrimaryKeyFields()[0].getObjectIdFieldTypeCode(); return JavaTypes.OBJECT; } /** * For a primary key field, return the type of the corresponding object id * class field. */ public Class getObjectIdFieldType() { ClassMetaData relmeta = getDeclaredTypeMetaData(); if (relmeta == null || getValue().isEmbedded()) return getDeclaredType(); switch (relmeta.getIdentityType()) { case ClassMetaData.ID_DATASTORE: boolean unwrap = getRepository().getMetaDataFactory(). getDefaults().isDataStoreObjectIdFieldUnwrapped(); return (unwrap) ? long.class : Object.class; case ClassMetaData.ID_APPLICATION: if (relmeta.isOpenJPAIdentity()) return relmeta.getPrimaryKeyFields()[0]. getObjectIdFieldType(); return (relmeta.getObjectIdType() == null) ? Object.class : relmeta.getObjectIdType(); default: return Object.class; } } /** * Whether this field holds optimistic version information. */ public boolean isVersion() { return _version == Boolean.TRUE; } /** * Whether this field holds optimistic version information. */ public void setVersion(boolean version) { _version = (version) ? Boolean.TRUE : Boolean.FALSE; } /** * Whether this field is in the default fetch group. */ public boolean isInDefaultFetchGroup() { if (_dfg == 0) { if (_manage != MANAGE_PERSISTENT || isPrimaryKey() || isVersion()) _dfg = DFG_FALSE; else { // field left as default; dfg setting depends on type switch (getTypeCode()) { case JavaTypes.OBJECT: if (isSerializable() || isEnum()) _dfg = DFG_TRUE; else _dfg = DFG_FALSE; break; case JavaTypes.ARRAY: if (isLobArray()) _dfg = DFG_TRUE; else _dfg = DFG_FALSE; break; case JavaTypes.COLLECTION: case JavaTypes.MAP: case JavaTypes.PC: case JavaTypes.PC_UNTYPED: _dfg = DFG_FALSE; break; default: _dfg = DFG_TRUE; } } } return (_dfg & DFG_TRUE) > 0; } private boolean isEnum() { if (_enumField == null) { Class decl = getDeclaredType(); _enumField = Enum.class.isAssignableFrom(decl) ? Boolean.TRUE : Boolean.FALSE; } return _enumField.booleanValue(); } private boolean isSerializable() { if (_serializableField == null) { Class decl = getDeclaredType(); if (Serializable.class.isAssignableFrom(decl)) _serializableField = Boolean.TRUE; else _serializableField = Boolean.FALSE; } return _serializableField.booleanValue(); } private boolean isLobArray() { // check for byte[], Byte[], char[], Character[] if (_lobField == null) { Class decl = getDeclaredType(); if (decl == byte[].class || decl == Byte[].class || decl == char[].class || decl == Character[].class) _lobField = Boolean.TRUE; else _lobField = Boolean.FALSE; } return _lobField.booleanValue(); } /** * Whether this field is in the default fetch group. */ public void setInDefaultFetchGroup(boolean dfg) { if (dfg) _dfg = DFG_TRUE; else _dfg = DFG_FALSE; _dfg |= DFG_EXPLICIT; } /** * Whether the default fetch group setting is explicit. */ public boolean isDefaultFetchGroupExplicit() { return (_dfg & DFG_EXPLICIT) > 0; } /** * Whether the default fetch group setting is explicit. Allow setting * for testing. */ public void setDefaultFetchGroupExplicit(boolean explicit) { if (explicit) _dfg |= DFG_EXPLICIT; else _dfg &= ~DFG_EXPLICIT; } /** * Gets the name of the custom fetch groups those are associated to this * receiver. This does not include the "default" and "all" fetch groups. * * @return the set of fetch group names, not including the default and * all fetch groups. */ public String[] getCustomFetchGroups() { if (_fgs == null) { if (_fgSet == null || _manage != MANAGE_PERSISTENT || isPrimaryKey() || isVersion()) _fgs = new String[0]; else _fgs = (String[]) _fgSet.toArray(new String[_fgSet.size()]); } return _fgs; } /** * The fetch group that is to be loaded when this receiver is loaded, or * null if none set. */ public String getLoadFetchGroup () { return _lfg; } /** * The fetch group that is to be loaded when this receiver is loaded, or * null if none set. */ public void setLoadFetchGroup (String lfg) { if ("".equals(lfg)) lfg = null; _lfg = lfg; } /** * Whether this field is in the given fetch group. */ public boolean isInFetchGroup(String fg) { if (_manage != MANAGE_PERSISTENT || isPrimaryKey() || isVersion()) return false; if (FetchGroup.NAME_ALL.equals(fg)) return true; if (FetchGroup.NAME_DEFAULT.equals(fg)) return isInDefaultFetchGroup(); return _fgSet != null && _fgSet.contains(fg); } /** * Set whether this field is in the given fetch group. * * @param fg is the name of a fetch group that must be present in the * class that declared this field or any of its persistent superclasses. */ public void setInFetchGroup(String fg, boolean in) { if (StringUtils.isEmpty(fg)) throw new MetaDataException(_loc.get("empty-fg-name", this)); if (fg.equals(FetchGroup.NAME_ALL)) return; if (fg.equals(FetchGroup.NAME_DEFAULT)) { setInDefaultFetchGroup(in); return; } if (_owner.getFetchGroup(fg) == null) throw new MetaDataException(_loc.get("unknown-fg", fg, this)); if (in && _fgSet == null) _fgSet = new HashSet(); if ((in && _fgSet.add(fg)) || (!in && _fgSet != null && _fgSet.remove(fg))) _fgs = null; } /** * How the data store should treat null values for this field: *
      *
    • {@link #NULL_UNSET}: no value supplied
    • *
    • {@link #NULL_NONE}: leave null values as null in the data store
    • *
    • {@link #NULL_EXCEPTION}: throw an exception if this field is null * at commit
    • *
    • {@link #NULL_DEFAULT}: use the database default if this field is * null at commit
    • *
    Defaults to {@link #NULL_UNSET}. */ public int getNullValue() { return _nullValue; } /** * How the data store should treat null values for this field: *
      *
    • {@link #NULL_UNSET}: no value supplied
    • *
    • {@link #NULL_NONE}: leave null values as null in the data store
    • *
    • {@link #NULL_EXCEPTION}: throw an exception if this field is null * at commit
    • *
    • {@link #NULL_DEFAULT}: use the database default if this field is * null at commit
    • *
    Defaults to {@link #NULL_UNSET}. */ public void setNullValue(int nullValue) { _nullValue = nullValue; } /** * Whether this field is explicitly declared in the metadata. */ public boolean isExplicit() { return _explicit; } /** * Whether this field is explicitly declared in the metadata. */ public void setExplicit(boolean explicit) { _explicit = explicit; } /** * The field that this field shares a mapping with. */ public String getMappedBy() { return _mappedBy; } /** * The field that this field shares a mapping with. */ public void setMappedBy(String mapped) { _mappedBy = mapped; _mappedByMeta = null; } /** * The field that this field shares a mapping with. */ public FieldMetaData getMappedByMetaData() { if (_mappedBy != null && _mappedByMeta == null) { ClassMetaData meta = null; switch (getTypeCode()) { case JavaTypes.PC: meta = getTypeMetaData(); break; case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: meta = _elem.getTypeMetaData(); break; } FieldMetaData field = (meta == null) ? null : getMappedByField(meta, _mappedBy); if (field == null) throw new MetaDataException(_loc.get("no-mapped-by", this, _mappedBy)); if (field.getMappedBy() != null) throw new MetaDataException(_loc.get("circ-mapped-by", this, _mappedBy)); OpenJPAConfiguration conf = getRepository().getConfiguration(); boolean isAbstractMappingUniDirectional = getRepository().getMetaDataFactory(). getDefaults().isAbstractMappingUniDirectional(conf); if (isAbstractMappingUniDirectional) { if (field.getDeclaringMetaData().isAbstract()) throw new MetaDataException(_loc.get("no-mapped-by-in-mapped-super", field, field.getDeclaringMetaData())); if (this.getDeclaringMetaData().isAbstract()) throw new MetaDataException(_loc.get("no-mapped-by-in-mapped-super", this, this.getDeclaringMetaData())); } _mappedByMeta = field; } return _mappedByMeta; } public FieldMetaData getMappedByField(ClassMetaData meta, String mappedBy) { FieldMetaData field = meta.getField(mappedBy); if (field != null) return field; int dotIdx = mappedBy.indexOf("."); if ( dotIdx == -1) return null; String fieldName = mappedBy.substring(0, dotIdx); FieldMetaData field1 = meta.getField(fieldName); if (field1 == null) return null; ClassMetaData meta1 = field1.getEmbeddedMetaData(); if (meta1 == null) return null; String mappedBy1 = mappedBy.substring(dotIdx + 1); return getMappedByField(meta1, mappedBy1); } /** * Logical inverse field. */ public String getInverse() { if (ClassMetaData.DEFAULT_STRING.equals(_inverse)) _inverse = null; return _inverse; } /** * Logical inverse field. */ public void setInverse(String inverse) { _inverses = null; _inverse = inverse; } /** * Return all inverses of this field. */ public FieldMetaData[] getInverseMetaDatas() { if (_inverses == null) { // can't declare both an inverse owner and a logical inverse String inv = getInverse(); if (_mappedBy != null && inv != null && !_mappedBy.equals(inv)) throw new MetaDataException(_loc.get("mapped-not-inverse", this)); // get the metadata for the type on the other side of this relation ClassMetaData meta = null; switch (getTypeCode()) { case JavaTypes.PC: meta = getTypeMetaData(); break; case JavaTypes.ARRAY: case JavaTypes.COLLECTION: case JavaTypes.MAP: meta = _elem.getTypeMetaData(); break; } Collection inverses = null; if (meta != null) { // add mapped by and named inverse, if any FieldMetaData field = getMappedByMetaData(); if (field != null) { // mapped by field isn't necessarily a pc type, but all // inverses must be if (field.getTypeCode() == JavaTypes.PC || field.getElement().getTypeCode() == JavaTypes.PC) { inverses = new ArrayList(3); inverses.add(field); } } else if (inv != null) { field = meta.getField(inv); if (field == null) throw new MetaDataException(_loc.get("no-inverse", this, inv)); inverses = new ArrayList(3); inverses.add(field); } // scan rel type for fields that name this field as an inverse FieldMetaData[] fields = meta.getFields(); Class type = getDeclaringMetaData().getDescribedType(); for (int i = 0; i < fields.length; i++) { // skip fields that aren't compatible with our owning class switch (fields[i].getTypeCode()) { case JavaTypes.PC: if (!type.isAssignableFrom(fields[i].getType())) continue; break; case JavaTypes.COLLECTION: case JavaTypes.ARRAY: if (!type.isAssignableFrom(fields[i]. getElement().getType())) continue; break; default: continue; } // if the field declares us as its inverse and we haven't // already added it (we might have if we also declared it // as our inverse), add it now if (_name.equals(fields[i].getMappedBy()) || _name.equals(fields[i].getInverse())) { if (inverses == null) inverses = new ArrayList(3); if (!inverses.contains(fields[i])) inverses.add(fields[i]); } } } MetaDataRepository repos = getRepository(); if (inverses == null) _inverses = repos.EMPTY_FIELDS; else _inverses = inverses.toArray (repos.newFieldMetaDataArray(inverses.size())); } return _inverses; } /** * The strategy to use for insert value generation. * One of the constants from {@link ValueStrategies}. */ public int getValueStrategy() { if (_valStrategy == -1) _valStrategy = ValueStrategies.NONE; return _valStrategy; } /** * The strategy to use for insert value generation. * One of the constants from {@link ValueStrategies}. */ public void setValueStrategy(int strategy) { _valStrategy = strategy; if (strategy != ValueStrategies.SEQUENCE) setValueSequenceName(null); } /** * The value sequence name, or null for none. */ public String getValueSequenceName() { if (ClassMetaData.DEFAULT_STRING.equals(_seqName)) _seqName = null; return _seqName; } /** * The value sequence name, or null for none. */ public void setValueSequenceName(String seqName) { _seqName = seqName; _seqMeta = null; if (seqName != null) setValueStrategy(ValueStrategies.SEQUENCE); } /** * Metadata for the value sequence. */ public SequenceMetaData getValueSequenceMetaData() { if (_seqMeta == null && getValueSequenceName() != null) _seqMeta = getRepository().getSequenceMetaData(_owner, getValueSequenceName(), true); return _seqMeta; } /** * The strategy to use when updating the field. */ public int getUpdateStrategy() { if (isVersion()) return UpdateStrategies.RESTRICT; if (_upStrategy == -1) _upStrategy = UpdateStrategies.NONE; return _upStrategy; } /** * Set the update strategy. */ public void setUpdateStrategy(int strategy) { _upStrategy = strategy; } /** * Whether this field is backed by a large result set. */ public boolean isLRS() { return _lrs == Boolean.TRUE && _manage == MANAGE_PERSISTENT; } /** * Whether this field is backed by a large result set. */ public void setLRS(boolean lrs) { _lrs = (lrs) ? Boolean.TRUE : Boolean.FALSE; } /** * Whether this field is backed by a stream. * * @since 1.1.0 */ public boolean isStream() { return _stream == Boolean.TRUE && _manage == MANAGE_PERSISTENT; } /** * Whether this field is backed by a stream. * * @since 1.1.0 */ public void setStream(boolean stream) { _stream = (stream) ? Boolean.TRUE : Boolean.FALSE; } /** * Whether this field uses intermediate data when loading/storing * information through a {@link OpenJPAStateManager}. Defaults to true. * * @see OpenJPAStateManager#setIntermediate(int,Object) */ public boolean usesIntermediate() { return _intermediate; } /** * Whether this field uses intermediate data when loading/storing * information through a {@link OpenJPAStateManager}. Defaults to true. * * @see OpenJPAStateManager#setIntermediate(int,Object) */ public void setUsesIntermediate(boolean intermediate) { _intermediate = intermediate; _owner.clearExtraFieldDataTable(); } /** * Whether this field uses impl data in conjunction with standard * field data when acting on a {@link OpenJPAStateManager}. * Defaults to {@link Boolean#TRUE} (non-cachable impl data). * * @return {@link Boolean#FALSE} if this field does not use impl data, * {@link Boolean#TRUE} if this field uses non-cachable impl * data, or null if this field uses impl data that * should be cached across instances * @see OpenJPAStateManager#setImplData(int,Object) */ public Boolean usesImplData() { return _implData; } /** * Whether this field uses impl data in conjunction with standard * field data when acting on a {@link OpenJPAStateManager}. * * @see OpenJPAStateManager#setImplData(int,Object) * @see #usesImplData */ public void setUsesImplData(Boolean implData) { _implData = implData; _owner.clearExtraFieldDataTable(); } /** * The orderings for this field to be applied on load, or empty array. */ public Order[] getOrders() { if (_orders == null) { if (_orderDec == null) _orders = getRepository().EMPTY_ORDERS; else { String[] decs = Strings.split(_orderDec, ",", 0); Order[] orders = getRepository().newOrderArray(decs.length); int spc; boolean asc; for (int i = 0; i < decs.length; i++) { decs[i] = decs[i].trim(); spc = decs[i].indexOf(' '); if (spc == -1) asc = true; else { asc = decs[i].substring(spc + 1).trim(). toLowerCase().startsWith("asc"); decs[i] = decs[i].substring(0, spc); } orders[i] = getRepository().newOrder(this, decs[i], asc); //set "isUsedInOrderBy" to the field ClassMetaData elemCls = getElement() .getDeclaredTypeMetaData(); if (elemCls != null) { FieldMetaData fmd = elemCls.getDeclaredField(decs[i]); if (fmd != null) fmd.setUsedInOrderBy(true); } } _orders = orders; } } return _orders; } /** * The orderings for this field to be applied on load. */ public void setOrders(Order[] orders) { _orderDec = null; _orders = orders; } /** * String declaring the orderings for this field to be applied on load, * or null. The string is of the form:
    * orderable[ asc|desc][, ...]
    * The orderable #element is used to denote the value of * the field's elements. */ public String getOrderDeclaration() { if (_orderDec == null && _orders != null) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < _orders.length; i++) { if (i > 0) buf.append(", "); buf.append(_orders[i].getName()).append(" "); buf.append((_orders[i].isAscending()) ? "asc" : "desc"); } _orderDec = buf.toString(); } return _orderDec; } /** * String declaring the orderings for this field to be applied on load, * or null. The string is of the form:
    * orderable[ asc|desc][, ...]
    * The orderable #element is used to denote the value of * the field's elements. */ public void setOrderDeclaration(String dec) { _orderDec = StringUtils.trimToNull(dec); _orders = null; } /** * Order this field value when it is loaded. */ public Object order(Object val) { if (val == null) return null; Order[] orders = getOrders(); if (orders.length == 0) return val; // create a comparator for the elements of the value Comparator comp; if (orders.length == 1) comp = orders[0].getComparator(); else { List> comps = null; Comparator curComp; for (int i = 0; i < orders.length; i++) { curComp = orders[i].getComparator(); if (curComp != null) { if (comps == null) comps = new ArrayList>(orders.length); if (i != comps.size()) throw new MetaDataException(_loc.get ("mixed-inmem-ordering", this)); comps.add(curComp); } } if (comps == null) comp = null; else comp = new ComparatorChain(comps); } if (comp == null) return val; // sort switch (getTypeCode()) { case JavaTypes.ARRAY: List l = JavaTypes.toList(val, _elem.getType(), true); Collections.sort(l, (Comparator) comp); return JavaTypes.toArray(l, _elem.getType()); case JavaTypes.COLLECTION: if (val instanceof List) Collections.sort((List) val, (Comparator) comp); return val; default: throw new MetaDataException(_loc.get("cant-order", this)); } } /** * Whether the field is externalized. */ public boolean isExternalized() { return getExternalizerMethod() != null || getExternalValueMap() != null; } /** * Convert the given field value to its external value through the * provided externalizer, or return the value as-is if no externalizer. */ public Object getExternalValue(Object val, StoreContext ctx) { Map extValues = getExternalValueMap(); if (extValues != null) { Object foundVal = extValues.get(val); if (foundVal == null) { throw new UserException(_loc.get("bad-externalized-value", new Object[] { val, extValues.keySet(), this })) .setFatal(true).setFailedObject(val); } else { return foundVal; } } Method externalizer = getExternalizerMethod(); if (externalizer == null) return val; // special case for queries: allow the given value to pass through // as-is if it is already in externalized form if (val != null && getType().isInstance(val) && (!getDeclaredType().isInstance(val) || getDeclaredType() == Object.class)) return val; try { // either invoke the static toExternal(val[, ctx]) method, or the // non-static val.toExternal([ctx]) method if (Modifier.isStatic(externalizer.getModifiers())) { if (externalizer.getParameterTypes().length == 1) return externalizer.invoke(null, new Object[]{ val }); return externalizer.invoke(null, new Object[]{ val, ctx }); } if (val == null) return null; if (externalizer.getParameterTypes().length == 0) return externalizer.invoke(val, (Object[]) null); return externalizer.invoke(val, new Object[]{ ctx }); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { throw new MetaDataException(_loc.get("externalizer-err", this, Exceptions.toString(val), e.toString())).setCause(e); } } /** * Return the result of passing the given external value through the * factory to get the field value. If no factory is present, * the given value is returned as-is. */ public Object getFieldValue(Object val, StoreContext ctx) { Map fieldValues = getFieldValueMap(); if (fieldValues != null) return fieldValues.get(val); Member factory = getFactoryMethod(); if (factory == null) return val; try { if (val == null && getNullValue() == NULL_DEFAULT) return AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(getDeclaredType())); // invoke either the constructor for the field type, // or the static type.toField(val[, ctx]) method if (factory instanceof Constructor) { if (val == null) return null; return ((Constructor) factory).newInstance (new Object[]{ val }); } Method meth = (Method) factory; if (meth.getParameterTypes().length == 1) return meth.invoke(null, new Object[]{ val }); return meth.invoke(null, new Object[]{ val, ctx }); } catch (Exception e) { // unwrap cause if (e instanceof InvocationTargetException) { Throwable t = ((InvocationTargetException) e). getTargetException(); if (t instanceof Error) throw (Error) t; e = (Exception) t; // allow null values to cause NPEs and illegal arg exceptions // without error if (val == null && (e instanceof NullPointerException || e instanceof IllegalArgumentException)) return null; } if (e instanceof OpenJPAException) throw (OpenJPAException) e; if (e instanceof PrivilegedActionException) e = ((PrivilegedActionException) e).getException(); throw new MetaDataException(_loc.get("factory-err", this, Exceptions.toString(val), e.toString())).setCause(e); } } /** * The name of this field's externalizer, or null if none. */ public String getExternalizer() { return _extName; } /** * The name of this field's externalizer, or null if none. */ public void setExternalizer(String externalizer) { _extName = externalizer; _extMethod = DEFAULT_METHOD; } /** * The name of this field's factory, or null if none. */ public String getFactory() { return _factName; } /** * The name of this field's factory, or null if none. */ public void setFactory(String factory) { _factName = factory; _factMethod = DEFAULT_METHOD; } /** * Properties string mapping field values to external values. */ public String getExternalValues() { return _extString; } /** * Properties string mapping field values to external values. */ public void setExternalValues(String values) { _extString = values; _extValues = null; } /** * Return the mapping of field values to external values. */ public Map getExternalValueMap() { parseExternalValues(); return _extValues; } /** * Return the mapping of external values to field values. */ public Map getFieldValueMap() { parseExternalValues(); return _fieldValues; } /** * Parse external values into maps. */ private void parseExternalValues() { if (_extValues != Collections.EMPTY_MAP && _fieldValues != Collections.EMPTY_MAP) return; if (_extString == null) { _extValues = null; _fieldValues = null; return; } // parse string into options; this takes care of proper trimming etc Options values = Configurations.parseProperties(_extString); if (values.isEmpty()) throw new MetaDataException(_loc.get("no-external-values", this, _extString)); Map extValues = new HashMap((int) (values.size() * 1.33 + 1)); Map fieldValues = new HashMap((int) (values.size() * 1.33 + 1)); Map.Entry entry; Object extValue, fieldValue; for (Iterator itr = values.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); fieldValue = transform((String) entry.getKey(), getDeclaredTypeCode()); extValue = transform((String) entry.getValue(), getTypeCode()); extValues.put(fieldValue, extValue); fieldValues.put(extValue, fieldValue); } _extValues = extValues; _fieldValues = fieldValues; } /** * Return the string value converted to the given type code. The string * must be non-null and trimmed. */ private Object transform(String val, int typeCode) { if ("null".equals(val)) return null; switch (typeCode) { case JavaTypes.BOOLEAN: case JavaTypes.BOOLEAN_OBJ: return Boolean.valueOf(val); case JavaTypes.BYTE: case JavaTypes.BYTE_OBJ: return Byte.valueOf(val); case JavaTypes.INT: case JavaTypes.INT_OBJ: return Integer.valueOf(val); case JavaTypes.LONG: case JavaTypes.LONG_OBJ: return Long.valueOf(val); case JavaTypes.SHORT: case JavaTypes.SHORT_OBJ: return Short.valueOf(val); case JavaTypes.DOUBLE: case JavaTypes.DOUBLE_OBJ: return Double.valueOf(val); case JavaTypes.FLOAT: case JavaTypes.FLOAT_OBJ: return Float.valueOf(val); case JavaTypes.CHAR: case JavaTypes.CHAR_OBJ: return Character.valueOf(val.charAt(0)); case JavaTypes.STRING: return val; case JavaTypes.ENUM: return Enum.valueOf((Class)getDeclaredType(), val); } throw new MetaDataException(_loc.get("bad-external-type", this)); } /** * The externalizer method. */ public Method getExternalizerMethod() { if (_manage != MANAGE_PERSISTENT) return null; if (_extMethod == DEFAULT_METHOD) { if (_extName != null) { _extMethod = findMethod(_extName); if (_extMethod == null) throw new MetaDataException(_loc.get("bad-externalizer", this, _extName)); } else _extMethod = null; } return _extMethod; } /** * The factory method or constructor. */ public Member getFactoryMethod() { if (_manage != MANAGE_PERSISTENT) return null; if (_factMethod == DEFAULT_METHOD) { if (getExternalizerMethod() == null) _factMethod = null; else { try { if (_factName == null) _factMethod = getDeclaredType().getConstructor (new Class[]{ getType() }); else _factMethod = findMethodByNameAndType(_factName, getType()); } catch (OpenJPAException ke) { throw ke; } catch (Exception e) { } if (!(_factMethod instanceof Constructor) && !(_factMethod instanceof Method)) throw new MetaDataException(_loc.get("bad-factory", this)); } } return _factMethod; } /** * Find the method for the specified name. Possible forms are: *
      *
    • toExternalString
    • *
    • MyFactoryClass.toExternalString
    • *
    • com.company.MyFactoryClass.toExternalString
    • *
    * * @param method the name of the method to locate * @return the method for invocation */ private Method findMethod(String method) { return findMethodByNameAndType(method, null); } /** * Find the method for the specified name and type. Possible forms are: *
      *
    • toExternalString
    • *
    • MyFactoryClass.toExternalString
    • *
    • com.company.MyFactoryClass.toExternalString
    • *
    * * @param method the name of the method to locate * @param type The type of the parameter which will pass the object from the database. * @return the method for invocation */ private Method findMethodByNameAndType(String method, Class type) { if (StringUtils.isEmpty(method)) return null; // get class name and get package name divide on the last '.', so the // names don't apply in this case, but the methods do what we want String methodName = Strings.getClassName(method); String clsName = Strings.getPackageName(method); Class cls = null; Class owner = _owner.getDescribedType(); if (clsName.length() == 0) cls = getDeclaredType(); else if (clsName.equals(owner.getName()) || clsName.equals(Strings.getClassName(owner))) cls = owner; else cls = JavaTypes.classForName(clsName, this); // find the named method Method[] methods = cls.getMethods(); Class[] params; for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(methodName)) { params = methods[i].getParameterTypes(); // static factory methods require one argument or one argument // plus a context; non-static methods require zero arguments or // just a context if (Modifier.isStatic(methods[i].getModifiers()) && (params.length == 1 || (params.length == 2 && isStoreContextParameter(params[1])))) if (type == null) { return methods[i]; } else if (isConvertibleToByMethodInvocationConversion(type, params[0])) { return methods[i]; } if (!Modifier.isStatic(methods[i].getModifiers()) && (params.length == 0 || (params.length == 1 && isStoreContextParameter(params[0])))) return methods[i]; } } return null; } /** * Test if the {@code sourceType} is convertible to the {@code destType}. * Convertible follows the rules in Java Language Specification, 3rd Ed, s5.3 and means that: *