Changeset 4180
- Timestamp:
- Mar 17, 2008, 2:40:46 PM (15 years ago)
- Location:
- branches/extensions
- Files:
-
- 11 added
- 1 deleted
- 9 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
branches/extensions/config/dist/log4j.properties
r4093 r4180 57 57 #log4j.logger.net.sf.basedb.core.signal=debug 58 58 59 ### Extensions API 60 #log4j.logger.net.sf.basedb.clients.web.extensions=debug 61 59 62 60 63 # ----------------- -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/ExtensionsDirectory.java
r4170 r4180 24 24 package net.sf.basedb.clients.web.extensions; 25 25 26 27 import net.sf.basedb.util.extensions.Extension; 26 import java.io.File; 27 import java.io.FileFilter; 28 import java.util.HashMap; 29 import java.util.Iterator; 30 import java.util.Map; 31 import java.util.regex.Pattern; 32 33 import net.sf.basedb.util.RegexpFileFilter; 28 34 import net.sf.basedb.util.extensions.ExtensionsInvoker; 29 35 import net.sf.basedb.util.extensions.Registry; 36 import net.sf.basedb.util.extensions.xml.PathConverter; 37 import net.sf.basedb.util.extensions.xml.VariableConverter; 38 import net.sf.basedb.util.extensions.xml.XmlLoader; 30 39 31 40 /** 41 Represents a directory with extensions. This class can automatically 42 detect changes and install, update or uninstall extensions when files 43 are added, changed or removed from the specified directory. 44 Resources, such as images, JSP files, etc. are automatically extracted 45 from JAR files and placed in the resources directory. This directory is 46 accessible from the web server. 32 47 33 48 @author nicklas 34 49 @version 2.7 35 50 @base.modified $Date$ 36 37 public class WebExtensions51 */ 52 public class ExtensionsDirectory 38 53 { 39 54 40 public static Registry REGISTRY = new Registry(); 41 42 public static Settings SETTINGS; 43 44 public static String ROOT = "/extension"; 45 46 public static ExtensionsInvoker<?> useExtensions(JspContext context, String...extensionPoints) 47 { 48 return REGISTRY.useExtensions(context, SETTINGS, extensionPoints); 49 } 50 51 public static String getRoot(Extension extension) 52 { 53 return ROOT + "/extensions/" + extension.getId(); 54 } 55 private static final org.apache.log4j.Logger log = 56 org.apache.log4j.LogManager.getLogger("net.sf.basedb.clients.web.extensions.WebExtensions"); 57 58 private final Registry registry; 59 private final File extensionsDir; 60 private final File resourcesDir; 61 private final String resourcesUrl; 62 private final String rootUrl; 63 64 private final Settings settings; 65 66 private final Map<File, ExtensionsFile> installedExtensions; 67 private final VariableConverter variableConverter; 68 private final PathConverter pathConverter; 69 70 71 public ExtensionsDirectory(Registry registry, File extensionsDir, File resourcesDir, 72 String rootUrl, String resourcesUrl) 73 { 74 this.extensionsDir = extensionsDir; 75 this.resourcesDir = resourcesDir; 76 this.resourcesUrl = resourcesUrl; 77 this.rootUrl = rootUrl; 78 79 this.registry = registry; 80 this.settings = new Settings(new File(extensionsDir, "settings.xml")); 81 82 this.installedExtensions = new HashMap<File, ExtensionsFile>(); 83 this.variableConverter = new VariableConverter(); 84 this.variableConverter.setVariable("ROOT", rootUrl); 85 this.variableConverter.setVariable("HOME", null); 86 this.pathConverter = new PathConverter(rootUrl, null); 87 } 88 89 public Settings getSettings() 90 { 91 return settings; 92 } 93 94 public synchronized void installOrUpdateExtensions(boolean forceUpdate) 95 { 96 int numDeleted = unregisterDeleted(); 97 int numNew = scanForNew(); 98 loadDefinitions(forceUpdate); 99 extractResources(forceUpdate); 100 registerExtensions(); 101 } 102 103 104 public ExtensionsInvoker<?> useExtensions(JspContext context, String...extensionPoints) 105 { 106 return registry.useExtensions(context, settings, extensionPoints); 107 } 108 55 109 56 110 /** 57 Convert a path to an absolute path seen from the web 58 servers perspective. Here are the rules: 59 <ol> 60 <li>If <code>path</code> starts with '/', the path is relative to 61 the BASE application root directory, which is added to 62 the beginning of the path, for example, 63 <code>/images/copy.gif --> /base/images/copy.gif</code> 64 65 <li>If <code>path</code> stars with '~', the path is relative to 66 the extensions home directory. The home directory of an extension 67 is normally located in the <code>/extensions</code> directory 68 with a name based on the JAR file the extension is located in. 69 For example, 70 <code>~/images/tmev.png --> /base/extensions/net.sf.basedb.mev/images/tmev.png</code>. 71 72 <li>Otherwise, the <code>path</code> is returned unmodified. 73 </ol> 74 75 @param path The path to convert to an absolute path 76 @param extension The extension that is requesting the path 77 conversion 78 @return The absolute path 111 Unregister extensions/extension points that no longer 112 exists. 79 113 */ 80 public static String makeAbsolutePath(String path, Extension extension) 81 { 82 if (path != null) 83 { 84 if (path.startsWith("/")) 85 { 86 path = ROOT + path; 87 } 88 else if (path.startsWith("~")) 89 { 90 path = getRoot(extension) + path.substring(1); 91 } 92 } 93 return path; 94 } 95 114 private int unregisterDeleted() 115 { 116 log.info("Checking for deleted extensions in directory: " + 117 extensionsDir.getAbsolutePath()); 118 // Unregister extensions that have been deleted 119 int numDeleted = 0; 120 Iterator<ExtensionsFile> it = installedExtensions.values().iterator(); 121 while (it.hasNext()) 122 { 123 ExtensionsFile extFile = it.next(); 124 boolean exists = extFile.exists(); 125 log.debug("File '" + extFile.getName() + "' " + (exists ? "exists" : "has been deleted")); 126 if (!exists) 127 { 128 log.info("Unregistering extensions from " + extFile.getName()); 129 //extFile.unregisterAll(); 130 File homeDir = new File(resourcesDir, extFile.getName()); 131 extFile.removeResources(homeDir); 132 it.remove(); 133 numDeleted++; 134 } 135 } 136 log.info(numDeleted + " extensions has been deleted from directory: " + 137 extensionsDir.getAbsolutePath()); 138 return numDeleted; 139 } 140 141 /** 142 Scan for new extensions. This method checks in the 143 extensions directory for *.xml and *.jar files. 144 */ 145 private int scanForNew() 146 { 147 log.info("Scanning for new extensions in directory: " + 148 extensionsDir.getAbsolutePath()); 149 // Search for new .xml or .jar files; don't search subdirectories 150 FileFilter filter = new RegexpFileFilter(".*\\.(xml|jar)", ""); 151 int numNew = 0; 152 for (File file : extensionsDir.listFiles(filter)) 153 { 154 if (file.getName().equals("settings.xml")) continue; 155 156 // Ignore files that we already know about 157 if (!installedExtensions.containsKey(file)) 158 { 159 log.debug("Possible match: " + file.getName()); 160 ExtensionsFile extFile = 161 new ExtensionsFile(file, createXmlLoader()); 162 if (extFile.isValid()) 163 { 164 // This is a new valid extensions file 165 log.info("Found new extensions in file: " + file.getName()); 166 installedExtensions.put(file, extFile); 167 numNew++; 168 } 169 } 170 else 171 { 172 log.debug("File is already installed: " + file.getName()); 173 } 174 } 175 log.info(numNew + " new extensions found in directory: " + 176 extensionsDir.getAbsolutePath()); 177 return numNew; 178 } 179 180 /** 181 Load the extension definitions from XML files. 182 */ 183 private void loadDefinitions(boolean forceUpdate) 184 { 185 Iterator<ExtensionsFile> it = installedExtensions.values().iterator(); 186 while (it.hasNext()) 187 { 188 ExtensionsFile extFile = it.next(); 189 // Only load new or updated file, unless forced 190 if (forceUpdate || extFile.isModified()) 191 { 192 // Set home directory for resources on value converters 193 String homePath = resourcesUrl + "/" + extFile.getName(); 194 variableConverter.setVariable("HOME", homePath); 195 pathConverter.setHome(homePath); 196 extFile.loadExtensions(); 197 } 198 } 199 } 200 201 202 private void extractResources(boolean forceUpdate) 203 { 204 // Extract resources for new and modified extensions 205 Pattern resourcePattern = Pattern.compile("resources/(.*)"); 206 for (ExtensionsFile extFile : installedExtensions.values()) 207 { 208 if (forceUpdate || extFile.isModified()) 209 { 210 File homeDir = new File(resourcesDir, extFile.getName()); 211 extFile.extractResources(homeDir, resourcePattern, "$1", forceUpdate); 212 } 213 } 214 } 215 216 private void registerExtensions() 217 { 218 for (ExtensionsFile extFile : installedExtensions.values()) 219 { 220 if (extFile.isModified()) 221 { 222 extFile.registerExtensionPoints(registry); 223 } 224 } 225 226 for (ExtensionsFile extFile : installedExtensions.values()) 227 { 228 extFile.registerExtensions(registry); 229 extFile.resetModified(); 230 } 231 } 232 233 234 private XmlLoader createXmlLoader() 235 { 236 XmlLoader loader = new XmlLoader(); 237 loader.addValueConverter(variableConverter); 238 loader.addValueConverter(pathConverter); 239 return loader; 240 } 241 96 242 } -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/Settings.java
r4170 r4180 64 64 { 65 65 66 private final File file; 66 67 private boolean hasChanged; 67 68 private Presets presets; … … 70 71 private Preset disabledExtensionPoints; 71 72 72 private String filename; 73 74 public Settings(String filename) 75 throws IOException 73 public Settings(File file) 76 74 { 77 this.file name = filename;75 this.file = file; 78 76 this.presets = new Presets(); 79 File file = new File(filename);80 77 if (file.exists()) 81 78 { 82 InputStream in = new BufferedInputStream(new FileInputStream(file)); 83 presets.loadFrom(in, filename); 84 in.close(); 79 try 80 { 81 InputStream in = new BufferedInputStream(new FileInputStream(file)); 82 presets.loadFrom(in, file.getAbsolutePath()); 83 in.close(); 84 } 85 catch (IOException ex) 86 { 87 throw new RuntimeException(ex); 88 } 85 89 } 86 90 this.settings = presets.getDefault(); … … 134 138 Save the settings to disk. If the settings has not been 135 139 changed the file is not written. 136 137 @throws IOException138 140 */ 139 141 public synchronized void save() 140 throws IOException141 142 { 142 143 if (!hasChanged) return; 143 OutputStream out = new FileOutputStream(filename); 144 presets.writeTo(out); 145 out.close(); 144 try 145 { 146 OutputStream out = new FileOutputStream(file); 147 presets.writeTo(out); 148 out.close(); 149 } 150 catch (IOException ex) 151 { 152 throw new RuntimeException(ex); 153 } 146 154 hasChanged = true; 147 155 } -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/toolbar/ButtonAction.java
r4168 r4180 76 76 line up with the other icons used by the BASE. 77 77 The reference will be path converted as described by 78 {@link WebExtensions#makeAbsolutePath(String, net.sf.basedb.util.extensions.Extension)}78 {@link ExtensionsDirectory#makeAbsolutePath(String, net.sf.basedb.util.extensions.Extension)} 79 79 80 80 @return A reference to an image, or null if no image should -
branches/extensions/src/core/net/sf/basedb/util/extensions/Registry.java
r4170 r4180 51 51 @version 2.7 52 52 @base.modified $Date$ 53 @see net.sf.basedb.clients.web.extensions. WebExtensions53 @see net.sf.basedb.clients.web.extensions.ExtensionsDirectory 54 54 */ 55 55 public class Registry -
branches/extensions/src/core/net/sf/basedb/util/extensions/xml/XmlLoader.java
r4170 r4180 199 199 200 200 /** 201 Unregister all loaded extension points from a registry. 202 @param registry The registry 203 */ 204 public void unregisterExtensionPoints(Registry registry) 205 { 206 for (ExtensionPoint<Action> ep : extensionPoints) 207 { 208 registry.unregisterExtensionPoint(ep.getId()); 209 } 210 } 211 212 /** 201 213 Register all loaded extensions with a registry. 202 214 @param registry The registry … … 207 219 { 208 220 registry.registerExtension(ext); 221 } 222 } 223 224 /** 225 Unregister all loaded extensions from a registry. 226 @param registry The registry 227 */ 228 public void unregisterExtensions(Registry registry) 229 { 230 for (Extension<Action> ext : extensions) 231 { 232 registry.unregisterExtension(ext.getId()); 209 233 } 210 234 } -
branches/extensions/www/admin/extensions/details.jsp
r4168 r4180 37 37 import="net.sf.basedb.util.extensions.ExtensionPoint" 38 38 import="net.sf.basedb.util.extensions.Extension" 39 import="net.sf.basedb.clients.web. extensions.WebExtensions"39 import="net.sf.basedb.clients.web.servlet.ExtensionsServlet" 40 40 import="net.sf.basedb.clients.web.extensions.Settings" 41 41 import="net.sf.basedb.core.plugin.About" … … 57 57 final Client currentClient = Client.getById(dc, sc.getClientId()); 58 58 final boolean writePermission = currentClient.hasPermission(Permission.WRITE); 59 final Settings settings = WebExtensions.SETTINGS;59 final Settings settings = ExtensionsServlet.getSettings(); 60 60 61 61 Extension<?> ext = null; … … 64 64 if (extensionId != null) 65 65 { 66 ext = WebExtensions.REGISTRY.getExtension(extensionId);66 ext = ExtensionsServlet.getRegistry().getExtension(extensionId); 67 67 if (ext == null) 68 68 { … … 74 74 if (extensionPointId != null) 75 75 { 76 ep = WebExtensions.REGISTRY.getExtensionPoint(extensionPointId);76 ep = ExtensionsServlet.getRegistry().getExtensionPoint(extensionPointId); 77 77 if (ep == null) 78 78 { -
branches/extensions/www/admin/extensions/index.jsp
r4168 r4180 1 <%@page import="net.sf.basedb.clients.web.extensions.WebExtensions"%>2 1 <%-- $Id$ 3 2 ------------------------------------------------------------------ … … 36 35 import="net.sf.basedb.util.extensions.ExtensionPoint" 37 36 import="net.sf.basedb.util.extensions.Extension" 38 import="net.sf.basedb.clients.web. extensions.WebExtensions"37 import="net.sf.basedb.clients.web.servlet.ExtensionsServlet" 39 38 %> 40 39 <%@ taglib prefix="base" uri="/WEB-INF/base.tld" %> … … 59 58 String extensionId = request.getParameter("extensionId"); 60 59 boolean enable = Values.getBoolean(request.getParameter("enable")); 61 WebExtensions.SETTINGS.enableExtension(extensionId, enable);62 WebExtensions.SETTINGS.save();60 ExtensionsServlet.getSettings().enableExtension(extensionId, enable); 61 ExtensionsServlet.getSettings().save(); 63 62 redirect = "details.jsp?ID=" + ID + "&extensionId=" + extensionId; 64 63 } … … 67 66 String extensionPointId = request.getParameter("extensionPointId"); 68 67 boolean enable = Values.getBoolean(request.getParameter("enable")); 69 WebExtensions.SETTINGS.enableExtensionPoint(extensionPointId, enable);70 WebExtensions.SETTINGS.save();68 ExtensionsServlet.getSettings().enableExtensionPoint(extensionPointId, enable); 69 ExtensionsServlet.getSettings().save(); 71 70 redirect = "details.jsp?ID=" + ID + "&extensionPointId=" + extensionPointId; 72 71 } -
branches/extensions/www/admin/extensions/tree.jsp
r4168 r4180 34 34 import="net.sf.basedb.util.extensions.ExtensionPoint" 35 35 import="net.sf.basedb.util.extensions.Extension" 36 import="net.sf.basedb.clients.web. extensions.WebExtensions"36 import="net.sf.basedb.clients.web.servlet.ExtensionsServlet" 37 37 import="net.sf.basedb.clients.web.extensions.Settings" 38 38 import="net.sf.basedb.core.plugin.About" … … 73 73 <% 74 74 Iterator<ExtensionPoint<?>> extensionPoints = 75 WebExtensions.REGISTRY.getExtensionPoints();76 Settings settings = WebExtensions.SETTINGS;75 ExtensionsServlet.getRegistry().getExtensionPoints(); 76 Settings settings = ExtensionsServlet.getSettings(); 77 77 while (extensionPoints.hasNext()) 78 78 { … … 86 86 <% 87 87 Iterator<Extension<?>> extensions = 88 WebExtensions.REGISTRY.getExtensions(epId);88 ExtensionsServlet.getRegistry().getExtensions(epId); 89 89 while (extensions.hasNext()) 90 90 { -
branches/extensions/www/include/menu.jsp
r4168 r4180 57 57 import="net.sf.basedb.clients.web.util.HTML" 58 58 import="net.sf.basedb.util.Values" 59 import="net.sf.basedb.clients.web. extensions.WebExtensions"59 import="net.sf.basedb.clients.web.servlet.ExtensionsServlet" 60 60 import="net.sf.basedb.clients.web.extensions.JspContext" 61 61 import="net.sf.basedb.clients.web.extensions.menu.MenuItemAction" … … 954 954 JspContext context = new JspContext(sc); 955 955 ExtensionsInvoker<MenuItemAction> invoker = 956 (ExtensionsInvoker<MenuItemAction>) WebExtensions.useExtensions(context,956 (ExtensionsInvoker<MenuItemAction>)ExtensionsServlet.useExtensions(context, 957 957 "net.sf.basedb.clients.web.menu.extensions"); 958 958 ActionIterator<MenuItemAction> items = invoker.iterate(); … … 979 979 style="<%=item.getStyle()%>" 980 980 title="<%=item.getTitle()%>" 981 icon="<%= WebExtensions.makeAbsolutePath(item.getIcon(), extension)%>"981 icon="<%=item.getIcon()%>" 982 982 tooltip="<%=item.getTooltip()%>" 983 983 enabled="<%=item.isEnabled()%>"
Note: See TracChangeset
for help on using the changeset viewer.