/******************************************************************************* | |
* Copyright (c) 1998, 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: | |
* Oracle - initial API and implementation from Oracle TopLink | |
******************************************************************************/ | |
package org.eclipse.persistence.tools.workbench.test.mappingsio.legacy; | |
import java.io.File; | |
import java.net.URISyntaxException; | |
import junit.framework.TestCase; | |
import org.eclipse.persistence.tools.PackageRenamer; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWLoginSpec; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWTable; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWCachingPolicy; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWDescriptorCachingPolicy; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClass; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClassRepository; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWMethod; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.project.relational.MWRelationalProject; | |
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.relational.MWAbstractRelationalReadQuery; | |
import org.eclipse.persistence.tools.workbench.test.mappingsmodel.MappingsModelTestTools; | |
import org.eclipse.persistence.tools.workbench.test.mappingsmodel.MappingsModelTestTools.ClassRepositoryTypesFieldDifferentiator; | |
import org.eclipse.persistence.tools.workbench.test.utility.TestTools; | |
import org.eclipse.persistence.tools.workbench.utility.ClassTools; | |
import org.eclipse.persistence.tools.workbench.utility.diff.CompositeDiff; | |
import org.eclipse.persistence.tools.workbench.utility.diff.Diff; | |
import org.eclipse.persistence.tools.workbench.utility.diff.DiffEngine; | |
import org.eclipse.persistence.tools.workbench.utility.diff.EqualityDifferentiator; | |
import org.eclipse.persistence.tools.workbench.utility.diff.ReferenceDifferentiator; | |
import org.eclipse.persistence.tools.workbench.utility.diff.ReflectiveDifferentiator; | |
import org.eclipse.persistence.tools.workbench.utility.io.FileTools; | |
/** | |
* This abstract class provides the common behavior for testing | |
* backward-compatibility with MW project files: | |
* - it defines the projects that should be tested | |
* - it adds a few more fields to ignore | |
* - it provides a simple API for renaming project files | |
* | |
* Subclasses need to: | |
* - extend setUp() to add any more fields that need to be ignored during comparison | |
* - implement readOldProjectFor(MWRProject) to read the appropriate old project | |
* (and rename it if necessary) | |
*/ | |
public abstract class BackwardCompatibilityTestCase | |
extends TestCase | |
{ | |
private DiffEngine diffEngine; | |
protected BackwardCompatibilityTestCase(String name) { | |
super(name); | |
} | |
public void setUp() throws Exception { | |
super.setUp(); | |
TestTools.setUpOracleProxy(); | |
this.diffEngine = this.buildDiffEngine(); | |
} | |
protected DiffEngine buildDiffEngine() { | |
DiffEngine de = MappingsModelTestTools.buildDiffEngine(); | |
ReflectiveDifferentiator rd; | |
rd = (ReflectiveDifferentiator) de.getUserDifferentiator(MWClassRepository.class); | |
// the classpath has changed over the years | |
rd.ignoreFieldsNamed("classpathEntries"); | |
// the old projects have some extraneous classes saved to XML | |
ReferenceDifferentiator utDifferentiator = (ReferenceDifferentiator) rd.getFieldDifferentiator("userTypes"); | |
rd.replaceFieldDifferentiator("userTypes", new ClassRepositoryTypesFieldDifferentiator(utDifferentiator)); | |
rd = (ReflectiveDifferentiator) de.getUserDifferentiator(MWClass.class); | |
// the modifier and interfaces are treated differently now in "stub" MWClasses | |
rd.ignoreFieldsNamed("modifier", "interfaceHandles"); | |
rd = (ReflectiveDifferentiator) de.getUserDifferentiator(MWLoginSpec.class); | |
// the drivers, servers, and logins have changed over the years | |
rd.ignoreFieldsNamed("url", "userName", "driverClasspathEntries"); | |
rd = (ReflectiveDifferentiator) de.getUserDifferentiator(MWMethod.class); | |
// MWMethods did not have exception types in 4.0 | |
rd.ignoreFieldsNamed("exceptionTypeHandles"); | |
rd = (ReflectiveDifferentiator) de.getUserDifferentiator(MWRelationalProject.class); | |
// this will be different for legacy projects 5.0 and before | |
rd.ignoreFieldsNamed("generateDeprecatedDirectMappings"); | |
rd = de.addReflectiveDifferentiator(MWAbstractRelationalReadQuery.class); | |
setUpDescriptorCachingPolicyDifferentiator(de); | |
rd = (ReflectiveDifferentiator) de.getUserDifferentiator(MWDescriptorCachingPolicy.class); | |
// Need to perform a custom test to compare default value to project default value | |
rd.ignoreFieldNamed("cacheTypeHolder"); | |
rd.ignoreFieldNamed("existenceChecking"); | |
rd = (ReflectiveDifferentiator) de.getUserDifferentiator(MWTable.class); | |
//this is only used on reading of a legacy project and gets to a default null value of True | |
rd.ignoreFieldNamed("legacyIsFullyQualified"); | |
return de; | |
} | |
private void setUpDescriptorCachingPolicyDifferentiator(DiffEngine de) { | |
de.setUserDifferentiator(MWDescriptorCachingPolicy.class, | |
new ReflectiveDifferentiator(MWDescriptorCachingPolicy.class, de.getRecordingDifferentiator()) { | |
public Diff diff(Object object1, Object object2) { | |
return new CompositeDiff( | |
object1, | |
object2, | |
new Diff[] { | |
super.diff(object1, object2), | |
cacheTypeDiff((MWCachingPolicy) object1, (MWCachingPolicy) object2) | |
}, | |
this | |
); | |
} | |
private Diff cacheTypeDiff(MWCachingPolicy cachingPolicy1, MWCachingPolicy cachingPolicy2) { | |
if (cachingPolicy1.getCacheType() != cachingPolicy2.getCacheType() && | |
cachingPolicy1.getCacheType().getMWModelOption() == MWCachingPolicy.CACHE_TYPE_PROJECT_DEFAULT) | |
{ | |
String cacheType1 = cachingPolicy1.getProject().getDefaultsPolicy().getCachingPolicy().getCacheType().getMWModelOption(); | |
String cacheType2 = cachingPolicy2.getCacheType().getMWModelOption(); | |
return new CompositeDiff( | |
cachingPolicy1, | |
cachingPolicy2, | |
new Diff[] { | |
EqualityDifferentiator.instance().diff(cacheType1, cacheType2), | |
cacheExistenceCheckingDiff(cachingPolicy1, cachingPolicy2) | |
}, | |
this | |
); | |
} | |
return cacheExistenceCheckingDiff(cachingPolicy1, cachingPolicy2); | |
} | |
private Diff cacheExistenceCheckingDiff(MWCachingPolicy cachingPolicy1, MWCachingPolicy cachingPolicy2) { | |
if (cachingPolicy1.getExistenceChecking() != cachingPolicy2.getExistenceChecking() && | |
cachingPolicy1.getExistenceChecking().getMWModelOption() == MWCachingPolicy.EXISTENCE_CHECKING_PROJECT_DEFAULT) | |
{ | |
String existenceChecking1 = cachingPolicy1.getProject().getDefaultsPolicy().getCachingPolicy().getExistenceChecking().getMWModelOption(); | |
String existenceChecking2 = cachingPolicy2.getExistenceChecking().getMWModelOption(); | |
return EqualityDifferentiator.instance().diff(existenceChecking1, existenceChecking2); | |
} | |
return EqualityDifferentiator.instance().diff(cachingPolicy1.getExistenceChecking(), cachingPolicy2.getExistenceChecking()); | |
} | |
} | |
); | |
} | |
protected void tearDown() throws Exception { | |
TestTools.clear(this); | |
super.tearDown(); | |
} | |
/** | |
* rename all the files in the specified directory tree; | |
* use the specified properties file; | |
* put the files in a temporary directory with the specified name; | |
* return the new directory that contains the renamed files | |
*/ | |
private File renameDirectoryTree(String propertiesFileName, File sourceDirectory, String destinationDirectoryName) throws URISyntaxException { | |
propertiesFileName = FileTools.resourceFile("/backwards-compatibility/rename/" + propertiesFileName).getAbsolutePath(); | |
String sourceDirectoryName = sourceDirectory.getAbsolutePath(); | |
File workDirectory = FileTools.temporaryDirectory("MW-backward-compatibility"); | |
File destinationDirectory = new File(workDirectory, destinationDirectoryName); | |
destinationDirectory.mkdirs(); | |
FileTools.deleteDirectoryContents(destinationDirectory); | |
destinationDirectoryName = destinationDirectory.getAbsolutePath(); | |
File logFile = new File(workDirectory, destinationDirectory.getName() + ".log"); | |
if (logFile.exists()) { | |
if ( ! logFile.delete()) { | |
throw new RuntimeException("unable to delete package renamer log file: " + logFile.getAbsolutePath()); | |
} | |
} | |
String logFileName = logFile.getAbsolutePath(); | |
PackageRenamer renamer = new PackageRenamer(new String[] { | |
propertiesFileName, | |
sourceDirectoryName, | |
destinationDirectoryName, | |
logFileName}); | |
renamer.run(); | |
// I don't understand: #run() is public, but #cleanup() is protected; | |
// and you can't call #run() without calling #cleanup() or the log doesn't get closed... | |
ClassTools.invokeMethod(renamer, "cleanup"); | |
return destinationDirectory; | |
} | |
/** | |
* rename all the files in the specified directory tree; | |
* return the new directory that contains the renamed files | |
*/ | |
protected File renameDirectoryTree(File sourceDirectory, String version) throws URISyntaxException { | |
// first rename the tree with the standard properties file... | |
return this.renameDirectoryTree("eclipselinkPackageRename.properties", sourceDirectory, sourceDirectory.getName() + " " + version + " (temp renamed)"); | |
} | |
protected Diff diff(Object object1, Object object2) { | |
return this.diffEngine.diff(object1, object2); | |
} | |
} |