0001: /***************************************************************
0002: * This file is part of the [fleXive](R) project.
0003: *
0004: * Copyright (c) 1999-2008
0005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
0006: * All rights reserved
0007: *
0008: * The [fleXive](R) project is free software; you can redistribute
0009: * it and/or modify it under the terms of the GNU General Public
0010: * License as published by the Free Software Foundation;
0011: * either version 2 of the License, or (at your option) any
0012: * later version.
0013: *
0014: * The GNU General Public License can be found at
0015: * http://www.gnu.org/copyleft/gpl.html.
0016: * A copy is found in the textfile GPL.txt and important notices to the
0017: * license from the author are found in LICENSE.txt distributed with
0018: * these libraries.
0019: *
0020: * This library is distributed in the hope that it will be useful,
0021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0023: * GNU General Public License for more details.
0024: *
0025: * For further information about UCS - unique computing solutions gmbh,
0026: * please see the company website: http://www.ucs.at
0027: *
0028: * For further information about [fleXive](R), please see the
0029: * project website: http://www.flexive.org
0030: *
0031: *
0032: * This copyright notice MUST APPEAR in all copies of the file!
0033: ***************************************************************/package com.flexive.ejb.beans;
0034:
0035: import com.flexive.core.Database;
0036: import static com.flexive.core.DatabaseConst.*;
0037: import com.flexive.core.security.UserTicketImpl;
0038: import com.flexive.core.structure.FxEnvironmentImpl;
0039: import com.flexive.core.structure.StructureLoader;
0040: import com.flexive.shared.CacheAdmin;
0041: import com.flexive.shared.EJBLookup;
0042: import com.flexive.shared.FxContext;
0043: import com.flexive.shared.FxSharedUtils;
0044: import com.flexive.shared.configuration.Parameter;
0045: import com.flexive.shared.configuration.SystemParameters;
0046: import com.flexive.shared.content.FxPermissionUtils;
0047: import com.flexive.shared.exceptions.*;
0048: import com.flexive.shared.interfaces.ScriptingEngine;
0049: import com.flexive.shared.interfaces.ScriptingEngineLocal;
0050: import com.flexive.shared.interfaces.SequencerEngine;
0051: import com.flexive.shared.interfaces.SequencerEngineLocal;
0052: import com.flexive.shared.scripting.*;
0053: import com.flexive.shared.security.Role;
0054: import com.flexive.shared.security.UserTicket;
0055: import com.flexive.shared.structure.FxAssignment;
0056: import com.flexive.shared.structure.FxType;
0057: import groovy.lang.Binding;
0058: import groovy.lang.GroovyShell;
0059: import groovy.lang.Script;
0060: import org.apache.commons.lang.StringUtils;
0061: import org.apache.commons.logging.Log;
0062: import org.apache.commons.logging.LogFactory;
0063: import org.codehaus.groovy.control.CompilationFailedException;
0064:
0065: import javax.annotation.Resource;
0066: import javax.ejb.*;
0067: import java.io.InputStream;
0068: import java.sql.Connection;
0069: import java.sql.PreparedStatement;
0070: import java.sql.ResultSet;
0071: import java.sql.SQLException;
0072: import java.util.ArrayList;
0073: import java.util.List;
0074: import java.util.concurrent.ConcurrentHashMap;
0075: import java.util.concurrent.ConcurrentMap;
0076: import java.lang.reflect.InvocationTargetException;
0077:
0078: /**
0079: * ScriptingEngine implementation
0080: *
0081: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
0082: */
0083: @Stateless(name="ScriptingEngine")
0084: @TransactionManagement(TransactionManagementType.CONTAINER)
0085: public class ScriptingEngineBean implements ScriptingEngine,
0086: ScriptingEngineLocal {
0087:
0088: // Our logger
0089: private static transient Log LOG = LogFactory
0090: .getLog(ScriptingEngineBean.class);
0091:
0092: @Resource
0093: javax.ejb.SessionContext ctx;
0094:
0095: @EJB
0096: SequencerEngineLocal seq;
0097:
0098: /**
0099: * Cache for compile groovy scripts
0100: */
0101: static ConcurrentMap<Long, Script> groovyScriptCache = new ConcurrentHashMap<Long, Script>(
0102: 50);
0103:
0104: /**
0105: * Timestamp of the script cache
0106: */
0107: static volatile long scriptCacheTimestamp = -1;
0108:
0109: /**
0110: * {@inheritDoc}
0111: */
0112: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
0113: public String loadScriptCode(long scriptId)
0114: throws FxApplicationException {
0115: Connection con = null;
0116: PreparedStatement ps = null;
0117: String sql;
0118: String code;
0119: try {
0120: // Obtain a database connection
0121: con = Database.getDbConnection();
0122: // 1
0123: sql = "SELECT SDATA FROM " + TBL_SCRIPTS + " WHERE ID=?";
0124: ps = con.prepareStatement(sql);
0125: ps.setLong(1, scriptId);
0126: ResultSet rs = ps.executeQuery();
0127: if (rs == null || !rs.next())
0128: throw new FxNotFoundException("ex.scripting.notFound",
0129: scriptId);
0130: code = rs.getString(1);
0131: } catch (SQLException exc) {
0132: ctx.setRollbackOnly();
0133: throw new FxLoadException(LOG, exc,
0134: "ex.scripting.load.failed", scriptId, exc
0135: .getMessage());
0136: } finally {
0137: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0138: }
0139: return code;
0140: }
0141:
0142: /**
0143: * {@inheritDoc}
0144: */
0145: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
0146: public FxScriptInfo getScriptInfo(long scriptId)
0147: throws FxApplicationException {
0148: Connection con = null;
0149: PreparedStatement ps = null;
0150: String sql;
0151: FxScriptInfo si;
0152: try {
0153: // Obtain a database connection
0154: con = Database.getDbConnection();
0155: // 1 2 3 4 5
0156: sql = "SELECT SNAME,SDESC,SDATA,STYPE,ACTIVE FROM "
0157: + TBL_SCRIPTS + " WHERE ID=?";
0158: ps = con.prepareStatement(sql);
0159: ps.setLong(1, scriptId);
0160: ResultSet rs = ps.executeQuery();
0161: if (rs == null || !rs.next())
0162: throw new FxNotFoundException("ex.scripting.notFound",
0163: scriptId);
0164: si = new FxScriptInfo(scriptId, FxScriptEvent.getById(rs
0165: .getLong(4)), rs.getString(1), rs.getString(2), rs
0166: .getString(3), rs.getBoolean(5));
0167: } catch (SQLException exc) {
0168: ctx.setRollbackOnly();
0169: throw new FxLoadException(LOG, exc,
0170: "ex.scripting.load.failed", scriptId, exc
0171: .getMessage());
0172: } finally {
0173: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0174: }
0175: return si;
0176: }
0177:
0178: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
0179: public FxScriptInfo[] getScriptInfos()
0180: throws FxApplicationException {
0181: Connection con = null;
0182: PreparedStatement ps = null;
0183: String sql;
0184: ArrayList<FxScriptInfo> slist = new ArrayList<FxScriptInfo>();
0185: try {
0186: // Obtain a database connection
0187: con = Database.getDbConnection();
0188: // 1 2 3 4 5
0189: sql = "SELECT ID, SNAME,SDESC,SDATA,STYPE,ACTIVE FROM "
0190: + TBL_SCRIPTS + " ORDER BY ID";
0191: ps = con.prepareStatement(sql);
0192: ResultSet rs = ps.executeQuery();
0193:
0194: while (rs != null && rs.next()) {
0195: slist.add(new FxScriptInfo(rs.getInt(1), FxScriptEvent
0196: .getById(rs.getLong(5)), rs.getString(2), rs
0197: .getString(3), rs.getString(4), rs
0198: .getBoolean(5)));
0199: }
0200:
0201: } catch (SQLException exc) {
0202: ctx.setRollbackOnly();
0203: throw new FxLoadException(LOG, exc,
0204: "ex.scripts.load.failed", exc.getMessage());
0205: } finally {
0206: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0207: }
0208: return slist.toArray(new FxScriptInfo[slist.size()]);
0209: }
0210:
0211: /**
0212: * {@inheritDoc}
0213: */
0214: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0215: public void updateScriptInfo(long scriptId, FxScriptEvent event,
0216: String name, String description, String code, boolean active)
0217: throws FxApplicationException {
0218: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0219: Role.ScriptManagement);
0220: Connection con = null;
0221: PreparedStatement ps = null;
0222: String sql;
0223: boolean success = false;
0224: try {
0225: if (code == null)
0226: code = "";
0227: // Obtain a database connection
0228: con = Database.getDbConnection();
0229: // 1 2 3 4 5 6
0230: sql = "UPDATE "
0231: + TBL_SCRIPTS
0232: + " SET SNAME=?,SDESC=?,SDATA=?,STYPE=?,ACTIVE=? WHERE ID=?";
0233: ps = con.prepareStatement(sql);
0234: ps.setString(1, name);
0235: ps.setString(2, description);
0236: ps.setString(3, code);
0237: ps.setLong(4, event.getId());
0238: ps.setBoolean(5, active);
0239: ps.setLong(6, scriptId);
0240: ps.executeUpdate();
0241: success = true;
0242: } catch (SQLException exc) {
0243: throw new FxUpdateException(LOG, exc,
0244: "ex.scripting.update.failed", name, exc
0245: .getMessage());
0246: } finally {
0247: if (!success)
0248: ctx.setRollbackOnly();
0249: else
0250: StructureLoader.reloadScripting(FxContext.get()
0251: .getDivisionId());
0252: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0253: }
0254: }
0255:
0256: /**
0257: * {@inheritDoc}
0258: */
0259: public void updateScriptInfo(FxScriptInfoEdit script)
0260: throws FxApplicationException {
0261: updateScriptInfo(script.getId(), script.getEvent(), script
0262: .getName(), script.getDescription(), script.getCode(),
0263: script.isActive());
0264: }
0265:
0266: /**
0267: * {@inheritDoc}
0268: */
0269: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0270: public void updateScriptCode(long scriptId, String code)
0271: throws FxApplicationException {
0272: FxScriptInfo si = getScriptInfo(scriptId);
0273: updateScriptInfo(si.getId(), si.getEvent(), si.getName(), si
0274: .getDescription(), code, si.isActive());
0275: }
0276:
0277: /**
0278: * {@inheritDoc}
0279: */
0280: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
0281: public List<Long> getByScriptType(FxScriptEvent scriptEvent) {
0282: Connection con = null;
0283: PreparedStatement ps = null;
0284: String sql;
0285: List<Long> ret = new ArrayList<Long>(10);
0286: try {
0287: // Obtain a database connection
0288: con = Database.getDbConnection();
0289: // 1
0290: sql = "SELECT DISTINCT ID FROM " + TBL_SCRIPTS
0291: + " WHERE STYPE=? ORDER BY ID";
0292: ps = con.prepareStatement(sql);
0293: ps.setLong(1, scriptEvent.getId());
0294: ResultSet rs = ps.executeQuery();
0295: while (rs != null && rs.next())
0296: ret.add(rs.getLong(1));
0297: } catch (SQLException exc) {
0298: ctx.setRollbackOnly();
0299: throw new FxDbException(LOG, exc, "ex.db.sqlError", exc
0300: .getMessage()).asRuntimeException();
0301: } finally {
0302: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0303: }
0304: return ret;
0305: }
0306:
0307: /**
0308: * {@inheritDoc}
0309: */
0310: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0311: public FxScriptInfo createScript(FxScriptEvent event, String name,
0312: String description, String code)
0313: throws FxApplicationException {
0314: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0315: Role.ScriptManagement);
0316: FxScriptInfo si;
0317: Connection con = null;
0318: PreparedStatement ps = null;
0319: String sql;
0320: boolean success = false;
0321: try {
0322: si = new FxScriptInfo(seq
0323: .getId(SequencerEngine.System.SCRIPTS), event,
0324: name, description, code, true);
0325: if (code == null)
0326: code = "";
0327: // Obtain a database connection
0328: con = Database.getDbConnection();
0329: // 1 2 3 4 5 6
0330: sql = "INSERT INTO "
0331: + TBL_SCRIPTS
0332: + " (ID,SNAME,SDESC,SDATA,STYPE,ACTIVE) VALUES (?,?,?,?,?,?)";
0333: ps = con.prepareStatement(sql);
0334: ps.setLong(1, si.getId());
0335: ps.setString(2, si.getName());
0336: ps.setString(3, si.getDescription());
0337: ps.setString(4, code);
0338: ps.setLong(5, si.getEvent().getId());
0339: ps.setBoolean(6, si.isActive());
0340: ps.executeUpdate();
0341: success = true;
0342: } catch (SQLException exc) {
0343: if (Database.isUniqueConstraintViolation(exc))
0344: throw new FxEntryExistsException(
0345: "ex.scripting.name.notUnique", name);
0346: throw new FxCreateException(LOG, exc,
0347: "ex.scripting.create.failed", name, exc
0348: .getMessage());
0349: } finally {
0350: if (!success)
0351: ctx.setRollbackOnly();
0352: else
0353: StructureLoader.reloadScripting(FxContext.get()
0354: .getDivisionId());
0355: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0356: }
0357: return si;
0358: }
0359:
0360: /**
0361: * {@inheritDoc}
0362: */
0363: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0364: public FxScriptInfo createScriptFromLibrary(FxScriptEvent event,
0365: String libraryname, String name, String description)
0366: throws FxApplicationException {
0367: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0368: Role.ScriptManagement);
0369: ClassLoader cl = Thread.currentThread().getContextClassLoader();
0370: String code = FxSharedUtils.loadFromInputStream(cl
0371: .getResourceAsStream("fxresources/scripts/library/"
0372: + libraryname), -1);
0373: if (code == null || code.length() == 0)
0374: throw new FxNotFoundException(
0375: "ex.scripting.load.library.failed", libraryname);
0376: return createScript(event, name, description, code);
0377: }
0378:
0379: /**
0380: * {@inheritDoc}
0381: */
0382: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0383: public FxScriptInfo createScriptFromDropLibrary(String dropName,
0384: FxScriptEvent event, String libraryname, String name,
0385: String description) throws FxApplicationException {
0386: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0387: Role.ScriptManagement);
0388: ClassLoader cl = Thread.currentThread().getContextClassLoader();
0389: String code = FxSharedUtils.loadFromInputStream(cl
0390: .getResourceAsStream(dropName
0391: + "Resources/scripts/library/" + libraryname),
0392: -1);
0393: if (code == null || code.length() == 0)
0394: throw new FxNotFoundException(
0395: "ex.scripting.load.library.failed", libraryname);
0396: return createScript(event, name, description, code);
0397: }
0398:
0399: /**
0400: * {@inheritDoc}
0401: */
0402: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0403: public void removeScript(long scriptId)
0404: throws FxApplicationException {
0405: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0406: Role.ScriptManagement);
0407: Connection con = null;
0408: PreparedStatement ps = null;
0409: String sql;
0410: boolean success = false;
0411: try {
0412: // Obtain a database connection
0413: con = Database.getDbConnection();
0414: sql = "DELETE FROM " + TBL_SCRIPT_MAPPING_ASSIGN
0415: + " WHERE SCRIPT=?";
0416: ps = con.prepareStatement(sql);
0417: ps.setLong(1, scriptId);
0418: ps.executeUpdate();
0419: ps.close();
0420: sql = "DELETE FROM " + TBL_SCRIPT_MAPPING_TYPES
0421: + " WHERE SCRIPT=?";
0422: ps = con.prepareStatement(sql);
0423: ps.setLong(1, scriptId);
0424: ps.executeUpdate();
0425: ps.close();
0426: // 1
0427: sql = "DELETE FROM " + TBL_SCRIPTS + " WHERE ID=?";
0428: ps = con.prepareStatement(sql);
0429: ps.setLong(1, scriptId);
0430: ps.executeUpdate();
0431: success = true;
0432: } catch (SQLException exc) {
0433: throw new FxRemoveException(LOG, exc,
0434: "ex.scripting.remove.failed", scriptId, exc
0435: .getMessage());
0436: } finally {
0437: if (!success)
0438: ctx.setRollbackOnly();
0439: else
0440: StructureLoader.reloadScripting(FxContext.get()
0441: .getDivisionId());
0442: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0443: }
0444: }
0445:
0446: /**
0447: * {@inheritDoc}
0448: */
0449: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
0450: public FxScriptResult runScript(long scriptId,
0451: FxScriptBinding binding) throws FxApplicationException {
0452: FxScriptInfo si = CacheAdmin.getEnvironment().getScript(
0453: scriptId);
0454:
0455: if (!si.isActive()) {
0456: LOG.warn("Script [" + si.getName() + "], Id " + si.getId()
0457: + " is deactivated and will not be run!");
0458: return new FxScriptResult(binding, null);
0459: }
0460:
0461: if (!FxSharedUtils.isGroovyScript(si.getName()))
0462: return internal_runScript(si.getName(), binding, si
0463: .getCode());
0464:
0465: if (si.getEvent() == FxScriptEvent.Manual)
0466: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0467: Role.ScriptExecution);
0468:
0469: long timeStamp = CacheAdmin.getEnvironment().getTimeStamp();
0470: if (timeStamp != scriptCacheTimestamp) {
0471: scriptCacheTimestamp = timeStamp;
0472: groovyScriptCache.clear();
0473: }
0474: Script script = groovyScriptCache.get(scriptId);
0475: if (script == null) {
0476: try {
0477: GroovyShell shell = new GroovyShell();
0478: script = shell.parse(CacheAdmin.getEnvironment()
0479: .getScript(scriptId).getCode());
0480: } catch (CompilationFailedException e) {
0481: throw new FxInvalidParameterException(si.getName(),
0482: "ex.general.scripting.compileFailed", si
0483: .getName());
0484: } catch (Throwable t) {
0485: throw new FxInvalidParameterException(si.getName(),
0486: "ex.general.scripting.exception", si.getName(),
0487: t.getMessage());
0488: }
0489: groovyScriptCache.putIfAbsent(scriptId, script);
0490: }
0491:
0492: if (binding == null)
0493: binding = new FxScriptBinding();
0494: if (!binding.getProperties().containsKey("ticket"))
0495: binding.setVariable("ticket", FxContext.get().getTicket());
0496: if (!binding.getProperties().containsKey("environment"))
0497: binding.setVariable("environment", CacheAdmin
0498: .getEnvironment());
0499: binding.setVariable("scriptname", si.getName());
0500:
0501: try {
0502: Object result;
0503: synchronized (script) {
0504: script.setBinding(new Binding(binding.getProperties()));
0505: result = script.run();
0506: }
0507: return new FxScriptResult(binding, result);
0508: } catch (Throwable e) {
0509: if (e instanceof FxApplicationException)
0510: throw (FxApplicationException) e;
0511: LOG.error("Scripting error: " + e.getMessage(), e);
0512: throw new FxInvalidParameterException(si.getName(),
0513: "ex.general.scripting.exception", si.getName(), e
0514: .getMessage());
0515: }
0516: }
0517:
0518: /**
0519: * {@inheritDoc}
0520: */
0521: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
0522: public FxScriptResult runScript(long scriptId)
0523: throws FxApplicationException {
0524: return runScript(scriptId, null);
0525: }
0526:
0527: /**
0528: * {@inheritDoc}
0529: */
0530: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0531: public FxScriptMappingEntry createAssignmentScriptMapping(
0532: FxScriptEvent scriptEvent, long scriptId,
0533: long assignmentId, boolean active, boolean derivedUsage)
0534: throws FxApplicationException {
0535: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0536: Role.ScriptManagement);
0537: FxScriptMappingEntry sm;
0538: Connection con = null;
0539: PreparedStatement ps = null;
0540: String sql;
0541: boolean success = false;
0542: //check existance
0543: getScriptInfo(scriptId);
0544: try {
0545: long[] derived;
0546: if (!derivedUsage)
0547: derived = new long[0];
0548: else {
0549: List<FxAssignment> ass = CacheAdmin.getEnvironment()
0550: .getDerivedAssignments(assignmentId);
0551: derived = new long[ass.size()];
0552: for (int i = 0; i < ass.size(); i++)
0553: derived[i] = ass.get(i).getId();
0554: }
0555: sm = new FxScriptMappingEntry(scriptEvent, scriptId,
0556: active, derivedUsage, assignmentId, derived);
0557: // Obtain a database connection
0558: con = Database.getDbConnection();
0559: sql = "INSERT INTO "
0560: + TBL_SCRIPT_MAPPING_ASSIGN
0561: + " (ASSIGNMENT,SCRIPT,DERIVED_USAGE,ACTIVE,STYPE) VALUES "
0562: +
0563: //1,2,3,4,5
0564: "(?,?,?,?,?)";
0565: ps = con.prepareStatement(sql);
0566: ps.setLong(1, sm.getId());
0567: ps.setLong(2, sm.getScriptId());
0568: ps.setBoolean(3, sm.isDerivedUsage());
0569: ps.setBoolean(4, sm.isActive());
0570: ps.setLong(5, sm.getScriptEvent().getId());
0571: ps.executeUpdate();
0572: success = true;
0573: } catch (SQLException exc) {
0574: if (Database.isUniqueConstraintViolation(exc))
0575: throw new FxEntryExistsException(
0576: "ex.scripting.mapping.assign.notUnique",
0577: scriptId, assignmentId);
0578: throw new FxCreateException(LOG, exc,
0579: "ex.scripting.mapping.assign.create.failed",
0580: scriptId, assignmentId, exc.getMessage());
0581: } finally {
0582: if (!success)
0583: ctx.setRollbackOnly();
0584: else
0585: StructureLoader.reloadScripting(FxContext.get()
0586: .getDivisionId());
0587: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0588: }
0589: return sm;
0590: }
0591:
0592: /**
0593: * {@inheritDoc}
0594: */
0595: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0596: public FxScriptMappingEntry createAssignmentScriptMapping(
0597: long scriptId, long typeId, boolean active,
0598: boolean derivedUsage) throws FxApplicationException {
0599: FxScriptInfo si = getScriptInfo(scriptId);
0600: return createAssignmentScriptMapping(si.getEvent(), scriptId,
0601: typeId, active, derivedUsage);
0602: }
0603:
0604: /**
0605: * {@inheritDoc}
0606: */
0607: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0608: public FxScriptMappingEntry createTypeScriptMapping(
0609: FxScriptEvent scriptEvent, long scriptId, long typeId,
0610: boolean active, boolean derivedUsage)
0611: throws FxApplicationException {
0612: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0613: Role.ScriptManagement);
0614: FxScriptMappingEntry sm;
0615: Connection con = null;
0616: PreparedStatement ps = null;
0617: String sql;
0618: boolean success = false;
0619: //check existance
0620: getScriptInfo(scriptId);
0621: try {
0622: long[] derived;
0623: if (!derivedUsage)
0624: derived = new long[0];
0625: else {
0626: List<FxType> types = CacheAdmin.getEnvironment()
0627: .getType(typeId).getDerivedTypes();
0628: derived = new long[types.size()];
0629: for (int i = 0; i < types.size(); i++)
0630: derived[i] = types.get(i).getId();
0631: }
0632: sm = new FxScriptMappingEntry(scriptEvent, scriptId,
0633: active, derivedUsage, typeId, derived);
0634: // Obtain a database connection
0635: con = Database.getDbConnection();
0636: sql = "INSERT INTO "
0637: + TBL_SCRIPT_MAPPING_TYPES
0638: + " (TYPEDEF,SCRIPT,DERIVED_USAGE,ACTIVE,STYPE) VALUES "
0639: +
0640: //1,2,3,4,5
0641: "(?,?,?,?,?)";
0642: ps = con.prepareStatement(sql);
0643: ps.setLong(1, sm.getId());
0644: ps.setLong(2, sm.getScriptId());
0645: ps.setBoolean(3, sm.isDerivedUsage());
0646: ps.setBoolean(4, sm.isActive());
0647: ps.setLong(5, sm.getScriptEvent().getId());
0648: ps.executeUpdate();
0649: success = true;
0650: } catch (SQLException exc) {
0651: if (Database.isUniqueConstraintViolation(exc))
0652: throw new FxEntryExistsException(
0653: "ex.scripting.mapping.types.notUnique",
0654: scriptId, typeId);
0655: throw new FxCreateException(LOG, exc,
0656: "ex.scripting.mapping.types.create.failed",
0657: scriptId, typeId, exc.getMessage());
0658: } finally {
0659: if (!success)
0660: ctx.setRollbackOnly();
0661: else
0662: StructureLoader.reloadScripting(FxContext.get()
0663: .getDivisionId());
0664: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0665: }
0666: return sm;
0667: }
0668:
0669: /**
0670: * {@inheritDoc}
0671: */
0672: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0673: public FxScriptMappingEntry createTypeScriptMapping(long scriptId,
0674: long typeId, boolean active, boolean derivedUsage)
0675: throws FxApplicationException {
0676: FxScriptInfo si = getScriptInfo(scriptId);
0677: return createTypeScriptMapping(si.getEvent(), scriptId, typeId,
0678: active, derivedUsage);
0679: }
0680:
0681: /**
0682: * {@inheritDoc}
0683: */
0684: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0685: public void removeAssignmentScriptMapping(long scriptId,
0686: long assignmentId) throws FxApplicationException {
0687: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0688: Role.ScriptManagement);
0689: Connection con = null;
0690: PreparedStatement ps = null;
0691: String sql;
0692: boolean success = false;
0693: try {
0694: // Obtain a database connection
0695: con = Database.getDbConnection();
0696: // 1 2
0697: sql = "DELETE FROM " + TBL_SCRIPT_MAPPING_ASSIGN
0698: + " WHERE SCRIPT=? AND ASSIGNMENT=?";
0699: ps = con.prepareStatement(sql);
0700: ps.setLong(1, scriptId);
0701: ps.setLong(2, assignmentId);
0702: ps.executeUpdate();
0703: success = true;
0704: } catch (SQLException exc) {
0705: throw new FxRemoveException(LOG, exc,
0706: "ex.scripting.mapping.assign.remove.failed",
0707: scriptId, assignmentId, exc.getMessage());
0708: } finally {
0709: if (!success)
0710: ctx.setRollbackOnly();
0711: else
0712: StructureLoader.reloadScripting(FxContext.get()
0713: .getDivisionId());
0714: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0715: }
0716: }
0717:
0718: /**
0719: * {@inheritDoc}
0720: */
0721: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0722: public void removeAssignmentScriptMappingForEvent(long scriptId,
0723: long assignmentId, FxScriptEvent event)
0724: throws FxApplicationException {
0725: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0726: Role.ScriptManagement);
0727: Connection con = null;
0728: PreparedStatement ps = null;
0729: String sql;
0730: boolean success = false;
0731: try {
0732: // Obtain a database connection
0733: con = Database.getDbConnection();
0734: // 1 2
0735: sql = "DELETE FROM " + TBL_SCRIPT_MAPPING_ASSIGN
0736: + " WHERE SCRIPT=? AND ASSIGNMENT=? AND STYPE=?";
0737: ps = con.prepareStatement(sql);
0738: ps.setLong(1, scriptId);
0739: ps.setLong(2, assignmentId);
0740: ps.setLong(3, event.getId());
0741: ps.executeUpdate();
0742: success = true;
0743: } catch (SQLException exc) {
0744: throw new FxRemoveException(LOG, exc,
0745: "ex.scripting.mapping.assign.remove.failed",
0746: scriptId, assignmentId, exc.getMessage());
0747: } finally {
0748: if (!success)
0749: ctx.setRollbackOnly();
0750: else
0751: StructureLoader.reloadScripting(FxContext.get()
0752: .getDivisionId());
0753: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0754: }
0755: }
0756:
0757: /**
0758: * {@inheritDoc}
0759: */
0760: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0761: public void removeTypeScriptMapping(long scriptId, long typeId)
0762: throws FxApplicationException {
0763: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0764: Role.ScriptManagement);
0765: Connection con = null;
0766: PreparedStatement ps = null;
0767: String sql;
0768: boolean success = false;
0769: try {
0770: // Obtain a database connection
0771: con = Database.getDbConnection();
0772: // 1 2
0773: sql = "DELETE FROM " + TBL_SCRIPT_MAPPING_TYPES
0774: + " WHERE SCRIPT=? AND TYPEDEF=?";
0775: ps = con.prepareStatement(sql);
0776: ps.setLong(1, scriptId);
0777: ps.setLong(2, typeId);
0778: ps.executeUpdate();
0779: success = true;
0780: } catch (SQLException exc) {
0781: throw new FxRemoveException(LOG, exc,
0782: "ex.scripting.mapping.type.remove.failed",
0783: scriptId, typeId, exc.getMessage());
0784: } finally {
0785: if (!success)
0786: ctx.setRollbackOnly();
0787: else
0788: StructureLoader.reloadScripting(FxContext.get()
0789: .getDivisionId());
0790: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0791: }
0792: }
0793:
0794: /**
0795: * {@inheritDoc}
0796: */
0797: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0798: public void removeTypeScriptMappingForEvent(long scriptId,
0799: long typeId, FxScriptEvent event)
0800: throws FxApplicationException {
0801: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0802: Role.ScriptManagement);
0803: Connection con = null;
0804: PreparedStatement ps = null;
0805: String sql;
0806: boolean success = false;
0807: try {
0808: // Obtain a database connection
0809: con = Database.getDbConnection();
0810: // 1 2
0811: sql = "DELETE FROM " + TBL_SCRIPT_MAPPING_TYPES
0812: + " WHERE SCRIPT=? AND TYPEDEF=? AND STYPE=?";
0813: ps = con.prepareStatement(sql);
0814: ps.setLong(1, scriptId);
0815: ps.setLong(2, typeId);
0816: ps.setLong(3, event.getId());
0817: ps.executeUpdate();
0818: success = true;
0819: } catch (SQLException exc) {
0820: throw new FxRemoveException(LOG, exc,
0821: "ex.scripting.mapping.type.remove.failed",
0822: scriptId, typeId, exc.getMessage());
0823: } finally {
0824: if (!success)
0825: ctx.setRollbackOnly();
0826: else
0827: StructureLoader.reloadScripting(FxContext.get()
0828: .getDivisionId());
0829: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0830: }
0831: }
0832:
0833: /**
0834: * {@inheritDoc}
0835: */
0836: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0837: public FxScriptMappingEntry updateAssignmentScriptMappingForEvent(
0838: long scriptId, long assignmentId, FxScriptEvent event,
0839: boolean active, boolean derivedUsage)
0840: throws FxApplicationException {
0841: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0842: Role.ScriptManagement);
0843: FxScriptMappingEntry sm;
0844: Connection con = null;
0845: PreparedStatement ps = null;
0846: String sql;
0847: boolean success = false;
0848: //check existance
0849: getScriptInfo(scriptId);
0850: try {
0851: long[] derived;
0852: if (!derivedUsage)
0853: derived = new long[0];
0854: else {
0855: List<FxAssignment> ass = CacheAdmin.getEnvironment()
0856: .getDerivedAssignments(assignmentId);
0857: derived = new long[ass.size()];
0858: for (int i = 0; i < ass.size(); i++)
0859: derived[i] = ass.get(i).getId();
0860: }
0861: sm = new FxScriptMappingEntry(event, scriptId, active,
0862: derivedUsage, assignmentId, derived);
0863: // Obtain a database connection
0864: con = Database.getDbConnection();
0865: // 1 2 3 4
0866: sql = "UPDATE "
0867: + TBL_SCRIPT_MAPPING_ASSIGN
0868: + " SET DERIVED_USAGE=?,ACTIVE=? WHERE ASSIGNMENT=? AND SCRIPT=? AND STYPE=?";
0869: ps = con.prepareStatement(sql);
0870: ps.setBoolean(1, sm.isDerivedUsage());
0871: ps.setBoolean(2, sm.isActive());
0872: ps.setLong(3, sm.getId());
0873: ps.setLong(4, sm.getScriptId());
0874: ps.setLong(5, sm.getScriptEvent().getId());
0875: ps.executeUpdate();
0876: success = true;
0877: } catch (SQLException exc) {
0878: if (Database.isUniqueConstraintViolation(exc))
0879: throw new FxEntryExistsException(
0880: "ex.scripting.mapping.assign.notUnique",
0881: scriptId, assignmentId);
0882: throw new FxUpdateException(LOG, exc,
0883: "ex.scripting.mapping.assign.update.failed",
0884: scriptId, assignmentId, exc.getMessage());
0885: } finally {
0886: if (!success)
0887: ctx.setRollbackOnly();
0888: else
0889: StructureLoader.reloadScripting(FxContext.get()
0890: .getDivisionId());
0891: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0892: }
0893: return sm;
0894: }
0895:
0896: /**
0897: * {@inheritDoc}
0898: */
0899: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0900: public FxScriptMappingEntry updateTypeScriptMappingForEvent(
0901: long scriptId, long typeId, FxScriptEvent event,
0902: boolean active, boolean derivedUsage)
0903: throws FxApplicationException {
0904: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
0905: Role.ScriptManagement);
0906: FxScriptMappingEntry sm;
0907: Connection con = null;
0908: PreparedStatement ps = null;
0909: String sql;
0910: boolean success = false;
0911: //check existance
0912: getScriptInfo(scriptId);
0913: try {
0914: long[] derived;
0915: if (!derivedUsage)
0916: derived = new long[0];
0917: else {
0918: List<FxType> types = CacheAdmin.getEnvironment()
0919: .getType(typeId).getDerivedTypes();
0920: derived = new long[types.size()];
0921: for (int i = 0; i < types.size(); i++)
0922: derived[i] = types.get(i).getId();
0923: }
0924: sm = new FxScriptMappingEntry(event, scriptId, active,
0925: derivedUsage, typeId, derived);
0926: // Obtain a database connection
0927: con = Database.getDbConnection();
0928: // 1 2 3 4 5
0929: sql = "UPDATE "
0930: + TBL_SCRIPT_MAPPING_TYPES
0931: + " SET DERIVED_USAGE=?,ACTIVE=? WHERE TYPEDEF=? AND SCRIPT=? AND STYPE=?";
0932: ps = con.prepareStatement(sql);
0933: ps.setBoolean(1, sm.isDerivedUsage());
0934: ps.setBoolean(2, sm.isActive());
0935: ps.setLong(3, sm.getId());
0936: ps.setLong(4, sm.getScriptId());
0937: ps.setLong(5, sm.getScriptEvent().getId());
0938: ps.executeUpdate();
0939: success = true;
0940: } catch (SQLException exc) {
0941: if (Database.isUniqueConstraintViolation(exc))
0942: throw new FxEntryExistsException(
0943: "ex.scripting.mapping.types.notUnique",
0944: scriptId, typeId);
0945: throw new FxUpdateException(LOG, exc,
0946: "ex.scripting.mapping.types.update.failed",
0947: scriptId, typeId, exc.getMessage());
0948: } finally {
0949: if (!success)
0950: ctx.setRollbackOnly();
0951: else
0952: StructureLoader.reloadScripting(FxContext.get()
0953: .getDivisionId());
0954: Database.closeObjects(ScriptingEngineBean.class, con, ps);
0955: }
0956: return sm;
0957: }
0958:
0959: /**
0960: * {@inheritDoc}
0961: */
0962: @TransactionAttribute(TransactionAttributeType.REQUIRED)
0963: public void executeRunOnceScripts() {
0964: final long start = System.currentTimeMillis();
0965: runOnce(SystemParameters.DIVISION_RUNONCE, "fxresources",
0966: "flexive");
0967: if (LOG.isInfoEnabled()) {
0968: LOG.info("Executed flexive run-once scripts in "
0969: + (System.currentTimeMillis() - start) + "ms");
0970: }
0971: }
0972:
0973: /**
0974: * Execute all runOnce scripts in the resource denoted by prefix if param is "false"
0975: *
0976: * @param param boolean parameter that will be flagged as "true" once the scripts are run
0977: * @param prefix resource directory prefix
0978: * @param applicationName the corresponding application name (for debug messages)
0979: */
0980: private void runOnce(Parameter<Boolean> param, String prefix,
0981: String applicationName) {
0982: try {
0983: Boolean executed = EJBLookup
0984: .getDivisionConfigurationEngine().get(param);
0985: if (executed) {
0986: // System.out.println("=============> skip run-once <==============");
0987: return;
0988: }
0989: } catch (FxApplicationException e) {
0990: LOG.error(e);
0991: return;
0992: }
0993: // System.out.println("<=============> run run-once <==============>");
0994: ClassLoader cl = Thread.currentThread().getContextClassLoader();
0995: final InputStream scriptIndex = cl.getResourceAsStream(prefix
0996: + "/scripts/runonce/scriptindex.flexive");
0997: if (scriptIndex == null) {
0998: if (LOG.isInfoEnabled()) {
0999: LOG.info("No run-once scripts defined for "
1000: + applicationName);
1001: }
1002: return;
1003: }
1004: if (LOG.isInfoEnabled()) {
1005: LOG.info("Executing run-once scripts for "
1006: + applicationName);
1007: }
1008: String[] files = FxSharedUtils.loadFromInputStream(scriptIndex,
1009: -1).replaceAll("\r", "").split("\n");
1010: FxContext.get().runAsSystem();
1011: final UserTicket originalTicket = FxContext.get().getTicket();
1012: try {
1013: FxScriptBinding binding = new FxScriptBinding();
1014: UserTicket ticket = ((UserTicketImpl) UserTicketImpl
1015: .getGuestTicket()).cloneAsGlobalSupervisor();
1016: binding.setVariable("ticket", ticket);
1017: FxContext.get().overrideTicket(ticket);
1018: for (String temp : files) {
1019: String[] file = temp.split("\\|");
1020: if (StringUtils.isBlank(file[0])) {
1021: continue;
1022: }
1023: if (LOG.isInfoEnabled()) {
1024: LOG.info("running run-once-script [" + file[0]
1025: + "] ...");
1026: }
1027: try {
1028: internal_runScript(file[0], binding, FxSharedUtils
1029: .loadFromInputStream(cl
1030: .getResourceAsStream(prefix
1031: + "/scripts/runonce/"
1032: + file[0]), -1));
1033: } catch (Throwable e) {
1034: LOG.error("Failed to run script " + file[0] + ": "
1035: + e.getMessage(), e);
1036: }
1037: }
1038: } finally {
1039: FxContext.get().stopRunAsSystem();
1040: FxContext.get().overrideTicket(originalTicket);
1041: }
1042: try {
1043: EJBLookup.getDivisionConfigurationEngine().put(param, true);
1044: } catch (FxApplicationException e) {
1045: LOG.error(e);
1046: }
1047: }
1048:
1049: /**
1050: * {@inheritDoc}
1051: */
1052: @TransactionAttribute(TransactionAttributeType.REQUIRED)
1053: public void executeDropRunOnceScripts(Parameter<Boolean> param,
1054: String dropName) throws FxApplicationException {
1055: if (!FxSharedUtils.getDrops().contains(dropName))
1056: throw new FxInvalidParameterException("dropName",
1057: "ex.scripting.drop.notFound", dropName);
1058: runOnce(param, dropName + "Resources", "drop " + dropName);
1059: }
1060:
1061: /**
1062: * {@inheritDoc}
1063: */
1064: @TransactionAttribute(TransactionAttributeType.REQUIRED)
1065: public void executeStartupScripts() {
1066: executeStartupScripts("fxresources", "flexive");
1067: }
1068:
1069: /**
1070: * {@inheritDoc}
1071: */
1072: @TransactionAttribute(TransactionAttributeType.REQUIRED)
1073: public void executeDropStartupScripts(String dropName)
1074: throws FxApplicationException {
1075: if (!FxSharedUtils.getDrops().contains(dropName))
1076: throw new FxInvalidParameterException("dropName",
1077: "ex.scripting.drop.notFound", dropName);
1078: executeStartupScripts(dropName + "Resources", "drop "
1079: + dropName);
1080: }
1081:
1082: /**
1083: * Eexecute startup scripts within the given subfolder identified by prefix
1084: *
1085: * @param prefix subfolder for scripts
1086: * @param applicationName the corresponding application name (for debug messages)
1087: */
1088: private void executeStartupScripts(String prefix,
1089: String applicationName) {
1090: ClassLoader cl = Thread.currentThread().getContextClassLoader();
1091: final InputStream scriptIndex = cl.getResourceAsStream(prefix
1092: + "/scripts/startup/scriptindex.flexive");
1093: if (scriptIndex == null) {
1094: if (LOG.isInfoEnabled()) {
1095: LOG.info("No startup scripts defined for "
1096: + applicationName);
1097: }
1098: return;
1099: }
1100: if (LOG.isInfoEnabled()) {
1101: LOG
1102: .info("Executing startup scripts for "
1103: + applicationName);
1104: }
1105: String[] files = FxSharedUtils.loadFromInputStream(scriptIndex,
1106: -1).replaceAll("\r", "").split("\n");
1107: FxContext.get().runAsSystem();
1108: final UserTicket originalTicket = FxContext.get().getTicket();
1109: try {
1110: FxScriptBinding binding = new FxScriptBinding();
1111: UserTicket ticket = ((UserTicketImpl) UserTicketImpl
1112: .getGuestTicket()).cloneAsGlobalSupervisor();
1113: binding.setVariable("ticket", ticket);
1114: FxContext.get().overrideTicket(ticket);
1115: for (String temp : files) {
1116: String[] file = temp.split("\\|");
1117: if (StringUtils.isBlank(file[0])) {
1118: continue;
1119: }
1120: LOG
1121: .info("running startup-script [" + file[0]
1122: + "] ...");
1123: try {
1124: internal_runScript(file[0], binding, FxSharedUtils
1125: .loadFromInputStream(cl
1126: .getResourceAsStream(prefix
1127: + "/scripts/startup/"
1128: + file[0]), -1));
1129: } catch (Throwable e) {
1130: LOG.error("Failed to run script " + file[0] + ": "
1131: + e.getMessage(), e);
1132: }
1133: }
1134: } finally {
1135: FxContext.get().stopRunAsSystem();
1136: FxContext.get().overrideTicket(originalTicket);
1137: }
1138: }
1139:
1140: /**
1141: * {@inheritDoc}
1142: */
1143: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
1144: public FxScriptResult runScript(String name,
1145: FxScriptBinding binding, String code)
1146: throws FxApplicationException {
1147: FxPermissionUtils.checkRole(FxContext.get().getTicket(),
1148: Role.ScriptExecution);
1149: return internal_runScript(name, binding, code);
1150: }
1151:
1152: /**
1153: * {@inheritDoc}
1154: */
1155: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
1156: public List<String[]> getAvailableScriptEngines()
1157: throws FxApplicationException {
1158: List<String[]> ret = null;
1159: if (FxSharedUtils.USE_JDK6_EXTENSION) {
1160: try {
1161: //noinspection unchecked
1162: ret = (List<String[]>) Class.forName(
1163: "com.flexive.core.JDK6Scripting").getMethod(
1164: "getAvailableScriptEngines", new Class[0])
1165: .invoke(null);
1166: } catch (Exception e) {
1167: LOG.error(e);
1168: }
1169: }
1170: if (ret == null)
1171: ret = new ArrayList<String[]>(2);
1172: String groovyVersion = org.codehaus.groovy.runtime.InvokerHelper
1173: .getVersion();
1174: ret.add(0,
1175: new String[] {
1176: "groovy",
1177: "groovy: Groovy v"
1178: + FxSharedUtils
1179: .getBundledGroovyVersion()
1180: + " (Bundled GroovyShell v"
1181: + FxSharedUtils
1182: .getBundledGroovyVersion()
1183: + ")" });
1184: ret.add(0,
1185: new String[] {
1186: "gy",
1187: "gy: Groovy v"
1188: + FxSharedUtils
1189: .getBundledGroovyVersion()
1190: + " (Bundled GroovyShell v"
1191: + FxSharedUtils
1192: .getBundledGroovyVersion()
1193: + ")" });
1194: return ret;
1195: }
1196:
1197: /**
1198: * Execute a script.
1199: * This method does not check the calling user's role nor does it cache scripts.
1200: * It should only be used to execute code from the groovy console or code that is not to be expected to
1201: * be run more than once.
1202: *
1203: * @param name name of the script, extension is needed to choose interpreter
1204: * @param binding bindings to apply
1205: * @param code the script code
1206: * @return last script evaluation result
1207: * @throws FxApplicationException on errors
1208: */
1209: private FxScriptResult internal_runScript(String name,
1210: FxScriptBinding binding, String code)
1211: throws FxApplicationException {
1212: if (!FxSharedUtils.isGroovyScript(name)
1213: && FxSharedUtils.USE_JDK6_EXTENSION) {
1214: try {
1215: return (FxScriptResult) Class.forName(
1216: "com.flexive.core.JDK6Scripting").getMethod(
1217: "runScript",
1218: new Class[] { String.class,
1219: FxScriptBinding.class, String.class })
1220: .invoke(null, name, binding, code);
1221: } catch (Exception e) {
1222: if (e instanceof FxApplicationException)
1223: throw (FxApplicationException) e;
1224: if (e instanceof InvocationTargetException
1225: && e.getCause() != null) {
1226: throw new FxInvalidParameterException(name, e
1227: .getCause(),
1228: "ex.general.scripting.exception", name, e
1229: .getCause().getMessage())
1230: .asRuntimeException();
1231: }
1232: throw new FxInvalidParameterException(name, e,
1233: "ex.general.scripting.exception", name, e
1234: .getMessage()).asRuntimeException();
1235: }
1236: }
1237: if (name == null)
1238: name = "unknown";
1239: if (binding != null) {
1240: if (!binding.getProperties().containsKey("ticket"))
1241: binding.setVariable("ticket", FxContext.get()
1242: .getTicket());
1243: if (!binding.getProperties().containsKey("environment"))
1244: binding.setVariable("environment", CacheAdmin
1245: .getEnvironment());
1246: binding.setVariable("scriptname", name);
1247: }
1248: if (FxSharedUtils.isGroovyScript(name)) {
1249: //we prefer the native groovy binding
1250: try {
1251: GroovyShell shell = new GroovyShell();
1252: Script script = shell.parse(code);
1253: if (binding != null)
1254: script.setBinding(new Binding(binding
1255: .getProperties()));
1256: Object result = script.run();
1257: return new FxScriptResult(binding, result);
1258: } catch (Throwable e) {
1259: if (e instanceof FxApplicationException)
1260: throw (FxApplicationException) e;
1261: LOG.error("Scripting error: " + e.getMessage(), e);
1262: throw new FxInvalidParameterException(name,
1263: "ex.general.scripting.exception", name, e
1264: .getMessage());
1265: }
1266: }
1267: throw new FxInvalidParameterException(name,
1268: "ex.general.scripting.needJDK6", name)
1269: .asRuntimeException();
1270: }
1271:
1272: /**
1273: * {@inheritDoc}
1274: */
1275: public FxScriptMapping loadScriptMapping(Connection _con,
1276: long scriptId) throws FxLoadException, SQLException {
1277: FxScriptMapping mapping;
1278: PreparedStatement ps_a = null, ps_t = null;
1279: String sql;
1280: Connection con = _con;
1281: if (con == null)
1282: con = Database.getDbConnection();
1283:
1284: List<FxScriptMappingEntry> e_ass;
1285: List<FxScriptMappingEntry> e_types;
1286: FxEnvironmentImpl environment = ((FxEnvironmentImpl) CacheAdmin
1287: .getEnvironment()).deepClone();
1288:
1289: try {
1290: // 1 2 3 4
1291: sql = "SELECT ASSIGNMENT,DERIVED_USAGE,ACTIVE,STYPE FROM "
1292: + TBL_SCRIPT_MAPPING_ASSIGN + " WHERE SCRIPT=?";
1293: ps_a = con.prepareStatement(sql);
1294: sql = "SELECT TYPEDEF,DERIVED_USAGE,ACTIVE,STYPE FROM "
1295: + TBL_SCRIPT_MAPPING_TYPES + " WHERE SCRIPT=?";
1296: ps_t = con.prepareStatement(sql);
1297: ResultSet rs;
1298:
1299: ps_a.setLong(1, scriptId);
1300: ps_t.setLong(1, scriptId);
1301: rs = ps_a.executeQuery();
1302: e_ass = new ArrayList<FxScriptMappingEntry>(20);
1303: e_types = new ArrayList<FxScriptMappingEntry>(20);
1304: while (rs != null && rs.next()) {
1305: long[] derived;
1306: if (!rs.getBoolean(2))
1307: derived = new long[0];
1308: else {
1309: List<FxAssignment> ass = environment
1310: .getDerivedAssignments(rs.getLong(1));
1311: derived = new long[ass.size()];
1312: for (int i = 0; i < ass.size(); i++)
1313: derived[i] = ass.get(i).getId();
1314: }
1315: e_ass.add(new FxScriptMappingEntry(FxScriptEvent
1316: .getById(rs.getLong(4)), scriptId, rs
1317: .getBoolean(3), rs.getBoolean(2),
1318: rs.getLong(1), derived));
1319: }
1320: rs = ps_t.executeQuery();
1321: while (rs != null && rs.next()) {
1322: long[] derived;
1323: if (!rs.getBoolean(2))
1324: derived = new long[0];
1325: else {
1326: List<FxType> types = environment.getType(
1327: rs.getLong(1)).getDerivedTypes();
1328: derived = new long[types.size()];
1329: for (int i = 0; i < types.size(); i++)
1330: derived[i] = types.get(i).getId();
1331: }
1332: e_types.add(new FxScriptMappingEntry(FxScriptEvent
1333: .getById(rs.getLong(4)), scriptId, rs
1334: .getBoolean(3), rs.getBoolean(2),
1335: rs.getLong(1), derived));
1336: }
1337: mapping = new FxScriptMapping(scriptId, e_types, e_ass);
1338:
1339: } catch (SQLException exc) {
1340: throw new FxLoadException(LOG, exc,
1341: "ex.scripting.mapping.load.failed", exc
1342: .getMessage());
1343: } catch (FxNotFoundException e) {
1344: throw new FxLoadException(e);
1345: } finally {
1346: try {
1347: if (ps_t != null)
1348: ps_t.close();
1349: } catch (SQLException e) {
1350: //ignore
1351: }
1352: if (_con == null) {
1353: Database.closeObjects(ScriptingEngineBean.class, con,
1354: ps_a);
1355: }
1356: }
1357: return mapping;
1358:
1359: }
1360: }
|