/******************************************************************************* * Copyright (c) 2011 GigaSpaces Technologies Ltd. All rights reserved * * Licensed 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.cloudifysource.dsl.internal; import groovy.lang.Closure; import groovy.lang.Script; import java.io.File; import java.io.FileNotFoundException; import java.lang.reflect.InvocationTargetException; import org.apache.commons.beanutils.BeanUtils; import org.cloudifysource.domain.Application; import org.cloudifysource.domain.Service; import org.cloudifysource.dsl.internal.packaging.PackagingException; /** * */ public abstract class BaseApplicationScript extends Script { private static java.util.logging.Logger logger = java.util.logging.Logger .getLogger(BaseApplicationScript.class.getName()); private Object activeObject = null; private Application application; private Object applicationDir; @Override public void setProperty(final String name, final Object value) { if (this.inServiceBlock) { try { handleServiceParameter(name, value); } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (PackagingException e) { throw new RuntimeException(e); } catch (DSLException e) { throw new RuntimeException(e); } } else { applyPropertyToObject(this.activeObject, name, value); } } private void applyPropertyToObject(final Object object, final String name, final Object value) { try { // first check that the property exists BeanUtils.getProperty(object, name); BeanUtils.setProperty(object, name, value); } catch (final IllegalAccessException e) { throw new IllegalArgumentException("Failed to set property " + name + " to " + value, e); } catch (final InvocationTargetException e) { throw new IllegalArgumentException("Failed to set property " + name + " to " + value, e); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("Property " + name + " does not exist in class: " + this.activeObject.getClass().getName(), e); } } private void handleServiceParameter(final String name, final Object value) throws FileNotFoundException, PackagingException, DSLException { if (!this.serviceBlockInitialized) { // first element MUST be name if (!"name".equals(name)) { throw new IllegalArgumentException( "The first declaraion in a service block that is part of an application MUST be its name"); } this.currentService = loadApplicationService(value.toString()); this.serviceBlockInitialized = true; } else { applyPropertyToObject(this.currentService, name, value); } } private Service loadApplicationService(final String serviceName) throws FileNotFoundException, PackagingException, DSLException { // First find the service dir final String serviceDirName = this.applicationDir + File.separator + serviceName; File serviceDir = new File(serviceDirName); if (!serviceDir.exists() || !serviceDir.isDirectory()) { throw new java.lang.IllegalStateException( "Could not find service directory: " + serviceDir + " while loading application"); } // Load the service DSLServiceCompilationResult result = ServiceReader.getServiceFromDirectory(serviceDir); return result.getService(); // execute the closure // swapActiveObject(closure, service); // add the service to the application // application.getServices().add(service); } /** * * @param name name * @param args args * @return null */ public Object methodMissing(final String name, final Object args) { setProperty(name, args); return null; } /** * * @param closure the closure * @return application */ public Application application(final Closure<Object> closure) { this.applicationDir = this.getProperty(DSLUtils.APPLICATION_DIR); if (this.applicationDir == null) { throw new java.lang.IllegalStateException( "Could not read application DSL file as the application Directory was not set"); } this.application = new Application(); // if (context == null) { // context = new ServiceContext(service, null, null); //TODO - fix this // } this.activeObject = this.application; closure.call(); return this.application; } @Override public void println(final Object obj) { logger.info(obj.toString()); } private boolean inServiceBlock = false; private boolean serviceBlockInitialized = false; private Service currentService = null; /** * * @param closure the closure */ public void service(final Closure<Object> closure) { if (inServiceBlock) { throw new java.lang.IllegalStateException( "Nested services are not supported"); } inServiceBlock = true; serviceBlockInitialized = false; currentService = null; closure.call(); if (this.currentService == null) { throw new IllegalArgumentException( "Service element must specify the service name in the first line"); } // add the service to the application application.getServices().add(this.currentService); inServiceBlock = false; serviceBlockInitialized = false; currentService = null; } /** * * @param closure the closure * @param obj the object * @return null */ protected Object swapActiveObject(final Closure<Object> closure, final Object obj) { final Object prevObject = this.activeObject; this.activeObject = obj; closure.setResolveStrategy(Closure.OWNER_ONLY); try { final Object res = closure.call(); activeObject = prevObject; return res; } catch (Exception e) { System.out.println(e); } return null; } }