Initial Contribution
Signed-off-by: Vinay Vishal <vinay.vishal@oracle.com>
diff --git a/appserver/resources/resources-runtime/osgi.bundle b/appserver/resources/resources-runtime/osgi.bundle
new file mode 100644
index 0000000..79376aa
--- /dev/null
+++ b/appserver/resources/resources-runtime/osgi.bundle
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2011, 2018 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.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+-exportcontents: \
+ org.glassfish.resources.deployer; \
+ org.glassfish.resources.beans; \
+ org.glassfish.resources.module; version=${project.osgi.version}
diff --git a/appserver/resources/resources-runtime/pom.xml b/appserver/resources/resources-runtime/pom.xml
new file mode 100755
index 0000000..34607f0
--- /dev/null
+++ b/appserver/resources/resources-runtime/pom.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2011, 2018 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.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.glassfish.main.resources</groupId>
+ <artifactId>resources</artifactId>
+ <version>5.0.1-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>resources-runtime</artifactId>
+ <packaging>glassfish-jar</packaging>
+
+ <name>GlassFish resources runtime</name>
+
+ <developers>
+ <developer>
+ <id>jr158900</id>
+ <name>Jagadish Ramu</name>
+ <url>http://blogs.sun.com/JagadishPrasath</url>
+ <organization>Oracle, Inc.</organization>
+ <roles>
+ <role>developer</role>
+ </roles>
+ </developer>
+ </developers>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.properties</include>
+ <include>**/*.xml</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.hk2</groupId>
+ <artifactId>hk2-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.main.deployment</groupId>
+ <artifactId>dol</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.main.admin</groupId>
+ <artifactId>config-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.main.resources</groupId>
+ <artifactId>resources-connector</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>glassfish-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.main.deployment</groupId>
+ <artifactId>deployment-javaee-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
+
diff --git a/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/beans/CustomResource.java b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/beans/CustomResource.java
new file mode 100755
index 0000000..4db75a4
--- /dev/null
+++ b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/beans/CustomResource.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1997, 2018 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.resources.beans;
+
+import org.glassfish.resources.api.JavaEEResource;
+import org.glassfish.resources.api.JavaEEResourceBase;
+import org.glassfish.resourcebase.resources.api.ResourceInfo;
+
+/**
+ * Resource info for CustomResourcel.
+ * IASRI #4626188
+ *
+ * @author Sridatta Viswanath
+ */
+public class CustomResource extends JavaEEResourceBase {
+
+ private String resType_;
+ private String factoryClass_;
+
+ public CustomResource(ResourceInfo resourceInfo) {
+ super(resourceInfo);
+ }
+
+ protected JavaEEResource doClone(ResourceInfo resourceInfo) {
+ CustomResource clone = new CustomResource(resourceInfo);
+ clone.setResType(getResType());
+ clone.setFactoryClass(getFactoryClass());
+ return clone;
+ }
+
+ public int getType() {
+ return JavaEEResource.CUSTOM_RESOURCE;
+ }
+
+ public String getResType() {
+ return resType_;
+ }
+
+ public void setResType(String resType) {
+ resType_ = resType;
+ }
+
+ public String getFactoryClass() {
+ return factoryClass_;
+ }
+
+ public void setFactoryClass(String factoryClass) {
+ factoryClass_ = factoryClass;
+ }
+
+ public String toString() {
+ return "< Custom Resource : " + getResourceInfo() + " , " + getResType() + "... >";
+ }
+}
diff --git a/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/beans/ExternalJndiResource.java b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/beans/ExternalJndiResource.java
new file mode 100755
index 0000000..71a767d
--- /dev/null
+++ b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/beans/ExternalJndiResource.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997, 2018 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.resources.beans;
+
+import org.glassfish.resources.api.JavaEEResource;
+import org.glassfish.resources.api.JavaEEResourceBase;
+import org.glassfish.resourcebase.resources.api.ResourceConstants;
+import org.glassfish.resourcebase.resources.api.ResourceInfo;
+
+/**
+ * Resource info for ExternalJndiResource.
+ * IASRI #4626188
+ * <p><b>NOT THREAD SAFE: mutable instance variables</b>
+ *
+ * @author Sridatta Viswanath
+ */
+public class ExternalJndiResource extends JavaEEResourceBase {
+
+ private String jndiLookupName_;
+ private String resType_;
+ private String factoryClass_;
+
+ public ExternalJndiResource(ResourceInfo resourceInfo) {
+ super(resourceInfo);
+ }
+
+ protected JavaEEResource doClone(ResourceInfo resourceInfo) {
+ ExternalJndiResource clone = new ExternalJndiResource(resourceInfo);
+ clone.setJndiLookupName(getJndiLookupName());
+ clone.setResType(getResType());
+ clone.setFactoryClass(getFactoryClass());
+ return clone;
+ }
+
+ public int getType() {
+ return JavaEEResource.EXTERNAL_JNDI_RESOURCE;
+ }
+
+ public String getJndiLookupName() {
+ return jndiLookupName_;
+ }
+
+ public void setJndiLookupName(String jndiLookupName) {
+ jndiLookupName_ = jndiLookupName;
+ }
+
+ public String getResType() {
+ return resType_;
+ }
+
+ public void setResType(String resType) {
+ resType_ = resType;
+ }
+
+ public String getFactoryClass() {
+ return factoryClass_;
+ }
+
+ public void setFactoryClass(String factoryClass) {
+ factoryClass_ = factoryClass;
+ }
+
+ //START OF IASRI 4660565
+ public boolean isJMSConnectionFactory() {
+ if (resType_ == null) return false;
+
+ return (ResourceConstants.JMS_QUEUE_CONNECTION_FACTORY.equals(resType_) ||
+ ResourceConstants.JMS_TOPIC_CONNECTION_FACTORY.equals(resType_));
+ }
+ //END OF IASRI 4660565
+
+ public String toString() {
+ return "< External Jndi Resource : " + getResourceInfo() + " , " + getJndiLookupName() + "... >";
+ }
+}
diff --git a/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/deployer/CustomResourceDeployer.java b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/deployer/CustomResourceDeployer.java
new file mode 100644
index 0000000..2be88eb
--- /dev/null
+++ b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/deployer/CustomResourceDeployer.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 1997, 2018 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.resources.deployer;
+
+import com.sun.enterprise.config.serverbeans.Application;
+import com.sun.enterprise.config.serverbeans.Resource;
+import com.sun.enterprise.config.serverbeans.Resources;
+import com.sun.enterprise.repository.ResourceProperty;
+import com.sun.enterprise.util.i18n.StringManager;
+import com.sun.logging.LogDomains;
+import org.glassfish.resources.api.*;
+import org.glassfish.resources.config.CustomResource;
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.config.types.Property;
+import org.glassfish.resourcebase.resources.api.ResourceInfo;
+import org.glassfish.resourcebase.resources.api.ResourceDeployer;
+import org.glassfish.resourcebase.resources.api.ResourceConflictException;
+import org.glassfish.resourcebase.resources.api.ResourceDeployerInfo;
+import org.glassfish.resourcebase.resources.util.ResourceUtil;
+import org.glassfish.resourcebase.resources.util.BindableResourcesHelper;
+import org.glassfish.resourcebase.resources.naming.ResourceNamingService;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Handles custom resource events in the server instance.
+ * <p/>
+ * The custom resource events from the admin instance are propagated
+ * to this object.
+ * <p/>
+ * The methods can potentially be called concurrently, therefore implementation
+ * need to be synchronized.
+ * <p/>
+ * <p/>
+ * Note: Since a notification is not sent to the user of the custom
+ * resources upon undeploy, it is possible that there would be
+ * stale objects not being garbage collected. Future versions
+ * should take care of this problem.
+ *
+ * @author Nazrul Islam
+ * @since JDK1.4
+ */
+@Service
+@ResourceDeployerInfo(CustomResource.class)
+@Singleton
+public class CustomResourceDeployer implements ResourceDeployer {
+
+
+ @Inject
+ private BindableResourcesHelper bindableResourcesHelper;
+
+ /**
+ * Stringmanager for this deployer
+ */
+ private static final StringManager localStrings =
+ StringManager.getManager(CustomResourceDeployer.class);
+
+ @Inject
+ private ResourceNamingService cns;
+ /**
+ * logger for this deployer
+ */
+ private static Logger _logger = LogDomains.getLogger(CustomResourceDeployer.class, LogDomains.RSR_LOGGER);
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void deployResource(Object resource, String applicationName, String moduleName)
+ throws Exception {
+ CustomResource customResource =
+ (CustomResource) resource;
+ ResourceInfo resourceInfo = new ResourceInfo(customResource.getJndiName(), applicationName, moduleName);
+ deployResource(resource, resourceInfo);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void deployResource(Object resource) throws Exception {
+ CustomResource customResource =
+ (CustomResource) resource;
+ ResourceInfo resourceInfo = ResourceUtil.getResourceInfo(customResource);
+ deployResource(customResource, resourceInfo);
+ }
+
+ private void deployResource(Object resource, ResourceInfo resourceInfo) {
+
+ CustomResource customRes =
+ (CustomResource) resource;
+
+ // converts the config data to j2ee resource
+ JavaEEResource j2eeResource = toCustomJavaEEResource(customRes, resourceInfo);
+
+ // installs the resource
+ installCustomResource((org.glassfish.resources.beans.CustomResource) j2eeResource, resourceInfo);
+
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void undeployResource(Object resource, String applicationName, String moduleName) throws Exception {
+ CustomResource customResource =
+ (CustomResource) resource;
+ ResourceInfo resourceInfo = new ResourceInfo(customResource.getJndiName(), applicationName, moduleName);
+ deleteResource(customResource, resourceInfo);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void undeployResource(Object resource)
+ throws Exception {
+
+ CustomResource customResource =
+ (CustomResource) resource;
+ ResourceInfo resourceInfo = ResourceUtil.getResourceInfo(customResource);
+ deleteResource(customResource, resourceInfo);
+ }
+
+ private void deleteResource(CustomResource customResource,
+ ResourceInfo resourceInfo) throws NamingException {
+ // converts the config data to j2ee resource
+ //JavaEEResource j2eeResource = toCustomJavaEEResource(customRes, resourceInfo);
+ // removes the resource from jndi naming
+ cns.unpublishObject(resourceInfo, resourceInfo.getName());
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean handles(Object resource) {
+ return resource instanceof CustomResource;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public boolean supportsDynamicReconfiguration() {
+ return false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public Class[] getProxyClassesForDynamicReconfiguration() {
+ return new Class[0];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void redeployResource(Object resource)
+ throws Exception {
+
+ undeployResource(resource);
+ deployResource(resource);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void enableResource(Object resource) throws Exception {
+ deployResource(resource);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void disableResource(Object resource) throws Exception {
+ undeployResource(resource);
+ }
+
+ /**
+ * Installs the given custom resource. It publishes the resource as a
+ * javax.naming.Reference with the naming manager (jndi). This method gets
+ * called during server initialization and custom resource deployer to
+ * handle custom resource events.
+ *
+ * @param customRes custom resource
+ */
+ public void installCustomResource(org.glassfish.resources.beans.CustomResource customRes, ResourceInfo resourceInfo) {
+
+ try {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "installCustomResource by jndi-name : " + resourceInfo);
+ }
+
+ // bind a Reference to the object factory
+ Reference ref = new Reference(customRes.getResType(), customRes.getFactoryClass(), null);
+
+ // add resource properties as StringRefAddrs
+ for (Iterator props = customRes.getProperties().iterator();
+ props.hasNext(); ) {
+
+ ResourceProperty prop = (ResourceProperty) props.next();
+
+ ref.add(new StringRefAddr(prop.getName(),
+ (String) prop.getValue()));
+ }
+
+ // publish the reference
+ cns.publishObject(resourceInfo, ref, true);
+ } catch (Exception ex) {
+ _logger.log(Level.SEVERE, "customrsrc.create_ref_error", resourceInfo);
+ _logger.log(Level.SEVERE, "customrsrc.create_ref_error_excp", ex);
+ }
+ }
+
+ /**
+ * Returns a new instance of j2ee custom resource from the given
+ * config bean.
+ * <p/>
+ * This method gets called from the custom resource deployer
+ * to convert custom-resource config bean into custom j2ee resource.
+ *
+ * @param rbean custom-resource config bean
+ * @return new instance of j2ee custom resource
+ */
+ public static JavaEEResource toCustomJavaEEResource(
+ CustomResource rbean, ResourceInfo resourceInfo) {
+
+
+ org.glassfish.resources.beans.CustomResource jr =
+ new org.glassfish.resources.beans.CustomResource(resourceInfo);
+
+ //jr.setDescription(rbean.getDescription()); // FIXME: getting error
+
+ // sets the enable flag
+ jr.setEnabled(Boolean.valueOf(rbean.getEnabled()));
+
+ // sets the resource type
+ jr.setResType(rbean.getResType());
+
+ // sets the factory class name
+ jr.setFactoryClass(rbean.getFactoryClass());
+
+ // sets the properties
+ List<Property> properties = rbean.getProperty();
+ if (properties != null) {
+ for (Property property : properties) {
+ ResourceProperty rp =
+ new ResourcePropertyImpl(property.getName(), property.getValue());
+ jr.addProperty(rp);
+ }
+ }
+ return jr;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean canDeploy(boolean postApplicationDeployment, Collection<Resource> allResources, Resource resource) {
+ if (handles(resource)) {
+ if (!postApplicationDeployment) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validatePreservedResource(Application oldApp, Application newApp, Resource resource,
+ Resources allResources)
+ throws ResourceConflictException {
+ //do nothing.
+ }
+}
diff --git a/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/deployer/ExternalJndiResourceDeployer.java b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/deployer/ExternalJndiResourceDeployer.java
new file mode 100644
index 0000000..6d584ef
--- /dev/null
+++ b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/deployer/ExternalJndiResourceDeployer.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 1997, 2018 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.resources.deployer;
+
+import com.sun.enterprise.config.serverbeans.Application;
+import com.sun.enterprise.config.serverbeans.Resource;
+import com.sun.enterprise.config.serverbeans.Resources;
+import com.sun.enterprise.repository.ResourceProperty;
+import com.sun.enterprise.util.i18n.StringManager;
+import com.sun.logging.LogDomains;
+import org.glassfish.resources.api.*;
+import org.glassfish.resources.config.ExternalJndiResource;
+import org.glassfish.resources.naming.JndiProxyObjectFactory;
+import org.glassfish.resources.naming.ProxyRefAddr;
+import org.glassfish.resourcebase.resources.naming.ResourceNamingService;
+import org.glassfish.resources.naming.SerializableObjectRefAddr;
+import org.glassfish.resourcebase.resources.util.BindableResourcesHelper;
+import org.glassfish.resourcebase.resources.util.ResourceUtil;
+import org.glassfish.resourcebase.resources.api.ResourceInfo;
+import org.glassfish.resourcebase.resources.api.ResourceDeployer;
+import org.glassfish.resourcebase.resources.api.ResourceDeployerInfo;
+import org.glassfish.resourcebase.resources.api.ResourceConflictException;
+import org.jvnet.hk2.annotations.Service;
+import javax.inject.Singleton;
+import org.jvnet.hk2.config.types.Property;
+
+import javax.inject.Inject;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import javax.naming.spi.InitialContextFactory;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Handles external-jndi resource events in the server instance.
+ * <p/>
+ * The external-jndi resource events from the admin instance are propagated
+ * to this object.
+ * <p/>
+ * The methods can potentially be called concurrently, therefore implementation
+ * need to be synchronized.
+ *
+ * @author Nazrul Islam
+ * @since JDK1.4
+ */
+@Service
+@ResourceDeployerInfo(ExternalJndiResource.class)
+@Singleton
+public class ExternalJndiResourceDeployer implements ResourceDeployer {
+
+ @Inject
+ private ResourceNamingService namingService;
+
+ @Inject
+ private BindableResourcesHelper bindableResourcesHelper;
+
+
+ /**
+ * StringManager for this deployer
+ */
+ private static final StringManager localStrings =
+ StringManager.getManager(ExternalJndiResourceDeployer.class);
+ /**
+ * logger for this deployer
+ */
+ private static Logger _logger = LogDomains.getLogger(ExternalJndiResourceDeployer.class, LogDomains.RSR_LOGGER);
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void deployResource(Object resource, String applicationName, String moduleName) throws Exception {
+ ExternalJndiResource jndiRes =
+ (ExternalJndiResource) resource;
+ ResourceInfo resourceInfo = new ResourceInfo(jndiRes.getJndiName(), applicationName, moduleName);
+ createExternalJndiResource(jndiRes, resourceInfo);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void deployResource(Object resource) throws Exception {
+
+ ExternalJndiResource jndiRes =
+ (ExternalJndiResource) resource;
+ ResourceInfo resourceInfo = ResourceUtil.getResourceInfo(jndiRes);
+ createExternalJndiResource(jndiRes, resourceInfo);
+ }
+
+ private void createExternalJndiResource(ExternalJndiResource jndiRes,
+ ResourceInfo resourceInfo) {
+ // converts the config data to j2ee resource
+ JavaEEResource j2eeRes = toExternalJndiJavaEEResource(jndiRes, resourceInfo);
+
+ // installs the resource
+ installExternalJndiResource((org.glassfish.resources.beans.ExternalJndiResource) j2eeRes, resourceInfo);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void undeployResource(Object resource, String applicationName, String moduleName) throws Exception {
+ ExternalJndiResource jndiRes =
+ (ExternalJndiResource) resource;
+ ResourceInfo resourceInfo = new ResourceInfo(jndiRes.getJndiName(), applicationName, moduleName);
+ deleteResource(jndiRes, resourceInfo);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void undeployResource(Object resource)
+ throws Exception {
+
+ ExternalJndiResource jndiRes =
+ (ExternalJndiResource) resource;
+ ResourceInfo resourceInfo = ResourceUtil.getResourceInfo(jndiRes);
+ deleteResource(jndiRes, resourceInfo);
+ }
+
+ private void deleteResource(ExternalJndiResource jndiResource,
+ ResourceInfo resourceInfo) {
+ // converts the config data to j2ee resource
+ JavaEEResource j2eeResource = toExternalJndiJavaEEResource(jndiResource, resourceInfo);
+ // un-installs the resource
+ uninstallExternalJndiResource(j2eeResource, resourceInfo);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void redeployResource(Object resource)
+ throws Exception {
+
+ undeployResource(resource);
+ deployResource(resource);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean handles(Object resource) {
+ return resource instanceof ExternalJndiResource;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public boolean supportsDynamicReconfiguration() {
+ return false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public Class[] getProxyClassesForDynamicReconfiguration() {
+ return new Class[0];
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void enableResource(Object resource) throws Exception {
+ deployResource(resource);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void disableResource(Object resource) throws Exception {
+ undeployResource(resource);
+ }
+
+ /**
+ * Installs the given external jndi resource. This method gets called
+ * during server initialization and from external jndi resource
+ * deployer to handle resource events.
+ *
+ * @param extJndiRes external jndi resource
+ */
+ public void installExternalJndiResource(org.glassfish.resources.beans.ExternalJndiResource extJndiRes, ResourceInfo resourceInfo) {
+
+ try {
+ // create the external JNDI factory, its initial context and
+ // pass them as references.
+ String factoryClass = extJndiRes.getFactoryClass();
+ String jndiLookupName = extJndiRes.getJndiLookupName();
+
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "installExternalJndiResources resourceName "
+ + resourceInfo + " factoryClass " + factoryClass
+ + " jndiLookupName = " + jndiLookupName);
+ }
+
+
+ Object factory = ResourceUtil.loadObject(factoryClass);
+ if (factory == null) {
+ _logger.log(Level.WARNING, "jndi.factory_load_error", factoryClass);
+ return;
+
+ } else if (!(factory instanceof javax.naming.spi.InitialContextFactory)) {
+ _logger.log(Level.WARNING, "jndi.factory_class_unexpected", factoryClass);
+ return;
+ }
+
+ // Get properties to create the initial naming context
+ // for the target JNDI factory
+ Hashtable env = new Hashtable();
+ for (Iterator props = extJndiRes.getProperties().iterator();
+ props.hasNext(); ) {
+
+ ResourceProperty prop = (ResourceProperty) props.next();
+ env.put(prop.getName(), prop.getValue());
+ }
+
+ Context context = null;
+ try {
+ context =
+ ((InitialContextFactory) factory).getInitialContext(env);
+
+ } catch (NamingException ne) {
+ _logger.log(Level.SEVERE, "jndi.initial_context_error", factoryClass);
+ _logger.log(Level.SEVERE, "jndi.initial_context_error_excp", ne.getMessage());
+ }
+
+ if (context == null) {
+ _logger.log(Level.SEVERE, "jndi.factory_create_error", factoryClass);
+ return;
+ }
+
+ // Bind a Reference to the proxy object factory; set the
+ // initial context factory.
+ //JndiProxyObjectFactory.setInitialContext(bindName, context);
+
+ Reference ref = new Reference(extJndiRes.getResType(),
+ "org.glassfish.resources.naming.JndiProxyObjectFactory",
+ null);
+
+ // unique JNDI name within server runtime
+ ref.add(new SerializableObjectRefAddr("resourceInfo", resourceInfo));
+
+ // target JNDI name
+ ref.add(new StringRefAddr("jndiLookupName", jndiLookupName));
+
+ // target JNDI factory class
+ ref.add(new StringRefAddr("jndiFactoryClass", factoryClass));
+
+ // add Context info as a reference address
+ ref.add(new ProxyRefAddr(extJndiRes.getResourceInfo().getName(), env));
+
+ // Publish the reference
+ namingService.publishObject(resourceInfo, ref, true);
+
+ } catch (Exception ex) {
+ _logger.log(Level.SEVERE, "customrsrc.create_ref_error", resourceInfo);
+ _logger.log(Level.SEVERE, "customrsrc.create_ref_error_excp", ex);
+
+ }
+ }
+
+ /**
+ * Un-installs the external jndi resource.
+ *
+ * @param resource external jndi resource
+ */
+ public void uninstallExternalJndiResource(JavaEEResource resource, ResourceInfo resourceInfo) {
+
+ // removes the jndi context from the factory cache
+ //String bindName = resource.getResourceInfo().getName();
+ JndiProxyObjectFactory.removeInitialContext(resource.getResourceInfo());
+
+ // removes the resource from jndi naming
+ try {
+ namingService.unpublishObject(resourceInfo, resourceInfo.getName());
+ /* TODO V3 handle jms later
+ //START OF IASRI 4660565
+ if (((ExternalJndiResource)resource).isJMSConnectionFactory()) {
+ nm.unpublishObject(IASJmsUtil.getXAConnectionFactoryName(resourceName));
+ }
+ //END OF IASRI 4660565
+ */
+ } catch (javax.naming.NamingException e) {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE,
+ "Error while unpublishing resource: " + resourceInfo, e);
+ }
+ }
+ }
+
+
+ /**
+ * Returns a new instance of j2ee external jndi resource from the given
+ * config bean.
+ * <p/>
+ * This method gets called from the external resource
+ * deployer to convert external-jndi-resource config bean into
+ * external-jndi j2ee resource.
+ *
+ * @param rbean external-jndi-resource config bean
+ * @return a new instance of j2ee external jndi resource
+ */
+ public static org.glassfish.resources.api.JavaEEResource toExternalJndiJavaEEResource(
+ ExternalJndiResource rbean, ResourceInfo resourceInfo) {
+
+ org.glassfish.resources.beans.ExternalJndiResource jr = new org.glassfish.resources.beans.ExternalJndiResource(resourceInfo);
+
+ //jr.setDescription( rbean.getDescription() ); // FIXME: getting error
+
+ // sets the enable flag
+ jr.setEnabled(Boolean.valueOf(rbean.getEnabled()));
+
+ // sets the jndi look up name
+ jr.setJndiLookupName(rbean.getJndiLookupName());
+
+ // sets the resource type
+ jr.setResType(rbean.getResType());
+
+ // sets the factory class name
+ jr.setFactoryClass(rbean.getFactoryClass());
+
+ // sets the properties
+ List<Property> properties = rbean.getProperty();
+ if (properties != null) {
+ for (Property property : properties) {
+ ResourceProperty rp =
+ new ResourcePropertyImpl(property.getName(), property.getValue());
+ jr.addProperty(rp);
+ }
+ }
+ return jr;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean canDeploy(boolean postApplicationDeployment, Collection<Resource> allResources, Resource resource) {
+ if (handles(resource)) {
+ if (!postApplicationDeployment) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validatePreservedResource(Application oldApp, Application newApp, Resource resource,
+ Resources allResources)
+ throws ResourceConflictException {
+ //do nothing.
+ }
+}
diff --git a/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourceUtilities.java b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourceUtilities.java
new file mode 100644
index 0000000..5a8064d
--- /dev/null
+++ b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourceUtilities.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 1997, 2018 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.resources.module;
+
+import com.sun.enterprise.config.serverbeans.Resources;
+import org.glassfish.resources.api.Resource;
+import com.sun.logging.LogDomains;
+import com.sun.enterprise.util.i18n.StringManager;
+import org.glassfish.resourcebase.resources.api.ResourceConflictException;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import java.util.*;
+
+import static org.glassfish.resources.admin.cli.ResourceConstants.*;
+
+/** A class that holds utility/helper routines. Expected to contain static
+* methods to perform utility operations.
+*
+* @since Appserver 9.0
+*/
+public class ResourceUtilities {
+
+ private final static Logger _logger = LogDomains.getLogger(ResourceUtilities.class, LogDomains.RSR_LOGGER);
+ private final static StringManager localStrings =
+ StringManager.getManager(ResourceUtilities.class);
+
+ private ResourceUtilities()/*disallowed*/ {
+ }
+
+ /**
+ * Checks if any of the Resource in the given set has a conflict with
+ * resource definitions in the domain.xml. A <b> conflict </b> is defined
+ * based on the type of the resource. For example, a JDBC Resource has "jndi-name"
+ * that is the identifying key where as for a JDBC Connection Pool, it is
+ * the "name" that must be unique.
+ * @param resSet a Set of Resource elements.
+ * @param resources instance of ConfigContext that you want to confirm this against. May not be null.
+ * @return a Set of Resource elements that contains conflicting elements from the given Set. This
+ * method does not create any Resource elements. It just references an element in conflict
+ * from a Set that is returned. If there are no conflicts, an empty Set is returned. This method
+ * never returns a null. If the given Set is null, an empty Set is returned.
+ */
+ public static Set<org.glassfish.resources.api.Resource> getResourceConfigConflicts(final Set<org.glassfish.resources.api.Resource> resSet,
+ final Resources resources) {
+ final Set<Resource> conflicts = new HashSet<Resource>();
+ if (resSet != null) {
+ for (final org.glassfish.resources.api.Resource res : resSet) {
+ boolean duplicate = hasDuplicate(resources, res);
+ if (duplicate) {
+ conflicts.add(res);
+ }
+ }
+ }
+ return ( conflicts );
+ }
+
+ private static boolean hasDuplicate(Resources resources, Resource res) {
+ final String id = getIdToCompare(res);
+ return resources.getResourceByName(res.getClass(), id) != null;
+ }
+
+ private static String getIdToCompare(final Resource res) {
+ final HashMap attrs = res.getAttributes();
+ final String type = res.getType();
+ String id;
+ if (org.glassfish.resources.api.Resource.JDBC_CONNECTION_POOL.equals(type) ||
+ Resource.CONNECTOR_CONNECTION_POOL.equals(type)){
+ id = getNamedAttributeValue(attrs, CONNECTION_POOL_NAME); // this should come from refactored stuff TBD
+ }
+ else if (org.glassfish.resources.api.Resource.CONNECTOR_SECURITY_MAP.equals(type)) {
+ id = getNamedAttributeValue(attrs, SECURITY_MAP_NAME); // this should come from refactored stuff TBD
+ }
+ else if (org.glassfish.resources.api.Resource.RESOURCE_ADAPTER_CONFIG.equals(type)) {
+ id = getNamedAttributeValue(attrs, RESOURCE_ADAPTER_CONFIG_NAME); // this should come from refactored stuff TBD
+ }
+ else if(org.glassfish.resources.api.Resource.CONNECTOR_WORK_SECURITY_MAP.equals(type)){
+ id = getNamedAttributeValue(attrs, WORK_SECURITY_MAP_NAME);
+ }
+ else {
+ //it is OK to assume that this Resource will one of the *RESOURCEs?
+ id = getNamedAttributeValue(attrs, JNDI_NAME); // this should come from refactored stuff TBD
+ }
+ return ( id );
+ }
+
+ private static String getNamedAttributeValue(final HashMap attributes, final String name) {
+ return (String)attributes.get(name);
+ }
+
+ /**
+ * Resolves all duplicates and conflicts within an archive and returns a set
+ * of resources that needs to be created for the archive being deployed. The
+ * deployment backend would then use these set of resources to check for
+ * conflicts with resources existing in domain.xml and then continue
+ * with deployment.
+ *
+ * All resource duplicates within an archive found are flagged with a
+ * WARNING and only one resource is added in the final <code>Resource</code>
+ * <code>Set</code> returned.
+ *
+ * We currently do not handle any resource conflicts found within the archive
+ * and the method throws an exception when this condition is detected.
+ *
+ * @param sunResList a list of <code>SunResourcesXML</code> corresponding to
+ * sun-resources.xml found within an archive.
+ *
+ * @return a Set of <code>Resource</code>s that have been resolved of
+ * duplicates and conflicts.
+ *
+ * @throws org.glassfish.resources.api.ResourceConflictException an exception is thrown when an archive is found to
+ * have two or more resources that conflict with each other.
+ */
+ public static Set<org.glassfish.resources.api.Resource> resolveResourceDuplicatesConflictsWithinArchive(
+ List<org.glassfish.resources.admin.cli.SunResourcesXML> sunResList) throws ResourceConflictException {
+ boolean conflictExist = false;
+ StringBuffer conflictingResources = new StringBuffer();
+ Set<org.glassfish.resources.api.Resource> resourceSet = new HashSet<org.glassfish.resources.api.Resource>();
+ Iterator<org.glassfish.resources.admin.cli.SunResourcesXML> sunResourcesXMLIter = sunResList.iterator();
+ while(sunResourcesXMLIter.hasNext()){
+ //get list of resources from one sun-resources.xml file
+ org.glassfish.resources.admin.cli.SunResourcesXML sunResXML = sunResourcesXMLIter.next();
+ List<org.glassfish.resources.api.Resource> resources = sunResXML.getResourcesList();
+ Iterator<org.glassfish.resources.api.Resource> resourcesIter = resources.iterator();
+ //for each resource mentioned
+ while(resourcesIter.hasNext()){
+ org.glassfish.resources.api.Resource res = resourcesIter.next();
+ Iterator<org.glassfish.resources.api.Resource> resSetIter = resourceSet.iterator();
+ boolean addResource = true;
+ //check if a duplicate has already been added
+ while(resSetIter.hasNext()){
+ Resource existingRes = resSetIter.next();
+ if(existingRes.equals(res)){
+ //duplicate within an archive
+ addResource = false;
+ _logger.warning(localStrings.getString("duplicate.resource.sun.resource.xml",
+ getIdToCompare(res), sunResXML.getXMLPath()));
+ break;
+ }
+ //check if another existing resource conflicts with the
+ //resource being added
+ if(existingRes.isAConflict(res)){
+ //conflict within an archive
+ addResource = false;
+ conflictingResources.append("\n");
+ String message = localStrings.getString("conflict.resource.sun.resource.xml",
+ getIdToCompare(res), sunResXML.getXMLPath());
+ conflictingResources.append(message);
+ _logger.warning(message);
+ if(_logger.isLoggable(Level.FINE))
+ logAttributes(res);
+ }
+ }
+ if(addResource)
+ resourceSet.add(res);
+ }
+ }
+ if(conflictingResources.toString().length() > 0){
+ throw new ResourceConflictException(conflictingResources.toString());
+ }
+ return resourceSet;
+ }
+
+ /**
+ * Checks if any of the Resource in the given set has a conflict with
+ * resource definitions in the domain.xml. A <b> conflict </b> is defined
+ * based on the type of the resource. For example, a JDBC Resource has "jndi-name"
+ * that is the identifying key where as for a JDBC Connection Pool, it is
+ * the "name" that must be unique.
+ *
+ * @param resList a Set of Resource elements.
+ * @param resources all resources from domain.xml
+ *
+ * @throws org.glassfish.resources.api.ResourceConflictException an exception is thrown when an archive is found to
+ * have two or more resources that conflict with resources already present in domain.xml.
+ */
+ public static void getResourceConflictsWithDomainXML(final List<Resource> resList,
+ final Resources resources) throws ResourceConflictException {
+ if (resList != null) {
+ Iterator<org.glassfish.resources.api.Resource> iterRes = resList.iterator();
+ StringBuffer conflictingResources = new StringBuffer();
+ while (iterRes.hasNext()) {
+ org.glassfish.resources.api.Resource res = iterRes.next();
+ final String id = getIdToCompare(res);
+
+ if (resources.getResourceByName(res.getClass(), id) != null) {
+ conflictingResources.append("\n");
+ String message = localStrings.getString("conflict.resource.with.domain.xml",
+ getIdToCompare(res));
+ conflictingResources.append(message);
+ _logger.warning(message);
+ if(_logger.isLoggable(Level.FINE))
+ logAttributes(res);
+ }
+ }
+ if(conflictingResources.toString().length() > 0){
+ throw new ResourceConflictException(conflictingResources.toString());
+ }
+ }
+ }
+
+ private static void logAttributes(Resource res) {
+ StringBuffer message = new StringBuffer();
+ Set<Map.Entry> entries = res.getAttributes().entrySet();
+ Iterator<Map.Entry> entriesIter = entries.iterator();
+ while(entriesIter.hasNext()){
+ Map.Entry entry = entriesIter.next();
+ message.append(entry.getKey());
+ message.append("=");
+ message.append(entry.getValue());
+ message.append(" ");
+ }
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine(localStrings.getString("resource.attributes",
+ message.toString()));
+ }
+ }
+}
diff --git a/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesApplication.java b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesApplication.java
new file mode 100644
index 0000000..9fa10f6
--- /dev/null
+++ b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesApplication.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1997, 2018 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.resources.module;
+
+import com.sun.enterprise.config.serverbeans.*;
+import com.sun.logging.LogDomains;
+import java.util.logging.Level;
+import org.glassfish.api.deployment.*;
+import org.glassfish.internal.data.ApplicationRegistry;
+import org.glassfish.resources.listener.ApplicationScopedResourcesManager;
+import org.jvnet.hk2.annotations.Service;
+
+import org.glassfish.hk2.api.PerLookup;
+
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+@Service
+@PerLookup
+public class ResourcesApplication implements ApplicationContainer{
+
+ private static final Logger _logger = LogDomains.getLogger(ResourcesApplication.class, LogDomains.RSR_LOGGER);
+ private String applicationName;
+
+ @Inject
+ private ApplicationRegistry appRegistry;
+
+ @Inject
+ private Applications applications;
+
+ private Resources resources ;
+
+ @Inject
+ private ApplicationScopedResourcesManager asrManager;
+
+ @Inject
+ private ResourcesDeployer resourcesDeployer;
+
+ public ResourcesApplication(){
+ }
+
+ public void setApplicationName(String applicationName){
+ this.applicationName = applicationName;
+ }
+
+ public String getApplicationName(){
+ return applicationName;
+ }
+
+ public Object getDescriptor() {
+ //TODO return all resources-xml ?
+ return null;
+ }
+
+ public boolean start(ApplicationContext startupContext) throws Exception {
+ DeploymentContext dc = (DeploymentContext)startupContext;
+ final DeployCommandParameters deployParams = dc.getCommandParameters(DeployCommandParameters.class);
+ //during app. deployment, create resources config and load resources
+ if(deployParams.origin == OpsParams.Origin.deploy || deployParams.origin == OpsParams.Origin.deploy_instance){
+ resourcesDeployer.deployResources(applicationName, true);
+ }else if (deployParams.origin == OpsParams.Origin.load ||
+ deployParams.origin == OpsParams.Origin.create_application_ref) {
+ //<application> and its <resources>, <modules> are already available.
+ //Deploy them.
+
+ //during app. load (eg: server start or application/application-ref enable(), load resources
+ asrManager.deployResources(applicationName);
+ }
+ return true;
+ }
+
+ public boolean stop(ApplicationContext stopContext) {
+ asrManager.undeployResources(applicationName);
+ return true;
+ }
+
+ public boolean suspend() {
+ return true;
+ }
+
+ public boolean resume() throws Exception {
+ return true;
+ }
+
+ public ClassLoader getClassLoader() {
+ //TODO return loader
+ return null;
+ }
+ private void debug(String message){
+ if(_logger.isLoggable(Level.FINEST)) {
+ _logger.finest("[ResourcesApplication] " + message);
+ }
+ }
+
+}
diff --git a/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesContainer.java b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesContainer.java
new file mode 100644
index 0000000..39f3ca7
--- /dev/null
+++ b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesContainer.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1997, 2018 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.resources.module;
+
+import com.sun.logging.LogDomains;
+import org.glassfish.api.container.Container;
+import org.glassfish.api.deployment.Deployer;
+import org.glassfish.resourcebase.resources.api.ResourceConstants;
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.hk2.api.PreDestroy;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+@Service(name = "org.glassfish.resources.module.ResourcesContainer")
+public class ResourcesContainer implements Container, PostConstruct, PreDestroy {
+
+ private final static Logger _logger = LogDomains.getLogger(ResourcesContainer.class, LogDomains.RSR_LOGGER);
+
+ public void postConstruct() {
+ logFine("postConstruct of ConnectorContainer");
+ }
+
+ public void preDestroy() {
+ logFine("preDestroy of ConnectorContainer");
+ }
+
+ /**
+ * Returns the Deployer implementation capable of deploying applications to this
+ * container.
+ *
+ * @return the Deployer implementation
+ */
+ public Class<? extends Deployer> getDeployer() {
+ return ResourcesDeployer.class;
+ }
+
+ /**
+ * Returns a human readable name for this container, this name is not used for
+ * identifying the container but can be used to display messages belonging to
+ * the container.
+ *
+ * @return a human readable name for this container.
+ */
+ public String getName() {
+ return ResourceConstants.GF_RESOURCES_MODULE;
+ }
+
+ public void logFine(String message) {
+ if(_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, message);
+ }
+ }
+
+}
diff --git a/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesDeployer.java b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesDeployer.java
new file mode 100644
index 0000000..d6c49b8
--- /dev/null
+++ b/appserver/resources/resources-runtime/src/main/java/org/glassfish/resources/module/ResourcesDeployer.java
@@ -0,0 +1,1010 @@
+/*
+ * Copyright (c) 2010, 2018 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.resources.module;
+
+import com.sun.enterprise.config.serverbeans.*;
+import com.sun.enterprise.config.serverbeans.Resource;
+import com.sun.enterprise.deployment.util.DOLUtils;
+import com.sun.logging.LogDomains;
+import org.glassfish.api.deployment.DeployCommandParameters;
+import org.glassfish.api.deployment.DeploymentContext;
+import org.glassfish.api.deployment.OpsParams;
+import org.glassfish.api.deployment.UndeployCommandParameters;
+import org.glassfish.api.deployment.archive.ReadableArchive;
+import org.glassfish.api.event.*;
+import org.glassfish.deployment.common.DeploymentException;
+import org.glassfish.deployment.common.DeploymentProperties;
+import org.glassfish.deployment.common.DeploymentUtils;
+import org.glassfish.internal.api.ServerContext;
+import org.glassfish.internal.data.ApplicationInfo;
+import org.glassfish.internal.data.ApplicationRegistry;
+import org.glassfish.internal.deployment.Deployment;
+import org.glassfish.javaee.core.deployment.JavaEEDeployer;
+import org.glassfish.resources.admin.cli.ResourceManager;
+import org.glassfish.resources.admin.cli.ResourcesXMLParser;
+import org.glassfish.resources.admin.cli.SunResourcesXML;
+import org.glassfish.resources.api.*;
+import org.glassfish.resourcebase.resources.util.ResourceManagerFactory;
+import org.glassfish.resourcebase.resources.api.ResourceDeployer;
+import org.glassfish.resources.util.ResourceUtil;
+import org.glassfish.resourcebase.resources.api.ResourcesBinder;
+import org.glassfish.resourcebase.resources.api.ResourceConflictException;
+import org.glassfish.resourcebase.resources.api.ResourceConstants;
+import org.glassfish.resourcebase.resources.api.ResourceInfo;
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.hk2.api.PreDestroy;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.jvnet.hk2.config.*;
+
+import org.glassfish.api.event.EventListener;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.resource.ResourceException;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static org.glassfish.resources.admin.cli.ResourceConstants.*;
+import static org.glassfish.resources.api.Resource.*;
+import static org.glassfish.resourcebase.resources.api.ResourceConstants.*;
+
+/**
+ * ResourcesDeployer to handle "glassfish-resources.xml(s)" bundled in the application.
+ *
+ * @author Jagadish Ramu
+ */
+@Service
+public class ResourcesDeployer extends JavaEEDeployer<ResourcesContainer, ResourcesApplication>
+ implements PostConstruct, PreDestroy, EventListener {
+ private final org.glassfish.resources.admin.cli.ResourceFactory resourceFactory;
+
+ @Inject
+ private Domain domain;
+
+ @Inject
+ private ServerContext context;
+
+ @Inject
+ private Provider<ResourcesApplication> resourcesApplicationProvider;
+
+ private final ApplicationRegistry appRegistry;
+
+ private final Provider<ResourceManagerFactory> resourceManagerFactoryProvider;
+
+ private final ResourcesBinder resourcesBinder;
+
+ @Inject
+ private ConfigSupport configSupport;
+
+ @Inject
+ private Events events;
+
+ @Inject
+ private ServiceLocator locator;
+
+ private final Applications applications;
+
+ private static Map<String, Application> preservedApps = new HashMap<String, Application>();
+
+ private final static Logger _logger = LogDomains.getLogger(ResourcesDeployer.class, LogDomains.RSR_LOGGER);
+
+ private static final String RESOURCES_XML_META_INF = "META-INF/glassfish-resources.xml";
+ private static final String RESOURCES_XML_WEB_INF = "WEB-INF/glassfish-resources.xml";
+
+ @Inject
+ public ResourcesDeployer(org.glassfish.resources.admin.cli.ResourceFactory resourceFactoryParam,
+ ApplicationRegistry appRegistryParam,
+ Provider<ResourceManagerFactory> resourceManagerFactoryProviderParam,
+ ResourcesBinder resourcesBinderParam,
+ Applications applicationsParam) {
+ resourceFactory = resourceFactoryParam;
+ appRegistry = appRegistryParam;
+ resourceManagerFactoryProvider = resourceManagerFactoryProviderParam;
+ resourcesBinder = resourcesBinderParam;
+ applications = applicationsParam;
+ }
+
+ public void postConstruct() {
+ events.register(this);
+ }
+
+ public void preDestroy(){
+ events.unregister(this);
+ }
+
+ /**
+ * Loads a previously prepared application in its execution environment and
+ * return a ContractProvider instance that will identify this environment in
+ * future communications with the application's container runtime.
+ *
+ * @param container in which the application will reside
+ * @param context of the deployment
+ * @return an ApplicationContainer instance identifying the running application
+ */
+ @Override
+ public ResourcesApplication load(ResourcesContainer container, DeploymentContext context) {
+ super.load(container, context);
+ debug("App-Scoped-Resources ResourcesDeployer.load()");
+ ResourcesApplication application = resourcesApplicationProvider.get();
+ application.setApplicationName(getAppNameFromDeployCmdParams(context));
+ return application;
+ }
+
+ public void unload(ResourcesApplication appContainer, DeploymentContext context) {
+ //TODO unregistering resources, removing resources configuration.
+ debug("Resources-Deployer :unload() called");
+ }
+
+ /**
+ * Retrieve connector and non-connector resources from the archive.
+ *
+ * @param archive Archieve from which the resources to be retrieved.
+ * @param appName Name of the application
+ * @param connectorResources Connector resources will be added to this list.
+ * @param nonConnectorResources Non connector resources will be added to this list.
+ * @param resourceXmlParsers Resource xml parsers corresponding to both connector and non connector resources will be stored in this.
+ */
+ public void getResources(ReadableArchive archive, String appName,
+ List<org.glassfish.resources.api.Resource> connectorResources,
+ List<org.glassfish.resources.api.Resource> nonConnectorResources,
+ Map<org.glassfish.resources.api.Resource, ResourcesXMLParser> resourceXmlParsers) {
+ try {
+ if (ResourceUtil.hasResourcesXML(archive, locator)) {
+ Map<String, Map<String, List>> appScopedResources = new HashMap<String, Map<String, List>>();
+ Map<String, String> fileNames = new HashMap<String, String>();
+ //using appName as it is possible that "deploy --name=APPNAME" will
+ //be different than the archive name.
+ retrieveAllResourcesXMLs(fileNames, archive, appName);
+
+ for (Map.Entry<String, String> entry : fileNames.entrySet()) {
+ String moduleName = entry.getKey();
+ String fileName = entry.getValue();
+ debug("GlassFish Resources XML : " + fileName);
+
+ moduleName = org.glassfish.resourcebase.resources.util.ResourceUtil.getActualModuleNameWithExtension(moduleName);
+ String scope;
+ if (appName.equals(moduleName)) {
+ scope = JAVA_APP_SCOPE_PREFIX;
+ } else {
+ scope = JAVA_MODULE_SCOPE_PREFIX;
+ }
+
+ File file = new File(fileName);
+ ResourcesXMLParser parser = new ResourcesXMLParser(file, scope);
+
+ validateResourcesXML(file, parser);
+
+ List<org.glassfish.resources.api.Resource> resources = parser.getResourcesList();
+
+ if (nonConnectorResources != null) {
+ nonConnectorResources.addAll(ResourcesXMLParser.
+ getNonConnectorResourcesList(resources, false, true));
+ }
+
+ if (connectorResources != null) {
+ connectorResources.addAll(ResourcesXMLParser.
+ getConnectorResourcesList(resources, false, true));
+ }
+
+ if (resourceXmlParsers != null) {
+ for (org.glassfish.resources.api.Resource res : resources) {
+ resourceXmlParsers.put(res, parser);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ // only DeploymentExceptions are propagated and result in deployment failure
+ // in the event notification infrastructure
+ throw new DeploymentException("Failue while processing glassfish-resources.xml(s) in the archive ", e);
+ }
+ }
+
+ private void processArchive(DeploymentContext dc) {
+
+ try {
+ ReadableArchive archive = dc.getSource();
+
+ if (ResourceUtil.hasResourcesXML(archive, locator)) {
+
+ Map<String,Map<String, List>> appScopedResources = new HashMap<String,Map<String,List>>();
+ Map<String, List<String>> jndiNames = new HashMap<String, List<String>>();
+ List<Map.Entry<String, String>> raNames = new ArrayList<>();
+ Map<String, String> fileNames = new HashMap<String, String>();
+
+ String appName = getAppNameFromDeployCmdParams(dc);
+ //using appName as it is possible that "deploy --name=APPNAME" will
+ //be different than the archive name.
+ retrieveAllResourcesXMLs(fileNames, archive, appName);
+
+ for (Map.Entry<String, String> entry: fileNames.entrySet()) {
+ String moduleName = entry.getKey();
+ String fileName = entry.getValue();
+ debug("Sun Resources XML : " + fileName);
+
+ moduleName = org.glassfish.resourcebase.resources.util.ResourceUtil.getActualModuleNameWithExtension(moduleName);
+ String scope ;
+ if(appName.equals(moduleName)){
+ scope = JAVA_APP_SCOPE_PREFIX;
+ }else{
+ scope = JAVA_MODULE_SCOPE_PREFIX;
+ }
+
+ File file = new File(fileName);
+ ResourcesXMLParser parser = new ResourcesXMLParser(file, scope);
+
+ validateResourcesXML(file, parser);
+
+ List list = parser.getResourcesList();
+
+ Map<String, List> resourcesList = new HashMap<String, List>();
+ List<String> jndiNamesList = new ArrayList<String>();
+ List<org.glassfish.resources.api.Resource> nonConnectorResources =
+ ResourcesXMLParser.getNonConnectorResourcesList(list, false, true);
+ resourcesList.put(NON_CONNECTOR_RESOURCES, nonConnectorResources);
+ for (org.glassfish.resources.api.Resource resource : nonConnectorResources) {
+ String jndiName = extractJNDIName(resource);
+ if (hasRAName(resource)) {
+ raNames.add(new AbstractMap.SimpleEntry<>(extractRAName(resource), resource.getType()));
+ }
+ if (jndiName != null) {
+ jndiNamesList.add(jndiName);
+ }
+ }
+
+ List<org.glassfish.resources.api.Resource> connectorResources =
+ ResourcesXMLParser.getConnectorResourcesList(list, false, true);
+ resourcesList.put(CONNECTOR_RESOURCES, connectorResources);
+ for (org.glassfish.resources.api.Resource resource : connectorResources) {
+ String jndiName = extractJNDIName(resource);
+ if (hasRAName(resource)) {
+ raNames.add(new AbstractMap.SimpleEntry<>(extractRAName(resource), resource.getType()));
+ }
+ if (jndiName != null) {
+ jndiNamesList.add(jndiName);
+ }
+ }
+
+ jndiNames.put(moduleName, jndiNamesList);
+ appScopedResources.put(moduleName, resourcesList);
+ }
+ dc.addTransientAppMetaData(APP_SCOPED_RESOURCES_JNDI_NAMES, jndiNames);
+ dc.addTransientAppMetaData(APP_SCOPED_RESOURCES_RA_NAMES, raNames);
+ dc.addTransientAppMetaData(APP_SCOPED_RESOURCES_MAP, appScopedResources);
+ ApplicationInfo appInfo = appRegistry.get(appName);
+ if(appInfo != null){
+ Application app = dc.getTransientAppMetaData(ServerTags.APPLICATION, Application.class);
+ appInfo.addTransientAppMetaData(ServerTags.APPLICATION, app);
+ }
+ }
+ } catch (Exception e) {
+ // only DeploymentExceptions are propagated and result in deployment failure
+ // in the event notification infrastructure
+ throw new DeploymentException("Failue while processing glassfish-resources.xml(s) in the archive ", e);
+ }
+ }
+
+ /**
+ * Extract the JNDI name from the resource. Collecting for resource valitation.
+ *
+ * @param resource
+ * @return jndi name if present, null otherwise
+ */
+ private String extractJNDIName(org.glassfish.resources.api.Resource resource) {
+ HashMap attrs = resource.getAttributes();
+ return (String) attrs.get(JNDI_NAME);
+ }
+
+ private boolean hasRAName(org.glassfish.resources.api.Resource resource) {
+ return resource.getType().equals(ADMIN_OBJECT_RESOURCE) ||
+ resource.getType().equals(CONNECTOR_CONNECTION_POOL) ||
+ resource.getType().equals(RESOURCE_ADAPTER_CONFIG) ||
+ resource.getType().equals(CONNECTOR_WORK_SECURITY_MAP);
+ }
+
+ /**
+ * Extract the RA name for a connector resource. Collecting for resource validation.
+ *
+ * @param resource
+ * @return resource adapter name
+ */
+ private String extractRAName(org.glassfish.resources.api.Resource resource) {
+ if (resource.getType().equals(ADMIN_OBJECT_RESOURCE))
+ return (String)resource.getAttributes().get(RES_ADAPTER);
+ else
+ return (String)resource.getAttributes().get(RES_ADAPTER_NAME);
+ }
+
+ private static void validateResourcesXML(File file, ResourcesXMLParser parser) throws ResourceConflictException {
+ String filePath = file.getPath();
+ SunResourcesXML sunResourcesXML = new SunResourcesXML(filePath, parser.getResourcesList());
+ List<SunResourcesXML> resourcesXMLList = new ArrayList<SunResourcesXML>();
+ resourcesXMLList.add(sunResourcesXML);
+ ResourceUtilities.resolveResourceDuplicatesConflictsWithinArchive(resourcesXMLList);
+ }
+
+ /**
+ * retain old resource configuration for the new archive being deployed.
+ * @param dc DeploymentContext
+ * @param allResources all resources (app scoped, module scoped) of old application
+ * @throws Exception when unable to retain old resource configuration.
+ */
+ public void retainResourceConfig(DeploymentContext dc, Map<String, Resources> allResources) throws Exception {
+ String appName = getAppNameFromDeployCmdParams(dc);
+ Application application = dc.getTransientAppMetaData(ServerTags.APPLICATION, Application.class);
+ Resources appScopedResources = allResources.get(appName);
+
+ if(appScopedResources != null){
+ application.setResources(appScopedResources);
+ }
+
+ if(DeploymentUtils.isArchiveOfType(dc.getSource(), DOLUtils.earType(), locator)){
+ List<Module> modules = application.getModule();
+ if(modules != null){
+ for(Module module : modules){
+ Resources moduleScopedResources = allResources.get(module.getName());
+ if(moduleScopedResources != null){
+ module.setResources(moduleScopedResources);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * During "load()" event (eg: app/app-ref enable, server start),
+ * populate resource-config in app-info so that it can be used for
+ * constructing connector-classloader for the application.
+ * @param dc DeploymentContext
+ */
+ public void populateResourceConfigInAppInfo(DeploymentContext dc){
+ String appName = getAppNameFromDeployCmdParams(dc);
+ Application application = applications.getApplication(appName);
+ ApplicationInfo appInfo = appRegistry.get(appName);
+ if(application != null && appInfo != null){
+ Resources appScopedResources = application.getResources();
+ if(appScopedResources != null){
+ appInfo.addTransientAppMetaData(ServerTags.APPLICATION, application);
+ appInfo.addTransientAppMetaData(application.getName()+"-resources", appScopedResources);
+ }
+
+ List<Module> modules = application.getModule();
+ if(modules != null){
+ for(Module module : modules){
+ Resources moduleScopedResources = module.getResources();
+ if(moduleScopedResources != null){
+ appInfo.addTransientAppMetaData(module.getName()+"-resources", moduleScopedResources);
+ }
+ }
+ }
+ }
+ }
+
+ public void createResources(DeploymentContext dc, boolean embedded, boolean deployResources) throws ResourceException {
+ String appName = getAppNameFromDeployCmdParams(dc);
+ Application app = dc.getTransientAppMetaData(ServerTags.APPLICATION, Application.class);
+ Map<String, Map<String, List>> resourcesList =
+ (Map<String, Map<String, List>>)dc.getTransientAppMetadata().get(APP_SCOPED_RESOURCES_MAP);
+
+ if (resourcesList != null) {
+ Map<String, List> appLevelResources = resourcesList.get(appName);
+ if (appLevelResources != null) {
+ List<org.glassfish.resources.api.Resource> connectorResources =
+ appLevelResources.get(CONNECTOR_RESOURCES);
+
+ createAppScopedResources(app, connectorResources, dc, embedded);
+
+ List<org.glassfish.resources.api.Resource> nonConnectorResources =
+ appLevelResources.get(NON_CONNECTOR_RESOURCES);
+
+ createAppScopedResources(app, nonConnectorResources, dc, embedded);
+
+ }
+ List<Module> modules = app.getModule();
+ if (modules != null) {
+ for (Module module : modules) {
+ String actualModuleName = org.glassfish.resourcebase.resources.util.ResourceUtil.getActualModuleNameWithExtension(module.getName());
+ //create resources for modules, ignore standalone applications where
+ //module name will be the same as app name
+ if(!appName.equals(actualModuleName)){
+ Map<String, List> moduleResources = resourcesList.get(actualModuleName);
+ if (moduleResources != null) {
+ List<org.glassfish.resources.api.Resource> connectorResources =
+ moduleResources.get(CONNECTOR_RESOURCES);
+ createModuleScopedResources(app, module, connectorResources, dc, embedded);
+
+ List<org.glassfish.resources.api.Resource> nonConnectorResources =
+ moduleResources.get(NON_CONNECTOR_RESOURCES);
+ createModuleScopedResources(app, module, nonConnectorResources, dc, embedded);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private Collection<Resource>
+ createConfig(Resources resources, Collection<org.glassfish.resources.api.Resource> resourcesToRegister,
+ boolean embedded)
+ throws ResourceException {
+ List<Resource> resourceConfigs =
+ new ArrayList<Resource>();
+ for (org.glassfish.resources.api.Resource resource : resourcesToRegister) {
+ final HashMap attrList = resource.getAttributes();
+ final Properties props = resource.getProperties();
+ String desc = resource.getDescription();
+ if (desc != null) {
+ attrList.put("description", desc);
+ }
+
+ try {
+ final ResourceManager rm = resourceFactory.getResourceManager(resource);
+ if(embedded && isEmbeddedResource(resource, resourcesToRegister)){
+ Resource configBeanResource =
+ rm.createConfigBean(resources, attrList, props, false);
+ resources.getResources().add(configBeanResource);
+ resourceConfigs.add(configBeanResource);
+ }else if(!embedded && !isEmbeddedResource(resource, resourcesToRegister)){
+ com.sun.enterprise.config.serverbeans.Resource configBeanResource =
+ rm.createConfigBean(resources, attrList, props, true);
+ resources.getResources().add(configBeanResource);
+ resourceConfigs.add(configBeanResource);
+ }
+ } catch (Exception e) {
+ throw new ResourceException(e);
+ }
+ }
+ return resourceConfigs;
+ }
+
+ private static boolean isConnectorResource(org.glassfish.resources.api.Resource resource){
+ if(resource.getType().equals(ADMIN_OBJECT_RESOURCE) ||
+ resource.getType().equals(CONNECTOR_CONNECTION_POOL) ||
+ resource.getType().equals(CONNECTOR_RESOURCE) ||
+ resource.getType().equals(RESOURCE_ADAPTER_CONFIG) ||
+ resource.getType().equals(CONNECTOR_WORK_SECURITY_MAP)){
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+ private static boolean isEmbeddedResource(org.glassfish.resources.api.Resource resource,
+ Collection<org.glassfish.resources.api.Resource> resources){
+ boolean result = false;
+ if(isConnectorResource(resource)){
+ String attributeName = null;
+ if(resource.getType().equals(ADMIN_OBJECT_RESOURCE)){
+ attributeName = RES_ADAPTER;
+ } else if(resource.getType().equals(CONNECTOR_CONNECTION_POOL)){
+ attributeName = RES_ADAPTER_NAME;
+ } else if(resource.getType().equals(CONNECTOR_RESOURCE)){
+ String poolName = (String)resource.getAttributes().get(POOL_NAME);
+ if(poolName != null){
+ org.glassfish.resources.api.Resource poolResource = getPoolResource(poolName, resources);
+ //point to poolResource
+ resource = poolResource;
+ attributeName = RES_ADAPTER_NAME;
+ }
+ }/* else if(resource.getType().equals(org.glassfish.resources.api.Resource.RESOURCE_ADAPTER_CONFIG)){
+ attributeName = ResourceConstants.RES_ADAPTER_NAME;
+ } */else if(resource.getType().equals(CONNECTOR_WORK_SECURITY_MAP)){
+ attributeName = RES_ADAPTER_NAME;
+ }
+ if(attributeName != null && resource != null){
+ result = isEmbeddedRar(resource, attributeName);
+ }
+ }
+ return result;
+ }
+
+ private static org.glassfish.resources.api.Resource getPoolResource(
+ String poolName, Collection<org.glassfish.resources.api.Resource> resources){
+ org.glassfish.resources.api.Resource result = null;
+ for(org.glassfish.resources.api.Resource resource : resources){
+ if(resource.getType().equals(CONNECTOR_CONNECTION_POOL)){
+ String cpName = (String)resource.getAttributes().get(CONNECTION_POOL_NAME);
+ if(poolName.equals(cpName)){
+ result = resource;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ private static boolean isEmbeddedRar(org.glassfish.resources.api.Resource resource, String attributeName) {
+ boolean result = false;
+ String raName = (String)resource.getAttributes().get(attributeName);
+ if(raName != null && raName.contains(ResourceConstants.EMBEDDEDRAR_NAME_DELIMITER)){
+ result = true;
+ }
+ return result;
+ }
+
+
+ private void createAppScopedResources(Application app, List<org.glassfish.resources.api.Resource> resources,
+ DeploymentContext dc, boolean embedded)
+ throws ResourceException {
+ try {
+ if (resources != null) {
+ Application application = dc.getTransientAppMetaData(ServerTags.APPLICATION, Application.class);
+ Resources asc = dc.getTransientAppMetaData(APP_META_DATA_RESOURCES, Resources.class);
+ if (asc == null) {
+ asc = application.createChild(Resources.class);
+ application.setResources(asc);
+ dc.addTransientAppMetaData(APP_META_DATA_RESOURCES, asc);
+ ApplicationInfo appInfo = appRegistry.get(app.getName());
+ if(appInfo != null){
+ appInfo.addTransientAppMetaData(app.getName()+"-resources", asc);
+ }
+ }
+
+ createConfig(asc, resources, embedded);
+ String appName = app.getName();
+ preserveResources(asc, appName, appName);
+ }
+ } catch (Exception e) {
+ Object params[] = new Object[]{app.getName(), e};
+ _logger.log(Level.SEVERE, "gf.resources.app.scope.deployment.failure", params);
+ throw new ResourceException(e);
+ }
+ }
+
+ /**
+ * preserve the resources such that they can be undeployed during deployment failure.
+ * @param resources resources
+ * @param appName application-name
+ * @param moduleName module-name
+ */
+ private static void preserveResources(Resources resources, String appName, String moduleName) {
+ Map<String, Resources> allResources = ResourcesRegistry.getResources(appName);
+ if(allResources != null){
+ allResources.put(moduleName, resources);
+ }else{
+ allResources = new HashMap<String, Resources>();
+ allResources.put(moduleName, resources);
+ ResourcesRegistry.putResources(appName, allResources);
+ }
+ }
+
+ private void createModuleScopedResources(Application app, Module module,
+ List<org.glassfish.resources.api.Resource> resources,
+ DeploymentContext dc, boolean embedded)
+ throws ResourceException {
+ try {
+ if (resources != null) {
+ Resources msc = dc.getTransientAppMetaData(module.getName()+"-resources", Resources.class);
+ if (msc == null) {
+ msc = module.createChild(Resources.class);
+ module.setResources(msc);
+ dc.addTransientAppMetaData(module.getName()+"-resources", msc);
+ ApplicationInfo appInfo = appRegistry.get(app.getName());
+ if(appInfo != null){
+ appInfo.addTransientAppMetaData(module.getName()+"-resources", msc);
+ }
+ }
+
+ createConfig(msc, resources, embedded);
+ preserveResources(msc, app.getName(), module.getName());
+ }
+ } catch (Exception e) {
+ Object params[] = new Object[]{module.getName(),app.getName(), e};
+ _logger.log(Level.SEVERE, "gf.resources.module.scope.deployment.failure", params);
+ throw new ResourceException(e);
+ }
+ }
+
+ public void deployResourcesFromConfiguration(String appName, boolean embedded) throws Exception {
+ Application application = applications.getApplication(appName);
+ ApplicationInfo appInfo = appRegistry.get(appName);
+ if(application != null && appInfo != null){
+ Resources appScopedResources = application.getResources();
+ if(appScopedResources != null){
+ deployResources(appName, null, appScopedResources.getResources(), embedded);
+ }
+
+ List<Module> modules = application.getModule();
+ if(modules != null){
+ for(Module module : modules){
+ Resources moduleScopedResources = module.getResources();
+ String moduleName = module.getName();
+ if(moduleScopedResources != null){
+ deployResources(appName, moduleName, moduleScopedResources.getResources(), embedded);
+ }
+ }
+ }
+ }
+ }
+
+ public void deployResources(String applicationName, boolean postDeployPhase) throws Exception {
+ Map<String, Resources> allResources = ResourcesRegistry.getResources(applicationName);
+ if(allResources != null){
+ for(Map.Entry<String, Resources> entry : allResources.entrySet()){
+ String moduleName = entry.getKey();
+ Resources resources = entry.getValue();
+ if(applicationName.equals(moduleName)){
+ deployResources(applicationName, null, resources.getResources(), postDeployPhase);
+ }else{
+ deployResources(applicationName, moduleName, resources.getResources(), postDeployPhase);
+ }
+ }
+ }
+ }
+ public void deployResources(String applicationName, String moduleName,
+ Collection<com.sun.enterprise.config.serverbeans.Resource> resources,
+ boolean postDeployPhase) throws Exception {
+ for(Resource resource : resources){
+ if(resource instanceof BindableResource) {
+ BindableResource bindableResource = (BindableResource)resource;
+ ResourceInfo resourceInfo = new ResourceInfo(bindableResource.getJndiName(), applicationName, moduleName);
+ if(getResourceDeployer(bindableResource).canDeploy(postDeployPhase, resources, bindableResource)){
+ resourcesBinder.deployResource(resourceInfo, bindableResource);
+ }
+ } else{
+ if(getResourceDeployer(resource).canDeploy(postDeployPhase, resources, resource)){
+ getResourceDeployer(resource).deployResource(resource, applicationName, moduleName);
+ }
+ }
+ }
+ }
+
+ private static String getAppNameFromDeployCmdParams(DeploymentContext dc) {
+ final DeployCommandParameters commandParams = dc.getCommandParameters(DeployCommandParameters.class);
+ return commandParams.name();
+ }
+
+ public void retrieveAllResourcesXMLs(Map<String, String> fileNames, ReadableArchive archive,
+ String actualArchiveName) throws IOException {
+
+ if(DeploymentUtils.isArchiveOfType(archive, DOLUtils.earType(), locator)){
+ //Look for top-level META-INF/glassfish-resources.xml
+ if(archive.exists(RESOURCES_XML_META_INF)){
+ String archivePath = archive.getURI().getPath();
+ String fileName = archivePath + RESOURCES_XML_META_INF;
+ if(_logger.isLoggable(Level.FINEST)){
+ _logger.finest("GlassFish-Resources Deployer - fileName : " + fileName +
+ " - parent : " + archive.getName());
+ }
+ fileNames.put(actualArchiveName, fileName);
+ }
+
+ //Lok for sub-module level META-INF/glassfish-resources.xml and WEB-INF/glassfish-resources.xml
+ Enumeration<String> entries = archive.entries();
+ while(entries.hasMoreElements()){
+ String element = entries.nextElement();
+ if(element.endsWith(".jar") || element.endsWith(".war") || element.endsWith(".rar") ||
+ element.endsWith("_jar") || element.endsWith("_war") || element.endsWith("_rar")){
+ ReadableArchive subArchive = archive.getSubArchive(element);
+ if(subArchive != null ){
+ retrieveResourcesXMLFromArchive(fileNames, subArchive, subArchive.getName());
+ }
+ }
+ }
+ }else{
+ //Look for standalone archive's META-INF/glassfish-resources.xml and WEB-INF/glassfish-resources.xml
+ retrieveResourcesXMLFromArchive(fileNames, archive, actualArchiveName);
+ }
+ }
+
+ private void retrieveResourcesXMLFromArchive(Map<String, String> fileNames, ReadableArchive archive,
+ String actualArchiveName) {
+ if(ResourceUtil.hasResourcesXML(archive, locator)){
+ String archivePath = archive.getURI().getPath();
+ String fileName ;
+ if(DeploymentUtils.isArchiveOfType(archive, DOLUtils.warType(), locator)){
+ fileName = archivePath + RESOURCES_XML_WEB_INF;
+ }else{
+ fileName = archivePath + RESOURCES_XML_META_INF;
+ }
+ if(_logger.isLoggable(Level.FINEST)){
+ _logger.finest("GlassFish-Resources Deployer - fileName : " + fileName +
+ " - parent : " + archive.getName());
+ }
+
+ fileNames.put(actualArchiveName, fileName);
+ }
+ }
+
+ /**
+ * Given a <i>resource</i> instance, appropriate deployer will be provided
+ *
+ * @param resource resource instance
+ * @return ResourceDeployer
+ */
+ private ResourceDeployer getResourceDeployer(Object resource){
+ return resourceManagerFactoryProvider.get().getResourceDeployer(resource);
+ }
+
+ /**
+ * Event listener to listen to </code>application undeploy validation</code> and
+ * if <i>preserveResources</i> flag is set, cache the <resources>
+ * config for persisting it in domain.xml
+ */
+ public void event(Event event) {
+ if (event.is(Deployment.DEPLOYMENT_BEFORE_CLASSLOADER_CREATION)) {
+ DeploymentContext dc = (DeploymentContext) event.hook();
+ final DeployCommandParameters deployParams = dc.getCommandParameters(DeployCommandParameters.class);
+ processResources(dc, deployParams);
+ }else if(event.is(Deployment.UNDEPLOYMENT_VALIDATION)){
+ DeploymentContext dc = (DeploymentContext) event.hook();
+ final UndeployCommandParameters undeployCommandParameters =
+ dc.getCommandParameters(UndeployCommandParameters.class);
+ preserveResources(dc, undeployCommandParameters);
+ }else if(Deployment.UNDEPLOYMENT_FAILURE.equals(event.type())){
+ DeploymentContext dc = (DeploymentContext) event.hook();
+ cleanupPreservedResources(dc, event);
+ }else if(Deployment.DEPLOYMENT_FAILURE.equals(event.type())){
+ DeploymentContext dc = (DeploymentContext) event.hook();
+ String appName = getAppNameFromDeployCmdParams(dc);
+ cleanupResources(appName, dc.getCommandParameters(DeployCommandParameters.class).origin);
+ //TODO ASR call this only when the flag is on ? --properties preserveAppScopedResources=true
+ cleanupPreservedResources(dc, event);
+ }else if(Deployment.DEPLOYMENT_SUCCESS.equals(event.type())){
+ ApplicationInfo applicationInfo = (ApplicationInfo) event.hook();
+ String appName = applicationInfo.getName();
+ ResourcesRegistry.remove(appName);
+ }
+ }
+
+ private void processResources(DeploymentContext dc, DeployCommandParameters deployParams) {
+ try{
+ if (deployParams.origin == OpsParams.Origin.deploy || deployParams.origin == OpsParams.Origin.deploy_instance
+ /*|| (deployParams.origin == OpsParams.Origin.create_application_ref && env.isInstance())*/) {
+ Properties properties = deployParams.properties;
+ if(properties != null){
+ //handle if "preserveAppScopedResources" property is set (during deploy --force=true or redeploy)
+ String preserve = properties.getProperty(DeploymentProperties.PRESERVE_APP_SCOPED_RESOURCES);
+ if (preserve != null && Boolean.valueOf(preserve)) {
+ Boolean redeploy = false;
+ redeploy = deployParams.force;
+
+ if (redeploy) {
+ String appName = getAppNameFromDeployCmdParams(dc);
+ Map<String, Resources> allResources = ResourcesRegistry.remove(appName);
+ Application oldApp = preservedApps.remove(appName);
+ if (allResources != null && oldApp != null) {
+ Application application = dc.getTransientAppMetaData(ServerTags.APPLICATION, Application.class);
+ validatePreservedResources(allResources, oldApp, application);
+ retainResourceConfig(dc, allResources);
+ }
+ return;
+ }
+ }
+ }
+ Application app = dc.getTransientAppMetaData(ServerTags.APPLICATION, Application.class);
+ String applicationName = getAppNameFromDeployCmdParams(dc);
+ if(app != null){
+ //application is stored in transient meta data only during deployment.
+ processArchive(dc);
+ createResources(dc, false, true);
+ createResources(dc, true, false);
+ deployResources(applicationName, false);
+ }else{
+ //application config is already present. Use the same.
+ deployResourcesFromConfiguration(applicationName, false);
+ populateResourceConfigInAppInfo(dc);
+ }
+ }else if(deployParams.origin == OpsParams.Origin.load){
+ //during load event (ie., app/app-ref enable or server start, resource configuration
+ //is present in domain.xml. Use the configuration.
+ populateResourceConfigInAppInfo(dc);
+ }
+ }catch(Exception e){
+ // only DeploymentExceptions are propagated and result in deployment failure
+ // in the event notification infrastructure
+ if(_logger.isLoggable(Level.FINEST)){
+ _logger.log(Level.FINEST, "Exception while processing archive of application" +
+ " [ "+getAppNameFromDeployCmdParams(dc)+" ] for resources definitions : " + e.getCause());
+ }
+ throw new DeploymentException(e);
+ }
+ }
+
+ /**
+ * Validates the old resource configuration against new archive's modules.
+ * @param allResources all resources (app scoped, module scoped)
+ * @param oldApp Old Application config
+ * @param newApp New Applicatoin config
+ * @throws org.glassfish.resourcebase.resources.api.ResourceConflictException when it is not possible to map any of the resource(s) to
+ * new application/its modules
+ */
+ private void validatePreservedResources(Map<String, Resources> allResources, Application oldApp,
+ Application newApp) throws ResourceConflictException {
+
+ String appName = newApp.getName();
+ Resources appScopedResources = allResources.get(appName);
+ if (appScopedResources != null) {
+ for(Resource resource : appScopedResources.getResources()){
+ getResourceDeployer(resource).validatePreservedResource(oldApp, newApp, resource, appScopedResources);
+ }
+ }
+
+ List<Module> newModules = newApp.getModule();
+ for(Module newModule : newModules){
+ Module oldModule = oldApp.getModule(newModule.getName());
+ if(oldModule != null){
+ Resources oldModuleResources = oldModule.getResources();
+ if(oldModuleResources != null){
+ for(Resource resource : oldModuleResources.getResources()){
+ getResourceDeployer(resource).validatePreservedResource(oldApp, newApp, resource, oldModuleResources);
+ }
+ }
+ }//else its a new module in the archive being redeployed.
+ }
+ }
+
+ /**
+ * clean up resources due to deployment failure.
+ * @param appName application-name
+ * @param deploymentPhase deployment-phase (deploy/load etc.,)
+ */
+ private void cleanupResources(String appName, OpsParams.Origin deploymentPhase){
+ try{
+ if (deploymentPhase == OpsParams.Origin.deploy || deploymentPhase == OpsParams.Origin.deploy_instance
+ || deploymentPhase == OpsParams.Origin.create_application_ref) {
+ Map<String, Resources> allResources = ResourcesRegistry.remove(appName);
+ if(allResources != null){
+ for(Map.Entry<String, Resources> entry : allResources.entrySet()){
+ String moduleName = entry.getKey();
+ Resources resources = entry.getValue();
+ String actualModuleName = moduleName;
+ //for app-scoped-resources, no module name is needed
+ if(appName.equals(moduleName)){
+ actualModuleName = null;
+ }
+ undeployResources(resources, appName, actualModuleName );
+ }
+ }
+ }else if(deploymentPhase == OpsParams.Origin.load){
+
+ Application application = applications.getApplication(appName);
+ if(application != null){
+ Resources appScopedResources = application.getResources();
+ undeployResources(appScopedResources, appName, null);
+
+ List<Module> modules = application.getModule();
+ if(modules != null){
+ for(Module module : modules){
+ Resources moduleScopedResources = module.getResources();
+ undeployResources(moduleScopedResources, appName, module.getName());
+ }
+ }
+ }
+ }
+ }catch(Exception e){
+ _logger.log(Level.WARNING, "Exception while cleaning-up resources during deployment failure", e);
+ }
+ }
+
+ private void undeployResources(Resources resources, String appName, String moduleName) {
+
+ if(resources != null){
+ for(Resource resource : resources.getResources()){
+ try{
+ //delete pools after resources
+ if(!(resource instanceof ResourcePool)){
+ getResourceDeployer(resource).undeployResource(resource, appName, moduleName);
+ }
+ }catch(Exception e){
+ //ignore as this is cleanup
+ }
+ }
+ Collection<ResourcePool> pools= resources.getResources(ResourcePool.class);
+ for(ResourcePool pool : pools){
+ try{
+ getResourceDeployer(pool).undeployResource(pool, appName, moduleName);
+ }catch(Exception e){
+ //ignore as this is cleanup
+ }
+ }
+ }
+ }
+
+ private void cleanupPreservedResources(DeploymentContext dc, Event event) {
+ if (Deployment.DEPLOYMENT_FAILURE.equals(event.type())) {
+ final DeployCommandParameters deployCommandParameters =
+ dc.getCommandParameters(DeployCommandParameters.class);
+ if (deployCommandParameters.origin == OpsParams.Origin.deploy ||
+ deployCommandParameters.origin == OpsParams.Origin.deploy_instance ||
+ deployCommandParameters.origin == OpsParams.Origin.create_application_ref) {
+ Properties properties = deployCommandParameters.properties;
+ String appName = deployCommandParameters.name();
+ cleanupPreservedResources(appName, properties);
+ }
+ } else if (Deployment.UNDEPLOYMENT_FAILURE.equals(event.type())) {
+ final UndeployCommandParameters undeployCommandParameters =
+ dc.getCommandParameters(UndeployCommandParameters.class);
+ if (undeployCommandParameters.origin == OpsParams.Origin.undeploy) {
+ Properties properties = undeployCommandParameters.properties;
+ String appName = undeployCommandParameters.name();
+ cleanupPreservedResources(appName, properties);
+ }
+ }
+ }
+
+ private void cleanupPreservedResources(String appName, Properties properties) {
+ if(properties != null){
+ String preserve = properties.getProperty(DeploymentProperties.PRESERVE_APP_SCOPED_RESOURCES);
+ if(preserve != null && Boolean.valueOf(preserve)){
+ ResourcesRegistry.remove(appName);
+ preservedApps.remove(appName);
+ }
+ }
+ }
+
+
+ /**
+ * preserve the old application's resources so that they can be registered during deploy.
+ * @param dc DeploymentContext
+ * @param undeployCommandParameters undeploy command parameters
+ */
+ private void preserveResources(DeploymentContext dc, UndeployCommandParameters undeployCommandParameters) {
+ try{
+ if (undeployCommandParameters.origin == OpsParams.Origin.undeploy) {
+ Properties properties = undeployCommandParameters.properties;
+ if(properties != null){
+ String preserve = properties.getProperty(DeploymentProperties.PRESERVE_APP_SCOPED_RESOURCES);
+ if(preserve != null && Boolean.valueOf(preserve)){
+ debug("Preserve app scoped resources enabled");
+ final UndeployCommandParameters commandParams =
+ dc.getCommandParameters(UndeployCommandParameters.class);
+ String appName = commandParams.name();
+ Application app = applications.getApplication(appName);
+ preserveResources(app);
+ //store application info (for module information ie., sniffer type)
+ preservedApps.put(appName, app);
+ }
+ }
+ }
+ }catch(Exception e){
+ // only DeploymentExceptions are propagated and result in deployment failure
+ // in the event notification infrastructure
+ throw new DeploymentException(e.getMessage(), e);
+ }
+ }
+
+ private void preserveResources(Application app) {
+ String appName = app.getName();
+ Map<String, Resources> allResources = new HashMap<String, Resources>();
+ Resources appScopedResources = app.getResources();
+ if(appScopedResources != null){
+ allResources.put(appName, appScopedResources);
+ }
+ List<Module> modules = app.getModule();
+ if(modules != null){
+ for(Module module : modules){
+ Resources moduleScopedResources = module.getResources();
+ if(moduleScopedResources != null){
+ allResources.put(module.getName(), moduleScopedResources);
+ }
+ }
+ }
+ //store the resource-configuration
+ ResourcesRegistry.putResources(appName, allResources);
+ }
+
+ private static void debug(String message){
+ if(_logger.isLoggable(Level.FINEST)) {
+ _logger.finest("[ASR] ResourceDeployer : " + message);
+ }
+ }
+}