blob: e709fbdc092b92b049f9cbf82e23d91bbf185946 [file] [log] [blame]
/*
* Copyright 2004-2005 The Apache Software Foundation or its licensors,
* as applicable.
*
* Licensed 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.webdav.version.report;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavServletResponse;
import org.apache.jackrabbit.webdav.version.DeltaVConstants;
import org.apache.jackrabbit.webdav.version.DeltaVResource;
import org.apache.jackrabbit.webdav.xml.DomUtil;
import org.apache.jackrabbit.webdav.xml.Namespace;
import org.apache.jackrabbit.webdav.xml.XmlSerializable;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.util.HashMap;
/**
* <code>ReportType</code>...
*/
public class ReportType implements DeltaVConstants, XmlSerializable {
private static Logger log = Logger.getLogger(ReportType.class);
private static final HashMap types = new HashMap();
public static final ReportType VERSION_TREE = register(XML_VERSION_TREE, NAMESPACE, VersionTreeReport.class);
public static final ReportType EXPAND_PROPERTY = register(XML_EXPAND_PROPERTY, NAMESPACE, ExpandPropertyReport.class);
public static final ReportType LOCATE_BY_HISTORY = register(XML_LOCATE_BY_HISTORY, NAMESPACE, LocateByHistoryReport.class);
private final String key;
private final String localName;
private final Namespace namespace;
private final Class reportClass;
/**
* Private constructor
*
* @see ReportType#register(String, org.apache.jackrabbit.webdav.xml.Namespace, Class)
*/
private ReportType(String localName, Namespace namespace, String key, Class reportClass) {
this.localName = localName;
this.namespace = namespace;
this.key = key;
this.reportClass = reportClass;
}
/**
* Creates a new {@link Report} with this type.
*
* @return
* @throws DavException
*/
public Report createReport(DeltaVResource resource, ReportInfo info) throws DavException {
try {
Report report = (Report) reportClass.getConstructor(new Class[0]).newInstance(new Object[0]);
report.init(resource, info);
return report;
} catch (Exception e) {
// should never occur
throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to register Report.");
}
}
/**
* Returns an Xml element representing this report type. It may be used to
* build the body for a REPORT request.
*
* @param document
* @return Xml representation
* @see XmlSerializable#toXml(org.w3c.dom.Document)
*/
public Element toXml(Document document) {
return DomUtil.createElement(document, localName, namespace);
}
/**
* Returns true if this <code>ReportType</code> is requested by the given
* <code>ReportInfo</code>
*
* @param reqInfo
* @return
*/
public boolean isRequestedReportType(ReportInfo reqInfo) {
if (reqInfo != null) {
return getReportName().equals(reqInfo.getReportName());
}
return false;
}
/**
* Return the qualified name of this <code>ReportType</code>.
*
* @return qualified name
*/
public String getReportName() {
return key;
}
/**
*
* @return
*/
public String getLocalName() {
return localName;
}
/**
*
* @return
*/
public Namespace getNamespace() {
return namespace;
}
/**
* Register the report type with the given name, namespace and class, that can
* run that report.
*
* @param localName
* @param namespace
* @param reportClass
* @return
* @throws IllegalArgumentException if either parameter is <code>null</code> or
* if the given class does not implement the {@link Report} interface or if
* it does not provide an empty constructor.
*/
public static ReportType register(String localName, Namespace namespace, Class reportClass) {
if (localName == null || namespace == null || reportClass == null) {
throw new IllegalArgumentException("A ReportType cannot be registered with a null name, namespace or report class");
}
String key = DomUtil.getQualifiedName(localName, namespace);
if (types.containsKey(key)) {
return (ReportType) types.get(key);
} else {
// test if this report class has an empty constructor and implements Report interface
boolean isValidClass = false;
Class[] interfaces = reportClass.getInterfaces();
for (int i = 0; i < interfaces.length && !isValidClass; i++) {
isValidClass = (interfaces[i] == Report.class);
}
if (!isValidClass) {
throw new IllegalArgumentException("The specified report class must implement the Report interface.");
}
try {
reportClass.getConstructor(new Class[0]);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("The specified report class must provide a default constructor.");
}
ReportType type = new ReportType(localName, namespace, key, reportClass);
types.put(key, type);
return type;
}
}
/**
* Return the <code>ReportType</code> requested by the given report info object.
*
* @param reportInfo
* @return the requested <code>ReportType</code>
* @throws IllegalArgumentException if the reportInfo is <code>null</code> or
* if the requested report type has not been registered yet.
*/
public static ReportType getType(ReportInfo reportInfo) {
if (reportInfo == null) {
throw new IllegalArgumentException("ReportInfo must not be null.");
}
String key = reportInfo.getReportName();
if (types.containsKey(key)) {
return (ReportType) types.get(key);
} else {
throw new IllegalArgumentException("The request report '"+key+"' has not been registered yet.");
}
}
}