/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
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, 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<org.glassfish.resources.api.Resource> nonConnectorResources =
ResourcesXMLParser.getNonConnectorResourcesList(list, false, true);
resourcesList.put(NON_CONNECTOR_RESOURCES, nonConnectorResources);
List<org.glassfish.resources.api.Resource> connectorResources =
ResourcesXMLParser.getConnectorResourcesList(list, false, true);
resourcesList.put(CONNECTOR_RESOURCES, connectorResources);
appScopedResources.put(moduleName, resourcesList);
}
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);
}
}
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);
}
}
}