001    /*****************************************************************************
002     * Copyright (C) NanoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the LICENSE.txt file.                                                     *
007     *                                                                           *
008     *****************************************************************************/
009    package org.nanocontainer.script;
010    
011    import java.io.IOException;
012    import java.io.InputStream;
013    import java.io.InputStreamReader;
014    import java.io.Reader;
015    import java.net.URL;
016    
017    import org.nanocontainer.integrationkit.LifecycleContainerBuilder;
018    import org.picocontainer.MutablePicoContainer;
019    import org.picocontainer.PicoContainer;
020    
021    /**
022     * Base abstract class for script-based container builders based.
023     *
024     * @author Aslak Hellesøy
025     * @author Obie Fernandez
026     * @author Mauro Talevi
027     * @version $Revision: 2164 $
028     */
029    public abstract class ScriptedContainerBuilder extends LifecycleContainerBuilder {
030        private final Reader scriptReader;
031        private final URL scriptURL;
032        private final ClassLoader classLoader;
033    
034        public ScriptedContainerBuilder(Reader script, ClassLoader classLoader) {
035            this.scriptReader = script;
036            if (script == null) {
037                throw new NullPointerException("script");
038            }
039            this.scriptURL = null;
040            this.classLoader = classLoader;
041            if ( classLoader == null) {
042                throw new NullPointerException("classLoader");
043            }
044        }
045    
046        public ScriptedContainerBuilder(URL script, ClassLoader classLoader) {
047            this.scriptReader = null;        
048            this.scriptURL = script;
049            if (script == null) {
050                throw new NullPointerException("script");
051            }
052            this.classLoader = classLoader;
053            if ( classLoader == null) {
054                throw new NullPointerException("classLoader");
055            }
056        }
057    
058        protected final PicoContainer createContainer(PicoContainer parentContainer, Object assemblyScope) {
059            try {
060                return createContainerFromScript(parentContainer, assemblyScope);
061            } finally {
062                try {
063                    Reader reader = getScriptReader();
064                    if (reader != null) {
065                        reader.close();
066                    }
067                } catch (IOException e) {
068                    // do nothing. we've given it our best try, now get on with it
069                }
070            }
071        }
072    
073        protected final ClassLoader getClassLoader() {
074            return classLoader;
075        }
076        
077        protected final InputStream getScriptInputStream() throws IOException{
078            if ( scriptReader != null ){
079                return new InputStream() {
080                    public int read() throws IOException {
081                        return scriptReader.read();
082                    }
083                };
084            }
085            return scriptURL.openStream();
086        }
087    
088        protected final Reader getScriptReader() throws IOException{
089            if ( scriptReader != null ){
090                return scriptReader;
091            }
092            return new InputStreamReader(scriptURL.openStream());
093        }
094        
095        // TODO: This should really return NanoContainer using a nano variable in the script. --Aslak
096        protected abstract PicoContainer createContainerFromScript(PicoContainer parentContainer, Object assemblyScope);
097    
098        protected void composeContainer(MutablePicoContainer container, Object assemblyScope) {
099            // do nothing. assume that this is done in createContainer().
100        }
101    }