/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomee.catalina;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.assembler.classic.Assembler;
import org.apache.openejb.assembler.classic.ResourceInfo;
import org.apache.openejb.assembler.dynamic.PassthroughFactory;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.tomcat.util.descriptor.web.ContextEjb;
import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
import org.apache.tomcat.util.descriptor.web.ContextLocalEjb;
import org.apache.tomcat.util.descriptor.web.ContextResource;
import org.apache.tomcat.util.descriptor.web.ContextResourceEnvRef;
import org.apache.tomcat.util.descriptor.web.ContextResourceLink;
import org.apache.tomcat.util.descriptor.web.ResourceBase;
import javax.naming.Context;
import javax.naming.NamingException;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@SuppressWarnings({"UnusedDeclaration"})
public class OpenEJBNamingContextListener implements LifecycleListener, PropertyChangeListener {
private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB.createChild("tomcat"), "org.apache.openejb.util.resources");
/**
* Associated standardServer.
*/
private final StandardServer standardServer;
/**
* Has the listener been started?
*/
private boolean running;
/**
* Associated naming resources.
*/
private final NamingResourcesImpl namingResources;
public OpenEJBNamingContextListener(final StandardServer standardServer) {
this.standardServer = standardServer;
namingResources = standardServer.getGlobalNamingResources();
}
public void lifecycleEvent(final LifecycleEvent event) {
if (event.getLifecycle() != standardServer) {
return;
}
if (Lifecycle.START_EVENT.equals(event.getType())) {
start();
} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
stop();
}
}
public boolean isRunning() {
return running;
}
public void start() {
if (running) {
return;
}
namingResources.addPropertyChangeListener(this);
processInitialNamingResources();
running = true;
}
public void stop() {
if (!running) {
return;
}
namingResources.removePropertyChangeListener(this);
running = false;
}
public void propertyChange(final PropertyChangeEvent event) {
if (!running) {
return;
}
final Object source = event.getSource();
if (source == namingResources) {
processGlobalResourcesChange(event.getPropertyName(), event.getOldValue(), event.getNewValue());
}
}
/**
* Process a property change on the global naming resources, by making the
* corresponding addition or removal to OpenEJB.
*
* @param name Property name of the change to be processed
* @param oldValue The old value (or <code>null</code> if adding)
* @param newValue The new value (or <code>null</code> if removing)
*/
private void processGlobalResourcesChange(final String name, final Object oldValue, final Object newValue) {
// NOTE - It seems that the Context for global JNDI resources
// is left in read-write mode, so we do not have to change it here
if (name.equals("ejb")) {
if (oldValue != null) {
final ContextEjb ejb = (ContextEjb) oldValue;
if (ejb.getName() != null) {
removeEjb(ejb.getName());
}
}
if (newValue != null) {
final ContextEjb ejb = (ContextEjb) newValue;
if (ejb.getName() != null) {
addEjb(ejb);
}
}
} else if (name.equals("environment")) {
if (oldValue != null) {
final ContextEnvironment env = (ContextEnvironment) oldValue;
if (env.getName() != null) {
removeEnvironment(env.getName());
}
}
if (newValue != null) {
final ContextEnvironment env = (ContextEnvironment) newValue;
if (env.getName() != null) {
addEnvironment(env);
}
}
} else if (name.equals("localEjb")) {
if (oldValue != null) {
final ContextLocalEjb ejb = (ContextLocalEjb) oldValue;
if (ejb.getName() != null) {
removeLocalEjb(ejb.getName());
}
}
if (newValue != null) {
final ContextLocalEjb ejb = (ContextLocalEjb) newValue;
if (ejb.getName() != null) {
addLocalEjb(ejb);
}
}
} else if (name.equals("resource")) {
if (oldValue != null) {
final ContextResource resource = (ContextResource) oldValue;
if (resource.getName() != null) {
removeResource(resource.getName());
}
}
if (newValue != null) {
final ContextResource resource = (ContextResource) newValue;
if (resource.getName() != null) {
addResource(resource);
}
}
} else if (name.equals("resourceEnvRef")) {
if (oldValue != null) {
final ContextResourceEnvRef resourceEnvRef = (ContextResourceEnvRef) oldValue;
if (resourceEnvRef.getName() != null) {
removeResourceEnvRef(resourceEnvRef.getName());
}
}
if (newValue != null) {
final ContextResourceEnvRef resourceEnvRef = (ContextResourceEnvRef) newValue;
if (resourceEnvRef.getName() != null) {
addResourceEnvRef(resourceEnvRef);
}
}
} else if (name.equals("resourceLink")) {
if (oldValue != null) {
final ContextResourceLink rl = (ContextResourceLink) oldValue;
if (rl.getName() != null) {
removeResourceLink(rl.getName());
}
}
if (newValue != null) {
final ContextResourceLink rl = (ContextResourceLink) newValue;
if (rl.getName() != null) {
addResourceLink(rl);
}
}
}
}
private void processInitialNamingResources() {
// Resource links
final ContextResourceLink[] resourceLinks = namingResources.findResourceLinks();
for (final ContextResourceLink resourceLink : resourceLinks) {
addResourceLink(resourceLink);
}
// Resources
final ContextResource[] resources = namingResources.findResources();
for (final ContextResource resource : resources) {
addResource(resource);
}
// Resources Env
final ContextResourceEnvRef[] resourceEnvRefs = namingResources.findResourceEnvRefs();
for (final ContextResourceEnvRef resourceEnvRef : resourceEnvRefs) {
addResourceEnvRef(resourceEnvRef);
}
// Environment entries
final ContextEnvironment[] contextEnvironments = namingResources.findEnvironments();
for (final ContextEnvironment contextEnvironment : contextEnvironments) {
addEnvironment(contextEnvironment);
}
// EJB references
final ContextEjb[] ejbs = namingResources.findEjbs();
for (final ContextEjb ejb : ejbs) {
addEjb(ejb);
}
}
public void addEjb(final ContextEjb ejb) {
}
public void addEnvironment(final ContextEnvironment env) {
bindResource(env);
}
public void addLocalEjb(final ContextLocalEjb localEjb) {
}
public void addResource(final ContextResource resource) {
bindResource(resource);
}
public void addResourceEnvRef(final ContextResourceEnvRef resourceEnvRef) {
bindResource(resourceEnvRef);
}
private void bindResource(final ResourceBase res) {
try {
final Context globalNamingContext = standardServer.getGlobalNamingContext();
final Object value = globalNamingContext.lookup(res.getName());
final String type = res.getType();
bindResource(res.getName(), value, type);
} catch (final NamingException e) {
logger.error("Unable to lookup Global Tomcat resource " + res.getName(), e);
}
}
private void bindResource(final String name, final Object value, final String type) {
final Assembler assembler = (Assembler) SystemInstance.get().getComponent(org.apache.openejb.spi.Assembler.class);
try {
assembler.getContainerSystem().getJNDIContext().lookup(Assembler.OPENEJB_RESOURCE_JNDI_PREFIX + name);
return;
} catch (final NamingException ne) {
// no-op: OK
}
final ResourceInfo resourceInfo = new ResourceInfo();
resourceInfo.id = name;
resourceInfo.service = "Resource";
resourceInfo.types.add(type);
PassthroughFactory.add(resourceInfo, value);
logger.info("Importing a Tomcat Resource with id '" + resourceInfo.id + "' of type '" + type + "'.");
try {
assembler.createResource(null, resourceInfo);
} catch (final OpenEJBException e) {
logger.error("Unable to bind Global Tomcat resource " + name + " into OpenEJB", e);
}
}
public void addResourceLink(final ContextResourceLink resourceLink) {
}
public void removeEjb(final String name) {
}
public void removeEnvironment(final String name) {
}
public void removeLocalEjb(final String name) {
}
public void removeResource(final String name) {
// there isn't any way to remove a resource yet
}
public void removeResourceEnvRef(final String name) {
// there isn't any way to remove a resource yet
}
public void removeResourceLink(final String name) {
}
}