Skip to content

Commit

Permalink
deep copy via serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
lprimak committed Nov 19, 2024
1 parent 4c255ef commit 4a79348
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
Expand All @@ -78,36 +82,37 @@
import static org.glassfish.weld.WeldDeployer.WELD_BOOTSTRAP;
import static org.glassfish.weld.connector.WeldUtils.*;



/*
* The means by which Weld Beans are discovered on the classpath.
*/
public class BeanDeploymentArchiveImpl implements BeanDeploymentArchive {
public class BeanDeploymentArchiveImpl implements BeanDeploymentArchive, Serializable {
private static final long serialVersionUID = 1L;

private static final Logger logger = Logger.getLogger(BeanDeploymentArchiveImpl.class.getName());

private ReadableArchive archive;
private String id;
private List<String> moduleClassNames = null; // Names of classes in the module
private List<String> beanClassNames = null; // Names of bean classes in the module
private List<Class<?>> moduleClasses = null; // Classes in the module
private List<Class<?>> beanClasses = null; // Classes identified as Beans through Weld SPI
private List<URL> beansXmlURLs = null;
private final Collection<EjbDescriptor<?>> ejbDescImpls;
private final Set<BeanDeploymentArchive> beanDeploymentArchives;
private transient ReadableArchive archive;
private final String id;
private final List<String> moduleClassNames; // Names of classes in the module
private final List<String> beanClassNames; // Names of bean classes in the module
private transient List<Class<?>> moduleClasses; // Classes in the module
private transient List<Class<?>> beanClasses; // Classes identified as Beans through Weld SPI
private final List<URL> beansXmlURLs;
private transient Collection<EjbDescriptor<?>> ejbDescImpls;
private transient Set<BeanDeploymentArchive> beanDeploymentArchives;
private transient List<BeanDeploymentArchive> deserializedBDAs;

private SimpleServiceRegistry simpleServiceRegistry = null;
private transient SimpleServiceRegistry simpleServiceRegistry = null;
private int originalIdentity;

private BDAType bdaType = BDAType.UNKNOWN;

DeploymentContext context;
WeldBootstrap weldBootstrap;
transient DeploymentContext context;
transient WeldBootstrap weldBootstrap;

private final Map<AnnotatedType<?>, InjectionTarget<?>> itMap = new HashMap<>();
private transient Map<AnnotatedType<?>, InjectionTarget<?>> itMap = new HashMap<>();

//workaround: WELD-781
private ClassLoader moduleClassLoaderForBDA = null;
private transient ClassLoader moduleClassLoaderForBDA;

private String friendlyId = "";

Expand Down Expand Up @@ -192,59 +197,38 @@ public BeanDeploymentArchiveImpl(String
getClassLoader();
}

BeanDeploymentArchiveImpl(BeanDeploymentArchiveImpl self) {
this.id = self.id;
this.moduleClasses = new ArrayList<>(self.moduleClasses);
this.beanClasses = new ArrayList<>(self.beanClasses);
this.moduleClassNames = new ArrayList<>(self.moduleClassNames);
this.beanClassNames = new ArrayList<>(self.beanClassNames);
this.beansXmlURLs = new ArrayList<>(self.beansXmlURLs);
this.ejbDescImpls = new LinkedHashSet<>(self.ejbDescImpls);
this.beanDeploymentArchives = new LinkedHashSet<>();
this.context = self.context;
this.weldBootstrap = self.weldBootstrap;
this.moduleClassLoaderForBDA = self.moduleClassLoaderForBDA;
}

BeanDeploymentArchiveImpl deepCopy() {
return copySubBDAs(copyArchive());
}

BeanDeploymentArchiveImpl copyArchive() {
BeanDeploymentArchiveImpl copy = new BeanDeploymentArchiveImpl(this);
copy.ejbDescImpls.addAll(this.ejbDescImpls);
copy.simpleServiceRegistry = this.simpleServiceRegistry;
return copy;
}

private BeanDeploymentArchiveImpl copySubBDAs(BeanDeploymentArchiveImpl copy) {
copy.beanDeploymentArchives.addAll(deepCopy(new HashSet<>()));
return copy;
}

private Set<BeanDeploymentArchive> deepCopy(Set<BeanDeploymentArchive> seen) {
Set<BeanDeploymentArchive> copySet = new HashSet<>();
for (BeanDeploymentArchive bda : this.beanDeploymentArchives) {
BeanDeploymentArchiveImpl bdaImpl = (BeanDeploymentArchiveImpl) bda;
BeanDeploymentArchiveImpl copy = bdaImpl.copyArchive();
copySet.add(copy);
if (!seen.contains(bda)) {
seen.add(copy);
copy.beanDeploymentArchives.addAll(bdaImpl.deepCopy(seen));
} else {
for (var subBda : bdaImpl.beanDeploymentArchives) {
if (seen.contains(subBda)) {
seen.stream().filter(subBda::equals).findFirst().ifPresent(copy.beanDeploymentArchives::add);
} else {
BeanDeploymentArchiveImpl subBdaImpl = (BeanDeploymentArchiveImpl) subBda;
BeanDeploymentArchiveImpl subBdaCopy = subBdaImpl.copyArchive();
seen.add(subBdaCopy);
subBdaCopy.beanDeploymentArchives.addAll(subBdaImpl.deepCopy(seen));
}
}
public BeanDeploymentArchiveImpl(BeanDeploymentArchiveImpl beanDeploymentArchive) {
this.id = beanDeploymentArchive.id;
this.originalIdentity = beanDeploymentArchive.originalIdentity;
this.moduleClassNames = new ArrayList<>(beanDeploymentArchive.moduleClassNames);
this.beanClassNames = new ArrayList<>(beanDeploymentArchive.beanClassNames);
this.beansXmlURLs = new CopyOnWriteArrayList<>(beanDeploymentArchive.beansXmlURLs);
this.deserializedBDAs = beanDeploymentArchive.deserializedBDAs;
this.friendlyId = beanDeploymentArchive.friendlyId;
this.bdaType = beanDeploymentArchive.bdaType;
this.deploymentComplete = beanDeploymentArchive.deploymentComplete;

initializeFromOriginal();
}

void initializeFromOriginal() {
if (context == null) {
this.context = DeploymentImpl.currentDeploymentContext.get();
this.weldBootstrap = context.getTransientAppMetaData(WELD_BOOTSTRAP, WeldBootstrap.class);
this.moduleClasses = getOriginal().moduleClasses;
this.beanClasses = getOriginal().beanClasses;
this.simpleServiceRegistry = getOriginal().simpleServiceRegistry;
this.moduleClassLoaderForBDA = getOriginal().moduleClassLoaderForBDA;
this.ejbDescImpls = new LinkedHashSet<>(getOriginal().ejbDescImpls);
if (this.itMap == null) {
this.itMap = new HashMap<>();
}
this.itMap.putAll(getOriginal().itMap);
}
return copySet;
}

BeanDeploymentArchiveImpl getOriginal() {
return DeploymentImpl.currentBDAs.get().get(originalIdentity);
}

private void populateEJBsForThisBDA(Collection<com.sun.enterprise.deployment.EjbDescriptor> ejbs) {
Expand All @@ -260,11 +244,15 @@ private void populateEJBsForThisBDA(Collection<com.sun.enterprise.deployment.Ejb

@Override
public Collection<BeanDeploymentArchive> getBeanDeploymentArchives() {
if (beanDeploymentArchives == null && deserializedBDAs != null) {
beanDeploymentArchives = new LinkedHashSet<>(deserializedBDAs);
}
return beanDeploymentArchives;
}

@Override
public Collection<String> getBeanClasses() {
initializeFromOriginal();
//This method is called during BeanDeployment.deployBeans, so this would
//be the right time to place the module classloader for the BDA as the TCL
if (logger.isLoggable(FINER)) {
Expand All @@ -282,6 +270,7 @@ public Collection<String> getBeanClasses() {
}

public Collection<Class<?>> getBeanClassObjects() {
initializeFromOriginal();
return beanClasses;
}

Expand All @@ -290,6 +279,7 @@ public Collection<String> getModuleBeanClasses() {
}

public Collection<Class<?>> getModuleBeanClassObjects() {
initializeFromOriginal();
return moduleClasses;
}

Expand Down Expand Up @@ -339,11 +329,12 @@ public BeansXml getBeansXml() {
*/
@Override
public Collection<EjbDescriptor<?>> getEjbs() {

initializeFromOriginal();
return ejbDescImpls;
}

public EjbDescriptor getEjbDescriptor(String ejbName) {
initializeFromOriginal();
EjbDescriptor match = null;

for (EjbDescriptor next : ejbDescImpls) {
Expand All @@ -358,6 +349,7 @@ public EjbDescriptor getEjbDescriptor(String ejbName) {

@Override
public ServiceRegistry getServices() {
initializeFromOriginal();
if (simpleServiceRegistry == null) {
simpleServiceRegistry = new SimpleServiceRegistry();
}
Expand All @@ -380,10 +372,36 @@ public Collection<String> getKnownClasses() {

@Override
public Collection<Class<?>> getLoadedBeanClasses() {
initializeFromOriginal();
return beanClasses;
}

Object readResolve() throws ObjectStreamException {
return new BeanDeploymentArchiveImpl(this);
}

private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
originalIdentity = System.identityHashCode(this);
if (DeploymentImpl.currentBDAs.get().put(originalIdentity, this) != null) {
throw new IllegalStateException("Duplicate BDA detected: " + this);
}
out.writeInt(originalIdentity);
out.writeInt(beanDeploymentArchives.size());
for (BeanDeploymentArchive bda : beanDeploymentArchives) {
out.writeObject(bda);
}
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
originalIdentity = in.readInt();
int size = in.readInt();
deserializedBDAs = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
deserializedBDAs.add((BeanDeploymentArchive) in.readObject());
}
}

//A graphical representation of the BDA hierarchy to aid in debugging
//and to provide a better representation of how Weld treats the deployed
Expand Down Expand Up @@ -791,14 +809,17 @@ private ClassLoader getClassLoader() {
}

public InjectionTarget<?> getInjectionTarget(AnnotatedType<?> annotatedType) {
initializeFromOriginal();
return itMap.get(annotatedType);
}

void putInjectionTarget(AnnotatedType<?> annotatedType, InjectionTarget<?> it) {
initializeFromOriginal();
itMap.put(annotatedType, it);
}

public ClassLoader getModuleClassLoaderForBDA() {
initializeFromOriginal();
return moduleClassLoaderForBDA;
}

Expand Down
Loading

0 comments on commit 4a79348

Please sign in to comment.