/*
* 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.
*/
package org.apache.jackrabbit.server.io;
import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.webdav.DavResource;
import org.apache.jackrabbit.webdav.DavResourceIterator;
import org.apache.jackrabbit.webdav.property.PropEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;
/**
* <code>DirListingExportHandler</code> represents a simple export for collections:
* a human-readable view listing the members.<br>
* Note: If {@link #exportContent(ExportContext, boolean)} is called the view list
* child nodes only, without respecting their representation as <code>DavResource</code>s.
*/
public class DirListingExportHandler implements IOHandler, PropertyHandler {
private static Logger log = LoggerFactory.getLogger(DirListingExportHandler.class);
private IOManager ioManager;
/**
* Creates a new <code>DirListingExportHandler</code>
*/
public DirListingExportHandler() {
}
/**
* Creates a new <code>DirListingExportHandler</code>
*
* @param ioManager
*/
public DirListingExportHandler(IOManager ioManager) {
this.ioManager = ioManager;
}
/**
* Always returns false
*
* @see IOHandler#canImport(ImportContext, boolean)
*/
public boolean canImport(ImportContext context, boolean isFolder) {
return false;
}
/**
* Always returns false
*
* @see IOHandler#canImport(ImportContext, DavResource)
*/
public boolean canImport(ImportContext context, DavResource resource) {
return false;
}
/**
* Does nothing and returns false
*
* @see IOHandler#importContent(ImportContext, boolean)
*/
public boolean importContent(ImportContext context, boolean isCollection) throws IOException {
// can only handle export
return false;
}
/**
* Does nothing and returns false
*
* @see IOHandler#importContent(ImportContext, DavResource)
*/
public boolean importContent(ImportContext context, DavResource resource) throws IOException {
return false;
}
/**
* @return true if the specified context is still valid and provides a
* export root and if 'isCollection' is true. False otherwise
* @see IOHandler#canExport(ExportContext, boolean)
*/
public boolean canExport(ExportContext context, boolean isCollection) {
if (context == null || context.isCompleted()) {
return false;
}
return isCollection && context.getExportRoot() != null;
}
/**
* @return true if the specified context is still valid and provides a
* export root and if the specified resource is a collection. False otherwise.
* @see IOHandler#canExport(ExportContext, DavResource)
* @see DavResource#isCollection()
*/
public boolean canExport(ExportContext context, DavResource resource) {
if (resource == null) {
return false;
}
return canExport(context, resource.isCollection());
}
/**
* @see IOHandler#exportContent(ExportContext, boolean)
*/
public boolean exportContent(ExportContext context, boolean isCollection) throws IOException {
if (!canExport(context, isCollection)) {
throw new IOException(getName() + ": Cannot export " + context.getExportRoot());
}
// properties (content length undefined)
context.setModificationTime(new Date().getTime());
context.setContentType("text/html", "UTF-8");
context.setETag("");
// data
if (context.hasStream()) {
PrintWriter writer = new PrintWriter(new OutputStreamWriter(context.getOutputStream(), "utf8"));
try {
Item item = context.getExportRoot();
Repository rep = item.getSession().getRepository();
String repName = rep.getDescriptor(Repository.REP_NAME_DESC);
String repURL = rep.getDescriptor(Repository.REP_VENDOR_URL_DESC);
String repVersion = rep.getDescriptor(Repository.REP_VERSION_DESC);
writer.print("<html><head><title>");
writer.print(Text.encodeIllegalHTMLCharacters(repName));
writer.print(" ");
writer.print(Text.encodeIllegalHTMLCharacters(repVersion));
writer.print(" ");
writer.print(Text.encodeIllegalHTMLCharacters(item.getPath()));
writer.print("</title></head>");
writer.print("<body><h2>");
writer.print(Text.encodeIllegalHTMLCharacters(item.getPath()));
writer.print("</h2><ul>");
writer.print("<li><a href=\"..\">..</a></li>");
if (item.isNode()) {
NodeIterator iter = ((Node)item).getNodes();
while (iter.hasNext()) {
Node child = iter.nextNode();
String label = Text.getName(child.getPath());
writer.print("<li><a href=\"");
writer.print(Text.encodeIllegalHTMLCharacters(Text.escape(label)));
if (child.isNode()) {
writer.print("/");
}
writer.print("\">");
writer.print(Text.encodeIllegalHTMLCharacters(label));
writer.print("</a></li>");
}
}
writer.print("</ul><hr size=\"1\"><em>Powered by <a href=\"");
writer.print(Text.encodeIllegalHTMLCharacters(repURL));
writer.print("\">");
writer.print(Text.encodeIllegalHTMLCharacters(repName));
writer.print("</a> version ");
writer.print(Text.encodeIllegalHTMLCharacters(repVersion));
writer.print("</em></body></html>");
} catch (RepositoryException e) {
// should not occur
log.debug(e.getMessage());
}
writer.close();
}
return true;
}
/**
* @see IOHandler#exportContent(ExportContext, DavResource)
*/
public boolean exportContent(ExportContext context, DavResource resource) throws IOException {
if (!canExport(context, resource)) {
throw new IOException(getName() + ": Cannot export " + context.getExportRoot());
}
// properties (content length undefined)
context.setModificationTime(new Date().getTime());
context.setContentType("text/html", "UTF-8");
context.setETag("");
// data
if (context.hasStream()) {
PrintWriter writer = new PrintWriter(new OutputStreamWriter(context.getOutputStream(), "utf8"));
try {
Item item = context.getExportRoot();
Repository rep = item.getSession().getRepository();
String repName = rep.getDescriptor(Repository.REP_NAME_DESC);
String repURL = rep.getDescriptor(Repository.REP_VENDOR_URL_DESC);
String repVersion = rep.getDescriptor(Repository.REP_VERSION_DESC);
writer.print("<html><head><title>");
writer.print(Text.encodeIllegalHTMLCharacters(repName));
writer.print(" ");
writer.print(Text.encodeIllegalHTMLCharacters(repVersion));
writer.print(" ");
writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath()));
writer.print("</title></head>");
writer.print("<body><h2>");
writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath()));
writer.print("</h2><ul>");
writer.print("<li><a href=\"..\">..</a></li>");
DavResourceIterator iter = resource.getMembers();
while (iter.hasNext()) {
DavResource child = iter.nextResource();
String label = Text.getName(child.getResourcePath());
writer.print("<li><a href=\"");
writer.print(Text.encodeIllegalHTMLCharacters(child.getHref()));
writer.print("\">");
writer.print(Text.encodeIllegalHTMLCharacters(label));
writer.print("</a></li>");
}
writer.print("</ul><hr size=\"1\"><em>Powered by <a href=\"");
writer.print(Text.encodeIllegalHTMLCharacters(repURL));
writer.print("\">");
writer.print(Text.encodeIllegalHTMLCharacters(repName));
writer.print("</a> version ");
writer.print(Text.encodeIllegalHTMLCharacters(repVersion));
writer.print("</em></body></html>");
} catch (RepositoryException e) {
// should not occur
log.debug(e.getMessage());
}
writer.close();
}
return true;
}
/**
* @see IOHandler#getIOManager()
*/
public IOManager getIOManager() {
return ioManager;
}
/**
* @see IOHandler#setIOManager(IOManager)
*/
public void setIOManager(IOManager ioManager) {
this.ioManager = ioManager;
}
/**
* @see IOHandler#getName()
*/
public String getName() {
return "DirListing Export";
}
//----------------------------------------------------< PropertyHandler >---
/**
* Always returns false.
* @param context
* @param isCollection
* @return always returns false.
*/
public boolean canExport(PropertyExportContext context, boolean isCollection) {
return false;
}
/**
* @see PropertyHandler#exportProperties(PropertyExportContext, boolean)
*/
public boolean exportProperties(PropertyExportContext exportContext, boolean isCollection) throws RepositoryException {
// export-content facility only... no responsible for PROPFIND.
throw new RepositoryException(getName() + ": Cannot export properties for context " + exportContext);
}
public boolean canImport(PropertyImportContext context, boolean isCollection) {
return false;
}
/**
* @see PropertyHandler#importProperties(PropertyImportContext, boolean)
*/
public Map<? extends PropEntry, ?> importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException {
// export facilities only -> throw
throw new RepositoryException(getName() + ": Cannot import properties.");
}
}