package act.handler.builtin.cli; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * 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. * #L% */ import act.Act; import act.app.App; import act.cli.CliContext; import act.cli.CliException; import act.cli.CommandExecutor; import act.cli.bytecode.ReflectedCommandExecutor; import act.cli.meta.CommandMethodMetaInfo; import act.cli.meta.CommanderClassMetaInfo; import act.handler.CliHandlerBase; import act.util.PropertySpec; import org.osgl.$; import org.osgl.logging.L; import org.osgl.logging.Logger; import org.osgl.util.S; import java.util.List; public final class CliHandlerProxy extends CliHandlerBase { private static Logger logger = L.get(CliHandlerProxy.class); private App app; private CommandMethodMetaInfo methodMetaInfo; private CommanderClassMetaInfo classMetaInfo; private volatile CommandExecutor executor = null; public CliHandlerProxy(CommanderClassMetaInfo classMetaInfo, CommandMethodMetaInfo metaInfo, App app) { this.methodMetaInfo = $.notNull(metaInfo); this.classMetaInfo = $.notNull(classMetaInfo); this.app = $.notNull(app); } @Override protected void releaseResources() { if (null != executor) { executor.destroy(); executor = null; } } public CommandMethodMetaInfo methodMetaInfo() { return methodMetaInfo; } public CommanderClassMetaInfo classMetaInfo() { return classMetaInfo; } @Override public boolean appliedIn(Act.Mode mode) { return mode == Act.Mode.DEV || mode == methodMetaInfo.mode(); } @Override public void handle(CliContext context) { try { ensureAgentsReady(); saveCommandPath(context); Object result = _handle(context); onResult(result, context); } catch ($.Break b) { throw b; } catch (CliException error) { context.println(error.getMessage()); } catch (Exception e) { String msg = e.getMessage(); if (S.blank(msg)) { msg = S.fmt("Error processing command: %s", e); } context.println(msg); logger.error(e, "Error handling request"); } finally { PropertySpec.current.remove(); } } @Override public $.T2<String, String> commandLine() { return methodMetaInfo.commandLine(classMetaInfo, app.classLoader()); } @Override public List<$.T2<String, String>> options() { return methodMetaInfo.options(classMetaInfo, app.classLoader()); } @SuppressWarnings("unchecked") private void onResult(Object result, CliContext context) { if (null == result) { return; } PropertySpec.MetaInfo filter = methodMetaInfo.propertySpec(); methodMetaInfo.view().print(result, filter, context); } private void ensureAgentsReady() { if (null == executor) { synchronized (this) { if (null == executor) { generateExecutor(); } } } } // could be used by View to resolve default path to template private void saveCommandPath(CliContext context) { context.commandPath(methodMetaInfo.fullName()); } private void generateExecutor() { executor = new ReflectedCommandExecutor(methodMetaInfo, app); } private Object _handle(CliContext context) { return executor.execute(context); } @Override public String toString() { return methodMetaInfo.fullName(); } @Override public int hashCode() { return $.hc(methodMetaInfo); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof CliHandlerProxy) { CliHandlerProxy that = (CliHandlerProxy)obj; return $.eq(that.methodMetaInfo, this.methodMetaInfo); } return false; } }