Author: scottbw
Date: Fri Feb 24 13:32:55 2012
New Revision: 1293247
URL: http://svn.apache.org/viewvc?rev=1293247&view=rev
Log:
Modified the POST /widgets implementation so that widget packages are processed
synchronously and return appropriate HTTP status codes and additional error
information in the response body. This means that the REST API now has parity
with the to-be-removed admin web interface. I also changed the test helpers to
use this API rather than the admin web interface. See WOOKIE-318
Modified:
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/helpers/WidgetUploader.java
incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java
incubator/wookie/trunk/src/org/apache/wookie/messages.properties
incubator/wookie/trunk/src/org/apache/wookie/messages_nl.properties
Modified:
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/helpers/WidgetUploader.java
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src-tests/org/apache/wookie/tests/helpers/WidgetUploader.java?rev=1293247&r1=1293246&r2=1293247&view=diff
==============================================================================
---
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/helpers/WidgetUploader.java
(original)
+++
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/helpers/WidgetUploader.java
Fri Feb 24 13:32:55 2012
@@ -32,20 +32,16 @@ import org.apache.commons.httpclient.met
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
-import org.htmlcleaner.HtmlCleaner;
-import org.htmlcleaner.TagNode;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
/**
* Helper class for uploading widgets and gathering any errors generated
- * @author scott
- *
*/
public class WidgetUploader {
- public static final String SERVICE_URL =
"http://localhost:8080/wookie/admin/WidgetAdminServlet?operation=UPLOADWIDGET";
+ public static final String SERVICE_URL =
"http://localhost:8080/wookie/widgets";
/**
* Upload a widget from a file at a given URL
@@ -82,24 +78,9 @@ public class WidgetUploader {
Part[] parts = { new FilePart(file.getName(), file) };
post.setRequestEntity(new MultipartRequestEntity(parts, post
.getParams()));
- int status = httpclient.executeMethod(post);
- if (status != 200 && status != 201){
- fail("problem with upload");
- }
String response =
IOUtils.toString(post.getResponseBodyAsStream());
post.releaseConnection();
- return getError(response);
- }
-
- private static String getError(String response) throws IOException{
- String error = null;
- HtmlCleaner cleaner = new HtmlCleaner();
- TagNode html = cleaner.clean(response);
- TagNode errortag = html.findElementByAttValue("id", "error",
true, true);
- if (errortag != null){
- error = errortag.getAttributeByName("title");
- }
- return error;
+ return response;
}
/**
Modified:
incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java?rev=1293247&r1=1293246&r2=1293247&view=diff
==============================================================================
---
incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java
(original)
+++
incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java
Fri Feb 24 13:32:55 2012
@@ -16,18 +16,13 @@ package org.apache.wookie.controller;
import java.io.File;
import java.io.IOException;
-import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.configuration.Configuration;
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileItemFactory;
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.wookie.Messages;
import org.apache.wookie.beans.IWidget;
import org.apache.wookie.beans.util.IPersistenceManager;
import org.apache.wookie.beans.util.PersistenceManagerFactory;
@@ -35,10 +30,20 @@ import org.apache.wookie.exceptions.Inva
import org.apache.wookie.exceptions.ResourceDuplicationException;
import org.apache.wookie.exceptions.ResourceNotFoundException;
import org.apache.wookie.exceptions.UnauthorizedAccessException;
+import org.apache.wookie.feature.Features;
import org.apache.wookie.helpers.WidgetFactory;
import org.apache.wookie.helpers.WidgetHelper;
+import org.apache.wookie.server.LocaleHandler;
+import org.apache.wookie.util.WidgetFileUtils;
+import org.apache.wookie.util.WidgetJavascriptSyntaxAnalyzer;
import org.apache.wookie.util.gadgets.GadgetUtils;
+import org.apache.wookie.util.html.StartPageProcessor;
import org.apache.wookie.w3c.W3CWidget;
+import org.apache.wookie.w3c.W3CWidgetFactory;
+import org.apache.wookie.w3c.exceptions.BadManifestException;
+import org.apache.wookie.w3c.exceptions.BadWidgetZipFileException;
+import org.apache.wookie.w3c.exceptions.InvalidContentTypeException;
+import org.apache.wookie.w3c.exceptions.InvalidStartFileException;
/**
* <p>Controller for widget resources.</p>
@@ -122,86 +127,118 @@ public class WidgetsController extends C
}
/**
- * Install a new Widget by saving it in the deploy folder
+ * Install a new Widget by uploading and installing it
* Note: a Widget must have a .wgt extension!
- * FIXME: Support POSTing references to OpenSocial gadgets, remote
widget files
*/
- @Override
- protected boolean create(String resourceId, HttpServletRequest request)
- throws ResourceDuplicationException, InvalidParametersException,
- UnauthorizedAccessException {
-
- //
- // Check for a "url" parameter in the request, indicating this is a
remote widget or opensocial gadget xml file
- // FIXME implement this
- //
- String url = request.getParameter("url");
- if (url != null && url.trim().length() != 0){
- return createGadget(request, url);
- }
-
- //
- // Get the path for the deploy folder
- //
- Configuration properties = (Configuration)
request.getSession().getServletContext().getAttribute("properties");
//$NON-NLS-1$
- final String DEPLOY_FOLDER =
getServletContext().getRealPath(properties.getString("widget.deployfolder"));//$NON-NLS-1$
-
- //
- // Create factory for processing POSTed files
- //
- FileItemFactory factory = new DiskFileItemFactory();
-
- //
- // Create a new file upload handler
- //
- ServletFileUpload upload = new ServletFileUpload(factory);
-
- //
- // Create a flag we'll use to check if we got any .wgt files in the
POST
- //
- boolean requestContainedWgtFile = false;
-
- //
- // Save file in the deploy folder
- //
- try {
- @SuppressWarnings("unchecked")
- List <FileItem> items = upload.parseRequest(request);
-
- //
- // Only save .wgt files and ignore any others in the POST
- //
- for (FileItem item: items){
- if (item.getName()!=null && item.getName().endsWith(".wgt")){
- File saveFile = new File(DEPLOY_FOLDER + "/" + item.getName());
- item.write(saveFile);
- requestContainedWgtFile = true;
- }
- }
-
- } catch (FileUploadException e) {
- throw new InvalidParametersException();
- } catch (Exception e) {
- //
- // Catch any other exceptions thrown by the save file operation
- // and throw a basic 400 response to the client, though really
- // this is more like a 500. At least we can log the details.
- //
- _logger.error(e.getMessage(), e);
- throw new InvalidParametersException();
- }
+ /* (non-Javadoc)
+ * @see org.apache.wookie.controller.Controller#create(java.lang.String,
javax.servlet.http.HttpServletRequest)
+ */
+ @Override
+ protected boolean create(String resourceId, HttpServletRequest request)
+ throws ResourceDuplicationException, InvalidParametersException,
+ UnauthorizedAccessException {
+
+ //
+ // Check for a "url" parameter in the request, indicating this is a remote
widget or opensocial gadget xml file
+ //
+ String url = request.getParameter("url");
+ if (url != null && url.trim().length() != 0){
+ return createGadget(request, url);
+ }
+
+ //
+ // Get the path to the upload folder, and the widget install folder
+ //
+ Configuration properties = (Configuration)
getServletContext().getAttribute("properties"); //$NON-NLS-1$
+ final String WIDGETFOLDER =
getServletContext().getRealPath(properties.getString("widget.widgetfolder"));//$NON-NLS-1$
+ final String UPLOADFOLDER =
getServletContext().getRealPath(properties.getString("widget.useruploadfolder"));//$NON-NLS-1$
+
+ //
+ // Get localized messages so we can return errors
+ //
+ Messages localizedMessages = LocaleHandler.localizeMessages(request);
+
+ //
+ // Try to obtain a zipfile from the request.
+ //
+ File zipFile;
+ try {
+ zipFile = WidgetFileUtils.upload(UPLOADFOLDER, request);
+ } catch (Exception ex) {
+ throw new
InvalidParametersException(localizedMessages.getString("widgets.invalid-config-xml")
+ "\n" + ex.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ //
+ // No file uploaded
+ //
+ if(zipFile == null || !zipFile.exists()){
+ throw new
InvalidParametersException(localizedMessages.getString("widgets.no-widget-file-uploaded"));
//$NON-NLS-1$
+ }
+
+ try {
- //
- // If there are no .wgt files in the POST, throw an exception
- // We have to check for this here as other exceptions are caught in
- // the code above, e.g. generic file system errors
- //
- if (requestContainedWgtFile == false){
- throw new InvalidParametersException();
- }
+ //
+ // Parse and validate the zip as a widget
+ //
+ final String[] locales = properties.getStringArray("widget.locales");
+ W3CWidgetFactory fac = new W3CWidgetFactory();
+ fac.setLocales(locales);
+ fac.setLocalPath(getServletContext().getContextPath() +
properties.getString("widget.widgetfolder"));
+ fac.setOutputDirectory(WIDGETFOLDER);
+ fac.setFeatures(Features.getFeatureNames());
+ fac.setStartPageProcessor(new StartPageProcessor());
+ W3CWidget widgetModel = fac.parse(zipFile);
+ new WidgetJavascriptSyntaxAnalyzer(fac.getUnzippedWidgetDirectory());
+
+ //
+ // Check if the widget model corresponds to an existing installed
widget
+ //
+ IPersistenceManager persistenceManager =
PersistenceManagerFactory.getPersistenceManager();
+ if (persistenceManager.findWidgetByGuid(widgetModel.getIdentifier())
== null) {
+
+ //
+ // A new widget was created, so return 201
+ //
+ WidgetFactory.addNewWidget(widgetModel, zipFile,false);
+ return true;
+
+ } else {
+
+ //
+ // Widget already exists, so update the widget metadata and
configuration details
+ // and return 200
+ //
+
WidgetFactory.update(widgetModel,persistenceManager.findWidgetByGuid(widgetModel.getIdentifier()),false,
zipFile);
+ return false;
+
+ }
+
+ //
+ // Catch specific parsing and validation errors and throw exception
with error message
+ //
+ } catch (InvalidStartFileException ex) {
+ _logger.error(ex);
+ throw new InvalidParametersException(
+ localizedMessages.getString("widgets.no-start-file") + "\n" +
ex.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ } catch (BadManifestException ex) {
+ _logger.error(ex);
+ String message = ex.getMessage();
+ if (ex.getMessage() == null || ex.getMessage().equals(""))message =
localizedMessages.getString("widgets.invalid-config-xml"); //$NON-NLS-1$
+ if (ex instanceof InvalidContentTypeException)
+ message =
localizedMessages.getString("widgets.unsupported-content-type");//$NON-NLS-1$
+ throw new InvalidParametersException(message);
+ } catch (BadWidgetZipFileException ex) {
+ _logger.error(ex);
+ String message = ex.getMessage();
+ if (ex.getMessage() == null || ex.getMessage().equals(""))message =
localizedMessages.getString("widgets.bad-zip-file"); //$NON-NLS-1$
+ throw new InvalidParametersException(message);
+ } catch (Exception ex) {
+ _logger.error(ex);
+ throw new InvalidParametersException(
+ localizedMessages.getString("widgets.cant-parse-config-xml") + "\n"
+ ex.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
- return true;
- }
+ }
/**
* Register a gadget
Modified: incubator/wookie/trunk/src/org/apache/wookie/messages.properties
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/messages.properties?rev=1293247&r1=1293246&r2=1293247&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/messages.properties (original)
+++ incubator/wookie/trunk/src/org/apache/wookie/messages.properties Fri Feb 24
13:32:55 2012
@@ -1,3 +1,10 @@
+widgets.no-widget-file-uploaded=No file found uploaded to server
+widgets.invalid-config-xml=Invalid Widget: Config.xml is not a valid W3C
Widgets configuration document
+widgets.cant-parse-config-xml=Unable to parse the config.xml file
+widgets.bad-zip-file=Invalid Widget: Bad zip file
+widgets.no-start-file=Invalid Widget: No valid custom start file was
specified, and no valid default start file can be located
+widgets.unsupported-content-type=Invalid Widget: Config.xml specifies an
unsupported content type
+
WidgetAdminServlet.0=New Service Type was added.
WidgetAdminServlet.2=New uri was added.
WidgetAdminServlet.3=There was a problem adding the entry.
Modified: incubator/wookie/trunk/src/org/apache/wookie/messages_nl.properties
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/messages_nl.properties?rev=1293247&r1=1293246&r2=1293247&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/messages_nl.properties
(original)
+++ incubator/wookie/trunk/src/org/apache/wookie/messages_nl.properties Fri Feb
24 13:32:55 2012
@@ -1,3 +1,10 @@
+widgets.no-widget-file-uploaded=No file found uploaded to server
+widgets.invalid-config-xml=Invalid Widget: Config.xml is not a valid W3C
Widgets configuration document
+widgets.cant-parse-config-xml=Unable to parse the config.xml file
+widgets.bad-zip-file=Invalid Widget: Bad zip file
+widgets.no-start-file=Invalid Widget: No valid custom start file was
specified, and no valid default start file can be located
+widgets.unsupported-content-type=Invalid Widget: Config.xml specifies an
unsupported content type
+
WidgetAdminServlet.0=New Service Type was added.(dutch)
WidgetAdminServlet.2=New uri was added.(dutch)
WidgetAdminServlet.3=There was a problem adding the entry.(dutch)