001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thierry Delprat <tdelprat@nuxeo.com> 016 */ 017package org.nuxeo.automation.scripting.internals.operation; 018 019import java.net.URL; 020import java.util.Arrays; 021import java.util.Calendar; 022import java.util.List; 023import java.util.Map; 024 025import javax.script.ScriptException; 026 027import org.nuxeo.automation.scripting.internals.ScriptOperationContext; 028import org.nuxeo.ecm.automation.AutomationService; 029import org.nuxeo.ecm.automation.OperationContext; 030import org.nuxeo.ecm.automation.OperationDocumentation; 031import org.nuxeo.ecm.automation.OperationException; 032import org.nuxeo.ecm.automation.core.Constants; 033import org.nuxeo.ecm.automation.core.impl.InvokableMethod; 034import org.nuxeo.ecm.automation.core.impl.OperationTypeImpl; 035import org.nuxeo.ecm.automation.core.util.BlobList; 036import org.nuxeo.ecm.core.api.Blob; 037import org.nuxeo.ecm.core.api.DocumentModel; 038import org.nuxeo.ecm.core.api.DocumentModelList; 039import org.nuxeo.ecm.core.api.DocumentRef; 040import org.nuxeo.ecm.core.api.DocumentRefList; 041import org.nuxeo.ecm.core.api.NuxeoException; 042 043/** 044 * @since 7.2 045 */ 046public class ScriptingOperationTypeImpl extends OperationTypeImpl { 047 048 protected final AutomationService service; 049 050 protected final ScriptingOperationDescriptor desc; 051 052 protected final InvokableMethod[] methods; 053 054 public ScriptingOperationTypeImpl(AutomationService service, 055 ScriptingOperationDescriptor desc) { 056 this.service = service; 057 this.desc = desc; 058 this.inputType = desc.getInputType(); 059 this.methods = new InvokableMethod[] { runMethod() }; 060 } 061 062 063 @Override 064 public String getContributingComponent() { 065 return null; 066 } 067 068 @Override 069 public OperationDocumentation getDocumentation() { 070 OperationDocumentation doc = new OperationDocumentation(getId()); 071 doc.label = getId(); 072 doc.category = desc.getCategory(); 073 doc.description = desc.getDescription(); 074 doc.params = desc.getParams(); 075 doc.signature = new String[] { desc.getInputType(), desc.getOutputType() }; 076 doc.aliases = desc.getAliases(); 077 return doc; 078 } 079 080 @Override 081 public String getId() { 082 return desc.getId(); 083 } 084 085 @Override 086 public String[] getAliases() { 087 return desc.getAliases(); 088 } 089 090 @Override 091 public List<InvokableMethod> getMethods() { 092 return Arrays.asList(methods); 093 } 094 095 @Override 096 public InvokableMethod[] getMethodsMatchingInput(Class<?> in) { 097 return methods; 098 } 099 100 @Override 101 public AutomationService getService() { 102 return service; 103 } 104 105 @Override 106 public Class<?> getType() { 107 return ScriptingOperationImpl.class; 108 } 109 110 @SuppressWarnings("unchecked") 111 @Override 112 public Object newInstance(OperationContext ctx, Map<String, Object> args) throws OperationException { 113 // As org.nuxeo.ecm.automation.core.impl.OperationTypeImpl.inject() is not called in this OperationTypeImpl, 114 // we have to inject into arguments all context variables to play the fallback on chains variables. 115 if (ctx.getVars().containsKey(Constants.VAR_RUNTIME_CHAIN)) { 116 args.putAll((Map<String, Object>) ctx.getVars().get(Constants.VAR_RUNTIME_CHAIN)); 117 } 118 ScriptingOperationImpl impl; 119 ScriptOperationContext sctx = new ScriptOperationContext(ctx); 120 try { 121 impl = new ScriptingOperationImpl(desc.getScript(), sctx, args); 122 } catch (ScriptException e) { 123 throw new NuxeoException(e); 124 } 125 return impl; 126 } 127 128 protected String getParamDocumentationType(Class<?> type, boolean isIterable) { 129 String t; 130 if (DocumentModel.class.isAssignableFrom(type) || DocumentRef.class.isAssignableFrom(type)) { 131 t = isIterable ? Constants.T_DOCUMENTS : Constants.T_DOCUMENT; 132 } else if (DocumentModelList.class.isAssignableFrom(type) || DocumentRefList.class.isAssignableFrom(type)) { 133 t = Constants.T_DOCUMENTS; 134 } else if (BlobList.class.isAssignableFrom(type)) { 135 t = Constants.T_BLOBS; 136 } else if (Blob.class.isAssignableFrom(type)) { 137 t = isIterable ? Constants.T_BLOBS : Constants.T_BLOB; 138 } else if (URL.class.isAssignableFrom(type)) { 139 t = Constants.T_RESOURCE; 140 } else if (Calendar.class.isAssignableFrom(type)) { 141 t = Constants.T_DATE; 142 } else { 143 t = type.getSimpleName().toLowerCase(); 144 } 145 return t; 146 } 147 148 protected InvokableMethod runMethod() { 149 try { 150 return new InvokableMethod(this, ScriptingOperationImpl.class.getMethod("run", Object.class)); 151 } catch (NoSuchMethodException | SecurityException e) { 152 throw new UnsupportedOperationException("Cannot use reflection for run method", e); 153 } 154 } 155 156}