Package org.apache.cocoon.components.language.programming

Source Code of org.apache.cocoon.components.language.programming.CompiledProgrammingLanguage

/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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.apache.cocoon.components.language.programming;

import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.parameters.ParameterException;

import org.apache.cocoon.Constants;
import org.apache.cocoon.components.language.LanguageException;
import org.apache.cocoon.components.language.programming.java.JavaProgram;
import org.apache.cocoon.util.ClassUtils;
import org.apache.cocoon.util.IOUtils;

import java.io.File;

/**
* A compiled programming language. This class extends <code>AbstractProgrammingLanguage</code> adding support for compilation
* and object program files
* @author <a href="mailto:ricardo@apache.org">Ricardo Rocha</a>
* @version CVS $Id: CompiledProgrammingLanguage.java 30932 2004-07-29 17:35:38Z vgritsenko $
*/
public abstract class CompiledProgrammingLanguage extends AbstractProgrammingLanguage implements Contextualizable {

    /** The compiler */
    protected Class compilerClass;

    /** The local classpath */
    protected String classpath;

    /** The source deletion option */
    protected boolean deleteSources = false;

    /**
     * Set the configuration parameters. This method instantiates the sitemap-specified language compiler
     * @param params The configuration parameters
     * @exception ParameterException If the language compiler cannot be loaded
     */
    public void parameterize(Parameters params) throws ParameterException {
        super.parameterize(params);

        String compilerClass = params.getParameter("compiler");
        try {
            this.compilerClass = ClassUtils.loadClass(compilerClass);
        } catch (ClassNotFoundException e) {
            throw new ParameterException("Unable to load compiler: " + compilerClass, e);
        }
        this.deleteSources = params.getParameterAsBoolean("delete-sources", false);
    }

    /**
     * Set the context
     * @param context The context
     */
    public void contextualize(Context context) throws ContextException {
        this.classpath = (String) context.get(Constants.CONTEXT_CLASSPATH);
    }

    /**
     * Return the language's canonical object file extension.
     * @return The object file extension
     */
    public abstract String getObjectExtension();

    /**
     * Unload a previously loaded program
     * @param program A previously loaded object program
     * @exception LanguageException If an error occurs during unloading
     */
    public abstract void doUnload(Object program) throws LanguageException;

    /**
     * Unload a previously loaded program given its original filesystem location
     * @param program The previously loaded object program
     * @param filename The base filename of the object program
     * @param baseDirectory The directory contaning the object program file
     * @exception LanguageException If an error occurs
     */
    protected final void doUnload(Object program, String filename, File baseDirectory) throws LanguageException {
        int index = filename.lastIndexOf(File.separator);
        String dir = filename.substring(0, index);
        String file = filename.substring(index + 1);

        File baseDir = new File(baseDirectory, dir);
        File[] files = baseDir.listFiles();

        for (int i = 0;(files != null) && (i < files.length); i++) {
            if (files[i].getName().startsWith(file)) {
                files[i].delete();
            }
        }
        this.doUnload(program);
    }

    /**
     * Actually load an object program from a file.
     * @param filename The object program base file name
     * @param baseDirectory The directory containing the object program file
     * @return The loaded object program
     * @exception LanguageException If an error occurs during loading
     */
    protected abstract Class loadProgram(String filename, File baseDirectory) throws LanguageException;

    /**
     * Compile a source file yielding a loadable object file.
     * @param filename The object program base file name
     * @param baseDirectory The directory containing the object program file
     * @param encoding The encoding expected in the source file or <code>null</code> if it is the platform's default encoding
     * @exception LanguageException If an error occurs during compilation
     */
    protected abstract void compile(String filename, File baseDirectory, String encoding) throws LanguageException;

    /**
     * Preload an object program from a file.
     * This method does not compiles the corresponding source file.
     *
     * @param filename The object program base file name
     * @param baseDirectory The directory containing the object program file
     * @param encoding The encoding expected in the source file or <code>null</code> if it is the platform's default encoding
     * @return The loaded object program
     * @exception LanguageException If an error occurs during compilation
     */
    public Program preload(String filename, File baseDirectory, String encoding) throws LanguageException {
        // Don't need to test for existence of the object code as it might be bundled into the WAR.
        try {
            Class program = this.loadProgram(filename, baseDirectory);
            // Create and discard test instance.
            program.newInstance();
            return new JavaProgram(program);
        } catch (Throwable t) {
            throw new LanguageException("Unable to preload program " + filename, t);
        }
    }

    /**
     * Load an object program from a file.
     * This method compiles the corresponding source file if necessary.
     *
     * @param filename The object program base file name
     * @param baseDirectory The directory containing the object program file
     * @param encoding The encoding expected in the source file or <code>null</code> if it is the platform's default encoding
     * @return The loaded object program
     * @exception LanguageException If an error occurs during compilation
     */
    public Program load(String filename, File baseDirectory, String encoding) throws LanguageException {

        // Does source file exist?
        File sourceFile = new File(baseDirectory, filename + "." + this.getSourceExtension());
        if (!sourceFile.exists()) {
            throw new LanguageException("Can't load program - File doesn't exist: " + IOUtils.getFullFilename(sourceFile));
        }
        if (!sourceFile.isFile()) {
            throw new LanguageException("Can't load program - File is not a normal file: " + IOUtils.getFullFilename(sourceFile));
        }
        if (!sourceFile.canRead()) {
            throw new LanguageException("Can't load program - File cannot be read: " + IOUtils.getFullFilename(sourceFile));
        }
        this.compile(filename, baseDirectory, encoding);
        if (this.deleteSources) {
            sourceFile.delete();
        }
        Class program = this.loadProgram(filename, baseDirectory);

        // Try to instantiate once to ensure there are no exceptions thrown in the constructor
        try {
            // Create and discard test instance
            program.newInstance();
        } catch(IllegalAccessException iae) {
            getLogger().debug("No public constructor for class " + program.getName());
        } catch(Exception e) {
            // Unload class and delete the object file, or it won't be recompiled
            // (leave the source file to allow examination).
            this.doUnload(program);
            new File(baseDirectory, filename + "." + this.getObjectExtension()).delete();

            String message = "Error while instantiating " + filename;
            getLogger().debug(message, e);
            throw new LanguageException(message, e);
        }

        if (program == null) {
            throw new LanguageException("Can't load program : " + baseDirectory.toString() + File.separator + filename);
        }

        return new JavaProgram(program);
    }
}
TOP

Related Classes of org.apache.cocoon.components.language.programming.CompiledProgrammingLanguage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.