Java tutorial
/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.xpn.xwiki.api; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; import org.apache.commons.fileupload.FileItem; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.suigeneris.jrcs.diff.DifferentiationFailedException; import org.suigeneris.jrcs.diff.delta.Delta; import org.suigeneris.jrcs.rcs.Version; import org.xwiki.context.Execution; import org.xwiki.context.ExecutionContext; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.DocumentReferenceResolver; import org.xwiki.model.reference.EntityReferenceSerializer; import org.xwiki.rendering.parser.ParseException; import org.xwiki.rendering.syntax.Syntax; import org.xwiki.rendering.syntax.SyntaxFactory; import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiConstant; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.criteria.impl.Period; import com.xpn.xwiki.criteria.impl.PeriodFactory; import com.xpn.xwiki.criteria.impl.Range; import com.xpn.xwiki.criteria.impl.RangeFactory; import com.xpn.xwiki.criteria.impl.RevisionCriteria; import com.xpn.xwiki.criteria.impl.Scope; import com.xpn.xwiki.criteria.impl.ScopeFactory; import com.xpn.xwiki.doc.AttachmentDiff; import com.xpn.xwiki.doc.MetaDataDiff; import com.xpn.xwiki.doc.XWikiAttachment; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.doc.XWikiDocumentArchive; import com.xpn.xwiki.doc.XWikiLink; import com.xpn.xwiki.doc.XWikiLock; import com.xpn.xwiki.objects.BaseObject; import com.xpn.xwiki.objects.BaseProperty; import com.xpn.xwiki.objects.ObjectDiff; import com.xpn.xwiki.objects.classes.BaseClass; import com.xpn.xwiki.plugin.fileupload.FileUploadPlugin; import com.xpn.xwiki.stats.api.XWikiStatsService; import com.xpn.xwiki.stats.impl.DocumentStats; import com.xpn.xwiki.stats.impl.RefererStats; import com.xpn.xwiki.util.TOCGenerator; import com.xpn.xwiki.util.Util; import com.xpn.xwiki.web.Utils; /** * This class represents a document or page in the wiki. * This is a security and usability wrapper which wraps {@link com.xpn.xwiki.doc.XWikiDocument} * In scripting, an object representing the document in which the script resides will be bound to a variable called * doc. * * @version $Id: 738bdd6e784f9350b87a0f23035940c2618cdc1c $ */ public class Document extends Api { /** Logging helper object. */ private static final Logger LOGGER = LoggerFactory.getLogger(Document.class); /** * The XWikiDocument object wrapped by this API. */ protected XWikiDocument doc; /** * Indicates if this API wraps a cloned XWikiDocument. */ protected boolean cloned = false; /** * Convenience object used by object related methods. */ protected Object currentObj; /** * Used to resolve a string into a proper Document Reference using the current document's reference to fill the * blanks, except for the page name for which the default page name is used instead and for the wiki name for which * the current wiki is used instead of the current document reference's wiki. */ @SuppressWarnings("unchecked") private DocumentReferenceResolver<String> currentMixedDocumentReferenceResolver = Utils .getComponent(DocumentReferenceResolver.class, "currentmixed"); /** * Used to convert a proper Document Reference to string (standard form). */ @SuppressWarnings("unchecked") private EntityReferenceSerializer<String> defaultEntityReferenceSerializer = Utils .getComponent(EntityReferenceSerializer.class); /** * Used to convert a proper Document Reference to a string but without the wiki name. */ @SuppressWarnings("unchecked") private EntityReferenceSerializer<String> localEntityReferenceSerializer = Utils .getComponent(EntityReferenceSerializer.class, "local"); /** * Used to convert user references to string. */ @SuppressWarnings("unchecked") private EntityReferenceSerializer<String> compactWikiEntityReferenceSerializer = Utils .getComponent(EntityReferenceSerializer.class, "compactwiki"); /** * Document constructor. * * @param doc The XWikiDocument object to wrap. * @param context The current request context. */ public Document(XWikiDocument doc, XWikiContext context) { super(context); this.doc = doc; } /** * Get the XWikiDocument wrapped by this API. This function is accessible only if you have the programming rights * give access to the priviledged API of the Document. * * @return The XWikiDocument wrapped by this API. */ public XWikiDocument getDocument() { if (hasProgrammingRights()) { return this.doc; } else { return null; } } /** * Get a clone of the XWikiDocument wrapped by this API. * * @return A clone of the XWikiDocument wrapped by this API. */ protected XWikiDocument getDoc() { if (!this.cloned) { this.doc = this.doc.clone(); this.cloned = true; } return this.doc; } /** * return the ID of the document. this ID is unique across the wiki. * * @return the id of the document. */ public long getId() { return this.doc.getId(); } /** * @since 2.3M1 */ public DocumentReference getDocumentReference() { // Clone the document reference since it can be modified return new DocumentReference(this.doc.getDocumentReference()); } /** * return the name of a document. for exemple if the fullName of a document is "MySpace.Mydoc", the name is MyDoc. * * @return the name of the document */ public String getName() { return this.doc.getDocumentReference().getName(); } /** * return the name of the space of the document for example if the fullName of a document is "MySpace.Mydoc", the * name is MySpace. * * @return the name of the space of the document */ public String getSpace() { return this.doc.getDocumentReference().getLastSpaceReference().getName(); } /** * Get the name wiki where the document is stored. * * @return The name of the wiki where this document is stored. * @since XWiki Core 1.1.2, XWiki Core 1.2M2 */ public String getWiki() { return this.doc.getDocumentReference().getWikiReference().getName(); } /** * Get the name of the space of the document for exemple if the fullName of a document is "MySpace.Mydoc", the name * is MySpace. * * @return The name of the space of the document. * @deprecated use {@link #getSpace()} instead of this function. */ @Deprecated public String getWeb() { return this.doc.getSpace(); } /** * Get the fullName of the document. If a document is named "MyDoc" in space "MySpace", the fullname is * "MySpace.MyDoc". In a wiki, all the documents have a different fullName. * * @return fullName of the document. */ public String getFullName() { return this.localEntityReferenceSerializer.serialize(this.doc.getDocumentReference()); } /** * Get the complete fullName of the document. The real full name of the document containing the name of the wiki * where the document is stored. For a document stored in the wiki "xwiki", in space "MySpace", named "MyDoc", its * complete full name is "xwiki:MySpace.MyDoc". * * @return The complete fullName of the document. * @since XWiki Core 1.1.2, XWiki Core 1.2M2 */ public String getPrefixedFullName() { return this.defaultEntityReferenceSerializer.serialize(this.doc.getDocumentReference()); } /** * Get a Version object representing the current version of the document. * * @return A Version object representing the current version of the document */ public Version getRCSVersion() { return this.doc.getRCSVersion(); } /** * Get a string representing the current version of the document. * * @return A string representing the current version of the document. */ public String getVersion() { return this.doc.getVersion(); } /** * Get a string representing the previous version of the document. * * @return A string representing the previous version of the document. If this is the first version then it returns * null. */ public String getPreviousVersion() { return this.doc.getPreviousVersion(); } /** * Get the value of the title field of the document. * * @return The value of the title field of the document. */ public String getTitle() { return this.doc.getTitle(); } /** * Get document title. If a title has not been provided through the title field, it looks for a section title in the * document's content and if not found return the page name. The returned title is also interpreted which means it's * allowed to use Velocity, Groovy, etc syntax within a title. * * @return The document title as XHTML */ public String getDisplayTitle() { return this.doc.getRenderedTitle(Syntax.XHTML_1_0, getXWikiContext()); } /** * @return the document title as plain text (all markup removed) * @since 3.0M1 */ public String getPlainTitle() { return this.doc.getRenderedTitle(Syntax.PLAIN_1_0, getXWikiContext()); } /** * @see XWikiDocument#getRenderedTitle(Syntax, XWikiContext) */ public String getRenderedTitle(String syntaxId) throws XWikiException { try { return this.doc.getRenderedTitle( Utils.getComponent(SyntaxFactory.class).createSyntaxFromIdString(syntaxId), getXWikiContext()); } catch (ParseException e) { LOGGER.error("Failed to parse provided syntax identifier [" + syntaxId + "]", e); throw new XWikiException(XWikiException.MODULE_XWIKI_RENDERING, XWikiException.ERROR_XWIKI_UNKNOWN, "Failed to parse syntax identifier [" + syntaxId + "]", e); } catch (Exception e) { LOGGER.error("Failed to render document [" + getPrefixedFullName() + "] title content", e); throw new XWikiException(XWikiException.MODULE_XWIKI_RENDERING, XWikiException.ERROR_XWIKI_UNKNOWN, "Failed to render document [" + getPrefixedFullName() + "] content title", e); } } // TODO: document this. public String getFormat() { return this.doc.getFormat(); } /** * Get fullName of the profile document of the author of the current version of the document. Example: XWiki.Admin. * * @return The fullName of the profile document of the author of the current version of the document. */ public String getAuthor() { String author = ""; DocumentReference authorReference = this.doc.getAuthorReference(); if (authorReference != null) { author = this.compactWikiEntityReferenceSerializer.serialize(authorReference, this.doc.getDocumentReference()); } return author; } /** * Get fullName of the profile document of the author of the last content modification in the document. Example: * XWiki.Admin. * * @return The fullName of the profile document of the author of the last content modification in the document. */ public String getContentAuthor() { String contentAuthor = ""; DocumentReference contentAuthorReference = this.doc.getContentAuthorReference(); if (contentAuthorReference != null) { contentAuthor = this.compactWikiEntityReferenceSerializer.serialize(contentAuthorReference, this.doc.getDocumentReference()); } return contentAuthor; } /** * Get the date when the current document version has been created, i.e. the date of the last modification of the * document. * * @return The date where the current document version has been created. */ public Date getDate() { return this.doc.getDate(); } /** * Get the date when the last content modification has been done on the document. * * @return The date where the last content modification has been done on the document. */ public Date getContentUpdateDate() { return this.doc.getContentUpdateDate(); } /** * Get the date when the document has been created. return The date when the document has been created. */ public Date getCreationDate() { return this.doc.getCreationDate(); } /** * Get the name of the parent of this document. * * @return The name of the parent of this document. */ public String getParent() { return this.doc.getParent(); } /** * Get fullName of the profile document of the document creator. * * @return The fullName of the profile document of the document creator. */ public String getCreator() { String creator = ""; DocumentReference creatorReference = this.doc.getCreatorReference(); if (creatorReference != null) { creator = this.compactWikiEntityReferenceSerializer.serialize(creatorReference, getDocumentReference()); } return creator; } /** * Get raw content of the document, i.e. the content that is visible through the wiki editor. * * @return The raw content of the document. */ public String getContent() { return this.doc.getContent(); } /** * @return The syntax representing the syntax used for the document's content * @since 2.3M1 */ public Syntax getSyntax() { return this.doc.getSyntax(); } /** * Get the Syntax id representing the syntax used for the document. For example "xwiki/1.0" represents the first * version XWiki syntax while "xwiki/2.0" represents version 2.0 of the XWiki Syntax. * * @return The syntax id representing the syntax used for the document. * @deprecated since 2.3M1 use {@link #getSyntax()} instead */ @Deprecated public String getSyntaxId() { return this.doc.getSyntax().toIdString(); } /** * Get the language of the document. If the document is a translation it returns the language set for it, otherwise, * it returns the default language in the wiki where the document is stored. * * @return The language of the document. */ public String getLanguage() { return this.doc.getLanguage(); } public String getTemplate() { String templateReferenceAsString = ""; DocumentReference templateDocumentReference = this.doc.getTemplateDocumentReference(); if (templateDocumentReference != null) { templateReferenceAsString = this.localEntityReferenceSerializer.serialize(templateDocumentReference); } return templateReferenceAsString; } /** * return the real language of the document */ public String getRealLanguage() throws XWikiException { return this.doc.getRealLanguage(getXWikiContext()); } /** * return the language of the default document */ public String getDefaultLanguage() { return this.doc.getDefaultLanguage(); } public String getDefaultTemplate() { return this.doc.getDefaultTemplate(); } /** * @return the comment of the latest update of the document. */ public String getComment() { return this.doc.getComment(); } /** * @return true if the last change to this document was a minor edit. */ public boolean isMinorEdit() { return this.doc.isMinorEdit(); } /** * @return the list of existing translations for this document. */ public List<String> getTranslationList() throws XWikiException { return this.doc.getTranslationList(getXWikiContext()); } /** * @return the translated document's content if the wiki is multilingual, the language is first checked in the * URL, the cookie, the user profile and finally the wiki configuration if not, the language is the one * on the wiki configuration. */ public String getTranslatedContent() throws XWikiException { return this.doc.getTranslatedContent(getXWikiContext()); } /** * @return the translated content in the given language */ public String getTranslatedContent(String language) throws XWikiException { return this.doc.getTranslatedContent(language, getXWikiContext()); } /** * @return the translated document in the given document */ public Document getTranslatedDocument(String language) throws XWikiException { return this.doc.getTranslatedDocument(language, getXWikiContext()).newDocument(getXWikiContext()); } /** * @return the tranlated Document if the wiki is multilingual, the language is first checked in the URL, the * cookie, the user profile and finally the wiki configuration if not, the language is the one on the * wiki configuration. */ public Document getTranslatedDocument() throws XWikiException { return this.doc.getTranslatedDocument(getXWikiContext()).newDocument(getXWikiContext()); } /** * @return the content of the document rendered. */ public String getRenderedContent() throws XWikiException { return this.doc.getRenderedContent(getXWikiContext()); } /** * @param text the text to render * @return the given text rendered in the context of this document * @deprecated since 1.6M1 use {@link #getRenderedContent(String, String)} */ @Deprecated public String getRenderedContent(String text) throws XWikiException { return this.doc.getRenderedContent(text, Syntax.XWIKI_1_0.toIdString(), getXWikiContext()); } /** * @param text the text to render * @param syntaxId the id of the Syntax used by the passed text (for example: "xwiki/1.0") * @return the given text rendered in the context of this document using the passed Syntax * @since 1.6M1 */ public String getRenderedContent(String text, String syntaxId) throws XWikiException { return this.doc.getRenderedContent(text, syntaxId, getXWikiContext()); } /** * @param text the text to render * @param sourceSyntaxId the id of the Syntax used by the passed text (for example: "xwiki/1.0") * @param targetSyntaxId the id of the syntax in which to render the document content * @return the given text rendered in the context of this document using the passed Syntax * @since 2.0M3 */ public String getRenderedContent(String text, String sourceSyntaxId, String targetSyntaxId) throws XWikiException { return this.doc.getRenderedContent(text, sourceSyntaxId, targetSyntaxId, getXWikiContext()); } /** * @param targetSyntax the syntax in which to render the document content * @return the rendered content * @throws XWikiException error when rendering content */ public String getRenderedContent(Syntax targetSyntax) throws XWikiException { return this.doc.getRenderedContent(targetSyntax, getXWikiContext()); } /** * Get the document's content XML-escaped. * * @return an XML-escaped version of the content of this document. */ public String getEscapedContent() throws XWikiException { return this.doc.getEscapedContent(getXWikiContext()); } /** * @return the archive of the document in a string format. */ public String getArchive() throws XWikiException { return this.doc.getDocumentArchive(getXWikiContext()).getArchive(getXWikiContext()); } /** * Get the archive of this document's history. * This function is accessible only if you have the programming rights. * * @return the archive of this document's history as an {@link XWikiDocumentArchive}. */ public XWikiDocumentArchive getDocumentArchive() throws XWikiException { if (hasProgrammingRights()) { return this.doc.getDocumentArchive(getXWikiContext()); } return null; } /** * @return true if the document is a new one (ie it has never been saved) or false otherwise */ public boolean isNew() { return this.doc.isNew(); } /** * Return the URL of download for the the given attachment name. * * @param filename the name of the attachment * @return A String with the URL */ public String getAttachmentURL(String filename) { return this.doc.getAttachmentURL(filename, "download", getXWikiContext()); } /** * Get the URL of the given action for the the given attachment name. * * @param filename the name of the attachment. * @param action what to do to the file for example "delattachment", "download" or "downloadrev". * @return a string representation of a URL to do the given opperation. */ public String getAttachmentURL(String filename, String action) { return this.doc.getAttachmentURL(filename, action, getXWikiContext()); } /** * Get the URL of an action on an attachment. * the given action for the the given attachment name with "queryString" parameters * * @param filename the name of the attachment. * @param action what to do to the file for example "delattachment", "download" or "downloadrev" * @param queryString parameters added to the URL, the "rev" parameter is used to specify a revision if using * the "downloadrev" action. The query string must not begin with an ? character. * @return a string representation of a URL to do the given opperation. */ public String getAttachmentURL(String filename, String action, String queryString) { return this.doc.getAttachmentURL(filename, action, queryString, getXWikiContext()); } /** * Get an old revision of an attachment. * * @param filename the name of the attachment. * @param version a revision number such as "1.1" or "1.2". * @return the URL for accessing to the archive of the attachment "filename" at the version "version" */ public String getAttachmentRevisionURL(String filename, String version) { return this.doc.getAttachmentRevisionURL(filename, version, getXWikiContext()); } /** * Get an old revision of an attachment. * * @param filename the name of the attachment. * @param version a revision number such as "1.1" or "1.2". * @param queryString additional query parameters to pass in the request. * @return the URL for accessing to the archive of the attachment "filename" at the version "version" with the given * queryString parameters. */ public String getAttachmentRevisionURL(String filename, String version, String queryString) { return this.doc.getAttachmentRevisionURL(filename, version, queryString, getXWikiContext()); } /** * Get the URL of this document. * * @return the URL to view this document, this will be a relitive URL for example: /xwiki/bin/view/Main/WebHome * @see #getExternalURL() for an absolute URL which can used outside of the site. */ public String getURL() { return this.doc.getURL("view", getXWikiContext()); } /** * Get the URL to do a given action on this document. * * @param action what to do to the document for example "view", "edit" or "inline". * @return the URL of this document with the given action. * @see #getExternalURL(String) for an absolute URL which can used outside of the site. */ public String getURL(String action) { return this.doc.getURL(action, getXWikiContext()); } /** * Get the URL to do a given action on this document. * * @param action what to do to the document for example "view", "edit" or "inline". * @param queryString parameters to pass in the request eg: "paramA=value1¶mB=value2" * @return the URL of this document with the given action and queryString as parameters. * @see #getExternalURL(String, String) for an absolute URL which can used outside of the site. */ public String getURL(String action, String queryString) { return this.doc.getURL(action, queryString, getXWikiContext()); } /** * Get the external URL to do a given action on this document. * * @return the full URL of the document, sutable for use at external websites for example: * http://www.xwiki.org/xwiki/bin/view/Main/WebHome * @see #getURL() for a reletive URL which can only be used inside of the site. */ public String getExternalURL() { return this.doc.getExternalURL("view", getXWikiContext()); } /** * Get the external URL to do a given action on this document. * * @param action what to do to the document for example "view", "edit" or "inline". * @return the URL of this document with the given action. * @see #getURL() for a relative URL which can only be used inside of the site. */ public String getExternalURL(String action) { return this.doc.getExternalURL(action, getXWikiContext()); } /** * Get the URL to do a given action on this document. * * @param action what to do to the document for example "view", "edit" or "inline". * @param queryString parameters to pass in the request eg: "paramA=value1¶mB=value2" * @return the URL of this document with the given action and queryString as parameters. * @see #getURL() for a relative URL which can only be used inside of the site. */ public String getExternalURL(String action, String queryString) { return this.doc.getExternalURL(action, queryString, getXWikiContext()); } public String getParentURL() throws XWikiException { return this.doc.getParentURL(getXWikiContext()); } public Class getxWikiClass() { BaseClass bclass = this.getDoc().getXClass(); if (bclass == null) { return null; } else { return new Class(bclass, getXWikiContext()); } } public Class[] getxWikiClasses() { List<BaseClass> list = this.getDoc().getXClasses(getXWikiContext()); if (list == null) { return null; } Class[] result = new Class[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = new Class(list.get(i), getXWikiContext()); } return result; } public int createNewObject(String classname) throws XWikiException { return getDoc().createNewObject(classname, getXWikiContext()); } public Object newObject(String classname) throws XWikiException { int nb = createNewObject(classname); return getObject(classname, nb); } public boolean isFromCache() { return this.doc.isFromCache(); } public int getObjectNumbers(String classname) { return this.doc.getObjectNumbers(classname); } public Map<String, Vector<Object>> getxWikiObjects() { Map<DocumentReference, List<BaseObject>> map = this.getDoc().getXObjects(); Map<String, Vector<Object>> resultmap = new HashMap<String, Vector<Object>>(); for (Map.Entry<DocumentReference, List<BaseObject>> entry : map.entrySet()) { List<BaseObject> objects = entry.getValue(); if (objects != null) { resultmap.put(this.localEntityReferenceSerializer.serialize(entry.getKey()), getXObjects(objects)); } } return resultmap; } protected Vector<Object> getXObjects(List<BaseObject> objects) { if (objects == null) { return new Vector<Object>(0); } Vector<Object> result = new Vector<Object>(objects.size()); for (BaseObject bobj : objects) { if (bobj != null) { result.add(newObjectApi(bobj, getXWikiContext())); } } return result; } public Vector<Object> getObjects(String className) { List<BaseObject> objects = this.getDoc().getXObjects(this.doc.resolveClassReference(className)); return getXObjects(objects); } public Object getFirstObject(String fieldname) { try { BaseObject obj = this.getDoc().getFirstObject(fieldname, getXWikiContext()); if (obj == null) { return null; } else { return newObjectApi(obj, getXWikiContext()); } } catch (Exception e) { return null; } } public Object getObject(String classname, String key, String value, boolean failover) { try { BaseObject obj = this.getDoc().getObject(classname, key, value, failover); if (obj == null) { return null; } else { return newObjectApi(obj, getXWikiContext()); } } catch (Exception e) { return null; } } /** * Select a subset of objects from a given class, filtered on a "key = value" criteria. * * @param classname The type of objects to return. * @param key The name of the property used for filtering. * @param value The required value. * @return A Vector of {@link Object objects} matching the criteria. If no objects are found, or if the key is an * empty String, then an empty vector is returned. */ public Vector<Object> getObjects(String classname, String key, String value) { Vector<Object> result = new Vector<Object>(); if (StringUtils.isBlank(key) || value == null) { return getObjects(classname); } try { Vector<BaseObject> allObjects = this.getDoc().getObjects(classname); if (allObjects == null || allObjects.size() == 0) { return result; } else { for (BaseObject obj : allObjects) { if (obj != null) { BaseProperty prop = (BaseProperty) obj.get(key); if (prop == null || prop.getValue() == null) { continue; } if (value.equals(prop.getValue().toString())) { result.add(newObjectApi(obj, getXWikiContext())); } } } } } catch (Exception e) { } return result; } public Object getObject(String classname, String key, String value) { try { BaseObject obj = this.getDoc().getObject(classname, key, value); if (obj == null) { return null; } else { return newObjectApi(obj, getXWikiContext()); } } catch (Exception e) { return null; } } public Object getObject(String classname) { return getObject(classname, false); } /** * get the object of the given className. If there is no object of this className and the create parameter at true, * the object is created. */ public Object getObject(String classname, boolean create) { try { BaseObject obj = getDoc().getObject(classname, create, getXWikiContext()); if (obj == null) { return null; } else { return newObjectApi(obj, getXWikiContext()); } } catch (Exception e) { return null; } } public Object getObject(String classname, int nb) { try { BaseObject obj = this.getDoc().getObject(classname, nb); if (obj == null) { return null; } else { return newObjectApi(obj, getXWikiContext()); } } catch (Exception e) { return null; } } private Object newObjectApi(BaseObject obj, XWikiContext context) { return obj.newObjectApi(obj, context); } public String getXMLContent() throws XWikiException { String xml = this.doc.getXMLContent(getXWikiContext()); return getXWikiContext().getUtil().substitute("s/<email>.*?<\\/email>/<email>********<\\/email>/goi", getXWikiContext().getUtil() .substitute("s/<password>.*?<\\/password>/<password>********<\\/password>/goi", xml)); } public String toXML() throws XWikiException { if (hasProgrammingRights()) { return this.doc.toXML(getXWikiContext()); } else { return ""; } } public org.dom4j.Document toXMLDocument() throws XWikiException { if (hasProgrammingRights()) { return this.doc.toXMLDocument(getXWikiContext()); } else { return null; } } public Version[] getRevisions() throws XWikiException { return this.doc.getRevisions(getXWikiContext()); } public String[] getRecentRevisions() throws XWikiException { return this.doc.getRecentRevisions(5, getXWikiContext()); } public String[] getRecentRevisions(int nb) throws XWikiException { return this.doc.getRecentRevisions(nb, getXWikiContext()); } /** * Get document versions matching criterias like author, minimum creation date, etc. * * @param criteria criteria used to match versions * @return a list of matching versions */ public List<String> getRevisions(RevisionCriteria criteria) throws XWikiException { return this.doc.getRevisions(criteria, this.context); } /** * Get information about a document version : author, date, etc. * * @param version the version you want to get information about * @return a new RevisionInfo object */ public RevisionInfo getRevisionInfo(String version) throws XWikiException { return new RevisionInfo(this.doc.getRevisionInfo(version, getXWikiContext()), getXWikiContext()); } public List<Attachment> getAttachmentList() { List<Attachment> apis = new ArrayList<Attachment>(); for (XWikiAttachment attachment : this.getDoc().getAttachmentList()) { apis.add(new Attachment(this, attachment, getXWikiContext())); } return apis; } public Vector<Object> getComments() { return getComments(true); } public Vector<Object> getComments(boolean asc) { return getXObjects(this.getDoc().getComments(asc)); } public void use(Object object) { this.currentObj = object; } public void use(String className) { this.currentObj = getObject(className); } public void use(String className, int nb) { this.currentObj = getObject(className, nb); } public String getActiveClass() { if (this.currentObj == null) { return null; } else { return this.currentObj.getName(); } } public String displayPrettyName(String fieldname) { if (this.currentObj == null) { return this.doc.displayPrettyName(fieldname, getXWikiContext()); } else { return this.doc.displayPrettyName(fieldname, this.currentObj.getBaseObject(), getXWikiContext()); } } public String displayPrettyName(String fieldname, Object obj) { if (obj == null) { return ""; } return this.doc.displayPrettyName(fieldname, obj.getBaseObject(), getXWikiContext()); } public String displayPrettyName(String fieldname, boolean showMandatory) { if (this.currentObj == null) { return this.doc.displayPrettyName(fieldname, showMandatory, getXWikiContext()); } else { return this.doc.displayPrettyName(fieldname, showMandatory, this.currentObj.getBaseObject(), getXWikiContext()); } } public String displayPrettyName(String fieldname, boolean showMandatory, Object obj) { if (obj == null) { return ""; } return this.doc.displayPrettyName(fieldname, showMandatory, obj.getBaseObject(), getXWikiContext()); } public String displayPrettyName(String fieldname, boolean showMandatory, boolean before) { if (this.currentObj == null) { return this.doc.displayPrettyName(fieldname, showMandatory, before, getXWikiContext()); } else { return this.doc.displayPrettyName(fieldname, showMandatory, before, this.currentObj.getBaseObject(), getXWikiContext()); } } public String displayPrettyName(String fieldname, boolean showMandatory, boolean before, Object obj) { if (obj == null) { return ""; } return this.doc.displayPrettyName(fieldname, showMandatory, before, obj.getBaseObject(), getXWikiContext()); } public String displayTooltip(String fieldname) { if (this.currentObj == null) { return this.doc.displayTooltip(fieldname, getXWikiContext()); } else { return this.doc.displayTooltip(fieldname, this.currentObj.getBaseObject(), getXWikiContext()); } } public String displayTooltip(String fieldname, Object obj) { if (obj == null) { return ""; } return this.doc.displayTooltip(fieldname, obj.getBaseObject(), getXWikiContext()); } public String display(String fieldname) { if (this.currentObj == null) { return this.doc.display(fieldname, getXWikiContext()); } else { return this.doc.display(fieldname, this.currentObj.getBaseObject(), getXWikiContext()); } } public String display(String fieldname, String mode) { if (this.currentObj == null) { return this.doc.display(fieldname, mode, getXWikiContext()); } else { return this.doc.display(fieldname, mode, this.currentObj.getBaseObject(), getXWikiContext()); } } public String display(String fieldname, String mode, String prefix) { if (this.currentObj == null) { return this.doc.display(fieldname, mode, prefix, getXWikiContext()); } else { return this.doc.display(fieldname, mode, prefix, this.currentObj.getBaseObject(), getSyntaxId(), getXWikiContext()); } } public String display(String fieldname, Object obj) { if (obj == null) { return ""; } return this.doc.display(fieldname, obj.getBaseObject(), getXWikiContext()); } /** * @param fieldname the name of the field to display * @param type the type of the field to display * @param obj the object containing the field to display * @param wrappingSyntaxId the syntax of the content in which the result will be included. This to take care of some * escaping depending of the syntax. * @return the rendered field */ public String display(String fieldname, String type, Object obj, String wrappingSyntaxId) { if (obj == null) { return ""; } return this.doc.display(fieldname, type, obj.getBaseObject(), wrappingSyntaxId, getXWikiContext()); } public String display(String fieldname, String mode, Object obj) { if (obj == null) { return ""; } return this.doc.display(fieldname, mode, obj.getBaseObject(), getXWikiContext()); } public String display(String fieldname, String mode, String prefix, Object obj) { if (obj == null) { return ""; } return this.doc.display(fieldname, mode, prefix, obj.getBaseObject(), getSyntaxId(), getXWikiContext()); } public String displayForm(String className, String header, String format) { return this.doc.displayForm(className, header, format, getXWikiContext()); } public String displayForm(String className, String header, String format, boolean linebreak) { return this.doc.displayForm(className, header, format, linebreak, getXWikiContext()); } public String displayForm(String className) { return this.doc.displayForm(className, getXWikiContext()); } public String displayRendered(com.xpn.xwiki.api.PropertyClass pclass, String prefix, Collection object) throws XWikiException { if ((pclass == null) || (object == null)) { return ""; } return this.doc.displayRendered(pclass.getBasePropertyClass(), prefix, object.getCollection(), getXWikiContext()); } public String displayView(com.xpn.xwiki.api.PropertyClass pclass, String prefix, Collection object) { if ((pclass == null) || (object == null)) { return ""; } return this.doc.displayView(pclass.getBasePropertyClass(), prefix, object.getCollection(), getXWikiContext()); } public String displayEdit(com.xpn.xwiki.api.PropertyClass pclass, String prefix, Collection object) { if ((pclass == null) || (object == null)) { return ""; } return this.doc.displayEdit(pclass.getBasePropertyClass(), prefix, object.getCollection(), getXWikiContext()); } public String displayHidden(com.xpn.xwiki.api.PropertyClass pclass, String prefix, Collection object) { if ((pclass == null) || (object == null)) { return ""; } return this.doc.displayHidden(pclass.getBasePropertyClass(), prefix, object.getCollection(), getXWikiContext()); } public List<String> getIncludedPages() { return this.doc.getIncludedPages(getXWikiContext()); } public List<String> getIncludedMacros() { return this.doc.getIncludedMacros(getXWikiContext()); } public List<String> getLinkedPages() { return new ArrayList<String>(this.doc.getUniqueLinkedPages(getXWikiContext())); } public Attachment getAttachment(String filename) { XWikiAttachment attach = this.getDoc().getAttachment(filename); if (attach == null) { return null; } else { return new Attachment(this, attach, getXWikiContext()); } } public List<Delta> getContentDiff(Document origdoc, Document newdoc) throws XWikiException, DifferentiationFailedException { try { if ((origdoc == null) && (newdoc == null)) { return Collections.emptyList(); } if (origdoc == null) { return this.doc.getContentDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc, getXWikiContext()); } if (newdoc == null) { return this.doc.getContentDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()), getXWikiContext()); } return this.doc.getContentDiff(origdoc.doc, newdoc.doc, getXWikiContext()); } catch (Exception e) { java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() }; List list = new ArrayList(); XWikiException xe = new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_CONTENT_ERROR, "Error while making content diff of {0} between version {1} and version {2}", e, args); String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext()); list.add(errormsg); return list; } } public List<Delta> getXMLDiff(Document origdoc, Document newdoc) throws XWikiException, DifferentiationFailedException { try { if ((origdoc == null) && (newdoc == null)) { return Collections.emptyList(); } if (origdoc == null) { return this.doc.getXMLDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc, getXWikiContext()); } if (newdoc == null) { return this.doc.getXMLDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()), getXWikiContext()); } return this.doc.getXMLDiff(origdoc.doc, newdoc.doc, getXWikiContext()); } catch (Exception e) { java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() }; List list = new ArrayList(); XWikiException xe = new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_XML_ERROR, "Error while making xml diff of {0} between version {1} and version {2}", e, args); String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext()); list.add(errormsg); return list; } } public List<Delta> getRenderedContentDiff(Document origdoc, Document newdoc) throws XWikiException, DifferentiationFailedException { try { if ((origdoc == null) && (newdoc == null)) { return Collections.emptyList(); } if (origdoc == null) { return this.doc.getRenderedContentDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc, getXWikiContext()); } if (newdoc == null) { return this.doc.getRenderedContentDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()), getXWikiContext()); } return this.doc.getRenderedContentDiff(origdoc.doc, newdoc.doc, getXWikiContext()); } catch (Exception e) { java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() }; List list = new ArrayList(); XWikiException xe = new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_RENDERED_ERROR, "Error while making rendered diff of {0} between version {1} and version {2}", e, args); String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext()); list.add(errormsg); return list; } } public List<MetaDataDiff> getMetaDataDiff(Document origdoc, Document newdoc) throws XWikiException { try { if ((origdoc == null) && (newdoc == null)) { return Collections.emptyList(); } if (origdoc == null) { return this.doc.getMetaDataDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc, getXWikiContext()); } if (newdoc == null) { return this.doc.getMetaDataDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()), getXWikiContext()); } return this.doc.getMetaDataDiff(origdoc.doc, newdoc.doc, getXWikiContext()); } catch (Exception e) { java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() }; List list = new ArrayList(); XWikiException xe = new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_METADATA_ERROR, "Error while making meta data diff of {0} between version {1} and version {2}", e, args); String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext()); list.add(errormsg); return list; } } public List<List<ObjectDiff>> getObjectDiff(Document origdoc, Document newdoc) { try { if ((origdoc == null) && (newdoc == null)) { return Collections.emptyList(); } if (origdoc == null) { return this.doc.getObjectDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc, getXWikiContext()); } if (newdoc == null) { return this.doc.getObjectDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()), getXWikiContext()); } return this.doc.getObjectDiff(origdoc.doc, newdoc.doc, getXWikiContext()); } catch (Exception e) { java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() }; List list = new ArrayList(); XWikiException xe = new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_OBJECT_ERROR, "Error while making meta object diff of {0} between version {1} and version {2}", e, args); String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext()); list.add(errormsg); return list; } } public List<List<ObjectDiff>> getClassDiff(Document origdoc, Document newdoc) { try { if ((origdoc == null) && (newdoc == null)) { return Collections.emptyList(); } if (origdoc == null) { return this.doc.getClassDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc, getXWikiContext()); } if (newdoc == null) { return this.doc.getClassDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()), getXWikiContext()); } return this.doc.getClassDiff(origdoc.doc, newdoc.doc, getXWikiContext()); } catch (Exception e) { java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() }; List list = new ArrayList(); XWikiException xe = new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_CLASS_ERROR, "Error while making class diff of {0} between version {1} and version {2}", e, args); String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext()); list.add(errormsg); return list; } } public List<AttachmentDiff> getAttachmentDiff(Document origdoc, Document newdoc) { try { if ((origdoc == null) && (newdoc == null)) { return Collections.emptyList(); } if (origdoc == null) { return this.doc.getAttachmentDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc, getXWikiContext()); } if (newdoc == null) { return this.doc.getAttachmentDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()), getXWikiContext()); } return this.doc.getAttachmentDiff(origdoc.doc, newdoc.doc, getXWikiContext()); } catch (Exception e) { java.lang.Object[] args = { (origdoc != null) ? origdoc.getFullName() : null, (origdoc != null) ? origdoc.getVersion() : null, (newdoc != null) ? newdoc.getVersion() : null }; List list = new ArrayList(); XWikiException xe = new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_ATTACHMENT_ERROR, "Error while making attachment diff of {0} between version {1} and version {2}", e, args); String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext()); list.add(errormsg); return list; } } public List<Delta> getLastChanges() throws XWikiException, DifferentiationFailedException { return this.doc.getLastChanges(getXWikiContext()); } /** * Get statistics about the number of request for the current page during the current month. * * @param action the type of request for which to retrieve statistics: view, edit... * @return the statistics object holding information for this document and the current month */ public DocumentStats getCurrentMonthPageStats(String action) { Scope scope = ScopeFactory.createPageScope(this.getFullName()); Range range = RangeFactory.ALL; Period period = PeriodFactory.getCurrentMonth(); XWikiStatsService statisticsService = getXWikiContext().getWiki().getStatsService(getXWikiContext()); List<DocumentStats> stats = statisticsService.getDocumentStatistics(action, scope, period, range, this.context); if (stats.size() > 0) { return stats.get(0); } return new DocumentStats(); } /** * Get statistics about the number of request for the current space during the current month. * * @param action the type of request for which to retrieve statistics: view, edit... * @return the statistics object holding information for the document's space and the current month */ public DocumentStats getCurrentMonthSpaceStats(String action) { Scope scope = ScopeFactory.createSpaceScope(this.doc.getSpace(), false); Range range = RangeFactory.ALL; Period period = PeriodFactory.getCurrentMonth(); XWikiStatsService statisticsService = getXWikiContext().getWiki().getStatsService(getXWikiContext()); List<DocumentStats> stats = statisticsService.getDocumentStatistics(action, scope, period, range, this.context); if (stats.size() > 0) { return stats.get(0); } return new DocumentStats(); } /** * Get referer statistics for the current document during the current month. * * @return a list of referer statistics for the document's space */ public List<RefererStats> getCurrentMonthRefStats() { Scope scope = ScopeFactory.createPageScope(this.getFullName()); Range range = RangeFactory.ALL; Period period = PeriodFactory.getCurrentMonth(); XWikiStatsService statisticsService = getXWikiContext().getWiki().getStatsService(getXWikiContext()); List<RefererStats> stats = statisticsService.getRefererStatistics("", scope, period, range, this.context); return stats; } public boolean checkAccess(String right) { try { return getXWikiContext().getWiki().checkAccess(right, this.doc, getXWikiContext()); } catch (XWikiException e) { return false; } } public boolean hasAccessLevel(String level) { try { return getXWikiContext().getWiki().getRightService().hasAccessLevel(level, getXWikiContext().getUser(), this.getPrefixedFullName(), getXWikiContext()); } catch (Exception e) { return false; } } @Override public boolean hasAccessLevel(String level, String user) { try { return getXWikiContext().getWiki().getRightService().hasAccessLevel(level, user, this.getPrefixedFullName(), getXWikiContext()); } catch (Exception e) { return false; } } public boolean getLocked() { try { XWikiLock lock = this.doc.getLock(getXWikiContext()); if (lock != null && !getXWikiContext().getUser().equals(lock.getUserName())) { return true; } else { return false; } } catch (Exception e) { return false; } } public String getLockingUser() { try { XWikiLock lock = this.doc.getLock(getXWikiContext()); if (lock != null && !getXWikiContext().getUser().equals(lock.getUserName())) { return lock.getUserName(); } else { return ""; } } catch (XWikiException e) { return ""; } } public Date getLockingDate() { try { XWikiLock lock = this.doc.getLock(getXWikiContext()); if (lock != null && !getXWikiContext().getUser().equals(lock.getUserName())) { return lock.getDate(); } else { return null; } } catch (XWikiException e) { return null; } } public java.lang.Object get(String classOrFieldName) { if (this.currentObj != null) { return this.doc.display(classOrFieldName, this.currentObj.getBaseObject(), getXWikiContext()); } BaseObject object = this.doc.getFirstObject(classOrFieldName, getXWikiContext()); if (object != null) { return this.doc.display(classOrFieldName, object, getXWikiContext()); } return this.getDoc().getObject(classOrFieldName); } public java.lang.Object getValue(String fieldName) { Object object; if (this.currentObj == null) { object = new Object(this.getDoc().getFirstObject(fieldName, getXWikiContext()), getXWikiContext()); } else { object = this.currentObj; } return getValue(fieldName, object); } public java.lang.Object getValue(String fieldName, Object object) { if (object != null) { try { return ((BaseProperty) object.getBaseObject().safeget(fieldName)).getValue(); } catch (NullPointerException e) { return null; } } return null; } public String getTextArea() { return com.xpn.xwiki.XWiki.getTextArea(this.doc.getContent(), getXWikiContext()); } /** * Returns data needed for a generation of Table of Content for this document. * * @param init an intial level where the TOC generation should start at * @param max maximum level TOC is generated for * @param numbered if should generate numbering for headings * @return a map where an heading (title) ID is the key and value is another map with two keys: text, level and * numbering */ public Map<String, Map<String, java.lang.Object>> getTOC(int init, int max, boolean numbered) { getXWikiContext().put("tocNumbered", new Boolean(numbered)); return TOCGenerator.generateTOC(getContent(), init, max, numbered, getXWikiContext()); } public String getTags() { return this.doc.getTags(getXWikiContext()); } public List<String> getTagList() { return this.getDoc().getTagsList(getXWikiContext()); } public List<String> getTagsPossibleValues() { return this.doc.getTagsPossibleValues(getXWikiContext()); } public void insertText(String text, String marker) throws XWikiException { if (hasAccessLevel("edit")) { getDoc().insertText(text, marker, getXWikiContext()); } } @Override public boolean equals(java.lang.Object arg0) { if (!(arg0 instanceof Document)) { return false; } Document d = (Document) arg0; return d.getXWikiContext().equals(getXWikiContext()) && this.doc.equals(d.doc); } public List<String> getBacklinks() throws XWikiException { return this.doc.getBackLinkedPages(getXWikiContext()); } public List<XWikiLink> getLinks() throws XWikiException { return new ArrayList<XWikiLink>(this.doc.getUniqueWikiLinkedPages(getXWikiContext())); } /** * Get the top sections contained in the document. * <p> * The section are filtered by xwiki.section.depth property on the maximum depth of the sections to return. This * method is usually used to get "editable" sections. * * @return the sections in the current document */ public List<DocumentSection> getSections() throws XWikiException { return this.doc.getSections(); } /** * Get document children. Children are documents with the current document as parent. * * @return The list of children for the current document. * @since 1.8 Milestone 2 */ public List<String> getChildren() throws XWikiException { return this.doc.getChildren(getXWikiContext()); } /** * Get document children. Children are documents with the current document as parent. Where a document has a large * number of children, one may desire to return a certain number of children (nb) and skip some number (start) of * the first results. * * @param nb The number of results to return. * @param start The number of results to skip before we begin returning results. * @return The list of children for the current document. */ public List<String> getChildren(int nb, int start) throws XWikiException { return this.doc.getChildren(nb, start, getXWikiContext()); } /** * @return "inline" if the document should be edited in inline mode by default or "edit" otherwise. * @throws XWikiException if an error happens when computing the edit mode */ public String getDefaultEditMode() throws XWikiException { return this.doc.getDefaultEditMode(getXWikiContext()); } public String getDefaultEditURL() throws XWikiException { return this.doc.getDefaultEditURL(getXWikiContext()); } public String getEditURL(String action, String mode) throws XWikiException { return this.doc.getEditURL(action, mode, getXWikiContext()); } public String getEditURL(String action, String mode, String language) { return this.doc.getEditURL(action, mode, language, getXWikiContext()); } public boolean isCurrentUserCreator() { return this.doc.isCurrentUserCreator(getXWikiContext()); } public boolean isCurrentUserPage() { return this.doc.isCurrentUserPage(getXWikiContext()); } public boolean isCurrentLocalUserPage() { return this.doc.isCurrentLocalUserPage(getXWikiContext()); } public boolean isCreator(String username) { return this.doc.isCreator(username); } public void set(String fieldname, java.lang.Object value) { Object obj; if (this.currentObj != null) { obj = this.currentObj; } else { obj = getFirstObject(fieldname); } set(fieldname, value, obj); } public void set(String fieldname, java.lang.Object value, Object obj) { if (obj == null) { return; } obj.set(fieldname, value); } public void setTitle(String title) { getDoc().setTitle(title); } public void setCustomClass(String customClass) { getDoc().setCustomClass(customClass); } public void setParent(String parent) { getDoc().setParent(parent); } public void setContent(String content) { getDoc().setContent(content); } /** * @param syntax the Syntax representing the syntax used for the current document's content. * @since 2.3M1 */ public void setSyntax(Syntax syntax) { getDoc().setSyntax(syntax); } /** * @param syntaxId the Syntax id representing the syntax used for the current document. For example "xwiki/1.0" * represents the first version XWiki syntax while "xwiki/2.0" represents version 2.0 of the XWiki * Syntax. */ public void setSyntaxId(String syntaxId) { getDoc().setSyntaxId(syntaxId); } public void setDefaultTemplate(String dtemplate) { getDoc().setDefaultTemplate(dtemplate); } public void setComment(String comment) { getDoc().setComment(comment); } public void setMinorEdit(boolean isMinor) { getDoc().setMinorEdit(isMinor); } public void save() throws XWikiException { save("", false); } public void save(String comment) throws XWikiException { save(comment, false); } public void save(String comment, boolean minorEdit) throws XWikiException { if (hasAccessLevel("edit")) { saveDocument(comment, minorEdit); } else { java.lang.Object[] args = { this.defaultEntityReferenceSerializer.serialize(getDocumentReference()) }; throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access denied in edit mode on document {0}", null, args); } } public void saveWithProgrammingRights() throws XWikiException { saveWithProgrammingRights("", false); } public void saveWithProgrammingRights(String comment) throws XWikiException { saveWithProgrammingRights(comment, false); } public void saveWithProgrammingRights(String comment, boolean minorEdit) throws XWikiException { if (hasProgrammingRights()) { saveDocument(comment, minorEdit); } else { java.lang.Object[] args = { this.getFullName() }; throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access denied with no programming rights document {0}", null, args); } } /** * Save the document if the {@link #getContentAuthor content author} of the script calling this method has * permission to do so. The author of this document is also set to the said content author. * * @throws XWikiException if script author is not allowed to save the document or if save operation fails. * @since 2.3M2 */ public void saveAsAuthor() throws XWikiException { saveAsAuthor("", false); } /** * Save the document if the {@link #getContentAuthor content author} of the script calling this method has * permission to do so. The author of this document is also set to the said content author. * * @param comment The comment to display in document history (what did you change in the document) * @throws XWikiException if script author is not allowed to save the document or if save operation fails. * @since 2.3M2 */ public void saveAsAuthor(String comment) throws XWikiException { saveAsAuthor(comment, false); } /** * Save the document if the {@link #getContentAuthor content author} of the script calling this method has * permission to do so. The author of this document is also set to the said content author. * * @param comment The comment to display in document history (what did you change in the document) * @param minorEdit Set true to advance the document version number by 0.1 or false to advance version to the next * integer + 0.1 eg: 25.1 * @throws XWikiException if script author is not allowed to save the document or if save operation fails. * @since 2.3M2 */ public void saveAsAuthor(String comment, boolean minorEdit) throws XWikiException { String author = this.getEffectiveScriptAuthorName(); if (hasAccessLevel("edit", author)) { String viewer = getXWikiContext().getUser(); try { getXWikiContext().setUser(author); saveDocument(comment, minorEdit); } finally { getXWikiContext().setUser(viewer); } } else { java.lang.Object[] args = { author, getXWikiContext().getDoc(), this.getFullName() }; throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access denied; user {0}, acting through script in document {1} cannot save document {2}", null, args); } } protected void saveDocument(String comment, boolean minorEdit) throws XWikiException { XWikiDocument doc = getDoc(); doc.setAuthor(this.context.getUser()); if (doc.isNew()) { doc.setCreator(this.context.getUser()); } getXWikiContext().getWiki().saveDocument(doc, comment, minorEdit, getXWikiContext()); this.cloned = false; } public com.xpn.xwiki.api.Object addObjectFromRequest() throws XWikiException { // Call to getDoc() ensures that we are working on a clone() return new com.xpn.xwiki.api.Object(getDoc().addObjectFromRequest(getXWikiContext()), getXWikiContext()); } public com.xpn.xwiki.api.Object addObjectFromRequest(String className) throws XWikiException { return new com.xpn.xwiki.api.Object(getDoc().addObjectFromRequest(className, getXWikiContext()), getXWikiContext()); } public List<Object> addObjectsFromRequest(String className) throws XWikiException { return addObjectsFromRequest(className, ""); } public com.xpn.xwiki.api.Object addObjectFromRequest(String className, String prefix) throws XWikiException { return new com.xpn.xwiki.api.Object(getDoc().addObjectFromRequest(className, prefix, getXWikiContext()), getXWikiContext()); } public List<Object> addObjectsFromRequest(String className, String prefix) throws XWikiException { List<BaseObject> objs = getDoc().addObjectsFromRequest(className, prefix, getXWikiContext()); List<Object> wrapped = new ArrayList<Object>(); for (BaseObject object : objs) { wrapped.add(new com.xpn.xwiki.api.Object(object, getXWikiContext())); } return wrapped; } public com.xpn.xwiki.api.Object updateObjectFromRequest(String className) throws XWikiException { return new com.xpn.xwiki.api.Object(getDoc().updateObjectFromRequest(className, getXWikiContext()), getXWikiContext()); } public List<Object> updateObjectsFromRequest(String className) throws XWikiException { return updateObjectsFromRequest(className, ""); } public com.xpn.xwiki.api.Object updateObjectFromRequest(String className, String prefix) throws XWikiException { return new com.xpn.xwiki.api.Object(getDoc().updateObjectFromRequest(className, prefix, getXWikiContext()), getXWikiContext()); } public List<Object> updateObjectsFromRequest(String className, String prefix) throws XWikiException { List<BaseObject> objs = getDoc().updateObjectsFromRequest(className, prefix, getXWikiContext()); List<Object> wrapped = new ArrayList<Object>(); for (BaseObject object : objs) { wrapped.add(new com.xpn.xwiki.api.Object(object, getXWikiContext())); } return wrapped; } public boolean isAdvancedContent() { return this.doc.isAdvancedContent(); } public boolean isProgrammaticContent() { return this.doc.isProgrammaticContent(); } /** * Remove an XObject from the document. The changes are not persisted until the document is saved. * * @param object the object to remove * @return {@code true} if the object was successfully removed, {@code false} if the object was not found in the * current document. */ public boolean removeObject(Object object) { return getDoc().removeObject(object.getBaseObject()); } /** * Remove all the objects of a given type (XClass) from the document. The object counter is left unchanged, so that * future objects will have new (different) numbers. However, on some storage engines the counter will be reset if * the document is removed from the cache and reloaded from the persistent storage. * * @param className The class name of the objects to be removed. * @return {@code true} if the objects were successfully removed, {@code false} if no object from the target class * was in the current document. */ public boolean removeObjects(String className) { return getDoc().removeObjects(className); } /** * Remove document from the wiki. Reinit <code>cloned</code>. * * @throws XWikiException */ protected void deleteDocument() throws XWikiException { getXWikiContext().getWiki().deleteDocument(this.doc, getXWikiContext()); this.cloned = false; } public void delete() throws XWikiException { if (hasAccessLevel("delete")) { deleteDocument(); } else { java.lang.Object[] args = { this.getFullName() }; throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access denied in edit mode on document {0}", null, args); } } /** * Delete the document if the {@link #getContentAuthor content author} of the script calling this method has * permission to do so. The deleter is also set to the said content author. * * @throws XWikiException if script author is not allowed to delete the document or if save operation fails. * @since 2.3M2 */ public void deleteAsAuthor() throws XWikiException { String author = this.getEffectiveScriptAuthorName(); if (hasAccessLevel("delete", author)) { String viewer = getXWikiContext().getUser(); try { getXWikiContext().setUser(author); deleteDocument(); } finally { getXWikiContext().setUser(viewer); } } else { java.lang.Object[] args = { author, getXWikiContext().getDoc(), this.getFullName() }; throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access denied; user {0}, acting through script in document {1} cannot delete document {2}", null, args); } } public void deleteWithProgrammingRights() throws XWikiException { if (hasProgrammingRights()) { deleteDocument(); } else { java.lang.Object[] args = { this.getFullName() }; throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access denied with no programming rights document {0}", null, args); } } public String getVersionHashCode() { return this.doc.getVersionHashCode(getXWikiContext()); } public int addAttachments() throws XWikiException { return addAttachments(null); } public int addAttachments(String fieldName) throws XWikiException { if (!hasAccessLevel("edit")) { java.lang.Object[] args = { this.getFullName() }; throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access denied in edit mode on document {0}", null, args); } XWiki xwiki = getXWikiContext().getWiki(); FileUploadPlugin fileupload = (FileUploadPlugin) xwiki.getPlugin("fileupload", getXWikiContext()); List<FileItem> fileuploadlist = fileupload.getFileItems(getXWikiContext()); List<XWikiAttachment> attachments = new ArrayList<XWikiAttachment>(); // adding attachment list to context so we find the names this.context.put("addedAttachments", attachments); int nb = 0; if (fileuploadlist == null) { return 0; } for (FileItem item : fileuploadlist) { String name = item.getFieldName(); if (fieldName != null && !fieldName.equals(name)) { continue; } if (item.isFormField()) { continue; } byte[] data = fileupload.getFileItemData(name, getXWikiContext()); String filename; String fname = fileupload.getFileName(name, getXWikiContext()); int i = fname.lastIndexOf("\\"); if (i == -1) { i = fname.lastIndexOf("/"); } filename = fname.substring(i + 1); filename = filename.replaceAll("\\+", " "); if ((data != null) && (data.length > 0)) { XWikiAttachment attachment = this.getDoc().addAttachment(filename, data, getXWikiContext()); getDoc().saveAttachmentContent(attachment, getXWikiContext()); // commenting because this was already done by addAttachment // getDoc().getAttachmentList().add(attachment); attachments.add(attachment); nb++; } } if (nb > 0) { getXWikiContext().getWiki().saveDocument(getDoc(), getXWikiContext()); this.cloned = false; } return nb; } public Attachment addAttachment(String fileName, InputStream iStream) { try { return new Attachment(this, this.getDoc().addAttachment(fileName, iStream, getXWikiContext()), getXWikiContext()); } catch (XWikiException e) { // TODO Log the error and let the user know about it } catch (IOException e) { // TODO Log the error and let the user know about it } return null; } public Attachment addAttachment(String fileName, byte[] data) { try { return new Attachment(this, this.getDoc().addAttachment(fileName, data, getXWikiContext()), getXWikiContext()); } catch (XWikiException e) { // TODO Log the error and let the user know about it } return null; } public boolean validate() throws XWikiException { return this.doc.validate(getXWikiContext()); } public boolean validate(String[] classNames) throws XWikiException { return this.doc.validate(classNames, getXWikiContext()); } /** * Retrieves the validation script associated with this document, a Velocity script that is executed when validating * the document data. * * @return A <code>String</code> representation of the validation script, or an empty string if there is no such * script. */ public String getValidationScript() { return getDoc().getValidationScript(); } /** * Sets a new validation script for this document, a Velocity script that is executed when validating the document * data. * * @param validationScript The new validation script, which can be an empty string or <code>null</code> if the * script should be removed. */ public void setValidationScript(String validationScript) { getDoc().setValidationScript(validationScript); } /** * @deprecated use {@link #rename(String)} instead */ @Deprecated public void renameDocument(String newDocumentName) throws XWikiException { rename(newDocumentName); } /** * Rename the current document and all the backlinks leading to it. Will also change parent field in all documents * which list the document we are renaming as their parent. See * {@link #rename(String, java.util.List, java.util.List)} for more details. * * @param newDocumentName the new document name. If the space is not specified then defaults to the current space. * @throws XWikiException in case of an error */ public void rename(String newDocumentName) throws XWikiException { rename(this.currentMixedDocumentReferenceResolver.resolve(newDocumentName)); } /** * Rename the current document and all the backlinks leading to it. Will also change parent field in all documents * which list the document we are renaming as their parent. See * {@link #rename(String, java.util.List, java.util.List)} for more details. * * @param newReference the reference to the new document * @throws XWikiException in case of an error * @since 2.3M2 */ public void rename(DocumentReference newReference) throws XWikiException { if (hasAccessLevel("delete") && this.context.getWiki().checkAccess("edit", this.context.getWiki().getDocument(newReference, this.context), this.context)) { this.getDoc().rename(newReference, getXWikiContext()); } } /** * @deprecated use {@link #rename(String, java.util.List)} instead */ @Deprecated public void renameDocument(String newDocumentName, List<String> backlinkDocumentNames) throws XWikiException { rename(newDocumentName, backlinkDocumentNames); } /** * Rename the current document and all the links pointing to it in the list of passed backlink documents. The * renaming algorithm takes into account the fact that there are several ways to write a link to a given page and * all those forms need to be renamed. For example the following links all point to the same page: * <ul> * <li>[Page]</li> * <li>[Page?param=1]</li> * <li>[currentwiki:Page]</li> * <li>[currentwiki:CurrentSpace.Page]</li> * </ul> * <p> * Note: links without a space are renamed with the space added and all documents which have the document being * renamed as parent have their parent field set to "currentwiki:CurrentSpace.Page". * </p> * * @param newDocumentName the new document name. If the space is not specified then defaults to the current space. * @param backlinkDocumentNames the list of documents to parse and for which links will be modified to point to the * new renamed document. * @throws XWikiException in case of an error */ public void rename(String newDocumentName, List<String> backlinkDocumentNames) throws XWikiException { if (hasAccessLevel("delete") && this.context.getWiki().checkAccess("edit", this.context.getWiki().getDocument(newDocumentName, this.context), this.context)) { this.getDoc().rename(newDocumentName, backlinkDocumentNames, getXWikiContext()); } } /** * Same as {@link #rename(String, List)} but the list of documents having the current document as their parent is * passed in parameter. * * @param newDocumentName the new document name. If the space is not specified then defaults to the current space. * @param backlinkDocumentNames the list of documents to parse and for which links will be modified to point to the * new renamed document. * @param childDocumentNames the list of documents whose parent field will be set to the new document name. * @throws XWikiException in case of an error */ public void rename(String newDocumentName, List<String> backlinkDocumentNames, List<String> childDocumentNames) throws XWikiException { List<DocumentReference> backlinkDocumentReferences = new ArrayList<DocumentReference>(); for (String backlinkDocumentName : backlinkDocumentNames) { backlinkDocumentReferences .add(this.currentMixedDocumentReferenceResolver.resolve(backlinkDocumentName)); } List<DocumentReference> childDocumentReferences = new ArrayList<DocumentReference>(); for (String childDocumentName : childDocumentNames) { childDocumentReferences.add(this.currentMixedDocumentReferenceResolver.resolve(childDocumentName)); } rename(this.currentMixedDocumentReferenceResolver.resolve(newDocumentName), backlinkDocumentReferences, childDocumentReferences); } /** * Same as {@link #rename(String, List)} but the list of documents having the current document as their parent is * passed in parameter. * * @param newReference the reference to the new document * @param backlinkDocumentNames the list of reference to documents to parse and for which links will be modified to * point to the new renamed document * @param childDocumentNames the list of references to documents whose parent field will be set to the new document * reference * @throws XWikiException in case of an error * @since 2.3M2 */ public void rename(DocumentReference newReference, List<DocumentReference> backlinkDocumentNames, List<DocumentReference> childDocumentNames) throws XWikiException { if (hasAccessLevel("delete") && this.context.getWiki().checkAccess("edit", this.context.getWiki().getDocument(newReference, this.context), this.context)) { // Every page given in childDocumentNames has it's parent changed whether it needs it or not. // Let's make sure the user has edit permission on any page given which is not actually a child. // Otherwise it would be embarrassing if a user called: // $doc.rename("mynewpage",$doc.getBacklinks(),$xwiki.searchDocuments("true")) int counter = childDocumentNames.size(); List<String> actuallyChildren = getChildren(); while (counter > 0) { counter--; if (!actuallyChildren.contains(childDocumentNames.get(counter)) && !this.context.getWiki().checkAccess("edit", this.context.getWiki().getDocument(childDocumentNames.get(counter), this.context), this.context)) { return; } } this.getDoc().rename(newReference, backlinkDocumentNames, childDocumentNames, getXWikiContext()); } } /** * Allow to easily access any revision of a document * * @param revision version to access * @return Document object * @throws XWikiException */ public Document getDocumentRevision(String revision) throws XWikiException { return new Document(this.context.getWiki().getDocument(this.doc, revision, this.context), this.context); } /** * Allow to easily access the previous revision of a document * * @return Document * @throws XWikiException */ public Document getPreviousDocument() throws XWikiException { return getDocumentRevision(getPreviousVersion()); } /** * @return is document most recent. false if and only if there are older versions of this document. */ public boolean isMostRecent() { return this.doc.isMostRecent(); } /** * {@inheritDoc} * * @see java.lang.Object#toString() */ @Override public String toString() { return this.doc.toString(); } /** * Convert the current document content from its current syntax to the new syntax passed as parameter. * * @param targetSyntaxId the syntax to convert to (eg "xwiki/2.0", "xhtml/1.0", etc) * @throws XWikiException if an exception occurred during the conversion process */ public boolean convertSyntax(String targetSyntaxId) throws XWikiException { try { getDoc().convertSyntax(targetSyntaxId, this.context); } catch (Exception ex) { LOGGER.error( "Failed to convert document [" + getPrefixedFullName() + "] to syntax [" + targetSyntaxId + "]", ex); return false; } return true; } /** * Drop permissions for the remainder of the rendering cycle. * After this is called: * <ul> * <li>1. {@link com.xpn.xwiki.api.Api#hasProgrammingRights()} will always return false.</li> * <li>2. {@link com.xpn.xwiki.api.XWiki#getDocumentAsAuthor(org.xwiki.model.reference.DocumentReference)}, * {@link com.xpn.xwiki.api.XWiki#getDocumentAsAuthor(String)}, {@link com.xpn.xwiki.api.Document#saveAsAuthor()}, * {@link com.xpn.xwiki.api.Document#saveAsAuthor(String)}, * {@link com.xpn.xwiki.api.Document#saveAsAuthor(String, boolean)}, and * {@link com.xpn.xwiki.api.Document#deleteAsAuthor()} will perform all of their actions as if the document's * content author was the guest user (XWiki.XWikiGuest).</li> * </ul> * <p> * This sandboxing will expire at the end of the rendering cycle and can be suspended by * beginning a new rendering cycle. A rendering cycle can be begin by calling * {@link #getRenderedContent(String)}, {@link #display(String)} (or variations thereof) * or by invoking the include macro or using {@link com.xpn.xwiki.api.XWiki#includeTopic(String)} * <p> * NOTE: Even if you include the same document, permissions will be regained. * What this does is sandbox the remainder of the code on the page because although * it can temporarily suspend the permissions drop, it cannot get itself to be executed * with permissions because if it calls itself, it will hit the drop function first. * <p> * If you are interested in a more secure sandboxing method where code is guaranteed not * to have permissions for the remainder of the request, you should consider * {@link com.xpn.xwiki.api.Context#dropPermissions()}. * <p> * * @since 3.2M2 */ public void dropPermissions() { // Set the droppedPermissions key to the context so if the context is cloned and // pushed, it will return false until it is popped again. final ExecutionContext context = Utils.getComponent(Execution.class).getContext(); context.setProperty(XWikiConstant.DROPPED_PERMISSIONS, System.identityHashCode(context)); } }