1 3 package com.sslexplorer.extensions.types; 4 5 import java.io.File ; 6 import java.io.FileFilter ; 7 import java.io.IOException ; 8 import java.net.MalformedURLException ; 9 import java.net.URL ; 10 import java.util.HashMap ; 11 import java.util.Iterator ; 12 import java.util.Map ; 13 14 import javax.servlet.ServletException ; 15 16 import org.apache.commons.logging.Log; 17 import org.apache.commons.logging.LogFactory; 18 import org.jdom.Element; 19 20 import com.sslexplorer.boot.ContextHolder; 21 import com.sslexplorer.boot.Util; 22 import com.sslexplorer.core.CoreServlet; 23 import com.sslexplorer.core.CoreUtil; 24 import com.sslexplorer.extensions.ExtensionDescriptor; 25 import com.sslexplorer.extensions.ExtensionException; 26 import com.sslexplorer.extensions.ExtensionType; 27 import com.sslexplorer.security.SessionInfo; 28 29 34 public class PluginType implements ExtensionType { 35 36 final static Log log = LogFactory.getLog(PluginType.class); 37 38 41 public final static String TYPE = "plugin"; 42 43 private static Map <String , Plugin> plugins = new HashMap <String , Plugin>(); 45 46 48 private PluginDefinition def; 49 private Plugin plugin; 50 private boolean classpathAdded; 51 52 55 public PluginType() { 56 } 57 58 65 public static Plugin getPlugin(String id) { 66 return plugins.get(id); 67 } 68 69 75 public void start(ExtensionDescriptor descriptor, Element element) throws ExtensionException { 76 readConfiguration(descriptor, element); 77 createPlugin(); 78 startPlugin(descriptor, element); 79 80 } 81 82 87 public void verifyRequiredElements() throws ExtensionException { 88 } 89 90 95 public boolean isHidden() { 96 return true; 97 } 98 99 104 public String getType() { 105 return TYPE; 106 } 107 108 113 public void stop() throws ExtensionException { 114 116 if (def != null) { 117 for (URL u : def.getResourceBases()) { 118 ContextHolder.getContext().removeResourceBase(u); 119 } 120 def.getResourceBases().clear(); 121 } 122 123 if (plugin != null) { 124 String tilesConfigFile = plugin.getTilesConfigFile(); 125 if (tilesConfigFile != null) { 126 CoreServlet.getServlet().removeTileConfigurationFile(tilesConfigFile); 127 } 128 plugin.stopPlugin(); 129 } 130 } 131 132 public void activate() throws ExtensionException { 133 plugin.activatePlugin(); 134 } 135 136 public boolean canStop() throws ExtensionException { 137 return false; 140 } 141 142 void readConfiguration(ExtensionDescriptor descriptor, Element element) throws ExtensionException { 143 144 String name = element.getAttributeValue("name"); 146 if (name == null || name.equals("")) { 147 throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR, 148 "The name attribute must be supplied for <plugin> elements (" + descriptor.getApplicationBundle().getFile().getPath() + ")."); 149 } 150 151 String className = element.getAttributeValue("class"); 153 if (className == null || className.equals("")) { 154 throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR, 155 "The class attribute must be supplied for <plugin> elements (" + descriptor.getApplicationBundle().getFile().getPath() + ")."); 156 } 157 158 String orderText = element.getAttributeValue("order"); 160 int order = 999; 161 if (orderText != null && !orderText.equals("")) { 162 order = Integer.parseInt(orderText); 163 } 164 165 String dependencies = element.getAttributeValue("dependencies"); 167 if (dependencies != null) { 168 log.warn("DEPRECATED. dependencies attribute in plugin definition in " 169 + descriptor.getApplicationBundle().getFile().getAbsolutePath() + " should now use 'depends'."); 170 } else { 171 dependencies = element.getAttributeValue("depends"); 172 } 173 174 def = new PluginDefinition(descriptor); 175 176 def.setName(name); 178 def.setClassName(className); 179 180 def.setOrder(order); 182 183 184 if(!descriptor.getApplicationBundle().isDevExtension()) { 185 for (Iterator i = element.getChildren().iterator(); i.hasNext();) { 186 Element el = (Element) i.next(); 187 if (el.getName().equals("classpath")) { 188 String path = Util.trimmedBothOrBlank(el.getText()); 189 if (!path.equals("")) { 190 File f = new File (descriptor.getApplicationBundle().getBaseDir(), path); 191 if (f.exists()) { 192 try { 193 URL u = f.toURL(); 194 if (log.isInfoEnabled()) 195 log.info("Adding " + u + " to classpath"); 196 def.addClassPath(u); 197 } catch (MalformedURLException murle) { 198 throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR, 199 murle, "Invalid classpath."); 200 } 201 } else { 202 if (!"true".equals(System.getProperty("sslexplorer.useDevConfig"))) { 203 log.warn("Plugin classpath element " + f.getAbsolutePath() + " does not exist."); 204 } 205 } 206 } 207 } else if (el.getName().equals("resources")) { 208 File f = new File (descriptor.getApplicationBundle().getBaseDir(), el.getText()); 209 if (f.exists() && f.isDirectory()) { 210 try { 211 def.addResourceBase(f.getCanonicalFile().toURL()); 212 } catch (Exception ex) { 213 throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR, ex, "Invalid resource base."); 214 } 215 } else { 216 if (log.isInfoEnabled()) 217 log.info("<resources> element does not point to a valid directory."); 218 } 219 } else if (el.getName().equals("native")) { 220 File f = new File (descriptor.getApplicationBundle().getBaseDir(), el.getText()); 221 if (f.exists() && f.isDirectory()) { 222 try { 223 def.addNativeDirectory(f.getCanonicalFile()); 224 } catch (Exception ex) { 225 throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR, 226 ex, "Invalid native directory."); 227 } 228 } else { 229 if (log.isInfoEnabled()) 230 log.info("<native> element does not point to a valid directory."); 231 } 232 } else { 233 throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR, 234 "The <plugin> element only supports the nested <classpath>, <resources> or <native> elements"); 235 } 236 } 237 } 238 239 242 if(descriptor.getApplicationBundle().isDevExtension()) { 243 File d = new File (new File (System.getProperty("user.dir")).getParentFile(), descriptor.getApplicationBundle().getId()); 244 File extensionDir = new File (new File (d, "extensions"), d.getName()); 245 File webapp = new File (d, "webapp"); 246 File classes = new File (new File (d, "build"), "classes"); 247 if (webapp.exists()) { 248 try { 249 def.addResourceBase(webapp.toURL()); 250 } catch (MalformedURLException e) { 251 } 252 } 253 if (classes.exists()) { 254 try { 255 def.addClassPath(classes.toURL()); 256 } catch (MalformedURLException e) { 257 } 258 } 259 File privateDir = new File (extensionDir, "private"); 260 if (privateDir.exists()) { 261 File [] jars = privateDir.listFiles(new FileFilter () { 262 public boolean accept(File pathname) { 263 return pathname.getName().toLowerCase().endsWith(".jar"); 264 } 265 }); 266 for (int idx = 0; jars != null && idx < jars.length; idx++) { 267 try { 268 def.addClassPath(jars[idx].toURL()); 269 } catch (MalformedURLException e) { 270 } 271 } 272 } 273 File nativeDir = new File (new File (d, "build"), "native"); 274 if (nativeDir.exists()) { 275 try { 276 def.addNativeDirectory(nativeDir.getCanonicalFile()); 277 } 278 catch(Exception e) { 279 } 280 } 281 } 282 } 283 284 synchronized void createPlugin() throws ExtensionException { 285 286 if (!classpathAdded) { 288 for (URL url : def.getClassPath()) { 289 ContextHolder.getContext().addContextLoaderURL(url); 290 } 291 292 for (Iterator j = def.getNativeDirectories(); j.hasNext();) { 293 File f = (File ) j.next(); 294 try { 295 CoreUtil.addLibraryPath(f.getAbsolutePath()); 296 } catch (IOException e) { 297 log.error("Failed to add native directory " + f.getAbsolutePath() + ". The plugin " + def.getName() 298 + " may not function correctly.", e); 299 } 300 } 301 classpathAdded = true; 302 } 303 304 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 305 if (cl == null) { 306 cl = getClass().getClassLoader(); 307 } 308 309 try { 310 if(log.isInfoEnabled()) { 311 log.info("Creating plugin " + def.getClassName()); 312 } 313 plugin = (Plugin) Class.forName(def.getClassName(), true, cl).newInstance(); 314 } catch (Exception e) { 315 throw new ExtensionException(ExtensionException.FAILED_TO_CREATE_PLUGIN_INSTANCE, 316 def.getName(), 317 def.getClassName(), 318 e.getMessage(), 319 e); 320 } 321 322 plugins.put(def.getName(), plugin); 323 324 String resn = plugin.getClass().getName().replace('.', '/') + ".class"; 325 if (log.isDebugEnabled()) 326 log.debug("Looking for resource " + resn); 327 URL res = plugin.getClass().getClassLoader().getResource(resn); 328 String resource = ""; 329 if (res == null) 330 log.error("Could not locate resource " + resn); 331 else { 332 333 String n = res.toExternalForm(); 334 if (n.startsWith("jar:file:")) { 335 n = n.substring(4); 336 int idx = n.lastIndexOf('!'); 337 if (idx != -1) 338 n = n.substring(0, idx); 339 n = n.substring(5); 340 if (n.startsWith("/") && n.length() > 3 && n.charAt(2) == ':' && Character.isLetter(n.charAt(1)) 342 && n.charAt(3) == '/') 343 n = n.substring(1); 344 File f = new File (n); 345 resource = f.getAbsolutePath(); 346 } 347 if (log.isDebugEnabled()) 348 log.debug("Resource is " + resource); 349 } 350 } 351 352 void startPlugin(ExtensionDescriptor descriptor, Element element) throws ExtensionException { 353 354 for (URL url : def.getResourceBases()) { 356 ContextHolder.getContext().addResourceBase(url); 357 } 358 359 try { 360 String tilesConfigFile = plugin.getTilesConfigFile(); 361 if (tilesConfigFile != null) { 362 CoreServlet.getServlet().addTileConfigurationFile(tilesConfigFile); 363 } 364 365 String path = "/WEB-INF/" + def.getDescriptor().getId() + "-struts-config.xml"; 366 CoreServlet.getServlet().addStrutsConfig(path); 367 plugin.startPlugin(def, descriptor, element); 368 } catch (ExtensionException e) { 369 for (URL url : def.getResourceBases()) { 371 ContextHolder.getContext().removeResourceBase(url); 372 } 373 throw e; 374 } catch (ServletException se) { 375 throw new ExtensionException(ExtensionException.INTERNAL_ERROR, se); 376 } 377 } 378 379 384 public void descriptorCreated(Element element, SessionInfo session) throws IOException { 385 } 386 387 390 public String getTypeBundle() { 391 return "extensions"; 392 } 393 } 394 | Popular Tags |