com.googlecode.openbeans.DefaultPersistenceDelegate Maven / Gradle / Ivy
Show all versions of app55-java Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.openbeans;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import org.apache.harmony.beans.BeansUtils;
/**
* Default PersistenceDelegate for normal classes. The instances of this class are used when other customized PersistenceDelegate is not set in the encoders for
* a particular type.
*
* This PersistenceDelegate assumes that the bean to be made persistent has a default constructor that takes no parameters or a constructor that takes some
* properties as its parameters. Only the properties that can be got or set based on the knowledge gained through an introspection will be made persistent. In
* the case that a bean is constructed with some properties, the value of these properties should be available via the conventional getter method.
*
*
* @see Encoder
*/
public class DefaultPersistenceDelegate extends PersistenceDelegate
{
// shared empty property name array
private static String[] EMPTY_PROPERTIES = new String[0];
// names of the properties accepted by the bean's constructor
private String[] propertyNames = EMPTY_PROPERTIES;
/**
* Constructs a DefaultPersistenceDelegate
instance that supports the persistence of a bean which has a default constructor.
*
*/
public DefaultPersistenceDelegate()
{
// empty
}
/**
* Constructs a DefaultPersistenceDelegate
instance that supports the persistence of a bean which is constructed with some properties.
*
* @param propertyNames
* the name of the properties that are taken as parameters by the bean's constructor
*/
public DefaultPersistenceDelegate(String[] propertyNames)
{
if (null != propertyNames)
{
this.propertyNames = propertyNames;
}
}
/**
* Initializes the new instance in the new environment so that it becomes equivalent with the old one, meanwhile recording this process in the encoder.
*
* This is done by inspecting each property of the bean. The property value from the old bean instance and the value from the new bean instance are both
* retrieved and examined to see whether the latter mutates to the former, and if not, issue a call to the write method to set the equivalent value for the
* new instance. Exceptions occured during this process are reported to the exception listener of the encoder.
*
*
* @param type
* the type of the bean
* @param oldInstance
* the original bean object to be recorded
* @param newInstance
* the simmulating new bean object to be initialized
* @param enc
* the encoder to write the outputs to
*/
@Override
protected void initialize(Class> type, Object oldInstance, Object newInstance, Encoder enc)
{
// Call the initialization of the super type
super.initialize(type, oldInstance, newInstance, enc);
// Continue only if initializing the "current" type
if (type != oldInstance.getClass())
{
return;
}
// Get all bean properties
BeanInfo info = null;
try
{
info = Introspector.getBeanInfo(type);
}
catch (IntrospectionException ex)
{
enc.getExceptionListener().exceptionThrown(ex);
return;
}
PropertyDescriptor[] pds = info.getPropertyDescriptors();
Method getter, setter;
// Initialize each found non-transient property
for (int i = 0; i < pds.length; i++)
{
// Skip a property whose transient attribute is true
if (Boolean.TRUE.equals(pds[i].getValue("transient"))) { //$NON-NLS-1$
continue;
}
getter = pds[i].getReadMethod();
setter = pds[i].getWriteMethod();
// Skip a property having no setter or getter
if (getter == null || setter == null)
{
continue;
}
// Get the value of the property in the old instance
Expression getterExp = new Expression(oldInstance, getter.getName(), null);
try
{
// Calculate the old value of the property
Object oldVal = getterExp.getValue();
// Write the getter expression to the encoder
enc.writeExpression(getterExp);
// Get the target value that exists in the new environment
Object targetVal = enc.get(oldVal);
Object newVal = new Expression(newInstance, getter.getName(), null).getValue();
if (targetVal == null ? (newVal != null && oldVal == null) : targetVal != newVal && !targetVal.equals(newVal))
{
enc.writeStatement(new Statement(oldInstance, setter.getName(), new Object[] { oldVal }));
}
}
catch (Exception ex)
{
enc.getExceptionListener().exceptionThrown(ex);
}
}
}
/*
* Get the field value of an object using privileged code.
*/
private Object getFieldValue(Object oldInstance, String fieldName) throws NoSuchFieldException, IllegalAccessException
{
Class extends Object> c = oldInstance.getClass();
final Field f = c.getDeclaredField(fieldName);
AccessController.doPrivileged(new PrivilegedAction