diff --git a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/GDataRequest.java b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/GDataRequest.java
index e8d1d50860e..addd86e031e 100644
--- a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/GDataRequest.java
+++ b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/GDataRequest.java
@@ -58,6 +58,7 @@ public class GDataRequest {
private static final String RESPONSE_FORMAT_PARAMETER = "alt";
private static final String RESPONSE_FORMAT_PARAMETER_RSS = "rss";
+ private static final String RESPONSE_FORMAT_PARAMETER_HTML = "html";
private static final int DEFAULT_ITEMS_PER_PAGE = 25;
@@ -276,6 +277,8 @@ public class GDataRequest {
return;
if (formatParameter.equalsIgnoreCase(RESPONSE_FORMAT_PARAMETER_RSS))
this.responseFormat = OutputFormat.RSS;
+ if (formatParameter.equalsIgnoreCase(RESPONSE_FORMAT_PARAMETER_HTML))
+ this.responseFormat = OutputFormat.HTML;
}
@@ -439,7 +442,11 @@ public class GDataRequest {
/**
* Output format RSS
*/
- RSS
+ RSS,
+ /**
+ * Output format html if user defined xsl style sheet is present
+ */
+ HTML
}
/**
diff --git a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/GDataResponse.java b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/GDataResponse.java
index 8d6c422baf7..384f1be42dc 100644
--- a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/GDataResponse.java
+++ b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/GDataResponse.java
@@ -17,14 +17,23 @@
package org.apache.lucene.gdata.server;
import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
import java.io.Writer;
import java.util.Date;
import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.gdata.server.GDataRequest.OutputFormat;
+import org.apache.lucene.gdata.server.registry.ProvidedService;
import org.apache.lucene.gdata.utils.DateFormater;
import com.google.gdata.data.BaseEntry;
@@ -104,7 +113,7 @@ public class GDataResponse {
public static final int UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED;
- private static final Log LOG = LogFactory.getLog(GDataResponse.class);
+ static final Log LOG = LogFactory.getLog(GDataResponse.class);
private int error;
private boolean isError = false;
@@ -119,11 +128,6 @@ public class GDataResponse {
protected static final String XMLMIME_RSS = "text/xml";
- private static final String DEFAUL_NAMESPACE_URI = "http://www.w3.org/2005/Atom";
-
- private static final Namespace DEFAULT_NAMESPACE = new Namespace("",
- DEFAUL_NAMESPACE_URI);
-
private static final String HEADER_LASTMODIFIED = "Last-Modified";
/**
@@ -188,33 +192,26 @@ public class GDataResponse {
*
* @param feed -
* the feed to respond to the client
- * @param profile -
- * the extension profile for the feed to write
+ * @param service - the service to render the feed
+ *
* @throws IOException -
* if an I/O exception occurs, often caused by an already
* closed Writer or OutputStream
*
*/
- public void sendResponse(BaseFeed feed, ExtensionProfile profile)
+ public void sendResponse(final BaseFeed feed, final ProvidedService service)
throws IOException {
if (feed == null)
throw new IllegalArgumentException("feed must not be null");
- if (profile == null)
+ if (service == null)
throw new IllegalArgumentException(
- "extension profile must not be null");
+ "provided service must not be null");
DateTime time = feed.getUpdated();
if (time != null)
setLastModifiedHeader(time.getValue());
- XmlWriter writer = createWriter();
-
- if (this.outputFormat.equals(OutputFormat.ATOM)) {
- this.response.setContentType(XMLMIME_ATOM);
- feed.generateAtom(writer, profile);
- } else {
- this.response.setContentType(XMLMIME_RSS);
- feed.generateRss(writer, profile);
- }
- writer.close();
+ FormatWriter writer = FormatWriter.getFormatWriter(this,service);
+ writer.generateOutputFormat(feed,this.response);
+
}
/**
@@ -226,38 +223,27 @@ public class GDataResponse {
*
* @param entry -
* the modified / created entry to send
- * @param profile -
- * the entries extension profile
+ * @param service - the service to render the feed
* @throws IOException -
* if an I/O exception occurs, often caused by an already
* closed Writer or OutputStream
*/
- public void sendResponse(BaseEntry entry, ExtensionProfile profile)
+ public void sendResponse(BaseEntry entry, ProvidedService service)
throws IOException {
if (entry == null)
throw new IllegalArgumentException("entry must not be null");
- if (profile == null)
+ if (service == null)
throw new IllegalArgumentException(
- "extension profile must not be null");
+ "service must not be null");
DateTime time = entry.getUpdated();
if (time != null)
setLastModifiedHeader(time.getValue());
- XmlWriter writer = createWriter();
- if (this.outputFormat.equals(OutputFormat.ATOM))
- entry.generateAtom(writer, profile);
- else
- entry.generateRss(writer, profile);
- writer.close();
+ FormatWriter writer = FormatWriter.getFormatWriter(this,service);
+ writer.generateOutputFormat(entry,this.response);
+
}
- private XmlWriter createWriter() throws IOException {
- XmlWriter writer = new XmlWriter(getWriter(), this.encoding);
- // set the default namespace to Atom if Atom is the response format
- if (this.outputFormat.equals(OutputFormat.ATOM))
- writer.setDefaultNamespace(DEFAULT_NAMESPACE);
- return writer;
- }
/**
* This encoding will be used to encode the xml representation of feed or
@@ -326,4 +312,138 @@ public class GDataResponse {
this.response.setStatus(status);
}
+ private static abstract class FormatWriter{
+
+ static FormatWriter getFormatWriter(final GDataResponse response, final ProvidedService service ){
+ OutputFormat format = response.getOutputFormat();
+ if(format == OutputFormat.HTML){
+ return new HTMLFormatWriter(service);
+ }
+ return new SyndicateFormatWriter(service,format,response.getEncoding());
+ }
+
+ abstract void generateOutputFormat(final BaseFeed feed, final HttpServletResponse response) throws IOException;
+ abstract void generateOutputFormat(final BaseEntry entry, final HttpServletResponse response) throws IOException;
+
+ private static class HTMLFormatWriter extends FormatWriter{
+ private static final String CONTENT_TYPE = "text/html";
+ private final ProvidedService service;
+
+ HTMLFormatWriter(final ProvidedService service){
+ this.service = service;
+ }
+ @Override
+ void generateOutputFormat(BaseFeed feed, final HttpServletResponse response) throws IOException {
+ Templates template = this.service.getTransformTemplate();
+ response.setContentType(CONTENT_TYPE);
+ if(template == null){
+ sendNotAvailable(response);
+ return;
+ }
+ StringWriter writer = new StringWriter();
+ XmlWriter xmlWriter = new XmlWriter(writer);
+ feed.generateAtom(xmlWriter,this.service.getExtensionProfile());
+ try {
+ writeHtml(template,response.getWriter(),writer);
+ } catch (TransformerException e) {
+ LOG.error("Can not transform feed for service "+this.service.getName(),e);
+ sendNotAvailable(response);
+
+ }
+ }
+
+ @Override
+ void generateOutputFormat(BaseEntry entry, final HttpServletResponse response) throws IOException{
+ Templates template = this.service.getTransformTemplate();
+ response.setContentType(CONTENT_TYPE);
+ if(template == null){
+ sendNotAvailable(response);
+ return;
+ }
+ StringWriter writer = new StringWriter();
+ XmlWriter xmlWriter = new XmlWriter(writer);
+ entry.generateAtom(xmlWriter,this.service.getExtensionProfile());
+ try {
+ writeHtml(template,response.getWriter(),writer);
+ } catch (TransformerException e) {
+ LOG.error("Can not transform feed for service "+this.service.getName(),e);
+ sendNotAvailable(response);
+
+ }
+
+ }
+
+ private void writeHtml(final Templates template, final Writer writer, final StringWriter source ) throws TransformerException{
+ Transformer transformer = template.newTransformer();
+ Source tranformSource = new StreamSource(new StringReader(source.toString()));
+ transformer.transform(tranformSource,new StreamResult(writer));
+ }
+
+ private void sendNotAvailable(final HttpServletResponse response) throws IOException{
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "No transformation stylesheet available");
+ }
+
+ }
+ private static class SyndicateFormatWriter extends FormatWriter{
+ private static final String DEFAUL_NAMESPACE_URI = "http://www.w3.org/2005/Atom";
+
+ private static final Namespace DEFAULT_NAMESPACE = new Namespace("",
+ DEFAUL_NAMESPACE_URI);
+ private final ProvidedService service;
+ private final String encoding;
+ private final OutputFormat format;
+
+ SyndicateFormatWriter(final ProvidedService service,final OutputFormat format, String encoding){
+ this.service = service;
+ this.format = format;
+ this.encoding = encoding;
+
+ }
+ @Override
+ void generateOutputFormat(final BaseFeed feed, final HttpServletResponse response) throws IOException {
+ XmlWriter writer = null;
+ try{
+ writer = createWriter(response.getWriter());
+ if (this.format == OutputFormat.ATOM) {
+ response.setContentType(XMLMIME_ATOM);
+ feed.generateAtom(writer, this.service.getExtensionProfile());
+ } else {
+ response.setContentType(XMLMIME_RSS);
+ feed.generateRss(writer, this.service.getExtensionProfile());
+ }
+ }finally{
+ if(writer != null)
+ writer.close();
+ }
+ }
+
+ @Override
+ void generateOutputFormat(final BaseEntry entry, final HttpServletResponse response) throws IOException {
+ XmlWriter writer = null;
+ try{
+ writer = createWriter(response.getWriter());
+ if (this.format == OutputFormat.ATOM) {
+ response.setContentType(XMLMIME_ATOM);
+ entry.generateAtom(writer, this.service.getExtensionProfile());
+ } else {
+ response.setContentType(XMLMIME_RSS);
+ entry.generateRss(writer, this.service.getExtensionProfile());
+ }
+ }finally{
+ if(writer != null)
+ writer.close();
+ }
+ }
+ private XmlWriter createWriter(final Writer target) throws IOException {
+ XmlWriter writer = new XmlWriter(target, this.encoding);
+ // set the default namespace to Atom if Atom is the response format
+ if (this.format == OutputFormat.ATOM)
+ writer.setDefaultNamespace(DEFAULT_NAMESPACE);
+ return writer;
+ }
+ }
+ }
+
+
+
}
diff --git a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/ProvidedService.java b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/ProvidedService.java
index 61ab86b7381..2d51f67fe0e 100644
--- a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/ProvidedService.java
+++ b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/ProvidedService.java
@@ -15,6 +15,8 @@
*/
package org.apache.lucene.gdata.server.registry;
+import javax.xml.transform.Templates;
+
import org.apache.lucene.gdata.search.config.IndexSchema;
import com.google.gdata.data.ExtensionProfile;
@@ -55,4 +57,9 @@ public interface ProvidedService {
* @return the index schema configuration for this service
*/
public abstract IndexSchema getIndexSchema();
+ /**
+ * @return the compiled xslt stylesheet to transform the feed / entry for preview
+ */
+ public abstract Templates getTransformTemplate();
+
}
\ No newline at end of file
diff --git a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/ProvidedServiceConfig.java b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/ProvidedServiceConfig.java
index 11e7ae800e0..95f3f29fc32 100644
--- a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/ProvidedServiceConfig.java
+++ b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/ProvidedServiceConfig.java
@@ -17,6 +17,11 @@ package org.apache.lucene.gdata.server.registry;
import java.lang.reflect.Constructor;
+import javax.xml.transform.Templates;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.gdata.search.config.IndexSchema;
@@ -26,9 +31,7 @@ import org.apache.lucene.gdata.utils.SimpleObjectPool;
import com.google.gdata.data.BaseEntry;
import com.google.gdata.data.BaseFeed;
-import com.google.gdata.data.Entry;
import com.google.gdata.data.ExtensionProfile;
-import com.google.gdata.data.Feed;
/**
* Standard implementation of
@@ -78,6 +81,9 @@ public class ProvidedServiceConfig implements ProvidedService, ScopeVisitor {
private ExtensionProfile extensionProfile;
private int poolSize = DEFAULT_POOL_SIZE;
+
+ private Templates transformerTemplate;
+
/**
* @return Returns the poolSize.
@@ -326,4 +332,33 @@ public class ProvidedServiceConfig implements ProvidedService, ScopeVisitor {
this.indexSchema.setName(this.serviceName);
}
+ /**
+ * @see org.apache.lucene.gdata.server.registry.ProvidedService#getTransformTemplate()
+ */
+ public Templates getTransformTemplate() {
+
+ return this.transformerTemplate;
+ }
+
+ /**
+ * Sets and creates the preview transformer xslt template to provide a html formate for feeds and entries.
+ * The given file name must be available in the classpath.
+ * @param filename - the name of the file in the classpath
+ */
+ public void setXsltStylesheet(String filename){
+ if(filename == null || filename.length() == 0){
+ LOG.info("No preview stylesheet configured for service "+this.serviceName);
+ return;
+ }
+
+ TransformerFactory factory = TransformerFactory.newInstance();
+
+ try {
+ this.transformerTemplate = factory.newTemplates(new StreamSource(ProvidedServiceConfig.class.getResourceAsStream(filename.startsWith("/")?filename:"/"+filename)));
+ } catch (TransformerConfigurationException e) {
+ throw new RuntimeException("Can not compile xslt stylesheet path: "+filename,e);
+ }
+
+ }
+
}
diff --git a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/RegistryBuilder.java b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/RegistryBuilder.java
index 3a1e695c53c..146131c6e26 100644
--- a/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/RegistryBuilder.java
+++ b/contrib/gdata-server/src/java/org/apache/lucene/gdata/server/registry/RegistryBuilder.java
@@ -77,6 +77,7 @@ class RegistryBuilder {
digester.addBeanPropertySetter("gdata/service/entry-class", "entryType");
digester.addBeanPropertySetter("gdata/service/extension-profile",
"extensionProfileClass");
+ digester.addBeanPropertySetter("gdata/service/previewStyleSheet","xsltStylesheet");
addIndexRule(digester);
/*
* load components and configurations
diff --git a/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultGetHandler.java b/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultGetHandler.java
index 0bbd74e8688..af77e2b3380 100644
--- a/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultGetHandler.java
+++ b/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultGetHandler.java
@@ -90,12 +90,12 @@ public class DefaultGetHandler extends AbstractGdataRequestHandler {
this.feedResponse);
this.feedResponse.sendResponse(feed, this.feedRequest
- .getConfigurator().getExtensionProfile());
+ .getConfigurator());
} else {
BaseEntry entry = this.service.getSingleEntry(this.feedRequest,
this.feedResponse);
this.feedResponse.sendResponse(entry, this.feedRequest
- .getConfigurator().getExtensionProfile());
+ .getConfigurator());
}
} catch (ServiceException e) {
diff --git a/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultInsertHandler.java b/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultInsertHandler.java
index 21d4eb9daf9..ff6eefb7896 100644
--- a/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultInsertHandler.java
+++ b/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultInsertHandler.java
@@ -74,7 +74,7 @@ public class DefaultInsertHandler extends AbstractGdataRequestHandler {
BaseEntry entry = this.service.createEntry(this.feedRequest,this.feedResponse);
setFeedResponseFormat();
setFeedResponseStatus(GDataResponse.CREATED);
- this.feedResponse.sendResponse(entry, this.feedRequest.getConfigurator().getExtensionProfile());
+ this.feedResponse.sendResponse(entry, this.feedRequest.getConfigurator());
}catch (ServiceException e) {
LOG.error("Could not process GetFeed request - "+e.getMessage(),e);
diff --git a/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultUpdateHandler.java b/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultUpdateHandler.java
index 33d980544a2..32ae3b04b21 100644
--- a/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultUpdateHandler.java
+++ b/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/DefaultUpdateHandler.java
@@ -75,7 +75,7 @@ public class DefaultUpdateHandler extends AbstractGdataRequestHandler {
BaseEntry entry = this.service.updateEntry(this.feedRequest,
this.feedResponse);
setFeedResponseFormat();
- this.feedResponse.sendResponse(entry, this.feedRequest.getConfigurator().getExtensionProfile());
+ this.feedResponse.sendResponse(entry, this.feedRequest.getConfigurator());
}
catch (ServiceException e) {
diff --git a/contrib/gdata-server/src/test/org/apache/lucene/gdata/server/TestGDataResponse.java b/contrib/gdata-server/src/test/org/apache/lucene/gdata/server/TestGDataResponse.java
index 59750181c28..400ee5a7cdf 100644
--- a/contrib/gdata-server/src/test/org/apache/lucene/gdata/server/TestGDataResponse.java
+++ b/contrib/gdata-server/src/test/org/apache/lucene/gdata/server/TestGDataResponse.java
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.apache.lucene.gdata.server.GDataRequest.OutputFormat;
+import org.apache.lucene.gdata.utils.ProvidedServiceStub;
import org.easymock.MockControl;
import com.google.gdata.data.Entry;
@@ -69,7 +70,7 @@ public class TestGDataResponse extends TestCase {
public void testSendResponseBaseFeedExtensionProfile() throws IOException {
try{
Feed f = null;
- this.response.sendResponse(f,new ExtensionProfile());
+ this.response.sendResponse(f, new ProvidedServiceStub());
fail("Exception expected");
}catch (IllegalArgumentException e) {
//
@@ -90,7 +91,7 @@ public class TestGDataResponse extends TestCase {
this.response.setOutputFormat(OutputFormat.ATOM);
this.control.replay();
- this.response.sendResponse(createFeed(),new ExtensionProfile());
+ this.response.sendResponse(createFeed(), new ProvidedServiceStub());
assertEquals("Simple XML representation",stringWriter.toString(),generatedFeedAtom);
this.control.reset();
@@ -102,8 +103,7 @@ public class TestGDataResponse extends TestCase {
this.httpResponse.setContentType(GDataResponse.XMLMIME_RSS);
this.control.replay();
- this.response.sendResponse(createFeed(),new ExtensionProfile
- ());
+ this.response.sendResponse(createFeed(), new ProvidedServiceStub());
assertEquals("Simple XML representation",stringWriter.toString(),generatedFeedRSS);
@@ -117,7 +117,7 @@ public class TestGDataResponse extends TestCase {
public void testSendResponseBaseEntryExtensionProfile() throws IOException {
try{
Entry e = null;
- this.response.sendResponse(e,new ExtensionProfile());
+ this.response.sendResponse(e, new ProvidedServiceStub());
fail("Exception expected");
}catch (IllegalArgumentException e) {
//
@@ -134,11 +134,11 @@ public class TestGDataResponse extends TestCase {
PrintWriter writer = new PrintWriter(stringWriter);
this.control.expectAndReturn(this.httpResponse.getWriter(),writer);
+ this.httpResponse.setContentType(GDataResponse.XMLMIME_ATOM);
this.response.setOutputFormat(OutputFormat.ATOM);
this.control.replay();
- this.response.sendResponse(createEntry(),new ExtensionProfile
- ());
+ this.response.sendResponse(createEntry(), new ProvidedServiceStub());
assertEquals("Simple XML representation ATOM",stringWriter.toString(),generatedEntryAtom);
// test rss output
@@ -147,11 +147,11 @@ public class TestGDataResponse extends TestCase {
writer = new PrintWriter(stringWriter);
this.control.expectAndReturn(this.httpResponse.getWriter(),writer);
+ this.httpResponse.setContentType(GDataResponse.XMLMIME_RSS);
this.response.setOutputFormat(OutputFormat.RSS);
this.control.replay();
- this.response.sendResponse(createEntry(),new ExtensionProfile
- ());
+ this.response.sendResponse(createEntry(), new ProvidedServiceStub());
assertEquals("Simple XML representation RSS",stringWriter.toString(),generatedEntryRSS);
diff --git a/contrib/gdata-server/src/test/org/apache/lucene/gdata/utils/ProvidedServiceStub.java b/contrib/gdata-server/src/test/org/apache/lucene/gdata/utils/ProvidedServiceStub.java
index 126df36ad1c..c9d8cb58ec2 100644
--- a/contrib/gdata-server/src/test/org/apache/lucene/gdata/utils/ProvidedServiceStub.java
+++ b/contrib/gdata-server/src/test/org/apache/lucene/gdata/utils/ProvidedServiceStub.java
@@ -15,6 +15,8 @@
*/
package org.apache.lucene.gdata.utils;
+import javax.xml.transform.Templates;
+
import org.apache.lucene.gdata.search.config.IndexSchema;
import org.apache.lucene.gdata.server.registry.ProvidedService;
@@ -63,4 +65,11 @@ public class ProvidedServiceStub implements ProvidedService {
return this.indexSchema;
}
+ public Templates getTransformTemplate() {
+
+ return null;
+ }
+
+
+
}
diff --git a/contrib/gdata-server/webroot/WEB-INF/classes/gdata-config.xml b/contrib/gdata-server/webroot/WEB-INF/classes/gdata-config.xml
index 4991ea00e96..a6137e64ccd 100644
--- a/contrib/gdata-server/webroot/WEB-INF/classes/gdata-config.xml
+++ b/contrib/gdata-server/webroot/WEB-INF/classes/gdata-config.xml
@@ -6,6 +6,7 @@
com.google.gdata.data.ExtensionProfile
+ transform.xslt
diff --git a/contrib/gdata-server/webroot/WEB-INF/classes/gdata-config.xsd b/contrib/gdata-server/webroot/WEB-INF/classes/gdata-config.xsd
index 5fb08c05de4..bca82cd8068 100755
--- a/contrib/gdata-server/webroot/WEB-INF/classes/gdata-config.xsd
+++ b/contrib/gdata-server/webroot/WEB-INF/classes/gdata-config.xsd
@@ -3,6 +3,7 @@
+
@@ -27,6 +28,8 @@
minOccurs="1" />
+