blob: a5d73bf71f084723554f52e3efbb5e01f3a0fe9f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.scxml2.env.groovy;
import groovy.lang.Closure;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.SCInstanceObjectInputStream;
import org.apache.commons.scxml2.env.SimpleContext;
/**
* Groovy Context implementation for Commons SCXML.
*/
public class GroovyContext extends SimpleContext {
private static final long serialVersionUID = 1L;
private static final Log log = LogFactory.getLog(GroovyContext.class);
private String scriptBaseClass;
private GroovyEvaluator evaluator;
private GroovyContextBinding binding;
private Map<String, Object> vars;
GroovyContextBinding getBinding() {
if (binding == null) {
binding = new GroovyContextBinding(this);
}
return binding;
}
/**
* Constructor.
*/
public GroovyContext() {
}
/**
* Constructor with initial vars.
*
* @param parent The parent context.
* @param initialVars The initial set of variables.
* @param evaluator The groovy evaluator
*/
public GroovyContext(final Context parent, final Map<String, Object> initialVars, GroovyEvaluator evaluator) {
super(parent, initialVars);
this.evaluator = evaluator;
}
/**
* Constructor with parent context.
*
* @param parent The parent context.
* @param evaluator The groovy evaluator
*/
public GroovyContext(final Context parent, GroovyEvaluator evaluator) {
super(parent);
this.evaluator = evaluator;
}
protected GroovyEvaluator getGroovyEvaluator() {
return evaluator;
}
protected void setGroovyEvaluator(GroovyEvaluator evaluator) {
this.evaluator = evaluator;
}
@Override
public Map<String, Object> getVars() {
return vars;
}
@Override
protected void setVars(final Map<String, Object> vars) {
this.vars = vars;
}
protected void setScriptBaseClass(String scriptBaseClass) {
this.scriptBaseClass = scriptBaseClass;
}
protected String getScriptBaseClass() {
if (scriptBaseClass != null) {
return scriptBaseClass;
}
if (getParent() instanceof GroovyContext) {
return ((GroovyContext)getParent()).getScriptBaseClass();
}
return null;
}
private void writeObject(ObjectOutputStream out) throws IOException {
boolean closureErased = false;
if (vars != null) {
Iterator<Map.Entry<String, Object>> iterator = getVars().entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
if (entry.getValue() != null && entry.getValue() instanceof Closure) {
iterator.remove();
closureErased = true;
}
}
if (closureErased) {
log.warn("Encountered and removed Groovy Closure(s) in the GroovyContext during serialization: these are not supported for (de)serialization");
}
}
out.writeObject(this.scriptBaseClass);
out.writeObject(this.evaluator);
out.writeObject(this.binding);
out.writeObject(this.vars);
}
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException {
this.scriptBaseClass = (String)in.readObject();
this.evaluator = (GroovyEvaluator)in.readObject();
this.binding = (GroovyContextBinding)in.readObject();
SCInstanceObjectInputStream.ClassResolver currentResolver = null;
try {
if (evaluator != null && in instanceof SCInstanceObjectInputStream) {
currentResolver = ((SCInstanceObjectInputStream)in).setClassResolver(osc -> Class.forName(osc.getName(), true, evaluator.getGroovyClassLoader()));
}
this.vars = (Map<String, Object>)in.readObject();
}
finally {
if (in instanceof SCInstanceObjectInputStream) {
((SCInstanceObjectInputStream)in).setClassResolver(currentResolver);
}
}
}
}