Changeset 5602


Ignore:
Timestamp:
Apr 7, 2011, 11:04:27 AM (10 years ago)
Author:
Nicklas Nordborg
Message:

References #1592: Unified installation procedure for plug-ins, extensions and more...
References #1593: Extension system for the core API

Added fuctionality for metadata handling and status/error reporting. Everything is still only loaded at startup but now we can see most of the information in the admin interface.

Location:
trunk
Files:
5 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/ExtensionsControl.java

    r5601 r5602  
    5454import net.sf.basedb.util.extensions.Registry;
    5555import net.sf.basedb.util.extensions.events.EventType;
     56import net.sf.basedb.util.extensions.manager.ExtensionsFile.WriteableExtensionsFile;
    5657import net.sf.basedb.util.extensions.manager.ExtensionsManager;
    5758import net.sf.basedb.util.extensions.manager.ExtractResourcesProcessor;
     59import net.sf.basedb.util.extensions.manager.ObjectKey;
     60import net.sf.basedb.util.extensions.manager.ProcessResults;
    5861import net.sf.basedb.util.extensions.manager.RegisterExtensionsProcessor;
    5962import net.sf.basedb.util.extensions.xml.ExtensionPointFilter;
     
    132135   
    133136  // The result of the last automatic update
    134   private static ScanResults lastScanResults;
     137  private static ProcessResults lastScanResults;
    135138   
    136139  /**
     
    155158    EditUtil.registerExtensionPoints(registry); // TabControls
    156159   
    157     manager.addExtensionsFile(new net.sf.basedb.util.extensions.manager.ExtensionsFile(URI.create(ExtensionsControl.class.getResource("/web-extensions.xml").toString())));
     160    manager.addURI(URI.create(ExtensionsControl.class.getResource("/web-extensions.xml").toString()));
    158161
    159162    // Load settings
     
    164167    // Install extensions
    165168    XmlLoader loader = new XmlLoader();
     169    lastScanResults = new ProcessResults(false, false);
     170   
    166171    // Filter that only load web extension points
    167172    loader.setFilter(new ExtensionPointFilter("net\\.sf\\.basedb\\.clients\\.web\\..*"));
     
    176181    loader.addValueConverter(pathConverter);
    177182
    178     manager.processFiles(new RegisterExtensionsProcessor(loader)
     183    manager.processFiles(new RegisterExtensionsProcessor(loader, false, lastScanResults)
    179184    {
    180185
    181186      @Override
    182187      public void processFile(ExtensionsManager manager,
    183           net.sf.basedb.util.extensions.manager.ExtensionsFile xtFile)
     188          WriteableExtensionsFile xtFile)
    184189      {
    185         String homePath = servletContext.getContextPath() + RESOURCES_URL + "/" + xtFile.getName();
     190        String homePath = servletContext.getContextPath() + RESOURCES_URL + "/" + xtFile.getExtensionsFile().getName();
    186191        //String servletHomePath = getServletsUrl(extFile);
    187192        variableConverter.setVariable("HOME", homePath);
     
    193198     
    194199    });
    195     manager.processFiles(new ExtractResourcesProcessor(new java.io.File(servletContext.getRealPath(RESOURCES_URL)), false, Pattern.compile("resources/(.*)"), "$1"));
     200    manager.processFiles(new ExtractResourcesProcessor(new java.io.File(servletContext.getRealPath(RESOURCES_URL)), false, Pattern.compile("resources/(.*)"), "$1", lastScanResults));
     201    //lastScanResults = new ScanResults(true, false);
    196202    /*
    197203    lastScanResults = extensionsDir.installAndUpdateExtensions(registry,
     
    223229  }
    224230 
     231  /*
    225232  private static synchronized void setLastScanResults(ScanResults scanResults)
    226233  {
    227234    lastScanResults = scanResults;
    228235  }
     236  */
    229237 
    230238
     
    438446      has taken place
    439447  */
    440   public ScanResults getLastScanResults()
     448  public ProcessResults getLastScanResults()
    441449  {
    442450    return lastScanResults;
     
    605613  /**
    606614    Get information about an installed extensions file.
    607     @param filename The filename of the file
     615    @param fileuri The URI to the file
    608616    @return An {@link ExtensionsFile} object or null if
    609617      the given file doesn't exists or isn't an extensions file
    610618  */
    611   public net.sf.basedb.util.extensions.manager.ExtensionsFile getFile(String filename)
    612   {
    613     return null;
    614     //return extensionsDir.getFile(filename);
     619  public net.sf.basedb.util.extensions.manager.ExtensionsFile getFile(String fileuri)
     620  {
     621    return manager.getFileByURI(fileuri);
    615622  }
    616623 
     
    622629      or null if no extension with the given ID is found
    623630  */
    624   public net.sf.basedb.util.extensions.manager.ExtensionsFile getFileByObjectId(String objectId)
    625   {
    626     return manager.getFileByObjectId(objectId);
    627     //return null;
    628     //return extensionsDir.getFileByExtensionId(extensionId);
     631  public net.sf.basedb.util.extensions.manager.ExtensionsFile getFileByObjectKey(ObjectKey key)
     632  {
     633    return manager.getFileByObjectKey(key);
    629634  }
    630635 
  • trunk/src/core/net/sf/basedb/core/Application.java

    r5600 r5602  
    3737import net.sf.basedb.util.extensions.manager.ExtensionsFile;
    3838import net.sf.basedb.util.extensions.manager.ExtensionsManager;
     39import net.sf.basedb.util.extensions.manager.ProcessResults;
    3940import net.sf.basedb.util.extensions.manager.RegisterExtensionsProcessor;
    4041import net.sf.basedb.util.extensions.xml.ExtensionPointFilter;
     
    537538       
    538539        // Add core extension points and extensions
    539         ExtensionsFile core = new ExtensionsFile(Application.class.getResource("/core-extensions.xml").toURI());
    540         xtManager.addExtensionsFile(core);
     540        xtManager.addURI(Application.class.getResource("/core-extensions.xml").toURI());
    541541       
    542542        // Add plugins directory to the manager
     
    545545        // Register and load core extensions
    546546        XmlLoader loader = new XmlLoader();
     547        ProcessResults results = new ProcessResults(false, false);
    547548        // Filter that only load core extension points
    548549        loader.setFilter(new ExtensionPointFilter("net\\.sf\\.basedb\\.core\\..*"));
    549         xtManager.processFiles(new RegisterExtensionsProcessor(loader));
    550            
     550        xtManager.processFiles(new RegisterExtensionsProcessor(loader, false, results));
     551       
     552       
    551553        // Initialise log manager factory
    552554        if (logManagerFactoryDriver != null)
  • trunk/src/core/net/sf/basedb/util/extensions/manager/ExtensionsFile.java

    r5601 r5602  
    2828import java.io.InputStream;
    2929import java.net.URI;
     30import java.util.ArrayList;
    3031import java.util.HashMap;
     32import java.util.LinkedHashMap;
     33import java.util.List;
    3134import java.util.Map;
     35import java.util.concurrent.TimeUnit;
     36import java.util.concurrent.locks.Lock;
     37import java.util.concurrent.locks.ReadWriteLock;
     38import java.util.concurrent.locks.ReentrantReadWriteLock;
    3239import java.util.zip.ZipEntry;
    3340import java.util.zip.ZipFile;
     
    3643import net.sf.basedb.util.FileUtil;
    3744import net.sf.basedb.util.JarClassLoader;
     45import net.sf.basedb.util.extensions.Extension;
     46import net.sf.basedb.util.extensions.ExtensionPoint;
    3847import net.sf.basedb.util.extensions.xml.XmlLoader;
    3948import net.sf.basedb.util.uri.CloseResourceInputStream;
     
    5867    org.apache.log4j.LogManager.getLogger("net.sf.basedb.util.extensions.manager.ExtensionsFile");
    5968
     69  private final ExtensionsManager manager;
    6070  private final File file;
    6171  private final URI uri;
    6272  private final boolean isJar;
    6373  private final String name;
     74  private final ReadWriteLock rwLock;
     75  private final Map<ObjectKey, Object> allObjects;
     76  private final Map<ObjectKey, Object> objectMetadata;
    6477 
    6578  private JarClassLoader jarLoader;
     
    6780  private long lastSize;
    6881  private About about;
     82  private boolean hasError;
    6983
    7084  private volatile boolean hasValidated;
     
    7993    @param file The file
    8094  */
    81   public ExtensionsFile(File file)
    82   {
    83     this(file, file.getName().endsWith(".jar"));
     95  ExtensionsFile(ExtensionsManager manager, File file)
     96  {
     97    this(manager, file, file.getName().endsWith(".jar"));
    8498  }
    8599 
     
    92106    @param isJar TRUE if it is a JAR file, FALSE if it is an XML file
    93107   */
    94   public ExtensionsFile(File file, boolean isJar)
    95   {
    96     this.file = file;
    97     this.isJar = isJar;
    98     this.uri = file.toURI();
    99     this.name = file.getName();
     108  ExtensionsFile(ExtensionsManager manager, File file, boolean isJar)
     109  {
     110    this(manager, file, file.toURI(), file.getName(), isJar);
    100111  }
    101112
     
    105116    @param uri The URI
    106117  */
    107   public ExtensionsFile(URI uri)
    108   {
    109     this.file = null;
    110     this.isJar = false;
     118  ExtensionsFile(ExtensionsManager manager, URI uri)
     119  {
     120    this(manager, null, uri, uri.toString().replaceFirst(".*/", ""), false);
     121  }
     122 
     123  private ExtensionsFile(ExtensionsManager manager, File file, URI uri, String name, boolean isJar)
     124  {
     125    this.manager = manager;
     126    this.file = file;
    111127    this.uri = uri;
    112     this.name = uri.toString().replaceFirst(".*/", "");
     128    this.name = name;
     129    this.isJar = isJar;
     130    this.rwLock = new ReentrantReadWriteLock();
     131    this.allObjects = new LinkedHashMap<ObjectKey, Object>();
     132    this.objectMetadata = new HashMap<ObjectKey, Object>();
    113133  }
    114134 
     
    301321  }
    302322 
     323  /**
     324    If there was an error when registering the extensions in this file.
     325    This property is only set if the file has been determined to be a
     326    valid extensions file by the {@link #isValid()} method. Extensions that
     327    has an error are automatically disabled.
     328   
     329    @return TRUE if there was some error, FALSE if everything is ok
     330  */
     331  public boolean hasError()
     332  {
     333    return hasError;
     334  }
     335 
     336  /**
     337    Get a list of all objects defined in this extensions
     338    file. This list can contain any type of objects that
     339    have been registered by a processer, but typically
     340    this list contains {@link ExtensionPoint}:s and
     341    {@link Extension}:s. Use {@link #getObjectsOfClass(Class)}
     342    to get a list with only one type of objects.
     343   
     344    @return A list with the objects
     345  */
     346  public List<Object> getAllObjects()
     347  {
     348    List<Object> copy = new ArrayList<Object>();
     349    boolean lock = readLock();
     350    try
     351    {
     352      if (lock)
     353      {
     354        copy.addAll(allObjects.values());
     355      }
     356    }
     357    finally
     358    {
     359      if (lock) rwLock.readLock().unlock();
     360    }
     361    return copy;
     362  }
     363 
     364  /**
     365    Get a list of all objects defined in this extensions
     366    file that are of the specified class or interface.
     367    Note! The returned list may be empty if another
     368    thread is currently processing this file.
     369   
     370    @param ofClass The class/interface the objects must be
     371      an instance of
     372    @return A list with the objects, if no objects are found
     373      the list is empty
     374  */
     375  public <T> List<T> getObjectsOfClass(Class<T> ofClass)
     376  {
     377    List<T> matching = new ArrayList<T>();
     378    Lock lock = null;
     379    try
     380    {
     381      if (readLock())
     382      {
     383        for (Object o : allObjects.values())
     384        {
     385          if (ofClass.isInstance(o)) matching.add(ofClass.cast(o));
     386        }
     387      }
     388    }
     389    finally
     390    {
     391      if (lock != null) lock.unlock();
     392    }
     393    return matching;
     394  }
     395 
     396  /**
     397    Get the object that was registered for the given key.
     398    @param key An object key
     399    @return The object or null if no object was found
     400  */
     401  @SuppressWarnings("unchecked")
     402  public <O> O getObjectForKey(ObjectKey<O> key)
     403  {
     404    return (O)allObjects.get(key);
     405  }
     406 
     407  /**
     408    Get metadata registered for a given given key.
     409    @param key An object key
     410    @return A metadata object, or null if no metadata was found
     411  */
     412  @SuppressWarnings("unchecked")
     413  public <M> M getMetadata(ObjectKey<M> key)
     414  {
     415    return (M)objectMetadata.get(key);
     416  }
     417
    303418  public ClassLoader getClassLoader()
    304419    throws IOException
     
    347462
    348463
    349  
     464  /**
     465    Get a writeable view for the current file. Note that the view
     466    is returned in read-only mode and to really be able to write information
     467    the method {@link WriteableExtensionsFile#open()} must be called.
     468  */
     469  WriteableExtensionsFile getWriteableFile()
     470  {
     471    return new WriteableExtensionsFile(this);
     472  }
     473 
     474  /**
     475    Try to aquire a read-lock. A read-lock is needed when reading information
     476    that may be corrupted if another thread is currently writing information
     477    to this file.
     478    @return TRUE if the read-lock could be aquired immediately, FALSE if not
     479  */
     480  boolean readLock()
     481  {
     482    return rwLock.readLock().tryLock();
     483  }
     484 
     485  /**
     486    Try to aquire a write-lock. A write-lock is needed by any thread that wants
     487    to update information about this file. The write-lock can only be held by
     488    a single thread at a time.
     489    @return TRUE if the write-lock could be aquired within 1 second, FALSE if not
     490  */
     491  boolean writeLock()
     492  {
     493    try
     494    {
     495      return rwLock.writeLock().tryLock(1, TimeUnit.SECONDS);
     496    }
     497    catch (InterruptedException ex)
     498    {}
     499    return false;
     500  }
     501 
     502  /**
     503    An extensions file with additional methods that allows adding
     504    or modifying information in the underlying extensions file. This kind of
     505    view is usually handed out to {@link ExtensionsFileProcessor} implementations
     506    as a result of calling {@link ExtensionsManager#processFiles(ExtensionsFileProcessor)}.
     507    <p>
     508   
     509    Note that the file starts out in read-only mode and that
     510    the processor has to call {@link #open()} to aquire a write-lock
     511    before calling any writing methods. It is recommended that
     512    the lock is released as soon as possible by calling {@link #close()}.
     513  */
     514  public static class WriteableExtensionsFile
     515  {
     516    private final ExtensionsFile xtFile;
     517    private boolean isClosed;
     518   
     519    /**
     520      Creates a new writeable extensions file.
     521    */
     522    WriteableExtensionsFile(ExtensionsFile xtFile)
     523    {
     524      this.xtFile = xtFile;
     525      this.isClosed = true;
     526    }
     527   
     528    /**
     529      Get the underlying extensions file (for readin information)
     530    */
     531    public ExtensionsFile getExtensionsFile()
     532    {
     533      return xtFile;
     534    }
     535   
     536    /**
     537      Close the writeable file. This will release the lock and
     538      any further write operations are disallowed.
     539    */
     540    public void close()
     541    {
     542      if (isClosed) return;
     543      isClosed = true;
     544      xtFile.rwLock.writeLock().unlock();
     545    }
     546   
     547    public boolean open()
     548    {
     549      if (isClosed)
     550      {
     551        isClosed = !xtFile.writeLock();
     552      }
     553      return !isClosed;
     554    }
     555   
     556    /**
     557      Check if the file has been closed and throws an
     558      IllegalStateException if it has.
     559    */
     560    private void checkClosed()
     561    {
     562      if (isClosed)
     563      {
     564        throw new IllegalStateException("The file has been closed: " + xtFile);
     565      }
     566    }
     567   
     568    /**
     569      Sets the error status. This method can be called even on closed
     570      files, since it is important to error handling.
     571    */
     572    public void setError(boolean error)
     573    {
     574      xtFile.hasError = error;
     575    }
     576
     577    /**
     578      Register an object as "defined" by this extensions file.
     579      @param key The object key used to identify the object
     580      @param obj The object to register
     581      @throws IllegalStateException If the file has been closed
     582    */
     583    public <O> void registerObject(ObjectKey<O> key, O obj)
     584    {
     585      checkClosed();
     586      xtFile.allObjects.put(key, obj);
     587      xtFile.manager.registerObject(key, this.xtFile);
     588    }
     589   
     590    /**
     591      Register metadata about an object. The difference
     592      between this method and the {@link #registerObject(ObjectKey, Object)}
     593      method is that the <code>registerObject</code> method
     594      also registers the objects with the {@link ExtensionsManager}.
     595     
     596      @param key The object key used to identify the metadata
     597      @param metadata The metadata to store under the key
     598    */
     599    public <M> void registerMetadata(ObjectKey<M> key, M metadata)
     600    {
     601      checkClosed();
     602      xtFile.objectMetadata.put(key, metadata);
     603    }
     604   
     605   
     606  }
    350607}
  • trunk/src/core/net/sf/basedb/util/extensions/manager/ExtensionsFileProcessor.java

    r5598 r5602  
    2222package net.sf.basedb.util.extensions.manager;
    2323
     24import net.sf.basedb.util.extensions.manager.ExtensionsFile.WriteableExtensionsFile;
     25
    2426/**
    2527  Interface that is used to request a callback for each extensions file
     
    3436 
    3537  The manager will first call {@link #begin(ExtensionsManager, int)} and
    36   then {@link #processFile(ExtensionsManager, ExtensionsFile)} for each
     38  then {@link #processFile(ExtensionsManager, WriteableExtensionsFile)} for each
    3739  file that has been confirmed to contain a valid extension definitions
    3840  file. If all files could be processed without problems the manager
     
    6466    If the processor throws an exception the manager will abort
    6567    processing and call {@link #done(ExtensionsManager, Throwable)}.
     68    Error that are related to a specific file should be catched
     69    by the processor and registered by calling .......
    6670    <p>
    6771   
    6872    If all files was processed without exceptions the manager
    6973    will call {@link #done(ExtensionsManager)}.
     74
     75    <p>
     76    Note that the file is read-only to begin with. If the processor
     77    wants to call any write-operation the file must be opened by
     78    calling {@link WriteableExtensionsFile#open()}. It is recommended
     79    that the processor calls {@link WriteableExtensionsFile#close()}
     80    once it is done writing.
    7081   
    7182    @param manager The manager that is executing the action
    7283    @param file The file to be processed
    7384  */
    74   public void processFile(ExtensionsManager manager, ExtensionsFile file);
     85  public void processFile(ExtensionsManager manager, WriteableExtensionsFile file);
    7586
    7687  /**
  • trunk/src/core/net/sf/basedb/util/extensions/manager/ExtensionsManager.java

    r5601 r5602  
    2424import java.io.File;
    2525import java.io.FileFilter;
     26import java.net.URI;
    2627import java.util.ArrayList;
    2728import java.util.HashMap;
     
    3031import java.util.Map;
    3132import java.util.Set;
    32 import java.util.TreeSet;
    33 
    34 import org.apache.commons.collections.map.HashedMap;
     33import java.util.TreeMap;
    3534
    3635import net.sf.basedb.util.RegexpFileFilter;
    3736import net.sf.basedb.util.extensions.Registry;
     37import net.sf.basedb.util.extensions.manager.ExtensionsFile.WriteableExtensionsFile;
    3838
    3939/**
     
    5959  private final Set<ExtensionsFile> ignore;
    6060  // Valid extension files
    61   private final Set<ExtensionsFile> xtFiles;
    62  
    63   // Map objects to the file they are defined in. The key is a unique object id
    64   private final Map<String, ExtensionsFile> installedObjects;
     61  private final Map<URI, ExtensionsFile> xtFiles;
     62 
     63  // Map objects to the file they are defined in. The key is a unique object id.
     64  private final Map<ObjectKey, ExtensionsFile> installedObjects;
    6565 
    6666  /**
     
    7575    this.staticIgnore = new HashSet<File>();
    7676    this.ignore = new HashSet<ExtensionsFile>();
    77     this.xtFiles = new TreeSet<ExtensionsFile>();
    78     this.installedObjects = new HashMap<String, ExtensionsFile>();
     77    this.xtFiles = new TreeMap<URI, ExtensionsFile>();
     78    this.installedObjects = new HashMap<ObjectKey, ExtensionsFile>();
    7979  }
    8080 
     
    9898  {
    9999    if (file == null) return;
    100     ignore.add(new ExtensionsFile(file));
     100    ignore.add(new ExtensionsFile(this, file));
    101101    staticIgnore.add(file);
    102102  }
     
    110110  {
    111111    if (file == null) return;
    112     ignore.remove(new ExtensionsFile(file));
     112    ignore.remove(new ExtensionsFile(this, file));
    113113    staticIgnore.remove(file);
    114114  }
     
    128128    for (File file : dir.listFiles(filter))
    129129    {
    130       addExtensionsFile(new ExtensionsFile(file));
     130      addFile(file);
    131131    }
    132132
     
    136136  /**
    137137    Add a file to the manager that is supposed to contain extensions.
     138    The file either be an XML file containing definitions, or a JAR
     139    file with the definitions in the META-INF/extensions.xml path.
    138140   
    139     @param xtFile An extensions file
    140    */
    141   public void addExtensionsFile(ExtensionsFile xtFile)
    142   {
    143     if (xtFile == null) throw new NullPointerException("xtFile");
    144    
     141    @param file An extensions file (null is not allowed)
     142  */
     143  public void addFile(File file)
     144  {
     145    if (file == null) throw new NullPointerException("file");
     146    addExtensionsFile(new ExtensionsFile(this, file));
     147  }
     148 
     149  /**
     150    Add an URI that points to an XML file containing definitions.
     151    This method is mostly useful for system-defined extensions that
     152    are defined in a XML file inside a JAR file.
     153    <p>
     154   
     155    This method can't be used for JAR files and if used for
     156    XML files it doesn't detect changes that are made after
     157    installation.
     158   
     159    @param uri An URI pointing to an extensions file (null is not allowed)
     160  */
     161  public void addURI(URI uri)
     162  {
     163    if (uri == null) throw new NullPointerException("uri");
     164    addExtensionsFile(new ExtensionsFile(this, uri));
     165  }
     166
     167  private void addExtensionsFile(ExtensionsFile xtFile)
     168  {
    145169    if (ignore.contains(xtFile))
    146170    {
     
    151175    if (xtFile.isValid())
    152176    {
    153       xtFiles.add(xtFile);
     177      xtFiles.put(xtFile.getURI(), xtFile);
    154178    }
    155179    else
     
    159183  }
    160184 
     185  /**
     186    Get a list of all extension files managed by this manager.
     187    @return A list
     188  */
    161189  public List<ExtensionsFile> getFiles()
    162190  {
    163191    // Create a copy, or the iterator will fail if new
    164192    // files are added by another thread
    165     List<ExtensionsFile> copy = new ArrayList<ExtensionsFile>(xtFiles);
     193    List<ExtensionsFile> copy = new ArrayList<ExtensionsFile>(xtFiles.values());
    166194    return copy;
    167195  }
    168196
    169197  /**
    170     Find out which file the object with the given id was defined.
    171     An object id is typically created by an object-specific prefix
    172     plus the unique if of the object. Example:
    173    
    174     <ul>
    175     <li>extension:id-of-extension
    176     <li>extension-point:id-of-extension-point
    177     <li>servlet:name-of-servlet
    178     <li>etc.
    179     </ul>
    180    
    181     @param objectId The complete object id
     198    Get the extension file that is located at the given URI.
     199    This method can be used for all files even those that
     200    have been added with {@link #addFile(File)} or
     201    {@link #addDirectory(File)}.
     202   
     203    @param uri An URI that is pointing to an extensions file
     204    @return An extensions file object, or null if no file is found
     205  */
     206  public ExtensionsFile getFileByURI(String uri)
     207  {
     208    return xtFiles.get(URI.create(uri));
     209  }
     210 
     211  /**
     212    Find out which file the object with the given key was defined.
     213    See implementations of {@link ObjectKey} for various types
     214    of objects to look for.
     215   
     216    @param key The object key
    182217    @return Information about the file the object is defined in,
    183       or null if no extension with the given ID is found
    184   */
    185   public ExtensionsFile getFileByObjectId(String objectId)
    186   {
    187     return installedObjects.get(objectId);
    188   }
    189  
    190   public void setFileForObject(String objectId, ExtensionsFile xtFile)
    191   {
    192     installedObjects.put(objectId, xtFile);
     218      or null if no object is found for the given key
     219  */
     220  public ExtensionsFile getFileByObjectKey(ObjectKey key)
     221  {
     222    return installedObjects.get(key);
     223  }
     224 
     225  /**
     226    Register an object as defined by the given extensions file.
     227   
     228    @param key The object key
     229    @param xtFile The extensions file
     230  */
     231  void registerObject(ObjectKey key, ExtensionsFile xtFile)
     232  {
     233    installedObjects.put(key, xtFile);
    193234  }
    194235 
     
    200241  {
    201242    if (processor == null) throw new NullPointerException("processor");
     243    List<WriteableExtensionsFile> writeableFiles = new ArrayList<WriteableExtensionsFile>(xtFiles.size());
    202244    try
    203245    {
    204246      log.debug("Processing " + xtFiles.size() + " file(s) with processor: " + processor);
    205247      processor.begin(this, xtFiles.size());
    206       for (ExtensionsFile xtFile : xtFiles)
     248      for (ExtensionsFile xtFile : xtFiles.values())
    207249      {
    208250        log.debug("Processing file: " + xtFile);
    209         processor.processFile(this, xtFile);
     251        WriteableExtensionsFile wf = xtFile.getWriteableFile();
     252        writeableFiles.add(wf);
     253        processor.processFile(this, wf);
    210254      }
    211255      processor.done(this);
     
    217261      processor.done(null, t);
    218262    }
    219   }
    220  
     263    finally
     264    {
     265      // Make sure all WriteableExtensionFile:s are closed if the processor "forgets" it
     266      for (WriteableExtensionsFile wf : writeableFiles)
     267      {
     268        wf.close();
     269      }
     270    }
     271  }
    221272 
    222273}
  • trunk/src/core/net/sf/basedb/util/extensions/manager/ExtractResourcesProcessor.java

    r5601 r5602  
    3333
    3434import net.sf.basedb.util.FileUtil;
     35import net.sf.basedb.util.extensions.manager.ExtensionsFile.WriteableExtensionsFile;
    3536
    3637/**
     
    6263  private final Pattern filter;
    6364  private final String replacement;
     65  private final ProcessResults results;
    6466 
    6567  /**
     
    7072      only overwrite files if they are different from the files in the JAR
    7173  */
    72   public ExtractResourcesProcessor(File mainDir, boolean forceOverwrite)
     74  public ExtractResourcesProcessor(File mainDir, boolean forceOverwrite, ProcessResults results)
    7375  {
    74     this(mainDir, forceOverwrite, null, null);
     76    this(mainDir, forceOverwrite, null, null, results);
    7577  }
    7678
     
    8688      using {@link Matcher#replaceAll(String)}.
    8789  */
    88   public ExtractResourcesProcessor(File mainDir, boolean forceOverwrite, Pattern filter, String replacement)
     90  public ExtractResourcesProcessor(File mainDir, boolean forceOverwrite, Pattern filter, String replacement, ProcessResults results)
    8991  {
    9092    this.mainDir = mainDir;
     
    9294    this.filter = filter;
    9395    this.replacement = replacement;
     96    this.results = results;
    9497  }
    9598
     
    104107
    105108  @Override
    106   public void processFile(ExtensionsManager manager, ExtensionsFile file)
     109  public void processFile(ExtensionsManager manager, WriteableExtensionsFile writeableFile)
    107110  {
    108     if (!file.isJar()) return;
    109    
    110     File jar = file.getFile();
     111    ExtensionsFile xtFile = writeableFile.getExtensionsFile();
     112    if (!xtFile.isJar())
     113    {
     114      log.info("File is not a JAR file (skipping extraction): " + xtFile);
     115      return;
     116    }
     117   
     118    // Do not extract from files with an error
     119    if (xtFile.hasError())
     120    {
     121      log.info("File has errors (skipping extraction): " + xtFile);
     122      return;
     123    }
     124   
     125    // Skip the file not modified (unless forced to extract)
     126    if (!forceOverwrite && !xtFile.isModified())
     127    {
     128      log.info("File is unmodified (skipping extraction): " + xtFile);
     129      return;
     130    }
     131   
     132    File jar = xtFile.getFile();
    111133    File targetDir = new File(mainDir, jar.getName());
    112134
     
    127149        if (name.startsWith("/")) name = name.substring(1);
    128150
    129         // Should the current entry be extracted or not? We start by assuming that...
     151        // Should the current entry be extracted or not? We start by assuming so ...
    130152        boolean extract = true;
    131153        // A filter may change the actual name of the extracted file
     
    135157          // Ignore directories
    136158          extract = false;
    137           log.debug("File '" + name + "' is a directory. Ignored.");
     159          log.debug("Jar entry '" + name + "' is a directory (ignored).");
    138160        }
    139161        else if (filter != null)
     
    144166          {
    145167            extract = false;
    146             log.debug("File '" + name + "' doesn't match filter. Ignored.");
     168            log.debug("Jar entry '" + name + "' doesn't match filter (ignored).");
    147169          }
    148170          else
     
    161183          {
    162184            extract = false;
    163             log.debug("File '" + name + "' has same time and size. Ignored.");
     185            log.debug("Jar entry '" + name + "' has same time and size (ignored).");
    164186          }
    165187        }
     
    197219        }
    198220      }
     221      log.info("Extracted " + numExtracted + " resources from '" + jar.getName() + "' to " + targetDir);
     222      results.addMessage(xtFile,  numExtracted + " resources extracted successfully.");
    199223    }
    200224    catch (Exception ex)
     
    202226      String msg = "Failed to extract resources from '" + jar.getName() + "' to " + targetDir;
    203227      log.error(msg, ex);
    204       //throw new RuntimeException(msg, ex);
     228      writeableFile.setError(true);
     229      results.addErrorMessage(xtFile, msg);
    205230    }
    206231    finally
     
    213238  public void done(ExtensionsManager manager)
    214239  {}
     240 
    215241  @Override
    216242  public void done(ExtensionsManager manager, Throwable t)
  • trunk/src/core/net/sf/basedb/util/extensions/manager/RegisterExtensionsProcessor.java

    r5601 r5602  
    3131import net.sf.basedb.util.extensions.ExtensionPoint;
    3232import net.sf.basedb.util.extensions.Registry;
     33import net.sf.basedb.util.extensions.manager.ExtensionsFile.WriteableExtensionsFile;
    3334import net.sf.basedb.util.extensions.xml.XmlLoader;
    3435
     
    3637  Extension file processor implementation that will load the
    3738  extension definitions from each file and register them with
    38   the registry that is managed by the manager.
     39  the registry that is managed by the manager. This processor
     40  is a two-step processer. The first step will load extension
     41  definitions from the files. The second step will register the
     42  loaded extension with the managers registry.
     43  <p>
     44  The first step is executed via the manager:
     45  {@link ExtensionsManager#processFiles(ExtensionsFileProcessor)}.
     46  The second step is either automatically executed when all files
     47  have been processed or executed by by calling {@link #registerExtensions(ExtensionsManager)}.
    3948
    4049  @author Nicklas
     
    5160 
    5261  private final XmlLoader loader;
    53   private List<Metadata> allMeta;
     62  private final ProcessResults results;
     63  private final boolean delayRegistration;
     64  private List<FileData> allData;
    5465 
    5566  /**
     
    5768   
    5869    @param loader The XML loader to use when parsing the metadata
    59   */
    60   public RegisterExtensionsProcessor(XmlLoader loader)
     70    @param delayRegistration If TRUE, the actual registriation of the extensions
     71      are delayed until {@link #registerExtensions(ExtensionsManager)} is called
     72  */
     73  public RegisterExtensionsProcessor(XmlLoader loader, boolean delayRegistration, ProcessResults results)
    6174  {
    6275    this.loader = loader;
     76    this.delayRegistration = delayRegistration;
     77    this.results = results;
    6378  }
    6479 
     
    7085  public void begin(ExtensionsManager manager, int numFiles)
    7186  {
    72     this.allMeta = new ArrayList<Metadata>(numFiles);
    73   }
    74 
    75   @Override
    76   public void processFile(ExtensionsManager manager, ExtensionsFile xtFile)
     87    this.allData = new ArrayList<FileData>(numFiles);
     88  }
     89
     90  @Override
     91  public void processFile(ExtensionsManager manager, WriteableExtensionsFile writeableFile)
    7792  {
    7893    InputStream in = null;
     94    ExtensionsFile xtFile = writeableFile.getExtensionsFile();
    7995    try
    8096    {
     97      log.info("Loading extensions from file: " + xtFile.getName());
    8198      in = xtFile.getXmlStream();
    82       log.debug("Loading extensions from file: " + xtFile.getName());
    8399      loader.loadXmlFile(in, xtFile.getName(), xtFile.getClassLoader(), true);
     100      FileData data = new FileData();
     101      data.writeableFile = writeableFile;
     102      data.extensionPoints = new ArrayList<ExtensionPoint>(loader.getExtensionPoints());
     103      data.extensions = new ArrayList<Extension>(loader.getExtensions());
     104      log.info("Loaded " + data.extensionPoints.size() + "/" + data.extensions.size() +
     105          " extensions from file: " + xtFile.getName());
     106      allData.add(data);
     107    }
     108    catch (Exception ex)
     109    {
     110      writeableFile.setError(true);
     111      String msg = "Failed to load extensions from '" + xtFile.getName() + "'";
     112      results.addErrorMessage(xtFile, msg + ":" + ex.getMessage());
     113      log.error(msg, ex);
     114    }
     115    finally
     116    {
     117      FileUtil.close(in);
     118    }
     119  }
     120 
     121  @Override
     122  public void done(ExtensionsManager manager)
     123  {
     124    if (!delayRegistration) registerExtensions(manager);
     125  }
     126 
     127  @Override
     128  public void done(ExtensionsManager manager, Throwable t)
     129  {
     130    if (allData != null)  allData.clear();
     131    allData = null;
     132  }
     133  // ------------------------------------------
     134
     135 
     136  public void registerExtensions(ExtensionsManager manager)
     137  {
     138    if (allData == null) return;
     139
     140    Registry registry = manager.getRegistry();
     141
     142    // First loop -- register extension points
     143    log.info("Registering all loaded extension points");
     144    for (FileData data : allData)
     145    {
     146      WriteableExtensionsFile wFile = data.writeableFile;
     147      ExtensionsFile xtFile = wFile.getExtensionsFile();
     148
     149      // NOTE! Do not register files with an error
     150      if (xtFile.hasError())
     151      {
     152        log.debug("Skipping file with error: " + xtFile);
     153        continue; // with the next file
     154      }
    84155     
    85       Metadata meta = new Metadata();
    86       meta.xtFile = xtFile;
    87       meta.extensionPoints = new ArrayList<ExtensionPoint>(loader.getExtensionPoints());
    88       meta.extensions = new ArrayList<Extension>(loader.getExtensions());
    89       allMeta.add(meta);
    90     }
    91     catch (Exception ex)
    92     {
    93       String msg = "Failed to load extensions from '" + xtFile.getName() + "'";
    94       log.error(msg, ex);
    95       //throw new RuntimeException(msg, ex));
    96     }
    97     finally
    98     {
    99       FileUtil.close(in);
    100     }
    101   }
    102  
    103   @Override
    104   public void done(ExtensionsManager manager)
    105   {
    106     log.debug("Registering all loaded extensions");
    107     if (allMeta != null)
    108     {
    109       Registry registry = manager.getRegistry();
    110       for (Metadata meta : allMeta)
    111       {
    112         for (ExtensionPoint<Action> ep : meta.extensionPoints)
     156      try
     157      {
     158        wFile.open();
     159        int num = registerExtensionPoints(data, registry);
     160        if (num > 0)
    113161        {
    114           if (!registry.extensionPointIsRegistered(ep.getId()))
    115           {
    116             registry.registerExtensionPoint(ep);
    117             manager.setFileForObject("extension-point:" + ep.getId(), meta.xtFile);
    118           }
     162          results.addMessage(xtFile, num + " extension points registered.");
    119163        }
    120       }
    121       for (Metadata meta : allMeta)
    122       {
    123         for (Extension<Action> ext : meta.extensions)
     164        log.info("Registered " + num + " extension points from file: " + xtFile);
     165      }
     166      catch (Throwable ex)
     167      {
     168        wFile.setError(true);
     169        results.addErrorMessage(xtFile,
     170          "Could not register extension points: " + ex.getMessage());
     171        log.error("Could not register extension points from file: " + xtFile, ex);
     172      }
     173      finally
     174      {
     175        wFile.close(); // Important! release the write lock
     176      }
     177    }
     178   
     179    // Second loop -- register extensions
     180    log.info("Registering all loaded extensions");
     181    for (FileData data : allData)
     182    {
     183      WriteableExtensionsFile wFile = data.writeableFile;
     184      ExtensionsFile xtFile = wFile.getExtensionsFile();
     185
     186      // NOTE! Do not register files with an error
     187      if (xtFile.hasError())
     188      {
     189        log.debug("Skipping file with error: " + xtFile);
     190        continue; // with the next file
     191      }
     192     
     193      try
     194      {
     195        wFile.open();
     196        int num = registerExtensions(data, registry);
     197        if (num > 0)
    124198        {
    125           if (!registry.extensionIsRegistered(ext.getId()))
    126           {
    127             registry.registerExtension(ext);
    128             manager.setFileForObject("extension:" + ext.getId(), meta.xtFile);
    129           }
     199          results.addMessage(xtFile, num + " extensions registered.");
    130200        }
    131       }
    132       allMeta.clear();
    133       allMeta = null;
    134     }
    135     /*
    136     loader.registerExtensionPoints(manager.getRegistry(), false);
    137     loader.registerExtensions(manager.getRegistry(), false);
    138     */
    139   }
    140  
    141   @Override
    142   public void done(ExtensionsManager manager, Throwable t)
    143   {
    144     if (allMeta != null) allMeta.clear();
    145     allMeta = null;
    146   }
    147   // ------------------------------------------
    148 
    149 
    150   static class Metadata
    151   {
    152     ExtensionsFile xtFile;
     201        log.info("Registered " + num + " extension points from file: " + xtFile);
     202      }
     203      catch (Throwable ex)
     204      {
     205        wFile.setError(true);
     206        results.addErrorMessage(xtFile,
     207          "Could not register extension points: " + ex.getMessage());
     208        log.error("Could not register extension points from file: " + xtFile, ex);
     209      }
     210      finally
     211      {
     212        wFile.close(); // Important! release the write lock
     213      }
     214    }
     215   
     216    allData.clear();
     217    allData = null;
     218  }
     219
     220 
     221  private int registerExtensionPoints(FileData data, Registry registry)
     222  {
     223    int numRegistered = 0;
     224    for (ExtensionPoint<Action> ep : data.extensionPoints)
     225    {
     226      if (!registry.extensionPointIsRegistered(ep.getId()))
     227      {
     228        ExtensionPointKey key = new ExtensionPointKey(ep);
     229        data.writeableFile.registerObject(key, ep);
     230        registerFactory(data, ep.getErrorHandlerFactory());
     231        registerFactory(data, ep.getRendererFactory());
     232        registry.registerExtensionPoint(ep);
     233        numRegistered++;
     234      }
     235    }
     236    return numRegistered;
     237  }
     238 
     239  private int registerExtensions(FileData data, Registry registry)
     240  {
     241    int numRegistered = 0;
     242    for (Extension<Action> ext : data.extensions)
     243    {
     244      if (!registry.extensionIsRegistered(ext.getId()))
     245      {
     246        ExtensionKey key = new ExtensionKey(ext);
     247        data.writeableFile.registerObject(key, ext);
     248        registerFactory(data, ext.getActionFactory());
     249        registerFactory(data, ext.getRendererFactory());
     250        registry.registerExtension(ext);
     251        numRegistered++;
     252      }
     253    }
     254    return numRegistered;
     255  }
     256 
     257  /**
     258    Register factory parameters for the given factory instance.
     259    The parameters are retreived from the {@link XmlLoader#getFactoryParameters(Object)}
     260    method.
     261   
     262    @param data The extension file the factory was defined in
     263    @param factory The factory instance (if null, no registration is done)
     264  */
     265  private void registerFactory(FileData data, Object factory)
     266  {
     267    if (factory == null) return;
     268    data.writeableFile.registerMetadata(new FactoryParametersKey(factory), loader.getFactoryParameters(factory));
     269  }
     270
     271  /**
     272    Keep track of the extension points and extensions found in a file.
     273  */
     274  static class FileData
     275  {
     276    WriteableExtensionsFile writeableFile;
    153277    List<Extension> extensions;
    154278    List<ExtensionPoint> extensionPoints;
    155279  }
    156280
    157 
    158281}
  • trunk/www/admin/extensions/details.jsp

    r5601 r5602  
    4040  import="net.sf.basedb.util.extensions.AboutBean"
    4141  import="net.sf.basedb.util.extensions.manager.ExtensionsFile"
     42  import="net.sf.basedb.util.extensions.manager.ExtensionPointKey"
     43  import="net.sf.basedb.util.extensions.manager.ExtensionKey"
     44  import="net.sf.basedb.util.extensions.manager.FactoryParametersKey"
     45  import="net.sf.basedb.util.extensions.manager.ProcessResults"
     46  import="net.sf.basedb.util.extensions.manager.ProcessResults.FileResults"
    4247  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
    43   import="net.sf.basedb.clients.web.extensions.ScanResults"
    44   import="net.sf.basedb.clients.web.extensions.ScanResults.FileResults"
    4548  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
    4649  import="net.sf.basedb.util.formatter.Formatter"
     
    6063  }
    6164  String text = factory.getClass().getName();
    62   String parameters = null; //file == null ? null : file.getFactoryParameters(factory);
     65  String parameters = file == null ? null : file.getMetadata(new FactoryParametersKey(factory));
    6366  if (parameters != null)
    6467  {
     
    7477String extensionId = request.getParameter("extensionId");
    7578String extensionPointId = request.getParameter("extensionPointId");
    76 String filename = request.getParameter("filename");
     79String fileuri = request.getParameter("fileuri");
    7780
    7881DbControl dc = sc.newDbControl();
     
    8891  ExtensionsFile epFile = null;
    8992
    90   if (filename != null)
    91   {
    92     file = ec.getFile(filename);
     93  if (fileuri != null)
     94  {
     95    file = ec.getFile(fileuri);
    9396    if (file == null)
    9497    {
    95       throw new ItemNotFoundException("ExtensionsFile[name=" + filename + "]");
     98      throw new ItemNotFoundException("ExtensionsFile[uri=" + fileuri + "]");
    9699    }
    97100  }
     
    105108    }
    106109    extensionPointId = ext.getExtends();
    107     extFile = ec.getFileByObjectId("extension:" + extensionId);
     110    extFile = ec.getFileByObjectKey(new ExtensionKey(extensionId));
    108111  }
    109112 
     
    115118      throw new ItemNotFoundException("ExtensionPoint[id=" + extensionPointId + "]");
    116119    }
    117     epFile = ec.getFileByObjectId("extension-point:" + extensionPointId);
     120    epFile = ec.getFileByObjectKey(new ExtensionPointKey(extensionPointId));
    118121  }
    119122%>
     
    144147  function enableFile(enable)
    145148  {
    146     window.parent.frames['tree'].setChildIcons('<%=HTML.javaScriptEncode(filename)%>', enable);
     149    window.parent.frames['tree'].setChildIcons('<%=HTML.javaScriptEncode(fileuri)%>', enable);
    147150    var url = 'index.jsp?ID=<%=ID%>&cmd=EnableFile';
    148     url += '&filename=<%=HTML.urlEncode(filename)%>';
     151    url += '&fileuri=<%=HTML.urlEncode(fileuri)%>';
    149152    url += '&enable='+enable;
    150153    location.href = url;
    151154  }
    152155 
    153   function showFile(filename)
    154   {
    155     window.parent.frames['tree'].selectFile(filename);
     156  function showFile(fileuri)
     157  {
     158    window.parent.frames['tree'].selectFile(fileuri);
    156159  }
    157160
     
    186189    {
    187190      boolean isEnabled = ec.isEnabled(ext);
    188       boolean hasRegistrationError = extFile != null; // && extFile.hasError();
     191      boolean hasRegistrationError = extFile != null && extFile.hasError();
    189192      boolean allow = writePermission && !hasRegistrationError;
    190193      %>
     
    207210    {
    208211      boolean isEnabled = ec.isEnabled(ep);
    209       boolean hasRegistrationError = epFile != null; // && epFile.hasError();
     212      boolean hasRegistrationError = epFile != null && epFile.hasError();
    210213      boolean allow = writePermission && !hasRegistrationError;
    211214      %>
     
    227230    else if (file != null)
    228231    {
    229       boolean hasRegistrationError = false; //file.hasError();
     232      boolean hasRegistrationError = file.hasError();
    230233      boolean allow = writePermission && !hasRegistrationError;
    231234      %>
     
    315318            ><%=extFile.getName()%></a>
    316319            (<%=extFile.isModified() ? "Modified" : "Up to date" %>;
    317             <%=false /*extFile.hasError()*/ ? "Error" : "Ok" %>)
     320            <%=extFile.hasError() ? "Error" : "Ok" %>)
    318321          </td>
    319322        </tr>
     
    403406              ><%=epFile.getName()%></a>
    404407              (<%=epFile.isModified() ? "Modified" : "Up to date" %>;
    405               <%=true /*epFile.hasError()*/ ? "Error" : "Ok" %>)
     408              <%=epFile.hasError() ? "Error" : "Ok" %>)
    406409              <%
    407410            }
     
    454457          <td>
    455458            <%
    456             if (false /*file.hasError()*/)
     459            if (file.hasError())
    457460            {
    458               ScanResults results = ec.getLastScanResults();
    459               FileResults fileResults = null; //results.getResults(file);
     461              ProcessResults results = ec.getLastScanResults();
     462              FileResults fileResults = results.getResults(file);
    460463              List<String> messages = fileResults.getMessages();
    461464              Throwable validationError = file.getValidationError();
     
    517520      if (ext == null && ep == null && file == null)
    518521      {
    519         ScanResults results = ec.getLastScanResults();
     522        ProcessResults results = ec.getLastScanResults();
    520523        Formatter dateTimeFormatter = FormatterFactory.getDateTimeFormatter(sc);
    521524        %>
  • trunk/www/admin/extensions/scan_results.jsp

    r5426 r5602  
    3636  import="net.sf.basedb.util.extensions.ExtensionPoint"
    3737  import="net.sf.basedb.util.extensions.Extension"
     38  import="net.sf.basedb.util.extensions.manager.ExtensionsFile"
     39  import="net.sf.basedb.util.extensions.manager.ProcessResults"
     40  import="net.sf.basedb.util.extensions.manager.ProcessResults.FileResults"
    3841  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
    39   import="net.sf.basedb.clients.web.extensions.ExtensionsFile"
    40   import="net.sf.basedb.clients.web.extensions.ScanResults"
    41   import="net.sf.basedb.clients.web.extensions.ScanResults.FileResults"
    4242  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
    4343  import="net.sf.basedb.util.formatter.Formatter"
     
    5555  dc = sc.newDbControl();
    5656  ExtensionsControl ec = ExtensionsControl.get(dc);
    57   ScanResults results = ec.getLastScanResults();
     57  ProcessResults results = ec.getLastScanResults();
    5858  Formatter timeFormatter = FormatterFactory.getDateTimeFormatter(sc);
    5959%>
     
    106106    <table class="form">
    107107    <%
    108     for (ExtensionsFile extFile : results.getFiles())
     108    for (FileResults fileResults : results.getAllResults())
    109109    {
    110       FileResults fileResults = results.getResults(extFile);
     110      ExtensionsFile extFile = fileResults.getExtensionsFile();
    111111      boolean isError = fileResults.hasError();
    112112      String detailsId = Integer.toString(extFile.hashCode());
  • trunk/www/admin/extensions/tree.jsp

    r5601 r5602  
    158158    var group;
    159159    <%
    160     //Iterator<ExtensionsFile> files = ec.getFiles();
    161160    for (ExtensionsFile ef : ec.getFiles())
    162161    {
    163       //ExtensionsFile ef = files.next();
    164162      String efName = ef.getName();
    165163      String icon = ef.isJar() ? "JarFile" : "XmlFile";
    166       //if (ef.hasError()) icon += "Error";
     164      if (ef.hasError()) icon += "Error";
    167165      String id = efName;
    168166      %>
    169       file = JoustMenu.addChildItem(byFile, '<%=icon%>', '<%=HTML.javaScriptEncode(efName)%>', 'fileOnClick("<%=efName%>")', '', '<%=id%>');
     167      file = JoustMenu.addChildItem(byFile, '<%=icon%>', '<%=HTML.javaScriptEncode(efName)%>', 'fileOnClick("<%=ef.getURI().toString()%>")', '', '<%=id%>');
    170168      <%
    171       /*
    172       Iterator<ExtensionPoint<?>> eps = ef.getExtensionPoints();
    173       while (eps.hasNext())
    174       {
    175         ExtensionPoint ep = eps.next();
     169      List<ExtensionPoint> eps = ef.getObjectsOfClass(ExtensionPoint.class);
     170      for (ExtensionPoint ep : eps)
     171      {
    176172        %>
    177173        <%=getJoustExtensionPoint("file", ec, ep)%>
    178174        <%
    179175      }
    180       */
    181       /*
    182       Iterator<Extension<?>> exts = ef.getExtensions();
     176      List<Extension> exts = ef.getObjectsOfClass(Extension.class);
    183177      String currentGroupId = null;
    184       while (exts.hasNext())
    185       {
    186         Extension ext = exts.next();
     178      for (Extension ext : exts)
     179      {
    187180        int groupIndex = ext.getId().indexOf(":");
    188181        // ID:s containing ':' should be grouped
     
    206199        <%
    207200      }
    208       */
    209201    }
    210202    %>
     
    295287    parent.frames['details'].location.href = 'details.jsp?ID=<%=ID%>&extensionId='+extensionId;
    296288  }
    297   function fileOnClick(filename)
    298   {
    299     parent.frames['details'].location.href = 'details.jsp?ID=<%=ID%>&filename='+escape(filename);
     289  function fileOnClick(fileuri)
     290  {
     291    parent.frames['details'].location.href = 'details.jsp?ID=<%=ID%>&fileuri='+escape(fileuri);
    300292  }
    301293  </script>
Note: See TracChangeset for help on using the changeset viewer.