Author: scottbw
Date: Wed Nov 25 23:31:16 2009
New Revision: 884338
URL: http://svn.apache.org/viewvc?rev=884338&view=rev
Log:
Implemented a watched folder solution for WOOKIE-51 that allows hot deployment
of widgets by dropping in .wgt files. This also involved separating further the
WidgetPackageUtils methods from the servlet concerns, and pushing more widget
package processing out of the admin servlet.
Added:
incubator/wookie/trunk/WebContent/deploy/
incubator/wookie/trunk/src/org/apache/wookie/util/WgtWatcher.java
Modified:
incubator/wookie/trunk/src/org/apache/wookie/WidgetAdminServlet.java
incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java
incubator/wookie/trunk/src/org/apache/wookie/util/WidgetPackageUtils.java
incubator/wookie/trunk/src/widgetserver.properties
Modified: incubator/wookie/trunk/src/org/apache/wookie/WidgetAdminServlet.java
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/WidgetAdminServlet.java?rev=884338&r1=884337&r2=884338&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/WidgetAdminServlet.java
(original)
+++ incubator/wookie/trunk/src/org/apache/wookie/WidgetAdminServlet.java Wed
Nov 25 23:31:16 2009
@@ -27,7 +27,6 @@
import javax.servlet.http.HttpSession;
import org.apache.commons.configuration.Configuration;
-import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.log4j.Logger;
import org.apache.wookie.beans.ApiKey;
import org.apache.wookie.beans.Whitelist;
@@ -42,13 +41,9 @@
import org.apache.wookie.manager.IWidgetAdminManager;
import org.apache.wookie.manager.impl.WidgetAdminManager;
import org.apache.wookie.manifestmodel.IManifestModel;
-import org.apache.wookie.manifestmodel.impl.ContentEntity;
-import org.apache.wookie.manifestmodel.impl.WidgetManifestModel;
import org.apache.wookie.server.LocaleHandler;
-import org.apache.wookie.util.StartPageJSParser;
import org.apache.wookie.util.WidgetPackageUtils;
import org.apache.wookie.util.gadgets.GadgetUtils;
-import org.jdom.JDOMException;
/**
* Servlet implementation class for Servlet: WidgetAdminServlet
@@ -361,11 +356,12 @@
}
private void removeWidget(HttpSession session, HttpServletRequest
request, Configuration properties, IWidgetAdminManager manager) {
+ final String WIDGETFOLDER =
request.getSession().getServletContext().getRealPath(properties.getString("widget.widgetfolder"));//$NON-NLS-1$
Messages localizedMessages =
LocaleHandler.localizeMessages(request);
String widgetId = request.getParameter("widgetId");
//$NON-NLS-1$
String guid = manager.getWidgetGuid(Integer.parseInt(widgetId));
if(manager.removeWidgetAndReferences(Integer.parseInt(widgetId))){
- if(WidgetPackageUtils.removeWidgetResources(request,
properties, guid)){
+
if(WidgetPackageUtils.removeWidgetResources(WIDGETFOLDER, guid)){
session.setAttribute("message_value",
localizedMessages.getString("WidgetAdminServlet.12"));
//$NON-NLS-1$ //$NON-NLS-2$
}
else{
@@ -449,12 +445,16 @@
}
private void uploadOperation(HttpServletRequest request, Configuration
properties, IWidgetAdminManager manager, HttpSession session) {
+
+ final String WIDGETFOLDER =
request.getSession().getServletContext().getRealPath(properties.getString("widget.widgetfolder"));//$NON-NLS-1$
+ final String UPLOADFOLDER =
request.getSession().getServletContext().getRealPath(properties.getString("widget.useruploadfolder"));//$NON-NLS-1$
+
Messages localizedMessages =
LocaleHandler.localizeMessages(request);
session.setAttribute("hasValidated", Boolean.valueOf(false));
//$NON-NLS-1$
session.setAttribute("closeWindow", Boolean.valueOf(true));
//$NON-NLS-1$
File zipFile;
try {
- zipFile =
WidgetPackageUtils.dealWithUploadFile(request, properties);
+ zipFile =
WidgetPackageUtils.dealWithUploadFile(UPLOADFOLDER, request);
}
catch (Exception ex) {
session.setAttribute("error_value",
localizedMessages.getString("WidgetAdminServlet.28") + "\n" + ex.getMessage());
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -463,69 +463,30 @@
try {
if(zipFile.exists()){
- ZipFile zip = new ZipFile(zipFile);
- if (WidgetPackageUtils.hasManifest(zip)){
- // build the model
- IManifestModel widgetModel = new
WidgetManifestModel(WidgetPackageUtils.extractManifest(zip), zip);
-
- // get the start file; if there is no
valid start file an exception will be thrown
- String src =
WidgetPackageUtils.locateStartFile(widgetModel, zip);
- // get the widget identifier
- String manifestIdentifier =
widgetModel.getIdentifier();
- // create the folder structure to unzip
the zip into
- File newWidgetFolder =
WidgetPackageUtils.createUnpackedWidgetFolder(request, properties,
manifestIdentifier);
- // now unzip it into that folder
- WidgetPackageUtils.unpackZip(zip,
newWidgetFolder);
- // get the url to the start page
- String relativestartUrl =
(WidgetPackageUtils.getURLForWidget(properties, manifestIdentifier, src));
- // update the model version of the
start page (or create one if none exists)
- if (widgetModel.getContent() == null)
widgetModel.setContent(new ContentEntity());
-
widgetModel.getContent().setSrc(relativestartUrl);
- // now update the js links in the start
page
- File startFile = new
File(newWidgetFolder.getCanonicalPath() + File.separator + src);
- if(startFile.exists()){
- StartPageJSParser parser = new
StartPageJSParser(startFile, widgetModel);
- parser.doParse();
- }
- // get the path to the root of the
unzipped folder
- String localPath =
WidgetPackageUtils.getURLForWidget(properties, manifestIdentifier, "");
- // now pass this to the model which
will prepend the path to local resources (not web icons)
- widgetModel.updateIconPaths(localPath);
- // check to see if this widget already
exists in the DB - using the ID (guid) key from the manifest
-
if(!manager.doesWidgetAlreadyExistInSystem(manifestIdentifier)){
- int dbkey =
manager.addNewWidget(widgetModel, new String[]{});
- // widget added
-
session.setAttribute("message_value", "'"+ widgetModel.getLocalName("en") +"' -
" + localizedMessages.getString("WidgetAdminServlet.19")); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- retrieveServices(session,
manager);
-
session.setAttribute("hasValidated", Boolean.valueOf(true));
//$NON-NLS-1$
- session.setAttribute("dbkey",
dbkey); //$NON-NLS-1$
- boolean isMaxable =
manager.isWidgetMaximized(dbkey);
-
session.setAttribute("isMaxable", Boolean.valueOf(isMaxable)); //$NON-NLS-1$
- }
- else{
- // TODO - call the manager to
update required resources
- // widget updated
-
session.setAttribute("message_value", "'"+ widgetModel.getLocalName("en") +"' -
" + localizedMessages.getString("WidgetAdminServlet.20")); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- }
- }
+ IManifestModel widgetModel =
WidgetPackageUtils.processWidgetPackage(zipFile,properties.getString("widget.widgetfolder"),
WIDGETFOLDER,UPLOADFOLDER);//$NON-NLS-1$
+
if(!manager.doesWidgetAlreadyExistInSystem(widgetModel.getIdentifier())){
+ // ADD
+ int dbkey =
manager.addNewWidget(widgetModel, new String[]{});
+ // widget added
+ session.setAttribute("message_value",
"'"+ widgetModel.getLocalName("en") +"' - " +
localizedMessages.getString("WidgetAdminServlet.19")); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ retrieveServices(session, manager);
+ session.setAttribute("hasValidated",
Boolean.valueOf(true));
//$NON-NLS-1$
+ session.setAttribute("dbkey", dbkey);
//$NON-NLS-1$
+ boolean isMaxable =
manager.isWidgetMaximized(dbkey);
+ session.setAttribute("isMaxable",
Boolean.valueOf(isMaxable)); //$NON-NLS-1$
+ }
else{
- // no manifest file found in zip archive
- throw new
BadWidgetZipFileException(localizedMessages.getString("WidgetAdminServlet.23"));
//$NON-NLS-1$
- }
+ // UPDATE
+ // TODO - call the manager to update
required resources
+ // widget updated
+ session.setAttribute("message_value",
"'"+ widgetModel.getLocalName("en") +"' - " +
localizedMessages.getString("WidgetAdminServlet.20")); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
}
else{
// no file found to be uploaded - shouldn't
happen
session.setAttribute("error_value",
localizedMessages.getString("WidgetAdminServlet.24")); //$NON-NLS-1$
//$NON-NLS-2$
}
}
- catch (JDOMException ex) {
- _logger.error(ex);
- session.setAttribute("error_value",
localizedMessages.getString("WidgetAdminServlet.25") + "\n" + ex.getMessage());
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- catch (IOException ex) {
- _logger.error(ex);
- session.setAttribute("error_value",
localizedMessages.getString("WidgetAdminServlet.25") + "\n" + ex.getMessage());
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
catch (InvalidStartFileException ex){
_logger.error(ex);
session.setAttribute("error_value",
localizedMessages.getString("WidgetAdminServlet.27") + "\n" + ex.getMessage());
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -543,6 +504,10 @@
if (ex.getMessage() == null ||
ex.getMessage().equals("")) message =
localizedMessages.getString("WidgetAdminServlet.29"); //$NON-NLS-1$
session.setAttribute("error_value", message);
//$NON-NLS-1$
}
+ catch (Exception ex) {
+ _logger.error(ex);
+ session.setAttribute("error_value",
localizedMessages.getString("WidgetAdminServlet.25") + "\n" + ex.getMessage());
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
}
Modified:
incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java?rev=884338&r1=884337&r2=884338&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java
(original)
+++ incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java
Wed Nov 25 23:31:16 2009
@@ -15,14 +15,23 @@
package org.apache.wookie.server;
+import java.io.File;
+
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.log4j.Logger;
+import org.apache.wookie.manager.impl.WidgetAdminManager;
+import org.apache.wookie.manifestmodel.IManifestModel;
+import org.apache.wookie.util.WgtWatcher;
+import org.apache.wookie.util.WidgetPackageUtils;
+import org.apache.wookie.util.hibernate.DBManagerFactory;
import org.apache.wookie.util.hibernate.HibernateUtil;
+import org.apache.wookie.util.hibernate.IDBManager;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
+
/**
* ContextListener - does some init work and makes certain things are
available
* to resources under this context
@@ -50,23 +59,106 @@
* load the widgetserver.properties file and put it
into this context
* as an attribute 'properties' available to all
resources
*/
- Configuration configuration = new
PropertiesConfiguration("widgetserver.properties");
+ PropertiesConfiguration configuration;
+ File localPropsFile = new
File(System.getProperty("user.dir") + File.separator +
"local.widgetserver.properties");
+ if (localPropsFile.exists()) {
+ configuration = new
PropertiesConfiguration(localPropsFile);
+ _logger.info("Using local widget server
properties file: " + localPropsFile.toString());
+ } else {
+ configuration = new
PropertiesConfiguration("widgetserver.properties");
+ configuration.setFile(localPropsFile);
+ configuration.save();
+ _logger.info("Using default widget server
properties, configure your local server using: " + localPropsFile.toString());
+ }
context.setAttribute("properties", (Configuration)
configuration);
- /*
- * load the opensocial.properties file and put it into
this context
- * as an attribute 'opensocial' available to all
resources
- */
- Configuration opensocialConfiguration = new
PropertiesConfiguration("opensocial.properties");
- context.setAttribute("opensocial", (Configuration)
opensocialConfiguration);
/*
* Initialise the locale handler
*/
LocaleHandler.getInstance().initialize(configuration);
+
+ if (configuration.getBoolean("widget.hot_deploy"))
startWatcher(context, configuration);
+
+ /*
+ * load the opensocial.properties file and put it into
this context
+ * as an attribute 'opensocial' available to all
resources
+ */
+ PropertiesConfiguration opensocialConfiguration;
+ File localOpenSocialPropsFile = new
File(System.getProperty("user.dir") + File.separator +
"local.opensocial.properties");
+ if (localOpenSocialPropsFile.exists()) {
+ opensocialConfiguration = new
PropertiesConfiguration(localOpenSocialPropsFile);
+ _logger.info("Using local open social
properties file: " + localOpenSocialPropsFile.toString());
+ } else {
+ opensocialConfiguration = new
PropertiesConfiguration("opensocial.properties");
+
opensocialConfiguration.setFile(localOpenSocialPropsFile);
+ opensocialConfiguration.save();
+ _logger.info("Using default open social
properties, configure your local server using: " +
localOpenSocialPropsFile.toString());
+ }
+ context.setAttribute("opensocial", (Configuration)
opensocialConfiguration);
}
catch (ConfigurationException ex) {
_logger.error("ConfigurationException thrown: "+
ex.toString());
}
}
+
+ /**
+ * Starts a watcher thread for hot-deploy of new widgets dropped into
the deploy folder
+ * this is controlled using the
<code>widget.hot_deploy=true|false</code> property
+ * and configured to look in the folder specified by the
<code>widget.deployfolder</code> property
+ * @param context the current servlet context
+ * @param configuration the configuration properties
+ */
+ private void startWatcher(ServletContext context, Configuration
configuration){
+ /*
+ * Start watching for widget deployment
+ */
+ final File deploy = new
File(WidgetPackageUtils.convertPathToPlatform(context.getRealPath(configuration.getString("widget.deployfolder"))));
+ final String UPLOADFOLDER =
context.getRealPath(configuration.getString("widget.useruploadfolder"));
+ final String WIDGETFOLDER =
context.getRealPath(configuration.getString("widget.widgetfolder"));
+ final String localWidgetFolderPath =
configuration.getString("widget.widgetfolder");
+ Thread thr = new Thread(){
+ public void run() {
+ /** Get a DBManager for this thread. */
+ final IDBManager dbManager =
DBManagerFactory.getDBManager();
+ int interval = 5000;
+ WgtWatcher watcher = new WgtWatcher();
+ watcher.setWatchDir(deploy);
+ watcher.setListener(new
WgtWatcher.FileChangeListener(){
+ public void fileModified(File f) {
+ _logger.info("Deploying
widget:"+f.getName());
+ try {
+ try {
+
dbManager.beginTransaction();
+ File upload =
WidgetPackageUtils.dealWithDroppedFile(UPLOADFOLDER, f);
+ IManifestModel
model = WidgetPackageUtils.processWidgetPackage(upload, localWidgetFolderPath,
WIDGETFOLDER, UPLOADFOLDER);
+
WidgetAdminManager manager = new WidgetAdminManager(null);
+
manager.addNewWidget(model, null);
+
dbManager.commitTransaction();
+ }
+ catch (Exception e) {
+
_logger.error("error: " + e.getCause());
+ }
+ } catch (Exception e) {
+ _logger.error("error:
"+e.getCause());
+ }
+ }
+ public void fileRemoved(File f) {
+ // Not implemented - the .wgt
files are removed as part of the deployment process
+ }
+ });
+ try {
+ while (true) {
+ watcher.check();
+ Thread.sleep(interval);
+ }
+ } catch (InterruptedException iex) {
+ dbManager.closeSession();
+ }
+ }
+ };
+
+ thr.start();
+
+ }
public void contextDestroyed(ServletContextEvent event){
HibernateUtil.getSessionFactory().close(); // Free all resources
Added: incubator/wookie/trunk/src/org/apache/wookie/util/WgtWatcher.java
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/util/WgtWatcher.java?rev=884338&view=auto
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/util/WgtWatcher.java (added)
+++ incubator/wookie/trunk/src/org/apache/wookie/util/WgtWatcher.java Wed Nov
25 23:31:16 2009
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.wookie.util;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.log4j.Logger;
+
+/**
+ * <p>
+ * The <b>WgtWatcher </b> watches the deployDir for changes made to the
+ * directory (adding new WGT files->deploy) And
+ * notifies a listener of the changes made
+ * </p>
+ * <p>
+ * Based on org.apache.catalina.cluster.deploy.WarWatcher
+ * </p>
+ * @author Scott Wilson
+ * @author Filip Hanik
+ * @author Peter Rossbach
+ * @version 1.1
+ */
+
+public class WgtWatcher {
+
+ /*--Static Variables----------------------------------------*/
+ static Logger log = Logger.getLogger(WgtWatcher.class.getName());
+
+ /*--Instance Variables--------------------------------------*/
+ /**
+ * Directory to watch for war files
+ */
+ protected File watchDir = null;
+
+ /**
+ * Parent to be notified of changes
+ */
+ protected FileChangeListener listener = null;
+
+ /**
+ * Currently deployed files
+ */
+ protected Map currentStatus = new ConcurrentHashMap();
+
+ /*--Constructor---------------------------------------------*/
+
+ public WgtWatcher() {
+ }
+
+ public WgtWatcher(FileChangeListener listener, File watchDir) {
+ this.listener = listener;
+ this.watchDir = watchDir;
+ }
+
+ /*--Logic---------------------------------------------------*/
+
+ /**
+ * check for modification and send notifcation to listener
+ */
+ public void check() {
+ if (log.isInfoEnabled())
+ log.debug("check for new widgets at " + watchDir);
+ File[] list = watchDir.listFiles(new WgtFilter());
+ if (list == null)
+ list = new File[0];
+ //first make sure all the files are listed in our current status
+ for (int i = 0; i < list.length; i++) {
+ addWarInfo(list[i]);
+ }
+
+ //check all the status codes and update the FarmDeployer
+ for (Iterator i = currentStatus.entrySet().iterator(); i.hasNext();) {
+ Map.Entry entry = (Map.Entry) i.next();
+ WarInfo info = (WarInfo) entry.getValue();
+ int check = info.check();
+ if (check == 1) {
+ listener.fileModified(info.getWar());
+ } else if (check == -1) {
+ listener.fileRemoved(info.getWar());
+ //no need to keep in memory
+ currentStatus.remove(info.getWar().getAbsolutePath());
+ }
+ }
+
+ }
+
+ /**
+ * add cluster war to the watcher state
+ * @param warfile
+ */
+ protected void addWarInfo(File warfile) {
+ WarInfo info = (WarInfo) currentStatus.get(warfile.getAbsolutePath());
+ if (info == null) {
+ info = new WarInfo(warfile);
+ info.setLastState(-1); //assume file is non existent
+ currentStatus.put(warfile.getAbsolutePath(), info);
+ }
+ }
+
+ /**
+ * clear watcher state
+ */
+ public void clear() {
+ currentStatus.clear();
+ }
+
+ /**
+ * @return Returns the watchDir.
+ */
+ public File getWatchDir() {
+ return watchDir;
+ }
+
+ /**
+ * @param watchDir
+ * The watchDir to set.
+ */
+ public void setWatchDir(File watchDir) {
+ this.watchDir = watchDir;
+ }
+
+ /**
+ * @return Returns the listener.
+ */
+ public FileChangeListener getListener() {
+ return listener;
+ }
+
+ /**
+ * @param listener
+ * The listener to set.
+ */
+ public void setListener(FileChangeListener listener) {
+ this.listener = listener;
+ }
+
+ /*--Inner classes-------------------------------------------*/
+
+ /**
+ * File name filter for wgt files
+ */
+ protected class WgtFilter implements java.io.FilenameFilter {
+ public boolean accept(File path, String name) {
+ if (name == null)
+ return false;
+ return name.endsWith(".wgt");
+ }
+ }
+
+ /**
+ * File information on existing WAR files
+ */
+ protected class WarInfo {
+ protected File war = null;
+
+ protected long lastChecked = 0;
+
+ protected long lastState = 0;
+
+ public WarInfo(File war) {
+ this.war = war;
+ this.lastChecked = war.lastModified();
+ if (!war.exists())
+ lastState = -1;
+ }
+
+ public boolean modified() {
+ return war.exists() && war.lastModified() > lastChecked;
+ }
+
+ public boolean exists() {
+ return war.exists();
+ }
+
+ /**
+ * Returns 1 if the file has been added/modified, 0 if the file is
+ * unchanged and -1 if the file has been removed
+ *
+ * @return int 1=file added; 0=unchanged; -1=file removed
+ */
+ public int check() {
+ //file unchanged by default
+ int result = 0;
+
+ if (modified()) {
+ //file has changed - timestamp
+ result = 1;
+ lastState = result;
+ } else if ((!exists()) && (!(lastState == -1))) {
+ //file was removed
+ result = -1;
+ lastState = result;
+ } else if ((lastState == -1) && exists()) {
+ //file was added
+ result = 1;
+ lastState = result;
+ }
+ this.lastChecked = System.currentTimeMillis();
+ return result;
+ }
+
+ public File getWar() {
+ return war;
+ }
+
+ public int hashCode() {
+ return war.getAbsolutePath().hashCode();
+ }
+
+ public boolean equals(Object other) {
+ if (other instanceof WarInfo) {
+ WarInfo wo = (WarInfo) other;
+ return wo.getWar().equals(getWar());
+ } else {
+ return false;
+ }
+ }
+
+ protected void setLastState(int lastState) {
+ this.lastState = lastState;
+ }
+
+ }
+ public interface FileChangeListener {
+ public void fileModified(File f);
+ public void fileRemoved(File f);
+ }
+
+}
\ No newline at end of file
Modified:
incubator/wookie/trunk/src/org/apache/wookie/util/WidgetPackageUtils.java
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/util/WidgetPackageUtils.java?rev=884338&r1=884337&r2=884338&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/util/WidgetPackageUtils.java
(original)
+++ incubator/wookie/trunk/src/org/apache/wookie/util/WidgetPackageUtils.java
Wed Nov 25 23:31:16 2009
@@ -23,12 +23,10 @@
import java.util.Iterator;
import java.util.List;
-import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
-import org.apache.commons.configuration.Configuration;
import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
@@ -40,6 +38,8 @@
import org.apache.wookie.exceptions.InvalidStartFileException;
import org.apache.wookie.manifestmodel.IManifestModel;
import org.apache.wookie.manifestmodel.IW3CXMLConfiguration;
+import org.apache.wookie.manifestmodel.impl.ContentEntity;
+import org.apache.wookie.manifestmodel.impl.WidgetManifestModel;
/**
* Utilities for working with Widget packages, i.e. Zip Files with an XML
manifest
@@ -78,22 +78,20 @@
throw new InvalidStartFileException(); //$NON-NLS-1$
return startFile;
}
-
- public static File createUnpackedWidgetFolder(HttpServletRequest
request, Configuration properties, String folder) throws IOException{
+
+ public static File createUnpackedWidgetFolder(String widgetFolder,
String folder) throws IOException{
folder = convertIdToFolderName(folder);
- String uploadPath =
properties.getString("widget.widgetfolder"); //$NON-NLS-1$
- ServletContext context =
request.getSession().getServletContext();
- String serverPath = context.getRealPath(uploadPath +
File.separator + folder) ;
+ String serverPath = widgetFolder + File.separator + folder;
File file = new File(convertPathToPlatform(serverPath));
return file;
}
- public static String getURLForWidget(Configuration properties, String
folder, String file){
+ public static String getURLForWidget(String widgetFolder, String
folder, String file){
folder = convertIdToFolderName(folder);
- String path = convertPathToRelativeUri("/wookie" +
properties.getString("widget.widgetfolder") + File.separator + folder +
File.separator + file); //$NON-NLS-1$ //$NON-NLS-2$
+ String path = convertPathToRelativeUri("/wookie" + widgetFolder
+ File.separator + folder + File.separator + file); //$NON-NLS-1$ //$NON-NLS-2$
return path;
}
-
+
public static String convertIdToFolderName(String folder){
if(folder.startsWith("http://")){ //$NON-NLS-1$
folder = folder.substring(7, folder.length());
@@ -101,12 +99,18 @@
folder.replaceAll(" ", ""); //$NON-NLS-1$ //$NON-NLS-2$
return folder;
}
+
+ public static File dealWithDroppedFile(String uploadPath, File file)
throws Exception{
+ String serverPath = convertPathToPlatform(uploadPath);
+ File uFile = new File(serverPath + File.separator +
file.getName());
+ FileUtils.copyFile(file, uFile);
+ file.delete();
+ return uFile;
+ }
- public static File dealWithUploadFile(HttpServletRequest request,
Configuration properties) throws Exception {
+ public static File dealWithUploadFile(String uploadPath,
HttpServletRequest request) throws Exception {
File uFile = null;
- String uploadPath =
properties.getString("widget.useruploadfolder"); //$NON-NLS-1$
- ServletContext context =
request.getSession().getServletContext();
- String serverPath =
convertPathToPlatform(context.getRealPath(uploadPath));
+ String serverPath = convertPathToPlatform(uploadPath);
_logger.debug(serverPath);
String archiveFileName = null;
if (FileUploadBase.isMultipartContent(request)) {
@@ -152,11 +156,9 @@
return result;
}
- public static boolean removeWidgetResources(HttpServletRequest request,
Configuration properties, String folder){
- folder = convertIdToFolderName(folder);
- String uploadPath =
properties.getString("widget.widgetfolder"); //$NON-NLS-1$
- ServletContext context =
request.getSession().getServletContext();
- String serverPath = context.getRealPath(uploadPath +
File.separator + folder) ;
+ public static boolean removeWidgetResources(String WIDGETFOLDER, String
widgetGuid){
+ String folder = convertIdToFolderName(widgetGuid);
+ String serverPath = WIDGETFOLDER + File.separator + folder;
File pFolder = new File(convertPathToPlatform(serverPath));
try {
_logger.debug("Deleting
folder:"+pFolder.getCanonicalFile().toString()); //$NON-NLS-1$
@@ -169,6 +171,56 @@
return true;
}
+ public static IManifestModel processWidgetPackage(File zipFile, String
localWidgetPath, String WIDGETFOLDER, String UPLOADFOLDER) throws
BadWidgetZipFileException, BadManifestException{
+ ZipFile zip;
+ try {
+ zip = new ZipFile(zipFile);
+ } catch (IOException e) {
+ throw new BadWidgetZipFileException();
+ }
+ if (WidgetPackageUtils.hasManifest(zip)){
+ try {
+ // build the model
+ IManifestModel widgetModel = new
WidgetManifestModel(WidgetPackageUtils.extractManifest(zip), zip);
+ // get the start file; if there is no valid
start file an exception will be thrown
+ String src =
WidgetPackageUtils.locateStartFile(widgetModel, zip);
+ // get the widget identifier
+ String manifestIdentifier =
widgetModel.getIdentifier();
+ // create the folder structure to unzip the zip
into
+ File newWidgetFolder =
WidgetPackageUtils.createUnpackedWidgetFolder(WIDGETFOLDER, manifestIdentifier);
+ // now unzip it into that folder
+ WidgetPackageUtils.unpackZip(zip,
newWidgetFolder);
+ // get the url to the start page
+ String relativestartUrl =
(WidgetPackageUtils.getURLForWidget(localWidgetPath, manifestIdentifier, src));
+ // update the model version of the start page
(or create one if none exists)
+ if (widgetModel.getContent() == null)
widgetModel.setContent(new ContentEntity());
+
widgetModel.getContent().setSrc(relativestartUrl);
+ // now update the js links in the start page
+ File startFile = new
File(newWidgetFolder.getCanonicalPath() + File.separator + src);
+ if(startFile.exists()){
+ StartPageJSParser parser = new
StartPageJSParser(startFile, widgetModel);
+ parser.doParse();
+ }
+ // get the path to the root of the unzipped
folder
+ String localPath =
WidgetPackageUtils.getURLForWidget(localWidgetPath, manifestIdentifier, "");
+ // now pass this to the model which will
prepend the path to local resources (not web icons)
+ widgetModel.updateIconPaths(localPath);
+ // check to see if this widget already exists
in the DB - using the ID (guid) key from the manifest
+ return widgetModel;
+ } catch (InvalidStartFileException e) {
+ throw e;
+ } catch (BadManifestException e) {
+ throw e;
+ } catch (Exception e){
+ throw new BadManifestException();
+ }
+ }
+ else{
+ // no manifest file found in zip archive
+ throw new BadWidgetZipFileException(); //$NON-NLS-1$
+ }
+ }
+
/**
* Checks for the existence of the Manifest.
* TODO not sure if this properly handles case-sensitive entries?
@@ -191,7 +243,7 @@
}
/**
- * uses apache commons compress to unpack all the zipe entries into a
target folder
+ * uses apache commons compress to unpack all the zip entries into a
target folder
* partly adapted from the examples on the apache commons compress
site, and an
* example of generic Zip unpacking. Note this iterates over the
ZipArchiveEntry enumeration rather
* than use the more typical ZipInputStream parsing model, as according
to the doco it will
Modified: incubator/wookie/trunk/src/widgetserver.properties
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/widgetserver.properties?rev=884338&r1=884337&r2=884338&view=diff
==============================================================================
--- incubator/wookie/trunk/src/widgetserver.properties (original)
+++ incubator/wookie/trunk/src/widgetserver.properties Wed Nov 25 23:31:16 2009
@@ -14,6 +14,11 @@
widget.useruploadfolder=/upload
widget.widgetfolder=/wservices
#######################################################################
+# Set hot_deploy to true, and .wgt files dropped into widget.deployfolder
+# will automatically be added to the server
+widget.deployfolder=/deploy
+widget.hot_deploy=false
+#######################################################################
# Location of Shindig services
widget.shindig.url=/wookie
widget.metadata.url=/wookie/gadgets/metadata