You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by oc...@apache.org on 2008/04/30 04:18:44 UTC
svn commit: r652230 - in /archiva/trunk/archiva-modules:
archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/
archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/
archiva-base/archiva-repository-l...
Author: oching
Date: Tue Apr 29 19:18:43 2008
New Revision: 652230
URL: http://svn.apache.org/viewvc?rev=652230&view=rev
Log:
[MRM-773]
-added the servlet that would handle the rss feed requests
-created tests for the servlet
-removed thrown exception in getSpringConfigLocation() that is being overridden in PlexusInStringTestCase
-updated jsps to the new rss feed urls
Added:
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/ArtifactDAOStub.java
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/rss/
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/rss/RssFeedServletTest.xml
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml
Modified:
archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java
archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/MavenProxyPropertyLoaderTest.java
archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java
archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/AbstractRepositoryLayerTestCase.java
archiva/trunk/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactVersionsConstraint.java
archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/RssFeedGenerator.java
archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/AbstractArtifactsRssFeedProcessor.java
archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java
archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessor.java
archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessorTest.java
archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessorTest.java
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/pom.xml
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/AbstractRepositoryServletTestCase.java
Modified: archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java Tue Apr 29 19:18:43 2008
@@ -42,7 +42,6 @@
* @see org.codehaus.plexus.spring.PlexusInSpringTestCase#getSpringConfigLocation()
*/
protected String getSpringConfigLocation()
- throws Exception
{
return "org/apache/maven/archiva/configuration/spring-context.xml";
}
Modified: archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/MavenProxyPropertyLoaderTest.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/MavenProxyPropertyLoaderTest.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/MavenProxyPropertyLoaderTest.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/MavenProxyPropertyLoaderTest.java Tue Apr 29 19:18:43 2008
@@ -40,7 +40,6 @@
* @see org.codehaus.plexus.spring.PlexusInSpringTestCase#getSpringConfigLocation()
*/
protected String getSpringConfigLocation()
- throws Exception
{
return "org/apache/maven/archiva/configuration/spring-context.xml";
}
Modified: archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java Tue Apr 29 19:18:43 2008
@@ -400,7 +400,6 @@
*/
@Override
protected String getSpringConfigLocation()
- throws Exception
{
return "org/apache/maven/archiva/proxy/spring-context.xml";
}
Modified: archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/AbstractRepositoryLayerTestCase.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/AbstractRepositoryLayerTestCase.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/AbstractRepositoryLayerTestCase.java (original)
+++ archiva/trunk/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/AbstractRepositoryLayerTestCase.java Tue Apr 29 19:18:43 2008
@@ -40,7 +40,6 @@
*/
@Override
protected String getSpringConfigLocation()
- throws Exception
{
return "org/apache/maven/archiva/repository/spring-context.xml";
}
Modified: archiva/trunk/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactVersionsConstraint.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactVersionsConstraint.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactVersionsConstraint.java (original)
+++ archiva/trunk/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactVersionsConstraint.java Tue Apr 29 19:18:43 2008
@@ -31,13 +31,18 @@
extends AbstractDeclarativeConstraint
implements Constraint
{
- private String whereClause;
+ private String whereClause = "";
private String sortColumn = "repositoryId";
public ArtifactVersionsConstraint( String repoId, String groupId, String artifactId )
{
- whereClause = "repositoryId == repoId && groupId == groupId && artifactId == artifactId";
+ if( repoId != null )
+ {
+ whereClause = "repositoryId == repoId && ";
+ }
+
+ whereClause = whereClause + "groupId == groupId && artifactId == artifactId";
declParams = new String[] { "String repoId", "String groupId", "String artifactId" };
params = new Object[] { repoId, groupId, artifactId };
}
@@ -47,7 +52,7 @@
this( repoId, groupId, artifactId );
this.sortColumn = sortColumn;
}
-
+
public String getSortColumn()
{
return sortColumn;
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/RssFeedGenerator.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/RssFeedGenerator.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/RssFeedGenerator.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/RssFeedGenerator.java Tue Apr 29 19:18:43 2008
@@ -54,33 +54,26 @@
private String DEFAULT_LINK = "http://localhost:8080/archiva/rss/";
public SyndFeed generateFeed( String title, String description, List<RssFeedEntry> dataEntries,
- String outputFilename )
+ String queryString )
{
- SyndFeed feed = null;
- List<SyndEntry> existingEntries = null;
-
- feed = new SyndFeedImpl();
+ SyndFeed feed = new SyndFeedImpl();
feed.setTitle( title );
- feed.setLink( DEFAULT_LINK + outputFilename );
+ feed.setLink( DEFAULT_LINK + queryString );
feed.setDescription( description );
feed.setLanguage( DEFAULT_LANGUAGE );
feed.setPublishedDate( Calendar.getInstance().getTime() );
feed.setFeedType( DEFAULT_FEEDTYPE );
- feed.setEntries( getEntries( dataEntries, existingEntries ) );
+ feed.setEntries( getEntries( dataEntries ) );
log.debug( "Finished generating the feed \'" + title + "\'." );
return feed;
}
- private List<SyndEntry> getEntries( List<RssFeedEntry> dataEntries, List<SyndEntry> existingEntries )
+ private List<SyndEntry> getEntries( List<RssFeedEntry> dataEntries )
{
- List<SyndEntry> entries = existingEntries;
- if ( entries == null )
- {
- entries = new ArrayList<SyndEntry>();
- }
+ List<SyndEntry> entries = new ArrayList<SyndEntry>();
SyndEntry entry;
SyndContent description;
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/AbstractArtifactsRssFeedProcessor.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/AbstractArtifactsRssFeedProcessor.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/AbstractArtifactsRssFeedProcessor.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/AbstractArtifactsRssFeedProcessor.java Tue Apr 29 19:18:43 2008
@@ -56,17 +56,18 @@
entry.setDescription( description );
entries.add( entry );
}
-
- String repoId = artifact.getModel().getRepositoryId();
+
if ( !isRepoLevel )
{
entry =
new RssFeedEntry( getTitle() + "\'" + artifact.getGroupId() + ":" + artifact.getArtifactId() +
"\'" + " as of " + new Date( whenGathered ) );
- description = getDescription() + "\'" + repoId + "\'" + ": \n" + artifact.toString() + " | ";
+ description = getDescription() + "\'" + artifact.getGroupId() + ":" + artifact.getArtifactId() +
+ "\'" + ": \n" + artifact.toString() + " | ";
}
else
{
+ String repoId = artifact.getModel().getRepositoryId();
entry = new RssFeedEntry( getTitle() + "\'" + repoId + "\'" + " as of " + new Date( whenGathered ) );
description = getDescription() + "\'" + repoId + "\'" + ": \n" + artifact.toString() + " | ";
}
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java Tue Apr 29 19:18:43 2008
@@ -48,7 +48,7 @@
{
private String title = "New Artifacts in Repository ";
- private String desc = "New Versions of Artifact ";
+ private String desc = "These are the new artifacts found in the repository ";
/**
* @plexus.requirement
@@ -89,7 +89,7 @@
List<RssFeedEntry> entries = processData( artifacts, true );
return generator.generateFeed( getTitle() + "\'" + repoId + "\'", "New artifacts found in repository " +
- "\'" + repoId + "\'" + " during repository scan.", entries, "new_artifacts_" + repoId + ".xml" );
+ "\'" + repoId + "\'" + " during repository scan.", entries, "rss_feeds?repoId=" + repoId );
}
catch ( ArchivaDatabaseException ae )
{
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessor.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessor.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessor.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessor.java Tue Apr 29 19:18:43 2008
@@ -49,7 +49,7 @@
{
private String title = "New Versions of Artifact ";
- private String desc = "These are the new artifacts found in the repository ";
+ private String desc = "These are the new versions of artifact ";
/**
* @plexus.requirement
@@ -71,8 +71,8 @@
String repoId = reqParams.get( RssFeedProcessor.KEY_REPO_ID );
String groupId = reqParams.get( RssFeedProcessor.KEY_GROUP_ID );
String artifactId = reqParams.get( RssFeedProcessor.KEY_ARTIFACT_ID );
-
- if ( repoId != null && groupId != null && artifactId != null )
+
+ if ( groupId != null && artifactId != null )
{
return processNewVersionsOfArtifact( repoId, groupId, artifactId );
}
@@ -87,12 +87,14 @@
Constraint artifactVersions = new ArtifactVersionsConstraint( repoId, groupId, artifactId, "whenGathered" );
List<ArchivaArtifact> artifacts = artifactDAO.queryArtifacts( artifactVersions );
+ log.info( "Queried artifacts size :: " + artifacts.size() );
+
List<RssFeedEntry> entries = processData( artifacts, false );
String key = groupId + ":" + artifactId;
return generator.generateFeed( getTitle() + "\'" + key + "\'", "New versions of artifact " + "\'" + key +
"\' found in repository " + "\'" + repoId + "\'" + " during repository scan.", entries,
- "new_versions_" + key + ".xml" );
+ "rss_feeds?groupId=" + groupId + "&artifactId=" + artifactId );
}
catch ( ObjectNotFoundException oe )
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessorTest.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessorTest.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessorTest.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessorTest.java Tue Apr 29 19:18:43 2008
@@ -116,7 +116,7 @@
SyndFeed feed = newArtifactsProcessor.process( reqParams );
assertTrue( feed.getTitle().equals( "New Artifacts in Repository 'test-repo'" ) );
- assertTrue( feed.getLink().equals( "http://localhost:8080/archiva/rss/new_artifacts_test-repo.xml" ) );
+ assertTrue( feed.getLink().equals( "http://localhost:8080/archiva/rss/rss_feeds?repoId=test-repo" ) );
assertTrue( feed.getDescription().equals(
"New artifacts found in repository 'test-repo' during repository scan." ) );
assertTrue( feed.getLanguage().equals( "en-us" ) );
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessorTest.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessorTest.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessorTest.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessorTest.java Tue Apr 29 19:18:43 2008
@@ -93,7 +93,7 @@
SyndFeed feed = newVersionsProcessor.process( reqParams );
assertEquals( "New Versions of Artifact 'org.apache.archiva:artifact-two'", feed.getTitle() );
- assertEquals( "http://localhost:8080/archiva/rss/new_versions_org.apache.archiva:artifact-two.xml",
+ assertEquals( "http://localhost:8080/archiva/rss/rss_feeds?groupId=org.apache.archiva&artifactId=artifact-two",
feed.getLink() );
assertEquals(
"New versions of artifact 'org.apache.archiva:artifact-two' found in repository 'test-repo' during repository scan.",
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/pom.xml
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/pom.xml?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/pom.xml (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/pom.xml Tue Apr 29 19:18:43 2008
@@ -81,6 +81,10 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.apache.archiva</groupId>
+ <artifactId>archiva-rss</artifactId>
+ </dependency>
+ <dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
Added: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java?rev=652230&view=auto
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java (added)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java Tue Apr 29 19:18:43 2008
@@ -0,0 +1,137 @@
+package org.apache.maven.archiva.web.rss;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.archiva.rss.RssFeedGenerator;
+import org.apache.archiva.rss.processor.RssFeedProcessor;
+import org.codehaus.plexus.spring.PlexusToSpringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import com.sun.syndication.feed.synd.SyndFeed;
+import com.sun.syndication.io.FeedException;
+import com.sun.syndication.io.SyndFeedOutput;
+
+/**
+ * Servlet for handling rss feed requests.
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version
+ */
+public class RssFeedServlet
+ extends HttpServlet
+{
+ public static final String MIME_TYPE = "application/xml; charset=UTF-8";
+
+ private static final String COULD_NOT_GENERATE_FEED_ERROR = "Could not generate feed";
+
+ private Logger log = LoggerFactory.getLogger( RssFeedGenerator.class );
+
+ private RssFeedProcessor processor;
+
+ private WebApplicationContext wac;
+
+ public void init( javax.servlet.ServletConfig servletConfig )
+ throws ServletException
+ {
+ super.init( servletConfig );
+ wac = WebApplicationContextUtils.getRequiredWebApplicationContext( servletConfig.getServletContext() );
+ }
+
+ public void doGet( HttpServletRequest req, HttpServletResponse res )
+ throws ServletException, IOException
+ {
+ log.info( "Request URL: " + req.getRequestURL() );
+ try
+ {
+ Map<String, String> map = new HashMap<String, String>();
+ SyndFeed feed = null;
+
+ if ( req.getParameter( "repoId" ) != null )
+ {
+ if ( isAuthorized() )
+ {
+ // new artifacts in repo feed request
+ processor =
+ (RssFeedProcessor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+ RssFeedProcessor.class.getName(),
+ "new-artifacts" ) );
+ map.put( RssFeedProcessor.KEY_REPO_ID, req.getParameter( "repoId" ) );
+ }
+ else
+ {
+ res.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Request is not authorized." );
+ return;
+ }
+ }
+ else if ( ( req.getParameter( "groupId" ) != null ) && ( req.getParameter( "artifactId" ) != null ) )
+ {
+ if ( isAuthorized() )
+ {
+ // new versions of artifact feed request
+ processor =
+ (RssFeedProcessor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+ RssFeedProcessor.class.getName(),
+ "new-versions" ) );
+ map.put( RssFeedProcessor.KEY_GROUP_ID, req.getParameter( "groupId" ) );
+ map.put( RssFeedProcessor.KEY_ARTIFACT_ID, req.getParameter( "artifactId" ) );
+ }
+ else
+ {
+ res.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Request is not authorized." );
+ return;
+ }
+ }
+ else
+ {
+ res.sendError( HttpServletResponse.SC_BAD_REQUEST, "Required fields not found in request." );
+ return;
+ }
+
+ feed = processor.process( map );
+ res.setContentType( MIME_TYPE );
+
+ SyndFeedOutput output = new SyndFeedOutput();
+ output.output( feed, res.getWriter() );
+ }
+ catch ( FeedException ex )
+ {
+ String msg = COULD_NOT_GENERATE_FEED_ERROR;
+ log.error( msg, ex );
+ res.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg );
+ }
+ }
+
+ private boolean isAuthorized()
+ {
+ return true;
+ }
+}
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp Tue Apr 29 19:18:43 2008
@@ -88,7 +88,7 @@
</ww:a>
</redback:ifAnyAuthorized>
<c:url var="rssFeedIconUrl" value="/images/icons/rss-feed.png"/>
- <a href="/archiva/rss/new_artifacts_${repository.id}.xml">
+ <a href="/archiva/rss/rss_feeds?repoId=${repository.id}">
<img src="${rssFeedIconUrl}" />
</a>
</div>
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp Tue Apr 29 19:18:43 2008
@@ -72,7 +72,7 @@
</c:set>
<li>
<a href="${url}">${artifactId}/</a>
- <a href="/archiva/rss/new_versions_${groupId}:${artifactId}.xml">
+ <a href="/archiva/rss/rss_feeds?groupId=${groupId}&artifactId=${artifactId}">
<img src="${rssFeedIconUrl}" />
</a>
</li>
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml Tue Apr 29 19:18:43 2008
@@ -85,7 +85,17 @@
<!-- Loading this on startup so as to take advantage of configuration listeners -->
<load-on-startup>1</load-on-startup>
</servlet>
-
+
+ <servlet>
+ <servlet-name>RssFeedServlet</servlet-name>
+ <servlet-class>org.apache.maven.archiva.web.rss.RssFeedServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>RssFeedServlet</servlet-name>
+ <url-pattern>/rss/*</url-pattern>
+ </servlet-mapping>
+
<servlet-mapping>
<servlet-name>RepositoryServlet</servlet-name>
<url-pattern>/repository/*</url-pattern>
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/AbstractRepositoryServletTestCase.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/AbstractRepositoryServletTestCase.java?rev=652230&r1=652229&r2=652230&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/AbstractRepositoryServletTestCase.java (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/AbstractRepositoryServletTestCase.java Tue Apr 29 19:18:43 2008
@@ -172,7 +172,6 @@
@Override
protected String getPlexusConfigLocation()
- throws Exception
{
return "org/apache/maven/archiva/web/repository/RepositoryServletTest.xml";
}
Added: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/ArtifactDAOStub.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/ArtifactDAOStub.java?rev=652230&view=auto
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/ArtifactDAOStub.java (added)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/ArtifactDAOStub.java Tue Apr 29 19:18:43 2008
@@ -0,0 +1,123 @@
+package org.apache.maven.archiva.web.rss;
+
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.database.ArtifactDAO;
+import org.apache.maven.archiva.database.Constraint;
+import org.apache.maven.archiva.database.ObjectNotFoundException;
+import org.apache.maven.archiva.model.ArchivaArtifact;
+
+/**
+ * Stub used for RssFeedServlet unit test.
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version
+ */
+public class ArtifactDAOStub
+ implements ArtifactDAO
+{
+
+ public ArchivaArtifact createArtifact( String groupId, String artifactId, String version, String classifier,
+ String type )
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void deleteArtifact( ArchivaArtifact artifact )
+ throws ArchivaDatabaseException
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public ArchivaArtifact getArtifact( String groupId, String artifactId, String version, String classifier,
+ String type )
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public List queryArtifacts( Constraint constraint )
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ List<ArchivaArtifact> artifacts = new ArrayList<ArchivaArtifact>();
+
+ Date whenGathered = Calendar.getInstance().getTime();
+ whenGathered.setTime( 123456789 );
+
+ ArchivaArtifact artifact = new ArchivaArtifact( "org.apache.archiva", "artifact-one", "1.0", "", "jar" );
+ artifact.getModel().setRepositoryId( "test-repo" );
+ artifact.getModel().setWhenGathered( whenGathered );
+ artifacts.add( artifact );
+
+ artifact = new ArchivaArtifact( "org.apache.archiva", "artifact-one", "1.1", "", "jar" );
+ artifact.getModel().setRepositoryId( "test-repo" );
+ artifact.getModel().setWhenGathered( whenGathered );
+ artifacts.add( artifact );
+
+ artifact = new ArchivaArtifact( "org.apache.archiva", "artifact-one", "2.0", "", "jar" );
+ artifact.getModel().setRepositoryId( "test-repo" );
+ artifact.getModel().setWhenGathered( whenGathered );
+ artifacts.add( artifact );
+
+ artifact = new ArchivaArtifact( "org.apache.archiva", "artifact-two", "1.0.1", "", "jar" );
+ artifact.getModel().setRepositoryId( "test-repo" );
+ artifact.getModel().setWhenGathered( whenGathered );
+ artifacts.add( artifact );
+
+ artifact = new ArchivaArtifact( "org.apache.archiva", "artifact-two", "1.0.2", "", "jar" );
+ artifact.getModel().setRepositoryId( "test-repo" );
+ artifact.getModel().setWhenGathered( whenGathered );
+ artifacts.add( artifact );
+
+ artifact = new ArchivaArtifact( "org.apache.archiva", "artifact-two", "1.0.3-SNAPSHOT", "", "jar" );
+ artifact.getModel().setRepositoryId( "test-repo" );
+ artifact.getModel().setWhenGathered( whenGathered );
+ artifacts.add( artifact );
+
+ artifact = new ArchivaArtifact( "org.apache.archiva", "artifact-three", "2.0-SNAPSHOT", "", "jar" );
+ artifact.getModel().setRepositoryId( "test-repo" );
+ artifact.getModel().setWhenGathered( whenGathered );
+ artifacts.add( artifact );
+
+ artifact = new ArchivaArtifact( "org.apache.archiva", "artifact-four", "1.1-beta-2", "", "jar" );
+ artifact.getModel().setRepositoryId( "test-repo" );
+ artifact.getModel().setWhenGathered( whenGathered );
+ artifacts.add( artifact );
+
+ return artifacts;
+ }
+
+ public ArchivaArtifact saveArtifact( ArchivaArtifact artifact )
+ throws ArchivaDatabaseException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
Added: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java?rev=652230&view=auto
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java (added)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java Tue Apr 29 19:18:43 2008
@@ -0,0 +1,139 @@
+package org.apache.maven.archiva.web.rss;
+
+/*
+ * 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.
+ */
+
+import javax.servlet.http.HttpServletResponse;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import com.meterware.httpunit.HttpException;
+import com.meterware.httpunit.WebResponse;
+import com.meterware.servletunit.ServletRunner;
+import com.meterware.servletunit.ServletUnitClient;
+
+/**
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version
+ */
+public class RssFeedServletTest
+ extends PlexusInSpringTestCase
+{
+ private ServletRunner sr;
+
+ private ServletUnitClient client;
+
+ public void setUp()
+ throws Exception
+ {
+ sr = new ServletRunner( getTestFile( "src/test/webapp/WEB-INF/feedServletTest-web.xml" ) );
+ client = sr.newClient();
+ }
+
+ public void testRetrieveServlet()
+ throws Exception
+ {
+ RssFeedServlet servlet =
+ (RssFeedServlet) client.newInvocation( "http://localhost/rss/rss_feeds?repoId=test-repo" ).getServlet();
+ assertNotNull( servlet );
+ }
+
+ public void testRequestNewArtifactsInRepo()
+ throws Exception
+ {
+ RssFeedServlet servlet =
+ (RssFeedServlet) client.newInvocation( "http://localhost/rss/rss_feeds?repoId=test-repo" ).getServlet();
+ assertNotNull( servlet );
+
+ WebResponse response = client.getResponse( "http://localhost/rss/rss_feeds?repoId=test-repo" );
+ assertEquals( RssFeedServlet.MIME_TYPE, response.getHeaderField( "CONTENT-TYPE" ) );
+
+ assertNotNull( "Should have recieved a response", response );
+ assertEquals( "Should have been an OK response code.", HttpServletResponse.SC_OK, response.getResponseCode() );
+ }
+
+ public void testRequestNewVersionsOfArtifact()
+ throws Exception
+ {
+ RssFeedServlet servlet =
+ (RssFeedServlet) client.newInvocation(
+ "http://localhost/rss/rss_feeds?groupId=org.apache.archiva&artifactId=artifact-two" ).getServlet();
+ assertNotNull( servlet );
+
+ WebResponse response = client.getResponse( "http://localhost/rss/rss_feeds?groupId=org.apache.archiva&artifactId=artifact-two" );
+ assertEquals( RssFeedServlet.MIME_TYPE, response.getHeaderField( "CONTENT-TYPE" ) );
+
+ assertNotNull( "Should have recieved a response", response );
+ assertEquals( "Should have been an OK response code.", HttpServletResponse.SC_OK, response.getResponseCode() );
+ }
+
+ public void testInvalidRequest()
+ throws Exception
+ {
+ RssFeedServlet servlet =
+ (RssFeedServlet) client.newInvocation(
+ "http://localhost/rss/rss_feeds?invalid_param=xxx" ).getServlet();
+ assertNotNull( servlet );
+
+ try
+ {
+ WebResponse response = client.getResponse( "http://localhost/rss/rss_feeds?invalid_param=xxx" );
+ }
+ catch ( HttpException he )
+ {
+ assertEquals( "Should have been a bad request response code.", HttpServletResponse.SC_BAD_REQUEST, he.getResponseCode() );
+ }
+ }
+
+ public void testUnAuthorizedRequest()
+ throws Exception
+ {
+ RssFeedServlet servlet =
+ (RssFeedServlet) client.newInvocation(
+ "http://localhost/rss/rss_feeds" ).getServlet();
+ assertNotNull( servlet );
+
+ //WebResponse response = client.getResponse( "http://localhost/rss/rss_feeds" );
+ //assertNotNull( "Should have recieved a response", response );
+ //assertEquals( "Should have been a bad request response code.", HttpServletResponse.SC_BAD_REQUEST, response.getResponseCode() );
+ }
+
+ @Override
+ protected String getPlexusConfigLocation()
+ {
+ return "org/apache/maven/archiva/web/rss/RssFeedServletTest.xml";
+ }
+
+ @Override
+ protected void tearDown()
+ throws Exception
+ {
+ if ( client != null )
+ {
+ client.clearContents();
+ }
+
+ if ( sr != null )
+ {
+ sr.shutDown();
+ }
+
+ super.tearDown();
+ }
+
+}
Added: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/rss/RssFeedServletTest.xml
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/rss/RssFeedServletTest.xml?rev=652230&view=auto
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/rss/RssFeedServletTest.xml (added)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/rss/RssFeedServletTest.xml Tue Apr 29 19:18:43 2008
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ ~ 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.
+ -->
+
+<plexus>
+ <components>
+ <!--
+ | Logger manager
+ -->
+ <component>
+ <role>org.codehaus.plexus.logging.LoggerManager</role>
+ <implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
+ <lifecycle-handler>basic</lifecycle-handler>
+ </component>
+
+ <component>
+ <role>org.apache.maven.archiva.database.ArtifactDAO</role>
+ <role-hint>jdo</role-hint>
+ <implementation>org.apache.maven.archiva.web.rss.ArtifactDAOStub</implementation>
+ </component>
+ </components>
+</plexus>
Added: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml?rev=652230&view=auto
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml (added)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml Tue Apr 29 19:18:43 2008
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ ~ 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.
+ -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"
+ 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">
+
+ <display-name>Apache Archiva</display-name>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>RssFeedServlet</servlet-name>
+ <servlet-class>org.apache.maven.archiva.web.rss.RssFeedServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>RssFeedServlet</servlet-name>
+ <url-pattern>/rss/*</url-pattern>
+ </servlet-mapping>
+
+ <context-param>
+ <param-name>contextClass</param-name>
+ <param-value>org.codehaus.plexus.spring.PlexusWebApplicationContext</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>
+ classpath*:/META-INF/plexus/components.xml
+ classpath*:/META-INF/spring-context.xml
+ target/test-classes/org/apache/maven/archiva/web/rss/RssFeedServletTest.xml
+ </param-value>
+ </context-param>
+
+</web-app>