001/** 002 * '$RCSfile$' 003 * '$Author: crawl $' 004 * '$Date: 2012-07-25 17:41:30 +0000 (Wed, 25 Jul 2012) $' 005 * '$Revision: 30276 $' 006 * 007 * For Details: 008 * http://www.kepler-project.org 009 * 010 * Copyright (c) 2012 The Regents of the 011 * University of California. All rights reserved. Permission is hereby granted, 012 * without written agreement and without license or royalty fees, to use, copy, 013 * modify, and distribute this software and its documentation for any purpose, 014 * provided that the above copyright notice and the following two paragraphs 015 * appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF 016 * CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, 017 * OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 018 * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE 019 * POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY 020 * DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 022 * SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 023 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 024 * ENHANCEMENTS, OR MODIFICATIONS. 025 */ 026package org.kepler.loader.util; 027 028import java.io.File; 029import java.io.IOException; 030import java.lang.reflect.Modifier; 031import java.net.URL; 032import java.sql.Connection; 033import java.sql.ResultSet; 034import java.sql.SQLException; 035import java.sql.Statement; 036import java.util.HashSet; 037import java.util.LinkedList; 038import java.util.List; 039import java.util.Set; 040 041import org.kepler.Kepler; 042import org.kepler.build.modules.Module; 043import org.kepler.build.modules.ModuleTree; 044import org.kepler.kar.KarDoclet; 045import org.kepler.objectmanager.library.LibraryManager; 046import org.kepler.util.sql.DatabaseFactory; 047import org.kepler.util.sql.HSQL; 048 049import ptolemy.actor.Actor; 050import ptolemy.actor.Director; 051import ptolemy.actor.gui.ConfigurationApplication; 052import ptolemy.data.expr.Parameter; 053import ptolemy.util.MessageHandler; 054 055/** A class to that finds source files whose classes are not in the actor tree. 056 * 057 * TODO: 058 * separate deprecated classes 059 * separate super classes 060 * include some subclasses of Attribute 061 * warn if xml has missing or invalid semantic types 062 * warn if xml has no semantic types in onto:2 063 * 064 * @author Daniel Crawl 065 * @version $Id: FindMissingActors.java 30276 2012-07-25 17:41:30Z crawl $ 066 */ 067public class FindMissingActors { 068 069 /** Find files whose classes are not in the actor tree. 070 * 071 * @param args a list of module names. if empty, all modules in 072 * current suite are searched. 073 */ 074 public static void main(String[] args) { 075 076 // call the module initializers 077 try { 078 Kepler.initialize(); 079 } catch (Exception e) { 080 MessageHandler.error("ERROR initializing modules.", e); 081 System.exit(1); 082 } 083 084 // start the kepler cache 085 086 Kepler.setOntologyIndexFile(); 087 088 _initializeCache(); 089 090 final ModuleTree tree = ModuleTree.instance(); 091 List<Module> modules; 092 if(args.length == 0 || (args.length == 1 && args[0].equals("undefined"))) { 093 modules = tree.getModuleList(); 094 } else { 095 modules = new LinkedList<Module>(); 096 for(String name : args) { 097 final Module module = tree.getModule(name); 098 if(module == null) { 099 System.out.println("Module " + name + " is not in current suite."); 100 } else { 101 modules.add(module); 102 } 103 } 104 } 105 106 for(Module module : modules) { 107 108 final String moduleName = module.getName(); 109 System.out.println("Find missing entries for module " + moduleName); 110 111 // print which files do not have entries 112 try { 113 _printFilesMissingEntries(module); 114 115 } catch(Exception e) { 116 MessageHandler.error("Error finding missing entries.", e); 117 } 118 119 } 120 121 // shutdown the cache and exit 122 _shutdownCache(true); 123 124 } 125 126 127 /** Get a list of source files in a module that are not in the actor cache. */ 128 private static void _printFilesMissingEntries(Module module) throws Exception { 129 130 131 List<String> fileNames = module.getSourceFileNames(); 132 File srcDir = module.getSrc(); 133 134 if(_actorCacheClasses.isEmpty()) { 135 136 Connection conn = null; 137 Statement st = null; 138 ResultSet result = null; 139 try { 140 conn = DatabaseFactory.getDBConnection(); 141 st = conn.createStatement(); 142 result = st.executeQuery("select classname from cachecontenttable "); 143 144 while(result.next()) { 145 _actorCacheClasses.add(result.getString(1)); 146 } 147 } finally { 148 try { 149 if(result != null) { 150 result.close(); 151 } 152 if(st != null) { 153 st.close(); 154 } 155 if(conn != null) { 156 conn.close(); 157 } 158 } catch(SQLException e) { 159 MessageHandler.error("ERROR closing cache database.", e); 160 } 161 } 162 } 163 164 List<String> missing = new LinkedList<String>(); 165 List<String> deprecated = new LinkedList<String>(); 166 167 for(String relativeName : fileNames) { 168 169 String className = relativeName.replace(File.separatorChar, '.'); 170 className = className.substring(0, className.indexOf(".java")); 171 //System.out.println("class is " + className); 172 173 String fileName = new File(srcDir, relativeName).getAbsolutePath(); 174 175 if(!_actorCacheClasses.contains(className)) { 176 177 // make sure class is an actor, director or parameter 178 //System.out.println("checking " + className); 179 Class<?> clazz = null; 180 181 try { 182 clazz = Class.forName(className); 183 } catch(Throwable t) { 184 // ignore 185 continue; 186 } 187 188 // see if the class is an Actor, Director, or Parameter 189 // is not abstract, or an interface 190 if((Actor.class.isAssignableFrom(clazz) || 191 Director.class.isAssignableFrom(clazz) || 192 Parameter.class.isAssignableFrom(clazz)) && 193 !clazz.isInterface() && 194 !Modifier.isAbstract(clazz.getModifiers())) { 195 196 // see if it's deprecated 197 // XXX this always returns false since KarDoclet was not 198 // run for this class. 199 if(KarDoclet.isClassDeprecated(className)) { 200 deprecated.add(fileName); 201 } else { 202 missing.add(fileName); 203 } 204 } 205 } 206 } 207 208 if(!missing.isEmpty()) { 209 System.out.println("Source files not in library:"); 210 for(String name : missing) { 211 System.out.println(name); 212 } 213 } 214 215 if(!deprecated.isEmpty()) { 216 System.out.println("Deprecated source files not in library:"); 217 for(String name : deprecated) { 218 System.out.println(name); 219 } 220 } 221 } 222 223 private static void _initializeCache() { 224 225 // load the configuration since it is required to load the 226 // KAR entries handlers, which in turn is required to build 227 // the actor library 228 229 // NOTE: we must use a configuration with the GUI, otherwise 230 // MoML filters are used to remove GUI actors. 231 String spec = "ptolemy/configs/kepler/ConfigGUIAndCache.xml"; 232 URL url = null; 233 try { 234 url = ConfigurationApplication.specToURL(spec); 235 } catch (IOException e) { 236 MessageHandler.error("ERROR configuration URL.", e); 237 System.exit(1); 238 } 239 240 try { 241 ConfigurationApplication.readConfiguration(url); 242 } catch (Exception e) { 243 MessageHandler.error("ERROR reading configuration.", e); 244 System.exit(1); 245 } 246 247 // build the actor library in case it does not exist 248 LibraryManager.getInstance().buildLibrary(); 249 } 250 251 252 private static void _shutdownCache(boolean exit) { 253 // call the module deinitializers 254 Kepler.shutdown(); 255 HSQL.shutdownServers(); 256 257 if(exit) { 258 // we have to call System.exit() because ??? 259 System.exit(0); 260 } 261 } 262 263 private static Set<String> _actorCacheClasses = new HashSet<String>(); 264}