| BOStorageCommand.java |
/* PAT: Persistent Applications Toolkit (patsystem.sf.net)
* Copyright (C) 2004, 2005 Tomasz Nazar, nthx at irc dot pl
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Full version of the license is /docs/LICENSE.txt
*/
package org.nthx.pat;
import org.apache.log4j.Logger;
import org.prevayler.Command;
import org.prevayler.PrevalentSystem;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
/** Command for (re)creating a business object - tagged with 'pat.bo' annotation.
* <p>When I want to solve "baptism problem", then I cannot simply put whole object
* into {@link GenericCommand GenericCommand}. I put OIDs there. But earlier I create every
* BO inside this command.
*
* @version $Id: BOStorageCommand.java 3725 2005-06-09 23:57:03Z nthx $
* @author nthx@users.sourceforge.net
*/
public class BOStorageCommand
implements Command
{
//--- Fields ----------------
private Class clazz;
private ObjectForStream[] classAndArgsForStream;
private Class[] parameterTypes; //to differ between 'long' and 'Long', etc.
//--- Constructors ----------
public BOStorageCommand(Constructor constructor,
Object[] args)
{
this.clazz = constructor.getDeclaringClass();
this.classAndArgsForStream =
CommandGenerationHelper.targetAndBos2FakeOIDs("", args);
this.parameterTypes = constructor.getParameterTypes();
if (!Modifier.isPublic(constructor.getModifiers()))
throw new IllegalStateException("Constructor: " + constructor
+ " has to be public!");
}
//--- Implementation --------
/** Invoked during writing (made by AOP) and reading (made by Prevayler
* deserialisation)
*/
public Serializable execute(PrevalentSystem system)
throws Throwable
{
Constructor constructor = clazz.getConstructor(parameterTypes);
Object[] recoveredArgs =
CommandGenerationHelper.fakeBOs2targetAndBos((IdentityMap) system,
classAndArgsForStream,
constructor.toString(),
parameterTypes);
try
{
Object[] recoveredArgsOnly =
new Object[recoveredArgs.length - 1];
System.arraycopy(recoveredArgs, 1,
recoveredArgsOnly, 0,
recoveredArgsOnly.length);
constructor.setAccessible(true);
Object created = constructor.newInstance(recoveredArgsOnly);
Pat.getInstance().getRootAsIdentityMap().putObject((Identifiable) created);
return (Serializable) created;
}
catch (IllegalAccessException e)
{
throw e.getCause();
}
catch (java.lang.reflect.InvocationTargetException e)
{
//log.error("Normal execution error. Commands may throw them: " + e.getMessage(), e);
//normal execution Exception: commands may throw them..
//XXX: i'm not sure if above stmnt is true
throw e.getCause();
}
}
private void logRecoveredParams(Object[] recoveredParams)
{
for (int i = 0; i < recoveredParams.length; i++)
{
Object recoveredParam = recoveredParams[i];
log.debug("\tRecovered: " + recoveredParam.toString());
}
}
//--- internal Fields -------
private transient static Logger log = Logger.getLogger("pat");
}