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