All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.mycontainer.ejb.StatelessDeployer Maven / Gradle / Ivy

There is a newer version: 1.7.5
Show newest version
/*
 * Copyright 2008 Whohoo Licensed 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 com.googlecode.mycontainer.ejb;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;


import com.googlecode.mycontainer.annotation.MycontainerLocalBinding;
import com.googlecode.mycontainer.kernel.deploy.DefaultIntercetorDeployer;
import com.googlecode.mycontainer.kernel.deploy.DeployException;
import com.googlecode.mycontainer.kernel.deploy.NamingAliasDeployer;
import com.googlecode.mycontainer.kernel.naming.MyNameParser;
import com.googlecode.mycontainer.kernel.naming.ObjectProvider;
import com.googlecode.mycontainer.kernel.reflect.proxy.ContextInterceptor;
import com.googlecode.mycontainer.kernel.reflect.proxy.ProxyEngine;

public class StatelessDeployer extends SessionBeanDeployer implements
		ObjectProvider {

	private static final long serialVersionUID = 6140595848352213485L;

	private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory
			.getLogger(StatelessDeployer.class);

	private Class resource;

	private Class api;

	private String intercetorDeployerName = SessionInterceptorDeployer.DEFAULT_NAME;

	public String getIntercetorDeployerName() {
		return intercetorDeployerName;
	}

	public void setIntercetorDeployerName(String intercetorDeployerName) {
		this.intercetorDeployerName = intercetorDeployerName;
	}

	public void config(Class resource) {
		Stateless stateless = resource.getAnnotation(Stateless.class);
		if (stateless == null) {
			throw new DeployException("@Stateless not found");
		}
		this.resource = resource;
		resolveInterface();

	}

	@SuppressWarnings("unchecked")
	private void resolveInterface() {
		this.api = null;
		resolveBeanLocalInterface();
		if (this.api != null) {
			return;
		}
		List> interfaces = getInterfaces();
		if (interfaces.isEmpty()) {
			throw new DeployException(
					"The bean must need some interface or @Local: "
							+ resource.getName());
		}
		if (interfaces.size() == 1) {
			this.api = (Class) interfaces.get(0);
			return;
		}
		int i = 0;
		while (i < interfaces.size()) {
			Class clazz = interfaces.get(i);
			if (clazz.getAnnotation(Local.class) == null) {
				interfaces.remove(i);
			} else {
				i++;
			}
		}
		if (interfaces.isEmpty()) {
			throw new DeployException(
					"Multiples interfaces, all without @Local: "
							+ resource.getName());
		}
		if (interfaces.size() > 1) {
			throw new DeployException("Multiples interfaces with @Local: "
					+ resource.getName());
		}
		this.api = (Class) interfaces.get(0);
	}

	private List> getInterfaces() {
		Class[] interfaces = resource.getInterfaces();
		List> ret = new ArrayList>();
		for (Class clazz : interfaces) {
			if (isValidInterface(clazz)) {
				ret.add(clazz);
			}
		}
		return ret;
	}

	@SuppressWarnings("unchecked")
	private void resolveBeanLocalInterface() {
		Local local = resource.getAnnotation(Local.class);
		if (local != null) {
			if (local.value() == null || local.value().length == 0) {
				throw new RuntimeException(
						"@Local used in the bean need one argument");
			}
			this.api = local.value()[0];
		}
	}

	private boolean isValidInterface(Class clazz) {
		boolean ret = !Serializable.class.isAssignableFrom(clazz)
				&& !Cloneable.class.isAssignableFrom(clazz);
		if (!ret) {
			return ret;
		}
		ret = !clazz.getName().startsWith("javax.ejb.");
		return ret;
	}

	public Object provide(Name name) {
		try {
			Context ctx = getContext();
			Object impl = resource.newInstance();
			ProxyEngine engine = new ProxyEngine(api, impl,
					getSessionContextName());
			engine.addInterface(StatelessCallback.class);

			DefaultIntercetorDeployer interceptors = (DefaultIntercetorDeployer) ctx
					.lookup(intercetorDeployerName);
			List list = interceptors.createInterceptors();
			for (ContextInterceptor contextInterceptor : list) {
				engine.addInterceptor(contextInterceptor);
			}

			StatelessCallback ret = (StatelessCallback) engine.create();
			ret.ejbPreConstruct();
			ret.ejbPostConstruct();

			return ret;
		} catch (InstantiationException e) {
			throw new DeployException(e);
		} catch (IllegalAccessException e) {
			throw new DeployException(e);
		} catch (NamingException e) {
			throw new DeployException(e);
		}
	}

	public String getName() {
		String name = resource.getSimpleName() + "/local";
		MycontainerLocalBinding localBinding = resource
				.getAnnotation(MycontainerLocalBinding.class);
		if (localBinding != null) {
			name = localBinding.value();
		}
		return name;
	}

	public static boolean isStateless(Class clazz) {
		return (clazz.getAnnotation(Stateless.class) != null);
	}

	@SuppressWarnings("unchecked")
	@Override
	public void deploy(Class resource) {
		try {
			Context ctx = getContext();

			config((Class) resource);
			String name = getName();
			LOG.info("Deploying: " + name + " " + resource.getSimpleName());
			String sessionContextName = getSessionContextName();
			ctx.createSubcontext(sessionContextName);
			ctx.bind(name, this);
			getKernel().addShutdownHook(this);

			String alias = MyNameParser.parseClassName("ejb", api);
			if (!name.equals(alias)) {
				new NamingAliasDeployer(ctx, alias, name).deploy();
			}

		} catch (NamingException e) {
			throw new DeployException(e);
		}
	}

	private String getSessionContextName() {
		String name = getName();
		return "sessionContext/" + name;
	}

	public void shutdown() {
		try {
			Context ctx = getContext();
			String name = getName();
			LOG.info("Undeploying: " + name);
			ctx.unbind(name);
		} catch (NamingException e) {
			throw new DeployException(e);
		}
	}

}