001    /*
002      Copyright (C) 2001-2002 Renaud Pawlak <renaud@aopsys.com>
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public
015      License along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
017      USA */
018    
019    package org.objectweb.jac.core;
020    
021    import java.io.*;
022    import java.util.*;
023    import org.apache.log4j.Logger;
024    import org.objectweb.jac.util.*;
025    
026    /**
027     * This class represents the JAC applications.
028     *
029     * <p>Before it is actually started, each application must define a
030     * name, some path informations, and a set of aspect configurations
031     * (one for each aspect the application needs to use) by instantiating
032     * and configuring this class. Then, the system registers the new
033     * application instance into the application repository of the system.
034     *
035     * <p>At a user-level, an application configuration is described in
036     * application descriptor files (*.acc). A typical application
037     * descriptor is:
038     *
039     * <pre class=code>
040     * // file myApp.acc
041     * applicationName: myApp
042     * lauchingClass: myPath.Run
043     * aspects: \
044     *     rtti rtti.acc true \
045     *     session session.acc false \
046     *     persistence persistence.acc true \
047     *     gui gui.acc true
048     * </pre>
049     *
050     * @see #Application(String,String,String,String[])
051     * @see #addAcConfiguration(ACConfiguration)
052     * @see ACConfiguration#ACConfiguration(Application,String,String,boolean)
053     * @see ApplicationRepository */
054    
055    public class Application implements Serializable {
056        static Logger logger = Logger.getLogger("application");
057    
058        String name;
059        String path;
060        String constructorClass;
061        String[] arguments;
062        /*org.objectweb.jac.lib.java.util.*/Vector acConfigurations = 
063        new /*org.objectweb.jac.lib.java.util.*/Vector();
064        Hashtable acs = new Hashtable();
065        boolean instantiated = false;
066    
067        Properties props = new Properties();
068    
069        /**
070         * Creates a new application.
071         *
072         * @param name the name of the application
073         * @param path the path of the application (root directory). If
074         * it's null, the current directory is used
075         * @param constructorClass the path of the launching class
076         * accessible within the current class path)
077         * @param arguments the launching arguments */
078    
079        public Application(String name, String path,
080                           String constructorClass, String[] arguments) {
081            this.name = name;
082            if (path==null) {
083                path = System.getProperty("user.dir");
084            }
085            this.path = path;
086            this.constructorClass = constructorClass;
087            this.arguments = arguments;
088            // put the application in the context of this thread
089            Collaboration.get().setCurApp(name);
090        }
091    
092        /**
093         * Inits the application by creating and weaving the aspects
094         * configuration that are not woven on demand. */
095    
096        public void init() {
097            Iterator it = acConfigurations.iterator();
098            while( it.hasNext() ) {
099                ACConfiguration acConf = (ACConfiguration) it.next();
100                if ( ! acConf.getWeaveOnDemand() ) {
101                    //acConf.weave();
102                    ApplicationRepository.get().extend(name,acConf.getName());
103                }
104            }
105        }
106    
107    
108        /**
109         * Gets the name of the application.
110         *
111         * @return the application's name */
112    
113        public String getName() {
114            return name;
115        }
116    
117        /**
118         * Sets the application's name.
119         *
120         * @param name the application's name */
121    
122        public void setName(String name) {
123            this.name = name;
124        }   
125    
126        /**
127         * Gets the path of the application (its root directory).
128         *
129         * @return the application's path
130         * @see #setPath(String) */
131    
132        public String getPath() {
133            return path;
134        }
135    
136        /**
137         * The path's setter.
138         *
139         * @param path the new application root directory
140         * @see #getPath() */
141    
142        public void setPath(String path) {
143            this.path = path;
144        }
145    
146        /**
147         * Gets the path of the launching class (that implements the static
148         * <code>main(String[])</code> method).
149         *
150         * @return the launching class */
151    
152        public String getConstructorClass() {
153            return constructorClass;
154        }
155    
156        /**
157         * Gets the path of the launching class (that implements the static
158         * <code>main(String[])</code> method).
159         *
160         * @param constructorClass the launching class */
161    
162        public void setConstructorClass(String constructorClass) {
163            this.constructorClass = constructorClass;
164        }
165    
166        /**
167         * Tells if this application currently realizes a given aspect
168         * component. <b>Not available yet</b>.
169         *
170         * @param acName the aspect component name
171         * @return true if the application realizes the given aspect */
172    
173        public boolean realizes(String acName) {
174            return false; //acs.containsKey( "acName" );
175        }
176    
177        /**
178         * Tells if this application configures a given aspect
179         * component. <b>Not available yet</b>. 
180         *
181         * @param acName the aspect component name
182         * @return true if the application configures the given aspect */
183    
184        public boolean configures(String acName) {
185            return false; //acs.containsKey( "acName" );
186        }      
187    
188        /**
189         * Adds an aspect component configuration for this application.
190         *
191         * @param configuration the new configuration */
192    
193        public void addAcConfiguration(ACConfiguration configuration) {
194            acConfigurations.add(configuration);
195        }
196    
197        /**
198         * Removes an aspect component configuration for this application.
199         *
200         * @param configuration the configuration to remove */
201    
202        public void removeAcConfiguration(ACConfiguration configuration) {
203            acConfigurations.remove(configuration.getName());
204        }
205    
206        /**
207         * Returns all the configurations for the current application.
208         *
209         * @return a collection of configurations */
210    
211        public Collection getAcConfigurations() {
212            return (org.objectweb.jac.lib.java.util.Vector)acConfigurations.clone();
213        }
214    
215        /**
216         * Gets a configurations from its name (the name of the aspect as
217         * defined in the <code>jac.prop</code> file.
218         *
219         * @param name the aspect name
220         * @return the corresponding configuration */
221    
222        public ACConfiguration getAcConfiguration(String name) {
223            Iterator i = acConfigurations.iterator();
224            while(i.hasNext()) {
225                ACConfiguration conf = (ACConfiguration)i.next();
226                if (conf.getName().equals(name))
227                    return conf;
228            }
229            return null;
230        }
231    
232        /**
233         * Starts the application with its current aspect component
234         * configurations.
235         *
236         * <p>If the application is already instantiated or if the launching
237         * path is not found, then do nothing. 
238         */
239    
240        public void start() {
241            if (instantiated) {
242                logger.warn("application '" + name + "' is already instantiated");
243                return;
244            }
245            try {
246                logger.info("launching application "+this);
247                Class.forName(constructorClass)
248                    .getMethod( "main", new Class[] { String[].class } )
249                    .invoke( null, new Object[] { arguments } );
250                instantiated = true;
251                Iterator it = acConfigurations.iterator();
252                while( it.hasNext() ) {
253                    ACConfiguration conf = (ACConfiguration) it.next();
254                    if( ! conf.weaveOnDemand ) {
255                        conf.weave();
256                    }
257                }
258    
259            } catch(Exception e) {
260                logger.error("application '" + name + "' unable to start",e);
261            }
262        }
263    
264    
265        /**
266         * Returns a string representation of this application.
267         * @return a string */
268    
269        public String toString() {
270            return "Application " + name;
271        }
272    
273    }