public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    final Enhancer enhancer = new Enhancer();
    reader.moveDown();
    enhancer.setSuperclass((Class) context.convertAnother(null, Class.class));
    reader.moveUp();
    reader.moveDown();
    List interfaces = new ArrayList();
    while (reader.hasMoreChildren()) {
      reader.moveDown();
      interfaces.add(context.convertAnother(null, mapper.realClass(reader.getNodeName())));
      reader.moveUp();
    }
    enhancer.setInterfaces((Class[]) interfaces.toArray(new Class[interfaces.size()]));
    reader.moveUp();
    reader.moveDown();
    boolean useFactory = Boolean.valueOf(reader.getValue()).booleanValue();
    enhancer.setUseFactory(useFactory);
    reader.moveUp();

    List callbacksToEnhance = new ArrayList();
    List callbacks = new ArrayList();
    Map callbackIndexMap = null;
    reader.moveDown();
    if ("callbacks".equals(reader.getNodeName())) {
      reader.moveDown();
      callbackIndexMap = (Map) context.convertAnother(null, HashMap.class);
      reader.moveUp();
      while (reader.hasMoreChildren()) {
        reader.moveDown();
        readCallback(reader, context, callbacksToEnhance, callbacks);
        reader.moveUp();
      }
    } else {
      readCallback(reader, context, callbacksToEnhance, callbacks);
    }
    enhancer.setCallbacks(
        (Callback[]) callbacksToEnhance.toArray(new Callback[callbacksToEnhance.size()]));
    if (callbackIndexMap != null) {
      enhancer.setCallbackFilter(new ReverseEngineeredCallbackFilter(callbackIndexMap));
    }
    reader.moveUp();
    Object result = null;
    while (reader.hasMoreChildren()) {
      reader.moveDown();
      if (reader.getNodeName().equals("serialVersionUID")) {
        enhancer.setSerialVersionUID(Long.valueOf(reader.getValue()));
      } else if (reader.getNodeName().equals("instance")) {
        result = create(enhancer, callbacks, useFactory);
        super.doUnmarshalConditionally(result, reader, context);
      }
      reader.moveUp();
    }
    if (result == null) {
      result = create(enhancer, callbacks, useFactory);
    }
    return serializationMethodInvoker.callReadResolve(result);
  }
  private Object createServiceInterfaceProxy(
      String serviceInterfaceClassName,
      Map seiPortNameToFactoryMap,
      Map seiClassNameToFactoryMap,
      ClassLoader classLoader)
      throws NamingException {
    boolean initialize = (this.serviceConstructor == null);

    if (initialize) {
      Class serviceInterface;
      try {
        serviceInterface = classLoader.loadClass(serviceInterfaceClassName);
      } catch (ClassNotFoundException e) {
        throw (NamingException)
            new NamingException(
                    "Could not load service interface class " + serviceInterfaceClassName)
                .initCause(e);
      }

      // create method interceptors
      Callback callback = new ServiceMethodInterceptor(seiPortNameToFactoryMap);
      this.methodInterceptors = new Callback[] {NoOp.INSTANCE, callback};

      // create service class
      Enhancer enhancer = new Enhancer();
      enhancer.setClassLoader(classLoader);
      enhancer.setSuperclass(ServiceImpl.class);
      enhancer.setInterfaces(new Class[] {serviceInterface});
      enhancer.setCallbackFilter(new NoOverrideCallbackFilter(Service.class));
      enhancer.setCallbackTypes(new Class[] {NoOp.class, MethodInterceptor.class});
      enhancer.setUseFactory(false);
      enhancer.setUseCache(false);
      this.enhancedServiceClass = enhancer.createClass();

      // get constructor
      this.serviceConstructor =
          FastClass.create(this.enhancedServiceClass).getConstructor(SERVICE_CONSTRUCTOR_TYPES);
    }

    // associate the method interceptors with the generated service class on the current thread
    Enhancer.registerCallbacks(this.enhancedServiceClass, this.methodInterceptors);

    Object[] arguments = new Object[] {seiPortNameToFactoryMap, seiClassNameToFactoryMap};

    Object serviceInstance = null;

    try {
      serviceInstance = this.serviceConstructor.newInstance(arguments);
    } catch (InvocationTargetException e) {
      throw (NamingException)
          new NamingException("Could not construct service instance")
              .initCause(e.getTargetException());
    }

    if (initialize) {
      for (Iterator iterator = seiPortNameToFactoryMap.values().iterator(); iterator.hasNext(); ) {
        SeiFactoryImpl seiFactory = (SeiFactoryImpl) iterator.next();
        try {
          seiFactory.initialize(serviceInstance, classLoader);
        } catch (ClassNotFoundException e) {
          throw (NamingException)
              new NamingException("Could not load service interface class; " + e.getMessage())
                  .initCause(e);
        }
      }
    }

    return serviceInstance;
  }