Merge pull request #10 from skycao/master

Added write sitemap to string functionality
This commit is contained in:
dfabulich 2015-06-12 20:35:44 -07:00
commit a46ea9ffe5
12 changed files with 294 additions and 132 deletions

View File

@ -16,12 +16,15 @@ abstract class AbstractSitemapGeneratorOptions<THIS extends AbstractSitemapGener
boolean gzip = false; boolean gzip = false;
public AbstractSitemapGeneratorOptions(URL baseUrl, File baseDir) { public AbstractSitemapGeneratorOptions(URL baseUrl, File baseDir) {
if (baseDir == null) throw new NullPointerException("baseDir may not be null");
if (baseUrl == null) throw new NullPointerException("baseUrl may not be null"); if (baseUrl == null) throw new NullPointerException("baseUrl may not be null");
this.baseDir = baseDir; this.baseDir = baseDir;
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
} }
public AbstractSitemapGeneratorOptions(URL baseUrl) {
this(baseUrl, null);
}
/** The prefix of the name of the sitemaps we'll create; by default this is "sitemap" */ /** The prefix of the name of the sitemaps we'll create; by default this is "sitemap" */
public THIS fileNamePrefix(String fileNamePrefix) { public THIS fileNamePrefix(String fileNamePrefix) {
if (fileNamePrefix == null) throw new NullPointerException("fileNamePrefix may not be null"); if (fileNamePrefix == null) throw new NullPointerException("fileNamePrefix may not be null");

View File

@ -1,33 +1,31 @@
package com.redfin.sitemapgenerator; package com.redfin.sitemapgenerator;
import java.io.IOException;
import java.io.OutputStreamWriter;
abstract class AbstractSitemapUrlRenderer<T extends WebSitemapUrl> implements ISitemapUrlRenderer<T> { abstract class AbstractSitemapUrlRenderer<T extends WebSitemapUrl> implements ISitemapUrlRenderer<T> {
public void render(WebSitemapUrl url, OutputStreamWriter out, W3CDateFormat dateFormat, String additionalData) public void render(WebSitemapUrl url, StringBuilder sb, W3CDateFormat dateFormat, String additionalData) {
throws IOException { sb.append(" <url>\n");
out.write(" <url>\n"); sb.append(" <loc>");
out.write(" <loc>"); sb.append(url.getUrl().toString());
out.write(url.getUrl().toString()); sb.append("</loc>\n");
out.write("</loc>\n");
if (url.getLastMod() != null) { if (url.getLastMod() != null) {
out.write(" <lastmod>"); sb.append(" <lastmod>");
out.write(dateFormat.format(url.getLastMod())); sb.append(dateFormat.format(url.getLastMod()));
out.write("</lastmod>\n"); sb.append("</lastmod>\n");
} }
if (url.getChangeFreq() != null) { if (url.getChangeFreq() != null) {
out.write(" <changefreq>"); sb.append(" <changefreq>");
out.write(url.getChangeFreq().toString()); sb.append(url.getChangeFreq().toString());
out.write("</changefreq>\n"); sb.append("</changefreq>\n");
} }
if (url.getPriority() != null) { if (url.getPriority() != null) {
out.write(" <priority>"); sb.append(" <priority>");
out.write(url.getPriority().toString()); sb.append(url.getPriority().toString());
out.write("</priority>\n"); sb.append("</priority>\n");
} }
if (additionalData != null) out.write(additionalData); if (additionalData != null) {
out.write(" </url>\n"); sb.append(additionalData);
}
sb.append(" </url>\n");
} }
public void renderTag(StringBuilder sb, String namespace, String tagName, Object value) { public void renderTag(StringBuilder sb, String namespace, String tagName, Object value) {

View File

@ -1,8 +1,6 @@
package com.redfin.sitemapgenerator; package com.redfin.sitemapgenerator;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
@ -37,6 +35,26 @@ public class GoogleCodeSitemapGenerator extends SitemapGenerator<GoogleCodeSitem
this(new SitemapGeneratorOptions(baseUrl, baseDir)); this(new SitemapGeneratorOptions(baseUrl, baseDir));
} }
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleCodeSitemapGenerator(String baseUrl) throws MalformedURLException {
this(new SitemapGeneratorOptions(new URL(baseUrl)));
}
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleCodeSitemapGenerator(URL baseUrl) {
this(new SitemapGeneratorOptions(baseUrl));
}
/** Configures a builder so you can specify sitemap generator options /** Configures a builder so you can specify sitemap generator options
* *
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL * @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
@ -63,23 +81,23 @@ public class GoogleCodeSitemapGenerator extends SitemapGenerator<GoogleCodeSitem
public Class<GoogleCodeSitemapUrl> getUrlClass() { public Class<GoogleCodeSitemapUrl> getUrlClass() {
return GoogleCodeSitemapUrl.class; return GoogleCodeSitemapUrl.class;
} }
public void render(GoogleCodeSitemapUrl url, OutputStreamWriter out,
W3CDateFormat dateFormat) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append(" <codesearch:codesearch>\n");
renderTag(sb, "codesearch", "filetype", url.getFileType());
renderTag(sb, "codesearch", "license", url.getLicense());
renderTag(sb, "codesearch", "filename", url.getFileName());
renderTag(sb, "codesearch", "packageurl", url.getPackageUrl());
renderTag(sb, "codesearch", "packagemap", url.getPackageMap());
sb.append(" </codesearch:codesearch>\n");
super.render(url, out, dateFormat, sb.toString());
}
public String getXmlNamespaces() { public String getXmlNamespaces() {
return "xmlns:codesearch=\"http://www.google.com/codesearch/schemas/sitemap/1.0\""; return "xmlns:codesearch=\"http://www.google.com/codesearch/schemas/sitemap/1.0\"";
} }
public void render(GoogleCodeSitemapUrl url, StringBuilder sb,
W3CDateFormat dateFormat) {
StringBuilder tagSb = new StringBuilder();
tagSb.append(" <codesearch:codesearch>\n");
renderTag(tagSb, "codesearch", "filetype", url.getFileType());
renderTag(tagSb, "codesearch", "license", url.getLicense());
renderTag(tagSb, "codesearch", "filename", url.getFileName());
renderTag(tagSb, "codesearch", "packageurl", url.getPackageUrl());
renderTag(tagSb, "codesearch", "packagemap", url.getPackageMap());
tagSb.append(" </codesearch:codesearch>\n");
super.render(url, sb, dateFormat, tagSb.toString());
}
} }

View File

@ -1,8 +1,6 @@
package com.redfin.sitemapgenerator; package com.redfin.sitemapgenerator;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
@ -57,6 +55,27 @@ public class GoogleGeoSitemapGenerator extends SitemapGenerator<GoogleGeoSitemap
public GoogleGeoSitemapGenerator(URL baseUrl, File baseDir) { public GoogleGeoSitemapGenerator(URL baseUrl, File baseDir) {
this(new SitemapGeneratorOptions(baseUrl, baseDir)); this(new SitemapGeneratorOptions(baseUrl, baseDir));
} }
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleGeoSitemapGenerator(String baseUrl) throws MalformedURLException {
this(new SitemapGeneratorOptions(new URL(baseUrl)));
}
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleGeoSitemapGenerator(URL baseUrl) {
this(new SitemapGeneratorOptions(baseUrl));
}
private static class Renderer extends AbstractSitemapUrlRenderer<GoogleGeoSitemapUrl> implements ISitemapUrlRenderer<GoogleGeoSitemapUrl> { private static class Renderer extends AbstractSitemapUrlRenderer<GoogleGeoSitemapUrl> implements ISitemapUrlRenderer<GoogleGeoSitemapUrl> {
@ -64,19 +83,17 @@ public class GoogleGeoSitemapGenerator extends SitemapGenerator<GoogleGeoSitemap
return GoogleGeoSitemapUrl.class; return GoogleGeoSitemapUrl.class;
} }
public void render(GoogleGeoSitemapUrl url, OutputStreamWriter out,
W3CDateFormat dateFormat) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append(" <geo:geo>\n");
sb.append(" <geo:format>"+url.getFormat()+"</geo:format>\n");
sb.append(" </geo:geo>\n");
super.render(url, out, dateFormat, sb.toString());
}
public String getXmlNamespaces() { public String getXmlNamespaces() {
return "xmlns:geo=\"http://www.google.com/geo/schemas/sitemap/1.0\""; return "xmlns:geo=\"http://www.google.com/geo/schemas/sitemap/1.0\"";
} }
public void render(GoogleGeoSitemapUrl url, StringBuilder sb, W3CDateFormat dateFormat) {
StringBuilder tagSb = new StringBuilder();
tagSb.append(" <geo:geo>\n");
tagSb.append(" <geo:format>"+url.getFormat()+"</geo:format>\n");
tagSb.append(" </geo:geo>\n");
super.render(url, sb, dateFormat, tagSb.toString());
}
} }
} }

View File

@ -1,8 +1,6 @@
package com.redfin.sitemapgenerator; package com.redfin.sitemapgenerator;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
@ -56,6 +54,26 @@ public class GoogleMobileSitemapGenerator extends SitemapGenerator<GoogleMobileS
public GoogleMobileSitemapGenerator(URL baseUrl, File baseDir) { public GoogleMobileSitemapGenerator(URL baseUrl, File baseDir) {
this(new SitemapGeneratorOptions(baseUrl, baseDir)); this(new SitemapGeneratorOptions(baseUrl, baseDir));
} }
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleMobileSitemapGenerator(String baseUrl) throws MalformedURLException {
this(new SitemapGeneratorOptions(new URL(baseUrl)));
}
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleMobileSitemapGenerator(URL baseUrl) {
this(new SitemapGeneratorOptions(baseUrl));
}
private static class Renderer extends AbstractSitemapUrlRenderer<GoogleMobileSitemapUrl> implements ISitemapUrlRenderer<GoogleMobileSitemapUrl> { private static class Renderer extends AbstractSitemapUrlRenderer<GoogleMobileSitemapUrl> implements ISitemapUrlRenderer<GoogleMobileSitemapUrl> {
@ -63,16 +81,14 @@ public class GoogleMobileSitemapGenerator extends SitemapGenerator<GoogleMobileS
return GoogleMobileSitemapUrl.class; return GoogleMobileSitemapUrl.class;
} }
public void render(GoogleMobileSitemapUrl url, OutputStreamWriter out,
W3CDateFormat dateFormat) throws IOException {
String additionalData = " <mobile:mobile/>\n";
super.render(url, out, dateFormat, additionalData);
}
public String getXmlNamespaces() { public String getXmlNamespaces() {
return "xmlns:mobile=\"http://www.google.com/schemas/sitemap-mobile/1.0\""; return "xmlns:mobile=\"http://www.google.com/schemas/sitemap-mobile/1.0\"";
} }
public void render(GoogleMobileSitemapUrl url, StringBuilder sb, W3CDateFormat dateFormat) {
String additionalData = " <mobile:mobile/>\n";
super.render(url, sb, dateFormat, additionalData);
}
} }
} }

View File

@ -1,8 +1,6 @@
package com.redfin.sitemapgenerator; package com.redfin.sitemapgenerator;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
@ -69,26 +67,44 @@ public class GoogleNewsSitemapGenerator extends SitemapGenerator<GoogleNewsSitem
this(new SitemapGeneratorOptions(baseUrl, baseDir)); this(new SitemapGeneratorOptions(baseUrl, baseDir));
} }
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleNewsSitemapGenerator(String baseUrl) throws MalformedURLException {
this(new SitemapGeneratorOptions(new URL(baseUrl)));
}
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleNewsSitemapGenerator(URL baseUrl) {
this(new SitemapGeneratorOptions(baseUrl));
}
private static class Renderer extends AbstractSitemapUrlRenderer<GoogleNewsSitemapUrl> implements ISitemapUrlRenderer<GoogleNewsSitemapUrl> { private static class Renderer extends AbstractSitemapUrlRenderer<GoogleNewsSitemapUrl> implements ISitemapUrlRenderer<GoogleNewsSitemapUrl> {
public Class<GoogleNewsSitemapUrl> getUrlClass() { public Class<GoogleNewsSitemapUrl> getUrlClass() {
return GoogleNewsSitemapUrl.class; return GoogleNewsSitemapUrl.class;
} }
public void render(GoogleNewsSitemapUrl url, OutputStreamWriter out,
W3CDateFormat dateFormat) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append(" <news:news>\n");
renderTag(sb, "news", "publication_date", dateFormat.format(url.getPublicationDate()));
renderTag(sb, "news", "keywords", url.getKeywords());
sb.append(" </news:news>\n");
super.render(url, out, dateFormat, sb.toString());
}
public String getXmlNamespaces() { public String getXmlNamespaces() {
return "xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\""; return "xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\"";
} }
public void render(GoogleNewsSitemapUrl url, StringBuilder sb, W3CDateFormat dateFormat) {
StringBuilder tagSb = new StringBuilder();
tagSb.append(" <news:news>\n");
renderTag(tagSb, "news", "publication_date", dateFormat.format(url.getPublicationDate()));
renderTag(tagSb, "news", "keywords", url.getKeywords());
tagSb.append(" </news:news>\n");
super.render(url, sb, dateFormat, tagSb.toString());
}
} }

View File

@ -1,8 +1,6 @@
package com.redfin.sitemapgenerator; package com.redfin.sitemapgenerator;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
@ -56,49 +54,67 @@ public class GoogleVideoSitemapGenerator extends SitemapGenerator<GoogleVideoSit
public GoogleVideoSitemapGenerator(URL baseUrl, File baseDir) { public GoogleVideoSitemapGenerator(URL baseUrl, File baseDir) {
this(new SitemapGeneratorOptions(baseUrl, baseDir)); this(new SitemapGeneratorOptions(baseUrl, baseDir));
} }
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleVideoSitemapGenerator(String baseUrl) throws MalformedURLException {
this(new SitemapGeneratorOptions(new URL(baseUrl)));
}
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public GoogleVideoSitemapGenerator(URL baseUrl) {
this(new SitemapGeneratorOptions(baseUrl));
}
private static class Renderer extends AbstractSitemapUrlRenderer<GoogleVideoSitemapUrl> implements ISitemapUrlRenderer<GoogleVideoSitemapUrl> { private static class Renderer extends AbstractSitemapUrlRenderer<GoogleVideoSitemapUrl> implements ISitemapUrlRenderer<GoogleVideoSitemapUrl> {
public Class<GoogleVideoSitemapUrl> getUrlClass() { public Class<GoogleVideoSitemapUrl> getUrlClass() {
return GoogleVideoSitemapUrl.class; return GoogleVideoSitemapUrl.class;
} }
public void render(GoogleVideoSitemapUrl url, OutputStreamWriter out,
W3CDateFormat dateFormat) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append(" <video:video>\n");
renderTag(sb, "video", "content_loc", url.getContentUrl());
if (url.getPlayerUrl() != null) {
sb.append(" <video:player_loc allow_embed=\"");
sb.append(url.getAllowEmbed());
sb.append("\">");
sb.append(url.getPlayerUrl());
sb.append("</video:player_loc>\n");
}
renderTag(sb, "video", "thumbnail_loc", url.getThumbnailUrl());
renderTag(sb, "video", "title", url.getTitle());
renderTag(sb, "video", "description", url.getDescription());
renderTag(sb, "video", "rating", url.getRating());
renderTag(sb, "video", "view_count", url.getViewCount());
if (url.getPublicationDate() != null) {
renderTag(sb, "video", "publication_date", dateFormat.format(url.getPublicationDate()));
}
if (url.getTags() != null) {
for (String tag : url.getTags()) {
renderTag(sb, "video", "tag", tag);
}
}
renderTag(sb, "video", "category", url.getCategory());
renderTag(sb, "video", "family_friendly", url.getFamilyFriendly());
renderTag(sb, "video", "duration", url.getDurationInSeconds());
sb.append(" </video:video>\n");
super.render(url, out, dateFormat, sb.toString());
}
public String getXmlNamespaces() { public String getXmlNamespaces() {
return "xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\""; return "xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"";
} }
public void render(GoogleVideoSitemapUrl url, StringBuilder sb, W3CDateFormat dateFormat) {
StringBuilder tagSb = new StringBuilder();
tagSb.append(" <video:video>\n");
renderTag(tagSb, "video", "content_loc", url.getContentUrl());
if (url.getPlayerUrl() != null) {
tagSb.append(" <video:player_loc allow_embed=\"");
tagSb.append(url.getAllowEmbed());
tagSb.append("\">");
tagSb.append(url.getPlayerUrl());
tagSb.append("</video:player_loc>\n");
}
renderTag(tagSb, "video", "thumbnail_loc", url.getThumbnailUrl());
renderTag(tagSb, "video", "title", url.getTitle());
renderTag(tagSb, "video", "description", url.getDescription());
renderTag(tagSb, "video", "rating", url.getRating());
renderTag(tagSb, "video", "view_count", url.getViewCount());
if (url.getPublicationDate() != null) {
renderTag(tagSb, "video", "publication_date", dateFormat.format(url.getPublicationDate()));
}
if (url.getTags() != null) {
for (String tag : url.getTags()) {
renderTag(tagSb, "video", "tag", tag);
}
}
renderTag(tagSb, "video", "category", url.getCategory());
renderTag(tagSb, "video", "family_friendly", url.getFamilyFriendly());
renderTag(tagSb, "video", "duration", url.getDurationInSeconds());
tagSb.append(" </video:video>\n");
super.render(url, sb, dateFormat, tagSb.toString());
}
} }

View File

@ -1,11 +1,8 @@
package com.redfin.sitemapgenerator; package com.redfin.sitemapgenerator;
import java.io.IOException;
import java.io.OutputStreamWriter;
interface ISitemapUrlRenderer<T extends ISitemapUrl> { interface ISitemapUrlRenderer<T extends ISitemapUrl> {
public Class<T> getUrlClass(); public Class<T> getUrlClass();
public String getXmlNamespaces(); public String getXmlNamespaces();
public void render(T url, OutputStreamWriter out, W3CDateFormat dateFormat) throws IOException; public void render(T url, StringBuilder sb, W3CDateFormat dateFormat);
} }

View File

@ -59,10 +59,12 @@ abstract class SitemapGenerator<U extends ISitemapUrl, THIS extends SitemapGener
UrlUtils.checkUrl(url.getUrl(), baseUrl); UrlUtils.checkUrl(url.getUrl(), baseUrl);
if (urls.size() == maxUrls) { if (urls.size() == maxUrls) {
if (!allowMultipleSitemaps) throw new RuntimeException("More than " + maxUrls + " urls, but allowMultipleSitemaps is false. Enable allowMultipleSitemaps to split the sitemap into multiple files with a sitemap index."); if (!allowMultipleSitemaps) throw new RuntimeException("More than " + maxUrls + " urls, but allowMultipleSitemaps is false. Enable allowMultipleSitemaps to split the sitemap into multiple files with a sitemap index.");
if (mapCount == 0) mapCount++; if (baseDir != null) {
writeSiteMap(); if (mapCount == 0) mapCount++;
mapCount++; writeSiteMap();
urls.clear(); mapCount++;
urls.clear();
}
} }
urls.add(url); urls.add(url);
return getThis(); return getThis();
@ -163,6 +165,41 @@ abstract class SitemapGenerator<U extends ISitemapUrl, THIS extends SitemapGener
return outFiles; return outFiles;
} }
/**
* Writes out the sitemaps as a list of strings.
* Each string in the list is a formatted list of URLs.
* We return a list because the URLs may not all fit --
* google specifies a maximum of 50,000 URLs in one sitemap.
* @return a list of XML-formatted strings
*/
public List<String> writeAsStrings() {
List<String> listOfSiteMapStrings = new ArrayList<String>();
for (int start = 0; start < urls.size(); start += maxUrls) {
int end = start + maxUrls;
if (end > urls.size()) {
end = urls.size();
}
StringBuilder sb = new StringBuilder();
writeSiteMapAsString(sb, urls.subList(start, end));
listOfSiteMapStrings.add(sb.toString());
}
return listOfSiteMapStrings;
}
private void writeSiteMapAsString(StringBuilder sb, List<U> urls) {
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" ");
if (renderer.getXmlNamespaces() != null) {
sb.append(renderer.getXmlNamespaces());
sb.append(' ');
}
sb.append(">\n");
for (U url : urls) {
renderer.render(url, sb, dateFormat);
}
sb.append("</urlset>");
}
/** After you've called {@link #write()}, call this to generate a sitemap index of all sitemaps you generated. /** After you've called {@link #write()}, call this to generate a sitemap index of all sitemaps you generated.
* *
*/ */
@ -175,6 +212,9 @@ abstract class SitemapGenerator<U extends ISitemapUrl, THIS extends SitemapGener
} }
private void writeSiteMap() { private void writeSiteMap() {
if (baseDir == null) {
throw new NullPointerException("To write to files, baseDir must not be null");
}
if (urls.size() == 0) return; if (urls.size() == 0) return;
String fileNamePrefix; String fileNamePrefix;
if (mapCount > 0) { if (mapCount > 0) {
@ -204,18 +244,9 @@ abstract class SitemapGenerator<U extends ISitemapUrl, THIS extends SitemapGener
} }
private void writeSiteMap(OutputStreamWriter out) throws IOException { private void writeSiteMap(OutputStreamWriter out) throws IOException {
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); StringBuilder sb = new StringBuilder();
out.write("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" "); writeSiteMapAsString(sb, urls);
out.write(sb.toString());
if (renderer.getXmlNamespaces() != null) {
out.write(renderer.getXmlNamespaces());
out.write(' ');
}
out.write(">\n");
for (U url : urls) {
renderer.render(url, out, dateFormat);
}
out.write("</urlset>");
out.close(); out.close();
} }

View File

@ -14,5 +14,13 @@ class SitemapGeneratorOptions extends
public SitemapGeneratorOptions(String baseUrl, File baseDir) throws MalformedURLException { public SitemapGeneratorOptions(String baseUrl, File baseDir) throws MalformedURLException {
this(new URL(baseUrl), baseDir); this(new URL(baseUrl), baseDir);
} }
public SitemapGeneratorOptions(URL baseUrl) {
super(baseUrl);
}
public SitemapGeneratorOptions(String baseUrl) throws MalformedURLException {
super(new URL(baseUrl));
}
} }

View File

@ -1,8 +1,6 @@
package com.redfin.sitemapgenerator; package com.redfin.sitemapgenerator;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
@ -57,6 +55,25 @@ public class WebSitemapGenerator extends SitemapGenerator<WebSitemapUrl,WebSitem
this(new SitemapGeneratorOptions(baseUrl, baseDir)); this(new SitemapGeneratorOptions(baseUrl, baseDir));
} }
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public WebSitemapGenerator(String baseUrl) throws MalformedURLException {
this(new SitemapGeneratorOptions(new URL(baseUrl)));
}
/**Configures the generator with a base URL and a null directory. The object constructed
* is not intended to be used to write to files. Rather, it is intended to be used to obtain
* XML-formatted strings that represent sitemaps.
*
* @param baseUrl All URLs in the generated sitemap(s) should appear under this base URL
*/
public WebSitemapGenerator(URL baseUrl) {
this(new SitemapGeneratorOptions(baseUrl));
}
private static class Renderer extends AbstractSitemapUrlRenderer<WebSitemapUrl> implements ISitemapUrlRenderer<WebSitemapUrl> { private static class Renderer extends AbstractSitemapUrlRenderer<WebSitemapUrl> implements ISitemapUrlRenderer<WebSitemapUrl> {
@ -64,13 +81,13 @@ public class WebSitemapGenerator extends SitemapGenerator<WebSitemapUrl,WebSitem
return WebSitemapUrl.class; return WebSitemapUrl.class;
} }
public void render(WebSitemapUrl url, OutputStreamWriter out, W3CDateFormat dateFormat) throws IOException {
super.render(url, out, dateFormat, null);
}
public String getXmlNamespaces() { public String getXmlNamespaces() {
return null; return null;
} }
public void render(WebSitemapUrl url, StringBuilder sb, W3CDateFormat dateFormat) {
super.render(url, sb, dateFormat, null);
}
} }
} }

View File

@ -306,6 +306,31 @@ public class SitemapGeneratorTest extends TestCase {
assertEquals("sitemap didn't match", SITEMAP1, actual); assertEquals("sitemap didn't match", SITEMAP1, actual);
} }
public void testBaseDirIsNullThrowsNullPointerException() throws Exception {
wsg = WebSitemapGenerator.builder("http://www.example.com", null).autoValidate(true).maxUrls(10).build();
wsg.addUrl("http://www.example.com/index.html");
Exception e = null;
try {
wsg.write();
} catch (Exception ex) {
e = ex;
}
assertTrue(e instanceof NullPointerException);
assertEquals("Correct exception was not thrown", e.getMessage(), "To write to files, baseDir must not be null");
}
public void testWriteAsStringsMoreThanOneString() throws Exception {
wsg = WebSitemapGenerator.builder("http://www.example.com", null).autoValidate(true).maxUrls(10).build();
for (int i = 0; i < 9; i++) {
wsg.addUrl("http://www.example.com/"+i);
}
wsg.addUrl("http://www.example.com/9");
wsg.addUrl("http://www.example.com/just-one-more");
List<String> siteMapsAsStrings = wsg.writeAsStrings();
assertEquals("First string didn't match", SITEMAP1, siteMapsAsStrings.get(0));
assertEquals("Second string didn't match", SITEMAP_PLUS_ONE, siteMapsAsStrings.get(1));
}
private String writeSingleSiteMap(WebSitemapGenerator wsg) { private String writeSingleSiteMap(WebSitemapGenerator wsg) {
List<File> files = wsg.write(); List<File> files = wsg.write();
assertEquals("Too many files: " + files.toString(), 1, files.size()); assertEquals("Too many files: " + files.toString(), 1, files.size());