You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by sc...@apache.org on 2011/05/03 10:42:09 UTC
svn commit: r1098967 - in /incubator/wookie/trunk: WebContent/WEB-INF/
src-tests/org/apache/wookie/tests/functional/ src/org/apache/wookie/updates/
Author: scottbw
Date: Tue May 3 08:42:09 2011
New Revision: 1098967
URL: http://svn.apache.org/viewvc?rev=1098967&view=rev
Log:
Added a controller and helper classes for Widget Updates (see WOOKIE-103). This provides an admin-only REST-like API for managing updates; you can get a list of available updates, trigger individual updates, or trigger all updates. This could be used to create an admin user interface.
Added:
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/UpdatesControllerTest.java
incubator/wookie/trunk/src/org/apache/wookie/updates/
incubator/wookie/trunk/src/org/apache/wookie/updates/UpdateInformation.java
incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesController.java
incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesHelper.java
Modified:
incubator/wookie/trunk/WebContent/WEB-INF/web.xml
Modified: incubator/wookie/trunk/WebContent/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/WebContent/WEB-INF/web.xml?rev=1098967&r1=1098966&r2=1098967&view=diff
==============================================================================
--- incubator/wookie/trunk/WebContent/WEB-INF/web.xml (original)
+++ incubator/wookie/trunk/WebContent/WEB-INF/web.xml Tue May 3 08:42:09 2011
@@ -121,6 +121,20 @@
<url-pattern>/participants</url-pattern>
</servlet-mapping>
+ <servlet>
+ <description></description>
+ <display-name>Updates</display-name>
+ <servlet-name>UpdatesServlet</servlet-name>
+ <servlet-class>
+ org.apache.wookie.updates.UpdatesController
+ </servlet-class>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>UpdatesServlet</servlet-name>
+ <url-pattern>/updates/*</url-pattern>
+ </servlet-mapping>
+
<servlet>
<description></description>
@@ -350,6 +364,19 @@
<role-name>widgetadmin</role-name>
</auth-constraint>
</security-constraint>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>UpdatesController</web-resource-name>
+ <url-pattern>/updates/*</url-pattern>
+ <http-method>GET</http-method>
+ <http-method>DELETE</http-method>
+ <http-method>PUT</http-method>
+ <http-method>POST</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>widgetadmin</role-name>
+ </auth-constraint>
+ </security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>WidgetServlet</web-resource-name>
Added: incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/UpdatesControllerTest.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/UpdatesControllerTest.java?rev=1098967&view=auto
==============================================================================
--- incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/UpdatesControllerTest.java (added)
+++ incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/UpdatesControllerTest.java Tue May 3 08:42:09 2011
@@ -0,0 +1,89 @@
+/*
+ * Licensed 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.tests.functional;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.wookie.tests.helpers.WidgetUploader;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test cases for Widget Updates controller
+ */
+public class UpdatesControllerTest extends AbstractControllerTest{
+
+ protected static final String TEST_UPDATES_URL_VALID = TEST_SERVER_LOCATION+"updates";
+
+ @BeforeClass
+ public static void setup(){
+
+ // Install all the test widgets
+ try {
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-acquisition11/001/ta-ac-001.wgt");//ac11
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-acquisition13/001/ta-ac-001.wgt");//ac13
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/003/ta-pr-003.wgt");//pr203
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/008/ta-pr-008.wgt");//pr208
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/009/ta-pr-009.wgt");//pr209
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/010/ta-pr-010.wgt");//pr210
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/011/ta-pr-011.wgt");//pr211
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/012/ta-pr-012.wgt");//pr212
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/013/ta-pr-013.wgt");//pr213
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/015/ta-pr-015.wgt");//pr215
+ WidgetUploader.uploadWidget("http://dev.w3.org/2006/waf/widgets-updates/test-suite/test-cases/ta-processing2/016/ta-pr-016.wgt");//pr216
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void getUpdatesUnauthorized(){
+ try {
+ HttpClient client = new HttpClient();
+ GetMethod get = new GetMethod(TEST_UPDATES_URL_VALID);
+ client.executeMethod(get);
+ int code = get.getStatusCode();
+ assertEquals(401, code);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ fail("get failed");
+ }
+ }
+
+ @Test
+ public void getUpdates(){
+ try {
+ HttpClient client = new HttpClient();
+ GetMethod get = new GetMethod(TEST_UPDATES_URL_VALID);
+ setAuthenticationCredentials(client);
+ get.setRequestHeader("Content-type", "text/xml");
+ client.executeMethod(get);
+ int code = get.getStatusCode();
+ assertEquals(200, code);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ fail("get failed");
+ }
+ }
+
+ // NOTE: Actually triggering the updates is tested using the conformance tests.
+
+}
Added: incubator/wookie/trunk/src/org/apache/wookie/updates/UpdateInformation.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/updates/UpdateInformation.java?rev=1098967&view=auto
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/updates/UpdateInformation.java (added)
+++ incubator/wookie/trunk/src/org/apache/wookie/updates/UpdateInformation.java Tue May 3 08:42:09 2011
@@ -0,0 +1,65 @@
+/*
+ * Licensed 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.updates;
+
+import org.apache.wookie.beans.IWidget;
+import org.apache.wookie.helpers.WidgetHelper;
+import org.apache.wookie.w3c.updates.UpdateDescriptionDocument;
+import org.jdom.Element;
+
+/**
+ * Simple class for passing update information, linking an IWidget reference to an UpdateDescriptionDocument
+ */
+public class UpdateInformation {
+
+ private IWidget widget;
+
+ private UpdateDescriptionDocument udd;
+
+ /**
+ * @return the widget
+ */
+ public IWidget getWidget() {
+ return widget;
+ }
+
+ /**
+ * @param widget the widget to set
+ */
+ public void setWidget(IWidget widget) {
+ this.widget = widget;
+ }
+
+ /**
+ * @return the document
+ */
+ public UpdateDescriptionDocument getUpdateDescriptionDocument() {
+ return udd;
+ }
+
+ /**
+ * @param document the document to set
+ */
+ public void setUpdateDescriptionDocument(UpdateDescriptionDocument udd) {
+ this.udd = udd;
+ }
+
+ public Element toXml(){
+ Element element = this.udd.toXml();
+ element.setAttribute("widget", this.widget.getId().toString());
+ element.setAttribute("widget_title", WidgetHelper.getEncodedWidgetTitle(this.widget, null));
+ return element;
+ }
+
+}
Added: incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesController.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesController.java?rev=1098967&view=auto
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesController.java (added)
+++ incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesController.java Tue May 3 08:42:09 2011
@@ -0,0 +1,210 @@
+/*
+ * Licensed 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.updates;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+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.IServerFeature;
+import org.apache.wookie.beans.IWidget;
+import org.apache.wookie.beans.util.IPersistenceManager;
+import org.apache.wookie.beans.util.PersistenceManagerFactory;
+import org.apache.wookie.controller.Controller;
+import org.apache.wookie.exceptions.InvalidParametersException;
+import org.apache.wookie.exceptions.ResourceDuplicationException;
+import org.apache.wookie.exceptions.ResourceNotFoundException;
+import org.apache.wookie.exceptions.UnauthorizedAccessException;
+import org.apache.wookie.helpers.FlashMessage;
+import org.apache.wookie.helpers.WidgetFactory;
+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.updates.UpdateDescriptionDocument;
+import org.apache.wookie.w3c.updates.UpdateUtils;
+
+/**
+ * Controller for managing widget updates
+ *
+ * GET - gets the list of updates available
+ * GET/{internal_widget_id} - redirects you to the UDD for the widget
+ * POST - attempts to apply ALL available updates
+ * PUT/{internal_widget_id} - applies update to specified widget only
+ */
+public class UpdatesController extends Controller {
+
+ private static final long serialVersionUID = 5891956245633379750L;
+
+ static Logger _logger = Logger.getLogger(UpdatesController.class.getName());
+
+ @Override
+ protected void index(HttpServletRequest request,
+ HttpServletResponse response) throws UnauthorizedAccessException,
+ IOException {
+ List<UpdateInformation> updates = getAllUpdates();
+ response.setStatus(HttpServletResponse.SC_OK);
+ returnXml(UpdatesHelper.createXML(updates),response);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.wookie.controller.Controller#show(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ protected void show(String resourceId, HttpServletRequest request,
+ HttpServletResponse response) throws ResourceNotFoundException,
+ UnauthorizedAccessException, IOException {
+ // attempt to get specific widget by id
+ IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
+ IWidget widget = persistenceManager.findById(IWidget.class, resourceId);
+ if (widget == null) throw new ResourceNotFoundException();
+ // redirect to the UDD
+ if (widget.getUpdateLocation() == null) throw new ResourceNotFoundException();
+ response.sendRedirect(widget.getUpdateLocation());
+ }
+
+ @Override
+ protected boolean create(String resourceId, HttpServletRequest request)
+ throws ResourceDuplicationException, InvalidParametersException,
+ UnauthorizedAccessException {
+
+ boolean onlyUseHttps = Boolean.parseBoolean(request.getParameter("use-https"));
+ if (!onlyUseHttps) _logger.warn("checking for updates using non-secure method");
+ IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
+ IWidget[] widgets = persistenceManager.findAll(IWidget.class);
+ W3CWidgetFactory factory = getFactory(request.getSession().getServletContext());
+ for (IWidget widget: widgets){
+ try {
+ installUpdate(factory, widget, onlyUseHttps);
+ } catch (Exception e) {
+ _logger.warn(e.getMessage(), e);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ protected void update(String resourceId, HttpServletRequest request)
+ throws ResourceNotFoundException, InvalidParametersException,
+ UnauthorizedAccessException {
+ // attempt to get specific widget by id
+ IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
+ IWidget widget = persistenceManager.findById(IWidget.class, resourceId);
+ if (widget == null) throw new ResourceNotFoundException();
+ // FIXME localize error messages
+ try {
+ W3CWidgetFactory factory = getFactory(request.getSession().getServletContext());
+ installUpdate(factory, widget, false);
+ } catch (IOException e) {
+ _logger.warn("Problem updating "+resourceId+": widget couldn't be downloaded");
+ throw new InvalidParametersException();
+ } catch (InvalidContentTypeException e) {
+ _logger.warn("Problem updating "+resourceId+": incorrect content type");
+ throw new InvalidParametersException();
+ } catch (BadWidgetZipFileException e) {
+ _logger.warn("Problem updating "+resourceId+": update is an invalid widget package");
+ throw new InvalidParametersException();
+ } catch (BadManifestException e) {
+ _logger.warn("Problem updating "+resourceId+": update has an invalid config.xml");
+ throw new InvalidParametersException();
+ } catch (Exception e) {
+ _logger.warn("Problem updating "+resourceId+": "+e.getMessage());
+ throw new InvalidParametersException();
+ }
+ }
+
+ /**
+ * Installs an update only for the specified widget
+ * @param factory a W3CWidgetFactory configured for this server
+ * @param widget the Widget to update
+ * @param doc the UpdateDescriptionDocument for the Widget update
+ * @param onlyUseHttps true to only install over HTTPS
+ * @throws Exception
+ * @throws IOException
+ * @throws BadManifestException
+ * @throws BadWidgetZipFileException
+ * @throws InvalidContentTypeException
+ */
+ // FIXME localize messages
+ private void installUpdate(W3CWidgetFactory factory, IWidget widget, boolean onlyUseHttps) throws InvalidContentTypeException, BadWidgetZipFileException, BadManifestException, IOException, Exception{
+ W3CWidget updatedWidget = UpdateUtils.getUpdate(factory, widget.getGuid(), widget.getUpdateLocation(), widget.getVersion(), onlyUseHttps);
+ if (updatedWidget != null){
+ WidgetFactory.update(updatedWidget, widget, false);
+ _logger.info("Successfully updated "+widget.getGuid()+" to version "+updatedWidget.getVersion());
+ FlashMessage.getInstance().message("Successfully updated "+widget.getGuid()+" to version "+updatedWidget.getVersion());
+ }
+ }
+
+ /**
+ * Obtain a W3CWidgetFactory configured for this servlet context
+ * @param context
+ * @return the factory
+ * @throws IOException
+ */
+ private W3CWidgetFactory getFactory(ServletContext context){
+ Configuration properties = (Configuration) context.getAttribute("properties"); //$NON-NLS-1$
+ W3CWidgetFactory factory = new W3CWidgetFactory();
+ final String[] locales = properties.getStringArray("widget.locales");
+ factory.setLocales(locales);
+ factory.setLocalPath(context.getContextPath()+properties.getString("widget.widgetfolder"));
+ final String WIDGETFOLDER = context.getRealPath(properties.getString("widget.widgetfolder"));//$NON-NLS-1$
+ try {
+ factory.setOutputDirectory(WIDGETFOLDER);
+ } catch (IOException e) {
+ _logger.error(e);
+ }
+ // Configure the widget factory with the installed feature set
+ IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
+ IServerFeature[] features = persistenceManager.findAll(IServerFeature.class);
+ String[] featureNames = new String[features.length];
+ for (int i=0;i<features.length;i++){
+ featureNames[i] = features[i].getFeatureName();
+ }
+ factory.setFeatures(featureNames);
+ factory.setStartPageProcessor(new StartPageProcessor());
+ return factory;
+ }
+
+ /**
+ * Get available updates for all installed widgets. Note that this method takes a long
+ * time to return as it has to poll all the available update sites, so where possible
+ * cache the returned updates
+ * @return a list containing all the updates available.
+ */
+ public List<UpdateInformation> getAllUpdates(){
+ ArrayList<UpdateInformation> updates = new ArrayList<UpdateInformation>();
+ IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
+ IWidget[] widgets = persistenceManager.findAll(IWidget.class);
+ for (IWidget widget: widgets){
+ UpdateDescriptionDocument udd = UpdateUtils.checkForUpdate(widget.getUpdateLocation(), widget.getVersion());
+ if (udd != null){
+ UpdateInformation info = new UpdateInformation();
+ info.setUpdateDescriptionDocument(udd);
+ info.setWidget(widget);
+ updates.add(info);
+ }
+ }
+ return updates;
+ }
+
+
+}
Added: incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesHelper.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesHelper.java?rev=1098967&view=auto
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesHelper.java (added)
+++ incubator/wookie/trunk/src/org/apache/wookie/updates/UpdatesHelper.java Tue May 3 08:42:09 2011
@@ -0,0 +1,40 @@
+/*
+ * Licensed 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.updates;
+
+import java.util.List;
+
+import org.apache.wookie.w3c.IW3CXMLConfiguration;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.output.XMLOutputter;
+
+/**
+ * View Helper for updates
+ */
+public class UpdatesHelper {
+
+ public static String createXML(
+ List<UpdateInformation> updates) {
+ Document document = new Document();
+ Element root = new Element("updates",IW3CXMLConfiguration.MANIFEST_NAMESPACE);
+ for (UpdateInformation info: updates){
+ root.addContent(info.toXml());
+ }
+ document.setRootElement(root);
+ XMLOutputter outputter = new XMLOutputter();
+ return outputter.outputString(document);
+ }
+
+}