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.FileInputStream; 022 import java.io.IOException; 023 import java.io.InputStream; 024 import java.io.StreamTokenizer; 025 import java.io.StringReader; 026 import java.lang.NoSuchMethodException; 027 import java.lang.reflect.InvocationTargetException; 028 import java.lang.reflect.Method; 029 import java.lang.reflect.Modifier; 030 import java.net.URLClassLoader; 031 import java.util.Arrays; 032 import java.util.HashMap; 033 import java.util.Hashtable; 034 import java.util.Properties; 035 import java.util.StringTokenizer; 036 import org.apache.log4j.Logger; 037 import org.objectweb.jac.core.rtti.*; 038 import org.objectweb.jac.util.*; 039 040 /** 041 * This class is a repository for all the applications defined in the 042 * JAC system. 043 * 044 * @see Application */ 045 046 public class ApplicationRepository { 047 static Logger logger = Logger.getLogger("jac"); 048 static Logger loggerCP = Logger.getLogger("classpath"); 049 static Logger loggerAspects = Logger.getLogger("aspects"); 050 051 static Hashtable owningApplications = new Hashtable(); 052 053 public static Application getOwningApplication(Wrappee wrappee, 054 ClassItem cl) { 055 if (wrappee!=null) 056 return (Application)owningApplications.get(wrappee); 057 else if (cl!=null) 058 return (Application)owningApplications.get(cl); 059 else 060 return null; 061 } 062 063 public static String getOwningApplicationName(Wrappee wrappee, 064 ClassItem cl) { 065 Application app = getOwningApplication(wrappee,cl); 066 if (app!=null) 067 return app.getName(); 068 else 069 return null; 070 } 071 072 public static void setOwningApplication(Wrappee wrappee,ClassItem cl, 073 Application application) { 074 if(wrappee!=null) 075 owningApplications.put(wrappee,application); 076 else if(cl!=null) 077 owningApplications.put(cl,application); 078 } 079 080 HashMap applications = new HashMap(); 081 082 static ApplicationRepository applicationRepository; 083 084 /** 085 * Returns the application of the current thread. 086 * 087 * @return an application, null if none */ 088 089 public static Application getCurrentApplication() { 090 String appName = (String)Collaboration.get().getCurApp(); 091 if( appName == null ) return null; 092 return (Application)get().applications.get(appName); 093 } 094 095 /** 096 * Launches a JAC program. 097 * 098 * @param args the program arguments (first is the .jac file) */ 099 100 public static void launchProgram(String [] args) { 101 InputStream fis = null; 102 Properties applicationDescriptor = new Properties(); 103 104 try { 105 fis = new FileInputStream(args[0]); 106 applicationDescriptor.load(fis); 107 } catch(Exception e) { 108 ClassLoader loader = ApplicationRepository.class.getClassLoader(); 109 110 loggerCP.debug("trying to load "+args[0]+" with "+loader); 111 fis = loader.getResourceAsStream(args[0]); 112 if (fis == null) { 113 logger.error("cannot find application descriptor "+args[0]); 114 if (loader instanceof URLClassLoader) 115 logger.error(" classpath="+Arrays.asList(((URLClassLoader)loader).getURLs())); 116 return; 117 } 118 try { 119 applicationDescriptor.load(fis); 120 } catch (IOException ioe) { 121 logger.error("failed to read applicationDescriptor descriptor "+ 122 args[0]+": "+ioe); 123 return; 124 } 125 } 126 127 // We must use reflection here because 128 // JacLoader.class!=ApplicationRepository.class.getClassLoader().class 129 ClassLoader loader = ApplicationRepository.class.getClassLoader(); 130 try { 131 loader.getClass().getMethod("readProperties", 132 new Class[] {Properties.class}) 133 .invoke(loader,new Object[] {applicationDescriptor}); 134 } catch (Exception e) { 135 logger.error("failed to read JAC properties from application descriptor "+args[0]); 136 } 137 138 JacPropLoader.addProps(applicationDescriptor); 139 140 String applicationName = 141 applicationDescriptor.getProperty("applicationName"); 142 String launchingClass = 143 applicationDescriptor.getProperty("launchingClass"); 144 String aspects = applicationDescriptor.getProperty("aspects"); 145 String topology = applicationDescriptor.getProperty("topology"); 146 147 if (applicationName==null) { 148 logger.warn("bad application descriptor "+args[0]); 149 return; 150 } 151 152 logger.info("launching application "+applicationName); 153 154 // bind to the given topology if any 155 if (topology!=null) { 156 Class remoteContainerClass = null; 157 try { 158 remoteContainerClass = 159 Class.forName("org.objectweb.jac.core.dist.RemoteContainer"); 160 } catch (ClassNotFoundException e) { 161 logger.fatal("Could not find class org.objectweb.jac.core.dist.RemoteContainer"); 162 System.exit(1); 163 } 164 StringTokenizer st1 = new StringTokenizer(topology); 165 while (st1.hasMoreElements()) { 166 String container = (String)st1.nextElement(); 167 try { 168 remoteContainerClass.getMethod("bindNewContainer", 169 new Class[] {String.class}) 170 .invoke(null,new Object[] {container}); 171 } catch (InvocationTargetException e) { 172 logger.error("Failed to bind to "+container+": "+ 173 e.getTargetException().getMessage()); 174 } catch (Exception e) { 175 logger.error("Failed to bind to "+container+": "+e.getMessage()); 176 } 177 } 178 logger.debug("application topology successfully bound"); 179 } 180 181 // create the application 182 Application app = new Application(applicationName,null, 183 launchingClass,null); 184 185 // create the aspects configurations 186 if (aspects!=null) { 187 StreamTokenizer tokens = 188 new StreamTokenizer(new StringReader(aspects)); 189 tokens.wordChars('/','/'); 190 tokens.wordChars('_','_'); 191 tokens.wordChars('-','-'); 192 tokens.wordChars(':',':'); 193 tokens.wordChars('$','$'); 194 char fileSep = System.getProperty("file.separator").charAt(0); 195 tokens.wordChars(fileSep,fileSep); 196 try { 197 while (tokens.nextToken()!=StreamTokenizer.TT_EOF) { 198 String ac_name = tokens.sval; 199 tokens.nextToken(); 200 String ac_path = tokens.sval; 201 tokens.nextToken(); 202 String ac_weave = tokens.sval; 203 loggerAspects.info( 204 "adding aspect "+ac_name+"["+ac_path+ 205 "]:"+ac_weave+" to "+app); 206 app.addAcConfiguration( 207 new ACConfiguration(app, ac_name, 208 ac_path, 209 (ac_weave.equals("true")?true:false))); 210 } 211 } catch (IOException e) { 212 e.printStackTrace(); 213 } 214 } 215 216 logger.debug("adding application "+app); 217 ApplicationRepository.get().addApplication(app); 218 219 try { 220 String[] appargs = new String[args.length - 1]; 221 if (appargs.length > 0) { 222 System.arraycopy(args, 1, appargs, 0, args.length - 1); 223 } 224 Class lc = Class.forName(launchingClass); 225 try { 226 Method mainMethod = lc.getMethod("main",new Class[] {String[].class}); 227 if (!Modifier.isStatic(mainMethod.getModifiers())) { 228 logger.error("main method of class "+launchingClass+" is not static"); 229 return; 230 } 231 mainMethod.invoke(null,new Object[] {appargs}); 232 } catch (NoSuchMethodException e) { 233 logger.error("No such method "+launchingClass+".main(String[])"); 234 return; 235 } 236 } catch(Exception e) { 237 logger.error(applicationName+" launch failed",e); 238 } 239 ((ACManager)ACManager.get()).afterApplicationStarted(); 240 } 241 242 /** 243 * Launches and initializes the application repository (this method 244 * is called by the system). 245 * 246 * @param args the launching arguments of JAC */ 247 248 public static void main(String[] args) throws Throwable { 249 if (applicationRepository == null) 250 applicationRepository = new ApplicationRepository(); 251 launchProgram(args); 252 } 253 254 public ApplicationRepository() { 255 } 256 257 /** 258 * Gets the sole instance of the application repository within the 259 * local JAC system. 260 * 261 * @return the application repository */ 262 263 public static ApplicationRepository get() { 264 if (applicationRepository == null) { 265 applicationRepository = new ApplicationRepository(); 266 } 267 return applicationRepository; 268 } 269 270 /** 271 * Adds an application within the repository. 272 * 273 * <p>When added, the application is initialized so that the needed 274 * aspects are woven. 275 * 276 * @param app the application to add */ 277 278 public void addApplication(Application app) { 279 logger.info("--- Launching " +app+ " ---"); 280 applications.put(app.getName(), app); 281 app.init(); 282 } 283 284 /** 285 * Returns the applications that have been added to the repository. 286 * 287 * @return a hash map (application's name -> application) 288 * @see #addApplication */ 289 290 public HashMap getApplications() { 291 return applications; 292 } 293 294 /** 295 * Gets an application from its name. 296 * 297 * @param name the application's name 298 * @return the application named <code>name</code> 299 * @see #getApplications() */ 300 301 public Application getApplication(String name) { 302 return (Application) applications.get(name); 303 } 304 305 /** 306 * Extends an application with a given aspect (only if this 307 * application has a configuration for this aspect and if this 308 * aspect is not yet woven). 309 * 310 * @param applicationName the application's name 311 * @param aspectName the aspect's name */ 312 313 public void extend(String applicationName, String aspectName) { 314 if (ACManager.get().getObject(applicationName+"."+aspectName)!=null) 315 return; 316 loggerAspects.info("extending application "+applicationName+ 317 " with "+aspectName); 318 Application application = getApplication(applicationName); 319 if (application == null) { 320 logger.error("No such application to extend: "+applicationName); 321 } 322 ACConfiguration acConf = application.getAcConfiguration(aspectName); 323 if (acConf == null) { 324 logger.error("No such AC configuration: "+aspectName+ 325 " found in "+applicationName); 326 } 327 acConf.weave(); 328 } 329 330 /** 331 * Un-extends an application with a given aspect (only if this 332 * application has a configuration for this aspect and if this 333 * aspect is woven). 334 * 335 * @param applicationName the application's name 336 * @param aspectName the aspect's name */ 337 338 public void unextend(String applicationName, String aspectName) { 339 loggerAspects.info("un-extending application "+applicationName+ 340 " with "+aspectName); 341 Application application = getApplication(applicationName); 342 if (application == null) { 343 logger.error("No such application to extend: "+applicationName); 344 } 345 ACConfiguration acConf = application.getAcConfiguration(aspectName); 346 if (acConf == null) { 347 logger.error("No such AC configuration: "+aspectName+ 348 " found in "+applicationName); 349 } 350 acConf.unweave(); 351 } 352 353 }