У меня возникла ситуация, когда мне нужно определить право одного объекта на «езду» на другом. Правила для транспортных средств дико запутаны, и я хотел бы иметь возможность менять их без перезапуска или перекомпиляции моего проекта.
Это работает, но в основном заставляет моих друзей по безопасности биться в конвульсиях и говорить на языках:
class SweetRider{
String stuff
BigDecimal someNumber
BigDecimal anotherNumber
}
class SweetVehicle{
static hasMany=[constraintLinkers:VehicleConstraintLinker]
String vehicleName
Boolean canIRideIt(SweetRider checkRider){
def checkList = VehicleConstraintLinker.findAllByVehicle(this)
checkList.each{
def theClosureObject = it.closureConstraint
def iThinkINeedAShell = new GroovyShell()
def checkerThing = iThinkINeedAShell.evaluate(theClosureObject.closureText)
def result = checkerThing(checkRider)
return result
}
}
}
class VehicleConstraintLinker{
static belongsTo = [closureConstraint:ConstraintByClosure, vehicle:SweetVehicle]
}
class ConstraintByClosure{
String humanReadable
String closureText
static hasMany = [vehicleLinkers:VehicleConstraintLinker]
}
Итак, если я хочу добавить правило, согласно которому вы имеете право на определенное транспортное средство только в том случае, если ваши «вещи» — это «пегги» или «вафли», а ваш someNumber больше, чем ваш otherNumber, все, что мне нужно сделать, это следующее:
Создайте новый ConstraintByClosure с humanReadable = "peggy waffle some#>" (это удобочитаемое объяснение), а затем добавьте эту строку в качестве closureText
{
checkRider->if(
["peggy","waffles"].contains(checkRider.stuff) &&
checkRider.someNumber > checkRider.anotherNumber ) {
return true
}
else {
return false
}
}
Затем я просто создаю VehicleConstraintLinker, чтобы связать его, и вуаля.
У меня такой вопрос: есть ли способ ограничить возможности GroovyShell? Могу ли я сделать так, чтобы он не мог изменять какие-либо файлы, глобальные переменные или данные базы данных? Этого достаточно?