@Test
	public void testExtendedResourceInjectionWithOverriding() {
		DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
		CommonAnnotationBeanPostProcessor bpp = new CommonAnnotationBeanPostProcessor();
		bpp.setBeanFactory(bf);
		bf.addBeanPostProcessor(bpp);
		bf.registerResolvableDependency(BeanFactory.class, bf);

		PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
		Properties props = new Properties();
		props.setProperty("tb", "testBean3");
		ppc.setProperties(props);
		ppc.postProcessBeanFactory(bf);

		RootBeanDefinition annotatedBd = new RootBeanDefinition(ExtendedResourceInjectionBean.class);
		TestBean tb5 = new TestBean();
		annotatedBd.getPropertyValues().add("testBean2", tb5);
		bf.registerBeanDefinition("annotatedBean", annotatedBd);
		bf.registerBeanDefinition("annotatedBean2", new RootBeanDefinition(NamedResourceInjectionBean.class));
		TestBean tb = new TestBean();
		bf.registerSingleton("testBean", tb);
		TestBean tb2 = new TestBean();
		bf.registerSingleton("testBean2", tb2);
		TestBean tb3 = new TestBean();
		bf.registerSingleton("testBean3", tb3);
		TestBean tb4 = new TestBean();
		bf.registerSingleton("testBean4", tb4);
		NestedTestBean tb6 = new NestedTestBean();
		bf.registerSingleton("xy", tb6);

		ExtendedResourceInjectionBean bean = (ExtendedResourceInjectionBean) bf.getBean("annotatedBean");
		assertTrue(bean.initCalled);
		assertTrue(bean.init2Called);
		assertSame(tb, bean.getTestBean());
		assertSame(tb5, bean.getTestBean2());
		assertSame(tb4, bean.getTestBean3());
		assertSame(tb3, bean.getTestBean4());
		assertSame(tb6, bean.testBean5);
		assertSame(tb6, bean.testBean6);
		assertSame(bf, bean.beanFactory);

		try {
			bf.getBean("annotatedBean2");
		}
		catch (BeanCreationException ex) {
			assertTrue(ex.getRootCause() instanceof NoSuchBeanDefinitionException);
			NoSuchBeanDefinitionException innerEx = (NoSuchBeanDefinitionException) ex.getRootCause();
			assertEquals("testBean9", innerEx.getBeanName());
		}

		bf.destroySingletons();
		assertTrue(bean.destroyCalled);
		assertTrue(bean.destroy2Called);
	}
  @SuppressWarnings("resource")
  @Before
  public void setup() throws Exception {
    DefaultListableBeanFactory dlbf = new DefaultListableBeanFactory();
    dlbf.registerSingleton("mvcValidator", testValidator());
    GenericApplicationContext ctx = new GenericApplicationContext(dlbf);
    ctx.refresh();
    this.resolver =
        new PayloadArgumentResolver(
            ctx, new MethodParameterConverter(new ObjectMapper(), new GenericConversionService()));
    this.payloadMethod =
        getClass()
            .getDeclaredMethod(
                "handleMessage",
                String.class,
                String.class,
                String.class,
                String.class,
                String.class,
                String.class,
                String.class,
                Integer.class);

    this.paramAnnotated = getMethodParameter(this.payloadMethod, 0);
    this.paramAnnotatedNotRequired = getMethodParameter(this.payloadMethod, 1);
    this.paramAnnotatedRequired = getMethodParameter(this.payloadMethod, 2);
    this.paramWithSpelExpression = getMethodParameter(this.payloadMethod, 3);
    this.paramValidated = getMethodParameter(this.payloadMethod, 4);
    this.paramValidated.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
    this.paramValidatedNotAnnotated = getMethodParameter(this.payloadMethod, 5);
    this.paramNotAnnotated = getMethodParameter(this.payloadMethod, 6);
  }
  @SuppressWarnings({"rawtypes", "unchecked"})
  public void testRegisterNotificationListenerWithObjectNameBeforeBeanNameMappedToSameBeanInstance()
      throws Exception {
    String beanName = "testBean";
    ObjectName objectName = ObjectName.getInstance("spring:name=Test");

    SelfNamingTestBean testBean = new SelfNamingTestBean();
    testBean.setObjectName(objectName);

    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    factory.registerSingleton(beanName, testBean);

    Map<String, Object> beans = new HashMap<String, Object>();
    beans.put(beanName, testBean);

    Map listenerMappings = new HashMap();
    CountingAttributeChangeNotificationListener listener =
        new CountingAttributeChangeNotificationListener();
    listenerMappings.put(objectName, listener);
    listenerMappings.put(beanName, listener);

    MBeanExporter exporter = new MBeanExporter();
    exporter.setServer(server);
    exporter.setBeans(beans);
    exporter.setNotificationListenerMappings(listenerMappings);
    exporter.setBeanFactory(factory);
    exporter.afterPropertiesSet();
    assertIsRegistered("Should have registered MBean", objectName);

    server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
    assertEquals("Listener should have been notified exactly once", 1, listener.getCount("Age"));
  }
  private boolean reconfigureBean(
      DefaultListableBeanFactory beanFactory, Class<?> beanClass, String beanName) {
    Object serviceConnector = this.cloud.getSingletonServiceConnector(beanClass, null);
    beanFactory.registerSingleton(getServiceBeanName(), serviceConnector);
    beanFactory.removeBeanDefinition(beanName);
    beanFactory.registerAlias(getServiceBeanName(), beanName);

    return true;
  }
	@Test
	public void testResourceInjectionWithDefaultMethod() {
		DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
		CommonAnnotationBeanPostProcessor bpp = new CommonAnnotationBeanPostProcessor();
		bpp.setBeanFactory(bf);
		bf.addBeanPostProcessor(bpp);
		bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(DefaultMethodResourceInjectionBean.class));
		TestBean tb2 = new TestBean();
		bf.registerSingleton("testBean2", tb2);
		NestedTestBean tb7 = new NestedTestBean();
		bf.registerSingleton("testBean7", tb7);

		DefaultMethodResourceInjectionBean bean = (DefaultMethodResourceInjectionBean) bf.getBean("annotatedBean");
		assertSame(tb2, bean.getTestBean2());
		assertSame(2, bean.counter);

		bf.destroySingletons();
		assertSame(3, bean.counter);
	}
	@Test
	public void testResourceInjection() {
		DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
		CommonAnnotationBeanPostProcessor bpp = new CommonAnnotationBeanPostProcessor();
		bpp.setResourceFactory(bf);
		bf.addBeanPostProcessor(bpp);
		bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ResourceInjectionBean.class));
		TestBean tb = new TestBean();
		bf.registerSingleton("testBean", tb);
		TestBean tb2 = new TestBean();
		bf.registerSingleton("testBean2", tb2);

		ResourceInjectionBean bean = (ResourceInjectionBean) bf.getBean("annotatedBean");
		assertTrue(bean.initCalled);
		assertTrue(bean.init2Called);
		assertTrue(bean.init3Called);
		assertSame(tb, bean.getTestBean());
		assertSame(tb2, bean.getTestBean2());
		bf.destroySingletons();
		assertTrue(bean.destroyCalled);
		assertTrue(bean.destroy2Called);
		assertTrue(bean.destroy3Called);
	}
	@Test
	public void testExtendedEjbInjection() {
		DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
		CommonAnnotationBeanPostProcessor bpp = new CommonAnnotationBeanPostProcessor();
		bpp.setBeanFactory(bf);
		bf.addBeanPostProcessor(bpp);
		bf.registerResolvableDependency(BeanFactory.class, bf);

		bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ExtendedEjbInjectionBean.class));
		TestBean tb = new TestBean();
		bf.registerSingleton("testBean", tb);
		TestBean tb2 = new TestBean();
		bf.registerSingleton("testBean2", tb2);
		TestBean tb3 = new TestBean();
		bf.registerSingleton("testBean3", tb3);
		TestBean tb4 = new TestBean();
		bf.registerSingleton("testBean4", tb4);
		NestedTestBean tb6 = new NestedTestBean();
		bf.registerSingleton("xy", tb6);
		bf.registerAlias("xy", "testBean9");

		ExtendedEjbInjectionBean bean = (ExtendedEjbInjectionBean) bf.getBean("annotatedBean");
		assertTrue(bean.initCalled);
		assertTrue(bean.init2Called);
		assertSame(tb, bean.getTestBean());
		assertSame(tb2, bean.getTestBean2());
		assertSame(tb4, bean.getTestBean3());
		assertSame(tb3, bean.getTestBean4());
		assertSame(tb6, bean.testBean5);
		assertSame(tb6, bean.testBean6);
		assertSame(bf, bean.beanFactory);

		bf.destroySingletons();
		assertTrue(bean.destroyCalled);
		assertTrue(bean.destroy2Called);
	}
  protected ApplicationContext prepareParentContext(final AcServiceConfig serviceConfig)
      throws AcServiceException {
    AcCoreContext coreContext = serviceConfig.getCoreContext();
    GenericApplicationContext parentContext = new GenericApplicationContext();
    DefaultListableBeanFactory beanFactory = parentContext.getDefaultListableBeanFactory();

    // add service config
    beanFactory.registerSingleton(AcServiceConfig.SERVICE_CONFIG_BEAN_NAME, serviceConfig);

    // add core context
    beanFactory.registerSingleton(AcServiceConfig.CORE_CONTEXT_BEAN_NAME, coreContext);

    // add session
    beanFactory.registerSingleton(AcServiceConfig.SESSION_BEAN_NAME, coreContext.getSession());

    // add profile
    beanFactory.registerSingleton(
        AcServiceConfig.PROFILE_BEAN_NAME, coreContext.getSession().getProfile());

    // add data repository
    beanFactory.registerSingleton(
        AcServiceConfig.REPOSITORY_BEAN_NAME, coreContext.getDataRepository());

    // add service preferences
    beanFactory.registerSingleton(
        AcServiceConfig.PREFERENCES_BEAN_NAME, serviceConfig.getServicePreferences());

    // add dictionary
    beanFactory.registerSingleton(
        AcServiceConfig.DICTIONARY_BEAN_NAME,
        coreContext.getSession().getProfile().getDictionary());

    for (String serviceClassName : metadata().getDependsServiceClassNames()) {
      try {
        AcService dependService = coreContext.getServiceByClassName(serviceClassName);
        beanFactory.registerSingleton(serviceClassName, dependService);
      } catch (Exception e) {
        throw new AcServiceException("load depend service error: " + serviceClassName, e);
      }
    }

    // ready for parent context
    parentContext.refresh();
    return parentContext;
  }
  @SuppressWarnings({"rawtypes", "unchecked"})
  public void testRegisterNotificationListenerWithTwoBeanNamesMappedToDifferentBeanInstances()
      throws Exception {
    String beanName1 = "testBean1";
    String beanName2 = "testBean2";

    ObjectName objectName1 = ObjectName.getInstance("spring:name=Test1");
    ObjectName objectName2 = ObjectName.getInstance("spring:name=Test2");

    SelfNamingTestBean testBean1 = new SelfNamingTestBean();
    testBean1.setObjectName(objectName1);

    SelfNamingTestBean testBean2 = new SelfNamingTestBean();
    testBean2.setObjectName(objectName2);

    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    factory.registerSingleton(beanName1, testBean1);
    factory.registerSingleton(beanName2, testBean2);

    Map<String, Object> beans = new HashMap<String, Object>();
    beans.put(beanName1, testBean1);
    beans.put(beanName2, testBean2);

    Map listenerMappings = new HashMap();
    CountingAttributeChangeNotificationListener listener =
        new CountingAttributeChangeNotificationListener();
    listenerMappings.put(beanName1, listener);
    listenerMappings.put(beanName2, listener);

    MBeanExporter exporter = new MBeanExporter();
    exporter.setServer(server);
    exporter.setBeans(beans);
    exporter.setNotificationListenerMappings(listenerMappings);
    exporter.setBeanFactory(factory);
    exporter.afterPropertiesSet();
    assertIsRegistered("Should have registered MBean", objectName1);
    assertIsRegistered("Should have registered MBean", objectName2);

    server.setAttribute(
        ObjectNameManager.getInstance(objectName1), new Attribute("Age", new Integer(77)));
    assertEquals("Listener not notified for testBean1", 1, listener.getCount("Age"));

    server.setAttribute(
        ObjectNameManager.getInstance(objectName2), new Attribute("Age", new Integer(33)));
    assertEquals("Listener not notified for testBean2", 2, listener.getCount("Age"));
  }
	@Test
	public void testExtendedResourceInjection() {
		DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
		CommonAnnotationBeanPostProcessor bpp = new CommonAnnotationBeanPostProcessor();
		bpp.setBeanFactory(bf);
		bf.addBeanPostProcessor(bpp);
		bf.registerResolvableDependency(BeanFactory.class, bf);

		PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
		Properties props = new Properties();
		props.setProperty("tb", "testBean3");
		ppc.setProperties(props);
		ppc.postProcessBeanFactory(bf);

		bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ExtendedResourceInjectionBean.class));
		bf.registerBeanDefinition("annotatedBean2", new RootBeanDefinition(NamedResourceInjectionBean.class));
		bf.registerBeanDefinition("annotatedBean3", new RootBeanDefinition(ConvertedResourceInjectionBean.class));
		TestBean tb = new TestBean();
		bf.registerSingleton("testBean", tb);
		TestBean tb2 = new TestBean();
		bf.registerSingleton("testBean2", tb2);
		TestBean tb3 = new TestBean();
		bf.registerSingleton("testBean3", tb3);
		TestBean tb4 = new TestBean();
		bf.registerSingleton("testBean4", tb4);
		NestedTestBean tb6 = new NestedTestBean();
		bf.registerSingleton("value", "5");
		bf.registerSingleton("xy", tb6);
		bf.registerAlias("xy", "testBean9");

		ExtendedResourceInjectionBean bean = (ExtendedResourceInjectionBean) bf.getBean("annotatedBean");
		assertTrue(bean.initCalled);
		assertTrue(bean.init2Called);
		assertSame(tb, bean.getTestBean());
		assertSame(tb2, bean.getTestBean2());
		assertSame(tb4, bean.getTestBean3());
		assertSame(tb3, bean.getTestBean4());
		assertSame(tb6, bean.testBean5);
		assertSame(tb6, bean.testBean6);
		assertSame(bf, bean.beanFactory);

		NamedResourceInjectionBean bean2 = (NamedResourceInjectionBean) bf.getBean("annotatedBean2");
		assertSame(tb6, bean2.testBean);

		ConvertedResourceInjectionBean bean3 = (ConvertedResourceInjectionBean) bf.getBean("annotatedBean3");
		assertSame(5, bean3.value);

		bf.destroySingletons();
		assertTrue(bean.destroyCalled);
		assertTrue(bean.destroy2Called);
	}
 @Before
 public void setup() {
   beanFactory = new DefaultListableBeanFactory();
   channelResolver = new BeanFactoryChannelResolver(beanFactory);
   beanFactory.registerSingleton("c", testChannel);
 }
 /**
  * @author:shaochuan.wangsc
  * @date:2010-3-24
  */
 private void scan(WebModuleConfigurer webModuleConfigurer) {
   try {
     String pattern =
         ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
             + ClassUtils.convertClassNameToResourcePath(
                 webModuleConfigurer.getModuleBasePackage())
             + webModuleConfigurer.getContextPackage()
             + RESOURCE_PATTERN;
     Resource[] resources = this.resourcePatternResolver.getResources(pattern);
     MetadataReaderFactory readerFactory =
         new CachingMetadataReaderFactory(this.resourcePatternResolver);
     //
     for (Resource resource : resources) {
       if (resource.isReadable()) {
         MetadataReader reader = readerFactory.getMetadataReader(resource);
         ClassMetadata classMetadata = reader.getClassMetadata();
         //
         if (classMetadata.isConcrete()) {
           String className = classMetadata.getClassName();
           if (!(BeanUtils.isWidget(className) || BeanUtils.isController(className))) {
             continue;
           }
           //
           AutowireCapableBeanFactory beanFactory =
               applicationContext.getAutowireCapableBeanFactory();
           Object clazz =
               beanFactory.createBean(
                   classLoader.loadClass(className),
                   AutowireCapableBeanFactory.AUTOWIRE_NO,
                   false);
           //
           if (clazz instanceof FreeMarkerWidget) {
             String widget = className.replace(webModuleConfigurer.getModuleBasePackage(), "");
             widget = ClassUtils.convertClassNameToResourcePath(widget);
             widget = BeanUtils.stripEndString(widget, BeanUtils.WIDGET_BEAN_SUFFIX);
             String widgetKey = BeanUtils.makeControllerOrWidgetMappingKey(widget);
             webModuleConfigurer.getWidgetMap().put(widgetKey, (FreeMarkerWidget) clazz);
             widgets.put(widgetKey, (FreeMarkerWidget) clazz);
           }
           //
           if (clazz instanceof Controller) {
             String controller = className.replace(webModuleConfigurer.getModuleBasePackage(), "");
             controller = ClassUtils.convertClassNameToResourcePath(controller);
             controller = BeanUtils.stripEndString(controller, BeanUtils.CONTROLLER_BEAN_SUFFIX);
             String controllerKey = BeanUtils.makeControllerOrWidgetMappingKey(controller);
             String controllerRule =
                 webModuleConfigurer.getContextPackage() + CONTROLLERS_PACKAGE + SLASH;
             if (controllerKey.startsWith(controllerRule)) {
               //
               controllerKey =
                   controllerKey.replaceFirst(controllerRule, webModuleConfigurer.getContext());
               //
               if ("/index".equals(controllerKey)) {
                 webModuleConfigurer.getControllerMap().put("/", (Controller) clazz);
                 controllers.put("/", (Controller) clazz);
                 defaultListableBeanFactory.registerSingleton("/", (Controller) clazz);
               }
               //
               String controller_key = BeanUtils.processControllerKey(controllerKey);
               String controller_keyv = controller_key + webModuleConfigurer.getUriExtension();
               //
               webModuleConfigurer.getControllerMap().put(controller_keyv, (Controller) clazz);
               controllers.put(controller_keyv, (Controller) clazz);
               defaultListableBeanFactory.registerSingleton(controller_keyv, (Controller) clazz);
             }
           }
         }
       }
     }
   } catch (IOException e) {
     logger.error("Failed to scan classpath for unlisted classes", e);
     throw new RuntimeException("Failed to scan classpath for unlisted classes", e);
   } catch (ClassNotFoundException e) {
     logger.error("Failed to load classes from classpath", e);
     throw new RuntimeException("Failed to load classes from classpath", e);
   }
 }
  @Test
  public void testReplyContainerRecovery() throws Exception {
    JmsOutboundGateway gateway = new JmsOutboundGateway();
    ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
    gateway.setConnectionFactory(connectionFactory);
    gateway.setRequestDestinationName("foo");
    gateway.setUseReplyContainer(true);
    ReplyContainerProperties replyContainerProperties = new ReplyContainerProperties();
    final List<Throwable> errors = new ArrayList<Throwable>();
    ErrorHandlingTaskExecutor errorHandlingTaskExecutor =
        new ErrorHandlingTaskExecutor(
            Executors.newFixedThreadPool(10),
            new ErrorHandler() {

              @Override
              public void handleError(Throwable t) {
                logger.info("Error:", t);
                errors.add(t);
                throw new RuntimeException(t);
              }
            });
    replyContainerProperties.setTaskExecutor(errorHandlingTaskExecutor);
    replyContainerProperties.setRecoveryInterval(100L);
    gateway.setReplyContainerProperties(replyContainerProperties);
    final Connection connection = mock(Connection.class);
    final AtomicInteger connectionAttempts = new AtomicInteger();
    doAnswer(
            new Answer<Connection>() {

              @SuppressWarnings("serial")
              @Override
              public Connection answer(InvocationOnMock invocation) throws Throwable {
                int theCount = connectionAttempts.incrementAndGet();
                if (theCount > 1 && theCount < 4) {
                  throw new JmsException("bar") {};
                }
                return connection;
              }
            })
        .when(connectionFactory)
        .createConnection();
    Session session = mock(Session.class);
    when(connection.createSession(false, 1)).thenReturn(session);
    MessageConsumer consumer = mock(MessageConsumer.class);
    when(session.createConsumer(any(Destination.class), anyString())).thenReturn(consumer);
    when(session.createTemporaryQueue()).thenReturn(mock(TemporaryQueue.class));
    final Message message = mock(Message.class);
    final AtomicInteger count = new AtomicInteger();
    doAnswer(
            new Answer<Message>() {

              @SuppressWarnings("serial")
              @Override
              public Message answer(InvocationOnMock invocation) throws Throwable {
                int theCount = count.incrementAndGet();
                if (theCount > 1 && theCount < 4) {
                  throw new JmsException("foo") {};
                }
                if (theCount > 4) {
                  Thread.sleep(100);
                  return null;
                }
                return message;
              }
            })
        .when(consumer)
        .receive(anyLong());
    when(message.getJMSCorrelationID()).thenReturn("foo");
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.initialize();
    beanFactory.registerSingleton("taskScheduler", taskScheduler);
    gateway.setBeanFactory(beanFactory);
    gateway.afterPropertiesSet();
    gateway.start();
    try {
      int n = 0;
      while (n++ < 100 && count.get() < 5) {
        Thread.sleep(100);
      }
      assertTrue(count.get() > 4);
      assertEquals(0, errors.size());
    } finally {
      gateway.stop();
    }
  }
  public static void main(String args[]) {
    try {
      DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

      // Define a bean and register it
      beanFactory.registerSingleton("args", Arrays.asList(args));
      GenericApplicationContext cmdArgCxt = new GenericApplicationContext(beanFactory);
      // Must call refresh to initialize context
      cmdArgCxt.refresh();

      String configs[] = {"/META-INF/spring/app-config.xml"};
      AbstractApplicationContext context = new ClassPathXmlApplicationContext(configs, cmdArgCxt);
      context.registerShutdownHook();
      Workflow workflow = (Workflow) context.getBean("workflow");
      System.out.println("Workflow names:");
      int i = 1;
      for (String name : workflow.getWorkflowNames()) {
        System.out.format("%02d) %s%n", i++, name);
      }

      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

      System.out.print("User: "******"caller", username);

      String command;
      do {
        try {
          System.out.print("Enter command: ");
          command = in.readLine();

          if (command == null || "q".equals(command) || "quit".equals(command)) break;

          if ("log".equals(command)) {
            System.out.print("User: "******"caller", username);
          }
          if ("init".equals(command)) {
            System.out.print("Workflow name: ");
            String workflowName = in.readLine();

            long id = workflow.initialize(workflowName, 1, inputs);
            System.out.println("Workflow initialized with id: " + id);
          } else if ("desc".equals(command)) {
            System.out.print("Workflow ID: ");
            long id = Long.parseLong(in.readLine());

            String workflowName = workflow.getWorkflowName(id);
            WorkflowDescriptor descriptor = workflow.getWorkflowDescriptor(workflowName);

            System.out.print("Workflow state: ");
            switch (workflow.getEntryState(id)) {
              case WorkflowEntry.CREATED:
                System.out.println("CREATED");
                break;
              case WorkflowEntry.ACTIVATED:
                System.out.println("ACTIVATED");
                break;
              case WorkflowEntry.SUSPENDED:
                System.out.println("SUSPENDED");
                break;
              case WorkflowEntry.KILLED:
                System.out.println("KILLED");
                break;
              case WorkflowEntry.COMPLETED:
                System.out.println("COMPLETED");
                break;
              default:
                System.out.println("UNKNOWN");
            }

            List<Step> currentSteps = workflow.getCurrentSteps(id);
            System.out.println("Current steps:");
            int j = 0;
            for (Step step : currentSteps) {
              ++j;
              StepDescriptor stepDesc = descriptor.getStep(step.getStepId());
              System.out.println("Meta attributes:");
              System.out.format("\t%s%n", stepDesc.getMetaAttributes().toString());
              System.out.format(
                  "%02d) %s (%s - %s)%n",
                  step.getStepId(), stepDesc.getName(), step.getStatus(), step.getOwner());
            }

            int[] availableActions = workflow.getAvailableActions(id, inputs);
            System.out.println("Available actions:");
            for (j = 0; j < availableActions.length; j++) {
              ActionDescriptor action = descriptor.getAction(availableActions[j]);
              System.out.println(String.format("%02d) %s", availableActions[j], action.getName()));
            }
          } else if ("exec".equals(command)) {
            System.out.print("Workflow ID: ");
            long id = Long.parseLong(in.readLine());
            System.out.print("Action ID: ");
            int actionId = Integer.parseInt(in.readLine());

            workflow.doAction(id, actionId, inputs);
          } else if ("query".equals(command)) {
            Set<WorkflowNameAndStep> stepInfos = new LinkedHashSet<WorkflowNameAndStep>();
            stepInfos.add(new WorkflowNameAndStep(1, "example"));
            stepInfos.add(new WorkflowNameAndStep(2, "sp3-moderation"));
            List ids = workflow.getWorkflowsByNamesAndSteps(stepInfos);
            System.out.println("Found ids are: " + ids);
          }
        } catch (Exception e) {
          e.printStackTrace();
        }

        System.out.println("-------------------------------------");
      } while (true);

      System.out.println("Exiting");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }