use of org.apache.openejb.assembler.classic.ResourceInfo in project tomee by apache.
the class AutoConfig method autoCreateResource.
private String autoCreateResource(final String type, final Properties required, final String beanName) throws OpenEJBException {
final String resourceId;
resourceId = ServiceUtils.getServiceProviderId(type, required);
if (resourceId == null) {
throw new OpenEJBException("No provider available for resource-ref '" + resourceId + "' of type '" + type + "' for '" + beanName + "'.");
}
final ResourceInfo resourceInfo = configFactory.configureService(resourceId, ResourceInfo.class);
logAutoCreateResource(resourceInfo, type, beanName);
return installResource(beanName, resourceInfo);
}
use of org.apache.openejb.assembler.classic.ResourceInfo in project tomee by apache.
the class AutoConfig method deploy.
private void deploy(final AppModule app, final PersistenceModule persistenceModule) throws OpenEJBException {
if (!autoCreateResources) {
return;
}
final Persistence persistence = persistenceModule.getPersistence();
for (final PersistenceUnit unit : persistence.getPersistenceUnit()) {
if (unit.getProvider() != null) {
logger.info("Configuring PersistenceUnit(name=" + unit.getName() + ", provider=" + unit.getProvider() + ")");
} else {
logger.info("Configuring PersistenceUnit(name=" + unit.getName() + ")");
}
if (unit.getJtaDataSource() == null && unit.getNonJtaDataSource() == null && "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.force-unit-type", unit.getProperty("openejb.force-unit-type", "true")))) {
// 8.2.1.5 of JPA 2.0 spec
unit.setTransactionType(TransactionType.JTA);
}
// if jta datasource is specified it can be used as model fo rnon jta datasource
final boolean resourceLocal = TransactionType.RESOURCE_LOCAL.equals(unit.getTransactionType()) && unit.getJtaDataSource() == null;
if (resourceLocal && unit.getNonJtaDataSource() == null && isDataSourcePropertiesConfigured(unit.getProperties())) {
continue;
}
final Properties required = new Properties();
if ("org.apache.openjpa.persistence.PersistenceProviderImpl".equals(unit.getProvider())) {
if (unit.getJtaDataSource() == null) {
unit.setJtaDataSource(unit.getProperty("openjpa.ConnectionFactoryName"));
}
if (unit.getNonJtaDataSource() == null) {
unit.setNonJtaDataSource(unit.getProperty("openjpa.ConnectionFactory2Name"));
}
}
logger.debug("raw <jta-data-source>" + unit.getJtaDataSource() + "</jta-datasource>");
logger.debug("raw <non-jta-data-source>" + unit.getNonJtaDataSource() + "</non-jta-datasource>");
// keep it can start with java:global for instance
final String originalJtaDataSource = unit.getJtaDataSource();
unit.setJtaDataSource(normalizeResourceId(originalJtaDataSource));
final String originalNonJtaDataSource = unit.getNonJtaDataSource();
unit.setNonJtaDataSource(normalizeResourceId(originalNonJtaDataSource));
logger.debug("normalized <jta-data-source>" + unit.getJtaDataSource() + "</jta-datasource>");
logger.debug("normalized <non-jta-data-source>" + unit.getNonJtaDataSource() + "</non-jta-datasource>");
if (logger.isDebugEnabled()) {
required.put("JtaManaged", "true");
final List<String> managed = configFactory.getResourceIds("DataSource", required);
required.put("JtaManaged", "false");
final List<String> unmanaged = configFactory.getResourceIds("DataSource", required);
required.clear();
final List<String> unknown = configFactory.getResourceIds("DataSource", required);
logger.debug("Available DataSources");
for (final String name : managed) {
logger.debug("DataSource(name=" + name + ", JtaManaged=true)");
}
for (final String name : unmanaged) {
logger.debug("DataSource(name=" + name + ", JtaManaged=false)");
}
for (final String name : unknown) {
if (managed.contains(name)) {
continue;
}
if (unmanaged.contains(name)) {
continue;
}
logger.debug("DataSource(name=" + name + ", JtaManaged=<unknown>)");
}
}
final String prefix = app.getModuleId() + "/";
String jtaDataSourceId = null;
String nonJtaDataSourceId = null;
// first try exact matching without JtaManaged which is not mandatory actually (custom DS + JTADataSourceWrapperFactory)
final String jtaWithJavaAndSlash = replaceJavaAndSlash(unit.getJtaDataSource());
for (final String potentialName : asList(prefix + jtaWithJavaAndSlash, originalJtaDataSource, jtaWithJavaAndSlash)) {
if (potentialName == null) {
// If unit.getJtaDataSource() is null, one of the potentialName is also null.
continue;
}
final ResourceInfo jtaInfo = configFactory.getResourceInfo(potentialName);
if (jtaInfo != null) {
if (// don't test true since it can be missing
!"false".equalsIgnoreCase(jtaInfo.properties.getProperty("JtaManaged")) && (jtaInfo.types.contains("DataSource") || jtaInfo.types.contains(DataSource.class.getName()))) {
jtaDataSourceId = jtaInfo.id;
break;
} else {
logger.warning("Found matching datasource: " + jtaInfo.id + " but this one is not a JTA datasource");
}
}
}
final String nonJtaWithJavaAndSlash = replaceJavaAndSlash(unit.getNonJtaDataSource());
for (final String potentialName : asList(prefix + nonJtaWithJavaAndSlash, originalNonJtaDataSource, nonJtaWithJavaAndSlash)) {
if (potentialName == null) {
// If unit.getNonJtaDataSource() is null, one of the potentialName is also null.
continue;
}
final ResourceInfo info = configFactory.getResourceInfo(potentialName);
if (info != null) {
if (!"true".equalsIgnoreCase(info.properties.getProperty("JtaManaged")) && (info.types.contains("DataSource") || info.types.contains(DataSource.class.getName()))) {
nonJtaDataSourceId = info.id;
break;
} else {
logger.warning("Found matching datasource: " + info.id + " but this one is a JTA datasource");
}
}
}
// then that's ok to force configuration
if (jtaDataSourceId == null && !resourceLocal) {
required.put("JtaManaged", "true");
jtaDataSourceId = findResourceId(prefix + jtaWithJavaAndSlash, "DataSource", required, null);
if (jtaDataSourceId == null) {
// test with javax.sql.DataSource before DataSource since RA can register resources without our shortcut
jtaDataSourceId = findResourceId(jtaWithJavaAndSlash, "javax.sql.DataSource", required, null);
}
/* this shouldn't be mandatory anymore since our DataSource has as alias javax.sql.DataSource
if (jtaDataSourceId == null) {
jtaDataSourceId = findResourceId(replaceJavaAndSlash(unit.getJtaDataSource()), "DataSource", required, null);
}
*/
}
if (nonJtaDataSourceId == null) {
required.put("JtaManaged", "false");
nonJtaDataSourceId = findResourceId(prefix + nonJtaWithJavaAndSlash, "DataSource", required, null);
if (nonJtaDataSourceId == null) {
nonJtaDataSourceId = findResourceId(nonJtaWithJavaAndSlash, "DataSource", required, null);
}
}
if ((jtaDataSourceId != null || resourceLocal) && nonJtaDataSourceId != null) {
// Both DataSources were explicitly configured.
if (jtaDataSourceId != null) {
setJtaDataSource(unit, jtaDataSourceId);
}
setNonJtaDataSource(unit, nonJtaDataSourceId);
continue;
}
//
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
required.put("JtaManaged", ServiceUtils.NONE);
if (!resourceLocal) {
jtaDataSourceId = findResourceId(unit.getJtaDataSource(), "DataSource", required, null);
}
nonJtaDataSourceId = findResourceId(unit.getNonJtaDataSource(), "DataSource", required, null);
if (jtaDataSourceId != null || nonJtaDataSourceId != null) {
if (jtaDataSourceId != null) {
setJtaDataSource(unit, jtaDataSourceId);
}
if (nonJtaDataSourceId != null) {
setNonJtaDataSource(unit, nonJtaDataSourceId);
}
continue;
}
}
// We are done with the most optimal configuration.
//
// If both the jta-data-source and non-jta-data-source
// references were explicitly and correctly configured
// to existing datasource, we wouldn't get this far.
//
// At this point we see if either we can't figure out
// if there's an issue with their configuration or
// if we can't intelligently complete their configuration.
//
// Do both the jta-data-source and non-jta-data-source references
// point to the same datasource?
//
// If so, then unlink the invalid one so defaulting rules can
// possibly fill in a good value.
//
required.put("JtaManaged", ServiceUtils.ANY);
final String possibleJta = findResourceId(jtaWithJavaAndSlash, "DataSource", required, null);
final String possibleNonJta = findResourceId(nonJtaWithJavaAndSlash, "DataSource", required, null);
if (possibleJta != null && possibleJta.equals(possibleNonJta)) {
final ResourceInfo dataSource = configFactory.getResourceInfo(possibleJta);
final String jtaManaged = (String) dataSource.properties.get("JtaManaged");
logger.warning("PeristenceUnit(name=" + unit.getName() + ") invalidly refers to Resource(id=" + dataSource.id + ") as both its <jta-data-source> and <non-jta-data-source>.");
if ("true".equalsIgnoreCase(jtaManaged)) {
nonJtaDataSourceId = null;
unit.setNonJtaDataSource(null);
} else if ("false".equalsIgnoreCase(jtaManaged)) {
jtaDataSourceId = null;
unit.setJtaDataSource(null);
}
}
//
// Do the jta-data-source and non-jta-data-source references
// point to innapropriately configured Resources?
//
checkUnitDataSourceRefs(unit);
//
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
jtaDataSourceId = findResourceProviderId(unit.getJtaDataSource());
nonJtaDataSourceId = findResourceProviderId(unit.getNonJtaDataSource());
// we can just create the second resource using the first as a template
if (jtaDataSourceId != null || nonJtaDataSourceId != null) {
final Resource jtaResource = new Resource(jtaDataSourceId, "DataSource", jtaDataSourceId);
jtaResource.getProperties().setProperty("JtaManaged", "true");
final Resource nonJtaResource = new Resource(nonJtaDataSourceId, "DataSource", nonJtaDataSourceId);
nonJtaResource.getProperties().setProperty("JtaManaged", "false");
if (jtaDataSourceId == null) {
jtaResource.setId(nonJtaDataSourceId + "Jta");
jtaResource.setProvider(nonJtaDataSourceId);
} else if (nonJtaDataSourceId == null) {
nonJtaResource.setId(jtaDataSourceId + "NonJta");
nonJtaResource.setProvider(jtaDataSourceId);
}
final ResourceInfo jtaResourceInfo = configFactory.configureService(jtaResource, ResourceInfo.class);
final ResourceInfo nonJtaResourceInfo = configFactory.configureService(nonJtaResource, ResourceInfo.class);
if (jtaDataSourceId != null && nonJtaDataSourceId == null) {
nonJtaResourceInfo.originAppName = jtaResourceInfo.originAppName;
}
logAutoCreateResource(jtaResourceInfo, "DataSource", unit.getName());
jtaDataSourceId = installResource(unit.getName(), jtaResourceInfo);
logAutoCreateResource(nonJtaResourceInfo, "DataSource", unit.getName());
nonJtaDataSourceId = installResource(unit.getName(), nonJtaResourceInfo);
setJtaDataSource(unit, jtaDataSourceId);
setNonJtaDataSource(unit, nonJtaDataSourceId);
continue;
}
}
// Look for defaults, see https://issues.apache.org/jira/browse/OPENEJB-1027
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
// We check for data sources matching the following names:
// 1. The persistence unit id
// 2. The web module id
// 3. The web module context root
// 4. The application module id
final List<String> ids = new ArrayList<String>();
ids.add(unit.getName());
for (final WebModule webModule : app.getWebModules()) {
ids.add(webModule.getModuleId());
ids.add(webModule.getContextRoot());
}
ids.add(app.getModuleId());
// Search for a matching data source
for (final String id : ids) {
// Try finding a jta managed data source
required.put("JtaManaged", "true");
jtaDataSourceId = findResourceId(id, "DataSource", required, null);
if (jtaDataSourceId == null) {
// No jta managed data source found. Try finding a non-jta managed
required.clear();
required.put("JtaManaged", "false");
nonJtaDataSourceId = findResourceId(id, "DataSource", required, null);
}
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
// Neither jta nor non-jta managed data sources were found. try to find one with it unset
required.clear();
required.put("JtaManaged", ServiceUtils.NONE);
jtaDataSourceId = findResourceId(id, "DataSource", required, null);
}
if (jtaDataSourceId != null || nonJtaDataSourceId != null) {
// We have found a default. Exit the loop
break;
}
}
}
//
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
required.clear();
required.put("JtaManaged", "true");
jtaDataSourceId = firstMatching(prefix, "DataSource", required, null);
if (jtaDataSourceId == null) {
required.clear();
required.put("JtaManaged", "false");
nonJtaDataSourceId = firstMatching(prefix, "DataSource", required, null);
}
}
if (jtaDataSourceId != null && nonJtaDataSourceId == null) {
final ResourceInfo jtaResourceInfo = configFactory.getResourceInfo(jtaDataSourceId);
final Properties jtaProperties = jtaResourceInfo.properties;
if (jtaProperties.containsKey("JtaManaged")) {
// Strategy 1: Best match search
required.clear();
required.put("JtaManaged", "false");
for (final String key : asList("JdbcDriver", "JdbcUrl")) {
if (jtaProperties.containsKey(key)) {
required.put(key, jtaProperties.get(key));
}
}
nonJtaDataSourceId = firstMatching(prefix, "DataSource", required, null);
if (nonJtaDataSourceId == null) {
final ResourceInfo nonJtaResourceInfo = copy(jtaResourceInfo);
nonJtaResourceInfo.id = jtaResourceInfo.id + "NonJta";
nonJtaResourceInfo.originAppName = jtaResourceInfo.originAppName;
suffixAliases(nonJtaResourceInfo, "NonJta");
configureImplicitDataSource(nonJtaResourceInfo);
final Properties overrides = ConfigurationFactory.getSystemProperties(nonJtaResourceInfo.id, nonJtaResourceInfo.service);
nonJtaResourceInfo.properties.putAll(overrides);
nonJtaResourceInfo.properties.setProperty("JtaManaged", "false");
// if created from annotation we just want live config
nonJtaResourceInfo.properties.remove("Definition");
logAutoCreateResource(nonJtaResourceInfo, "DataSource", unit.getName());
logger.info("configureService.configuring", nonJtaResourceInfo.id, nonJtaResourceInfo.service, jtaResourceInfo.id);
nonJtaDataSourceId = installResource(unit.getName(), nonJtaResourceInfo);
}
}
}
//
// Does the jta-data-source reference point an existing
// Resource in the system with JtaManaged=false?
//
// If so, we can search for an existing datasource
// configured with identical properties and use it.
//
// If that doesn't work, we can copy the jta-data-source
// and auto-create the missing non-jta-data-source
// using it as a template, applying the overrides,
// and finally setting JtaManaged=false
//
final String deduceJtaFromNonJta = unit.getProperty(AUTOCREATE_JTA_DATASOURCE_FROM_NON_JTA_ONE_KEY, SystemInstance.get().getOptions().get(AUTOCREATE_JTA_DATASOURCE_FROM_NON_JTA_ONE_KEY, (String) null));
if (nonJtaDataSourceId != null && jtaDataSourceId == null && // hibernate uses the fact that this ds is missing to get a non jta em instead of a JTA one
(!resourceLocal || deduceJtaFromNonJta != null) && (deduceJtaFromNonJta == null || deduceJtaFromNonJta != null && Boolean.parseBoolean(deduceJtaFromNonJta))) {
final ResourceInfo nonJtaResourceInfo = configFactory.getResourceInfo(nonJtaDataSourceId);
final Properties nonJtaProperties = nonJtaResourceInfo.properties;
if (nonJtaProperties.containsKey("JtaManaged")) {
// Strategy 1: Best match search
required.clear();
required.put("JtaManaged", "true");
for (final String key : asList("JdbcDriver", "JdbcUrl")) {
if (nonJtaProperties.containsKey(key)) {
required.put(key, nonJtaProperties.get(key));
}
}
jtaDataSourceId = firstMatching(prefix, "DataSource", required, null);
if (jtaDataSourceId == null) {
final ResourceInfo jtaResourceInfo = copy(nonJtaResourceInfo);
jtaResourceInfo.id = nonJtaResourceInfo.id + "Jta";
suffixAliases(jtaResourceInfo, "Jta");
configureImplicitDataSource(jtaResourceInfo);
final Properties overrides = ConfigurationFactory.getSystemProperties(jtaResourceInfo.id, jtaResourceInfo.service);
jtaResourceInfo.properties.putAll(overrides);
jtaResourceInfo.properties.setProperty("JtaManaged", "true");
// if created from annotation we just want live config
jtaResourceInfo.properties.remove("Definition");
logAutoCreateResource(jtaResourceInfo, "DataSource", unit.getName());
logger.info("configureService.configuring", jtaResourceInfo.id, jtaResourceInfo.service, nonJtaResourceInfo.id);
jtaDataSourceId = installResource(unit.getName(), jtaResourceInfo);
}
}
}
//
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
if (!resourceLocal) {
required.put("JtaManaged", "true");
jtaDataSourceId = autoCreateResource("DataSource", required, unit.getName());
}
required.put("JtaManaged", "false");
nonJtaDataSourceId = autoCreateResource("DataSource", required, unit.getName());
}
if (jtaDataSourceId != null) {
setJtaDataSource(unit, jtaDataSourceId);
}
if (nonJtaDataSourceId != null) {
setNonJtaDataSource(unit, nonJtaDataSourceId);
}
}
}
use of org.apache.openejb.assembler.classic.ResourceInfo in project tomee by apache.
the class AutoConfig method getResourceEnvId.
private String getResourceEnvId(final String beanName, String resourceId, final String type, AppResources appResources) throws OpenEJBException {
if (resourceId == null) {
return null;
}
if (appResources == null) {
appResources = EMPTY_APP_RESOURCES;
}
// skip references such as URLs which are automatically handled by the server
if (ignoredReferenceTypes.contains(type)) {
return null;
}
resourceId = normalizeResourceId(resourceId);
// check for existing resource with specified resourceId
final List<String> resourceEnvIds = getResourceIds(appResources, type, null);
for (final String id : resourceEnvIds) {
if (id.equalsIgnoreCase(resourceId)) {
return id;
}
}
// throw an exception or log an error
final String message = "No existing resource found while attempting to Auto-link unmapped resource-env-ref '" + resourceId + "' of type '" + type + "' for '" + beanName + "'. Looked for Resource(id=" + resourceId + ")";
if (!autoCreateResources) {
throw new OpenEJBException(message);
}
logger.debug(message);
// Auto create a resource using the first provider that can supply a resource of the desired type
final String providerId = ServiceUtils.getServiceProviderId(type);
if (providerId == null) {
// if there are any existing resources of the desired type, use the first one
if (resourceEnvIds.size() > 0) {
return resourceEnvIds.get(0);
}
throw new OpenEJBException("No provider available for resource-env-ref '" + resourceId + "' of type '" + type + "' for '" + beanName + "'.");
}
final Resource resource = new Resource(resourceId, null, providerId);
resource.getProperties().setProperty("destination", resourceId);
final ResourceInfo resourceInfo = configFactory.configureService(resource, ResourceInfo.class);
logAutoCreateResource(resourceInfo, type, beanName);
return installResource(beanName, resourceInfo);
}
use of org.apache.openejb.assembler.classic.ResourceInfo in project tomee by apache.
the class AutoConfig method processApplicationResources.
private void processApplicationResources(final AppModule module) throws OpenEJBException {
final Collection<Resource> resources = module.getResources();
if (resources.size() == 0) {
return;
}
final List<JndiConsumer> jndiConsumers = new ArrayList<JndiConsumer>();
for (final WebModule webModule : module.getWebModules()) {
final JndiConsumer consumer = webModule.getWebApp();
jndiConsumers.add(consumer);
}
for (final EjbModule ejbModule : module.getEjbModules()) {
Collections.addAll(jndiConsumers, ejbModule.getEjbJar().getEnterpriseBeans());
}
List<ResourceInfo> resourceInfos = new ArrayList<ResourceInfo>();
final Map<ResourceInfo, Resource> resourcesMap = new HashMap<ResourceInfo, Resource>(resources.size());
for (final Resource resource : resources) {
final String originalId = PropertyPlaceHolderHelper.value(resource.getId());
final String modulePrefix = module.getModuleId() + "/";
if ("/".equals(modulePrefix) || originalId.startsWith("global") || originalId.startsWith("/global")) {
resource.setId(replaceJavaAndSlash(originalId));
} else {
resource.getProperties().setProperty(ORIGINAL_ID, originalId);
resource.setId(modulePrefix + replaceJavaAndSlash(originalId));
}
resource.setJndi(PropertyPlaceHolderHelper.value(resource.getJndi()));
final Thread thread = Thread.currentThread();
final ClassLoader oldCl = thread.getContextClassLoader();
thread.setContextClassLoader(module.getClassLoader());
try {
resource.getProperties().putAll(PropertyPlaceHolderHelper.holds(resource.getProperties()));
} finally {
thread.setContextClassLoader(oldCl);
}
final Collection<String> aliases = resource.getAliases();
if (!aliases.isEmpty()) {
final Collection<String> newAliases = new ArrayList<String>();
for (final String s : aliases) {
newAliases.add(module.getModuleId() + "/" + s);
}
resource.getAliases().clear();
resource.getAliases().addAll(newAliases);
}
final Properties properties = resource.getProperties();
if (DataSource.class.getName().equals(resource.getType()) || DataSource.class.getSimpleName().equals(resource.getType())) {
DataSourceFactory.trimNotSupportedDataSourceProperties(properties);
}
final boolean shouldGenerateJdbcUrl = DataSource.class.getName().equals(resource.getType()) && resource.getProperties().containsKey(ORIGIN_FLAG) && resource.getProperties().getProperty(ORIGIN_FLAG).equals(ORIGIN_ANNOTATION);
if (shouldGenerateJdbcUrl && properties.get("JdbcUrl") == null) {
final String url = getVendorUrl(properties);
if (url != null) {
properties.put("JdbcUrl", url);
}
}
final ResourceInfo resourceInfo = configFactory.configureService(resource, ResourceInfo.class);
resourceInfo.originAppName = module.getModuleId();
final ResourceRef resourceRef = new ResourceRef();
resourceRef.setResType(chooseType(module.getClassLoader(), resourceInfo, resource.getType()));
if (shouldGenerateJdbcUrl) {
properties.remove(ORIGIN_FLAG);
resourceRef.setResRefName(dataSourceLookupName(resource));
} else {
resourceRef.setResRefName(OPENEJB_RESOURCE_JNDI_PREFIX + resourceInfo.id);
}
resourceRef.setMappedName(resourceInfo.id);
final ResourceRef strictRef = new ResourceRef(OPENEJB_RESOURCE_JNDI_PREFIX + originalId, resourceRef.getResType(), resourceRef.getResAuth(), resourceRef.getResSharingScope());
strictRef.setMappedName(resourceInfo.id);
for (final JndiConsumer consumer : jndiConsumers) {
// for injections etc...
addResource(consumer, resourceRef);
if (!"/".equals(modulePrefix)) {
// for lookups (without prefix)
addResource(consumer, strictRef);
}
}
resourceInfos.add(resourceInfo);
resourcesMap.put(resourceInfo, resource);
}
resourceInfos = ConfigurationFactory.sort(resourceInfos, module.getModuleId() + "/");
for (final ResourceInfo resourceInfo : resourceInfos) {
final int originalSize = resourceInfo.aliases.size();
final String id = installResource(module.getModuleId(), resourceInfo);
final Resource resource = resourcesMap.remove(resourceInfo);
resource.setId(id);
if (resourceInfo.aliases.size() > originalSize) {
// an aliases is generally added to be able to bind in global jndi tree
resource.getAliases().add(resourceInfo.aliases.get(resourceInfo.aliases.size() - 1));
}
}
resourceInfos.clear();
// resources.clear(); // don't clear it since we want to keep this to be able to undeploy resources with the app
}
use of org.apache.openejb.assembler.classic.ResourceInfo in project tomee by apache.
the class AutoConfig method copy.
private ResourceInfo copy(final ResourceInfo a) {
final ResourceInfo b = new ResourceInfo();
b.id = a.id;
b.service = a.service;
b.className = a.className;
b.codebase = a.codebase;
b.displayName = a.displayName;
b.description = a.description;
b.factoryMethod = a.factoryMethod;
b.constructorArgs.addAll(a.constructorArgs);
b.originAppName = a.originAppName;
b.types.addAll(a.types);
b.properties = new SuperProperties();
b.properties.putAll(a.properties);
if (a.classpath != null) {
b.classpath = new URI[a.classpath.length];
System.arraycopy(a.classpath, 0, b.classpath, 0, a.classpath.length);
}
return b;
}
Aggregations