2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.io
.common
;
12 import java
.lang
.reflect
.Constructor
;
13 import java
.lang
.reflect
.InvocationTargetException
;
14 import java
.util
.HashSet
;
17 import org
.apache
.commons
.lang
.StringUtils
;
18 import org
.apache
.log4j
.Logger
;
19 import org
.hibernate
.SessionFactory
;
20 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
21 import org
.springframework
.transaction
.PlatformTransactionManager
;
22 import org
.springframework
.transaction
.TransactionDefinition
;
23 import org
.springframework
.transaction
.TransactionStatus
;
24 import org
.springframework
.transaction
.support
.DefaultTransactionDefinition
;
26 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationDefaultConfiguration
;
27 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
28 import eu
.etaxonomy
.cdm
.io
.common
.events
.IIoEvent
;
29 import eu
.etaxonomy
.cdm
.io
.common
.events
.IIoObserver
;
30 import eu
.etaxonomy
.cdm
.io
.common
.events
.IoProblemEvent
;
31 import eu
.etaxonomy
.cdm
.io
.common
.events
.IoProgressEvent
;
32 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
39 public abstract class CdmIoBase
<STATE
extends IoStateBase
> extends CdmApplicationDefaultConfiguration
40 implements ICdmIO
<STATE
>, IIoObservable
{
41 private static final Logger logger
= Logger
.getLogger(CdmIoBase
.class);
43 private final Set
<IIoObserver
> observers
= new HashSet
<IIoObserver
>();
44 protected String ioName
= null;
52 this.ioName
= this.getClass().getSimpleName();
55 //******************** Observers *********************************************************
58 public boolean addObserver(IIoObserver observer
){
59 return observers
.add(observer
);
63 * @see eu.etaxonomy.cdm.io.common.IIoObservable#getObservers()
66 public Set
<IIoObserver
> getObservers() {
71 * @see eu.etaxonomy.cdm.io.common.IIoObservable#addObservers(java.util.Set)
74 public void addObservers(Set
<IIoObserver
> newObservers
) {
75 for (IIoObserver observer
: newObservers
){
76 this.observers
.add(observer
);
82 * @see eu.etaxonomy.cdm.io.common.IIoObservable#countObservers()
85 public int countObservers(){
86 return observers
.size();
91 * @see eu.etaxonomy.cdm.io.common.IIoObservable#removeObserver(eu.etaxonomy.cdm.io.common.events.IIoObserver)
94 public boolean removeObserver(IIoObserver observer
){
95 return observers
.remove(observer
);
99 * @see eu.etaxonomy.cdm.io.common.IIoObservable#removeObservers()
102 public void removeObservers(){
103 observers
.removeAll(observers
);
108 * @see eu.etaxonomy.cdm.io.common.ICdmIO#fire(eu.etaxonomy.cdm.io.common.events.IIoEvent)
111 public void fire(IIoEvent event
){
112 for (IIoObserver observer
: observers
){
113 observer
.handleEvent(event
);
117 //******************** End Observers *********************************************************
121 public int countSteps(){
127 * @see eu.etaxonomy.cdm.io.common.ICdmExport#invoke(eu.etaxonomy.cdm.io.common.ExportStateBase)
130 public boolean invoke(STATE state
) {
131 if (isIgnore( state
)){
132 logger
.info("No invoke for " + ioName
+ " (ignored)");
135 updateProgress(state
, "Invoking " + ioName
);
137 return state
.isSuccess();
142 * invoke method to be implemented by implementing classes
146 protected abstract void doInvoke(STATE state
);
149 private SessionFactory sessionFactory
;
152 * flush the current session
154 //TODO move into super class CdmApplicationDefaultConfiguration#flush() ?
155 public void flush() {
156 sessionFactory
.getCurrentSession().flush();
160 * @see eu.etaxonomy.cdm.api.application.CdmApplicationDefaultConfiguration#startTransaction()
163 //TODO seems to be exact duplicate of CdmApplicationDefaultConfiguration#startTransaction(), remove duplicate
164 public TransactionStatus
startTransaction() {
165 return startTransaction(false);
169 * @see eu.etaxonomy.cdm.api.application.CdmApplicationDefaultConfiguration#startTransaction(java.lang.Boolean)
172 //TODO seems to be exact duplicate of CdmApplicationDefaultConfiguration#startTransaction(java.lang.Boolean)
173 public TransactionStatus
startTransaction(Boolean readOnly
) {
175 DefaultTransactionDefinition defaultTxDef
= new DefaultTransactionDefinition();
176 defaultTxDef
.setReadOnly(readOnly
);
177 TransactionDefinition txDef
= defaultTxDef
;
179 // Log some transaction-related debug information.
180 if (logger
.isDebugEnabled()) {
181 logger
.debug("Transaction name = " + txDef
.getName());
182 logger
.debug("Transaction facets:");
183 logger
.debug("Propagation behavior = " + txDef
.getPropagationBehavior());
184 logger
.debug("Isolation level = " + txDef
.getIsolationLevel());
185 logger
.debug("Timeout = " + txDef
.getTimeout());
186 logger
.debug("Read Only = " + txDef
.isReadOnly());
187 // org.springframework.orm.hibernate4.HibernateTransactionManager
188 // provides more transaction/session-related debug information.
191 TransactionStatus txStatus
= super.getTransactionManager().getTransaction(txDef
);
196 //TODO seems to be exact duplicate of CdmApplicationDefaultConfiguration#startTransaction(java.lang.Boolean), remove duplicate?
197 public void commitTransaction(TransactionStatus txStatus
){
198 PlatformTransactionManager txManager
= super.getTransactionManager();
199 txManager
.commit(txStatus
);
203 //TODO move into super class CdmApplicationDefaultConfiguration#startTransaction(java.lang.Boolean)
204 public void rollbackTransaction(TransactionStatus txStatus
){
205 PlatformTransactionManager txManager
= super.getTransactionManager();
206 txManager
.rollback(txStatus
);
211 * @see eu.etaxonomy.cdm.io.common.ICdmIO#check(eu.etaxonomy.cdm.io.common.IIoConfigurator)
214 public boolean check(STATE state
) {
215 if (isIgnore(state
)){
216 logger
.info("No check for " + ioName
+ " (ignored)");
219 return doCheck(state
);
223 protected abstract boolean doCheck(STATE state
);
227 * @see eu.etaxonomy.cdm.io.common.ICdmIO#invoke(eu.etaxonomy.cdm.io.common.IIoConfigurator, java.util.Map)
229 // public boolean invoke(T config,
230 // Map<String, MapWrapper<? extends CdmBase>> stores) {
231 // if (isIgnore(config)){
232 // logger.warn("No invoke for " + ioName + " (ignored)");
235 // return doInvoke(config, stores);
239 // protected abstract boolean doInvoke(T config,
240 // Map<String, MapWrapper<? extends CdmBase>> stores);
244 * Returns true if this (IO-)class should be ignored during the import/export process.
245 * This information is usually stored in the configuration
249 protected abstract boolean isIgnore(STATE state
);
251 protected <T
extends CdmBase
> T
getInstance(Class
<?
extends T
> clazz
){
254 Constructor
<?
extends T
> constructor
= clazz
.getDeclaredConstructor();
255 constructor
.setAccessible(true);
256 result
= constructor
.newInstance();
257 } catch (InstantiationException e
) {
258 logger
.error("Class " + clazz
.getSimpleName()+" could not be instantiated. Class = " );
260 } catch (IllegalAccessException e
) {
261 logger
.error("Constructor of class "+clazz
.getSimpleName()+" could not be accessed." );
263 } catch (SecurityException e
) {
265 } catch (NoSuchMethodException e
) {
266 logger
.error("SecurityException for Constructor of class "+clazz
.getSimpleName()+"." );
268 } catch (IllegalArgumentException e
) {
269 logger
.error("Empty Constructor does not exist for class "+clazz
.getSimpleName()+"." );
271 } catch (InvocationTargetException e
) {
272 logger
.error("Empty Constructor could not be invoked for class "+clazz
.getSimpleName()+"." );
279 protected String
getSuccessString(boolean success
){
281 return "with success";
283 return "with errors";
288 public void updateProgress(STATE state
, String message
) {
289 updateProgress(state
, message
, 1);
293 public void updateProgress(STATE state
, String message
, int worked
) {
294 IProgressMonitor progressMonitor
= state
.getConfig().getProgressMonitor();
295 if(progressMonitor
!= null){
296 progressMonitor
.worked(worked
);
297 progressMonitor
.subTask(message
);
302 public void warnProgress(STATE state
, String message
, Throwable e
) {
303 if(state
.getConfig().getProgressMonitor() != null){
304 IProgressMonitor monitor
= state
.getConfig().getProgressMonitor();
306 monitor
.warning(message
);
308 monitor
.warning(message
, e
);
313 protected void fireProgressEvent(String message
, String location
) {
314 IoProgressEvent event
= new IoProgressEvent();
315 event
.setThrowingClass(this.getClass());
316 event
.setMessage(message
);
317 event
.setLocation(location
);
318 // int linenumber = new Exception().getStackTrace()[0].getLineNumber();
323 protected void fireWarningEvent(String message
, String dataLocation
, Integer severity
) {
324 fireWarningEvent(message
, dataLocation
, severity
, 1);
327 protected void fireWarningEvent(String message
, String dataLocation
, Integer severity
, int stackDepth
) {
329 StackTraceElement
[] stackTrace
= new Exception().getStackTrace();
330 int lineNumber
= stackTrace
[stackDepth
].getLineNumber();
331 String methodName
= stackTrace
[stackDepth
].getMethodName();
333 IoProblemEvent event
= IoProblemEvent
.NewInstance(this.getClass(), message
, dataLocation
,
334 lineNumber
, severity
, methodName
);
336 //for performance improvement one may read:
337 //http://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection
338 // Object o = new SecurityManager().getSecurityContext();
344 protected boolean isBlank(String str
){
345 return StringUtils
.isBlank(str
);
348 protected boolean isNotBlank(String str
){
349 return StringUtils
.isNotBlank(str
);
354 // * Returns the first stack trace element of the first class not equal to "StackTraceUtils" or "LogUtils" and aClass. <br />
355 // * Stored in array of the callstack. <br />
356 // * Allows to get past a certain class.
357 // * @param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils.
358 // * @return stackTraceElement (never null, because if aClass is not found, returns first class past StackTraceUtils)
359 // * @throws AssertionFailedException if resulting statckTrace is null (RuntimeException)
361 // public static StackTraceElement getCallingStackTraceElement(final Class aclass) {
362 // final Throwable t = new Throwable();
363 // final StackTraceElement[] ste = t.getStackTrace();
365 // final int limit = ste.length;
366 // StackTraceElement st = ste[index];
367 // String className = st.getClassName();
368 // boolean aclassfound = false;
369 // if(aclass == null) {
370 // aclassfound = true;
372 // StackTraceElement resst = null;
373 // while(index < limit) {
374 // if(shouldExamine(className, aclass) == true) {
375 // if(resst == null) {
378 // if(aclassfound == true) {
379 // final StackTraceElement ast = onClassFound(aclass, className, st);
387 // if(aclass != null && aclass.getName().equals(className) == true) {
388 // aclassfound = true;
392 // index = index + 1;
394 // className = st.getClassName();
396 // if(resst == null) {
397 // throw new AssertionFailedException(StackTraceUtils.getClassMethodLine() + " null argument:" + "stack trace should null"); //$NON-NLS-1$
402 // static private boolean shouldExamine(String className, Class aclass) {
403 // final boolean res = StackTraceUtils.class.getName().equals(className) == false && (className.endsWith(LOG_UTILS
404 // ) == false || (aclass !=null && aclass.getName().endsWith(LOG_UTILS)));
408 // static private StackTraceElement onClassFound(Class aclass, String className, StackTraceElement st) {
409 // StackTraceElement resst = null;
410 // if(aclass != null && aclass.getName().equals(className) == false)
414 // if(aclass == null)