/* * Copyright (c) 2014 Red Hat, Inc. 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 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cheng Fang - Initial API and implementation */ package org.jberet.job.model; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.List; import javax.batch.operations.JobStartException; import org.jberet.creation.ArchiveXmlLoader; import org.jberet.spi.BatchEnvironment; import org.jberet.spi.JobXmlResolver; import org.jberet.util.BatchUtil; import org.wildfly.security.manager.WildFlySecurityManager; /** * Responsible for merging a child flow and its parent job, and resolving its JSL inheritance. * * @see AbstractMerger * @see JobMerger * @see StepMerger * * @since 1.0.1 */ public final class FlowMerger extends AbstractMerger<Flow> { /** * Constructs a flow merger. * * @param job the current job * @param child the flow to resolve its JSL inheritance * @param classLoader the class loader to use for loading jobs and resources * @param loadedJobs list of already loaded jobs to avoid reloading them while resolving inheritance * @param jobXmlResolver job xml resolver, typically obtained from {@code org.jberet.spi.BatchEnvironment#getJobXmlResolver()} * * @throws JobStartException if failed to construct the flow merger * * @see BatchEnvironment#getJobXmlResolver() */ FlowMerger(final Job job, final Flow child, final ClassLoader classLoader, final List<Job> loadedJobs, final JobXmlResolver jobXmlResolver) throws JobStartException { super(job, classLoader, loadedJobs, jobXmlResolver); this.child = child; final String parentName = child.getParent(); final String jslName = child.getJslName(); if (jslName == null || jslName.equals("*") || jslName.equals(job.id)) { for (final JobElement e : job.getJobElements()) { if (parentName.equals(e.getId())) { this.parent = (Flow) e; break; } } } else { // jslName points to a different jsl document final Job jobOfParentFlow = ArchiveXmlLoader.loadJobXml(jslName, classLoader, loadedJobs, jobXmlResolver); for (final JobElement e : jobOfParentFlow.getJobElements()) { if (parentName.equals(e.getId())) { this.parent = (Flow) e; } } } } /** * Performs the merge, and if the parent flow has its own parent, it is also resolved. * This method does not process JSL inheritance in the flow's sub-element, which is done in * {@link JobMerger#resolveInheritance(Job, ClassLoader, List, JobXmlResolver)} * * @throws JobStartException if failed due to cyclic inheritance or other errors */ public void merge() throws JobStartException { checkInheritingElements(this.parent, this.parent.getId()); //check if parent has its own parent, which may be in the same or different job xml document if (parent.getParent() != null) { final FlowMerger merger2 = new FlowMerger(currentJob, parent, classLoader, loadedJobs, jobXmlResolver); recordInheritingElements(merger2); merger2.merge(); } if (child.getAttributeNext() == null) { child.next= parent.next; } child.jobElements.clear(); if (WildFlySecurityManager.isChecking()) { child.jobElements = AccessController.doPrivileged(new PrivilegedAction<List<JobElement>>() { @Override public List<JobElement> run() { return BatchUtil.clone(parent.jobElements); } }); } else { child.jobElements = BatchUtil.clone(parent.jobElements); } child.setParentAndJslName(null, null); } }