From: Cherian Mathew Date: Wed, 12 Feb 2014 12:48:35 +0000 (+0000) Subject: erging from remoting-1.0 branch X-Git-Tag: 3.6.0~792 X-Git-Url: https://dev.e-taxonomy.eu/gitweb/taxeditor.git/commitdiff_plain/f6eae72a89fcca232bd560d6746fce716c9ec953 erging from remoting-1.0 branch - adding new confugration / controller classes for remoting - adding aspect and related aop.xml config file - added aspect and spring remoting jars - updated manifest , pom and classpath for the new dependencies --- diff --git a/.gitattributes b/.gitattributes index e9d2265cc..a057e3836 100644 --- a/.gitattributes +++ b/.gitattributes @@ -140,12 +140,15 @@ eu.etaxonomy.taxeditor.bulkeditor/src/test/java/eu/etaxonomy/taxeditor/bulkedito 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 @@ -299,6 +302,7 @@ eu.etaxonomy.taxeditor.cdmlib/lib/spring-expression-3.2.2.RELEASE.jar -text eu.etaxonomy.taxeditor.cdmlib/lib/spring-modules-cache-0.7.jar -text eu.etaxonomy.taxeditor.cdmlib/lib/spring-security-config-3.1.3.RELEASE.jar -text eu.etaxonomy.taxeditor.cdmlib/lib/spring-security-core-3.1.3.RELEASE.jar -text +eu.etaxonomy.taxeditor.cdmlib/lib/spring-security-remoting-3.1.3.RELEASE.jar -text eu.etaxonomy.taxeditor.cdmlib/lib/stax-1.2.0.jar -text eu.etaxonomy.taxeditor.cdmlib/lib/stax-api-1.0.1.jar -text eu.etaxonomy.taxeditor.cdmlib/lib/unitils-core-3.3.jar -text @@ -329,6 +333,18 @@ eu.etaxonomy.taxeditor.cdmlib/lib/xpp3_min-1.1.4c.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/CdmApplicationRemoteConfiguration.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/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 diff --git a/eu.etaxonomy.taxeditor.cdmlib/.classpath b/eu.etaxonomy.taxeditor.cdmlib/.classpath index c6bf57c85..766a24b44 100644 --- a/eu.etaxonomy.taxeditor.cdmlib/.classpath +++ b/eu.etaxonomy.taxeditor.cdmlib/.classpath @@ -1,5 +1,8 @@ + + + @@ -30,7 +33,7 @@ - + @@ -204,5 +207,6 @@ + diff --git a/eu.etaxonomy.taxeditor.cdmlib/META-INF/MANIFEST.MF b/eu.etaxonomy.taxeditor.cdmlib/META-INF/MANIFEST.MF index 8a64331c9..8ff9d9558 100644 --- a/eu.etaxonomy.taxeditor.cdmlib/META-INF/MANIFEST.MF +++ b/eu.etaxonomy.taxeditor.cdmlib/META-INF/MANIFEST.MF @@ -124,6 +124,7 @@ Export-Package: com.google.api, 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, @@ -349,6 +350,7 @@ Export-Package: com.google.api, org.springframework.security.core.context, org.springframework.security.core.userdetails, org.springframework.security.provisioning, + org.springframework.security.remoting.httpinvoker, org.springframework.stereotype, org.springframework.transaction;uses:="org.springframework.core", org.springframework.transaction.annotation;uses:="javax.ejb,org.springframework.transaction.interceptor", @@ -599,4 +601,6 @@ Bundle-ClassPath: ., lib/yjp-controller-api-redist-9.0.8.jar, lib/google-api-translate-java-0.92.jar, lib/odfdom-0.8.jar, - lib/h2mig_pagestore_addon.jar + lib/h2mig_pagestore_addon.jar, + lib/spring-security-remoting-3.1.3.RELEASE.jar +Import-Package: eu.etaxonomy.cdm.api.application diff --git a/eu.etaxonomy.taxeditor.cdmlib/META-INF/aop.xml b/eu.etaxonomy.taxeditor.cdmlib/META-INF/aop.xml new file mode 100644 index 000000000..80e76a14a --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/META-INF/aop.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eu.etaxonomy.taxeditor.cdmlib/build.properties b/eu.etaxonomy.taxeditor.cdmlib/build.properties index dcedb199b..f6b53c4d7 100644 --- a/eu.etaxonomy.taxeditor.cdmlib/build.properties +++ b/eu.etaxonomy.taxeditor.cdmlib/build.properties @@ -200,5 +200,11 @@ bin.includes = META-INF/,\ lib/yjp-controller-api-redist-9.0.8.jar,\ lib/google-api-translate-java-0.92.jar,\ lib/odfdom-0.8.jar,\ - lib/h2mig_pagestore_addon.jar + lib/h2mig_pagestore_addon.jar,\ + lib/spring-security-remoting-3.1.3.RELEASE.jar +jars.compile.order = . +output.. = bin/ +source.. = src/main/java/,\ + src/main/resources/,\ + src/test/java/ diff --git a/eu.etaxonomy.taxeditor.cdmlib/lib/aspectjrt-1.7.1-sources.jar b/eu.etaxonomy.taxeditor.cdmlib/lib/aspectjrt-1.7.1-sources.jar new file mode 100644 index 000000000..21ffee7c9 Binary files /dev/null and b/eu.etaxonomy.taxeditor.cdmlib/lib/aspectjrt-1.7.1-sources.jar differ diff --git a/eu.etaxonomy.taxeditor.cdmlib/lib/aspectjweaver-1.7.1-sources.jar b/eu.etaxonomy.taxeditor.cdmlib/lib/aspectjweaver-1.7.1-sources.jar new file mode 100644 index 000000000..9625da0b6 Binary files /dev/null and b/eu.etaxonomy.taxeditor.cdmlib/lib/aspectjweaver-1.7.1-sources.jar differ diff --git a/eu.etaxonomy.taxeditor.cdmlib/lib/spring-security-remoting-3.1.3.RELEASE.jar b/eu.etaxonomy.taxeditor.cdmlib/lib/spring-security-remoting-3.1.3.RELEASE.jar new file mode 100644 index 000000000..6268e5868 Binary files /dev/null and b/eu.etaxonomy.taxeditor.cdmlib/lib/spring-security-remoting-3.1.3.RELEASE.jar differ diff --git a/eu.etaxonomy.taxeditor.cdmlib/pom.xml b/eu.etaxonomy.taxeditor.cdmlib/pom.xml index 4df0203a4..dae259d3a 100644 --- a/eu.etaxonomy.taxeditor.cdmlib/pom.xml +++ b/eu.etaxonomy.taxeditor.cdmlib/pom.xml @@ -141,6 +141,16 @@ cdmlib-ext ${cdmlib.version} + + org.aspectj + aspectjrt + 1.7.1 + + + org.aspectj + aspectjweaver + 1.7.1 + AspectJ Compile-Time Weaving " + ll.getEntityName() + " with id " + classid); + Class clazz = (Class) 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; + } + } + +} diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/CdmApplicationRemoteConfiguration.java b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/CdmApplicationRemoteConfiguration.java new file mode 100644 index 000000000..bbd3286bb --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/CdmApplicationRemoteConfiguration.java @@ -0,0 +1,45 @@ +// $Id: CdmApplicationDefaultConfiguration.java 11680 2011-04-04 17:07:39Z a.mueller $ +/** +* Copyright (C) 2007 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.cdm.remote.api.application; + +import org.apache.log4j.Logger; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +import eu.etaxonomy.cdm.api.application.CdmApplicationConfiguration; +import eu.etaxonomy.cdm.api.application.CdmApplicationDefaultConfiguration; +import eu.etaxonomy.cdm.api.conversation.ConversationHolder; +import eu.etaxonomy.cdm.api.conversation.ConversationHolderMock; + +/** + * @author a.mueller + * @created 21.05.2008 + * @version 1.0 + */ +/** + * @author a.mueller + * @author j.koch + */ +@Component +public class CdmApplicationRemoteConfiguration extends CdmApplicationConfiguration implements ICdmApplicationRemoteConfiguration, ApplicationContextAware { + + @SuppressWarnings("unused") + private static final Logger logger = Logger.getLogger(CdmApplicationRemoteConfiguration.class); + + public CdmApplicationRemoteConfiguration() { + } + + @Override + public ConversationHolder NewConversation() { + // TODO Auto-generated method stub + return new ConversationHolderMock(); + } +} diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/CdmApplicationRemoteController.java b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/CdmApplicationRemoteController.java new file mode 100644 index 000000000..0e71ca72f --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/CdmApplicationRemoteController.java @@ -0,0 +1,328 @@ +// $Id: CdmApplicationController.java 11680 2011-04-04 17:07:39Z a.mueller $ +/** + * Copyright (C) 2007 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.cdm.remote.api.application; + +import java.util.UUID; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.security.access.PermissionEvaluator; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.transaction.PlatformTransactionManager; +//import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; + +import eu.etaxonomy.cdm.api.conversation.ConversationHolder; +import eu.etaxonomy.cdm.api.service.IAgentService; +import eu.etaxonomy.cdm.api.service.IClassificationService; +import eu.etaxonomy.cdm.api.service.ICollectionService; +import eu.etaxonomy.cdm.api.service.ICommonService; +import eu.etaxonomy.cdm.api.service.IDatabaseService; +import eu.etaxonomy.cdm.api.service.IDescriptionService; +import eu.etaxonomy.cdm.api.service.IFeatureNodeService; +import eu.etaxonomy.cdm.api.service.IFeatureTreeService; +import eu.etaxonomy.cdm.api.service.IGrantedAuthorityService; +import eu.etaxonomy.cdm.api.service.IGroupService; +import eu.etaxonomy.cdm.api.service.IIdentificationKeyService; +import eu.etaxonomy.cdm.api.service.ILocationService; +import eu.etaxonomy.cdm.api.service.IMediaService; +import eu.etaxonomy.cdm.api.service.INameService; +import eu.etaxonomy.cdm.api.service.IOccurrenceService; +import eu.etaxonomy.cdm.api.service.IPolytomousKeyNodeService; +import eu.etaxonomy.cdm.api.service.IPolytomousKeyService; +import eu.etaxonomy.cdm.api.service.IReferenceService; +import eu.etaxonomy.cdm.api.service.IService; +import eu.etaxonomy.cdm.api.service.ITaxonNodeService; +import eu.etaxonomy.cdm.api.service.ITaxonService; +import eu.etaxonomy.cdm.api.service.ITermService; +import eu.etaxonomy.cdm.api.service.IUserService; +import eu.etaxonomy.cdm.api.service.IVocabularyService; +import eu.etaxonomy.cdm.api.service.IWorkingSetService; +import eu.etaxonomy.cdm.common.monitor.IProgressMonitor; +import eu.etaxonomy.cdm.common.monitor.NullProgressMonitor; +import eu.etaxonomy.cdm.model.common.CdmBase; +import eu.etaxonomy.cdm.model.common.DefinedTermBase; +import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator; + + +/** + * @author a.mueller + * @author j.koch + * + */ +public class CdmApplicationRemoteController implements ICdmApplicationRemoteConfiguration { + private static final Logger logger = Logger.getLogger(CdmApplicationRemoteController.class); + + public static final String DEFAULT_APPLICATION_CONTEXT_RESOURCE = "/eu/etaxonomy/cdm/remotingApplicationContext.xml"; + + public AbstractApplicationContext applicationContext; + private ICdmApplicationRemoteConfiguration configuration; + private Resource applicationContextResource; + private IProgressMonitor progressMonitor; + + /** + * Constructor, opens a spring ApplicationContext with defaults + */ + public static CdmApplicationRemoteController NewInstance() { + logger.info("Configure CdmApplicationRemoteController with defaults"); + return new CdmApplicationRemoteController(null, null); + } + + /** + * Constructor, opens a spring ApplicationContext with given application context + * @param applicationContextResource + */ + public static CdmApplicationRemoteController NewInstance(Resource applicationContextResource, IProgressMonitor progressMonitor) { + logger.info("Configure CdmApplicationRemoteController with given application context"); + return new CdmApplicationRemoteController(applicationContextResource, progressMonitor); + } + + /** + * Constructor, starts the application remote controller + * @param applicationContextResource + */ + private CdmApplicationRemoteController(Resource applicationContextResource, IProgressMonitor progressMonitor){ + logger.info("Start CdmApplicationRemoteController"); + this.applicationContextResource = applicationContextResource != null ? applicationContextResource : new ClassPathResource(DEFAULT_APPLICATION_CONTEXT_RESOURCE); + this.progressMonitor = progressMonitor != null ? progressMonitor : new NullProgressMonitor(); + setNewApplicationContext(); + } + + /** + * Sets the application context to a new spring ApplicationContext and initializes the Controller + */ + private boolean setNewApplicationContext(){ + logger.info("Set new application context"); + progressMonitor.beginTask("Start application context.", 6); + progressMonitor.worked(1); + + GenericApplicationContext applicationContext = new GenericApplicationContext(); + + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(applicationContext); + progressMonitor.subTask("Registering resources."); + xmlReader.loadBeanDefinitions(applicationContextResource); + progressMonitor.worked(1); + + progressMonitor.subTask("This might take a while ..."); + applicationContext.refresh(); + applicationContext.start(); + progressMonitor.worked(1); + + progressMonitor.subTask("Cleaning up."); + setApplicationContext(applicationContext); + progressMonitor.done(); + return true; + } + + /** + * Tests if some DefinedTermsAreMissing. + * @return true, if at least one is missing, else false + */ + public boolean testDefinedTermsAreMissing(){ + UUID englishUuid = UUID.fromString("e9f8cdb7-6819-44e8-95d3-e2d0690c3523"); + DefinedTermBase english = this.getTermService().find(englishUuid); + if ( english == null || ! english.getUuid().equals(englishUuid)){ + return true; + }else{ + return false; + } + } + + /** + * Sets a new application Context. + * @param ac + */ + public void setApplicationContext(AbstractApplicationContext ac){ + closeApplicationContext(); //closes old application context if necessary + applicationContext = ac; + applicationContext.registerShutdownHook(); + init(); + } + + /* (non-Javadoc) + * @see java.lang.Object#finalize() + */ + public void finalize(){ + close(); + } + + /** + * closes the application + */ + public void close(){ + closeApplicationContext(); + } + + /** + * closes the application context + */ + private void closeApplicationContext(){ + if (applicationContext != null){ + logger.info("Close ApplicationContext"); + applicationContext.close(); + } + } + + private void init(){ + logger.info("Init " + this.getClass().getName() + " ... "); + if (logger.isInfoEnabled()){for (String beanName : applicationContext.getBeanDefinitionNames()){ logger.debug(beanName);}} + //TODO delete next row (was just for testing) + if (logger.isInfoEnabled()){ + logger.info("Registered Beans: "); + String[] beanNames = applicationContext.getBeanDefinitionNames(); + for (String beanName : beanNames){ + logger.info(beanName); + } + } + configuration = new CdmApplicationRemoteConfiguration(); + } + + + + /* ****** Services *********/ + + public final INameService getNameService(){ + return configuration.getNameService(); + } + + public final ITaxonService getTaxonService(){ + return configuration.getTaxonService(); + } + + public final IClassificationService getClassificationService(){ + return configuration.getClassificationService(); + } + + public final ITaxonNodeService getTaxonNodeService(){ + return configuration.getTaxonNodeService(); + } + + public final IReferenceService getReferenceService(){ + return configuration.getReferenceService(); + } + + public final IAgentService getAgentService(){ + return configuration.getAgentService(); + } + + public final ITermService getTermService(){ + return configuration.getTermService(); + } + + public final IDescriptionService getDescriptionService(){ + return configuration.getDescriptionService(); + } + + public final IOccurrenceService getOccurrenceService(){ + return configuration.getOccurrenceService(); + } + + public final IMediaService getMediaService(){ + return configuration.getMediaService(); + } + + public final ICommonService getCommonService(){ + return configuration.getCommonService(); + } + + public final ILocationService getLocationService(){ + return configuration.getLocationService(); + } + + public final IUserService getUserService(){ + return configuration.getUserService(); + } + + public IGroupService getGroupService() { + return configuration.getGroupService(); + } + + public final ICollectionService getCollectionService(){ + return configuration.getCollectionService(); + } + + public final IFeatureTreeService getFeatureTreeService(){ + return configuration.getFeatureTreeService(); + } + + public final IFeatureNodeService getFeatureNodeService(){ + return configuration.getFeatureNodeService(); + } + + public final IVocabularyService getVocabularyService(){ + return configuration.getVocabularyService(); + } + + public final IIdentificationKeyService getIdentificationKeyService(){ + return configuration.getIdentificationKeyService(); + } + + public final IPolytomousKeyService getPolytomousKeyService(){ + return configuration.getPolytomousKeyService(); + } + + public final IPolytomousKeyNodeService getPolytomousKeyNodeService(){ + return configuration.getPolytomousKeyNodeService(); + } + + public final IService getMainService(){ + return configuration.getMainService(); + } + + public final IWorkingSetService getWorkingSetService(){ + return configuration.getWorkingSetService(); + } + + + @Override + public ProviderManager getAuthenticationManager() { + return configuration.getAuthenticationManager(); + } + + + + @Override + public ConversationHolder NewConversation() { + return configuration.NewConversation(); + } + + @Override + public Object getBean(String name) { + return configuration.getBean(name); + } + + @Override + public IGrantedAuthorityService getGrantedAuthorityService() { + return configuration.getGrantedAuthorityService(); + } + + @Override + public ICdmPermissionEvaluator getPermissionEvaluator() { + return configuration.getPermissionEvaluator(); + } + + @Override + public void authenticate(String username, String password) { + configuration.authenticate(username, password); + + } + + +} diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/ICdmApplicationRemoteConfiguration.java b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/ICdmApplicationRemoteConfiguration.java new file mode 100644 index 000000000..57b520089 --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/remote/api/application/ICdmApplicationRemoteConfiguration.java @@ -0,0 +1,9 @@ +package eu.etaxonomy.cdm.remote.api.application; + +import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration; + + +public interface ICdmApplicationRemoteConfiguration extends ICdmApplicationConfiguration { + + +} diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java new file mode 100644 index 000000000..adbbd466f --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java @@ -0,0 +1,1175 @@ + + +/* + * 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 Logger log = Logger.getLogger( AbstractPersistentCollection.class ); + + private static final long serialVersionUID = -7238232378593030571L; + + private transient SessionImplementor session; + private boolean initialized; + private transient List 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() { + @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; + } + } + ); + if ( isExtraLazy ) { + return true; + } + } + } + return false; + } + + public static interface LazyInitializationWork { + public T doWork(); + } + + private T withTemporarySessionIfNeeded(LazyInitializationWork 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() { + @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() { + @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( 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() { + @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; + } + +} + diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java new file mode 100644 index 000000000..b9068070c --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java @@ -0,0 +1,410 @@ +/* + * 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'. + *

+ * 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. + *

+ * 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. + *

+ * 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; + } +} diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/httpInvokerServiceClients.xml b/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/httpInvokerServiceClients.xml new file mode 100644 index 000000000..3c548e329 --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/httpInvokerServiceClients.xml @@ -0,0 +1,430 @@ + + + + + + http://${serverName}/${contextPath}/agent.service + + + eu.etaxonomy.cdm.api.service.IAgentService + + + + + + + + + http://${serverName}/${contextPath}/annotation.service + + + eu.etaxonomy.cdm.api.service.IAnnotationService + + + + + + + + + http://${serverName}/${contextPath}/auditevent.service + + + eu.etaxonomy.cdm.api.service.IAuditEventService + + + + + + + + + http://${serverName}/${contextPath}/classification.service + + + eu.etaxonomy.cdm.api.service.IClassificationService + + + + + + + + + http://${serverName}/${contextPath}/collection.service + + + eu.etaxonomy.cdm.api.service.ICollectionService + + + + + + + + + http://${serverName}/${contextPath}/common.service + + + eu.etaxonomy.cdm.api.service.ICommonService + + + + + + + + + http://${serverName}/${contextPath}/description.service + + + eu.etaxonomy.cdm.api.service.IDescriptionService + + + + + + + + + http://${serverName}/${contextPath}/featurenode.service + + + eu.etaxonomy.cdm.api.service.IFeatureNodeService + + + + + + + + + http://${serverName}/${contextPath}/featuretree.service + + + eu.etaxonomy.cdm.api.service.IFeatureTreeService + + + + + + + + + http://${serverName}/${contextPath}/group.service + + + eu.etaxonomy.cdm.api.service.IGroupService + + + + + + + + + http://${serverName}/${contextPath}/identificationkey.service + + + eu.etaxonomy.cdm.api.service.IIdentificationKeyService + + + + + + + + + http://${serverName}/${contextPath}/location.service + + + eu.etaxonomy.cdm.api.service.ILocationService + + + + + + + + + http://${serverName}/${contextPath}/marker.service + + + eu.etaxonomy.cdm.api.service.IMarkerService + + + + + + + + + http://${serverName}/${contextPath}/media.service + + + eu.etaxonomy.cdm.api.service.IMediaService + + + + + + + + + http://${serverName}/${contextPath}/name.service + + + eu.etaxonomy.cdm.api.service.INameService + + + + + + + + + http://${serverName}/${contextPath}/occurrence.service + + + eu.etaxonomy.cdm.api.service.IOccurrenceService + + + + + + + + + http://${serverName}/${contextPath}/polytomouskeynode.service + + + eu.etaxonomy.cdm.api.service.IPolytomousKeyNodeService + + + + + + + + + http://${serverName}/${contextPath}/polytomouskey.service + + + eu.etaxonomy.cdm.api.service.IPolytomousKeyService + + + + + + + + + http://${serverName}/${contextPath}/reference.service + + + eu.etaxonomy.cdm.api.service.IReferenceService + + + + + + + + + + + http://${serverName}/${contextPath}/taxonnode.service + + + eu.etaxonomy.cdm.api.service.ITaxonNodeService + + + + + + + + + http://${serverName}/${contextPath}/taxon.service + + + eu.etaxonomy.cdm.api.service.ITaxonService + + + + + + + + + http://${serverName}/${contextPath}/term.service + + + eu.etaxonomy.cdm.api.service.ITermService + + + + + + + + + http://${serverName}/${contextPath}/user.service + + + eu.etaxonomy.cdm.api.service.IUserService + + + + + + + + + http://${serverName}/${contextPath}/vocabulary.service + + + eu.etaxonomy.cdm.api.service.IVocabularyService + + + + + + + + + http://${serverName}/${contextPath}/workingset.service + + + eu.etaxonomy.cdm.api.service.IWorkingSetService + + + + + + + + + http://${serverName}/${contextPath}/grantedauthority.service + + + eu.etaxonomy.cdm.api.service.IGrantedAuthorityService + + + + + + + + + http://${serverName}/${contextPath}/database.service + + + eu.etaxonomy.cdm.api.service.IDatabaseService + + + + + + + + + http://${serverName}/${contextPath}/lsidauthoruty.service + + + eu.etaxonomy.cdm.api.service.lsid.LSIDAuthorityService + + + + + + + + + http://${serverName}/${contextPath}/lsidmetadata.service + + + eu.etaxonomy.cdm.api.service.lsid.LSIDMetadataService + + + + + + + + + http://${serverName}/${contextPath}/lsiddata.service + + + eu.etaxonomy.cdm.api.service.lsid.LSIDDataService + + + + + + + + + http://${serverName}/${contextPath}/authenticationManager.service + + + org.springframework.security.authentication.AuthenticationManager + + + + + + + + + + + diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remotingApplicationContext.xml b/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remotingApplicationContext.xml new file mode 100644 index 000000000..9e3d1ec65 --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remotingApplicationContext.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remoting_persistence_security.xml b/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remoting_persistence_security.xml new file mode 100644 index 000000000..46916f58e --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remoting_persistence_security.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remoting_services_security.xml b/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remoting_services_security.xml new file mode 100644 index 000000000..fcadad411 --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remoting_services_security.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/CdmApplicationRemoteControllerTest.java b/eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/CdmApplicationRemoteControllerTest.java new file mode 100644 index 000000000..ccb5dc74a --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/CdmApplicationRemoteControllerTest.java @@ -0,0 +1,14 @@ +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(); + } + +} diff --git a/eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/RemoteLazyLoadingTest.java b/eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/RemoteLazyLoadingTest.java new file mode 100644 index 000000000..23b43151a --- /dev/null +++ b/eu.etaxonomy.taxeditor.cdmlib/src/test/java/eu/etaxonomy/taxeditor/remoting/RemoteLazyLoadingTest.java @@ -0,0 +1,215 @@ +/** +* 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.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.taxon.SynonymRelationship; +import eu.etaxonomy.cdm.model.taxon.Taxon; + + +/** + * 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 synRelations = taxon.getSynonymRelations(); +// Iterator 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 taxonRelationsFrom = taxon.getRelationsFromThisTaxon(); +// Iterator 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 taxonRelationsTo = taxon.getRelationsToThisTaxon(); +// Iterator 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 synRelations = taxon.getSynonymRelations(); + Iterator 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 synRelations = taxon.getSynonymRelations(); + Set relToTitles = new HashSet(); + Iterator 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 synRelationsNew = taxonNew.getSynonymRelations(); + + Iterator srItrNew = synRelationsNew.iterator(); + Iterator 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 synRelationsOld = taxonNew.getSynonymRelations(); + Iterator 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); + + } + } +}