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

com.alibaba.dubbo.common.bytecode.Mixin Maven / Gradle / Ivy

/*
 * Copyright 1999-2011 Alibaba Group.
 *  
 * 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.alibaba.dubbo.common.bytecode;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import com.alibaba.dubbo.common.utils.ClassHelper;
import com.alibaba.dubbo.common.utils.ReflectUtils;

/**
 * Mixin
 * 
 * @author qian.lei
 */

public abstract class Mixin
{
	private static AtomicLong MIXIN_CLASS_COUNTER = new AtomicLong(0);

	private static final String PACKAGE_NAME = Mixin.class.getPackage().getName();

	public static interface MixinAware{ void setMixinInstance(Object instance); }

	/**
	 * mixin interface and delegates.
	 * all class must be public.
	 * 
	 * @param ics interface class array.
	 * @param dc delegate class.
	 * @return Mixin instance.
	 */
	public static Mixin mixin(Class[] ics, Class dc)
	{
		return mixin(ics, new Class[]{dc});
	}

	/**
	 * mixin interface and delegates.
	 * all class must be public.
	 * 
	 * @param ics interface class array.
	 * @param dc delegate class.
	 * @param cl class loader.
	 * @return Mixin instance.
	 */
	public static Mixin mixin(Class[] ics, Class dc, ClassLoader cl)
	{
		return mixin(ics, new Class[]{dc}, cl);
	}

	/**
	 * mixin interface and delegates.
	 * all class must be public.
	 * 
	 * @param ics interface class array.
	 * @param dcs delegate class array.
	 * @return Mixin instance.
	 */
	public static Mixin mixin(Class[] ics, Class[] dcs)
	{
		return mixin(ics, dcs, ClassHelper.getCallerClassLoader(Mixin.class));
	}

	/**
	 * mixin interface and delegates.
	 * all class must be public.
	 * 
	 * @param ics interface class array.
	 * @param dcs delegate class array.
	 * @param cl class loader.
	 * @return Mixin instance.
	 */
	public static Mixin mixin(Class[] ics, Class[] dcs, ClassLoader cl)
	{
		assertInterfaceArray(ics);

		long id = MIXIN_CLASS_COUNTER.getAndIncrement();
		String pkg = null;
		ClassGenerator ccp = null, ccm = null;
		try
		{
			ccp = ClassGenerator.newInstance(cl);

			// impl constructor
			StringBuilder code = new StringBuilder();
			for(int i=0;i[]{ Object[].class }, code.toString());

			// impl methods.
			Set worked = new HashSet();
			for(int i=0;i rt = method.getReturnType();
					String mn = method.getName();
					if( Void.TYPE.equals(rt) )
						ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(),
								"d" + ix + "." + mn + "($$);");
					else
						ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(),
								"return ($r)d" + ix + "." + mn + "($$);");
				}
			}

			if( pkg == null )
				pkg = PACKAGE_NAME;

			// create MixinInstance class.
			String micn = pkg + ".mixin" + id;
			ccp.setClassName(micn);
			ccp.toClass();

			// create Mixin class.
			String fcn = Mixin.class.getName() + id;
			ccm = ClassGenerator.newInstance(cl);
			ccm.setClassName(fcn);
			ccm.addDefaultConstructor();
			ccm.setSuperClass(Mixin.class.getName());
			ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }");
			Class mixin = ccm.toClass();
			return (Mixin)mixin.newInstance();
		}
		catch(RuntimeException e)
		{
			throw e;
		}
		catch(Exception e)
		{
			throw new RuntimeException(e.getMessage(), e);
		}
		finally
		{
			// release ClassGenerator
			if( ccp != null )
				ccp.release();
			if( ccm != null )
				ccm.release();
		}
	}

	/**
	 * new Mixin instance.
	 * 
	 * @param ds delegates instance.
	 * @return instance.
	 */
	abstract public Object newInstance(Object[] ds);

	protected Mixin(){}

	private static int findMethod(Class[] dcs, String desc)
	{
		Class cl;
		Method[] methods;
		for(int i=0;i[] ics)
	{
		for(int i=0;i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy