- Added aspectj library dependencies : eu.etaxonomy.taxeditor.cdmlib/META-INF/MANIFEST.MF, eu.etaxonomy.taxeditor.cdmlib/META-INF/aop.xml, eu.etaxonomy.taxeditor.cdmlib/pom.xml, eu.etaxonomy.taxeditor.cdmlib/lib/aspectjrt-1.7.1-sources.jar, eu.etaxonomy.taxeditor.cdmlib/lib/aspectjweaver-1.7.1-sources.jar
- Added aspects to initialize cdm entites / collections remotely : eu.etaxonomy.taxeditor.cdmlib/META-INF/aop.xml, eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/api/lazyloading/CdmLazyLoader.java
- Hibernate classes to be aspect woven (need these explicitly on client-side to set serial uuid) : eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java, eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java
- remote spring application context config files : eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remotingApplicationContext.xml, remoting_persistence_security.xml, httpInvokerServiceClients.xml, remoting_services_security.xml
- Remote application controller which uses the remote spring application context : eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/ICdmApplicationRemoteConfiguration.java,CdmApplicationRemoteController.java, CdmApplicationRemoteDefaultConfiguration.java
- Initial tests for remoting : eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/RemoteLazyLoadingTest.java, CdmApplicationRemoteControllerTest.java
eu.etaxonomy.taxeditor.cdmlib/.classpath -text
eu.etaxonomy.taxeditor.cdmlib/.project -text
eu.etaxonomy.taxeditor.cdmlib/META-INF/MANIFEST.MF -text
+eu.etaxonomy.taxeditor.cdmlib/META-INF/aop.xml -text
eu.etaxonomy.taxeditor.cdmlib/README.txt -text
eu.etaxonomy.taxeditor.cdmlib/build.properties -text
eu.etaxonomy.taxeditor.cdmlib/lib/activation-1.1.1.jar -text
eu.etaxonomy.taxeditor.cdmlib/lib/antlr-2.7.7.jar -text
eu.etaxonomy.taxeditor.cdmlib/lib/aopalliance-1.0.jar -text
+eu.etaxonomy.taxeditor.cdmlib/lib/aspectjrt-1.7.1-sources.jar -text
eu.etaxonomy.taxeditor.cdmlib/lib/aspectjrt-1.7.1.jar -text
+eu.etaxonomy.taxeditor.cdmlib/lib/aspectjweaver-1.7.1-sources.jar -text
eu.etaxonomy.taxeditor.cdmlib/lib/aspectjweaver-1.7.1.jar -text
eu.etaxonomy.taxeditor.cdmlib/lib/avro-1.6.3.jar -text
eu.etaxonomy.taxeditor.cdmlib/lib/batik-anim-1.7.jar -text
eu.etaxonomy.taxeditor.cdmlib/lib/xstream-1.4.4.jar -text
eu.etaxonomy.taxeditor.cdmlib/lib/yjp-controller-api-redist-9.0.8.jar -text
eu.etaxonomy.taxeditor.cdmlib/pom.xml -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/api/lazyloading/CdmLazyLoader.java -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/CdmApplicationRemoteController.java -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/CdmApplicationRemoteDefaultConfiguration.java -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/ICdmApplicationRemoteConfiguration.java -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/httpInvokerServiceClients.xml -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remotingApplicationContext.xml -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remoting_persistence_security.xml -text
+eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remoting_services_security.xml -text
+eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/CdmApplicationRemoteControllerTest.java -text
+eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/RemoteLazyLoadingTest.java -text
eu.etaxonomy.taxeditor.editor/.classpath -text
eu.etaxonomy.taxeditor.editor/.project -text
eu.etaxonomy.taxeditor.editor/META-INF/MANIFEST.MF -text
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" path="src/test/java"/>
+ <classpathentry kind="src" path="src/main/resources"/>
<classpathentry exported="true" kind="lib" path="lib/activation-1.1.1.jar"/>
<classpathentry exported="true" kind="lib" path="lib/antlr-2.7.7.jar"/>
<classpathentry exported="true" kind="lib" path="lib/aopalliance-1.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/cdmlib-io-3.3.0-SNAPSHOT-sources.jar"/>
<classpathentry exported="true" kind="lib" path="lib/cdmlib-io-3.3.0-SNAPSHOT.jar"/>
<classpathentry exported="true" kind="lib" path="lib/cdmlib-model-3.3.0-SNAPSHOT-sources.jar"/>
- <classpathentry exported="true" kind="lib" path="lib/cdmlib-model-3.3.0-SNAPSHOT.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/cdmlib-model-3.3.0-SNAPSHOT.jar" sourcepath="lib/cdmlib-model-3.3.0-SNAPSHOT-sources.jar"/>
<classpathentry exported="true" kind="lib" path="lib/cdmlib-persistence-3.3.0-SNAPSHOT-sources.jar"/>
- <classpathentry exported="true" kind="lib" path="lib/cdmlib-persistence-3.3.0-SNAPSHOT.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/cdmlib-persistence-3.3.0-SNAPSHOT.jar" sourcepath="lib/cdmlib-persistence-3.3.0-SNAPSHOT-sources.jar"/>
<classpathentry exported="true" kind="lib" path="lib/cdmlib-print-3.3.0-SNAPSHOT-sources.jar"/>
<classpathentry exported="true" kind="lib" path="lib/cdmlib-print-3.3.0-SNAPSHOT.jar"/>
<classpathentry exported="true" kind="lib" path="lib/cdmlib-remote-3.3.0-SNAPSHOT-sources.jar"/>
eu.etaxonomy.cdm.print.out.pdf,
eu.etaxonomy.cdm.print.out.taxpub,
eu.etaxonomy.cdm.print.out.xml,
+ eu.etaxonomy.cdm.remote.api.application,
eu.etaxonomy.cdm.remote.config,
eu.etaxonomy.cdm.remote.controller,
eu.etaxonomy.cdm.remote.controller.csv,
--- /dev/null
+<!DOCTYPE aspectj PUBLIC
+ "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
+<aspectj>
+ <weaver options="-verbose -showWeaveInfo">
+ <include within="org.hibernate.proxy.*" />
+ <include within="org.hibernate.collection.internal.*" />
+ <include within="eu.etaxonomy.cdm.api.lazyloading.*" />
+ </weaver>
+ <aspects>
+ <!-- use only this aspect for weaving -->
+ <aspect name="eu.etaxonomy.cdm.api.lazyloading.CdmLazyLoader" />
+
+ </aspects>
+
+</aspectj>
+
\ No newline at end of file
lib/odfdom-0.8.jar,\\r
lib/h2mig_pagestore_addon.jar,\\r
lib/spring-security-remoting-3.1.3.RELEASE.jar\r
+jars.compile.order = .\r
+output.. = bin/\r
+source.. = src/main/java/,\\r
+ src/main/resources/,\\r
+ src/test/java/\r
\r
<artifactId>cdmlib-ext</artifactId>\r
<version>${cdmlib.version}</version>\r
</dependency>\r
+ <dependency>\r
+ <groupId>org.aspectj</groupId>\r
+ <artifactId>aspectjrt</artifactId>\r
+ <version>1.7.1</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.aspectj</groupId>\r
+ <artifactId>aspectjweaver</artifactId>\r
+ <version>1.7.1</version>\r
+ </dependency>\r
<!-- for ikey-plus \r
TODO this should not be needed but the utils class contained in this jar \r
seems to be loaded as bean by spring\r
--- /dev/null
+package eu.etaxonomy.cdm.api.lazyloading;
+
+import java.beans.Transient;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.hibernate.collection.internal.PersistentList;
+import org.hibernate.collection.internal.PersistentMap;
+import org.hibernate.collection.internal.PersistentSet;
+import org.hibernate.collection.internal.PersistentSortedMap;
+import org.hibernate.collection.internal.PersistentSortedSet;
+import org.hibernate.collection.spi.PersistentCollection;
+import org.hibernate.proxy.LazyInitializer;
+import org.springframework.beans.factory.annotation.Autowire;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Configurable;
+import org.springframework.stereotype.Component;
+
+import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
+import eu.etaxonomy.cdm.api.service.ICommonService;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.common.PersistentMultiLanguageText;
+
+
+@Aspect
+@Component
+@Configurable(autowire = Autowire.BY_TYPE)
+public class CdmLazyLoader {
+
+
+ private Set classes = new HashSet();
+
+ public static boolean enableWeaving = true;
+ private static Set<String> classesToIgnore = new HashSet<String>();
+
+
+ @Autowired
+ private ICommonService commonService;
+
+ public CdmLazyLoader() {
+ //classesToIgnore.add("eu.etaxonomy.cdm.model.common.TermVocabulary");
+ //classesToIgnore.add("eu.etaxonomy.cdm.model.common.OrderedTermVocabulary");
+
+ }
+
+ /**
+ * Point cut for the 'initialize' method of the AbstractLazyInitializer.
+ *
+ */
+ @Pointcut("execution(* org.hibernate.proxy.AbstractLazyInitializer.initialize())")
+ public void possibleEntityLazyInitializationException() {
+ }
+
+
+ /**
+ * 'Around' advice for the initialization of CDM Entity Objects
+ *
+ */
+ @Around(value = "possibleEntityLazyInitializationException()")
+ public Object preloadEntityOnDemand(ProceedingJoinPoint pjp) throws Throwable {
+ if(enableWeaving) {
+ LazyInitializer ll = (LazyInitializer)pjp.getTarget();
+ if(ll.isUninitialized()) {
+ int classid = ((Integer)ll.getIdentifier()).intValue();
+ System.out.print("--> AspectJ Compile-Time Weaving " + ll.getEntityName() + " with id " + classid);
+ Class clazz = (Class<? extends CdmBase>) Class.forName(ll.getEntityName());
+ CdmBase cdmBase = CdmBase.deproxy(commonService.find(clazz,classid),clazz);
+ ll.setImplementation(cdmBase);
+ System.out.println("....Done");
+ }
+ }
+ return pjp.proceed();
+ }
+
+
+ /**
+ * Point cut for the 'initialize' method of the AbstractPersistentCollection.
+ *
+ */
+ @Pointcut("execution(protected final void org.hibernate.collection.internal.AbstractPersistentCollection.initialize(..))")
+ public void possibleCollectionLazyInitializationException() {
+ }
+
+ /**
+ * 'Around' advice for the initialization of Collection objects
+ *
+ */
+ @Around(value = "possibleCollectionLazyInitializationException()")
+ @Transient
+ public Object preloadCollectionOnDemand(ProceedingJoinPoint pjp) throws Throwable {
+ if(enableWeaving) {
+ PersistentCollection ps = (PersistentCollection) pjp.getTarget();
+ if (ps.getOwner() != null && !classesToIgnore.contains(ps.getOwner().getClass().getName()) && !ps.wasInitialized() && !classes.contains(ps.getKey())) {
+ System.out.print("--> AspectJCompile-Time Weaving " + ps.getRole());
+ classes.add(ps.getKey());
+ try {
+ String role = ps.getRole();
+ String fieldName = role.substring(role.lastIndexOf(".") + 1);
+ System.out.print(", field : " + fieldName);
+ Object owner = ps.getOwner();
+
+ PersistentCollection col = commonService.initializeCollection(ps);
+ ps.afterInitialize();
+
+ Class<?> clazz = ps.getClass();
+ if (clazz != null) {
+ CollectionField cf = getCollectionField(col);
+ Field field = clazz.getDeclaredField(cf.getFieldName());
+ field.setAccessible(true);
+ field.set(ps, cf.getCollection());
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ System.out.println("Error in ReattachSessionAspect : " + ex.getMessage());
+ } finally {
+ classes.remove(ps.getKey());
+ System.out.println("....Done");
+ }
+ }
+ }
+ return pjp.proceed();
+
+ }
+
+ private CollectionField getCollectionField(PersistentCollection pc) {
+ if(pc != null) {
+ if(pc instanceof PersistentSet) {
+ return new CollectionField(new HashSet((Set)pc), "set");
+ }
+ if(pc instanceof PersistentSortedSet) {
+ return new CollectionField(new TreeSet((Set)pc), "set");
+ }
+ if(pc instanceof PersistentList) {
+ return new CollectionField(new ArrayList((List)pc), "list");
+ }
+ if(pc instanceof PersistentMap || pc instanceof PersistentMultiLanguageText) {
+ return new CollectionField(new HashMap((Map)pc), "map");
+ }
+ if(pc instanceof PersistentSortedMap) {
+ return new CollectionField(new TreeMap((Map)pc), "map");
+ }
+ }
+ return null;
+ }
+
+ private String getCollectionFieldName(PersistentCollection pc) {
+ if(pc != null) {
+ if(pc instanceof PersistentSet || pc instanceof PersistentSortedSet) {
+ return "set";
+ }
+
+ if(pc instanceof PersistentList) {
+ return "list";
+ }
+ if(pc instanceof PersistentMap || pc instanceof PersistentMultiLanguageText) {
+ return "map";
+ }
+ }
+ return null;
+ }
+
+ private class CollectionField {
+ private Object col;
+ private String fieldName;
+ public CollectionField(Object col, String fieldName) {
+ this.col = col;
+ this.fieldName = fieldName;
+ }
+
+ public Object getCollection() {
+ return this.col;
+ }
+
+ public String getFieldName() {
+ return this.fieldName;
+ }
+ }
+
+}
--- /dev/null
+// $Id: CdmApplicationController.java 11680 2011-04-04 17:07:39Z a.mueller $\r
+/**\r
+ * Copyright (C) 2007 EDIT\r
+ * European Distributed Institute of Taxonomy \r
+ * http://www.e-taxonomy.eu\r
+ * \r
+ * The contents of this file are subject to the Mozilla Public License Version 1.1\r
+ * See LICENSE.TXT at the top of this package for the full license terms.\r
+ */\r
+\r
+\r
+package eu.etaxonomy.cdm.remote.api.application;\r
+\r
+import java.util.UUID;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;\r
+import org.springframework.context.support.AbstractApplicationContext;\r
+import org.springframework.context.support.GenericApplicationContext;\r
+import org.springframework.core.io.ClassPathResource;\r
+import org.springframework.core.io.Resource;\r
+import org.springframework.security.access.PermissionEvaluator;\r
+import org.springframework.security.authentication.ProviderManager;\r
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\r
+import org.springframework.security.core.Authentication;\r
+import org.springframework.security.core.context.SecurityContext;\r
+import org.springframework.security.core.context.SecurityContextHolder;\r
+import org.springframework.transaction.PlatformTransactionManager;\r
+//import org.springframework.transaction.PlatformTransactionManager;\r
+import org.springframework.transaction.TransactionStatus;\r
+\r
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;\r
+import eu.etaxonomy.cdm.api.service.IAgentService;\r
+import eu.etaxonomy.cdm.api.service.IClassificationService;\r
+import eu.etaxonomy.cdm.api.service.ICollectionService;\r
+import eu.etaxonomy.cdm.api.service.ICommonService;\r
+import eu.etaxonomy.cdm.api.service.IDatabaseService;\r
+import eu.etaxonomy.cdm.api.service.IDescriptionService;\r
+import eu.etaxonomy.cdm.api.service.IFeatureNodeService;\r
+import eu.etaxonomy.cdm.api.service.IFeatureTreeService;\r
+import eu.etaxonomy.cdm.api.service.IGrantedAuthorityService;\r
+import eu.etaxonomy.cdm.api.service.IGroupService;\r
+import eu.etaxonomy.cdm.api.service.IIdentificationKeyService;\r
+import eu.etaxonomy.cdm.api.service.ILocationService;\r
+import eu.etaxonomy.cdm.api.service.IMediaService;\r
+import eu.etaxonomy.cdm.api.service.INameService;\r
+import eu.etaxonomy.cdm.api.service.IOccurrenceService;\r
+import eu.etaxonomy.cdm.api.service.IPolytomousKeyNodeService;\r
+import eu.etaxonomy.cdm.api.service.IPolytomousKeyService;\r
+import eu.etaxonomy.cdm.api.service.IReferenceService;\r
+import eu.etaxonomy.cdm.api.service.IService;\r
+import eu.etaxonomy.cdm.api.service.ITaxonNodeService;\r
+import eu.etaxonomy.cdm.api.service.ITaxonService;\r
+import eu.etaxonomy.cdm.api.service.ITermService;\r
+import eu.etaxonomy.cdm.api.service.IUserService;\r
+import eu.etaxonomy.cdm.api.service.IVocabularyService;\r
+import eu.etaxonomy.cdm.api.service.IWorkingSetService;\r
+import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;\r
+import eu.etaxonomy.cdm.common.monitor.NullProgressMonitor;\r
+import eu.etaxonomy.cdm.model.common.CdmBase;\r
+import eu.etaxonomy.cdm.model.common.DefinedTermBase;\r
+\r
+\r
+/**\r
+ * @author a.mueller\r
+ * @author j.koch\r
+ *\r
+ */\r
+public class CdmApplicationRemoteController implements ICdmApplicationRemoteConfiguration {\r
+ private static final Logger logger = Logger.getLogger(CdmApplicationRemoteController.class);\r
+ \r
+ public static final String DEFAULT_APPLICATION_CONTEXT_RESOURCE = "/eu/etaxonomy/cdm/remotingApplicationContext.xml";\r
+ \r
+ public AbstractApplicationContext applicationContext;\r
+ private ICdmApplicationRemoteConfiguration configuration; \r
+ private Resource applicationContextResource;\r
+ private IProgressMonitor progressMonitor;\r
+ \r
+ /**\r
+ * Constructor, opens a spring ApplicationContext with defaults\r
+ */\r
+ public static CdmApplicationRemoteController NewInstance() {\r
+ logger.info("Configure CdmApplicationRemoteController with defaults");\r
+ return new CdmApplicationRemoteController(null, null);\r
+ }\r
+ \r
+ /**\r
+ * Constructor, opens a spring ApplicationContext with given application context\r
+ * @param applicationContextResource\r
+ */\r
+ public static CdmApplicationRemoteController NewInstance(Resource applicationContextResource, IProgressMonitor progressMonitor) {\r
+ logger.info("Configure CdmApplicationRemoteController with given application context");\r
+ return new CdmApplicationRemoteController(applicationContextResource, progressMonitor);\r
+ }\r
+\r
+ /**\r
+ * Constructor, starts the application remote controller\r
+ * @param applicationContextResource\r
+ */\r
+ private CdmApplicationRemoteController(Resource applicationContextResource, IProgressMonitor progressMonitor){\r
+ logger.info("Start CdmApplicationRemoteController");\r
+ this.applicationContextResource = applicationContextResource != null ? applicationContextResource : new ClassPathResource(DEFAULT_APPLICATION_CONTEXT_RESOURCE);\r
+ this.progressMonitor = progressMonitor != null ? progressMonitor : new NullProgressMonitor();\r
+ setNewApplicationContext();\r
+ }\r
+ \r
+ /**\r
+ * Sets the application context to a new spring ApplicationContext and initializes the Controller\r
+ */\r
+ private boolean setNewApplicationContext(){\r
+ logger.info("Set new application context");\r
+ progressMonitor.beginTask("Start application context.", 6);\r
+ progressMonitor.worked(1);\r
+\r
+ GenericApplicationContext applicationContext = new GenericApplicationContext();\r
+ \r
+ XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(applicationContext);\r
+ progressMonitor.subTask("Registering resources.");\r
+ xmlReader.loadBeanDefinitions(applicationContextResource);\r
+ progressMonitor.worked(1);\r
+ \r
+ progressMonitor.subTask("This might take a while ...");\r
+ applicationContext.refresh();\r
+ applicationContext.start();\r
+ progressMonitor.worked(1);\r
+ \r
+ progressMonitor.subTask("Cleaning up.");\r
+ setApplicationContext(applicationContext);\r
+ progressMonitor.done();\r
+ return true;\r
+ }\r
+ \r
+ /**\r
+ * Tests if some DefinedTermsAreMissing.\r
+ * @return true, if at least one is missing, else false\r
+ */\r
+ public boolean testDefinedTermsAreMissing(){\r
+ UUID englishUuid = UUID.fromString("e9f8cdb7-6819-44e8-95d3-e2d0690c3523");\r
+ DefinedTermBase<?> english = this.getTermService().find(englishUuid);\r
+ if ( english == null || ! english.getUuid().equals(englishUuid)){\r
+ return true;\r
+ }else{\r
+ return false;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Sets a new application Context.\r
+ * @param ac\r
+ */\r
+ public void setApplicationContext(AbstractApplicationContext ac){\r
+ closeApplicationContext(); //closes old application context if necessary\r
+ applicationContext = ac;\r
+ applicationContext.registerShutdownHook();\r
+ init();\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see java.lang.Object#finalize()\r
+ */\r
+ public void finalize(){\r
+ close();\r
+ }\r
+ \r
+ /**\r
+ * closes the application\r
+ */\r
+ public void close(){\r
+ closeApplicationContext();\r
+ }\r
+ \r
+ /**\r
+ * closes the application context\r
+ */\r
+ private void closeApplicationContext(){\r
+ if (applicationContext != null){\r
+ logger.info("Close ApplicationContext");\r
+ applicationContext.close();\r
+ }\r
+ }\r
+ \r
+ private void init(){\r
+ logger.info("Init " + this.getClass().getName() + " ... ");\r
+ if (logger.isInfoEnabled()){for (String beanName : applicationContext.getBeanDefinitionNames()){ logger.debug(beanName);}}\r
+ //TODO delete next row (was just for testing)\r
+ if (logger.isInfoEnabled()){\r
+ logger.info("Registered Beans: ");\r
+ String[] beanNames = applicationContext.getBeanDefinitionNames();\r
+ for (String beanName : beanNames){\r
+ logger.info(beanName);\r
+ }\r
+ }\r
+ configuration = (ICdmApplicationRemoteConfiguration)applicationContext.getBean("cdmApplicationRemoteDefaultConfiguration");\r
+ }\r
+ \r
+ \r
+\r
+ /* ****** Services *********/\r
+ \r
+ public final INameService getNameService(){\r
+ return configuration.getNameService();\r
+ }\r
+\r
+ public final ITaxonService getTaxonService(){\r
+ return configuration.getTaxonService();\r
+ }\r
+ \r
+ public final IClassificationService getClassificationService(){\r
+ return configuration.getClassificationService();\r
+ }\r
+ \r
+ public final ITaxonNodeService getTaxonNodeService(){\r
+ return configuration.getTaxonNodeService();\r
+ }\r
+\r
+ public final IReferenceService getReferenceService(){\r
+ return configuration.getReferenceService();\r
+ }\r
+ \r
+ public final IAgentService getAgentService(){\r
+ return configuration.getAgentService();\r
+ }\r
+ \r
+ public final ITermService getTermService(){\r
+ return configuration.getTermService();\r
+ }\r
+\r
+ public final IDescriptionService getDescriptionService(){\r
+ return configuration.getDescriptionService();\r
+ }\r
+ \r
+ public final IOccurrenceService getOccurrenceService(){\r
+ return configuration.getOccurrenceService();\r
+ }\r
+\r
+ public final IMediaService getMediaService(){\r
+ return configuration.getMediaService();\r
+ }\r
+\r
+ public final ICommonService getCommonService(){\r
+ return configuration.getCommonService();\r
+ }\r
+ \r
+ public final ILocationService getLocationService(){\r
+ return configuration.getLocationService();\r
+ }\r
+ \r
+ public final IUserService getUserService(){\r
+ return configuration.getUserService();\r
+ }\r
+\r
+ public IGroupService getGroupService() {\r
+ return configuration.getGroupService();\r
+ }\r
+ \r
+ public final ICollectionService getCollectionService(){\r
+ return configuration.getCollectionService();\r
+ }\r
+ \r
+ public final IFeatureTreeService getFeatureTreeService(){\r
+ return configuration.getFeatureTreeService();\r
+ }\r
+ \r
+ public final IFeatureNodeService getFeatureNodeService(){\r
+ return configuration.getFeatureNodeService();\r
+ }\r
+ \r
+ public final IVocabularyService getVocabularyService(){\r
+ return configuration.getVocabularyService();\r
+ }\r
+ \r
+ public final IIdentificationKeyService getIdentificationKeyService(){\r
+ return configuration.getIdentificationKeyService();\r
+ }\r
+\r
+ public final IPolytomousKeyService getPolytomousKeyService(){\r
+ return configuration.getPolytomousKeyService();\r
+ }\r
+\r
+ public final IPolytomousKeyNodeService getPolytomousKeyNodeService(){\r
+ return configuration.getPolytomousKeyNodeService();\r
+ }\r
+ \r
+ public final IService<CdmBase> getMainService(){\r
+ return configuration.getMainService();\r
+ }\r
+ \r
+ public final IWorkingSetService getWorkingSetService(){\r
+ return configuration.getWorkingSetService();\r
+ }\r
+ \r
+// public final Object getBean(String name){\r
+// return this.applicationContext.getBean(name);\r
+// }\r
+\r
+ @Override\r
+ public IDatabaseService getDatabaseService() {\r
+ return configuration.getDatabaseService();\r
+ }\r
+\r
+ @Override\r
+ public ProviderManager getAuthenticationManager() {\r
+ return configuration.getAuthenticationManager();\r
+ }\r
+\r
+\r
+\r
+ @Override\r
+ public ConversationHolder NewConversation() {\r
+ return configuration.NewConversation();\r
+ }\r
+\r
+ @Override\r
+ public Object getBean(String name) {\r
+ return configuration.getBean(name);\r
+ }\r
+\r
+ @Override\r
+ public IGrantedAuthorityService getGrantedAuthorityService() {\r
+ return configuration.getGrantedAuthorityService();\r
+ }\r
+\r
+ @Override\r
+ public PermissionEvaluator getPermissionEvaluator() {\r
+ return configuration.getPermissionEvaluator();\r
+ }\r
+\r
+ @Override\r
+ public void authenticate(String username, String password) {\r
+ configuration.authenticate(username, password);\r
+ \r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+// $Id: CdmApplicationDefaultConfiguration.java 11680 2011-04-04 17:07:39Z a.mueller $\r
+/**\r
+* Copyright (C) 2007 EDIT\r
+* European Distributed Institute of Taxonomy \r
+* http://www.e-taxonomy.eu\r
+* \r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/\r
+\r
+package eu.etaxonomy.cdm.remote.api.application;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.springframework.beans.BeansException;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.context.ApplicationContext;\r
+import org.springframework.context.ApplicationContextAware;\r
+import org.springframework.security.access.PermissionEvaluator;\r
+import org.springframework.security.authentication.ProviderManager;\r
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\r
+import org.springframework.security.core.Authentication;\r
+import org.springframework.security.core.context.SecurityContext;\r
+import org.springframework.security.core.context.SecurityContextHolder;\r
+import org.springframework.stereotype.Component;\r
+\r
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;\r
+import eu.etaxonomy.cdm.api.conversation.ConversationHolderMock;\r
+import eu.etaxonomy.cdm.api.service.IAgentService;\r
+import eu.etaxonomy.cdm.api.service.IClassificationService;\r
+import eu.etaxonomy.cdm.api.service.ICollectionService;\r
+import eu.etaxonomy.cdm.api.service.ICommonService;\r
+import eu.etaxonomy.cdm.api.service.IDatabaseService;\r
+import eu.etaxonomy.cdm.api.service.IDescriptionService;\r
+import eu.etaxonomy.cdm.api.service.IFeatureNodeService;\r
+import eu.etaxonomy.cdm.api.service.IFeatureTreeService;\r
+import eu.etaxonomy.cdm.api.service.IGrantedAuthorityService;\r
+import eu.etaxonomy.cdm.api.service.IGroupService;\r
+import eu.etaxonomy.cdm.api.service.IIdentificationKeyService;\r
+import eu.etaxonomy.cdm.api.service.ILocationService;\r
+import eu.etaxonomy.cdm.api.service.IMediaService;\r
+import eu.etaxonomy.cdm.api.service.INameService;\r
+import eu.etaxonomy.cdm.api.service.IOccurrenceService;\r
+import eu.etaxonomy.cdm.api.service.IPolytomousKeyNodeService;\r
+import eu.etaxonomy.cdm.api.service.IPolytomousKeyService;\r
+import eu.etaxonomy.cdm.api.service.IReferenceService;\r
+import eu.etaxonomy.cdm.api.service.IService;\r
+import eu.etaxonomy.cdm.api.service.ITaxonNodeService;\r
+import eu.etaxonomy.cdm.api.service.ITaxonService;\r
+import eu.etaxonomy.cdm.api.service.ITermService;\r
+import eu.etaxonomy.cdm.api.service.IUserService;\r
+import eu.etaxonomy.cdm.api.service.IVocabularyService;\r
+import eu.etaxonomy.cdm.api.service.IWorkingSetService;\r
+import eu.etaxonomy.cdm.model.common.CdmBase;\r
+\r
+/**\r
+ * @author a.mueller\r
+ * @created 21.05.2008\r
+ * @version 1.0\r
+ */\r
+/**\r
+ * @author a.mueller\r
+ * @author j.koch\r
+ */\r
+@Component\r
+public class CdmApplicationRemoteDefaultConfiguration implements ICdmApplicationRemoteConfiguration, ApplicationContextAware {\r
+ @SuppressWarnings("unused")\r
+ private static final Logger logger = Logger.getLogger(CdmApplicationRemoteDefaultConfiguration.class);\r
+\r
+ @Autowired\r
+ //@Qualifier("nameService")\r
+ private INameService nameService;\r
+ @Autowired\r
+ //@Qualifier("taxonService")\r
+ private ITaxonService taxonService;\r
+ @Autowired\r
+ //@Qualifier("classificationService")\r
+ private IClassificationService classificationService;\r
+ @Autowired\r
+ //@Qualifier("referenceService")\r
+ private IReferenceService referenceService;\r
+ @Autowired\r
+ //@Qualifier("agentService")\r
+ private IAgentService agentService;\r
+ @Autowired\r
+ //@Qualifier("termService")\r
+ private ITermService termService;\r
+ @Autowired\r
+ //@Qualifier("descriptionService")\r
+ private IDescriptionService descriptionService;\r
+ @Autowired\r
+ //@Qualifier("occurrenceService")\r
+ private IOccurrenceService occurrenceService;\r
+ @Autowired\r
+ //@Qualifier("mediaService")\r
+ private IMediaService mediaService;\r
+ @Autowired\r
+ //@Qualifier("commonService")\r
+ private ICommonService commonService;\r
+ @Autowired\r
+ private ILocationService locationService;\r
+ @Autowired\r
+ private IUserService userService;\r
+ @Autowired\r
+ private IGroupService groupService;\r
+ @Autowired\r
+ private ICollectionService collectionService;\r
+ @Autowired\r
+ private IFeatureTreeService featureTreeService;\r
+ @Autowired\r
+ private IFeatureNodeService featureNodeService;\r
+ @Autowired\r
+ private IVocabularyService vocabularyService;\r
+ @Autowired\r
+ private ITaxonNodeService taxonNodeService;\r
+ @Autowired\r
+ private IIdentificationKeyService identificationKeyService;\r
+ @Autowired\r
+ private IPolytomousKeyService polytomousKeyService;\r
+ @Autowired\r
+ private IPolytomousKeyNodeService polytomousKeyNodeService;\r
+ @Autowired\r
+ private IGrantedAuthorityService grantedAuthorityService;\r
+// @Autowired\r
+ //@Qualifier("mainService")\r
+ private IService<CdmBase> mainService;\r
+\r
+ @Autowired\r
+ private IWorkingSetService workingSetService;\r
+ @Autowired\r
+ private ProviderManager authenticationManager;\r
+ @Autowired\r
+ private PermissionEvaluator permissionEvaluator;\r
+ \r
+ protected ApplicationContext applicationContext;\r
+ \r
+ /**\r
+ * \r
+ */\r
+ public CdmApplicationRemoteDefaultConfiguration() {\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getAgentService()\r
+ */\r
+ public IAgentService getAgentService() {\r
+ return this.agentService;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getNameService()\r
+ */\r
+ public INameService getNameService() {\r
+ return this.nameService;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getReferenceService()\r
+ */\r
+ public IReferenceService getReferenceService() {\r
+ return this.referenceService;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getTaxonService()\r
+ */\r
+ public ITaxonService getTaxonService() {\r
+ return this.taxonService;\r
+ }\r
+ \r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getClassificationService()\r
+ */\r
+ public IClassificationService getClassificationService() {\r
+ return this.classificationService;\r
+ }\r
+ \r
+ public ITaxonNodeService getTaxonNodeService(){\r
+ return this.taxonNodeService;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getDescriptionService()\r
+ */\r
+ public IDescriptionService getDescriptionService(){\r
+ return this.descriptionService;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getOccurrenceService()\r
+ */\r
+ public IOccurrenceService getOccurrenceService(){\r
+ return this.occurrenceService;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getMediaService()\r
+ */\r
+ public IMediaService getMediaService(){\r
+ return this.mediaService;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getTermService()\r
+ */\r
+ public ITermService getTermService() {\r
+ return this.termService;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getCommonService()\r
+ */\r
+ public ICommonService getCommonService(){\r
+ return this.commonService;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getLocationService()\r
+ */\r
+ public ILocationService getLocationService() {\r
+ return this.locationService;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getUserService()\r
+ */\r
+ public IUserService getUserService() {\r
+ return this.userService;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getCommonService()\r
+ */\r
+ public IService<CdmBase> getMainService(){\r
+ return this.mainService;\r
+ }\r
+ \r
+ /*\r
+ * (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getCollectionService()\r
+ */\r
+ public ICollectionService getCollectionService() {\r
+ return collectionService;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getFeatureTreeService()\r
+ */\r
+ public IFeatureTreeService getFeatureTreeService() {\r
+ return featureTreeService;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getFeatureNodeService()\r
+ */\r
+ public IFeatureNodeService getFeatureNodeService(){\r
+ return featureNodeService;\r
+ }\r
+ \r
+ /*\r
+ * (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getVocabularyService()\r
+ */\r
+ public IVocabularyService getVocabularyService() {\r
+ return vocabularyService;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getIdentificationKeyService()\r
+ */\r
+ public IIdentificationKeyService getIdentificationKeyService(){\r
+ return identificationKeyService;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getPolytomousKeyService()\r
+ */\r
+ public IPolytomousKeyService getPolytomousKeyService(){\r
+ return polytomousKeyService;\r
+ }\r
+ \r
+ public IPolytomousKeyNodeService getPolytomousKeyNodeService(){\r
+ return polytomousKeyNodeService;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getWorkingSetService()\r
+ */\r
+ @Override\r
+ public IWorkingSetService getWorkingSetService() {\r
+ return workingSetService;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationRemoteConfiguration#getGroupService()\r
+ */\r
+ @Override\r
+ public IGroupService getGroupService() {\r
+ return groupService;\r
+ }\r
+\r
+ @Override\r
+ public IDatabaseService getDatabaseService() {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public ProviderManager getAuthenticationManager() {\r
+ return authenticationManager;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)\r
+ */\r
+ @Override\r
+ public void setApplicationContext(ApplicationContext applicationContext)\r
+ throws BeansException {\r
+ this.applicationContext = applicationContext;\r
+ }\r
+\r
+ \r
+ @Override\r
+ public final Object getBean(String name){\r
+ return this.applicationContext.getBean(name);\r
+ }\r
+\r
+ @Override\r
+ public ConversationHolder NewConversation() {\r
+ return new ConversationHolderMock();\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration#authenticate(java.lang.String, java.lang.String)\r
+ */\r
+ @Override\r
+ public void authenticate(String username, String password){\r
+ UsernamePasswordAuthenticationToken tokenForUser = new UsernamePasswordAuthenticationToken(username, password);\r
+ Authentication authentication = this.getAuthenticationManager().authenticate(tokenForUser);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+ }\r
+\r
+ @Override\r
+ public IGrantedAuthorityService getGrantedAuthorityService() { \r
+ return this.grantedAuthorityService;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration#getPermissionEvaluator()\r
+ */\r
+ @Override\r
+ public PermissionEvaluator getPermissionEvaluator() {\r
+ return permissionEvaluator;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package eu.etaxonomy.cdm.remote.api.application;
+
+import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
+
+
+public interface ICdmApplicationRemoteConfiguration extends ICdmApplicationConfiguration {
+
+
+}
--- /dev/null
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.collection.internal;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.naming.NamingException;
+
+import org.hibernate.AssertionFailure;
+import org.hibernate.HibernateException;
+import org.hibernate.LazyInitializationException;
+import org.hibernate.Session;
+import org.hibernate.collection.spi.PersistentCollection;
+import org.hibernate.engine.internal.ForeignKeys;
+import org.hibernate.engine.spi.CollectionEntry;
+import org.hibernate.engine.spi.EntityEntry;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.engine.spi.Status;
+import org.hibernate.engine.spi.TypedValue;
+import org.hibernate.internal.SessionFactoryRegistry;
+import org.hibernate.internal.util.MarkerObject;
+import org.hibernate.internal.util.collections.EmptyIterator;
+import org.hibernate.internal.util.collections.IdentitySet;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.pretty.MessageHelper;
+import org.hibernate.type.Type;
+import org.jboss.logging.Logger;
+
+/**
+ * Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
+ *
+ * @author Gavin King
+ */
+public abstract class AbstractPersistentCollection implements Serializable, PersistentCollection {
+ private static final long serialVersionUID = -7238232378593030571L;
+ private static final Logger log = Logger.getLogger( AbstractPersistentCollection.class );
+
+ private transient SessionImplementor session;
+ private boolean initialized;
+ private transient List<DelayedOperation> operationQueue;
+ private transient boolean directlyAccessible;
+ private transient boolean initializing;
+ private Object owner;
+ private int cachedSize = -1;
+
+ private String role;
+ private Serializable key;
+ // collections detect changes made via their public interface and mark
+ // themselves as dirty as a performance optimization
+ private boolean dirty;
+ private Serializable storedSnapshot;
+
+ private String sessionFactoryUuid;
+ private boolean specjLazyLoad = false;
+
+ public final String getRole() {
+ return role;
+ }
+
+ public final Serializable getKey() {
+ return key;
+ }
+
+ public final boolean isUnreferenced() {
+ return role == null;
+ }
+
+ public final boolean isDirty() {
+ return dirty;
+ }
+
+ public final void clearDirty() {
+ dirty = false;
+ }
+
+ public final void dirty() {
+ dirty = true;
+ }
+
+ public final Serializable getStoredSnapshot() {
+ return storedSnapshot;
+ }
+
+ //Careful: these methods do not initialize the collection.
+
+ /**
+ * Is the initialized collection empty?
+ */
+ public abstract boolean empty();
+
+ /**
+ * Called by any read-only method of the collection interface
+ */
+ protected final void read() {
+ initialize( false );
+ }
+
+ /**
+ * Called by the {@link Collection#size} method
+ */
+ @SuppressWarnings({"JavaDoc"})
+ protected boolean readSize() {
+ if ( !initialized ) {
+ if ( cachedSize != -1 && !hasQueuedOperations() ) {
+ return true;
+ }
+ else {
+// boolean isExtraLazy = withTemporarySessionIfNeeded(
+// new LazyInitializationWork<Boolean>() {
+// @Override
+// public Boolean doWork() {
+// CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+//
+// if ( entry != null ) {
+// CollectionPersister persister = entry.getLoadedPersister();
+// if ( persister.isExtraLazy() ) {
+// if ( hasQueuedOperations() ) {
+// session.flush();
+// }
+// cachedSize = persister.getSize( entry.getLoadedKey(), session );
+// return true;
+// }
+// else {
+// read();
+// }
+// }
+// else{
+// throwLazyInitializationExceptionIfNotConnected();
+// }
+// return false;
+ read();
+ return true;
+// }
+// }
+// );
+// if ( isExtraLazy ) {
+// return true;
+// }
+ }
+ }
+ return false;
+ }
+
+ public static interface LazyInitializationWork<T> {
+ public T doWork();
+ }
+
+ private <T> T withTemporarySessionIfNeeded(LazyInitializationWork<T> lazyInitializationWork) {
+ SessionImplementor originalSession = null;
+ boolean isTempSession = false;
+ boolean isJTA = false;
+
+ if ( session == null ) {
+ if ( specjLazyLoad ) {
+ session = openTemporarySessionForLoading();
+ isTempSession = true;
+ }
+ else {
+ throwLazyInitializationException( "could not initialize proxy - no Session" );
+ }
+ }
+ else if ( !session.isOpen() ) {
+ if ( specjLazyLoad ) {
+ originalSession = session;
+ session = openTemporarySessionForLoading();
+ isTempSession = true;
+ }
+ else {
+ throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
+ }
+ }
+ else if ( !session.isConnected() ) {
+ if ( specjLazyLoad ) {
+ originalSession = session;
+ session = openTemporarySessionForLoading();
+ isTempSession = true;
+ }
+ else {
+ throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
+ }
+ }
+
+ if ( isTempSession ) {
+ // TODO: On the next major release, add an
+ // 'isJTA' or 'getTransactionFactory' method to Session.
+ isJTA = session.getTransactionCoordinator()
+ .getTransactionContext().getTransactionEnvironment()
+ .getTransactionFactory()
+ .compatibleWithJtaSynchronization();
+
+ if ( !isJTA ) {
+ // Explicitly handle the transactions only if we're not in
+ // a JTA environment. A lazy loading temporary session can
+ // be created even if a current session and transaction are
+ // open (ex: session.clear() was used). We must prevent
+ // multiple transactions.
+ ( ( Session) session ).beginTransaction();
+ }
+
+ session.getPersistenceContext().addUninitializedDetachedCollection(
+ session.getFactory().getCollectionPersister( getRole() ),
+ this
+ );
+ }
+
+ try {
+ return lazyInitializationWork.doWork();
+ }
+ finally {
+ if ( isTempSession ) {
+ // make sure the just opened temp session gets closed!
+ try {
+ if ( !isJTA ) {
+ ( ( Session) session ).getTransaction().commit();
+ }
+ ( (Session) session ).close();
+ }
+ catch (Exception e) {
+ log.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
+ }
+ session = originalSession;
+ }
+ }
+ }
+
+ private SessionImplementor openTemporarySessionForLoading() {
+ if ( sessionFactoryUuid == null ) {
+ throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
+ }
+
+ SessionFactoryImplementor sf = (SessionFactoryImplementor)
+ SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
+ return (SessionImplementor) sf.openSession();
+ }
+
+ protected Boolean readIndexExistence(final Object index) {
+ if ( !initialized ) {
+ Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
+ new LazyInitializationWork<Boolean>() {
+ @Override
+ public Boolean doWork() {
+ CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+ CollectionPersister persister = entry.getLoadedPersister();
+ if ( persister.isExtraLazy() ) {
+ if ( hasQueuedOperations() ) {
+ session.flush();
+ }
+ return persister.indexExists( entry.getLoadedKey(), index, session );
+ }
+ else {
+ read();
+ }
+ return null;
+ }
+ }
+ );
+ if ( extraLazyExistenceCheck != null ) {
+ return extraLazyExistenceCheck;
+ }
+ }
+ return null;
+ }
+
+ protected Boolean readElementExistence(final Object element) {
+ if ( !initialized ) {
+ Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
+ new LazyInitializationWork<Boolean>() {
+ @Override
+ public Boolean doWork() {
+ CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+ CollectionPersister persister = entry.getLoadedPersister();
+ if ( persister.isExtraLazy() ) {
+ if ( hasQueuedOperations() ) {
+ session.flush();
+ }
+ return persister.elementExists( entry.getLoadedKey(), element, session );
+ }
+ else {
+ read();
+ }
+ return null;
+ }
+ }
+ );
+ if ( extraLazyExistenceCheck != null ) {
+ return extraLazyExistenceCheck;
+ }
+ }
+ return null;
+ }
+
+ protected static final Object UNKNOWN = new MarkerObject( "UNKNOWN" );
+
+ protected Object readElementByIndex(final Object index) {
+ if ( !initialized ) {
+ class ExtraLazyElementByIndexReader implements LazyInitializationWork {
+ private boolean isExtraLazy;
+ private Object element;
+
+ @Override
+ public Object doWork() {
+ CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+ CollectionPersister persister = entry.getLoadedPersister();
+ isExtraLazy = persister.isExtraLazy();
+ if ( isExtraLazy ) {
+ if ( hasQueuedOperations() ) {
+ session.flush();
+ }
+ element = persister.getElementByIndex( entry.getLoadedKey(), index, session, owner );
+ }
+ else {
+ read();
+ }
+ return null;
+ }
+ }
+
+ ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader();
+ //noinspection unchecked
+ withTemporarySessionIfNeeded( reader );
+ if ( reader.isExtraLazy ) {
+ return reader.element;
+ }
+ }
+ return UNKNOWN;
+
+ }
+
+ protected int getCachedSize() {
+ return cachedSize;
+ }
+
+ private boolean isConnectedToSession() {
+ return session != null &&
+ session.isOpen() &&
+ session.getPersistenceContext().containsCollection( this );
+ }
+
+ /**
+ * Called by any writer method of the collection interface
+ */
+ protected final void write() {
+ initialize( true );
+ dirty();
+ }
+
+ /**
+ * Is this collection in a state that would allow us to
+ * "queue" operations?
+ */
+ @SuppressWarnings({"JavaDoc"})
+ protected boolean isOperationQueueEnabled() {
+ return !initialized &&
+ isConnectedToSession() &&
+ isInverseCollection();
+ }
+
+ /**
+ * Is this collection in a state that would allow us to
+ * "queue" puts? This is a special case, because of orphan
+ * delete.
+ */
+ @SuppressWarnings({"JavaDoc"})
+ protected boolean isPutQueueEnabled() {
+ return !initialized &&
+ isConnectedToSession() &&
+ isInverseOneToManyOrNoOrphanDelete();
+ }
+
+ /**
+ * Is this collection in a state that would allow us to
+ * "queue" clear? This is a special case, because of orphan
+ * delete.
+ */
+ @SuppressWarnings({"JavaDoc"})
+ protected boolean isClearQueueEnabled() {
+ return !initialized &&
+ isConnectedToSession() &&
+ isInverseCollectionNoOrphanDelete();
+ }
+
+ /**
+ * Is this the "inverse" end of a bidirectional association?
+ */
+ @SuppressWarnings({"JavaDoc"})
+ private boolean isInverseCollection() {
+ CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ return ce != null && ce.getLoadedPersister().isInverse();
+ }
+
+ /**
+ * Is this the "inverse" end of a bidirectional association with
+ * no orphan delete enabled?
+ */
+ @SuppressWarnings({"JavaDoc"})
+ private boolean isInverseCollectionNoOrphanDelete() {
+ CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ return ce != null &&
+ ce.getLoadedPersister().isInverse() &&
+ !ce.getLoadedPersister().hasOrphanDelete();
+ }
+
+ /**
+ * Is this the "inverse" end of a bidirectional one-to-many, or
+ * of a collection with no orphan delete?
+ */
+ @SuppressWarnings({"JavaDoc"})
+ private boolean isInverseOneToManyOrNoOrphanDelete() {
+ CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ return ce != null && ce.getLoadedPersister().isInverse() && (
+ ce.getLoadedPersister().isOneToMany() ||
+ !ce.getLoadedPersister().hasOrphanDelete()
+ );
+ }
+
+ /**
+ * Queue an addition
+ */
+ @SuppressWarnings({"JavaDoc"})
+ protected final void queueOperation(DelayedOperation operation) {
+ if ( operationQueue == null ) {
+ operationQueue = new ArrayList<DelayedOperation>( 10 );
+ }
+ operationQueue.add( operation );
+ dirty = true; //needed so that we remove this collection from the second-level cache
+ }
+
+ /**
+ * After reading all existing elements from the database,
+ * add the queued elements to the underlying collection.
+ */
+ protected final void performQueuedOperations() {
+ for ( DelayedOperation operation : operationQueue ) {
+ operation.operate();
+ }
+ }
+
+ /**
+ * After flushing, re-init snapshot state.
+ */
+ public void setSnapshot(Serializable key, String role, Serializable snapshot) {
+ this.key = key;
+ this.role = role;
+ this.storedSnapshot = snapshot;
+ }
+
+ /**
+ * After flushing, clear any "queued" additions, since the
+ * database state is now synchronized with the memory state.
+ */
+ public void postAction() {
+ operationQueue = null;
+ cachedSize = -1;
+ clearDirty();
+ }
+
+ /**
+ * Not called by Hibernate, but used by non-JDK serialization,
+ * eg. SOAP libraries.
+ */
+ public AbstractPersistentCollection() {
+ }
+
+ protected AbstractPersistentCollection(SessionImplementor session) {
+ this.session = session;
+ }
+
+ /**
+ * return the user-visible collection (or array) instance
+ */
+ public Object getValue() {
+ return this;
+ }
+
+ /**
+ * Called just before reading any rows from the JDBC result set
+ */
+ public void beginRead() {
+ // override on some subclasses
+ initializing = true;
+ }
+
+ /**
+ * Called after reading all rows from the JDBC result set
+ */
+ public boolean endRead() {
+ //override on some subclasses
+ return afterInitialize();
+ }
+
+ public boolean afterInitialize() {
+ setInitialized();
+ //do this bit after setting initialized to true or it will recurse
+ if ( operationQueue != null ) {
+ performQueuedOperations();
+ operationQueue = null;
+ cachedSize = -1;
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+
+ /**
+ * Initialize the collection, if possible, wrapping any exceptions
+ * in a runtime exception
+ *
+ * @param writing currently obsolete
+ *
+ * @throws LazyInitializationException if we cannot initialize
+ */
+ protected final void initialize(final boolean writing) {
+ if ( initialized ) {
+ return;
+ }
+
+ withTemporarySessionIfNeeded(
+ new LazyInitializationWork<Object>() {
+ @Override
+ public Object doWork() {
+ session.initializeCollection( AbstractPersistentCollection.this, writing );
+ return null;
+ }
+ }
+ );
+ }
+
+ private void throwLazyInitializationExceptionIfNotConnected() {
+ if ( !isConnectedToSession() ) {
+ throwLazyInitializationException( "no session or session was closed" );
+ }
+ if ( !session.isConnected() ) {
+ throwLazyInitializationException( "session is disconnected" );
+ }
+ }
+
+ private void throwLazyInitializationException(String message) {
+ throw new LazyInitializationException(
+ "failed to lazily initialize a collection" +
+ (role == null ? "" : " of role: " + role) +
+ ", " + message
+ );
+ }
+
+ protected final void setInitialized() {
+ this.initializing = false;
+ this.initialized = true;
+ }
+
+ protected final void setDirectlyAccessible(boolean directlyAccessible) {
+ this.directlyAccessible = directlyAccessible;
+ }
+
+ /**
+ * Could the application possibly have a direct reference to
+ * the underlying collection implementation?
+ */
+ public boolean isDirectlyAccessible() {
+ return directlyAccessible;
+ }
+
+ /**
+ * Disassociate this collection from the given session.
+ *
+ * @return true if this was currently associated with the given session
+ */
+ public final boolean unsetSession(SessionImplementor currentSession) {
+ prepareForPossibleSpecialSpecjInitialization();
+ if ( currentSession == this.session ) {
+ this.session = null;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ protected void prepareForPossibleSpecialSpecjInitialization() {
+ if ( session != null ) {
+ specjLazyLoad = session.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled();
+
+ if ( specjLazyLoad && sessionFactoryUuid == null ) {
+ try {
+ sessionFactoryUuid = (String) session.getFactory().getReference().get( "uuid" ).getContent();
+ }
+ catch (NamingException e) {
+ //not much we can do if this fails...
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Associate the collection with the given session.
+ *
+ * @return false if the collection was already associated with the session
+ *
+ * @throws HibernateException if the collection was already associated
+ * with another open session
+ */
+ public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
+ if ( session == this.session ) {
+ return false;
+ }
+ else {
+ if ( isConnectedToSession() ) {
+ CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ if ( ce == null ) {
+ throw new HibernateException(
+ "Illegal attempt to associate a collection with two open sessions"
+ );
+ }
+ else {
+ throw new HibernateException(
+ "Illegal attempt to associate a collection with two open sessions: " +
+ MessageHelper.collectionInfoString(
+ ce.getLoadedPersister(), this,
+ ce.getLoadedKey(), session
+ )
+ );
+ }
+ }
+ else {
+ this.session = session;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Do we need to completely recreate this collection when it changes?
+ */
+ public boolean needsRecreate(CollectionPersister persister) {
+ return false;
+ }
+
+ /**
+ * To be called internally by the session, forcing
+ * immediate initialization.
+ */
+ public final void forceInitialization() throws HibernateException {
+ if ( !initialized ) {
+ if ( initializing ) {
+ throw new AssertionFailure( "force initialize loading collection" );
+ }
+ if ( session == null ) {
+ throw new HibernateException( "collection is not associated with any session" );
+ }
+ if ( !session.isConnected() ) {
+ throw new HibernateException( "disconnected session" );
+ }
+ session.initializeCollection( this, false );
+ }
+ }
+
+
+ /**
+ * Get the current snapshot from the session
+ */
+ @SuppressWarnings({"JavaDoc"})
+ protected final Serializable getSnapshot() {
+ return session.getPersistenceContext().getSnapshot( this );
+ }
+
+ /**
+ * Is this instance initialized?
+ */
+ public final boolean wasInitialized() {
+ return initialized;
+ }
+
+ public boolean isRowUpdatePossible() {
+ return true;
+ }
+
+ /**
+ * Does this instance have any "queued" additions?
+ */
+ public final boolean hasQueuedOperations() {
+ return operationQueue != null;
+ }
+
+ /**
+ * Iterate the "queued" additions
+ */
+ public final Iterator queuedAdditionIterator() {
+ if ( hasQueuedOperations() ) {
+ return new Iterator() {
+ int i = 0;
+
+ public Object next() {
+ return operationQueue.get( i++ ).getAddedInstance();
+ }
+
+ public boolean hasNext() {
+ return i < operationQueue.size();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ else {
+ return EmptyIterator.INSTANCE;
+ }
+ }
+
+ /**
+ * Iterate the "queued" additions
+ */
+ @SuppressWarnings({"unchecked"})
+ public final Collection getQueuedOrphans(String entityName) {
+ if ( hasQueuedOperations() ) {
+ Collection additions = new ArrayList( operationQueue.size() );
+ Collection removals = new ArrayList( operationQueue.size() );
+ for ( DelayedOperation operation : operationQueue ) {
+ additions.add( operation.getAddedInstance() );
+ removals.add( operation.getOrphan() );
+ }
+ return getOrphans( removals, additions, entityName, session );
+ }
+ else {
+ return Collections.EMPTY_LIST;
+ }
+ }
+
+ /**
+ * Called before inserting rows, to ensure that any surrogate keys
+ * are fully generated
+ */
+ public void preInsert(CollectionPersister persister) throws HibernateException {
+ }
+
+ /**
+ * Called after inserting a row, to fetch the natively generated id
+ */
+ public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
+ }
+
+ /**
+ * get all "orphaned" elements
+ */
+ public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException;
+
+ /**
+ * Get the current session
+ */
+ @SuppressWarnings({"JavaDoc"})
+ public final SessionImplementor getSession() {
+ return session;
+ }
+
+ protected final class IteratorProxy implements Iterator {
+ protected final Iterator itr;
+
+ public IteratorProxy(Iterator itr) {
+ this.itr = itr;
+ }
+
+ public boolean hasNext() {
+ return itr.hasNext();
+ }
+
+ public Object next() {
+ return itr.next();
+ }
+
+ public void remove() {
+ write();
+ itr.remove();
+ }
+
+ }
+
+ protected final class ListIteratorProxy implements ListIterator {
+ protected final ListIterator itr;
+
+ public ListIteratorProxy(ListIterator itr) {
+ this.itr = itr;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void add(Object o) {
+ write();
+ itr.add( o );
+ }
+
+ public boolean hasNext() {
+ return itr.hasNext();
+ }
+
+ public boolean hasPrevious() {
+ return itr.hasPrevious();
+ }
+
+ public Object next() {
+ return itr.next();
+ }
+
+ public int nextIndex() {
+ return itr.nextIndex();
+ }
+
+ public Object previous() {
+ return itr.previous();
+ }
+
+ public int previousIndex() {
+ return itr.previousIndex();
+ }
+
+ public void remove() {
+ write();
+ itr.remove();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void set(Object o) {
+ write();
+ itr.set( o );
+ }
+
+ }
+
+ protected class SetProxy implements java.util.Set {
+ protected final Collection set;
+
+ public SetProxy(Collection set) {
+ this.set = set;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public boolean add(Object o) {
+ write();
+ return set.add( o );
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public boolean addAll(Collection c) {
+ write();
+ return set.addAll( c );
+ }
+
+ public void clear() {
+ write();
+ set.clear();
+ }
+
+ public boolean contains(Object o) {
+ return set.contains( o );
+ }
+
+ public boolean containsAll(Collection c) {
+ return set.containsAll( c );
+ }
+
+ public boolean isEmpty() {
+ return set.isEmpty();
+ }
+
+ public Iterator iterator() {
+ return new IteratorProxy( set.iterator() );
+ }
+
+ public boolean remove(Object o) {
+ write();
+ return set.remove( o );
+ }
+
+ public boolean removeAll(Collection c) {
+ write();
+ return set.removeAll( c );
+ }
+
+ public boolean retainAll(Collection c) {
+ write();
+ return set.retainAll( c );
+ }
+
+ public int size() {
+ return set.size();
+ }
+
+ public Object[] toArray() {
+ return set.toArray();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public Object[] toArray(Object[] array) {
+ return set.toArray( array );
+ }
+
+ }
+
+ protected final class ListProxy implements java.util.List {
+ protected final List list;
+
+ public ListProxy(List list) {
+ this.list = list;
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked"})
+ public void add(int index, Object value) {
+ write();
+ list.add( index, value );
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked"})
+ public boolean add(Object o) {
+ write();
+ return list.add( o );
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked"})
+ public boolean addAll(Collection c) {
+ write();
+ return list.addAll( c );
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked"})
+ public boolean addAll(int i, Collection c) {
+ write();
+ return list.addAll( i, c );
+ }
+
+ @Override
+ public void clear() {
+ write();
+ list.clear();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return list.contains( o );
+ }
+
+ @Override
+ public boolean containsAll(Collection c) {
+ return list.containsAll( c );
+ }
+
+ @Override
+ public Object get(int i) {
+ return list.get( i );
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return list.indexOf( o );
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return list.isEmpty();
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new IteratorProxy( list.iterator() );
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return list.lastIndexOf( o );
+ }
+
+ @Override
+ public ListIterator listIterator() {
+ return new ListIteratorProxy( list.listIterator() );
+ }
+
+ @Override
+ public ListIterator listIterator(int i) {
+ return new ListIteratorProxy( list.listIterator( i ) );
+ }
+
+ @Override
+ public Object remove(int i) {
+ write();
+ return list.remove( i );
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ write();
+ return list.remove( o );
+ }
+
+ @Override
+ public boolean removeAll(Collection c) {
+ write();
+ return list.removeAll( c );
+ }
+
+ @Override
+ public boolean retainAll(Collection c) {
+ write();
+ return list.retainAll( c );
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked"})
+ public Object set(int i, Object o) {
+ write();
+ return list.set( i, o );
+ }
+
+ @Override
+ public int size() {
+ return list.size();
+ }
+
+ @Override
+ public List subList(int i, int j) {
+ return list.subList( i, j );
+ }
+
+ @Override
+ public Object[] toArray() {
+ return list.toArray();
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked"})
+ public Object[] toArray(Object[] array) {
+ return list.toArray( array );
+ }
+
+ }
+
+ /**
+ * Contract for operations which are part of a collection's operation queue.
+ */
+ protected interface DelayedOperation {
+ public void operate();
+
+ public Object getAddedInstance();
+
+ public Object getOrphan();
+ }
+
+ /**
+ * Given a collection of entity instances that used to
+ * belong to the collection, and a collection of instances
+ * that currently belong, return a collection of orphans
+ */
+ @SuppressWarnings({"JavaDoc", "unchecked"})
+ protected static Collection getOrphans(
+ Collection oldElements,
+ Collection currentElements,
+ String entityName,
+ SessionImplementor session) throws HibernateException {
+
+ // short-circuit(s)
+ if ( currentElements.size() == 0 ) {
+ return oldElements; // no new elements, the old list contains only Orphans
+ }
+ if ( oldElements.size() == 0 ) {
+ return oldElements; // no old elements, so no Orphans neither
+ }
+
+ final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
+ final Type idType = entityPersister.getIdentifierType();
+
+ // create the collection holding the Orphans
+ Collection res = new ArrayList();
+
+ // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
+ java.util.Set currentIds = new HashSet();
+ java.util.Set currentSaving = new IdentitySet();
+ for ( Object current : currentElements ) {
+ if ( current != null && ForeignKeys.isNotTransient( entityName, current, null, session ) ) {
+ EntityEntry ee = session.getPersistenceContext().getEntry( current );
+ if ( ee != null && ee.getStatus() == Status.SAVING ) {
+ currentSaving.add( current );
+ }
+ else {
+ Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(
+ entityName,
+ current,
+ session
+ );
+ currentIds.add( new TypedValue( idType, currentId, entityPersister.getEntityMode() ) );
+ }
+ }
+ }
+
+ // iterate over the *old* list
+ for ( Object old : oldElements ) {
+ if ( !currentSaving.contains( old ) ) {
+ Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, old, session );
+ if ( !currentIds.contains( new TypedValue( idType, oldId, entityPersister.getEntityMode() ) ) ) {
+ res.add( old );
+ }
+ }
+ }
+
+ return res;
+ }
+
+ public static void identityRemove(
+ Collection list,
+ Object object,
+ String entityName,
+ SessionImplementor session) throws HibernateException {
+
+ if ( object != null && ForeignKeys.isNotTransient( entityName, object, null, session ) ) {
+ final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
+ Type idType = entityPersister.getIdentifierType();
+
+ Serializable idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, object, session );
+ Iterator itr = list.iterator();
+ while ( itr.hasNext() ) {
+ Serializable idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, itr.next(), session );
+ if ( idType.isEqual( idOfCurrent, idOfOld, session.getFactory() ) ) {
+ itr.remove();
+ break;
+ }
+ }
+
+ }
+ }
+
+ public Object getIdentifier(Object entry, int i) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getOwner() {
+ return owner;
+ }
+
+ public void setOwner(Object owner) {
+ this.owner = owner;
+ }
+
+}
+
--- /dev/null
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.proxy;
+
+import java.io.Serializable;
+
+import javax.naming.NamingException;
+
+import org.hibernate.HibernateException;
+import org.hibernate.LazyInitializationException;
+import org.hibernate.Session;
+import org.hibernate.SessionException;
+import org.hibernate.TransientObjectException;
+import org.hibernate.engine.spi.EntityKey;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.internal.SessionFactoryRegistry;
+import org.hibernate.persister.entity.EntityPersister;
+import org.jboss.logging.Logger;
+import org.springframework.beans.factory.annotation.Configurable;
+
+/**
+ * Convenience base class for lazy initialization handlers. Centralizes the basic plumbing of doing lazy
+ * initialization freeing subclasses to acts as essentially adapters to their intended entity mode and/or
+ * proxy generation strategy.
+ *
+ * @author Gavin King
+ */
+@Configurable(dependencyCheck = true)
+public abstract class AbstractLazyInitializer implements LazyInitializer {
+ private static final Logger log = Logger.getLogger( AbstractLazyInitializer.class );
+
+ private String entityName;
+ private Serializable id;
+ private Object target;
+ private boolean initialized;
+ private boolean readOnly;
+ private boolean unwrap;
+ private transient SessionImplementor session;
+ private Boolean readOnlyBeforeAttachedToSession;
+
+ private String sessionFactoryUuid;
+ private boolean specjLazyLoad = false;
+
+ /**
+ * For serialization from the non-pojo initializers (HHH-3309)
+ */
+ protected AbstractLazyInitializer() {
+ }
+
+ /**
+ * Main constructor.
+ *
+ * @param entityName The name of the entity being proxied.
+ * @param id The identifier of the entity being proxied.
+ * @param session The session owning the proxy.
+ */
+ protected AbstractLazyInitializer(String entityName, Serializable id, SessionImplementor session) {
+ this.entityName = entityName;
+ this.id = id;
+ // initialize other fields depending on session state
+ if ( session == null ) {
+ unsetSession();
+ }
+ else {
+ setSession( session );
+ }
+ }
+
+ @Override
+ public final String getEntityName() {
+ return entityName;
+ }
+
+ @Override
+ public final Serializable getIdentifier() {
+ return id;
+ }
+
+ @Override
+ public final void setIdentifier(Serializable id) {
+ this.id = id;
+ }
+
+ @Override
+ public final boolean isUninitialized() {
+ return !initialized;
+ }
+
+ @Override
+ public final SessionImplementor getSession() {
+ return session;
+ }
+
+ @Override
+ public final void setSession(SessionImplementor s) throws HibernateException {
+ if ( s != session ) {
+ // check for s == null first, since it is least expensive
+ if ( s == null ) {
+ unsetSession();
+ }
+ else if ( isConnectedToSession() ) {
+ //TODO: perhaps this should be some other RuntimeException...
+ throw new HibernateException( "illegally attempted to associate a proxy with two open Sessions" );
+ }
+ else {
+ // s != null
+ session = s;
+ if ( readOnlyBeforeAttachedToSession == null ) {
+ // use the default read-only/modifiable setting
+ final EntityPersister persister = s.getFactory().getEntityPersister( entityName );
+ setReadOnly( s.getPersistenceContext().isDefaultReadOnly() || !persister.isMutable() );
+ }
+ else {
+ // use the read-only/modifiable setting indicated during deserialization
+ setReadOnly( readOnlyBeforeAttachedToSession.booleanValue() );
+ readOnlyBeforeAttachedToSession = null;
+ }
+ }
+ }
+ }
+
+ private static EntityKey generateEntityKeyOrNull(Serializable id, SessionImplementor s, String entityName) {
+ if ( id == null || s == null || entityName == null ) {
+ return null;
+ }
+ return s.generateEntityKey( id, s.getFactory().getEntityPersister( entityName ) );
+ }
+
+ @Override
+ public final void unsetSession() {
+ prepareForPossibleSpecialSpecjInitialization();
+ session = null;
+ readOnly = false;
+ readOnlyBeforeAttachedToSession = null;
+ }
+
+ @Override
+ public final void initialize() throws HibernateException {
+ if ( !initialized ) {
+ if ( specjLazyLoad ) {
+ specialSpecjInitialization();
+ }
+ else if ( session == null ) {
+ throw new LazyInitializationException( "could not initialize proxy - no Session" );
+ }
+ else if ( !session.isOpen() ) {
+ throw new LazyInitializationException( "could not initialize proxy - the owning Session was closed" );
+ }
+ else if ( !session.isConnected() ) {
+ throw new LazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
+ }
+ else {
+ target = session.immediateLoad( entityName, id );
+ initialized = true;
+ checkTargetState();
+ }
+ }
+ else {
+ checkTargetState();
+ }
+ }
+
+ protected void specialSpecjInitialization() {
+ if ( session == null ) {
+ //we have a detached collection thats set to null, reattach
+ if ( sessionFactoryUuid == null ) {
+ throw new LazyInitializationException( "could not initialize proxy - no Session" );
+ }
+ try {
+ SessionFactoryImplementor sf = (SessionFactoryImplementor)
+ SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
+ SessionImplementor session = (SessionImplementor) sf.openSession();
+
+ // TODO: On the next major release, add an
+ // 'isJTA' or 'getTransactionFactory' method to Session.
+ boolean isJTA = session.getTransactionCoordinator()
+ .getTransactionContext().getTransactionEnvironment()
+ .getTransactionFactory()
+ .compatibleWithJtaSynchronization();
+
+ if ( !isJTA ) {
+ // Explicitly handle the transactions only if we're not in
+ // a JTA environment. A lazy loading temporary session can
+ // be created even if a current session and transaction are
+ // open (ex: session.clear() was used). We must prevent
+ // multiple transactions.
+ ( ( Session) session ).beginTransaction();
+ }
+
+ try {
+ target = session.immediateLoad( entityName, id );
+ }
+ finally {
+ // make sure the just opened temp session gets closed!
+ try {
+ if ( !isJTA ) {
+ ( ( Session) session ).getTransaction().commit();
+ }
+ ( (Session) session ).close();
+ }
+ catch (Exception e) {
+ log.warn( "Unable to close temporary session used to load lazy proxy associated to no session" );
+ }
+ }
+ initialized = true;
+ checkTargetState();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ throw new LazyInitializationException( e.getMessage() );
+ }
+ }
+ else if ( session.isOpen() && session.isConnected() ) {
+ target = session.immediateLoad( entityName, id );
+ initialized = true;
+ checkTargetState();
+ }
+ else {
+ throw new LazyInitializationException( "could not initialize proxy - Session was closed or disced" );
+ }
+ }
+
+ protected void prepareForPossibleSpecialSpecjInitialization() {
+ if ( session != null ) {
+ specjLazyLoad = session.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled();
+
+ if ( specjLazyLoad && sessionFactoryUuid == null ) {
+ try {
+ sessionFactoryUuid = (String) session.getFactory().getReference().get( "uuid" ).getContent();
+ }
+ catch (NamingException e) {
+ //not much we can do if this fails...
+ }
+ }
+ }
+ }
+
+ private void checkTargetState() {
+ if ( !unwrap ) {
+ if ( target == null ) {
+ getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( entityName, id );
+ }
+ }
+ }
+
+ /**
+ * Getter for property 'connectedToSession'.
+ *
+ * @return Value for property 'connectedToSession'.
+ */
+ protected final boolean isConnectedToSession() {
+ return getProxyOrNull() != null;
+ }
+
+ private Object getProxyOrNull() {
+ final EntityKey entityKey = generateEntityKeyOrNull( getIdentifier(), session, getEntityName() );
+ if ( entityKey != null && session != null && session.isOpen() ) {
+ return session.getPersistenceContext().getProxy( entityKey );
+ }
+ return null;
+ }
+
+ @Override
+ public final Object getImplementation() {
+ initialize();
+ return target;
+ }
+
+ @Override
+ public final void setImplementation(Object target) {
+ this.target = target;
+ initialized = true;
+ }
+
+ @Override
+ public final Object getImplementation(SessionImplementor s) throws HibernateException {
+ final EntityKey entityKey = generateEntityKeyOrNull( getIdentifier(), s, getEntityName() );
+ return (entityKey == null ? null : s.getPersistenceContext().getEntity( entityKey ));
+ }
+
+ /**
+ * Getter for property 'target'.
+ * <p/>
+ * Same as {@link #getImplementation()} except that this method will not force initialization.
+ *
+ * @return Value for property 'target'.
+ */
+ protected final Object getTarget() {
+ return target;
+ }
+
+ @Override
+ public final boolean isReadOnlySettingAvailable() {
+ return (session != null && !session.isClosed());
+ }
+
+ private void errorIfReadOnlySettingNotAvailable() {
+ if ( session == null ) {
+ throw new TransientObjectException(
+ "Proxy is detached (i.e, session is null). The read-only/modifiable setting is only accessible when the proxy is associated with an open session."
+ );
+ }
+ if ( session.isClosed() ) {
+ throw new SessionException(
+ "Session is closed. The read-only/modifiable setting is only accessible when the proxy is associated with an open session."
+ );
+ }
+ }
+
+ @Override
+ public final boolean isReadOnly() {
+ errorIfReadOnlySettingNotAvailable();
+ return readOnly;
+ }
+
+ @Override
+ public final void setReadOnly(boolean readOnly) {
+ errorIfReadOnlySettingNotAvailable();
+ // only update if readOnly is different from current setting
+ if ( this.readOnly != readOnly ) {
+ final EntityPersister persister = session.getFactory().getEntityPersister( entityName );
+ if ( !persister.isMutable() && !readOnly ) {
+ throw new IllegalStateException( "cannot make proxies for immutable entities modifiable" );
+ }
+ this.readOnly = readOnly;
+ if ( initialized ) {
+ EntityKey key = generateEntityKeyOrNull( getIdentifier(), session, getEntityName() );
+ if ( key != null && session.getPersistenceContext().containsEntity( key ) ) {
+ session.getPersistenceContext().setReadOnly( target, readOnly );
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the read-only/modifiable setting that should be put in affect when it is
+ * attached to a session.
+ * <p/>
+ * This method should only be called during serialization when read-only/modifiable setting
+ * is not available (i.e., isReadOnlySettingAvailable() == false)
+ *
+ * @return null, if the default setting should be used;
+ * true, for read-only;
+ * false, for modifiable
+ *
+ * @throws IllegalStateException if isReadOnlySettingAvailable() == true
+ */
+ protected final Boolean isReadOnlyBeforeAttachedToSession() {
+ if ( isReadOnlySettingAvailable() ) {
+ throw new IllegalStateException(
+ "Cannot call isReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true"
+ );
+ }
+ return readOnlyBeforeAttachedToSession;
+ }
+
+ /**
+ * Set the read-only/modifiable setting that should be put in affect when it is
+ * attached to a session.
+ * <p/>
+ * This method should only be called during deserialization, before associating
+ * the proxy with a session.
+ *
+ * @param readOnlyBeforeAttachedToSession, the read-only/modifiable setting to use when
+ * associated with a session; null indicates that the default should be used.
+ *
+ * @throws IllegalStateException if isReadOnlySettingAvailable() == true
+ */
+ /* package-private */
+ final void setReadOnlyBeforeAttachedToSession(Boolean readOnlyBeforeAttachedToSession) {
+ if ( isReadOnlySettingAvailable() ) {
+ throw new IllegalStateException(
+ "Cannot call setReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true"
+ );
+ }
+ this.readOnlyBeforeAttachedToSession = readOnlyBeforeAttachedToSession;
+ }
+
+ @Override
+ public boolean isUnwrap() {
+ return unwrap;
+ }
+
+ @Override
+ public void setUnwrap(boolean unwrap) {
+ this.unwrap = unwrap;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:context="http://www.springframework.org/schema/context"\r
+ xmlns:tx="http://www.springframework.org/schema/tx"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd\r
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">\r
+\r
+ <bean id="agentService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/agent.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IAgentService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="annotationService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/annotation.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IAnnotationService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="auditeventService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/auditevent.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IAuditEventService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="classificationService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/classification.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IClassificationService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="collectionService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/collection.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.ICollectionService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="commonService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/common.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.ICommonService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="descriptionService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/description.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IDescriptionService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="featureNodeService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/featurenode.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IFeatureNodeService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="featureTreeService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/featuretree.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IFeatureTreeService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="groupService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/group.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IGroupService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="identificationKeyService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/identificationkey.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IIdentificationKeyService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="locationService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/location.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.ILocationService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="markerService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/marker.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IMarkerService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="mediaService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/media.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IMediaService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="nameService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/name.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.INameService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="occurrenceService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/occurrence.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IOccurrenceService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="polytomousKeyNodeService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/polytomouskeynode.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IPolytomousKeyNodeService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="polytomousKeyService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/polytomouskey.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IPolytomousKeyService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="referenceService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/reference.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IReferenceService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+ \r
+<!-- \r
+ <bean id="serviceService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/service.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IService</value>\r
+ </property>\r
+ </bean>\r
+ -->\r
+ \r
+ <bean id="taxonNodeService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/taxonnode.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.ITaxonNodeService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="taxonService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/taxon.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.ITaxonService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="termService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/term.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.ITermService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="userService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/user.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IUserService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="vocabularyService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/vocabulary.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IVocabularyService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="workingSetService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/workingset.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IWorkingSetService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="grantedAuthorityService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/grantedauthority.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IGrantedAuthorityService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="databaseService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/database.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.IDatabaseService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="lsidAuthorityService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/lsidauthoruty.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.lsid.LSIDAuthorityService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="lsidMetadataService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/lsidmetadata.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.lsid.LSIDMetadataService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="lsiDataService"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/lsiddata.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>eu.etaxonomy.cdm.api.service.lsid.LSIDDataService</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="providerManager"\r
+ class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">\r
+ <property name="serviceUrl">\r
+ <value>http://${serverName}/${contextPath}/authenticationManager.service</value>\r
+ </property>\r
+ <property name="serviceInterface">\r
+ <value>org.springframework.security.authentication.AuthenticationManager</value>\r
+ </property>\r
+ <property name="httpInvokerRequestExecutor">\r
+ <bean class="org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor" />\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="propertyConfigurer"\r
+ class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">\r
+ <property name="location" value="/eu/etaxonomy/cdm/config.properties" />\r
+ </bean>\r
+\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:context="http://www.springframework.org/schema/context"\r
+ xmlns:tx="http://www.springframework.org/schema/tx"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">\r
+\r
+ <context:spring-configured />\r
+ <bean id="cdmlazyLoader" class="eu.etaxonomy.cdm.api.lazyloading.CdmLazyLoader"\r
+ factory-method="aspectOf" />\r
+ <!-- <import resource="classpath:/eu/etaxonomy/cdm/services.xml"/> -->\r
+ <!--import resource="classpath:/eu/etaxonomy/cdm/defaultSecurityContext.xml"/> -->\r
+ <import resource="classpath:/eu/etaxonomy/cdm/remoting_services_security.xml"/> \r
+ <!-- <import resource="classpath:/eu/etaxonomy/cdm/spelling.xml"/> -->\r
+\r
+ <!-- includes service beans e.g. in eu/etaxonomy/cdm/api -->\r
+ <!-- Services are defined in httpInvokerServiceClients.xml, component-scan is not needed. -->\r
+ <!-- \r
+ <context:component-scan base-package="eu/etaxonomy/cdm/api/service">\r
+ </context:component-scan>\r
+ -->\r
+ \r
+ <bean name="cdmApplicationRemoteDefaultConfiguration" class="eu.etaxonomy.cdm.remote.api.application.CdmApplicationRemoteDefaultConfiguration">\r
+ </bean>\r
+ \r
+ <import resource="classpath:/eu/etaxonomy/cdm/httpInvokerServiceClients.xml"/>\r
+ \r
+ <context:component-scan base-package="eu/etaxonomy/cdm/api/application">\r
+ <context:exclude-filter type="regex" expression="eu\.etaxonomy\.cdm\.api\.application\.CdmApplicationController"/>\r
+ <context:exclude-filter type="regex" expression="eu\.etaxonomy\.cdm\.api\.application\.CdmApplicationDefaultConfiguration"/>\r
+ <context:exclude-filter type="regex" expression="eu\.etaxonomy\.cdm\.remote\.api\.application\.CdmApplicationRemoteController"/>\r
+ <context:exclude-filter type="regex" expression="eu\.etaxonomy\.cdm\.remote\.api\.application\.CdmApplicationRemoteDefaultConfiguration"/>\r
+ </context:component-scan>\r
+ <!--bean id="persistentTermInitializer" class="eu.etaxonomy.cdm.database.PersistentTermInitializer">\r
+ <property name="omit" value="false" />\r
+ </bean-->\r
+ <!--bean id="remoteTermInitializer" class="eu.etaxonomy.cdm.remote.service.RemoteTermInitializer">\r
+ <property name="omit" value="false" />\r
+ </bean-->\r
+\r
+ <!-- EditGeoService was moved to ext. Therefore it will not be found by the default component scan.
+ We added it here because the Editor needs it. However, this is only a temporary solution.
+ In the future we want to pass in an application context with the editor. -->\r
+\r
+ <!-- <bean id="conversationHolder" class="eu.etaxonomy.cdm.api.conversation.ConversationHolder" scope="prototype"/> -->\r
+\r
+ <!-- TODO move to io -->\r
+<!-- \r
+ <context:component-scan base-package="eu/etaxonomy/cdm/io">\r
+ <context:exclude-filter type="regex" expression="eu\.etaxonomy\.cdm\.io\.berlinModel.*" />\r
+ </context:component-scan>\r
+ -->\r
+ <!-- enable the configuration of transactional behavior based on annotations -->\r
+ <!-- <tx:annotation-driven transaction-manager="transactionManager"/> -->\r
+\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"\r
+ xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans\r
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\r
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd\r
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd\r
+ ">\r
+\r
+\r
+ <!--\r
+ ============================== SECURITY ==============================\r
+ -->\r
+ <bean id="accessDecisionManager" class="eu.etaxonomy.cdm.persistence.hibernate.permission.UnanimousBasedUnrevokable">\r
+ <property name="decisionVoters">\r
+ <list>\r
+ <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.GrantAlwaysVoter" />\r
+ <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.TaxonNodeVoter" />\r
+ <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.TaxonBaseVoter" />\r
+ <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.DescriptionBaseVoter" />\r
+ <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.DescriptionElementVoter" />\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <!--\r
+ CdmPermissionEvaluator.hasPermissions() evaluates the CdmPermissions like TAXONNODE.UPDATE{20c8f083-5870-4cbd-bf56-c5b2b98ab6a7}\r
+ -->\r
+ <bean id="cdmPermissionEvaluator" class="eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionEvaluator">\r
+ <property name="accessDecisionManager" ref="accessDecisionManager" />\r
+ </bean>\r
+\r
+ <!-- The CdmSecurityHibernateInterceptor checks onSave() and on flushDirty() if the currently authenticated principal or token has\r
+ sufficient permissions on the entity to be persisted -->\r
+ <bean id="securityHibernateInterceptor" class="eu.etaxonomy.cdm.persistence.hibernate.CdmSecurityHibernateInterceptor">\r
+ <property name="permissionEvaluator" ref="cdmPermissionEvaluator" />\r
+ </bean>\r
+\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:context="http://www.springframework.org/schema/context"\r
+ xmlns:security="http://www.springframework.org/schema/security"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\r
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd\r
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd\r
+ http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"\r
+ >\r
+\r
+ <import resource="classpath:/eu/etaxonomy/cdm/remoting_persistence_security.xml"/>\r
+ <!--\r
+ ======================================================================\r
+ security specific configuration\r
+ ======================================================================\r
+ -->\r
+ <security:global-method-security pre-post-annotations="enabled" run-as-manager-ref="runAsManager" >\r
+ <security:expression-handler ref="expressionHandler" />\r
+ </security:global-method-security>\r
+\r
+ <!--\r
+ To use "hasPermission()" in the Spring EL method annotations like @PreAuthorize we explicitly configure the permissionEvaluator\r
+ the cdmPermissionEvaluator is already defined in the persistence security context\r
+ -->\r
+ <bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">\r
+ <property name="permissionEvaluator" ref="cdmPermissionEvaluator" />\r
+ </bean>\r
+\r
+ <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">\r
+ <property name="providers">\r
+ <list>\r
+ <ref local="daoAuthenticationProvider"/>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">\r
+ <property name="userDetailsService" ref="userService"/>\r
+ <property name="saltSource" ref="saltSource"/>\r
+ <property name="passwordEncoder" ref="passwordEncoder"/>\r
+ </bean>\r
+\r
+ <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"/>\r
+\r
+ <bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">\r
+ <property name="userPropertyToUse" value="getUsername"/>\r
+ </bean>\r
+\r
+ <!--\r
+ Run-As Authentication Replacement for system operations\r
+ as e.g. performed by the eu.etaxonomy.cdm.api.application.FirstDataInserter\r
+\r
+ the key must match FirstDataInserter.RUN_AS_KEY\r
+ -->\r
+ <bean id="runAsManager"\r
+ class="org.springframework.security.access.intercept.RunAsManagerImpl">\r
+ <property name="key" value="TtlCx3pgKC4l"/>\r
+ </bean>\r
+\r
+\r
+</beans>\r
--- /dev/null
+package eu.etaxonomy.taxeditor.remoting;
+
+import org.junit.Test;
+
+import eu.etaxonomy.cdm.remote.api.application.CdmApplicationRemoteController;
+
+public class CdmApplicationRemoteControllerTest {
+
+ @Test
+ public void InitializeTest() {
+ CdmApplicationRemoteController carc = CdmApplicationRemoteController.NewInstance();
+ }
+
+}
--- /dev/null
+/**
+* Copyright (C) 2009 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.remoting;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.UUID;
+
+
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.unitils.UnitilsJUnit4;
+import org.unitils.database.annotations.Transactional;
+import org.unitils.database.util.TransactionMode;
+import org.unitils.dbunit.annotation.DataSet;
+import org.unitils.spring.annotation.SpringApplicationContext;
+import org.unitils.spring.annotation.SpringBeanByType;
+
+import eu.etaxonomy.cdm.api.service.ITaxonService;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.name.NonViralName;
+import eu.etaxonomy.cdm.model.name.Rank;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.taxon.ITaxon;
+import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
+
+
+/**
+ * This test class is a testing ground for solving the hibernate lazy loading problem using aspects
+ *
+ * @author c.mathew
+ *
+ */
+@SpringApplicationContext("classpath:/eu/etaxonomy/cdm/remotingApplicationContext.xml")
+@Transactional(TransactionMode.DISABLED)
+public class RemoteLazyLoadingTest extends UnitilsJUnit4 {
+
+ @SpringBeanByType
+ private ITaxonService taxonService;
+
+ private UUID taxonUuid1 = UUID.fromString("8217ef77-2ab1-4318-bd67-ccd0cdef07c4");
+ private UUID taxonUuid2 = UUID.fromString("ef96fafa-7750-4141-b31b-1ad1daab3e76");
+
+ /**
+ */
+
+// @Test
+// public void testLazyLoading(){
+//
+// Taxon taxon = (Taxon)taxonService.find(taxonUuid1);
+// System.out.println("Taxon title : " + taxon.getTitleCache());
+// taxon.setTitleCache("Taxon Title Cache 1");
+// taxonService.merge(taxon);
+//
+// NonViralName nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
+//
+//
+// System.out.println("name : " + nvn.getTitleCache());
+// nvn.setTitleCache("Taxon Name Title Cache 1");
+// taxonService.merge(taxon);
+//
+// Reference ref = taxon.getSec();
+// System.out.println("Secundum : " + ref.getTitleCache());
+//
+// Rank rank = nvn.getRank();
+// System.out.println("rank : " + rank.getTitleCache());
+//
+// Set<SynonymRelationship> synRelations = taxon.getSynonymRelations();
+// Iterator<SynonymRelationship> srItr = synRelations.iterator();
+// while(srItr.hasNext()) {
+// SynonymRelationship sr = srItr.next();
+// System.out.println("Synonym Relationship : " + sr.getType().getTitleCache());
+// sr.getType().setTitleCache(sr.getType().getTitleCache() + "*");
+// }
+// taxonService.merge(taxon);
+//
+// Set<TaxonRelationship> taxonRelationsFrom = taxon.getRelationsFromThisTaxon();
+// Iterator<TaxonRelationship> trItrFrom = taxonRelationsFrom.iterator();
+// while(trItrFrom.hasNext()) {
+// TaxonRelationship tr = trItrFrom.next();
+// System.out.println("Taxon From Relationship : " + tr.getType().getTitleCache());
+// tr.getType().setTitleCache(tr.getType().getTitleCache() + "*");
+// }
+// taxonService.merge(taxon);
+// Set<TaxonRelationship> taxonRelationsTo = taxon.getRelationsToThisTaxon();
+// Iterator<TaxonRelationship> trItrTo = taxonRelationsTo.iterator();
+// while(trItrTo.hasNext()) {
+// TaxonRelationship tr = trItrTo.next();
+// System.out.println("Taxon To Relationship : " + tr.getType().getTitleCache());
+// tr.getType().setTitleCache(tr.getType().getTitleCache() + "*");
+// }
+// taxonService.merge(taxon);
+// }
+
+ @Test
+ public void testCDMEntityGet() {
+ Taxon taxon = (Taxon)taxonService.find(taxonUuid1);
+ System.out.println("Taxon title : " + taxon.getTitleCache());
+
+ NonViralName nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
+ System.out.println("name : " + nvn.getTitleCache());
+
+ }
+
+ @Test
+ public void testCDMCollectionGet() {
+ Taxon taxon = (Taxon)taxonService.find(taxonUuid1);
+ System.out.println("Taxon title : " + taxon.getTitleCache());
+
+ Set<SynonymRelationship> synRelations = taxon.getSynonymRelations();
+ Iterator<SynonymRelationship> srItr = synRelations.iterator();
+ while(srItr.hasNext()) {
+ SynonymRelationship sr = srItr.next();
+ System.out.println("Synonym Relationship : " + sr.getType().getTitleCache());
+ }
+ }
+
+ @Test
+ public void testCDMEntitySaveEager() {
+ Taxon taxon = (Taxon)taxonService.find(taxonUuid1);
+ String oldTitleCache = taxon.getTitleCache();
+
+ System.out.println("Taxon title : " + oldTitleCache);
+
+ taxon.setTitleCache(oldTitleCache + ":updated");
+ taxonService.merge(taxon);
+
+ Taxon taxonNew = (Taxon)taxonService.find(taxonUuid1);
+ System.out.println("New Taxon Title : " + taxonNew.getTitleCache());
+
+ Assert.assertNotEquals("Title caches should not be equal",oldTitleCache,taxonNew.getTitleCache());
+
+ taxonNew.setTitleCache(oldTitleCache);
+ taxonService.merge(taxonNew);
+
+ Taxon taxonOld = (Taxon)taxonService.find(taxonUuid1);
+ System.out.println("Old Taxon Title : " + taxonOld.getTitleCache());
+
+ Assert.assertEquals("Title caches should be equal",oldTitleCache,taxonOld.getTitleCache());
+
+ }
+
+ @Test
+ public void testCDMEntitySaveLazy() {
+ Taxon taxon = (Taxon)taxonService.find(taxonUuid1);
+
+ NonViralName nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
+ String oldTitleCache = nvn.getTitleCache();
+ System.out.println("Taxon Name Title : " + oldTitleCache);
+ nvn.setTitleCache(oldTitleCache + ":updated");
+ taxonService.merge(taxon);
+
+ Taxon taxonNew = (Taxon)taxonService.find(taxonUuid1);
+ NonViralName nvnNew = CdmBase.deproxy(taxon.getName(),NonViralName.class);
+ System.out.println("New Taxon Name Title : " + nvnNew.getTitleCache());
+
+ Assert.assertNotEquals("Title caches should not be equal",oldTitleCache,nvnNew.getTitleCache());
+
+ nvnNew.setTitleCache(oldTitleCache);
+ taxonService.merge(taxon);
+
+ Taxon taxonOld = (Taxon)taxonService.find(taxonUuid1);
+ NonViralName nvnOld = CdmBase.deproxy(taxon.getName(),NonViralName.class);
+ System.out.println("Old Taxon Name Title : " + nvnNew.getTitleCache());
+
+ Assert.assertEquals("Title caches should be equal",oldTitleCache,nvnOld.getTitleCache());
+ }
+
+ @Test
+ public void testCDMEntitySaveCollection() {
+ Taxon taxon = (Taxon)taxonService.find(taxonUuid1);
+
+ Set<SynonymRelationship> synRelations = taxon.getSynonymRelations();
+ Set<String> relToTitles = new HashSet<String>();
+ Iterator<SynonymRelationship> srItr = synRelations.iterator();
+ while(srItr.hasNext()) {
+ SynonymRelationship sr = srItr.next();
+ System.out.println("Synonym Title Cache : " + sr.getSynonym().getTitleCache());
+ relToTitles.add(sr.getSynonym().getTitleCache());
+ sr.getSynonym().setTitleCache(sr.getSynonym().getTitleCache() + ":updated");
+
+ }
+ taxonService.merge(taxon);
+
+ Taxon taxonNew = (Taxon)taxonService.find(taxonUuid1);
+ Set<SynonymRelationship> synRelationsNew = taxonNew.getSynonymRelations();
+
+ Iterator<SynonymRelationship> srItrNew = synRelationsNew.iterator();
+ Iterator<String> relToTitlesItr = relToTitles.iterator();
+ while(srItrNew.hasNext() && relToTitlesItr.hasNext()) {
+ SynonymRelationship srNew = srItrNew.next();
+ String relToTitle = relToTitlesItr.next();
+ System.out.println("New Synonym Title Cache: " + srNew.getSynonym().getTitleCache());
+ Assert.assertNotEquals("Synonym Title caches should not be equal", srNew.getSynonym().getTitleCache(), relToTitle);
+ srNew.getSynonym().setTitleCache(relToTitle);
+ }
+
+ Taxon taxonOld = (Taxon)taxonService.find(taxonUuid1);
+
+ Set<SynonymRelationship> synRelationsOld = taxonNew.getSynonymRelations();
+ Iterator<SynonymRelationship> srItrOld = synRelationsOld.iterator();
+ relToTitlesItr = relToTitles.iterator();
+ while(srItrOld.hasNext() && relToTitlesItr.hasNext()) {
+ SynonymRelationship srOld = srItrOld.next();
+ String relToTitle = relToTitlesItr.next();
+ System.out.println("New Synonym Title Cache: " + srOld.getSynonym().getTitleCache());
+ Assert.assertEquals("Synonym Title caches should be equal", srOld.getSynonym().getTitleCache(), relToTitle);
+
+ }
+ }
+}