public static <X> Class<X> gen(Class<X> cl) {
    if (Modifier.isFinal(cl.getModifiers())) return cl;
    if (HandleAware.class.isAssignableFrom(cl)) return cl;

    SerializationAdapter<X> gen = new SerializationAdapter<X>(cl);

    Class<X> proxyClass = gen.generateProxy();

    return proxyClass;
  }
  /** Binds parameters */
  private CandiProducer<X> build() {
    Thread thread = Thread.currentThread();
    ClassLoader oldLoader = thread.getContextClassLoader();

    try {
      thread.setContextClassLoader(getBeanManager().getClassLoader());

      introspect();

      Class<X> cl = (Class<X>) _annotatedType.getBaseType();

      if (_beanCtor == null) {
        // XXX:
        AnnotatedType<X> beanType = _annotatedType;

        if (beanType == null) beanType = ReflectionAnnotatedFactory.introspectType(cl);

        introspectConstructor(beanType);
      }

      Class<X> instanceClass = null;

      if (_isGenerateInterception) {
        if (!_annotatedType.isAnnotationPresent(javax.interceptor.Interceptor.class)
            && !_annotatedType.isAnnotationPresent(javax.decorator.Decorator.class)) {
          CandiBeanGenerator<X> bean = new CandiBeanGenerator<X>(getBeanManager(), _annotatedType);
          bean.introspect();

          instanceClass = (Class<X>) bean.generateClass();
        }

        if (instanceClass == cl && isSerializeHandle()) {
          instanceClass = SerializationAdapter.gen(instanceClass);
        }
      }

      if (instanceClass != null && instanceClass != _instanceClass) {
        try {
          if (_javaCtor != null) {
            _javaCtor =
                (Constructor<X>) getConstructor(instanceClass, _javaCtor.getParameterTypes());
            _javaCtor.setAccessible(true);
          }
        } catch (Exception e) {
          // server/2423
          log.log(Level.FINE, e.toString(), e);
          // throw ConfigException.create(e);
        }
      }

      ConfigProgram[] injectProgram = introspectInject(_annotatedType);
      ConfigProgram[] initProgram = introspectPostConstruct(_annotatedType);

      ArrayList<ConfigProgram> destroyList = new ArrayList<ConfigProgram>();
      introspectDestroy(destroyList, _annotatedType);
      ConfigProgram[] destroyProgram = new ConfigProgram[destroyList.size()];
      destroyList.toArray(destroyProgram);

      Arg[] args = null;

      if (_beanCtor != null) args = introspectArguments(_beanCtor, _beanCtor.getParameters());

      CandiProducer<X> producer =
          new CandiProducer<X>(
              _bean,
              instanceClass,
              _javaCtor,
              args,
              injectProgram,
              initProgram,
              destroyProgram,
              _injectionPointSet);

      return producer;
    } finally {
      thread.setContextClassLoader(oldLoader);
    }
  }