blob: fc6acb06c4f0e4d44f1b74df83727b5ce38073b4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* 10/09/2012-2.5 Guy Pelletier
* - 374688: JPA 2.1 Converter support
* 10/25/2012-2.5 Guy Pelletier
* - 374688: JPA 2.1 Converter support
* 10/30/2012-2.5 Guy Pelletier
* - 374688: JPA 2.1 Converter support
* 11/28/2012-2.5 Guy Pelletier
* - 374688: JPA 2.1 Converter support
* 06/03/2013-2.5.1 Guy Pelletier
* - 402380: 3 jpa21/advanced tests failed on server with
* "java.lang.NoClassDefFoundError: org/eclipse/persistence/testing/models/jpa21/advanced/enums/Gender"
* 07/16/2013-2.5.1 Guy Pelletier
* - 412384: Applying Converter for parameterized basic-type for joda-time's DateTime does not work
******************************************************************************/
package org.eclipse.persistence.mappings.converters;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.DirectMapMapping;
import org.eclipse.persistence.mappings.DirectToFieldMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.sessions.Session;
import javax.persistence.AttributeConverter;
import javax.persistence.PersistenceException;
/**
* A JPA attribute converter class wrapped with an EclipseLink converter. This
* class is placed directly on mappings.
*
* @author Guy Pelletier
* @since Eclipselink 2.5
*/
public class ConverterClass implements Converter {
protected boolean isForMapKey;
protected boolean disableConversion;
protected Class fieldClassification;
protected String fieldClassificationName;
protected String attributeConverterClassName;
protected AttributeConverter attributeConverter;
/**
* INTERNAL:
* This method will be called when creating a converter for an embedded
* mapping attribute. The isForMapKey information will need to be known
* for proper initialization.
*/
public ConverterClass(String attributeConverterClassName, boolean isForMapKey, String fieldClassificationName, boolean disableConversion) {
this.isForMapKey = isForMapKey;
this.disableConversion = disableConversion;
this.fieldClassificationName = fieldClassificationName;
this.attributeConverterClassName = attributeConverterClassName;
}
/**
* INTERNAL:
* Convert all the class-name-based settings in this converter to actual
* class-based settings. This method is used when converting a project
* that has been built with class names to a project with classes.
*/
public void convertClassNamesToClasses(ClassLoader classLoader){
Class attributeConverterClass = null;
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
try {
attributeConverterClass = (Class) AccessController.doPrivileged(new PrivilegedClassForName(attributeConverterClassName, true, classLoader));
attributeConverter = AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(attributeConverterClass));
} catch (PrivilegedActionException exception) {
throw ValidationException.classNotFoundWhileConvertingClassNames(attributeConverterClassName, exception.getException());
}
} else {
attributeConverterClass = PrivilegedAccessHelper.getClassForName(attributeConverterClassName, true, classLoader);
attributeConverter = (AttributeConverter) PrivilegedAccessHelper.newInstanceFromClass(attributeConverterClass);
}
} catch (ClassNotFoundException exception) {
throw ValidationException.classNotFoundWhileConvertingClassNames(attributeConverterClassName, exception);
} catch (IllegalAccessException exception) {
throw ValidationException.errorInstantiatingClass(attributeConverterClass, exception);
} catch (InstantiationException exception) {
throw ValidationException.errorInstantiatingClass(attributeConverterClass, exception);
}
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
fieldClassification = (Class) AccessController.doPrivileged(new PrivilegedClassForName(fieldClassificationName, true, classLoader));
} catch (PrivilegedActionException exception) {
throw ValidationException.classNotFoundWhileConvertingClassNames(fieldClassificationName, exception.getException());
}
} else {
fieldClassification = PrivilegedAccessHelper.getClassForName(fieldClassificationName, true, classLoader);
}
} catch (ClassNotFoundException exception) {
throw ValidationException.classNotFoundWhileConvertingClassNames(attributeConverterClassName, exception);
}
}
/**
* INTERNAL:
*/
@Override
public Object convertDataValueToObjectValue(Object dataValue, Session session) {
try {
return attributeConverter.convertToEntityAttribute(dataValue);
} catch (RuntimeException re) {
throw new PersistenceException(ExceptionLocalization.buildMessage("wrap_convert_exception",
new Object[]{"convertToEntityAttribute", attributeConverterClassName, dataValue}), re);
}
}
/**
* INTERNAL:
*/
@Override
public Object convertObjectValueToDataValue(Object objectValue, Session session) {
try {
return attributeConverter.convertToDatabaseColumn(objectValue);
} catch (RuntimeException re) {
throw new PersistenceException(ExceptionLocalization.buildMessage("wrap_convert_exception",
new Object[]{"convertToDatabaseColumn", attributeConverterClassName, objectValue}), re);
}
}
/**
* INTERNAL:
*/
@Override
public void initialize(DatabaseMapping mapping, Session session) {
// Ensure the mapping has the correct field classification set.
if (mapping.isDirectToFieldMapping()) {
DirectToFieldMapping m = (DirectToFieldMapping) mapping;
if (disableConversion) {
m.setConverter(null);
} else {
m.setConverter(this);
m.setFieldClassification(fieldClassification);
m.setFieldClassificationClassName(fieldClassificationName);
}
} else if (mapping.isDirectMapMapping() && isForMapKey) {
DirectMapMapping m = (DirectMapMapping) mapping;
if (disableConversion) {
m.setKeyConverter(null);
} else {
m.setKeyConverter(this);
m.setDirectKeyFieldClassification(fieldClassification);
m.setDirectKeyFieldClassificationName(fieldClassificationName);
}
} else if (mapping.isDirectCollectionMapping()) {
DirectCollectionMapping m = (DirectCollectionMapping) mapping;
if (disableConversion) {
m.setValueConverter(null);
} else {
m.setValueConverter(this);
m.setDirectFieldClassification(fieldClassification);
m.setDirectFieldClassificationName(fieldClassificationName);
}
} else {
// TODO: what else could it be???
}
}
/**
* INTERNAL:
*/
@Override
public boolean isMutable() {
return false;
}
}