Author: mwringe
Date: 2010-09-22 11:01:36 -0400 (Wed, 22 Sep 2010)
New Revision: 4308
Added:
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/WSRPPortletInvoker.java
components/wsrp/trunk/wsrp-producer-war/src/test/assembly/test-state-portlet.xml
components/wsrp/trunk/wsrp-producer-war/src/test/java/org/gatein/wsrp/portlet/StateCountingPortlet.java
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/portlet.xml
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/web.xml
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/AbstractRegistrationPersistenceManager.java
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/Registration.java
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/RegistrationPersistenceManager.java
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/RegistrationPolicy.java
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/impl/RegistrationImpl.java
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/impl/RegistrationPersistenceManagerImpl.java
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/policies/DefaultRegistrationPolicy.java
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/policies/RegistrationPolicyWrapper.java
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/MarkupHandler.java
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/RegistrationHandler.java
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/processors/WSRPInstanceContext.java
components/wsrp/trunk/producer/src/test/java/org/gatein/wsrp/producer/config/TestRegistrationPolicy.java
components/wsrp/trunk/wsrp-producer-war/pom.xml
components/wsrp/trunk/wsrp-producer-war/src/test/java/org/gatein/wsrp/protocol/v2/MarkupTestCase.java
components/wsrp/trunk/wsrp-producer-war/src/test/producer-sar/META-INF/jboss-beans.xml
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-portletstate-portlet-war/WEB-INF/portlet.xml
Log:
GTNWSRP-72: Add portlet context handling to registrations. Allows for registrations to
have a filtered list of portlet contexts. RegistrationPolicy currently setup to handle
filtering so that only cloned created from a particular registration has access.
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/AbstractRegistrationPersistenceManager.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/AbstractRegistrationPersistenceManager.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/AbstractRegistrationPersistenceManager.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -59,6 +59,17 @@
internalSaveChangesTo(consumer);
}
+ public void saveChangesTo(Registration registration)
+ {
+ ParameterValidation.throwIllegalArgExceptionIfNull(registration,
"Registration");
+
+ if (registration.getPersistentKey() == null)
+ {
+ throw new IllegalArgumentException("Registration " + registration +
" hasn't yet been persisted and thus cannot be updated");
+ }
+ internalSaveChangesTo(registration);
+ }
+
public ConsumerGroup createConsumerGroup(String name) throws RegistrationException
{
ConsumerGroup group = getConsumerGroup(name);
@@ -165,6 +176,8 @@
protected abstract ConsumerSPI internalCreateConsumer(String consumerId, String
consumerName);
protected abstract ConsumerSPI internalSaveChangesTo(Consumer consumer);
+
+ protected abstract RegistrationSPI internalSaveChangesTo(Registration registration);
protected abstract void internalAddConsumerGroup(ConsumerGroupSPI group);
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/Registration.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/Registration.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/Registration.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -24,6 +24,8 @@
package org.gatein.registration;
import javax.xml.namespace.QName;
+
+import java.util.List;
import java.util.Map;
/**
@@ -106,4 +108,6 @@
Object getPropertyValueFor(QName propertyName);
Object getPropertyValueFor(String propertyName);
+
+ List<String> getPortletHandles();
}
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/RegistrationPersistenceManager.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/RegistrationPersistenceManager.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/RegistrationPersistenceManager.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -48,6 +48,13 @@
* @param consumer
*/
void saveChangesTo(Consumer consumer);
+
+ /**
+ * Saves changes made to the specified registration.
+ *
+ * @param registration
+ */
+ void saveChangesTo(Registration registration);
/**
* Retrieves the ConsumerGroup identified by the specified name.
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/RegistrationPolicy.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/RegistrationPolicy.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/RegistrationPolicy.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -26,6 +26,8 @@
import org.gatein.wsrp.registration.PropertyDescription;
import javax.xml.namespace.QName;
+
+import java.util.List;
import java.util.Map;
/**
@@ -120,5 +122,10 @@
* @throws RegistrationException if an exception occurred in the Registration
service
*/
void validateConsumerGroupName(String groupName, RegistrationManager manager) throws
IllegalArgumentException, RegistrationException;
-
+
+ //TODO: add javadocs here
+ boolean checkPortletHandle(Registration registration, String portletHandle);
+ void addPortletHandle(Registration registration, String portletHandle);
+ void removePortletHandle(Registration registration, String portletHandle);
+ void updatePortletHandles(List<String> portlets);
}
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/impl/RegistrationImpl.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/impl/RegistrationImpl.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/impl/RegistrationImpl.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -30,8 +30,10 @@
import org.gatein.registration.spi.RegistrationSPI;
import javax.xml.namespace.QName;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -47,6 +49,7 @@
private RegistrationStatus status;
private Map<QName, Object> properties;
private String registrationHandle;
+ private List<String> portletHandles;
RegistrationImpl(String key, ConsumerSPI consumer, RegistrationStatus status,
Map<QName, Object> properties)
@@ -55,6 +58,7 @@
this.consumer = consumer;
this.status = status;
this.properties = new HashMap<QName, Object>(properties);
+ this.portletHandles = new ArrayList<String>();
}
public String getPersistentKey()
@@ -189,4 +193,8 @@
properties = new HashMap(registrationProperties);
}
+ public List<String> getPortletHandles()
+ {
+ return portletHandles;
+ }
}
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/impl/RegistrationPersistenceManagerImpl.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/impl/RegistrationPersistenceManagerImpl.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/impl/RegistrationPersistenceManagerImpl.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -172,4 +172,10 @@
{
return (ConsumerSPI)consumer; // nothing to do here, left up to subclasses to
implement update in persistent store
}
+
+ @Override
+ protected RegistrationSPI internalSaveChangesTo(Registration registration)
+ {
+ return (RegistrationSPI)registration; // nothing to do here, left up to subclasses
to implement update in persistent store
+ }
}
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/policies/DefaultRegistrationPolicy.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/policies/DefaultRegistrationPolicy.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/policies/DefaultRegistrationPolicy.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -37,8 +37,10 @@
import org.slf4j.LoggerFactory;
import javax.xml.namespace.QName;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -54,6 +56,9 @@
{
private RegistrationPropertyValidator validator;
private static final Logger log =
LoggerFactory.getLogger(DefaultRegistrationPolicy.class);
+
+ //Stores a list of the default portlet handles which should be available to all
registrations (ie not cloned handles)
+ List<String> defaultPortletHandleList = new ArrayList<String>();
@Override
public boolean equals(Object o)
@@ -217,4 +222,40 @@
{
return validator;
}
+
+ public void addPortletHandle(Registration registration, String portletHandle)
+ {
+ if (registration != null &&
!registration.getPortletHandles().contains(portletHandle))
+ {
+ registration.getPortletHandles().add(portletHandle);
+ }
+ }
+
+ public boolean checkPortletHandle(Registration registration, String portletHandle)
+ {
+ if (defaultPortletHandleList.contains(portletHandle))
+ {
+ return true;
+ }
+
+ if (registration != null &&
registration.getPortletHandles().contains(portletHandle))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void removePortletHandle(Registration registration, String portletHandle)
+ {
+ if (registration != null)
+ {
+ registration.getPortletHandles().remove(portletHandle);
+ }
+ }
+
+ public void updatePortletHandles(List<String> portletHandles)
+ {
+ this.defaultPortletHandleList = portletHandles;
+ }
}
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/policies/RegistrationPolicyWrapper.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/policies/RegistrationPolicyWrapper.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/registration/policies/RegistrationPolicyWrapper.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -25,12 +25,15 @@
import org.gatein.common.util.ParameterValidation;
import org.gatein.registration.InvalidConsumerDataException;
+import org.gatein.registration.Registration;
import org.gatein.registration.RegistrationException;
import org.gatein.registration.RegistrationManager;
import org.gatein.registration.RegistrationPolicy;
import org.gatein.wsrp.registration.PropertyDescription;
import javax.xml.namespace.QName;
+
+import java.util.List;
import java.util.Map;
/**
@@ -98,4 +101,24 @@
return consumerName;
}
+
+ public void addPortletHandle(Registration registration, String portletHandle)
+ {
+ delegate.addPortletHandle(registration, portletHandle);
+ }
+
+ public boolean checkPortletHandle(Registration registration, String portletHandle)
+ {
+ return delegate.checkPortletHandle(registration, portletHandle);
+ }
+
+ public void removePortletHandle(Registration registration, String portletHandle)
+ {
+ delegate.removePortletHandle(registration, portletHandle);
+ }
+
+ public void updatePortletHandles(List<String> portletHandles)
+ {
+ delegate.updatePortletHandles(portletHandles);
+ }
}
Added:
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/WSRPPortletInvoker.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/WSRPPortletInvoker.java
(rev 0)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/WSRPPortletInvoker.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -0,0 +1,243 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2008, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org. *
+ ******************************************************************************/
+package org.gatein.wsrp.producer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.gatein.pc.api.NoSuchPortletException;
+import org.gatein.pc.api.Portlet;
+import org.gatein.pc.api.PortletContext;
+import org.gatein.pc.api.PortletInvokerException;
+import org.gatein.pc.api.PortletStateType;
+import org.gatein.pc.api.StatefulPortletContext;
+import org.gatein.pc.api.invocation.PortletInvocation;
+import org.gatein.pc.api.invocation.response.PortletInvocationResponse;
+import org.gatein.pc.api.invocation.response.UpdateNavigationalStateResponse;
+import org.gatein.pc.api.state.DestroyCloneFailure;
+import org.gatein.pc.api.state.PropertyChange;
+import org.gatein.pc.api.state.PropertyMap;
+import org.gatein.pc.portlet.PortletInvokerInterceptor;
+import org.gatein.registration.Registration;
+import org.gatein.registration.RegistrationLocal;
+import org.gatein.registration.RegistrationManager;
+import org.gatein.wsrp.WSRPUtils;
+import org.gatein.wsrp.producer.handlers.processors.WSRPInstanceContext;
+import org.oasis.wsrp.v2.InvalidHandle;
+
+/**
+ * @author <a href="mailto:mwringe@redhat.com">Matt Wringe</a>
+ * @version $Revision$
+ */
+public class WSRPPortletInvoker extends PortletInvokerInterceptor
+{
+ /** Registration Manager */
+ private RegistrationManager registrationManager; //todo: make sure it's
multi-thread safe
+
+ public RegistrationManager getRegistrationManager()
+ {
+ return registrationManager;
+ }
+
+ public void setRegistrationManager(RegistrationManager registrationManager)
+ {
+ this.registrationManager = registrationManager;
+ }
+
+ public Portlet getPortlet(PortletContext portletContext) throws
IllegalArgumentException, PortletInvokerException
+ {
+ checkPortletContext(portletContext);
+ Portlet portlet = super.getPortlet(portletContext);
+
+ if (!portlet.getContext().getId().equals(portletContext.getId()))
+ {
+ addPortletContext(portlet.getContext());
+ }
+
+ return portlet;
+ }
+
+ public Set<Portlet> getPortlets() throws PortletInvokerException
+ {
+ /**
+ * Note: due to the way the ProducerPortletInvoker work, when calling
super.getPortlets() it will
+ * return the portlets not for the ProducerPortletInvoker from its parent, which
should only return
+ * non-cloned Portlets.
+ */
+
+ Registration registration = RegistrationLocal.getRegistration();
+ Set<Portlet> portlets = super.getPortlets();
+
+ //We first need to let the RegistrationPolicy know that there are potentially new
portlets available
+ //from the PortletContainer (Note: this only included actual portlets, not
clones).
+ List<String> portletHandleList = new ArrayList<String>();
+ for (Portlet portlet: portlets)
+ {
+ String portletHandle =
WSRPUtils.convertToWSRPPortletContext(portlet.getContext()).getPortletHandle();
+ portletHandleList.add(portletHandle);
+ }
+ this.registrationManager.getPolicy().updatePortletHandles(portletHandleList);
+
+ //Now that the RegistrationPolicy knows about the new Portlets, we need to make
+ //sure that we only return portlets that the current registration has access to.
+ Set<Portlet> acceptedPortlets = new LinkedHashSet<Portlet>();
+ for (Portlet portlet : portlets)
+ {
+ String portletHandle =
WSRPUtils.convertToWSRPPortletContext(portlet.getContext()).getPortletHandle();
+ if (this.registrationManager.getPolicy().checkPortletHandle(registration,
portletHandle))
+ {
+ acceptedPortlets.add(portlet);
+ }
+ }
+
+ return acceptedPortlets;
+ }
+
+
+ public PortletInvocationResponse invoke(PortletInvocation invocation) throws
IllegalArgumentException,
+ PortletInvokerException
+ {
+ checkPortletContext(invocation.getTarget());
+
+ PortletInvocationResponse response = super.invoke(invocation);
+
+ if (invocation.getInstanceContext() instanceof WSRPInstanceContext)
+ {
+ WSRPInstanceContext wsrpIC =
(WSRPInstanceContext)invocation.getInstanceContext();
+ if (wsrpIC.wasModified() &&
!wsrpIC.getPortletContext().getId().equals(invocation.getTarget().getId()))
+ {
+ addPortletContext(wsrpIC.getPortletContext());
+ }
+ }
+
+ return response;
+ }
+
+ public PortletContext createClone(PortletStateType stateType, PortletContext
portletContext)
+ throws IllegalArgumentException, PortletInvokerException,
UnsupportedOperationException
+ {
+ checkPortletContext(portletContext);
+
+ PortletContext clonedPortletContext = super.createClone(stateType,
portletContext);
+
+ if (!portletContext.getId().equals(clonedPortletContext.getId()))
+ addPortletContext(clonedPortletContext);
+
+ return clonedPortletContext;
+ }
+
+ public List<DestroyCloneFailure> destroyClones(List<PortletContext>
portletContexts)
+ throws IllegalArgumentException, PortletInvokerException,
UnsupportedOperationException
+ {
+ //TODO: fix this, we shouldn't remove the pc from the registration policy
unless its actually removed from the invoker cleanly
+ for (PortletContext portletContext : portletContexts)
+ {
+ removePortletContext(portletContext);
+ }
+
+ return super.destroyClones(portletContexts);
+ }
+
+ public PropertyMap getProperties(PortletContext portletContext) throws
IllegalArgumentException,
+ PortletInvokerException, UnsupportedOperationException
+ {
+ checkPortletContext(portletContext);
+ return super.getProperties(portletContext);
+ }
+
+ public PropertyMap getProperties(PortletContext portletContext, Set<String>
keys) throws IllegalArgumentException,
+ PortletInvokerException, UnsupportedOperationException
+ {
+ checkPortletContext(portletContext);
+ return super.getProperties(portletContext, keys);
+ }
+
+ public PortletContext setProperties(PortletContext portletContext, PropertyChange[]
changes)
+ throws IllegalArgumentException, PortletInvokerException,
UnsupportedOperationException
+ {
+ checkPortletContext(portletContext);
+ PortletContext updatedPortletContext = super.setProperties(portletContext,
changes);
+
+ if (!portletContext.getId().equals(updatedPortletContext.getId()))
+ {
+ addPortletContext(updatedPortletContext);
+ }
+
+ return updatedPortletContext;
+ }
+
+ public PortletContext importPortlet(PortletStateType stateType, PortletContext
originalPortletContext)
+ throws PortletInvokerException, IllegalArgumentException
+ {
+ //The original portletcontext is the non cloned version and should be one the PC
available from the getPortlets operation
+ checkPortletContext(originalPortletContext);
+ PortletContext newPortletContext = super.importPortlet(stateType,
originalPortletContext);
+
+ if (!newPortletContext.getId().equals(originalPortletContext.getId()))
+ addPortletContext(newPortletContext);
+
+ return newPortletContext;
+ }
+
+ public PortletContext exportPortlet(PortletStateType stateType, PortletContext
portletContext)
+ throws PortletInvokerException, IllegalArgumentException
+ {
+ checkPortletContext(portletContext);
+ return super.exportPortlet(stateType, portletContext);
+ }
+
+ protected boolean checkPortletContext(PortletContext portletContext) throws
PortletInvokerException
+ {
+ Registration registration = RegistrationLocal.getRegistration();
+ String portletHandle =
WSRPUtils.convertToWSRPPortletContext(portletContext).getPortletHandle();
+ if (this.getRegistrationManager().getPolicy().checkPortletHandle(registration,
portletHandle))
+ {
+ return true;
+ }
+ else
+ {
+ throw new NoSuchPortletException("The PortletContext " +
portletContext.getId() + " does not exist or the application is lacking permission to
access it.", portletContext.getId());
+ }
+ }
+
+ protected void addPortletContext(PortletContext portletContext)
+ {
+ Registration registration = RegistrationLocal.getRegistration();
+ String portletHandle =
WSRPUtils.convertToWSRPPortletContext(portletContext).getPortletHandle();
+ this.getRegistrationManager().getPolicy().addPortletHandle(registration,
portletHandle);
+ this.getRegistrationManager().getPersistenceManager().saveChangesTo(registration);
+ }
+
+ protected void removePortletContext(PortletContext portletContext)
+ {
+ Registration registration = RegistrationLocal.getRegistration();
+ String portletHandle =
WSRPUtils.convertToWSRPPortletContext(portletContext).getPortletHandle();
+ this.getRegistrationManager().getPolicy().removePortletHandle(registration,
portletHandle);
+ this.getRegistrationManager().getPersistenceManager().saveChangesTo(registration);
+ }
+}
+
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/MarkupHandler.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/MarkupHandler.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/MarkupHandler.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -31,6 +31,8 @@
import org.gatein.pc.api.invocation.response.PortletInvocationResponse;
import org.gatein.pc.api.invocation.response.UpdateNavigationalStateResponse;
import org.gatein.pc.portlet.state.producer.PortletStateChangeRequiredException;
+import org.gatein.registration.Registration;
+import org.gatein.registration.RegistrationLocal;
import org.gatein.wsrp.producer.MarkupInterface;
import org.gatein.wsrp.producer.Utils;
import org.gatein.wsrp.producer.WSRPProducerImpl;
@@ -107,6 +109,8 @@
try
{
log.debug("RenderInvocation on portlet '" + handle +
"'");
+ Registration registration =
producer.getRegistrationOrFailIfInvalid(getMarkup.getRegistrationContext());
+ RegistrationLocal.setRegistration(registration);
response =
producer.getPortletInvoker().invoke(requestProcessor.getInvocation());
log.debug("RenderInvocation done");
}
@@ -134,6 +138,8 @@
try
{
log.debug("ResourceInvocation on portlet '" + handle +
"'");
+ Registration registration =
producer.getRegistrationOrFailIfInvalid(getResource.getRegistrationContext());
+ RegistrationLocal.setRegistration(registration);
response =
producer.getPortletInvoker().invoke(requestProcessor.getInvocation());
log.debug("ResourceInvocation done");
}
@@ -163,6 +169,8 @@
try
{
log.debug("ActionInvocation on portlet '" + handle +
"'");
+ Registration registration =
producer.getRegistrationOrFailIfInvalid(performBlockingInteraction.getRegistrationContext());
+ RegistrationLocal.setRegistration(registration);
response =
producer.getPortletInvoker().invoke(requestProcessor.getInvocation());
log.debug("ActionInvocation done");
}
@@ -218,6 +226,8 @@
try
{
log.debug("EventInvocation on portlet '" + handle +
"'");
+ Registration registration =
producer.getRegistrationOrFailIfInvalid(handleEvents.getRegistrationContext());
+ RegistrationLocal.setRegistration(registration);
response =
producer.getPortletInvoker().invoke(requestProcessor.getInvocation());
log.debug("EventInvocation done");
}
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/RegistrationHandler.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/RegistrationHandler.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/RegistrationHandler.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -81,7 +81,7 @@
throws MissingParameters, OperationFailed, OperationNotSupported
{
ProducerRegistrationRequirements registrationRequirements =
producer.getProducerRegistrationRequirements();
- if (registrationRequirements.isRegistrationRequired())
+ //if (registrationRequirements.isRegistrationRequired())
{
WSRP2ExceptionFactory.throwOperationFailedIfValueIsMissing(registrationData,
"RegistrationData");
String consumerName = registrationData.getConsumerName();
@@ -113,7 +113,7 @@
return registrationContext;
}
- throw WSRP2ExceptionFactory.throwWSException(OperationFailed.class,
"Registration shouldn't be attempted if registration is not required",
null);
+ //throw WSRP2ExceptionFactory.throwWSException(OperationFailed.class,
"Registration shouldn't be attempted if registration is not required",
null);
}
private void updateRegistrationInformation(Registration registration, RegistrationData
registrationData)
@@ -324,7 +324,10 @@
{
throwInvalidRegistrationFault("registration context is missing but
registration is required");
}
+ }
+ if (registrationContext != null)
+ {
String regHandle = registrationContext.getRegistrationHandle();
if (regHandle == null)
{
@@ -348,11 +351,33 @@
}
else
{
- if (registrationContext != null)
+ try
{
- throwInvalidRegistrationFault("no registration necessary yet one was
provided!");
+ //TODO: fix this giant hack,
+ String unregisteredConsumer = "UNREGISTEREDCONSUMER";
+ Consumer consumer =
producer.getRegistrationManager().getConsumerByIdentity(unregisteredConsumer);
+ if (consumer == null)
+ {
+ consumer =
producer.getRegistrationManager().createConsumer(unregisteredConsumer);
+ }
+
+ if (consumer.getRegistrations().isEmpty())
+ {
+ Registration registration =
producer.getRegistrationManager().addRegistrationTo(unregisteredConsumer, new HashMap(),
null, false);
+ registration.setStatus(RegistrationStatus.VALID);
+ return registration;
+ }
+ else
+ {
+ return consumer.getRegistrations().iterator().next();
+ }
}
- return null;
+ catch (RegistrationException e)
+ {
+ throwOperationFailedFault("Failed to create a virtual registration with
a unregistered consumer", e);
+ return null;
+ }
+ // return null;
}
}
Modified:
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/processors/WSRPInstanceContext.java
===================================================================
---
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/processors/WSRPInstanceContext.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/main/java/org/gatein/wsrp/producer/handlers/processors/WSRPInstanceContext.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -36,7 +36,7 @@
* @version $Revision: 8784 $
* @since 2.6
*/
-class WSRPInstanceContext implements InstanceContext
+public class WSRPInstanceContext implements InstanceContext
{
private PortletContext context;
private String instanceId;
@@ -84,7 +84,7 @@
return wasModified;
}
- PortletContext getPortletContext()
+ public PortletContext getPortletContext()
{
return context;
}
Modified:
components/wsrp/trunk/producer/src/test/java/org/gatein/wsrp/producer/config/TestRegistrationPolicy.java
===================================================================
---
components/wsrp/trunk/producer/src/test/java/org/gatein/wsrp/producer/config/TestRegistrationPolicy.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/producer/src/test/java/org/gatein/wsrp/producer/config/TestRegistrationPolicy.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -24,12 +24,15 @@
package org.gatein.wsrp.producer.config;
import org.gatein.registration.InvalidConsumerDataException;
+import org.gatein.registration.Registration;
import org.gatein.registration.RegistrationException;
import org.gatein.registration.RegistrationManager;
import org.gatein.registration.RegistrationPolicy;
import org.gatein.wsrp.registration.PropertyDescription;
import javax.xml.namespace.QName;
+
+import java.util.List;
import java.util.Map;
/**
@@ -66,4 +69,21 @@
{
}
+ public void addPortletHandle(Registration registration, String portletHandle)
+ {
+ }
+
+ public boolean checkPortletHandle(Registration registration, String portletHandle)
+ {
+ return true;
+ }
+
+ public void removePortletHandle(Registration registration, String portletHandle)
+ {
+ }
+
+ public void updatePortletHandles(List<String> portletHandles)
+ {
+ }
+
}
Modified: components/wsrp/trunk/wsrp-producer-war/pom.xml
===================================================================
--- components/wsrp/trunk/wsrp-producer-war/pom.xml 2010-09-22 13:35:10 UTC (rev 4307)
+++ components/wsrp/trunk/wsrp-producer-war/pom.xml 2010-09-22 15:01:36 UTC (rev 4308)
@@ -181,6 +181,7 @@
<descriptor>src/test/assembly/test-portletmodes-portlet.xml</descriptor>
<descriptor>src/test/assembly/test-prp-portlet.xml</descriptor>
<descriptor>src/test/assembly/test-testobject-jar.xml</descriptor>
+
<descriptor>src/test/assembly/test-state-portlet.xml</descriptor>
</descriptors>
</configuration>
<executions>
Added: components/wsrp/trunk/wsrp-producer-war/src/test/assembly/test-state-portlet.xml
===================================================================
--- components/wsrp/trunk/wsrp-producer-war/src/test/assembly/test-state-portlet.xml
(rev 0)
+++
components/wsrp/trunk/wsrp-producer-war/src/test/assembly/test-state-portlet.xml 2010-09-22
15:01:36 UTC (rev 4308)
@@ -0,0 +1,25 @@
+<assembly>
+ <id>state-portlet</id>
+ <formats>
+ <format>war</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <!-- Test Classes -->
+ <fileSet>
+ <directory>target/test-classes</directory>
+ <outputDirectory>WEB-INF/classes</outputDirectory>
+ <includes>
+
<include>org/gatein/wsrp/portlet/StateCountingPortlet.class</include>
+ </includes>
+ </fileSet>
+ <!-- Fileset for the sar strucuture -->
+ <fileSet>
+ <directory>src/test/test-portlets/test-state-portlet-war</directory>
+ <outputDirectory></outputDirectory>
+ </fileSet>
+ </fileSets>
+
+</assembly>
+
Added:
components/wsrp/trunk/wsrp-producer-war/src/test/java/org/gatein/wsrp/portlet/StateCountingPortlet.java
===================================================================
---
components/wsrp/trunk/wsrp-producer-war/src/test/java/org/gatein/wsrp/portlet/StateCountingPortlet.java
(rev 0)
+++
components/wsrp/trunk/wsrp-producer-war/src/test/java/org/gatein/wsrp/portlet/StateCountingPortlet.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -0,0 +1,73 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2008, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org. *
+ ******************************************************************************/
+package org.gatein.wsrp.portlet;
+
+import java.io.IOException;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.GenericPortlet;
+import javax.portlet.PortletException;
+import javax.portlet.PortletPreferences;
+import javax.portlet.PortletSecurityException;
+import javax.portlet.PortletURL;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+/**
+ * @author <a href="mailto:mwringe@redhat.com">Matt Wringe</a>
+ * @version $Revision$
+ */
+public class StateCountingPortlet extends GenericPortlet
+{
+
+ public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, PortletSecurityException, IOException
+ {
+ PortletPreferences pp = request.getPreferences();
+
+ String counter = pp.getValue("counter", "0");
+
+ int count = Integer.parseInt(counter);
+
+ count++;
+
+ pp.setValue("counter", "" + count);
+ pp.store();
+ }
+
+ protected void doView(RenderRequest request, RenderResponse response) throws
PortletException, PortletSecurityException, IOException
+ {
+ response.setContentType("text/html");
+ PortletPreferences pp = request.getPreferences();
+
+ String count = pp.getValue("counter", "0");
+ response.getWriter().write("COUNT : " + count);
+
+ PortletURL actionURL = response.createActionURL();
+
+ response.getWriter().write(" <a href=\"" + actionURL
+"\">count++</>");
+
+ }
+
+}
+
Modified:
components/wsrp/trunk/wsrp-producer-war/src/test/java/org/gatein/wsrp/protocol/v2/MarkupTestCase.java
===================================================================
---
components/wsrp/trunk/wsrp-producer-war/src/test/java/org/gatein/wsrp/protocol/v2/MarkupTestCase.java 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/wsrp-producer-war/src/test/java/org/gatein/wsrp/protocol/v2/MarkupTestCase.java 2010-09-22
15:01:36 UTC (rev 4308)
@@ -123,11 +123,20 @@
@Test
public void testGetMarkupViewNoSession() throws Exception
{
- GetMarkup getMarkup = createMarkupRequest();
+ try
+ {
+ GetMarkup getMarkup = createMarkupRequest();
- MarkupResponse response = producer.getMarkup(getMarkup);
+ MarkupResponse response = producer.getMarkup(getMarkup);
- checkMarkupResponse(response, DEFAULT_VIEW_MARKUP);
+ checkMarkupResponse(response, DEFAULT_VIEW_MARKUP);
+ }
+ catch (Exception e)
+ {
+ System.out.println("ERROR running testGetMarkupViewNoSession");
+ e.printStackTrace();
+ throw e;
+ }
}
@Test
@@ -600,44 +609,53 @@
@Test
public void testImplicitCloning() throws Exception
{
- undeploy(DEFAULT_MARKUP_PORTLET_WAR);
- String archiveName = "test-implicitcloning-portlet.war";
- deploy(archiveName);
-
try
{
- // check the initial value
- GetMarkup gm = createMarkupRequestForCurrentlyDeployedPortlet();
- MarkupResponse res = producer.getMarkup(gm);
- String markupString = res.getMarkupContext().getItemString();
- ExtendedAssert.assertEquals("initial", markupString);
+ undeploy(DEFAULT_MARKUP_PORTLET_WAR);
+ String archiveName = "test-implicitcloning-portlet.war";
+ deploy(archiveName);
- // modify the preference value
- PerformBlockingInteraction pbi =
createDefaultPerformBlockingInteraction(getHandleForCurrentlyDeployedArchive());
-
pbi.getInteractionParams().setPortletStateChange(StateChange.CLONE_BEFORE_WRITE); //
request cloning if needed
- String value = "new value";
-
pbi.getInteractionParams().getFormParameters().add(createNamedString("value",
value));
- BlockingInteractionResponse response =
producer.performBlockingInteraction(pbi);
- ExtendedAssert.assertNotNull(response);
+ try
+ {
+ // check the initial value
+ GetMarkup gm = createMarkupRequestForCurrentlyDeployedPortlet();
+ MarkupResponse res = producer.getMarkup(gm);
+ String markupString = res.getMarkupContext().getItemString();
+ ExtendedAssert.assertEquals("initial", markupString);
- // check that we got a new portlet context
- PortletContext pc = response.getUpdateResponse().getPortletContext();
- ExtendedAssert.assertNotNull(pc);
+ // modify the preference value
+ PerformBlockingInteraction pbi =
createDefaultPerformBlockingInteraction(getHandleForCurrentlyDeployedArchive());
+
pbi.getInteractionParams().setPortletStateChange(StateChange.CLONE_BEFORE_WRITE); //
request cloning if needed
+ String value = "new value";
+
pbi.getInteractionParams().getFormParameters().add(createNamedString("value",
value));
+ BlockingInteractionResponse response =
producer.performBlockingInteraction(pbi);
+ ExtendedAssert.assertNotNull(response);
- // get the markup again and check that we still get the initial value with the
initial portlet context
- res = producer.getMarkup(gm);
- markupString = res.getMarkupContext().getItemString();
- ExtendedAssert.assertEquals("initial", markupString);
+ // check that we got a new portlet context
+ PortletContext pc = response.getUpdateResponse().getPortletContext();
+ ExtendedAssert.assertNotNull(pc);
- // retrieving the markup with the new portlet context should return the new
value
- gm.setPortletContext(pc);
- res = producer.getMarkup(gm);
- markupString = res.getMarkupContext().getItemString();
- ExtendedAssert.assertEquals(value, markupString);
+ // get the markup again and check that we still get the initial value with
the initial portlet context
+ res = producer.getMarkup(gm);
+ markupString = res.getMarkupContext().getItemString();
+ ExtendedAssert.assertEquals("initial", markupString);
+
+ // retrieving the markup with the new portlet context should return the new
value
+ gm.setPortletContext(pc);
+ res = producer.getMarkup(gm);
+ markupString = res.getMarkupContext().getItemString();
+ ExtendedAssert.assertEquals(value, markupString);
+ }
+ finally
+ {
+ undeploy(archiveName);
+ }
}
- finally
+ catch (Exception e)
{
- undeploy(archiveName);
+ System.out.println("ERROR during " + this.getClass() + "
testImplicitCloning");
+ e.printStackTrace();
+ throw new Exception (e);
}
}
Modified:
components/wsrp/trunk/wsrp-producer-war/src/test/producer-sar/META-INF/jboss-beans.xml
===================================================================
---
components/wsrp/trunk/wsrp-producer-war/src/test/producer-sar/META-INF/jboss-beans.xml 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/wsrp-producer-war/src/test/producer-sar/META-INF/jboss-beans.xml 2010-09-22
15:01:36 UTC (rev 4308)
@@ -39,7 +39,7 @@
<parameter>true</parameter>
</constructor>
<property name="portletInvoker">
- <inject bean="PortletInvoker"/>
+ <inject bean="WSRPPortletInvoker"/>
</property>
<property name="registrationManager">
<inject bean="RegistrationManagerService"/>
@@ -67,6 +67,15 @@
</property>
</bean>
+ <bean name="WSRPPortletInvoker"
class="org.gatein.wsrp.producer.WSRPPortletInvoker">
+ <property name="next">
+ <inject bean="PortletInvoker"/>
+ </property>
+ <property name="registrationManager">
+ <inject bean="RegistrationManagerService"/>
+ </property>
+ </bean>
+
<!-- TODO: may need to write a new class for this -->
<bean name="ProducerPersistenceManagerService"
class="org.gatein.pc.portlet.impl.state.producer.PortletStatePersistenceManagerService"/>
Modified:
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-portletstate-portlet-war/WEB-INF/portlet.xml
===================================================================
---
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-portletstate-portlet-war/WEB-INF/portlet.xml 2010-09-22
13:35:10 UTC (rev 4307)
+++
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-portletstate-portlet-war/WEB-INF/portlet.xml 2010-09-22
15:01:36 UTC (rev 4308)
@@ -23,7 +23,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
<portlet-app
xmlns='http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:schemaLocation='http://java.sun.com/xml/ns/portlet/portlet-app_2_...
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd' version='2.0'>
<portlet>
- <portlet-name>Implicit Cloning Test Portlet</portlet-name>
+ <portlet-name>State Test Portlet</portlet-name>
<portlet-class>org.gatein.wsrp.portlet.StatePortlet</portlet-class>
<supports>
Added:
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/portlet.xml
===================================================================
---
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/portlet.xml
(rev 0)
+++
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/portlet.xml 2010-09-22
15:01:36 UTC (rev 4308)
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ JBoss, a division of Red Hat ~
+ ~ Copyright 2008, Red Hat Middleware, LLC, and individual ~
+ ~ contributors as indicated by the @authors tag. See the ~
+ ~ copyright.txt in the distribution for a full listing of ~
+ ~ individual contributors. ~
+ ~ ~
+ ~ This is free software; you can redistribute it and/or modify it ~
+ ~ under the terms of the GNU Lesser General Public License as ~
+ ~ published by the Free Software Foundation; either version 2.1 of ~
+ ~ the License, or (at your option) any later version. ~
+ ~ ~
+ ~ This software is distributed in the hope that it will be useful, ~
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of ~
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ~
+ ~ Lesser General Public License for more details. ~
+ ~ ~
+ ~ You should have received a copy of the GNU Lesser General Public ~
+ ~ License along with this software; if not, write to the Free ~
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ~
+ ~ 02110-1301 USA, or see the FSF site:
http://www.fsf.org. ~
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<portlet-app
xmlns='http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:schemaLocation='http://java.sun.com/xml/ns/portlet/portlet-app_2_...
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd' version='2.0'>
+ <portlet>
+ <portlet-name>State Test Portlet</portlet-name>
+
<portlet-class>org.gatein.wsrp.portlet.StateCountingPortlet</portlet-class>
+
+ <supports>
+ <mime-type>text/html</mime-type>
+ <portlet-mode>view</portlet-mode>
+ </supports>
+
+ <supported-locale>en</supported-locale>
+
+ <portlet-info>
+ <title>State Counter Portlet</title>
+ </portlet-info>
+
+ <portlet-preferences>
+ <preference>
+ <name>counter</name>
+ <value>0</value>
+ </preference>
+ </portlet-preferences>
+ </portlet>
+
+ <container-runtime-option>
+ <name>org.gatein.pc.remotable</name>
+ <value>true</value>
+ </container-runtime-option>
+</portlet-app>
Added:
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/web.xml
===================================================================
---
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/web.xml
(rev 0)
+++
components/wsrp/trunk/wsrp-producer-war/src/test/test-portlets/test-state-portlet-war/WEB-INF/web.xml 2010-09-22
15:01:36 UTC (rev 4308)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ JBoss, a division of Red Hat ~
+ ~ Copyright 2007, Red Hat Middleware, LLC, and individual ~
+ ~ contributors as indicated by the @authors tag. See the ~
+ ~ copyright.txt in the distribution for a full listing of ~
+ ~ individual contributors. ~
+ ~ ~
+ ~ This is free software; you can redistribute it and/or modify it ~
+ ~ under the terms of the GNU Lesser General Public License as ~
+ ~ published by the Free Software Foundation; either version 2.1 of ~
+ ~ the License, or (at your option) any later version. ~
+ ~ ~
+ ~ This software is distributed in the hope that it will be useful, ~
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of ~
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ~
+ ~ Lesser General Public License for more details. ~
+ ~ ~
+ ~ You should have received a copy of the GNU Lesser General Public ~
+ ~ License along with this software; if not, write to the Free ~
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ~
+ ~ 02110-1301 USA, or see the FSF site:
http://www.fsf.org. ~
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<web-app version="2.4"
+
xmlns="http://java.sun.com/xml/ns/j2ee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+</web-app>
\ No newline at end of file