Author: scottbw
Date: Wed Jun 29 20:43:25 2011
New Revision: 1141240

URL: http://svn.apache.org/viewvc?rev=1141240&view=rev
Log:
Several improvements to the Flatpack feature (see WOOKIE-182). (1) the 
controller uses the widgetserver properties to construct the return path for 
the exported .wgt rather than just the request (see WOOKIE-111). (2) feature 
resources are added once in the factory, not every time a start file is 
processed. (3) Improved code comments and formatting.

Modified:
    
incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java
    incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackFactory.java
    incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackProcessor.java

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java?rev=1141240&r1=1141239&r2=1141240&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java 
(original)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java 
Wed Jun 29 20:43:25 2011
@@ -21,6 +21,7 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.configuration.Configuration;
 import org.apache.log4j.Logger;
 import org.apache.wookie.beans.IWidgetInstance;
 import org.apache.wookie.controller.Controller;
@@ -80,15 +81,45 @@ public class FlatpackController extends 
                if (!WidgetKeyManager.isValidRequest(request)) throw new 
UnauthorizedAccessException();
                String path;
                try {
+                 //
+                 // Construct a FlatpackFactory for the instance identified in 
the request
+                 // If no instance can be found, throw an exception
+                 //
                        IWidgetInstance instance = 
WidgetInstancesController.findWidgetInstance(request);
+                       if (instance == null) throw new 
InvalidParametersException();
                        FlatpackFactory fac = new FlatpackFactory(instance);
+                       
+                       //
                        // Set the folder to save the flatpack to an 
appropriate location on this server
+                       //
                        fac.setFlatpackFolder(new 
File(request.getSession().getServletContext().getRealPath(FlatpackFactory.DEFAULT_FLATPACK_FOLDER.getPath())));
-                       // Construct the URL to the file
-                       String serverName = 
request.getSession().getServletContext().getContextPath();
-                       path = serverName + "/" + 
FlatpackFactory.DEFAULT_FLATPACK_FOLDER + "/" + fac.pack().getName();
-                       URL url =  new URL(request.getScheme() , 
request.getServerName() , request.getServerPort() , path);
+                       
+                       // 
+                       // Pack the widget instance and get the resulting File
+                       //
+                       File flatpack = fac.pack();
+                       
+                 //
+                       // Construct the URL pointing to the exported .wgt file
+                       // Use settings defined in properties if available, 
otherwise use the request context
+                       // to construct a URL. Note that the resource begins 
with the servlet path, typically
+                       // "/wookie"
+                       //
+      Configuration properties = (Configuration) 
request.getSession().getServletContext().getAttribute("properties"); 
//$NON-NLS-1$
+      String scheme = request.getScheme();
+      String serverName = request.getServerName();
+      int serverPort = request.getServerPort();
+      String resource = 
request.getSession().getServletContext().getContextPath() + "/" + 
FlatpackFactory.DEFAULT_FLATPACK_FOLDER + "/" + flatpack.getName();
+      if (properties.getString("widget.server.scheme")!=null && 
!properties.getString("widget.server.scheme").trim().equals("")) scheme = 
properties.getString("widget.server.scheme"); //$NON-NLS-1$ //$NON-NLS-2$ 
//$NON-NLS-3$
+      if (properties.getString("widget.server.host")!=null && 
!properties.getString("widget.server.host").trim().equals("")) serverName = 
properties.getString("widget.server.host"); //$NON-NLS-1$ //$NON-NLS-2$ 
//$NON-NLS-3$
+      if (properties.getString("widget.server.port")!=null && 
!properties.getString("widget.server.port").trim().equals("")) serverPort = 
Integer.parseInt(properties.getString("widget.server.port")); //$NON-NLS-1$ 
//$NON-NLS-2$ //$NON-NLS-3$
+      URL url =  new URL(scheme, serverName, serverPort, resource);
+      
+      //
+      // Return the String version of the URL pointing to the exported .wgt 
file
+      //
                        path = url.toString();
+                       
                } catch (Exception e) {
                        throw new InvalidParametersException();
                }

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackFactory.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackFactory.java?rev=1141240&r1=1141239&r2=1141240&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackFactory.java 
(original)
+++ incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackFactory.java 
Wed Jun 29 20:43:25 2011
@@ -15,10 +15,15 @@ package org.apache.wookie.flatpack;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
 import org.apache.wookie.beans.IPreference;
 import org.apache.wookie.beans.IWidgetInstance;
 import org.apache.wookie.feature.Features;
+import org.apache.wookie.feature.IFeature;
+import org.apache.wookie.w3c.IFeatureEntity;
 import org.apache.wookie.w3c.IPreferenceEntity;
 import org.apache.wookie.w3c.W3CWidget;
 import org.apache.wookie.w3c.W3CWidgetFactory;
@@ -28,181 +33,327 @@ import org.apache.wookie.w3c.util.Widget
 import org.apache.wookie.w3c.util.WidgetPackageUtils;
 
 /**
- * Factory class for creating flatpacks - Widgets re-packaged with Widget 
Instance information and exported as a .wgt package.
+ * Factory class for creating flatpacks - Widgets re-packaged with Widget
+ * Instance information and exported as a .wgt package.
  * 
- * <p>For example, this can be used to create an exported Widget for 
side-loading into a mobile widget runtime.</p>
+ * <p>
+ * For example, this can be used to create an exported Widget for side-loading
+ * into a mobile widget runtime.
+ * </p>
  * 
- * <p>Factory properties:</p>
+ * <p>
+ * Factory properties:
+ * </p>
  * 
  * <dl>
- *   <dt>parser</dt>
- *   <dd>The W3CWidgetFactory to use to parse the widget. If this is not 
specified, DEFAULT_PARSER will be used.</dd>
- *   <dt>instance</dt>
- *   <dd>The Widget Instance to be flatpacked.</dd>
- *   <dt>flatpackFolder</dt>
- *   <dd>The folder on the file system where the flatpacked Widget package 
should be saved. If this is not specified, DEFAULT_FLATPACK_FOLDER will be 
used</dd>
- *   <dt>featuresToFlatten</dt>
- *   <dd>The features that should be "flattened" rather than omitted - that 
is, that should be injected into the final package.</dd>
+ * <dt>parser</dt>
+ * <dd>The W3CWidgetFactory to use to parse the widget. If this is not
+ * specified, DEFAULT_PARSER will be used.</dd>
+ * <dt>instance</dt>
+ * <dd>The Widget Instance to be flatpacked.</dd>
+ * <dt>flatpackFolder</dt>
+ * <dd>The folder on the file system where the flatpacked Widget package should
+ * be saved. If this is not specified, DEFAULT_FLATPACK_FOLDER will be 
used</dd>
  * </dl>
- * @author [email protected]
- *
+ * 
+ * <p>
+ * When the FlatpackFactory has been created, call the <code>pack()</code>
+ * method to pack the widget instance, and return a pointer to the file where
+ * the .wgt package has been created
+ * </p>
+ * 
  */
 public class FlatpackFactory {
-       
-       public static final W3CWidgetFactory DEFAULT_PARSER = 
createDefaultParser();
-       public static final File DEFAULT_FLATPACK_FOLDER = new File("export");
-       private static final String DEFAULT_LOCAL_PATH = "/widgets"; // The 
default local path to use
-       
-       private W3CWidgetFactory parser; // the widget parser to use
-       private IWidgetInstance instance; // the instance of the widget to 
flatpack
-       private File inputWidget; // the source .wgt file for the instance
-       private File flatpackFolder; // the folder where we put all our 
flatpack .wgt files once we've created them
-       
-       /**
-        * Constructor, takes a Widget Instance as its argument
-        * @param instance the instance to flatpack
-        */
-       public FlatpackFactory(IWidgetInstance instance){
-               this.instance = instance;
-       }
-       
-       /**
-        * Packages a widget instance into a new .wgt Widget package
-        * @return the widget file
-        * @throws Exception
-        */
-       public File pack() throws Exception{
-               // Verify configuration and apply defaults
-               if (instance == null) throw new Exception("No instance 
specified");
-               if (flatpackFolder == null) flatpackFolder = 
DEFAULT_FLATPACK_FOLDER;
-               if (inputWidget == null){
-                       // try to locate the widget upload package from the 
WidgetInstance
-                       inputWidget = new 
File(instance.getWidget().getPackagePath());
-               }
-               if (parser == null) this.setParser(DEFAULT_PARSER);
-               
-               // Verify the file locations we're using exist
-               if (!inputWidget.exists()) throw new Exception("Input widget 
file does not exist:"+inputWidget.getPath());
-               if (!flatpackFolder.exists()){
-                       if (!flatpackFolder.mkdir()) throw new 
Exception("Flatpack folder could not be created:"+flatpackFolder.getPath());
-                       // Create an index.html file; this prevents browsing 
exported files.
-                       new 
File(flatpackFolder.getPath()+"/index.html").createNewFile();
-               }
-               
-               // Create tmp working area
-               File workingArea = File.createTempFile("wookie-flatpack", "");
-               if (workingArea.exists()) workingArea.delete();
-               workingArea.mkdir();
-               
-               // Set the working area for unpacking the widget
-               parser.setOutputDirectory(workingArea.getAbsolutePath());
-               
-               // Parse the widget and unpack it into the working area
-               W3CWidget widget = parser.parse(inputWidget);
-               
-               // Process the config.xml file
-               widget = processWidget(widget);
-               
-               // Save the config.xml
-               WidgetOutputter outputter = new WidgetOutputter();
-               outputter.setWidgetFolder(DEFAULT_LOCAL_PATH);
-               
-               File configXml = new File(parser.getUnzippedWidgetDirectory(), 
"config.xml");
-               outputter.outputXML(widget, configXml);
-               
-               // Select a filename
-               String name = new RandomGUID().toString()+".wgt";
-               
-               // Pack up the widget
-               File outputWidget = new File(flatpackFolder,name);
-               
WidgetPackageUtils.repackZip(parser.getUnzippedWidgetDirectory(), outputWidget);
-               
-               // Delete the working area
-               workingArea.delete();
-               
-               return outputWidget;
-       }
-       
-       /**
-        * Processes the Widget object, for example adding any preferences
-        * set in the Widget Instance
-        * @param widget the widget to process
-        * @return the processed widget
-        */
-       private W3CWidget processWidget(W3CWidget widget){
-               // Add each preferences from the instance to the widget
-               for (IPreference pref: instance.getPreferences()){
-                       PreferenceEntity newPref = 
(PreferenceEntity)getPreference(pref.getDkey(), widget);
-                       newPref.setValue(pref.getDvalue());
-                       newPref.setReadOnly(pref.isReadOnly());
-                       widget.getPrefences().add(newPref);
-               }
-               
-               // TODO Remove any flattened features
-               
-               return widget;
-       }
-       
-       /**
-        * Get the preference entity for the named preference; either use the 
existing
-        * one from the configuration or create a new instance if there was no 
existing
-        * entity.
-        * @param name
-        * @param widget
-        * @return a preference entity for the named preference
-        */
-       private IPreferenceEntity getPreference(String name, W3CWidget widget){
-               for (IPreferenceEntity pref:widget.getPrefences()){
-                       if (pref.getName().equals(name)) return pref;
-               }
-               PreferenceEntity pref = new PreferenceEntity();
-               pref.setName(name);
-               return pref;
-       }
-
-       /**
-        * Set the Widget file to flatpack. TODO remove this as the 
WidgetInstance should be capable of being used to locate the Widget.
-        * @param inputWidget
-        */
-       public void setInputWidget(File inputWidget) {
-               this.inputWidget = inputWidget;
-       }
-
-       /**
-        * Set the folder where flatpacked Widgets should be exported, e.g. 
"/flatpack" or "/exports"
-        * @param flatpackFolder
-        */
-       public void setFlatpackFolder(File flatpackFolder) {
-               this.flatpackFolder = flatpackFolder;
-       }
-       
-       /**
-        * Sets the W3CWidgetFactory to use as the widget parser
-        * Note that we override the startPageProcessor with FlatpackProcessor
-        * and rewrite the local path to DEFAULT_LOCAL_PATH.
-        * @param factory
-        * @throws IOException 
-        */
-       public void setParser(W3CWidgetFactory factory) throws IOException{
-               parser = factory;
-               parser.setStartPageProcessor(new FlatpackProcessor());
-               parser.setLocalPath(DEFAULT_LOCAL_PATH);
-       }
-       
-       /*
-        * Construct a standard W3CWidgetFactory parser for testing
-        */
-       private static W3CWidgetFactory createDefaultParser() {
-               W3CWidgetFactory fac = new W3CWidgetFactory();
-               fac.setLocalPath(DEFAULT_LOCAL_PATH);
-        fac.setFeatures(Features.getFeatureNames());
-               try {
-                       fac.setEncodings(new String[]{"UTF-8"});
-               } catch (Exception e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               }
-               return fac;
-       }       
+
+  // the default parser
+  public static final W3CWidgetFactory DEFAULT_PARSER = createDefaultParser();
+  
+  // the default export path to use
+  public static final File DEFAULT_FLATPACK_FOLDER = new File("export");
+  
+  // the default local widget path to use
+  private static final String DEFAULT_LOCAL_PATH = "/widgets";
+
+  // Logger for this class
+  static Logger _logger = Logger.getLogger(FlatpackFactory.class.getName()); 
+
+  // the widget parser to use
+  private W3CWidgetFactory parser; 
+  
+  // the instance of the widget to flatpack
+  private IWidgetInstance instance; 
+  
+  //the source .wgt file for the instance
+  private File inputWidget; 
+  
+  // the folder where we put all our flatpack .wgt files once we've created 
them
+  private File flatpackFolder;
+
+  /**
+   * Constructor, takes a Widget Instance as its argument
+   * 
+   * @param instance
+   *          the instance to flatpack
+   */
+  public FlatpackFactory(IWidgetInstance instance) {
+    this.instance = instance;
+  }
+
+  /**
+   * Packages a widget instance into a new .wgt Widget package
+   * 
+   * @return the widget file
+   * @throws Exception
+   */
+  public File pack() throws Exception {
+    //
+    // Verify configuration and apply defaults
+    //
+    if (instance == null)
+      throw new Exception("No instance specified");
+    if (flatpackFolder == null)
+      flatpackFolder = DEFAULT_FLATPACK_FOLDER;
+    if (inputWidget == null) {
+      //
+      // try to locate the widget upload package from the WidgetInstance
+      //
+      inputWidget = new File(instance.getWidget().getPackagePath());
+    }
+
+    //
+    // If no parser (W3CWidgetFactory) has been specified, create a default
+    // parser
+    //
+    if (parser == null)
+      this.setParser(DEFAULT_PARSER);
+
+    //
+    // Verify the file locations we're using exist
+    //
+    if (!inputWidget.exists())
+      throw new Exception("Input widget file does not exist:"
+          + inputWidget.getPath());
+    if (!flatpackFolder.exists()) {
+      //
+      // Try to create an output folder if none exists
+      //
+      if (!flatpackFolder.mkdir())
+        throw new Exception("Flatpack folder could not be created:"
+            + flatpackFolder.getPath());
+      //
+      // Create an index.html file; this prevents browsing the exported files 
by
+      // sending a GET to the flatpack folder.
+      // This is necessary as servlet containers do not have a consistent
+      // configuration mechanism for denying directory browsing.
+      //
+      new File(flatpackFolder.getPath() + "/index.html").createNewFile();
+    }
+
+    //
+    // Create tmp working area
+    //
+    File workingArea = File.createTempFile("wookie-flatpack", "");
+    if (workingArea.exists())
+      workingArea.delete();
+    workingArea.mkdir();
+
+    //
+    // Set the working area for unpacking the widget
+    //
+    parser.setOutputDirectory(workingArea.getAbsolutePath());
+
+    //
+    // Parse the widget and unpack it into the working area
+    //
+    W3CWidget widget = parser.parse(inputWidget);
+
+    //
+    // Set the W3CWidget's preferences to the current values of the Widget
+    // Instance
+    //
+    widget = setPreferences(widget);
+    
+    //
+    // Add resources for each flattened feature used by the Widget
+    //
+    widget = processFeatures(widget, parser.getUnzippedWidgetDirectory());
+
+    //
+    // Save the config.xml using WidgetOutputter - this marshalls the W3CWidget
+    // object into XML
+    // and writes it to a file
+    //
+    WidgetOutputter outputter = new WidgetOutputter();
+    outputter.setWidgetFolder(DEFAULT_LOCAL_PATH);
+    File configXml = new File(parser.getUnzippedWidgetDirectory(), 
"config.xml");
+    outputter.outputXML(widget, configXml);
+
+    //
+    // Select a filename using a RandomGUID. Its important that flatpack names
+    // are not trivial to guess as currently there are no download 
restrictions.
+    //
+    String name = new RandomGUID().toString() + ".wgt";
+
+    //
+    // Pack up the widget in a Zip
+    //
+    File outputWidget = new File(flatpackFolder, name);
+    WidgetPackageUtils.repackZip(parser.getUnzippedWidgetDirectory(),
+        outputWidget);
+
+    //
+    // Delete the working area
+    //
+    workingArea.delete();
+
+    //
+    // Return the File object for the flatpacked widget
+    //
+    return outputWidget;
+  }
+
+  /**
+   * For each Preference setting in the Widget Instance, either add or update a
+   * Preference for the exported Widget set in the Widget Instance
+   * 
+   * @param widget
+   *          the widget to process
+   * @return the processed widget
+   */
+  private W3CWidget setPreferences(W3CWidget widget) {
+    //
+    // Add each preferences from the instance to the widget
+    //
+    for (IPreference pref : instance.getPreferences()) {
+      PreferenceEntity newPref = (PreferenceEntity) getPreference(
+          pref.getDkey(), widget);
+      newPref.setValue(pref.getDvalue());
+      newPref.setReadOnly(pref.isReadOnly());
+      widget.getPrefences().add(newPref);
+    }
+    return widget;
+  }
+
+  /**
+   * Get the preference entity for the named preference; either use the 
existing
+   * one from the configuration or create a new instance if there was no
+   * existing entity.
+   * 
+   * @param name
+   * @param widget
+   * @return a preference entity for the named preference
+   */
+  private IPreferenceEntity getPreference(String name, W3CWidget widget) {
+    //
+    // Check for an existing PreferenceEntity for the W3CWidget with the given
+    // name, if so,
+    // return it.
+    //
+    for (IPreferenceEntity pref : widget.getPrefences()) {
+      if (pref.getName().equals(name))
+        return pref;
+    }
+    //
+    // Create a new PreferenceEntity and return it
+    //
+    PreferenceEntity pref = new PreferenceEntity();
+    pref.setName(name);
+    return pref;
+  }
+
+  /**
+   * Set the Widget file to flatpack. TODO remove this as the WidgetInstance
+   * should be capable of being used to locate the Widget.
+   * 
+   * @param inputWidget
+   */
+  public void setInputWidget(File inputWidget) {
+    this.inputWidget = inputWidget;
+  }
+
+  /**
+   * Set the folder where flatpacked Widgets should be exported, e.g.
+   * "/flatpack" or "/exports"
+   * 
+   * @param flatpackFolder
+   */
+  public void setFlatpackFolder(File flatpackFolder) {
+    this.flatpackFolder = flatpackFolder;
+  }
+  
+  /**
+   * for each Feature that is flagged as being suitable for "flattening", add
+   * its resources (e.g. JS, CSS) to the exported package and remove the 
&lt;feature&gt; element from
+   * the W3CWidget. Note that we put the complete contents of the feature in 
the exported package -
+   * this should ensure any required README, LICENSE and NOTICE files are 
exported too.
+   * 
+   * @param widget the widget being exported
+   * @param folder the folder to add resources to
+   * @return widget with flattened feature elements removed
+   * @throws IOException
+   */
+  private W3CWidget processFeatures(W3CWidget widget, File folder)
+      throws IOException {
+    ArrayList<IFeatureEntity> featuresToRemove = new 
ArrayList<IFeatureEntity>();
+    for (IFeatureEntity feature : widget.getFeatures()) {
+      for (IFeature theFeature : Features.getFeatures()) {
+        if (theFeature.getName().equals(feature.getName())
+            && theFeature.flattenOnExport()) {
+          //
+          // Copy everything under the feature to the working area
+          //
+          File featureFolder = new File(theFeature.getFolder());
+          FileUtils.copyDirectoryToDirectory(featureFolder, folder);
+          featuresToRemove.add(feature);
+        }
+      }
+    }
+    //
+    // Remove flattened features from the W3CWidget
+    //
+    for (IFeatureEntity feature : featuresToRemove) {
+      widget.getFeatures().remove(feature);
+    }
+    return widget;
+  }
+
+  /**
+   * Sets the W3CWidgetFactory to use as the widget parser Note that we 
override
+   * the startPageProcessor with FlatpackProcessor and rewrite the local path 
to
+   * DEFAULT_LOCAL_PATH.
+   * 
+   * @param factory
+   * @throws IOException
+   */
+  public void setParser(W3CWidgetFactory factory) throws IOException {
+    parser = factory;
+    parser.setStartPageProcessor(new FlatpackProcessor());
+    parser.setLocalPath(DEFAULT_LOCAL_PATH);
+  }
+
+  /*
+   * Construct a standard W3CWidgetFactory parser for testing
+   */
+  private static W3CWidgetFactory createDefaultParser() {
+    W3CWidgetFactory fac = new W3CWidgetFactory();
+    //
+    // Set the local path to the default value
+    //
+    fac.setLocalPath(DEFAULT_LOCAL_PATH);
+    //
+    // Set the features to all locally installed features
+    //
+    fac.setFeatures(Features.getFeatureNames());
+    //
+    // Set UTF-8 encoding
+    //
+    try {
+      fac.setEncodings(new String[] { "UTF-8" });
+    } catch (Exception e) {
+      _logger.error("Problem setting character encoding when creating default 
parser: ", e);
+    }
+
+    return fac;
+  }
 
 }

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackProcessor.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackProcessor.java?rev=1141240&r1=1141239&r2=1141240&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackProcessor.java 
(original)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackProcessor.java 
Wed Jun 29 20:43:25 2011
@@ -30,92 +30,99 @@ import org.apache.wookie.w3c.IStartPageP
 import org.apache.wookie.w3c.W3CWidget;
 
 /**
- * Flatpack Processor
+ * <p>
+ * This class is used to help create a "Flatpack" - a .wgt archive that can 
also
+ * include WidgetInstance information.
+ * </p>
  * 
- * This class is used to help create a "Flatpack" - a .wgt archive that can 
also include WidgetInstance 
- * information.
+ * <p>
+ * This class is invoked by the W3CWidgetFactory class when invoked by
+ * FlatpackFactory to unpack a Widget.
+ * </p>
  * 
- * This class is invoked by the W3CWidgetFactory class when invoked by 
FlatpackFactory to unpack a
- * Widget. The purpose of this processor is to modify the HTML start files in 
the Widget package,
- * injecting scripts only for the features set in the includedFeatures array.
+ * <p>
+ * The purpose of this processor is to modify the Widget package, for Features
+ * that are flagged as being suitable for "flattening", it adds their resources
+ * to the exported package, injects script and stylesheet references in each
+ * start file, and removes the &lt;feature&gt; element from the Widget's
+ * config.xml
+ * </p>
  * 
- * NOTE: At the moment this class doesn't actually do _anything_ as we haven't 
decided how to flatten features
- * 
- * @author [email protected]
- *
  */
-public class FlatpackProcessor  implements     IStartPageProcessor {
+public class FlatpackProcessor implements IStartPageProcessor {
+
+  /**
+   * Constructs a FlatpackProcessor
+   * 
+   * @param instance
+   */
+  public FlatpackProcessor() {
+  }
 
-       /**
-        * Constructs a FlatpackProcessor 
-        * @param instance
-        */
-       public FlatpackProcessor() {
-       }
-
-       /**
-        * Processes the start file.
-        * @param startFile the HTML file to process
-        * @param model the Widget object to apply
-        * @content the Content element to apply
-        * TODO implement
-        */
-       public void processStartFile(File startFile, W3CWidget 
model,IContentEntity content) throws Exception {
-          if (startFile == null) throw new Exception("Start file cannot be 
processed: file is null");
-           if (!startFile.exists()) throw new Exception("Start file cannot be 
processed:  file does not exist");
-           if (!(startFile.canWrite()&&startFile.canRead())) throw new 
Exception("Start file cannot be processed: read or write permissions missing");
-           if (model == null) throw new Exception("Start file cannot be 
processed: widget model is null");
-           IHtmlProcessor engine = new HtmlCleaner();
-           engine.setReader(new FileReader(startFile));
-           addFlattenedFeatures(startFile.getParentFile(), engine, model);
-           FileWriter writer = new FileWriter(startFile);
-           engine.process(writer);
-       }
-       
-        /**
+  /**
+   * Processes the start file.
+   * 
+   * @param startFile the HTML file to process
+   * @param model the Widget object to apply
+   * @content the Content element to apply TODO implement
+   */
+  public void processStartFile(File startFile, W3CWidget model,
+      IContentEntity content) throws Exception {
+    if (startFile == null)
+      throw new Exception("Start file cannot be processed: file is null");
+    if (!startFile.exists())
+      throw new Exception(
+          "Start file cannot be processed:  file does not exist");
+    if (!(startFile.canWrite() && startFile.canRead()))
+      throw new Exception(
+          "Start file cannot be processed: read or write permissions missing");
+    if (model == null)
+      throw new Exception(
+          "Start file cannot be processed: widget model is null");
+    //
+    // Set the HTML processing engine to use to modify the Widget start files
+    // and pass it a reference to a FileReader it can use to read the start 
file
+    //
+    IHtmlProcessor engine = new HtmlCleaner();
+    engine.setReader(new FileReader(startFile));
+    //
+    // Process Features
+    //
+    addFlattenedFeatures(startFile.getParentFile(), engine, model);
+    FileWriter writer = new FileWriter(startFile);
+    engine.process(writer);
+  }
+
+  /**
    * Adds features to widget start file by injecting javascript and stylesheets
    * required by each supported feature in the model.
+   * 
    * @param engine
    * @param model
    * @throws Exception if a feature cannot be found and instantiated for the 
widget.
    */
-  private void addFlattenedFeatures(File widgetFolder, IHtmlProcessor engine, 
W3CWidget model) throws Exception{
-    ArrayList<IFeatureEntity> featuresToRemove = new 
ArrayList<IFeatureEntity>();
-    for (IFeatureEntity feature: model.getFeatures()){
-      for (IFeature theFeature: Features.getFeatures()){
-        if (theFeature.getName().equals(feature.getName()) && 
theFeature.flattenOnExport()){
+  private void addFlattenedFeatures(File widgetFolder, IHtmlProcessor engine,
+      W3CWidget model) throws Exception {
+    for (IFeatureEntity feature : model.getFeatures()) {
+      for (IFeature theFeature : Features.getFeatures()) {
+        if (theFeature.getName().equals(feature.getName())
+            && theFeature.flattenOnExport()) {
           addScripts(engine, theFeature);
-          addStylesheets(engine, theFeature);  
-          addResources(widgetFolder, theFeature);
-          featuresToRemove.add(feature);
+          addStylesheets(engine, theFeature);
         }
       }
     }
-    // Remove flattened features
-    for (IFeatureEntity feature: featuresToRemove){
-      model.getFeatures().remove(feature);
-    }
-  }
-  
-  /**
-   * @param widgetFolder
-   * @param theFeature
-   * @throws IOException 
-   */
-  private void addResources(File widgetFolder, IFeature theFeature) throws 
IOException {
-    // Copy everything under the feature to the widgetfolder
-    File featureFolder = new File(theFeature.getFolder());
-    FileUtils.copyDirectoryToDirectory(featureFolder, widgetFolder);
   }
 
   /**
    * Adds scripts for a given feature
+   * 
    * @param engine
    * @param feature
    */
-  private void addScripts(IHtmlProcessor engine, IFeature feature){
-    if (feature.scripts() != null){
-      for (String script: feature.scripts()){
+  private void addScripts(IHtmlProcessor engine, IFeature feature) {
+    if (feature.scripts() != null) {
+      for (String script : feature.scripts()) {
         // remove the "base" path
         // FIXME this is fragile - consider replacing with a better solution
         script = script.replace("/wookie/features/", "");
@@ -123,15 +130,16 @@ public class FlatpackProcessor  implemen
       }
     }
   }
-  
+
   /**
    * Adds stylesheets for a given feature
+   * 
    * @param engine
    * @param feature
    */
-  private void addStylesheets(IHtmlProcessor engine, IFeature feature){
-    if (feature.stylesheets() != null){
-      for (String style: feature.stylesheets()){
+  private void addStylesheets(IHtmlProcessor engine, IFeature feature) {
+    if (feature.stylesheets() != null) {
+      for (String style : feature.stylesheets()) {
         // remove the "base" path
         // FIXME this is fragile - consider replacing with a better solution
         style = style.replace("/wookie/features/", "");


Reply via email to