blob: 12c0a88ed10dd07c1e83a438b9072b15a0506766 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// 04/01/2011-2.3 Guy Pelletier
// - 337323: Multi-tenant with shared schema support (part 2)
package org.eclipse.persistence.tools.weaving.jpa;
import java.io.IOException;
import java.io.Writer;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipException;
import jakarta.persistence.spi.ClassTransformer;
import jakarta.persistence.spi.TransformerException;
import org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl;
import org.eclipse.persistence.internal.jpa.StaticWeaveInfo;
import org.eclipse.persistence.internal.jpa.deployment.ArchiveFactoryImpl;
import org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor;
import org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.exceptions.PersistenceUnitLoadingException;
import org.eclipse.persistence.exceptions.StaticWeaveException;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.jpa.Archive;
/**
* <p>
* <b>Description</b>: This class provides the implementation of class transformer by leveraging on the following existing APIs,
* <ul>
* <li> PersistenceUnitProcessor.processORMetadata() - get class descriptor.
* <li> PersistenceUnitProcessor.buildEntityList() - get entity classes lsit.
* <li> TransformerFactory.createTransformerAndModifyProject - get class transformer.
* </ul>
* <p>
* <b>Responsibilities</b>:
* <ul>
* <li> Create the classtransformer for each persistence unit individually and store them into the list.
* <li> Provide class transfom method to perform weaving function.
* </ul>
*/
public class StaticWeaveClassTransformer {
private ArrayList<ClassTransformer> classTransformers;
StaticWeaveInfo info;
private ClassLoader aClassLoader;
/**
* Constructs an instance of StaticWeaveClassTransformer.
*/
public StaticWeaveClassTransformer(URL inputArchiveURL,ClassLoader aclassloader) throws Exception {
this(inputArchiveURL,null, aclassloader,null,SessionLog.OFF);
}
/**
* Constructs an instance of StaticWeaveClassTransformer.
*/
public StaticWeaveClassTransformer(URL inputArchiveURL, String persistenceXMLLocation, ClassLoader aclassloader, Writer logWriter, int loglevel) throws URISyntaxException,IOException {
this.aClassLoader = aclassloader;
this.info = new StaticWeaveInfo(logWriter, loglevel);
buildClassTransformers(inputArchiveURL, persistenceXMLLocation, aclassloader);
}
/**
* The method performs weaving function on the given class.
* @return the converted(woven) class
*/
public byte[] transform(String originalClassName, Class<?> originalClass, byte[] originalClassBytes)throws TransformerException {
byte[] newClassBytes = null;
for(ClassTransformer transformer : classTransformers){
newClassBytes=transformer.transform(aClassLoader, originalClassName, originalClass, null, originalClassBytes);
if(newClassBytes!=null) {
break;
};
}
return newClassBytes;
}
/**
* The method creates classtransformer list corresponding to each persistence unit.
*/
private void buildClassTransformers(URL inputArchiveURL, String persistenceXMLLocation, ClassLoader aclassloader) throws URISyntaxException,IOException{
if (classTransformers!=null) {
return ;
} else {
classTransformers = new ArrayList<ClassTransformer>();
}
Archive archive = null;
try {
archive = (new ArchiveFactoryImpl()).createArchive(inputArchiveURL, persistenceXMLLocation == null ? PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML_DEFAULT : persistenceXMLLocation, null);
List<SEPersistenceUnitInfo> persistenceUnitsList =
PersistenceUnitProcessor.processPersistenceArchive(archive, aclassloader);
if (persistenceUnitsList==null) {
throw PersistenceUnitLoadingException.couldNotGetUnitInfoFromUrl(inputArchiveURL);
}
Map<Object, Object> emptyMap = new HashMap<>(0);
Iterator<SEPersistenceUnitInfo> persistenceUnitsIterator = persistenceUnitsList.iterator();
while (persistenceUnitsIterator.hasNext()) {
SEPersistenceUnitInfo unitInfo = persistenceUnitsIterator.next();
//build class transformer.
String puName = unitInfo.getPersistenceUnitName();
String sessionName = (String)unitInfo.getProperties().get(PersistenceUnitProperties.SESSION_NAME);
if (sessionName == null) {
sessionName = puName;
}
EntityManagerSetupImpl emSetupImpl = new EntityManagerSetupImpl(puName, sessionName);
//indicates that predeploy is used for static weaving, also passes logging parameters
emSetupImpl.setStaticWeaveInfo(this.info);
ClassTransformer transformer = emSetupImpl.predeploy(unitInfo, emptyMap);
if (transformer != null) {
classTransformers.add(transformer);
}
}
} catch (ZipException e) {
throw StaticWeaveException.exceptionOpeningArchive(inputArchiveURL,e);
} finally {
if (archive != null) {
archive.close();
}
}
}
}