001    package org.apache.turbine.modules;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.List;
023    
024    import org.apache.turbine.Turbine;
025    import org.apache.turbine.TurbineConstants;
026    import org.apache.turbine.pipeline.PipelineData;
027    import org.apache.turbine.services.assemblerbroker.AssemblerBrokerService;
028    import org.apache.turbine.services.assemblerbroker.TurbineAssemblerBroker;
029    import org.apache.turbine.util.RunData;
030    
031    /**
032     * This is the base class for the loaders. It contains code that is
033     * used across all of the loaders. It also specifies the interface
034     * that is required to be called a Loader.
035     *
036     * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
037     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
038     * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
039     * @version $Id: GenericLoader.java 1078552 2011-03-06 19:58:46Z tv $
040     */
041    public abstract class GenericLoader<T extends Assembler>
042    {
043        /** The Assembler Broker Service */
044        protected AssemblerBrokerService ab = TurbineAssemblerBroker.getService();
045    
046        /** @serial This can be serialized */
047        private boolean reload = false;
048    
049        /** Base packages path for Turbine */
050        private static final String TURBINE_PACKAGE = "org.apache.turbine.modules";
051    
052        /** Packages paths for Turbine */
053        private static List<String> TURBINE_PACKAGES = null;
054    
055        /**
056         * Basic constructor for creating a loader.
057         */
058        public GenericLoader()
059        {
060            super();
061        }
062    
063        /**
064         * Attempts to load and execute the external action that has been
065         * set.
066         * Should revert to abstract when RunData has gone.
067         * @exception Exception a generic exception.
068         */
069        public void exec(PipelineData pipelineData, String name)
070                throws Exception
071        {
072            RunData data = getRunData(pipelineData);
073            exec(data, name);
074        }
075    
076    
077        /**
078         * Attempts to load and execute the external action that has been
079         * set.
080         * @deprecated Use of this method should be avoided. Use
081         * <code>exec(PipelineData data, String name)</code> instead.
082         * @exception Exception a generic exception.
083         */
084        @Deprecated
085        public abstract void exec(RunData data, String name)
086            throws Exception;
087    
088        /**
089         * Commented out.
090         * This method should return the complete classpath + name.
091         *
092         * @param name
093         * @return
094         *
095         public abstract String getClassName(String name);
096         */
097    
098        /**
099         * Returns whether or not this external action is reload itself.
100         * This is in cases where the Next button would be clicked, but
101         * since we are checking for that, we would go into an endless
102         * loop.
103         *
104         * @return True if the action is reload.
105         */
106        public boolean reload()
107        {
108            return this.reload;
109        }
110    
111        /**
112         * Sets whether or not this external action is reload itself.
113         * This is in cases where the Next button would be clicked, but
114         * since we are checking for that, we would go into an endless
115         * loop.
116         *
117         * @param reload True if the action must be marked as reload.
118         * @return Itself.
119         */
120        public GenericLoader setReload(boolean reload)
121        {
122            this.reload = reload;
123            return this;
124        }
125    
126        /**
127         * Gets the base package where Turbine should find its default
128         * modules.
129         *
130         * @return A String with the base package name.
131         */
132        public static String getBasePackage()
133        {
134            return TURBINE_PACKAGE;
135        }
136    
137        /**
138         * Gets the package list where Turbine should find its
139         * modules.
140         *
141         * @return A List with the package names (including the base package).
142         */
143        @SuppressWarnings("unchecked")
144        public static List<String> getPackages()
145        {
146            if (TURBINE_PACKAGES == null)
147            {
148                TURBINE_PACKAGES =
149                    Turbine.getConfiguration().getList(TurbineConstants.MODULE_PACKAGES);
150            }
151    
152            List<String> packages = TURBINE_PACKAGES;
153    
154            if (!packages.contains(TURBINE_PACKAGE))
155            {
156                packages.add(TURBINE_PACKAGE);
157            }
158    
159            return packages;
160        }
161    
162        /**
163         * Pulls out an instance of the object by name.  Name is just the
164         * single name of the object.
165         *
166         * @param type Type of the assembler.
167         * @param name Name of object instance.
168         * @return A Screen with the specified name, or null.
169         * @exception Exception a generic exception.
170         */
171        protected T getAssembler(String type, String name)
172            throws Exception
173        {
174            T asm = null;
175    
176            try
177            {
178                if (ab != null)
179                {
180                    // Attempt to load the assembler
181                    asm = (T) ab.getAssembler(type, name);
182                }
183            }
184            catch (ClassCastException cce)
185            {
186                // This can alternatively let this exception be thrown
187                // So that the ClassCastException is shown in the
188                // browser window.  Like this it shows "Screen not Found"
189                asm = null;
190            }
191    
192            if (asm == null)
193            {
194                // If we did not find a screen we should try and give
195                // the user a reason for that...
196                // FIX ME: The AssemblerFactories should each add it's
197                // own string here...
198                List<String> packages = GenericLoader.getPackages();
199    
200                throw new ClassNotFoundException(
201                        "\n\n\tRequested " + type + " not found: " + name +
202                        "\n\tTurbine looked in the following " +
203                        "modules.packages path: \n\t" + packages.toString() + "\n");
204            }
205    
206            return asm;
207        }
208    
209        /**
210         * Helper method to cast from PipelineData to RunData. This will go when
211         * the pipeline is fully implemented and the RunData-methods are removed
212         *
213         * @param pipelineData a PipelineData object
214         *
215         * @return the input object casted to RunData
216         */
217        private RunData getRunData(PipelineData pipelineData)
218        {
219            if(!(pipelineData instanceof RunData))
220            {
221                throw new RuntimeException("Can't cast to rundata from pipeline data.");
222            }
223            return (RunData)pipelineData;
224        }
225    }