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.util.ArrayList; 022import java.util.List; 023import java.util.Map; 024 025import javax.script.ScriptException; 026 027import jdk.nashorn.api.scripting.ScriptObjectMirror; 028import jdk.nashorn.internal.objects.NativeArray; 029 030import org.nuxeo.automation.scripting.api.AutomationScriptingService; 031import org.nuxeo.automation.scripting.internals.MarshalingHelper; 032import org.nuxeo.automation.scripting.internals.ScriptOperationContext; 033import org.nuxeo.ecm.automation.OperationException; 034import org.nuxeo.ecm.automation.core.Constants; 035import org.nuxeo.ecm.automation.core.scripting.DocumentWrapper; 036import org.nuxeo.ecm.automation.core.util.BlobList; 037import org.nuxeo.ecm.core.api.Blob; 038import org.nuxeo.ecm.core.api.DocumentModel; 039import org.nuxeo.ecm.core.api.DocumentModelList; 040import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl; 041import org.nuxeo.runtime.api.Framework; 042 043/** 044 * @since 7.2 045 */ 046public class ScriptingOperationImpl { 047 048 protected final ScriptOperationContext ctx; 049 050 protected final Map<String, Object> args; 051 052 protected final String source; 053 054 public ScriptingOperationImpl(String source, ScriptOperationContext ctx, Map<String, Object> args) throws ScriptException { 055 this.ctx = ctx; 056 this.args = args; 057 this.source = source; 058 } 059 060 public Object run(Object input) throws Exception { 061 try { 062 AutomationScriptingService scriptingService = Framework.getService(AutomationScriptingService.class); 063 scriptingService.setOperationContext(ctx); 064 ScriptingOperationInterface itf = scriptingService.getInterface(ScriptingOperationInterface.class, source, 065 ctx.getCoreSession()); 066 input = wrapArgsAndInput(input, args); 067 return unwrapResult(itf.run(input, args)); 068 } catch (ScriptException e) { 069 throw new OperationException(e); 070 } finally { 071 if (ctx.get(Constants.VAR_IS_CHAIN) != null && !(Boolean) ctx.get(Constants.VAR_IS_CHAIN)) { 072 ctx.deferredDispose(); 073 } 074 } 075 } 076 077 protected Object wrapArgsAndInput(Object input, Map<String, Object> args) { 078 for (String entryId : args.keySet()) { 079 Object entry = args.get(entryId); 080 if (entry instanceof DocumentModel) { 081 args.put(entryId, new DocumentWrapper(ctx.getCoreSession(), (DocumentModel) entry)); 082 } 083 if (entry instanceof DocumentModelList) { 084 List<DocumentWrapper> docs = new ArrayList<>(); 085 for (DocumentModel doc : (DocumentModelList) entry) { 086 docs.add(new DocumentWrapper(ctx.getCoreSession(), doc)); 087 } 088 args.put(entryId, docs); 089 } 090 } 091 if (input instanceof DocumentModel) { 092 return new DocumentWrapper(ctx.getCoreSession(), (DocumentModel) input); 093 } else if (input instanceof DocumentModelList) { 094 List<DocumentWrapper> docs = new ArrayList<>(); 095 for (DocumentModel doc : (DocumentModelList) input) { 096 docs.add(new DocumentWrapper(ctx.getCoreSession(), doc)); 097 } 098 return docs; 099 } 100 return input; 101 } 102 103 protected Object unwrapResult(Object res) { 104 // Unwrap Context 105 for (String entryId : ctx.keySet()) { 106 Object entry = ctx.get(entryId); 107 if (entry instanceof DocumentWrapper) { 108 ctx.put(entryId, ((DocumentWrapper) entry).getDoc()); 109 } else if (ctx.get(entryId) instanceof List<?>) { 110 DocumentModelList docs = new DocumentModelListImpl(); 111 List<?> l = (List<?>) entry; 112 for (Object item : l) { 113 if (ctx.get(entryId) instanceof DocumentWrapper) { 114 docs.add(((DocumentWrapper) item).getDoc()); 115 } 116 } 117 if (docs.size() == l.size() && docs.size() > 0) { 118 ctx.put(entryId, ((DocumentWrapper) entry).getDoc()); 119 } 120 } 121 } 122 // Unwrap Result 123 if (res == null) { 124 return null; 125 } 126 if (res instanceof ScriptObjectMirror) { 127 Object unwrapped = MarshalingHelper.unwrap( 128 (ScriptObjectMirror) res); 129 if (unwrapped instanceof List<?>) { 130 DocumentModelList docs = new DocumentModelListImpl(); 131 List<?> l = (List<?>) unwrapped; 132 for (Object item : l) { 133 if (item instanceof DocumentWrapper) { 134 docs.add(((DocumentWrapper) item).getDoc()); 135 } 136 } 137 if (docs.size() == l.size() && docs.size() > 0) { 138 return docs; 139 } 140 } else if (unwrapped instanceof DocumentWrapper) { 141 return ((DocumentWrapper) unwrapped).getDoc(); 142 } 143 return unwrapped; 144 } else if (res instanceof NativeArray) { 145 Object[] resList = ((NativeArray) res).asObjectArray(); 146 DocumentModelList documentModelList = new DocumentModelListImpl(); 147 BlobList blobList = new BlobList(); 148 for (Object entry : resList) { 149 if (entry instanceof DocumentModel) { 150 documentModelList.add((DocumentModel) entry); 151 } else if (entry instanceof Blob) { 152 blobList.add((Blob) entry); 153 } else if (entry instanceof DocumentWrapper) { 154 documentModelList.add(((DocumentWrapper) entry).getDoc()); 155 } 156 } 157 return documentModelList.isEmpty() ? blobList : documentModelList; 158 } else if (res instanceof DocumentWrapper) { 159 return ((DocumentWrapper) res).getDoc(); 160 } else if (res instanceof List<?>) { 161 DocumentModelList docs = new DocumentModelListImpl(); 162 List<?> l = (List<?>) res; 163 for (Object item : l) { 164 if (item instanceof DocumentWrapper) { 165 docs.add(((DocumentWrapper) item).getDoc()); 166 } 167 } 168 if (docs.size() == l.size() && docs.size() > 0) { 169 return docs; 170 } 171 } 172 return res; 173 } 174 175}