From fc256f48aa7e1a378f540fc1fdbde46739ff903c Mon Sep 17 00:00:00 2001
From: rsanchez <rsanchez@curisit.net>
Date: Wed, 28 Jan 2015 23:12:42 +0000
Subject: [PATCH] #0 fix - Fixed Application modification service
---
securis/src/main/resources/META-INF/persistence.xml | 2
securis/pom.xml | 245 +++++++++++++++++-----------------
securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java | 32 +++-
securis/src/main/java/net/curisit/securis/RestServicesApplication.java | 5
securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java | 50 ++++--
securis/src/main/webapp/WEB-INF/web.xml | 6
securis/src/main/java/net/curisit/securis/db/Application.java | 1
securis/src/main/java/net/curisit/securis/db/ApplicationMetadata.java | 5
securis/src/main/java/net/curisit/securis/services/ApplicationResource.java | 29 +++
9 files changed, 215 insertions(+), 160 deletions(-)
diff --git a/securis/pom.xml b/securis/pom.xml
index 0f1f5ab..2a6d146 100644
--- a/securis/pom.xml
+++ b/securis/pom.xml
@@ -1,100 +1,101 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>net.curisit</groupId>
- <artifactId>securis-server</artifactId>
- <version>0.0.9-SNAPSHOT</version>
- <name>SeCuris</name>
- <description>CurisTEC Server Licenses</description>
- <dependencies>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.6</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-multipart-provider</artifactId>
- <version>3.0.10.Final</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jaxrs</artifactId>
- <version>3.0.10.Final</version>
- </dependency>
-<dependency>
- <groupId>org.jboss.weld.servlet</groupId>
- <artifactId>weld-servlet</artifactId>
- <version>2.2.9.Final</version>
-</dependency>
-<dependency>
- <groupId>org.jboss</groupId>
- <artifactId>jandex</artifactId>
- <version>1.2.2.Final</version>
-</dependency>
- <dependency>
- <groupId>net.curisit</groupId>
- <artifactId>commons-curis</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-entitymanager</artifactId>
- <version>4.3.6.Final</version>
- </dependency>
- <dependency>
- <groupId>net.curisit</groupId>
- <artifactId>securis-client</artifactId>
- <version>1.0.4-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- <version>4.4-beta1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpmime</artifactId>
- <version>4.4-beta1</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jackson2-provider</artifactId>
- <version>3.0.10.Final</version>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-web</artifactId>
- <version>2.1</version>
- </dependency>
- <dependency>
- <groupId>javax.enterprise</groupId>
- <artifactId>cdi-api</artifactId>
- <version>1.2</version>
- <scope>provided</scope>
-</dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-cdi</artifactId>
- <version>3.0.10.Final</version>
- </dependency>
- </dependencies>
- <build>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>net.curisit</groupId>
+ <artifactId>securis-server</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>SeCuris</name>
+ <description>CurisTEC Server Licenses</description>
+ <dependencies>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-multipart-provider</artifactId>
+ <version>3.0.10.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>3.0.10.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.weld.servlet</groupId>
+ <artifactId>weld-servlet</artifactId>
+ <version>2.2.9.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss</groupId>
+ <artifactId>jandex</artifactId>
+ <version>1.2.2.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>net.curisit</groupId>
+ <artifactId>commons-curis</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <version>4.3.6.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>net.curisit</groupId>
+ <artifactId>securis-client</artifactId>
+ <version>1.0.5-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.4-beta1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpmime</artifactId>
+ <version>4.4-beta1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jackson2-provider</artifactId>
+ <version>3.0.10.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-web</artifactId>
+ <version>2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <version>1.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-cdi</artifactId>
+ <version>3.0.10.Final</version>
+ </dependency>
+ </dependencies>
+ <build>
<plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- <plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
@@ -108,31 +109,31 @@
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</plugin>
- </plugins>
+ </plugins>
</build>
- <repositories>
- <repository>
- <id>internal</id>
- <name>CurisIT Repository</name>
- <url>http://archiva.curisit.net/archiva/repository/internal</url>
- </repository>
- <repository>
- <id>curistec</id>
- <name>CurisTec Corporate Repository</name>
- <url>http://archiva.curisit.net/archiva/repository/internal/</url>
- <layout>default</layout>
- </repository>
- <repository>
- <id>curistecSnapshot</id>
- <name>CurisTec Snapshots</name>
- <url>http://archiva.curisit.net/archiva/repository/snapshots/</url>
- <layout>default</layout>
- </repository>
- <repository>
- <id>project.local</id>
- <name>project</name>
- <url>file:/opt/repo</url>
- </repository>
- </repositories>
-
+ <repositories>
+ <repository>
+ <id>internal</id>
+ <name>CurisIT Repository</name>
+ <url>http://archiva.curisit.net/archiva/repository/internal</url>
+ </repository>
+ <repository>
+ <id>curistec</id>
+ <name>CurisTec Corporate Repository</name>
+ <url>http://archiva.curisit.net/archiva/repository/internal/</url>
+ <layout>default</layout>
+ </repository>
+ <repository>
+ <id>curistecSnapshot</id>
+ <name>CurisTec Snapshots</name>
+ <url>http://archiva.curisit.net/archiva/repository/snapshots/</url>
+ <layout>default</layout>
+ </repository>
+ <repository>
+ <id>project.local</id>
+ <name>project</name>
+ <url>file:/opt/repo</url>
+ </repository>
+ </repositories>
+
</project>
\ No newline at end of file
diff --git a/securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java b/securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java
index fc29955..9a087cf 100644
--- a/securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java
+++ b/securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java
@@ -1,5 +1,6 @@
package net.curisit.securis;
+import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.core.Context;
@@ -32,23 +33,22 @@
HttpServletRequest request;
@Context
SecurityContext bsc;
+ @Context
+ EntityManager em;
@Override
public Response toResponse(Exception e) {
+ releaseEntityManager();
if (e instanceof ForbiddenException) {
LOG.warn("Unauthorized access to {}, user: {}", request.getPathInfo(), bsc.getUserPrincipal());
- return Response.status(Status.UNAUTHORIZED)
- .header(ERROR_CODE_MESSAGE_HEADER, ErrorCodes.INVALID_CREDENTIALS)
- .header(ERROR_MESSAGE_HEADER, "Unathorized access to the application")
- .type(MediaType.APPLICATION_JSON).build();
+ return Response.status(Status.UNAUTHORIZED).header(ERROR_CODE_MESSAGE_HEADER, ErrorCodes.INVALID_CREDENTIALS)
+ .header(ERROR_MESSAGE_HEADER, "Unathorized access to the application").type(MediaType.APPLICATION_JSON).build();
}
if (e instanceof SeCurisServiceException) {
LOG.warn("SeCurisServiceException accessing to {}, user: {}", request.getPathInfo(), bsc.getUserPrincipal());
- return Response.status(DEFAULT_APP_ERROR_STATUS_CODE)
- .header(ERROR_CODE_MESSAGE_HEADER, ((SeCurisServiceException) e).getStatus())
- .header(ERROR_MESSAGE_HEADER, e.getMessage())
- .type(MediaType.APPLICATION_JSON).build();
+ return Response.status(DEFAULT_APP_ERROR_STATUS_CODE).header(ERROR_CODE_MESSAGE_HEADER, ((SeCurisServiceException) e).getStatus())
+ .header(ERROR_MESSAGE_HEADER, e.getMessage()).type(MediaType.APPLICATION_JSON).build();
}
LOG.error("Unexpected error accesing to '{}' by user: {}", request.getPathInfo(), bsc.getUserPrincipal());
@@ -56,4 +56,20 @@
LOG.error("Request url: " + request.getRequestURL(), e);
return Response.serverError().header(ERROR_MESSAGE_HEADER, "Unexpected error: " + e.toString()).type(MediaType.APPLICATION_JSON).build();
}
+
+ private void releaseEntityManager() {
+ if (em != null && em.isOpen()) {
+ LOG.debug("CLOSING EM: {}, trans: {}", em, em.isJoinedToTransaction());
+ try {
+ if (em.isJoinedToTransaction()) {
+ em.getTransaction().rollback();
+ LOG.info("ROLLBACK");
+ }
+ em.close();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ LOG.error("Error closing EM: {}, {}", em, ex);
+ }
+ }
+ }
}
diff --git a/securis/src/main/java/net/curisit/securis/RestServicesApplication.java b/securis/src/main/java/net/curisit/securis/RestServicesApplication.java
index 85fe326..c5b3b95 100644
--- a/securis/src/main/java/net/curisit/securis/RestServicesApplication.java
+++ b/securis/src/main/java/net/curisit/securis/RestServicesApplication.java
@@ -27,7 +27,6 @@
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
- // classes.add(LicenseServices.class);
classes.add(UserResource.class);
classes.add(ApiResource.class);
classes.add(LicenseResource.class);
@@ -37,9 +36,11 @@
classes.add(LicenseTypeResource.class);
classes.add(PackResource.class);
classes.add(RequestsInterceptor.class);
+ // classes.add(TransactionsInterceptor.class);
+ // classes.add(JpaJacksonProvider.class);
+ // classes.add(JacksonConfig.class);
LOG.info("JAX-RS classes for services: {}", classes);
return classes;
}
-
}
diff --git a/securis/src/main/java/net/curisit/securis/db/Application.java b/securis/src/main/java/net/curisit/securis/db/Application.java
index b70867e..6bf6ba8 100644
--- a/securis/src/main/java/net/curisit/securis/db/Application.java
+++ b/securis/src/main/java/net/curisit/securis/db/Application.java
@@ -101,7 +101,6 @@
@JsonProperty("metadata")
public Set<ApplicationMetadata> getApplicationMetadata() {
- LOG.info("Getting metadata from app: {}", metadata);
return metadata;
}
diff --git a/securis/src/main/java/net/curisit/securis/db/ApplicationMetadata.java b/securis/src/main/java/net/curisit/securis/db/ApplicationMetadata.java
index c17a3e8..273b594 100644
--- a/securis/src/main/java/net/curisit/securis/db/ApplicationMetadata.java
+++ b/securis/src/main/java/net/curisit/securis/db/ApplicationMetadata.java
@@ -20,6 +20,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Objects;
/**
* Entity implementation class for Entity: application_metadata
@@ -102,13 +103,13 @@
if (!(obj instanceof ApplicationMetadata))
return false;
ApplicationMetadata other = (ApplicationMetadata) obj;
- return key.equals(other.key) && (application == null || application.equals(other.application));
+ return Objects.equal(key, other.key) && Objects.equal(application, other.application);
}
@Override
public int hashCode() {
- return key.hashCode() + (application == null ? 0 : application.hashCode());
+ return (key == null ? 0 : key.hashCode()) + (application == null ? 0 : application.hashCode());
}
@Override
diff --git a/securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java b/securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
index 39f9c7b..595f00d 100644
--- a/securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
+++ b/securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
@@ -9,16 +9,17 @@
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Priorities;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.container.ContainerResponseContext;
-import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
import net.curisit.securis.db.User;
import net.curisit.securis.security.BasicSecurityContext;
@@ -37,8 +38,11 @@
@Provider
@Priority(Priorities.AUTHENTICATION)
-public class RequestsInterceptor implements ContainerRequestFilter, ContainerResponseFilter {
+public class RequestsInterceptor implements ContainerRequestFilter, WriterInterceptor {
private static final Logger LOG = LogManager.getLogger(RequestsInterceptor.class);
+
+ @Context
+ private HttpServletResponse servletResponse;
@Context
private HttpServletRequest servletRequest;
@@ -58,6 +62,8 @@
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
EntityManager em = emProvider.getEntityManager();
+ LOG.info("GETTING EM: {}", em);
+
ResteasyProviderFactory.pushContext(EntityManager.class, em);
ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) containerRequestContext
@@ -68,12 +74,11 @@
boolean next = checkSecurableMethods(containerRequestContext, method);
if (next) {
- prepareTransaction(containerRequestContext, method);
+ prepareTransaction(containerRequestContext, method, em);
}
}
- private void prepareTransaction(ContainerRequestContext containerRequestContext, Method method) {
- EntityManager em = ResteasyProviderFactory.getContextData(EntityManager.class);
+ private void prepareTransaction(ContainerRequestContext containerRequestContext, Method method, EntityManager em) {
if (method.isAnnotationPresent(EnsureTransaction.class)) {
LOG.debug("Beginning a new transaction");
@@ -155,17 +160,30 @@
}
@Override
- public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ context.proceed();
EntityManager em = ResteasyProviderFactory.getContextData(EntityManager.class);
-
- if (em != null && em.getTransaction().isActive()) {
- LOG.debug("Transaction is active, ready to finish it");
- if (responseContext.getStatus() == Status.OK.getStatusCode()) {
- em.getTransaction().commit();
- LOG.debug("COMMIT");
- } else {
- em.getTransaction().rollback();
- LOG.debug("ROLLBACK");
+ try {
+ if (em != null && em.getTransaction().isActive()) {
+ if (servletResponse.getStatus() == Status.OK.getStatusCode()) {
+ em.getTransaction().commit();
+ LOG.debug("COMMIT");
+ } else {
+ // This code is never executed if there is an error the
+ // filter chain is broken
+ em.getTransaction().rollback();
+ LOG.debug("ROLLBACK");
+ }
+ }
+ } finally {
+ if (em.isOpen()) {
+ LOG.info("CLOSING EM: {}, trans: {}", em, em.isJoinedToTransaction());
+ try {
+ em.close();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ LOG.error("Error closing EM: {}, {}", em, ex);
+ }
}
}
}
diff --git a/securis/src/main/java/net/curisit/securis/services/ApplicationResource.java b/securis/src/main/java/net/curisit/securis/services/ApplicationResource.java
index 872dfa6..e103f1a 100644
--- a/securis/src/main/java/net/curisit/securis/services/ApplicationResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/ApplicationResource.java
@@ -1,7 +1,9 @@
package net.curisit.securis.services;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.annotation.security.RolesAllowed;
@@ -177,19 +179,24 @@
currentapp.setDescription(app.getDescription());
Set<ApplicationMetadata> newMD = app.getApplicationMetadata();
- for (ApplicationMetadata currentMd : currentapp.getApplicationMetadata()) {
- if (newMD == null || !newMD.contains(currentMd)) {
+ Set<ApplicationMetadata> oldMD = currentapp.getApplicationMetadata();
+ Map<String, ApplicationMetadata> directOldMD = getMapMD(oldMD);
+ Map<String, ApplicationMetadata> directNewMD = getMapMD(newMD);
+ for (ApplicationMetadata currentMd : oldMD) {
+ if (newMD == null || !directNewMD.containsKey(currentMd.getKey())) {
em.remove(currentMd);
}
}
if (newMD != null) {
- Set<ApplicationMetadata> oldMD = currentapp.getApplicationMetadata();
for (ApplicationMetadata md : newMD) {
- if (oldMD.contains(md)) {
- em.merge(md);
+ if (directOldMD.containsKey(md.getKey())) {
+ ApplicationMetadata amd = directOldMD.get(md.getKey());
+ amd.setValue(md.getValue());
+ amd.setMandatory(md.isMandatory());
+ em.merge(amd);
} else {
- md.setApplication(app);
+ md.setApplication(currentapp);
if (md.getCreationTimestamp() == null) {
md.setCreationTimestamp(app.getCreationTimestamp());
}
@@ -202,6 +209,16 @@
return Response.ok(currentapp).build();
}
+ private Map<String, ApplicationMetadata> getMapMD(Set<ApplicationMetadata> amd) {
+ Map<String, ApplicationMetadata> map = new HashMap<String, ApplicationMetadata>();
+ if (amd != null) {
+ for (ApplicationMetadata applicationMetadata : amd) {
+ map.put(applicationMetadata.getKey(), applicationMetadata);
+ }
+ }
+ return map;
+ }
+
@DELETE
@Path("/{appid}")
@EnsureTransaction
diff --git a/securis/src/main/resources/META-INF/persistence.xml b/securis/src/main/resources/META-INF/persistence.xml
index 5edb044..638909f 100644
--- a/securis/src/main/resources/META-INF/persistence.xml
+++ b/securis/src/main/resources/META-INF/persistence.xml
@@ -2,7 +2,7 @@
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
- <persistence-unit name="localdb" >
+ <persistence-unit name="localdb" transaction-type="RESOURCE_LOCAL">
<description>SeCuris LocalDB</description>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:comp/env/SeCurisDS</non-jta-data-source>
diff --git a/securis/src/main/webapp/WEB-INF/web.xml b/securis/src/main/webapp/WEB-INF/web.xml
index 3456bee..97d8d7e 100644
--- a/securis/src/main/webapp/WEB-INF/web.xml
+++ b/securis/src/main/webapp/WEB-INF/web.xml
@@ -40,8 +40,7 @@
<param-name>resteasy.injector.factory</param-name>
<param-value>org.jboss.resteasy.cdi.CdiInjectorFactory</param-value>
</context-param>
-
-
+
<filter>
<filter-name>Resteasy</filter-name>
<filter-class>
@@ -58,6 +57,9 @@
<url-pattern>/*</url-pattern>
</filter-mapping>
+
+
+
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
--
Gitblit v1.3.2