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