All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ceylon.modules.api.runtime.AbstractRuntime Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/*
 * Copyright 2011 Red Hat inc. and third party contributors as noted 
 * by the author tags.
 * 
 * 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 ceylon.modules.api.runtime;

import java.lang.reflect.Modifier;

import ceylon.modules.CeylonRuntimeException;
import ceylon.modules.Configuration;
import ceylon.modules.spi.Constants;
import ceylon.modules.spi.runtime.ClassLoaderHolder;

import com.redhat.ceylon.common.JVMModuleUtil;

/**
 * Abstract Ceylon Modules runtime.
 * Useful for potential extension.
 *
 * @author Ales Justin
 */
public abstract class AbstractRuntime implements ceylon.modules.spi.runtime.Runtime {

    public static final String MODULE_INFO_CLASS = ".$module_";
    public static final String OLD_MODULE_INFO_CLASS = ".module_";
    

    protected static void invokeRun(ClassLoaderHolder clh, String moduleName, String ceylonRunnableName, final String[] args) throws Exception {
        final Class runClass;
        ClassLoader cl = clh.getClassLoader();
        ClassLoader oldClassLoader = SecurityActions.setContextClassLoader(cl);
        try {
            try {
                String javaClassName = JVMModuleUtil.javaClassNameFromCeylon(moduleName, ceylonRunnableName);
                if (ceylonRunnableName == null) {
                    ceylonRunnableName = moduleName + "::" + JVMModuleUtil.RUN_INFO_CLASS;
                }
                runClass = cl.loadClass(javaClassName);
            } catch (ClassNotFoundException cnfe) {
                String type = Character.isUpperCase(ceylonRunnableName.charAt(0)) ? "class" : "function";
                String msg = String.format("Could not find toplevel %s '%s'.", type, ceylonRunnableName);
                if (!moduleName.equals(Constants.DEFAULT.toString()) && !ceylonRunnableName.contains(".") && !ceylonRunnableName.contains("::")) {
                    msg += String.format(" Class and method names need to be fully qualified, maybe you meant '%s'?", moduleName + "::" + ceylonRunnableName);
                }
                //msg += " [" + clh + "]";
                throw new CeylonRuntimeException(msg);
            }
            
            if ((runClass.getModifiers()&Modifier.PUBLIC) == 0) {
                String type = Character.isUpperCase(ceylonRunnableName.charAt(0)) ? "class" : "function";
                String msg = String.format("Cannot run toplevel %s '%s': it should be shared.", type, ceylonRunnableName);
                throw new CeylonRuntimeException(msg);
            }
            try {
                SecurityActions.invokeRun(runClass, args);
            } catch (NoSuchMethodException ex) {
                String type = Character.isUpperCase(ceylonRunnableName.charAt(0)) ? "class" : "function";
                String msg = String.format("Cannot run toplevel %s '%s': it should have no parameters or they should all have default values.", type, ceylonRunnableName);
                throw new CeylonRuntimeException(msg);
            }
        } finally {
            SecurityActions.setContextClassLoader(oldClassLoader);
        }
    }
    
 

    public void execute(Configuration conf) throws Exception {
        String exe = conf.module;
        // FIXME: argument checks could be done earlier
        if (exe == null) {
            throw new CeylonRuntimeException("No initial module defined");
        }

        int p = exe.indexOf("/");
        if (p == 0) {
            throw new CeylonRuntimeException("Missing runnable info: " + exe);
        }
        if (p == exe.length() - 1) {
            throw new CeylonRuntimeException("Missing version info: " + exe);
        }

        String name = exe.substring(0, p > 0 ? p : exe.length());
        String mv = (p > 0 ? exe.substring(p + 1) : null);

        final ClassLoaderHolder clh = createClassLoader(name, mv, conf);

        execute(conf, name, clh);
    }

    protected void execute(Configuration conf, String name, ClassLoaderHolder clh) throws Exception {
        invokeRun(clh, name, conf.run, conf.arguments);
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy