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; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.text.DateFormatSymbols; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import java.util.Set; import java.util.TimeZone; import java.util.Vector; import java.util.regex.Pattern; import java.util.zip.ZipOutputStream; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.URIException; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.util.URIUtil; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.net.smtp.SMTPClient; import org.apache.commons.net.smtp.SMTPReply; import org.apache.velocity.VelocityContext; import org.hibernate.HibernateException; import org.securityfilter.filter.URLPatternMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xwiki.bridge.event.DocumentCreatedEvent; import org.xwiki.bridge.event.DocumentCreatingEvent; import org.xwiki.bridge.event.DocumentDeletedEvent; import org.xwiki.bridge.event.DocumentDeletingEvent; import org.xwiki.bridge.event.DocumentUpdatedEvent; import org.xwiki.bridge.event.DocumentUpdatingEvent; import org.xwiki.cache.Cache; import org.xwiki.cache.CacheException; import org.xwiki.cache.CacheFactory; import org.xwiki.cache.CacheManager; import org.xwiki.cache.config.CacheConfiguration; import org.xwiki.cache.eviction.LRUEvictionConfiguration; import org.xwiki.component.manager.ComponentLookupException; import org.xwiki.context.Execution; import org.xwiki.context.ExecutionContext; import org.xwiki.model.EntityType; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.DocumentReferenceResolver; import org.xwiki.model.reference.EntityReference; import org.xwiki.model.reference.EntityReferenceResolver; import org.xwiki.model.reference.EntityReferenceSerializer; import org.xwiki.model.reference.EntityReferenceValueProvider; import org.xwiki.model.reference.ObjectReference; import org.xwiki.model.reference.RegexEntityReference; import org.xwiki.model.reference.SpaceReference; import org.xwiki.model.reference.WikiReference; import org.xwiki.observation.EventListener; import org.xwiki.observation.ObservationManager; import org.xwiki.observation.event.Event; import org.xwiki.query.QueryException; import org.xwiki.rendering.macro.wikibridge.WikiMacroInitializer; import org.xwiki.rendering.parser.ParseException; import org.xwiki.rendering.syntax.Syntax; import org.xwiki.rendering.syntax.SyntaxFactory; import org.xwiki.sheet.SheetBinder; import org.xwiki.url.XWikiEntityURL; import org.xwiki.url.standard.XWikiURLBuilder; import org.xwiki.xml.XMLUtils; import com.xpn.xwiki.api.Api; import com.xpn.xwiki.api.Document; import com.xpn.xwiki.api.User; import com.xpn.xwiki.criteria.api.XWikiCriteriaService; import com.xpn.xwiki.doc.DeletedAttachment; import com.xpn.xwiki.doc.XWikiAttachment; import com.xpn.xwiki.doc.XWikiDeletedDocument; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.doc.XWikiDocumentArchive; import com.xpn.xwiki.internal.event.XObjectAddedEvent; import com.xpn.xwiki.internal.event.XObjectDeletedEvent; import com.xpn.xwiki.internal.event.XObjectEvent; import com.xpn.xwiki.internal.event.XObjectPropertyAddedEvent; import com.xpn.xwiki.internal.event.XObjectPropertyDeletedEvent; import com.xpn.xwiki.internal.event.XObjectPropertyEvent; import com.xpn.xwiki.internal.event.XObjectPropertyUpdatedEvent; import com.xpn.xwiki.internal.event.XObjectUpdatedEvent; import com.xpn.xwiki.objects.BaseObject; import com.xpn.xwiki.objects.PropertyInterface; import com.xpn.xwiki.objects.classes.BaseClass; import com.xpn.xwiki.objects.classes.BooleanClass; import com.xpn.xwiki.objects.classes.GroupsClass; import com.xpn.xwiki.objects.classes.LevelsClass; import com.xpn.xwiki.objects.classes.NumberClass; import com.xpn.xwiki.objects.classes.PasswordClass; import com.xpn.xwiki.objects.classes.PropertyClass; import com.xpn.xwiki.objects.classes.StaticListClass; import com.xpn.xwiki.objects.classes.UsersClass; import com.xpn.xwiki.objects.meta.MetaClass; import com.xpn.xwiki.plugin.XWikiPluginInterface; import com.xpn.xwiki.plugin.XWikiPluginManager; import com.xpn.xwiki.plugin.query.QueryPlugin; import com.xpn.xwiki.plugin.query.XWikiCriteria; import com.xpn.xwiki.plugin.query.XWikiQuery; import com.xpn.xwiki.render.DefaultXWikiRenderingEngine; import com.xpn.xwiki.render.XWikiRenderingEngine; import com.xpn.xwiki.render.XWikiVelocityRenderer; import com.xpn.xwiki.render.groovy.XWikiGroovyRenderer; import com.xpn.xwiki.render.groovy.XWikiPageClassLoader; import com.xpn.xwiki.stats.api.XWikiStatsService; import com.xpn.xwiki.stats.impl.SearchEngineRule; import com.xpn.xwiki.stats.impl.XWikiStatsServiceImpl; import com.xpn.xwiki.store.AttachmentRecycleBinStore; import com.xpn.xwiki.store.AttachmentVersioningStore; import com.xpn.xwiki.store.XWikiAttachmentStoreInterface; import com.xpn.xwiki.store.XWikiCacheStore; import com.xpn.xwiki.store.XWikiCacheStoreInterface; import com.xpn.xwiki.store.XWikiHibernateStore; import com.xpn.xwiki.store.XWikiRecycleBinStoreInterface; import com.xpn.xwiki.store.XWikiStoreInterface; import com.xpn.xwiki.store.XWikiVersioningStoreInterface; import com.xpn.xwiki.store.migration.AbstractXWikiMigrationManager; import com.xpn.xwiki.user.api.XWikiAuthService; import com.xpn.xwiki.user.api.XWikiGroupService; import com.xpn.xwiki.user.api.XWikiRightService; import com.xpn.xwiki.user.api.XWikiUser; import com.xpn.xwiki.user.impl.LDAP.XWikiLDAPAuthServiceImpl; import com.xpn.xwiki.user.impl.xwiki.XWikiAuthServiceImpl; import com.xpn.xwiki.user.impl.xwiki.XWikiGroupServiceImpl; import com.xpn.xwiki.user.impl.xwiki.XWikiRightServiceImpl; import com.xpn.xwiki.util.Util; import com.xpn.xwiki.util.XWikiStubContextProvider; import com.xpn.xwiki.web.Utils; import com.xpn.xwiki.web.XWikiEngineContext; import com.xpn.xwiki.web.XWikiMessageTool; import com.xpn.xwiki.web.XWikiRequest; import com.xpn.xwiki.web.XWikiURLFactory; import com.xpn.xwiki.web.XWikiURLFactoryService; import com.xpn.xwiki.web.XWikiURLFactoryServiceImpl; import com.xpn.xwiki.web.includeservletasstring.IncludeServletAsString; public class XWiki implements EventListener { /** Name of the default wiki. */ public static final String DEFAULT_MAIN_WIKI = "xwiki"; /** Name of the default home space. */ public static final String DEFAULT_HOME_SPACE = "Main"; /** Name of the default system space. */ public static final String SYSTEM_SPACE = "XWiki"; /** Name of the default space homepage. */ public static final String DEFAULT_SPACE_HOMEPAGE = "WebHome"; /** Logging helper object. */ protected static final Logger LOGGER = LoggerFactory.getLogger(XWiki.class); /** Frequently used Document reference, the class which holds virtual wiki definitions. */ private static final DocumentReference VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE = new DocumentReference( DEFAULT_MAIN_WIKI, SYSTEM_SPACE, "XWikiServerClass"); /** The default encoding, and the internally used encoding when dealing with byte representation of strings. */ public static final String DEFAULT_ENCODING = "UTF-8"; /** XWiki configuration loaded from xwiki.cfg. */ private XWikiConfig config; /** The main document storage. */ private XWikiStoreInterface store; /** The attachment storage (excluding attachment history). */ private XWikiAttachmentStoreInterface attachmentStore; /** Store for attachment archives. */ private AttachmentVersioningStore attachmentVersioningStore; /** Document versioning storage. */ private XWikiVersioningStoreInterface versioningStore; /** Deleted documents storage. */ private XWikiRecycleBinStoreInterface recycleBinStore; /** * Storage for deleted attachment. * * @since 1.4M1 */ private AttachmentRecycleBinStore attachmentRecycleBinStore; private XWikiRenderingEngine renderingEngine; private XWikiPluginManager pluginManager; private XWikiAuthService authService; private XWikiRightService rightService; private XWikiGroupService groupService; private XWikiStatsService statsService; private XWikiURLFactoryService urlFactoryService; private XWikiCriteriaService criteriaService; /** Lock object used for the lazy initialization of the authentication service. */ private final Object AUTH_SERVICE_LOCK = new Object(); /** Lock object used for the lazy initialization of the authorization service. */ private final Object RIGHT_SERVICE_LOCK = new Object(); /** Lock object used for the lazy initialization of the group management service. */ private final Object GROUP_SERVICE_LOCK = new Object(); /** Lock object used for the lazy initialization of the statistics service. */ private final Object STATS_SERVICE_LOCK = new Object(); /** Lock object used for the lazy initialization of the URL Factory service. */ private final Object URLFACTORY_SERVICE_LOCK = new Object(); private MetaClass metaclass = MetaClass.getMetaClass(); /** Is the wiki running in test mode? Deprecated, was used when running Cactus tests. */ private boolean test = false; private String version = null; private XWikiEngineContext engine_context; private String database; private String fullNameSQL; private URLPatternMatcher urlPatternMatcher = new URLPatternMatcher(); // These are caches in order to improve finding virtual wikis private List<String> virtualWikiList = new ArrayList<String>(); /** * The cache containing the names of the wikis already initialized. */ private Cache<DocumentReference> virtualWikiMap; private boolean isReadOnly = false; public static final String CFG_ENV_NAME = "XWikiConfig"; public static final String MACROS_FILE = "/templates/macros.txt"; /** * File containing XWiki's version, in the format: <version name>.<SVN revision number>. */ private static final String VERSION_FILE = "/WEB-INF/version.properties"; /** * Property containing the version value in the {@link #VERSION_FILE} file. */ private static final String VERSION_FILE_PROPERTY = "version"; /* * i don't like using static variables like, but this avoid making a JNDI lookup with each request ... */ private static String configPath = null; /* * Work directory */ private static File workDir = null; /* * Temp directory */ private static File tempDir = null; /** * List of configured syntax ids. */ private List<String> configuredSyntaxes; /** * Used to convert a proper Document Reference to string (standard form). */ @SuppressWarnings("unchecked") private EntityReferenceSerializer<String> defaultEntityReferenceSerializer = Utils .getComponent(EntityReferenceSerializer.class); @SuppressWarnings("unchecked") private EntityReferenceSerializer<String> localStringEntityReferenceSerializer = Utils .getComponent(EntityReferenceSerializer.class, "local"); private EntityReferenceValueProvider defaultEntityReferenceValueProvider = Utils .getComponent(EntityReferenceValueProvider.class); @SuppressWarnings("unchecked") private EntityReferenceSerializer<EntityReference> localReferenceEntityReferenceSerializer = Utils .getComponent(EntityReferenceSerializer.class, "local/reference"); /** * 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. */ @SuppressWarnings("unchecked") private DocumentReferenceResolver<String> currentMixedDocumentReferenceResolver = Utils .getComponent(DocumentReferenceResolver.class, "currentmixed"); @SuppressWarnings("unchecked") private EntityReferenceResolver<String> relativeEntityReferenceResolver = Utils .getComponent(EntityReferenceResolver.class, "relative"); private SyntaxFactory syntaxFactory = Utils.getComponent(SyntaxFactory.class); private XWikiURLBuilder entityXWikiURLBuilder = Utils.getComponent(XWikiURLBuilder.class, "entity"); /** * Whether backlinks are enabled or not (cached for performance). * * @since 3.2M2 */ private Boolean hasBacklinks; public static String getConfigPath() throws NamingException { if (configPath == null) { try { Context envContext = (Context) new InitialContext().lookup("java:comp/env"); configPath = (String) envContext.lookup(CFG_ENV_NAME); } catch (Exception e) { configPath = "/WEB-INF/xwiki.cfg"; LOGGER.debug("The xwiki.cfg file will be read from [" + configPath + "] because " + "its location couldn't be read from the JNDI [" + CFG_ENV_NAME + "] " + "variable in [java:comp/env]."); } } return configPath; } public static XWiki getMainXWiki(XWikiContext context) throws XWikiException { String xwikiname = DEFAULT_MAIN_WIKI; XWiki xwiki; XWikiEngineContext econtext = context.getEngineContext(); context.setMainXWiki(xwikiname); try { xwiki = (XWiki) econtext.getAttribute(xwikiname); if (xwiki == null) { synchronized (XWiki.class) { xwiki = (XWiki) econtext.getAttribute(xwikiname); if (xwiki == null) { InputStream xwikicfgis = XWiki.readXWikiConfiguration(getConfigPath(), econtext, context); xwiki = new XWiki(xwikicfgis, context, context.getEngineContext()); econtext.setAttribute(xwikiname, xwiki); } } context.setWiki(xwiki); // initialize stub context here instead of during Execution context initialization because during // Execution context initialization, the XWikiContext is not fully initialized (does not contains XWiki // object) which make it unusable Utils.getComponent(XWikiStubContextProvider.class).initialize(context); } else { context.setWiki(xwiki); } return xwiki; } catch (Exception e) { throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_INIT_FAILED, "Could not initialize main XWiki context", e); } } /** * First try to find the configuration file pointed by the passed location as a file. If it does not exist or if the * file cannot be read (for example if the security manager doesn't allow it), then try to load the file as a * resource using the Servlet Context and failing that from teh classpath. * * @param configurationLocation the location where the XWiki configuration file is located (either an absolute or * relative file path or a resource location) * @return the stream containing the configuration data or null if not found * @todo this code should be moved to a Configuration class proper */ private static InputStream readXWikiConfiguration(String configurationLocation, XWikiEngineContext econtext, XWikiContext context) { InputStream xwikicfgis = null; // First try loading from a file. File f = new File(configurationLocation); try { if (f.exists()) { xwikicfgis = new FileInputStream(f); } } catch (Exception e) { // Error loading the file. Most likely, the Security Manager prevented it. // We'll try loading it as a resource below. LOGGER.debug("Failed to load the file [" + configurationLocation + "] using direct " + "file access. The error was [" + e.getMessage() + "]. Trying to load it " + "as a resource using the Servlet Context..."); } // Second, try loading it as a resource using the Servlet Context if (xwikicfgis == null) { xwikicfgis = econtext.getResourceAsStream(configurationLocation); LOGGER.debug("Failed to load the file [" + configurationLocation + "] as a resource " + "using the Servlet Context. Trying to load it as classpath resource..."); } // Third, try loading it from the classloader used to load this current class if (xwikicfgis == null) { // TODO: Verify if checking on MODE_GWT is correct. I think we should only check for // the debug mode and even for that we need to find some better way of doing it so // that we don't have hardcoded code only for development debugging purposes. if (context.getMode() == XWikiContext.MODE_GWT || context.getMode() == XWikiContext.MODE_GWT_DEBUG) { xwikicfgis = XWiki.class.getClassLoader().getResourceAsStream("xwiki-gwt.cfg"); } else { xwikicfgis = XWiki.class.getClassLoader().getResourceAsStream("xwiki.cfg"); } } LOGGER.debug("Failed to load the file [" + configurationLocation + "] using any method."); // TODO: Should throw an exception instead of return null... return xwikicfgis; } /** * Return the XWiki object (as in "the Wiki API") corresponding to the requested wiki. * * @param context the current context * @return an XWiki object configured for the wiki corresponding to the current request * @throws XWikiException if the requested URL does not correspond to a real wiki, or if there's an error in the * storage */ public static XWiki getXWiki(XWikiContext context) throws XWikiException { XWiki xwiki = getMainXWiki(context); if (!xwiki.isVirtualMode()) { return xwiki; } // Host is full.host.name in DNS-based multiwiki, and wikiname in path-based multiwiki. String host = ""; // Canonical name of the wiki (database) String wikiName = ""; // wikiDefinition should be the document holding the definition of the virtual wiki, a document in the main // wiki with a XWiki.XWikiServerClass object attached to it DocumentReference wikiDefinition; XWikiRequest request = context.getRequest(); try { URL requestURL = context.getURL(); host = requestURL.getHost(); } catch (Exception e) { } // In path-based multi-wiki, the wiki name is an element of the request path. // The url is in the form /xwiki (app name)/wiki (servlet name)/wikiname/ if ("1".equals(xwiki.Param("xwiki.virtual.usepath", "0"))) { String uri = request.getRequestURI(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Request uri is: " + uri); } // Remove the (eventual) context path from the URI, usually /xwiki uri = stripSegmentFromPath(uri, request.getContextPath()); // Remove the (eventual) servlet path from the URI, usually /wiki String servletPath = request.getServletPath(); uri = stripSegmentFromPath(uri, servletPath); if (servletPath.equals("/" + xwiki.Param("xwiki.virtual.usepath.servletpath", "wiki"))) { // Requested path corresponds to a path-based wiki, now the wiki name is between the first and // second "/" host = StringUtils.substringBefore(StringUtils.removeStart(uri, "/"), "/"); } } if (StringUtils.isEmpty(host) || host.equals(context.getMainXWiki())) { // Can't find any wiki name, return the main wiki return xwiki; } wikiDefinition = xwiki.findWikiServer(host, context); if (wikiDefinition == null) { // No definition found based on the full domain name/path wiki name, try to use the first part of the domain // name as the wiki name String servername = StringUtils.substringBefore(host, "."); // As a convenience, allow sites starting with www, localhost or using an // IP address not to have to create a XWikiServerXwiki page since we consider // in that case that they're pointing to the main wiki. if (!"0".equals(xwiki.Param("xwiki.virtual.autowww")) && (servername.equals("www") || host.equals("localhost") || host.matches("[0-9]{1,3}(?:\\.[0-9]{1,3}){3}"))) { return xwiki; } wikiDefinition = new DocumentReference(DEFAULT_MAIN_WIKI, SYSTEM_SPACE, "XWikiServer" + StringUtils.capitalize(servername)); } // Check if this wiki definition exists in the Database XWikiDocument doc = xwiki.getDocument(wikiDefinition, context); if (doc.isNew()) { throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_DOES_NOT_EXIST, "The wiki " + host + " does not exist"); } // Set the wiki owner String wikiOwner = doc.getStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, "owner"); if (wikiOwner.indexOf(':') == -1) { wikiOwner = xwiki.getDatabase() + ":" + wikiOwner; } context.setWikiOwner(wikiOwner); context.setWikiServer(doc); wikiName = StringUtils.removeStart(wikiDefinition.getName(), "XWikiServer").toLowerCase(); context.setDatabase(wikiName); context.setOriginalDatabase(wikiName); try { // Let's make sure the virtual wikis are upgraded to the latest database version xwiki.updateDatabase(wikiName, false, context); } catch (HibernateException ex) { // Just report it, hopefully the database is in a good enough state LOGGER.error("Failed to upgrade database: " + wikiName, ex); } return xwiki; } public static URL getRequestURL(XWikiRequest request) throws XWikiException { try { StringBuffer requestURL = request.getRequestURL(); String qs = request.getQueryString(); if ((qs != null) && (!qs.equals(""))) { return new URL(requestURL.toString() + "?" + qs); } else { return new URL(requestURL.toString()); } } catch (Exception e) { throw new XWikiException(XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_URL_EXCEPTION, "Exception while getting URL from request", e); } } public static Object callPrivateMethod(Object obj, String methodName) { return callPrivateMethod(obj, methodName, null, null); } public static Object callPrivateMethod(Object obj, String methodName, Class<?>[] classes, Object[] args) { try { Method method = obj.getClass().getDeclaredMethod(methodName, classes); method.setAccessible(true); return method.invoke(obj, args); } catch (IllegalAccessException e) { e.printStackTrace(); return null; } catch (NoSuchMethodException e) { return null; } catch (InvocationTargetException e) { e.printStackTrace(); return null; } } public static HttpClient getHttpClient(int timeout, String userAgent) { HttpClient client = new HttpClient(); if (timeout != 0) { client.getParams().setSoTimeout(timeout); client.getParams().setParameter("http.connection.timeout", Integer.valueOf(timeout)); } client.getParams().setParameter("http.useragent", userAgent); String proxyHost = System.getProperty("http.proxyHost"); String proxyPort = System.getProperty("http.proxyPort"); if ((proxyHost != null) && (!proxyHost.equals(""))) { int port = 3128; if ((proxyPort != null) && (!proxyPort.equals(""))) { port = Integer.parseInt(proxyPort); } client.getHostConfiguration().setProxy(proxyHost, port); } String proxyUser = System.getProperty("http.proxyUser"); if ((proxyUser != null) && (!proxyUser.equals(""))) { String proxyPassword = System.getProperty("http.proxyPassword"); Credentials defaultcreds = new UsernamePasswordCredentials(proxyUser, proxyPassword); client.getState().setProxyCredentials(AuthScope.ANY, defaultcreds); } return client; } public static Object getPrivateField(Object obj, String fieldName) { try { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } catch (NoSuchFieldException e) { return null; } catch (IllegalAccessException e) { e.printStackTrace(); return null; } finally { } } public static String getServerWikiPage(String servername) { return "XWiki.XWikiServer" + StringUtils.capitalize(servername); } public static String getTextArea(String content, XWikiContext context) { StringBuilder result = new StringBuilder(); // Forcing a new line after the <textarea> tag, as // http://www.w3.org/TR/html4/appendix/notes.html#h-B.3.1 causes an empty line at the start // of the document content to be trimmed. result.append("<textarea name=\"content\" id=\"content\" rows=\"25\" cols=\"80\">\n"); result.append(XMLUtils.escape(content)); result.append("</textarea>"); return result.toString(); } /** * This provide a way to create an XWiki object without initializing the whole XWiki (including plugins, storage, * etc.). * <p> * Needed for tools or tests which need XWiki because it is used everywhere in the API. * </p> */ public XWiki() { } public XWiki(XWikiConfig config, XWikiContext context) throws XWikiException { this(config, context, null, false); } public XWiki(XWikiConfig config, XWikiContext context, XWikiEngineContext engine_context, boolean noupdate) throws XWikiException { initXWiki(config, context, engine_context, noupdate); } /** * @deprecated use {@link #XWiki(XWikiConfig, XWikiContext)} instead */ @Deprecated public XWiki(String xwikicfgpath, XWikiContext context) throws XWikiException { this(xwikicfgpath, context, null, false); } /** * @deprecated use {@link #XWiki(XWikiConfig, XWikiContext, XWikiEngineContext, boolean)} instead */ @Deprecated public XWiki(String xwikicfgpath, XWikiContext context, XWikiEngineContext engine_context, boolean noupdate) throws XWikiException { try { initXWiki(new XWikiConfig(new FileInputStream(xwikicfgpath)), context, engine_context, noupdate); } catch (FileNotFoundException e) { Object[] args = { xwikicfgpath }; throw new XWikiException(XWikiException.MODULE_XWIKI_CONFIG, XWikiException.ERROR_XWIKI_CONFIG_FILENOTFOUND, "Configuration file {0} not found", e, args); } } /** * @deprecated use {@link #XWiki(XWikiConfig, XWikiContext, XWikiEngineContext, boolean)} instead */ @Deprecated public XWiki(InputStream is, XWikiContext context, XWikiEngineContext engine_context) throws XWikiException { initXWiki(new XWikiConfig(is), context, engine_context, true); } /** * Initialize all xwiki subsystems. */ public void initXWiki(XWikiConfig config, XWikiContext context, XWikiEngineContext engine_context, boolean noupdate) throws XWikiException { setDatabase(context.getMainXWiki()); setEngineContext(engine_context); context.setWiki(this); // Prepare the store setConfig(config); XWikiStoreInterface basestore = Utils.getComponent(XWikiStoreInterface.class, Param("xwiki.store.main.hint")); // Check if we need to use the cache store.. boolean nocache = "0".equals(Param("xwiki.store.cache", "1")); if (!nocache) { XWikiCacheStoreInterface cachestore = new XWikiCacheStore(basestore, context); setStore(cachestore); } else { setStore(basestore); } setCriteriaService((XWikiCriteriaService) createClassFromConfig("xwiki.criteria.class", "com.xpn.xwiki.criteria.impl.XWikiCriteriaServiceImpl", context)); setAttachmentStore( Utils.getComponent(XWikiAttachmentStoreInterface.class, Param("xwiki.store.attachment.hint"))); setVersioningStore( Utils.getComponent(XWikiVersioningStoreInterface.class, Param("xwiki.store.versioning.hint"))); setAttachmentVersioningStore(Utils.getComponent(AttachmentVersioningStore.class, hasAttachmentVersioning(context) ? Param("xwiki.store.attachment.versioning.hint") : "void")); if (hasRecycleBin(context)) { setRecycleBinStore( Utils.getComponent(XWikiRecycleBinStoreInterface.class, Param("xwiki.store.recyclebin.hint"))); } if (hasAttachmentRecycleBin(context)) { setAttachmentRecycleBinStore(Utils.getComponent(AttachmentRecycleBinStore.class, Param("xwiki.store.attachment.recyclebin.hint"))); } // Run migrations if ("1".equals(Param("xwiki.store.migration", "0"))) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Running storage migrations"); } AbstractXWikiMigrationManager manager = (AbstractXWikiMigrationManager) createClassFromConfig( "xwiki.store.migration.manager.class", "com.xpn.xwiki.store.migration.hibernate.XWikiHibernateMigrationManager", context); manager.startMigrations(context); if ("1".equals(Param("xwiki.store.migration.exitAfterEnd", "0"))) { if (LOGGER.isErrorEnabled()) { LOGGER.error("Exiting because xwiki.store.migration.exitAfterEnd is set"); } System.exit(0); } } resetRenderingEngine(context); // Prepare the Plugin Engine preparePlugins(context); // Make sure these classes exists if (noupdate) { initializeMandatoryClasses(context); getStatsService(context); } String ro = Param("xwiki.readonly", "no"); this.isReadOnly = ("yes".equalsIgnoreCase(ro) || "true".equalsIgnoreCase(ro) || "1".equalsIgnoreCase(ro)); // Save the configured syntaxes String syntaxes = Param("xwiki.rendering.syntaxes", "xwiki/1.0"); this.configuredSyntaxes = Arrays.asList(StringUtils.split(syntaxes, " ,")); // Initialize all wiki macros. // TODO: This is only a temporary work around, we need to use a component-based init mechanism instead. Note // that we need DB access to be available (at component initialization) to make this possible. registerWikiMacros(); Utils.getComponent(ObservationManager.class).addListener(this); } /** * Ensure that mandatory classes (ie classes XWiki needs to work properly) exist and create them if they don't * exist. */ private void initializeMandatoryClasses(XWikiContext context) throws XWikiException { getPrefsClass(context); getUserClass(context); getTagClass(context); getGroupClass(context); getRightsClass(context); getCommentsClass(context); getSkinClass(context); getGlobalRightsClass(context); getSheetClass(context); getEditModeClass(context); try { WikiMacroInitializer wikiMacroInitializer = Utils.getComponentManager() .lookup(WikiMacroInitializer.class); wikiMacroInitializer.installOrUpgradeWikiMacroClasses(); } catch (Exception ex) { LOGGER.error("Error while installing / upgrading xwiki classes required for wiki macros.", ex); } if (context.getDatabase().equals(context.getMainXWiki()) && "1".equals(context.getWiki().Param("xwiki.preferences.redirect"))) { getRedirectClass(context); } } /** * TODO: This is only a temporary work around, we need to use a component-based init mechanism instead. Note that we * need DB access to be available (at component initialization) to make this possible. * <p> * This method is protected to be able to skip it in unit tests. */ protected void registerWikiMacros() { try { WikiMacroInitializer wikiMacroInitializer = Utils.getComponentManager() .lookup(WikiMacroInitializer.class); wikiMacroInitializer.registerExistingWikiMacros(); } catch (Exception ex) { LOGGER.error("Error while registering wiki macros.", ex); } } public XWikiStoreInterface getNotCacheStore() { XWikiStoreInterface store = getStore(); if (store instanceof XWikiCacheStoreInterface) { store = ((XWikiCacheStoreInterface) store).getStore(); } return store; } public XWikiHibernateStore getHibernateStore() { XWikiStoreInterface store = getStore(); if (store instanceof XWikiHibernateStore) { return (XWikiHibernateStore) store; } else if (store instanceof XWikiCacheStoreInterface) { store = ((XWikiCacheStoreInterface) store).getStore(); if (store instanceof XWikiHibernateStore) { return (XWikiHibernateStore) store; } else { return null; } } else { return null; } } public void updateDatabase(String wikiName, XWikiContext context) throws HibernateException, XWikiException { updateDatabase(wikiName, false, context); } public void updateDatabase(String wikiName, boolean force, XWikiContext context) throws HibernateException, XWikiException { updateDatabase(wikiName, force, true, context); } public void updateDatabase(String wikiName, boolean force, boolean initClasses, XWikiContext context) throws HibernateException, XWikiException { String database = context.getDatabase(); try { List<String> wikiList = getVirtualWikiList(); // Make sure the wiki is updated if (force) { wikiList.remove(wikiName); context.remove("initdone"); } context.setDatabase(wikiName); synchronized (wikiName) { if (!wikiList.contains(wikiName)) { wikiList.add(wikiName); XWikiHibernateStore store = getHibernateStore(); if (store != null) { store.updateSchema(context, force); } // Make sure these classes exists if (initClasses) { initializeMandatoryClasses(context); getPluginManager().virtualInit(context); getRenderingEngine().virtualInit(context); } } } // Add initdone which will allow to // bypass some initializations context.put("initdone", "1"); } finally { context.setDatabase(database); } } /** * @return a cached list of all active virtual wikis (i.e. wikis who have been hit by a user request). To get a full * list of all virtual wikis database names use {@link #getVirtualWikisDatabaseNames(XWikiContext)}. */ public List<String> getVirtualWikiList() { return this.virtualWikiList; } /** * @return the full list of all database names of all defined virtual wikis. The database names are computed from * the names of documents having a XWiki.XWikiServerClass object attached to them by removing the * "XWiki.XWikiServer" prefix and making it lower case. For example a page named * "XWiki.XWikiServerMyDatabase" would return "mydatabase" as the database name. */ public List<String> getVirtualWikisDatabaseNames(XWikiContext context) throws XWikiException { String database = context.getDatabase(); try { context.setDatabase(context.getMainXWiki()); String query = ", BaseObject as obj where doc.space = 'XWiki' and obj.name=doc.fullName" + " and obj.name <> 'XWiki.XWikiServerClassTemplate' and obj.className='XWiki.XWikiServerClass' "; List<DocumentReference> documents = getStore().searchDocumentReferences(query, context); List<String> databaseNames = new ArrayList<String>(documents.size()); int prefixLength = "XWikiServer".length(); for (DocumentReference document : documents) { if (document.getName().startsWith("XWikiServer")) { databaseNames.add(document.getName().substring(prefixLength).toLowerCase()); } } return databaseNames; } finally { context.setDatabase(database); } } /** * @return the cache containing the names of the wikis already initialized. * @since 1.5M2. */ public Cache<DocumentReference> getVirtualWikiCache() { return this.virtualWikiMap; } /** * Searches for the document containing the definition of the virtual wiki corresponding to the specified hostname. * * @param host the hostname, as specified in the request (for example: {@code forge.xwiki.org}) * @param context the current context * @return the name of the document containing the wiki definition, or {@code null} if no wiki corresponds to the * hostname * @throws XWikiException if a problem occurs while searching the storage */ private DocumentReference findWikiServer(String host, XWikiContext context) throws XWikiException { this.ensureVirtualWikiMapExists(); DocumentReference wikiName = this.virtualWikiMap.get(host); if (wikiName == null) { // Not loaded yet, search for it in the main wiki String hql = ", BaseObject as obj, StringProperty as prop WHERE obj.name=doc.fullName" + " AND doc.space='XWiki' AND doc.name LIKE 'XWikiServer%'" + " AND obj.className='XWiki.XWikiServerClass' AND prop.id.id = obj.id" + " AND prop.id.name = 'server' AND prop.value=?"; List<String> parameters = new ArrayList<String>(1); parameters.add(host); try { List<DocumentReference> list = context.getWiki().getStore().searchDocumentReferences(hql, parameters, context); if ((list != null) && (list.size() > 0)) { wikiName = list.get(0); } this.virtualWikiMap.set(host, wikiName); } catch (XWikiException e) { LOGGER.warn("Error when searching for wiki name from URL host [" + host + "]", e); } } return wikiName; } private void ensureVirtualWikiMapExists() throws XWikiException { synchronized (this) { if (this.virtualWikiMap == null) { int iCapacity = 1000; try { String capacity = Param("xwiki.virtual.cache.capacity"); if (capacity != null) { iCapacity = Integer.parseInt(capacity); } } catch (Exception e) { } try { CacheConfiguration configuration = new CacheConfiguration(); configuration.setConfigurationId("xwiki.virtualwikimap"); LRUEvictionConfiguration lru = new LRUEvictionConfiguration(); lru.setMaxEntries(iCapacity); configuration.put(LRUEvictionConfiguration.CONFIGURATIONID, lru); this.virtualWikiMap = getCacheFactory().newCache(configuration); } catch (CacheException e) { throw new XWikiException(XWikiException.MODULE_XWIKI_CACHE, XWikiException.ERROR_CACHE_INITIALIZING, "Failed to create new cache", e); } } } } public String getWikiOwner(String servername, XWikiContext context) throws XWikiException { String wikiOwner = context.getWikiOwner(); if (!context.isMainWiki(servername)) { String serverwikipage = getServerWikiPage(servername); String currentdatabase = context.getDatabase(); try { context.setDatabase(context.getMainXWiki()); XWikiDocument doc = getDocument(serverwikipage, context); if (doc.isNew()) { throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_DOES_NOT_EXIST, "The wiki " + servername + " does not exist"); } wikiOwner = doc.getStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, "owner"); if (wikiOwner.indexOf(':') == -1) { wikiOwner = context.getMainXWiki() + ":" + wikiOwner; } } finally { context.setDatabase(currentdatabase); } } return wikiOwner; } protected Object createClassFromConfig(String param, String defClass, XWikiContext context) throws XWikiException { String storeclass = Param(param, defClass); try { Class<?>[] classes = new Class<?>[] { XWikiContext.class }; Object[] args = new Object[] { context }; Object result = Class.forName(storeclass).getConstructor(classes).newInstance(args); return result; } catch (Exception e) { Throwable ecause = e; if (e instanceof InvocationTargetException) { ecause = ((InvocationTargetException) e).getTargetException(); } Object[] args = { param, storeclass }; throw new XWikiException(XWikiException.MODULE_XWIKI_STORE, XWikiException.ERROR_XWIKI_STORE_CLASSINVOCATIONERROR, "Cannot load class {1} from param {0}", ecause, args); } } public void resetRenderingEngine(XWikiContext context) throws XWikiException { // Prepare the Rendering Engine setRenderingEngine(new DefaultXWikiRenderingEngine(this, context)); } private void preparePlugins(XWikiContext context) { setPluginManager(new XWikiPluginManager(getXWikiPreference("plugins", context), context)); String plugins = Param("xwiki.plugins", ""); if (!plugins.equals("")) { getPluginManager().addPlugins(StringUtils.split(plugins, " ,"), context); } } /** * @return the XWiki core version as specified in the {@link #VERSION_FILE} file */ public String getVersion() { if (this.version == null) { try { InputStream is = getResourceAsStream(VERSION_FILE); XWikiConfig properties = new XWikiConfig(is); this.version = properties.getProperty(VERSION_FILE_PROPERTY); } catch (Exception e) { // Failed to retrieve the version, log a warning and default to "Unknown" LOGGER.warn("Failed to retrieve XWiki's version from [" + VERSION_FILE + "], using the [" + VERSION_FILE_PROPERTY + "] property.", e); this.version = "Unknown version"; } } return this.version; } public URL getResource(String s) throws MalformedURLException { return getEngineContext().getResource(s); } public InputStream getResourceAsStream(String s) throws MalformedURLException { InputStream is = getEngineContext().getResourceAsStream(s); if (is == null) { is = getEngineContext().getResourceAsStream("/" + s); } return is; } public String getResourceContent(String name) throws IOException { InputStream is = null; if (getEngineContext() != null) { try { is = getResourceAsStream(name); } catch (Exception e) { } } if (is == null) { // Resources should always be encoded as UTF-8, to reduce the dependency on the system encoding return FileUtils.readFileToString(new File(name), DEFAULT_ENCODING); } return IOUtils.toString(is, DEFAULT_ENCODING); } public Date getResourceLastModificationDate(String name) { try { if (getEngineContext() != null) { return Util.getFileLastModificationDate(getEngineContext().getRealPath(name)); } } catch (Exception ex) { // Probably a SecurityException or the file is not accessible (inside a war) LOGGER.info("Failed to get file modification date: " + ex.getMessage()); } return new Date(); } public byte[] getResourceContentAsBytes(String name) throws IOException { InputStream is = null; if (getEngineContext() != null) { try { is = getResourceAsStream(name); } catch (Exception e) { } } if (is == null) { return FileUtils.readFileToByteArray(new File(name)); } return IOUtils.toByteArray(is); } public boolean resourceExists(String name) { if (getEngineContext() != null) { try { if (getResource(name) != null) { return true; } } catch (IOException e) { } } try { File file = new File(name); return file.exists(); } catch (Exception e) { // Could be running under -security, which prevents calling file.exists(). } return false; } public XWikiConfig getConfig() { return this.config; } public String getRealPath(String path) { return getEngineContext().getRealPath(path); } public String Param(String key) { return Param(key, null); } public String ParamAsRealPath(String key) { String param = Param(key); try { return getRealPath(param); } catch (Exception e) { return param; } } public String ParamAsRealPath(String key, XWikiContext context) { return ParamAsRealPath(key); } public String ParamAsRealPathVerified(String param) { String path; File fpath; path = Param(param); if (path == null) { return null; } fpath = new File(path); if (fpath.exists()) { return path; } path = getRealPath(path); if (path == null) { return null; } fpath = new File(path); if (fpath.exists()) { return path; } else { } return null; } public String Param(String key, String default_value) { if (getConfig() != null) { return getConfig().getProperty(key, default_value); } return default_value; } public long ParamAsLong(String key) { String param = Param(key); return Long.parseLong(param); } public long ParamAsLong(String key, long default_value) { try { return ParamAsLong(key); } catch (NumberFormatException e) { return default_value; } } public XWikiStoreInterface getStore() { return this.store; } public XWikiAttachmentStoreInterface getAttachmentStore() { return this.attachmentStore; } public AttachmentVersioningStore getAttachmentVersioningStore() { return this.attachmentVersioningStore; } public XWikiVersioningStoreInterface getVersioningStore() { return this.versioningStore; } public XWikiRecycleBinStoreInterface getRecycleBinStore() { return this.recycleBinStore; } public AttachmentRecycleBinStore getAttachmentRecycleBinStore() { return this.attachmentRecycleBinStore; } public void saveDocument(XWikiDocument doc, XWikiContext context) throws XWikiException { // If no comment is provided we should use an empty comment saveDocument(doc, "", context); } public void saveDocument(XWikiDocument doc, String comment, XWikiContext context) throws XWikiException { saveDocument(doc, comment, false, context); } public void saveDocument(XWikiDocument doc, String comment, boolean isMinorEdit, XWikiContext context) throws XWikiException { String server = null, database = null; try { server = doc.getDocumentReference().getWikiReference().getName(); if (server != null) { database = context.getDatabase(); context.setDatabase(server); } // Setting comment & minor edit before saving doc.setComment(StringUtils.defaultString(comment)); doc.setMinorEdit(isMinorEdit); // We need to save the original document since saveXWikiDoc() will reset it and we // need that original document for the notification below. XWikiDocument originalDocument = doc.getOriginalDocument(); // Always use an originalDocument, to provide a consistent behavior. The cases where // originalDocument is null are rare (specifically when the XWikiDocument object is // manually constructed, and not obtained using the API). if (originalDocument == null) { originalDocument = new XWikiDocument(doc.getDocumentReference()); } ObservationManager om = Utils.getComponent(ObservationManager.class); // Notify listeners about the document about to be created or updated // Note that for the moment the event being send is a bridge event, as we are still passing around // an XWikiDocument as source and an XWikiContext as data. if (om != null) { if (originalDocument.isNew()) { om.notify(new DocumentCreatingEvent(doc.getDocumentReference()), doc, context); } else { om.notify(new DocumentUpdatingEvent(doc.getDocumentReference()), doc, context); } } getStore().saveXWikiDoc(doc, context); // Since the store#saveXWikiDoc resets originalDocument, we need to temporarily put it // back to send notifications. XWikiDocument newOriginal = doc.getOriginalDocument(); try { doc.setOriginalDocument(originalDocument); // Notify listeners about the document having been created or updated // First the legacy notification mechanism // Then the new observation module // Note that for the moment the event being send is a bridge event, as we are still passing around // an XWikiDocument as source and an XWikiContext as data. // The old version is made available using doc.getOriginalDocument() if (om != null) { if (originalDocument.isNew()) { om.notify(new DocumentCreatedEvent(doc.getDocumentReference()), doc, context); } else { om.notify(new DocumentUpdatedEvent(doc.getDocumentReference()), doc, context); } } } catch (Exception ex) { LOGGER.error( "Failed to send document save notification for document [" + this.defaultEntityReferenceSerializer.serialize(doc.getDocumentReference()) + "]", ex); } finally { doc.setOriginalDocument(newOriginal); } } finally { if ((server != null) && (database != null)) { context.setDatabase(database); } } } public XWikiDocument getDocument(XWikiDocument doc, XWikiContext context) throws XWikiException { String database = context.getDatabase(); try { if (doc.getDocumentReference().getWikiReference().getName() != null) { context.setDatabase(doc.getDocumentReference().getWikiReference().getName()); } return getStore().loadXWikiDoc(doc, context); } finally { context.setDatabase(database); } } public XWikiDocument getDocument(XWikiDocument doc, String revision, XWikiContext context) throws XWikiException { XWikiDocument newdoc; String database = context.getDatabase(); try { if (doc.getDocumentReference().getWikiReference().getName() != null) { context.setDatabase(doc.getDocumentReference().getWikiReference().getName()); } if ((revision == null) || revision.equals("")) { newdoc = new XWikiDocument(doc.getDocumentReference()); } else if (revision.equals(doc.getVersion())) { newdoc = doc; } else { newdoc = getVersioningStore().loadXWikiDoc(doc, revision, context); } } catch (XWikiException e) { if (revision.equals("1.1") || revision.equals("1.0")) { newdoc = new XWikiDocument(doc.getDocumentReference()); } else { throw e; } } finally { context.setDatabase(database); } return newdoc; } /** * @since 2.2M1 */ public XWikiDocument getDocument(DocumentReference reference, XWikiContext context) throws XWikiException { XWikiDocument doc = new XWikiDocument(reference); doc.setContentDirty(true); return getDocument(doc, context); } /** * @deprecated since 2.2M1 use {@link #getDocument(DocumentReference, XWikiContext)} instead */ @Deprecated public XWikiDocument getDocument(String fullname, XWikiContext context) throws XWikiException { XWikiDocument doc = new XWikiDocument(); doc.setFullName(fullname, context); return getDocument(doc, context); } /** * @deprecated since 2.2M1 use {@link #getDocument(DocumentReference, XWikiContext)} instead */ @Deprecated public XWikiDocument getDocument(String space, String fullname, XWikiContext context) throws XWikiException { int dotPosition = fullname.lastIndexOf('.'); if (dotPosition != -1) { String spaceFromFullname = fullname.substring(0, dotPosition); String name = fullname.substring(dotPosition + 1); if (name.equals("")) { name = getDefaultPage(context); } return getDocument(spaceFromFullname + "." + name, context); } else { return getDocument(space + "." + fullname, context); } } public XWikiDocument getDocumentFromPath(String path, XWikiContext context) throws XWikiException { return getDocument(getDocumentReferenceFromPath(path, context), context); } /** * @since 2.3M1 */ public DocumentReference getDocumentReferenceFromPath(String path, XWikiContext context) { // TODO: Remove this and use XWikiURLFactory instead in XWikiAction and all entry points. List<String> segments = new ArrayList<String>(); for (String segment : path.split("/", -1)) { segments.add(Util.decodeURI(segment, context)); } // Remove the first segment if it's empty to cater for cases when the path starts with "/" if (segments.size() > 0 && segments.get(0).length() == 0) { segments.remove(0); } XWikiEntityURL entityURL = (XWikiEntityURL) this.entityXWikiURLBuilder .build(new WikiReference(context.getDatabase()), segments); return new DocumentReference(entityURL.getEntityReference().extractReference(EntityType.DOCUMENT)); } /** * @deprecated since 2.3M1 use {@link #getDocumentReferenceFromPath(String, XWikiContext)} instead */ @Deprecated public String getDocumentNameFromPath(String path, XWikiContext context) { return this.localStringEntityReferenceSerializer.serialize(getDocumentReferenceFromPath(path, context)); } /** * @see com.xpn.xwiki.api.XWiki#getDeletedDocuments(String, String) */ public XWikiDeletedDocument[] getDeletedDocuments(String fullname, String lang, XWikiContext context) throws XWikiException { if (hasRecycleBin(context)) { XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname)); doc.setLanguage(lang); return getRecycleBinStore().getAllDeletedDocuments(doc, context, true); } else { return null; } } /** * @see com.xpn.xwiki.api.XWiki#getDeletedDocument(String, String, String) */ public XWikiDeletedDocument getDeletedDocument(String fullname, String lang, int index, XWikiContext context) throws XWikiException { if (hasRecycleBin(context)) { XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname)); doc.setLanguage(lang); return getRecycleBinStore().getDeletedDocument(doc, index, context, true); } else { return null; } } /** * Retrieve all the deleted attachments that belonged to a certain document. Note that this does not distinguish * between different incarnations of a document name, and it does not require that the document still exists, it * returns all the attachments that at the time of their deletion had a document with the specified name as their * owner. * * @param docName the {@link XWikiDocument#getFullName() name} of the owner document * @param context the current request context * @return A list with all the deleted attachments which belonged to the specified document. If no such attachments * are found in the trash, an empty list is returned. * @throws XWikiException if an error occurs while loading the attachments */ public List<DeletedAttachment> getDeletedAttachments(String docName, XWikiContext context) throws XWikiException { if (hasAttachmentRecycleBin(context)) { XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(docName)); return getAttachmentRecycleBinStore().getAllDeletedAttachments(doc, context, true); } return null; } /** * Retrieve all the deleted attachments that belonged to a certain document and had the specified name. Multiple * versions can be returned since the same file can be uploaded and deleted several times, creating different * instances in the trash. Note that this does not distinguish between different incarnations of a document name, * and it does not require that the document still exists, it returns all the attachments that at the time of their * deletion had a document with the specified name as their owner. * * @param docName the {@link DeletedAttachment#getDocName() name of the document} the attachment belonged to * @param filename the {@link DeletedAttachment#getFilename() name} of the attachment to search for * @param context the current request context * @return A list with all the deleted attachments which belonged to the specified document and had the specified * filename. If no such attachments are found in the trash, an empty list is returned. * @throws XWikiException if an error occurs while loading the attachments */ public List<DeletedAttachment> getDeletedAttachments(String docName, String filename, XWikiContext context) throws XWikiException { if (hasAttachmentRecycleBin(context)) { XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(docName)); XWikiAttachment attachment = new XWikiAttachment(doc, filename); return getAttachmentRecycleBinStore().getAllDeletedAttachments(attachment, context, true); } return null; } /** * Retrieve a specific attachment from the trash. * * @param id the unique identifier of the entry in the trash * @return specified attachment from the trash, {@code null} if not found * @throws XWikiException if an error occurs while loading the attachments */ public DeletedAttachment getDeletedAttachment(String id, XWikiContext context) throws XWikiException { if (hasAttachmentRecycleBin(context)) { return getAttachmentRecycleBinStore().getDeletedAttachment(NumberUtils.toLong(id), context, true); } return null; } public XWikiRenderingEngine getRenderingEngine() { return this.renderingEngine; } public void setRenderingEngine(XWikiRenderingEngine renderingEngine) { this.renderingEngine = renderingEngine; } public MetaClass getMetaclass() { return this.metaclass; } public void setMetaclass(MetaClass metaclass) { this.metaclass = metaclass; } public List<String> getClassList(XWikiContext context) throws XWikiException { List<String> result = getStore().getClassList(context); Collections.sort(result); return result; } /* * public String[] getClassList() throws XWikiException { List list = store.getClassList(); String[] array = new * String[list.size()]; for (int i=0;i<list.size();i++) array[i] = (String)list.get(i); return array; } */ public <T> List<T> search(String sql, XWikiContext context) throws XWikiException { return getStore().search(sql, 0, 0, context); } public <T> List<T> search(String sql, int nb, int start, XWikiContext context) throws XWikiException { return getStore().search(sql, nb, start, context); } public <T> List<T> search(String sql, Object[][] whereParams, XWikiContext context) throws XWikiException { return getStore().search(sql, 0, 0, whereParams, context); } public <T> List<T> search(String sql, int nb, int start, Object[][] whereParams, XWikiContext context) throws XWikiException { return getStore().search(sql, nb, start, whereParams, context); } /** * Checks if the wiki is running in test mode. * * @return {@code true} if the wiki is running Cactus tests, {@code false} otherwise * @deprecated No longer used. */ @Deprecated public boolean isTest() { return this.test; } /** * Marks that the wiki is running in test mode. * * @param test whether tests are being executed * @deprecated No longer used. */ @Deprecated public void setTest(boolean test) { this.test = test; } public String parseContent(String content, XWikiContext context) { String parsedContent; if ((content != null) && (!content.equals(""))) { parsedContent = context.getWiki().getRenderingEngine().interpretText(content, context.getDoc(), context); } else { parsedContent = ""; } return parsedContent; } /** * @deprecated use {@link #evaluateTemplate(String, XWikiContext)} instead */ @Deprecated public String parseTemplate(String template, XWikiContext context) { String result = ""; try { result = evaluateTemplate(template, context); } catch (Exception e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Exception while parsing template [" + template + "] from /templates/", e); } } return result; } /** * Evaluate provided template content using velocity engine. * * @param template the template to evaluate * @param context the XWiki context * @return the return of the velocity script * @throws IOException failed to get the template content * @since 2.2.2 */ public String evaluateTemplate(String template, XWikiContext context) throws IOException { try { String skin = getSkin(context); String result = parseTemplate(template, skin, context); if (result != null) { return result; } // If we could not find the template in the skin // let's try in the base skin (as long as the base skin is not the same as the skin) String baseskin = getBaseSkin(context); if (!skin.equals(baseskin)) { result = parseTemplate(template, baseskin, context); if (result != null) { return result; } } // If we still could not find the template in the skin or in the base skin // let's try in the default base skin (as long as the default base skin is not the same // as the skin or the base skin String defaultbaseskin = getDefaultBaseSkin(context); if ((!baseskin.equals(defaultbaseskin)) && (!skin.equals(defaultbaseskin))) { result = parseTemplate(template, defaultbaseskin, context); if (result != null) { return result; } } } catch (Exception ex) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Exception while parsing template [" + template + "] from skin", ex); } } // Prevent inclusion of templates from other directories template = URI.create("/templates/" + template).normalize().toString(); if (!template.startsWith("/templates/")) { LOGGER.warn("Illegal access, tried to use file [" + template + "] as a template. Possible break-in attempt!"); return ""; } String content = getResourceContent(template); return XWikiVelocityRenderer.evaluate(content, template, (VelocityContext) context.get("vcontext"), context); } public String parseTemplate(String template, String skin, XWikiContext context) { try { XWikiDocument doc = getDocument(skin, context); if (!doc.isNew()) { // Try parsing the object property BaseObject object = doc.getXObject(new DocumentReference( doc.getDocumentReference().getWikiReference().getName(), SYSTEM_SPACE, "XWikiSkins")); if (object != null) { String content = object.getStringValue(template); if (StringUtils.isNotBlank(content)) { // Let's use this template // Use "" as namespace to register macros in global namespace. That way it // can be used in a renderer content not parsed at the same level. return XWikiVelocityRenderer.evaluate(content, "", (VelocityContext) context.get("vcontext"), context); } } // Try parsing a document attachment XWikiAttachment attachment = doc.getAttachment(template); if (attachment != null) { // It's impossible to know the real attachemtn encoding, but let's assume that they respect the // standard and use UTF-8 (which is required for the files located on the filesystem) String content = IOUtils.toString(attachment.getContentInputStream(context), DEFAULT_ENCODING); if (StringUtils.isNotBlank(content)) { // Let's use this template // Use "" as namespace to register macros in global namespace. That way it // can be used in a renderer content not parsed at the same level. return XWikiVelocityRenderer.evaluate(content, "", (VelocityContext) context.get("vcontext"), context); } } } } catch (Exception e) { } // Try parsing a file located in the directory with the same name. try { String path = "/skins/" + skin + "/" + template; // We must make sure the file is taken from the skins directory, otherwise people might // try to read things from WEB-INF. path = URI.create(path).normalize().toString(); // This is a safe assumption, as templates found under /templates/ are treated // separately, and there is no need to have templates in another place. if (path.startsWith("/skins/")) { String content = getResourceContent(path); // Use "" as namespace to register macros in global namespace. That way it can be // used in a renderer content not parsed at the same level. return XWikiVelocityRenderer.evaluate(content, "", (VelocityContext) context.get("vcontext"), context); } else { LOGGER.warn("Illegal access, tried to use file [" + path + "] as a template." + " Possible break-in attempt!"); } } catch (Exception e) { } return null; } public String renderTemplate(String template, String skin, XWikiContext context) { try { return getRenderingEngine().getRenderer("wiki").render(parseTemplate(template, skin, context), context.getDoc(), context.getDoc(), context); } catch (Exception ex) { LOGGER.error("Failed to render template [" + template + "] for skin [" + skin + "]", ex); return parseTemplate(template, skin, context); } } public String renderTemplate(String template, XWikiContext context) { try { return getRenderingEngine().getRenderer("wiki").render(parseTemplate(template, context), context.getDoc(), context.getDoc(), context); } catch (Exception ex) { LOGGER.error("Failed to render template [" + template + "]", ex); return parseTemplate(template, context); } } /** * Designed to include dynamic content, such as Servlets or JSPs, inside Velocity templates; works by creating a * RequestDispatcher, buffering the output, then returning it as a string. * * @author LBlaze */ public String invokeServletAndReturnAsString(String url, XWikiContext xwikiContext) { HttpServletRequest servletRequest = xwikiContext.getRequest(); HttpServletResponse servletResponse = xwikiContext.getResponse(); try { return IncludeServletAsString.invokeServletAndReturnAsString(url, servletRequest, servletResponse); } catch (Exception e) { LOGGER.warn("Exception including url: " + url, e); return "Exception including \"" + url + "\", see logs for details."; } } /** * @param iconName the standard name of an icon (it's not the name of the file on the filesystem, it's a generic * name, for example "success" for a success icon * @return the URL to the icon resource * @since 2.6M1 */ public String getIconURL(String iconName, XWikiContext context) { // TODO: Do a better mapping between generic icon name and physical resource name, especially to be independent // of the underlying icon library. Right now we assume it's the Silk icon library. return getSkinFile("icons/silk/" + iconName + ".gif", context); } public String getSkinFile(String filename, XWikiContext context) { return getSkinFile(filename, false, context); } public String getSkinFile(String filename, boolean forceSkinAction, XWikiContext context) { XWikiURLFactory urlf = context.getURLFactory(); try { // Try in the specified skin String skin = getSkin(context); String result = getSkinFile(filename, skin, forceSkinAction, context); if (result != null) { return result; } // Try in the parent skin String baseskin = getBaseSkin(context); if (!skin.equals(baseskin)) { result = getSkinFile(filename, baseskin, forceSkinAction, context); if (result != null) { return result; } } } catch (Exception e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Exception while getting skin file [" + filename + "]", e); } } // If all else fails, use the default base skin, even if the URLs could be invalid. URL url; if (forceSkinAction) { url = urlf.createSkinURL(filename, "skins", getDefaultBaseSkin(context), context); } else { url = urlf.createSkinURL(filename, getDefaultBaseSkin(context), context); } return urlf.getURL(url, context); } public String getSkinFile(String filename, String skin, XWikiContext context) { return getSkinFile(filename, skin, false, context); } public String getSkinFile(String filename, String skin, boolean forceSkinAction, XWikiContext context) { XWikiURLFactory urlf = context.getURLFactory(); try { XWikiDocument doc = getDocument(skin, context); if (!doc.isNew()) { // Look for an object property BaseObject object = doc.getXObject(new DocumentReference( doc.getDocumentReference().getWikiReference().getName(), SYSTEM_SPACE, "XWikiSkins")); if (object != null) { String content = object.getStringValue(filename); if (StringUtils.isNotBlank(content)) { URL url = urlf.createSkinURL(filename, doc.getSpace(), doc.getName(), doc.getDatabase(), context); return urlf.getURL(url, context); } } // Look for an attachment String shortName = StringUtils.replaceChars(filename, '/', '.'); XWikiAttachment attachment = doc.getAttachment(shortName); if (attachment != null) { return doc.getAttachmentURL(shortName, "skin", context); } } // Look for a skin file String path = "/skins/" + skin + "/" + filename; if (resourceExists(path)) { URL url; if (forceSkinAction) { url = urlf.createSkinURL(filename, "skins", skin, context); } else { url = urlf.createSkinURL(filename, skin, context); } return urlf.getURL(url, context); } // Look for a resource file path = "/resources/" + filename; if (resourceExists(path)) { URL url; url = urlf.createResourceURL(filename, forceSkinAction, context); return urlf.getURL(url, context); } } catch (Exception e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Exception while getting skin file [" + filename + "] from skin [" + skin + "]", e); } } return null; } public String getSkin(XWikiContext context) { String skin = ""; try { // Try to get it from context skin = (String) context.get("skin"); if (skin != null) { return skin; } // Try to get it from URL if (context.getRequest() != null) { skin = context.getRequest().getParameter("skin"); if (LOGGER.isDebugEnabled()) { if (skin != null && !skin.equals("")) { LOGGER.debug("Requested skin in the URL: [" + skin + "]"); } } } if ((skin == null) || (skin.equals(""))) { skin = getUserPreference("skin", context); if (LOGGER.isDebugEnabled()) { if (skin != null && !skin.equals("")) { LOGGER.debug("Configured skin in user preferences: [" + skin + "]"); } } } if (skin == null || skin.equals("")) { skin = Param("xwiki.defaultskin"); if (LOGGER.isDebugEnabled()) { if (skin != null && !skin.equals("")) { LOGGER.debug("Configured default skin in preferences: [" + skin + "]"); } } } if (skin == null || skin.equals("")) { skin = getDefaultBaseSkin(context); if (LOGGER.isDebugEnabled()) { if (skin != null && !skin.equals("")) { LOGGER.debug("Configured default base skin in preferences: [" + skin + "]"); } } } } catch (Exception e) { LOGGER.debug("Exception while determining current skin", e); skin = getDefaultBaseSkin(context); } try { if (skin.indexOf('.') != -1) { if (!getRightService().hasAccessLevel("view", context.getUser(), skin, context)) { LOGGER.debug("Cannot access configured skin due to access rights, using the default skin."); skin = Param("xwiki.defaultskin", getDefaultBaseSkin(context)); } } } catch (XWikiException e) { // if it fails here, let's just ignore it LOGGER.debug("Exception while determining current skin", e); } context.put("skin", skin); return skin; } public String getSkinPreference(String prefname, XWikiContext context) { return getSkinPreference(prefname, "", context); } public String getSkinPreference(String prefname, String default_value, XWikiContext context) { try { String skin = getSkin(context); String oldskin = skin; String value = context.getWiki().getDocument(skin, context).getStringValue("XWiki.XWikiSkins", prefname); if (value == null || "".equals(value)) { skin = getBaseSkin(context); if (!oldskin.equals(skin)) { value = context.getWiki().getDocument(skin, context).getStringValue("XWiki.XWikiSkins", prefname); oldskin = skin; } } if (value == null || "".equals(value)) { skin = getDefaultBaseSkin(context); if (!oldskin.equals(skin)) { value = context.getWiki().getDocument(skin, context).getStringValue("XWiki.XWikiSkins", prefname); } } if (value == null || "".equals(value)) { value = default_value; } return value; } catch (XWikiException ex) { LOGGER.warn("", ex); } return default_value; } public String getDefaultBaseSkin(XWikiContext context) { String defaultbaseskin = Param("xwiki.defaultbaseskin", ""); if (defaultbaseskin.equals("")) { defaultbaseskin = Param("xwiki.defaultskin", "colibri"); } return defaultbaseskin; } public String getBaseSkin(XWikiContext context) { return getBaseSkin(context, false); } public String getBaseSkin(XWikiContext context, boolean fromRenderSkin) { String baseskin = ""; try { // Try to get it from context baseskin = (String) context.get("baseskin"); if (baseskin != null) { return baseskin; } else { baseskin = ""; } // Let's get the base skin doc itself if (fromRenderSkin) { baseskin = context.getDoc().getStringValue("XWiki.XWikiSkins", "baseskin"); } if (baseskin.equals("")) { // Let's get the base skin from the skin itself String skin = getSkin(context); baseskin = getBaseSkin(skin, context); } if (baseskin.equals("")) { baseskin = getDefaultBaseSkin(context); } } catch (Exception e) { baseskin = getDefaultBaseSkin(context); LOGGER.debug("Exception while determining base skin", e); } context.put("baseskin", baseskin); return baseskin; } /** * @param skin the full name of the skin document for which to return the base skin. For example : * <tt>XWiki.DefaultSkin</tt> * @param context the XWiki context * @return if found, the name of the base skin the asked skin inherits from. If not found, returns an empty string. * @since 2.0.2 * @since 2.1M1 */ public String getBaseSkin(String skin, XWikiContext context) { if (context.getWiki().exists(skin, context)) { try { return getDocument(skin, context).getStringValue("XWiki.XWikiSkins", "baseskin"); } catch (XWikiException e) { // Do nothing and let return the empty string. } } return ""; } public String getSpaceCopyright(XWikiContext context) { String defaultValue = "Copyright 2004-" + Calendar.getInstance().get(Calendar.YEAR) + " XWiki"; return getSpacePreference("webcopyright", defaultValue, context); } public String getXWikiPreference(String prefname, XWikiContext context) { return getXWikiPreference(prefname, "", context); } /** * Obtain a preference value for the wiki, looking up first in the XWiki.XWikiPreferences document, then fallbacking * on a config parameter when the first lookup gives an empty string, then returning the default value if the config * parameter returned itself an empty string. * * @param prefname the parameter to look for in the XWiki.XWikiPreferences object corresponding to the context's * language in the XWiki.XWikiPreferences document of the wiki (or the first XWiki.XWikiPreferences * object contained, if the one for the context'ds language could not be found). * @param fallback_param the parameter in xwiki.cfg to fallback on, in case the XWiki.XWikiPreferences object gave * no result * @param default_value the default value to fallback on, in case both XWiki.XWikiPreferences and the fallback * xwiki.cfg parameter gave no result */ public String getXWikiPreference(String prefname, String fallback_param, String default_value, XWikiContext context) { try { DocumentReference xwikiPreferencesReference = new DocumentReference("XWikiPreferences", new SpaceReference(SYSTEM_SPACE, new WikiReference(context.getDatabase()))); XWikiDocument doc = getDocument(xwikiPreferencesReference, context); // First we try to get a translated preference object BaseObject object = doc.getXObject(xwikiPreferencesReference, "default_language", context.getLanguage(), true); String result = ""; if (object != null) { try { result = object.getStringValue(prefname); } catch (Exception e) { LOGGER.warn("Exception while getting wiki preference [" + prefname + "]", e); } } // If empty we take it from the default pref object if (result.equals("")) { object = doc.getXObject(); if (object != null) { result = object.getStringValue(prefname); } } if (!result.equals("")) { return result; } } catch (Exception e) { LOGGER.warn("Exception while getting wiki preference [" + prefname + "]", e); } return Param(fallback_param, default_value); } public String getXWikiPreference(String prefname, String default_value, XWikiContext context) { return getXWikiPreference(prefname, "", default_value, context); } public String getSpacePreference(String preference, XWikiContext context) { return getSpacePreference(preference, "", context); } public String getSpacePreference(String preference, String defaultValue, XWikiContext context) { XWikiDocument currentdoc = (XWikiDocument) context.get("doc"); return getSpacePreference(preference, (currentdoc == null) ? null : currentdoc.getSpace(), defaultValue, context); } public String getSpacePreference(String preference, String space, String defaultValue, XWikiContext context) { // If there's no space defined then don't return space preferences (since it'll usually mean that the current // doc is not set). if (space != null) { try { XWikiDocument doc = getDocument(space + ".WebPreferences", context); // First we try to get a translated preference object DocumentReference xwikiPreferencesReference = new DocumentReference("XWikiPreferences", new SpaceReference(SYSTEM_SPACE, new WikiReference(context.getDatabase()))); BaseObject object = doc.getXObject(xwikiPreferencesReference, "default_language", context.getLanguage(), true); String result = ""; if (object != null) { try { result = object.getStringValue(preference); } catch (Exception e) { LOGGER.warn("Exception while getting space preference [" + preference + "]", e); } } if (!result.equals("")) { return result; } } catch (Exception e) { LOGGER.warn("Exception while getting space preference [" + preference + "]", e); } } return getXWikiPreference(preference, defaultValue, context); } public String getUserPreference(String prefname, XWikiContext context) { try { String user = context.getUser(); XWikiDocument userdoc = getDocument(user, context); if (userdoc != null) { String result = userdoc.getStringValue("XWiki.XWikiUsers", prefname); if ((!result.equals("")) && (!result.equals("---"))) { return result; } } } catch (Exception e) { LOGGER.warn("Exception while getting user preference [" + prefname + "]", e); } return getSpacePreference(prefname, context); } public String getUserPreferenceFromCookie(String prefname, XWikiContext context) { Cookie[] cookies = context.getRequest().getCookies(); if (cookies == null) { return null; } for (int i = 0; i < cookies.length; i++) { String name = cookies[i].getName(); if (name.equals(prefname)) { String value = cookies[i].getValue(); if (!value.trim().equals("")) { return value; } else { break; } } } return null; } public String getUserPreference(String prefname, boolean useCookie, XWikiContext context) { // First we look in the cookies if (useCookie) { String result = Util.normalizeLanguage(getUserPreferenceFromCookie(prefname, context)); if (result != null) { return result; } } return getUserPreference(prefname, context); } /** * @deprecated use {@link #getLanguagePreference(XWikiContext)} instead */ @Deprecated public String getDocLanguagePreference(XWikiContext context) { return getLanguagePreference(context); } /** * First try to find the current language in use from the XWiki context. If none is used and if the wiki is not * multilingual use the default language defined in the XWiki preferences. If the wiki is multilingual try to get * the language passed in the request. If none was passed try to get it from a cookie. If no language cookie exists * then use the user default language and barring that use the browser's "Accept-Language" header sent in HTTP * request. If none is defined use the default language. * * @return the language to use */ public String getLanguagePreference(XWikiContext context) { // First we try to get the language from the XWiki Context. This is the current language // being used. String language = context.getLanguage(); if (language != null) { return language; } String defaultLanguage = getDefaultLanguage(context); // If the wiki is non multilingual then the language is the default language. if (!context.getWiki().isMultiLingual(context)) { language = defaultLanguage; context.setLanguage(language); return language; } // As the wiki is multilingual try to find the language to use from the request by looking // for a language parameter. If the language value is "default" use the default language // from the XWiki preferences settings. Otherwise set a cookie to remember the language // in use. try { language = Util.normalizeLanguage(context.getRequest().getParameter("language")); if ((language != null) && (!language.equals(""))) { if (language.equals("default")) { // forgetting language cookie Cookie cookie = new Cookie("language", ""); cookie.setMaxAge(0); cookie.setPath("/"); context.getResponse().addCookie(cookie); language = defaultLanguage; } else { // setting language cookie Cookie cookie = new Cookie("language", language); cookie.setMaxAge(60 * 60 * 24 * 365 * 10); cookie.setPath("/"); context.getResponse().addCookie(cookie); } context.setLanguage(language); return language; } } catch (Exception e) { } // As no language parameter was passed in the request, try to get the language to use // from a cookie. try { // First we get the language from the cookie language = Util.normalizeLanguage(getUserPreferenceFromCookie("language", context)); if ((language != null) && (!language.equals(""))) { context.setLanguage(language); return language; } } catch (Exception e) { } // Next from the default user preference try { String user = context.getUser(); XWikiDocument userdoc = null; userdoc = getDocument(user, context); if (userdoc != null) { language = Util.normalizeLanguage(userdoc.getStringValue("XWiki.XWikiUsers", "default_language")); if (!language.equals("")) { context.setLanguage(language); return language; } } } catch (XWikiException e) { } // If the default language is preferred, and since the user didn't explicitly ask for a // language already, then use the default wiki language. if (Param("xwiki.language.preferDefault", "0").equals("1") || getSpacePreference("preferDefaultLanguage", "0", context).equals("1")) { language = defaultLanguage; context.setLanguage(language); return language; } // Then from the navigator language setting if (context.getRequest() != null) { String acceptHeader = context.getRequest().getHeader("Accept-Language"); // If the client didn't specify some languages, skip this phase if ((acceptHeader != null) && (!acceptHeader.equals(""))) { List<String> acceptedLanguages = getAcceptedLanguages(context.getRequest()); // We can force one of the configured languages to be accepted if (Param("xwiki.language.forceSupported", "0").equals("1")) { List<String> available = Arrays.asList(getXWikiPreference("languages", context).split("[, |]")); // Filter only configured languages acceptedLanguages.retainAll(available); } if (acceptedLanguages.size() > 0) { // Use the "most-preferred" language, as requested by the client. context.setLanguage(acceptedLanguages.get(0)); return acceptedLanguages.get(0); } // If none of the languages requested by the client is acceptable, skip to next // phase (use default language). } } // Finally, use the default language from the global preferences. context.setLanguage(defaultLanguage); return defaultLanguage; } /** * Construct a list of language codes (ISO 639-1) from the Accept-Languages header. This method filters out some * bugs in different browsers or containers, like returning '*' as a language (Jetty) or using '_' as a * language--country delimiter (some versions of Opera). * * @param request The client request. * @return A list of language codes, in the client preference order; might be empty if the header is not well * formed. */ @SuppressWarnings("unchecked") private List<String> getAcceptedLanguages(XWikiRequest request) { List<String> result = new ArrayList<String>(); Enumeration<Locale> e = request.getLocales(); while (e.hasMoreElements()) { String language = e.nextElement().getLanguage().toLowerCase(); // All language codes should have 2 letters. if (StringUtils.isAlpha(language)) { result.add(language); } } return result; } public String getDefaultLanguage(XWikiContext context) { // Find out what is the default language from the XWiki preferences settings. String defaultLanguage = context.getWiki().getXWikiPreference("default_language", "", context); if (StringUtils.isBlank(defaultLanguage)) { defaultLanguage = "en"; } return Util.normalizeLanguage(defaultLanguage); } public String getDocLanguagePreferenceNew(XWikiContext context) { // Get context language String contextLanguage = context.getLanguage(); // If the language exists in the context, it was previously set by another call if (contextLanguage != null && contextLanguage != "") { return contextLanguage; } String language = "", requestLanguage = "", userPreferenceLanguage = "", navigatorLanguage = "", cookieLanguage = ""; boolean setCookie = false; if (!context.getWiki().isMultiLingual(context)) { language = context.getWiki().getXWikiPreference("default_language", "", context); context.setLanguage(language); return language; } // Get request language try { requestLanguage = Util.normalizeLanguage(context.getRequest().getParameter("language")); } catch (Exception ex) { } // Get user preference try { String user = context.getUser(); XWikiDocument userdoc = getDocument(user, context); if (userdoc != null) { userPreferenceLanguage = userdoc.getStringValue("XWiki.XWikiUsers", "default_language"); } } catch (XWikiException e) { } // Get navigator language setting if (context.getRequest() != null) { String accept = context.getRequest().getHeader("Accept-Language"); if ((accept != null) && (!accept.equals(""))) { String[] alist = StringUtils.split(accept, ",;-"); if ((alist != null) && !(alist.length == 0)) { context.setLanguage(alist[0]); navigatorLanguage = alist[0]; } } } // Get language from cookie try { cookieLanguage = Util.normalizeLanguage(getUserPreferenceFromCookie("language", context)); } catch (Exception e) { } // Determine which language to use // First we get the language from the request if ((requestLanguage != null) && (!requestLanguage.equals(""))) { if (requestLanguage.equals("default")) { setCookie = true; } else { language = requestLanguage; context.setLanguage(language); Cookie cookie = new Cookie("language", language); cookie.setMaxAge(60 * 60 * 24 * 365 * 10); cookie.setPath("/"); context.getResponse().addCookie(cookie); return language; } } // Next we get the language from the cookie if (cookieLanguage != null && cookieLanguage != "") { language = cookieLanguage; } // Next from the default user preference else if (userPreferenceLanguage != null && userPreferenceLanguage != "") { language = userPreferenceLanguage; } // Then from the navigator language setting else if (navigatorLanguage != null && navigatorLanguage != "") { language = navigatorLanguage; } context.setLanguage(language); if (setCookie) { Cookie cookie = new Cookie("language", language); cookie.setMaxAge(60 * 60 * 24 * 365 * 10); cookie.setPath("/"); context.getResponse().addCookie(cookie); } return language; } public String getInterfaceLanguagePreference(XWikiContext context) { String language = "", requestLanguage = "", userPreferenceLanguage = "", navigatorLanguage = "", cookieLanguage = "", contextLanguage = ""; boolean setCookie = false; if (!context.getWiki().isMultiLingual(context)) { language = Util .normalizeLanguage(context.getWiki().getXWikiPreference("default_language", "", context)); context.setInterfaceLanguage(language); return language; } // Get request language try { requestLanguage = Util.normalizeLanguage(context.getRequest().getParameter("interfacelanguage")); } catch (Exception ex) { } // Get context language contextLanguage = context.getInterfaceLanguage(); // Get user preference try { String user = context.getUser(); XWikiDocument userdoc = null; userdoc = getDocument(user, context); if (userdoc != null) { userPreferenceLanguage = userdoc.getStringValue("XWiki.XWikiUsers", "default_interface_language"); } } catch (XWikiException e) { } // Get navigator language setting if (context.getRequest() != null) { String accept = context.getRequest().getHeader("Accept-Language"); if ((accept != null) && (!accept.equals(""))) { String[] alist = StringUtils.split(accept, ",;-"); if ((alist != null) && !(alist.length == 0)) { context.setLanguage(alist[0]); navigatorLanguage = alist[0]; } } } // Get language from cookie try { cookieLanguage = Util.normalizeLanguage(getUserPreferenceFromCookie("interfacelanguage", context)); } catch (Exception e) { } // Determine which language to use // First we get the language from the request if ((requestLanguage != null) && (!requestLanguage.equals(""))) { if (requestLanguage.equals("default")) { setCookie = true; } else { language = requestLanguage; context.setLanguage(language); Cookie cookie = new Cookie("interfacelanguage", language); cookie.setMaxAge(60 * 60 * 24 * 365 * 10); cookie.setPath("/"); context.getResponse().addCookie(cookie); return language; } } // Next we get the language from the context if (contextLanguage != null && contextLanguage != "") { language = contextLanguage; } // Next we get the language from the cookie else if (cookieLanguage != null && cookieLanguage != "") { language = cookieLanguage; } // Next from the default user preference else if (userPreferenceLanguage != null && userPreferenceLanguage != "") { language = userPreferenceLanguage; } // Then from the navigator language setting else if (navigatorLanguage != null && navigatorLanguage != "") { language = navigatorLanguage; } context.setLanguage(language); if (setCookie) { Cookie cookie = new Cookie("interfacelanguage", language); cookie.setMaxAge(60 * 60 * 24 * 365 * 10); cookie.setPath("/"); context.getResponse().addCookie(cookie); } return language; } public long getXWikiPreferenceAsLong(String preference, XWikiContext context) { return Long.parseLong(getXWikiPreference(preference, context)); } public long getSpacePreferenceAsLong(String preference, XWikiContext context) { return Long.parseLong(getSpacePreference(preference, context)); } public long getXWikiPreferenceAsLong(String preference, long defaultValue, XWikiContext context) { return NumberUtils.toLong((getXWikiPreference(preference, context)), defaultValue); } public long getXWikiPreferenceAsLong(String preference, String fallbackParameter, long defaultValue, XWikiContext context) { return NumberUtils.toLong(getXWikiPreference(preference, fallbackParameter, "", context), defaultValue); } public long getSpacePreferenceAsLong(String preference, long defaultValue, XWikiContext context) { return NumberUtils.toLong(getSpacePreference(preference, context), defaultValue); } public long getUserPreferenceAsLong(String preference, XWikiContext context) { return Long.parseLong(getUserPreference(preference, context)); } public int getXWikiPreferenceAsInt(String preference, XWikiContext context) { return Integer.parseInt(getXWikiPreference(preference, context)); } public int getSpacePreferenceAsInt(String preference, XWikiContext context) { return Integer.parseInt(getSpacePreference(preference, context)); } public int getXWikiPreferenceAsInt(String preference, int defaultValue, XWikiContext context) { return NumberUtils.toInt(getXWikiPreference(preference, context), defaultValue); } public int getXWikiPreferenceAsInt(String preference, String fallbackParameter, int defaultValue, XWikiContext context) { return NumberUtils.toInt(getXWikiPreference(preference, fallbackParameter, "", context), defaultValue); } public int getSpacePreferenceAsInt(String preference, int defaultValue, XWikiContext context) { return NumberUtils.toInt(getSpacePreference(preference, context), defaultValue); } public int getUserPreferenceAsInt(String prefname, XWikiContext context) { return Integer.parseInt(getUserPreference(prefname, context)); } /** * Get XWiki context from execution context. * * @return the XWiki context for the current thread */ private XWikiContext getXWikiContext() { Execution execution = Utils.getComponent(Execution.class); ExecutionContext ec = execution.getContext(); return ec != null ? (XWikiContext) ec.getProperty("xwikicontext") : null; } /** * @deprecated user {@link #flushCache(XWikiContext)} instead */ @Deprecated public void flushCache() { flushCache(getXWikiContext()); } public void flushCache(XWikiContext context) { // We need to flush the virtual wiki list this.virtualWikiList = new ArrayList<String>(); // We need to flush the server Cache if (this.virtualWikiMap != null) { this.virtualWikiMap.dispose(); this.virtualWikiMap = null; } // We need to flush the group service cache if (this.groupService != null) { this.groupService.flushCache(); } // If we use the Cache Store layer.. we need to flush it XWikiStoreInterface store = getStore(); if ((store != null) && (store instanceof XWikiCacheStoreInterface)) { ((XWikiCacheStoreInterface) getStore()).flushCache(); } // Flush renderers.. Groovy renderer has a cache XWikiRenderingEngine rengine = getRenderingEngine(); if (rengine != null) { rengine.flushCache(); } XWikiPluginManager pmanager = getPluginManager(); if (pmanager != null) { pmanager.flushCache(context); } // Make sure we call all classes flushCache function try { List<String> classes = getClassList(context); for (int i = 0; i < classes.size(); i++) { String className = classes.get(i); try { getClass(className, context).flushCache(); } catch (Exception e) { } } } catch (Exception e) { } } public XWikiPluginManager getPluginManager() { return this.pluginManager; } public void setPluginManager(XWikiPluginManager pluginManager) { this.pluginManager = pluginManager; } public void setConfig(XWikiConfig config) { this.config = config; } public void setStore(XWikiStoreInterface store) { this.store = store; } public void setAttachmentStore(XWikiAttachmentStoreInterface attachmentStore) { this.attachmentStore = attachmentStore; } public void setAttachmentVersioningStore(AttachmentVersioningStore avStore) { this.attachmentVersioningStore = avStore; } public void setVersioningStore(XWikiVersioningStoreInterface versioningStore) { this.versioningStore = versioningStore; } public void setRecycleBinStore(XWikiRecycleBinStoreInterface recycleBinStore) { this.recycleBinStore = recycleBinStore; } public void setAttachmentRecycleBinStore(AttachmentRecycleBinStore attachmentRecycleBinStore) { this.attachmentRecycleBinStore = attachmentRecycleBinStore; } public void setCriteriaService(XWikiCriteriaService criteriaService) { this.criteriaService = criteriaService; } public void setVersion(String version) { this.version = version; } private void flushVirtualWikis(XWikiDocument doc) { List<BaseObject> bobjects = doc.getXObjects(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE); if (bobjects != null) { for (BaseObject bobj : bobjects) { if (bobj != null) { String host = bobj.getStringValue("server"); if (StringUtils.isNotEmpty(host)) { if (this.virtualWikiMap != null) { if (this.virtualWikiMap.get(host) != null) { this.virtualWikiMap.remove(host); } } } } } } } /** * Verify if the <code>XWiki.TagClass</code> page exists and that it contains all the required configuration * properties to make the tag feature work properly. If some properties are missing they are created and saved in * the database. * * @param context the XWiki Context * @return the TagClass Base Class object containing the properties * @throws XWikiException if an error happens during the save to the datavase */ public BaseClass getTagClass(XWikiContext context) throws XWikiException { XWikiDocument doc; boolean needsUpdate = false; doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "TagClass"), context); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } needsUpdate |= bclass.addStaticListField(XWikiConstant.TAG_CLASS_PROP_TAGS, "Tags", 30, true, true, "", "input", "|,"); StaticListClass tagClass = (StaticListClass) bclass.get(XWikiConstant.TAG_CLASS_PROP_TAGS); if (tagClass.isRelationalStorage() == false) { tagClass.setRelationalStorage(true); needsUpdate = true; } needsUpdate |= setClassDocumentFields(doc, "XWiki Tag Class"); if (needsUpdate) { saveDocument(doc, context); } return bclass; } /** * Verify if the <code>XWiki.SheetClass</code> page exists and that it contains all the required configuration * properties to make the sheet feature work properly. If some properties are missing they are created and saved in * the database. SheetClass is used to a page as a sheet. When a page is tagged as a sheet and that page is included * in another page using the include macro then editing it triggers automatic inline edition (for XWiki Syntax 2.0 * only - for XWiki Syntax 1.0 automatic inline edition is triggered using #includeForm). * * @param context the XWiki Context * @return the SheetClass Base Class object containing the properties * @throws XWikiException if an error happens during the save to the database * @deprecated since 3.1M2 edit mode class should be used for this purpose, not the sheet class * @see #getEditModeClass(XWikiContext) */ public BaseClass getSheetClass(XWikiContext context) throws XWikiException { XWikiDocument doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "SheetClass"), context); boolean needsUpdate = doc.isNew(); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } // Note: Ideally we don't want a special field in the sheet class but XWiki classes must have at // least one field or they're not saved. Thus we are introducing a "defaultEditMode" which will // tell what edit mode to use. If empty it'll default to "inline". needsUpdate |= bclass.addTextField("defaultEditMode", "Default Edit Mode", 15); if (doc.isNew()) { needsUpdate |= setClassDocumentFields(doc, "XWiki Sheet Class"); doc.setContent(doc.getContent() + "\n\nClass that should be used to recognize sheet pages."); } if (needsUpdate) { saveDocument(doc, context); } return bclass; } /** * Verify if the {@code XWiki.EditModeClass} page exists and that it contains all the required configuration * properties to make the edit mode feature work properly. If some properties are missing they are created and saved * in the database. EditModeClass is used to specify the default edit mode of a page. It can also be used to mark a * page as a sheet. When a page is marked as a sheet and that page is included in another page using the include * macro then editing it triggers automatic inline edition (for XWiki Syntax 2.0 only - for XWiki Syntax 1.0 * automatic inline edition is triggered using #includeForm). It replaces and enhances the SheetClass mechanism (see * {@link #getSheetClass(XWikiContext)}). * * @param context the XWiki Context * @return the EditModeClass Base Class object containing the properties * @throws XWikiException if an error happens during the save to the database * @since 3.1M2 */ public BaseClass getEditModeClass(XWikiContext context) throws XWikiException { DocumentReference classReference = new DocumentReference(context.getDatabase(), XWikiConstant.EDIT_MODE_CLASS.getParent().getName(), XWikiConstant.EDIT_MODE_CLASS.getName()); XWikiDocument doc = getDocument(classReference, context); boolean needsUpdate = doc.isNew(); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } needsUpdate |= bclass.addTextField("defaultEditMode", "Default Edit Mode", 15); if (doc.isNew()) { needsUpdate |= setClassDocumentFields(doc, "XWiki Edit Mode Class"); doc.setContent("Class that should be used to specify the edit mode of a page."); } if (needsUpdate) { saveDocument(doc, context); } return bclass; } /** * Verify if the <code>XWiki.XWikiUsers</code> page exists and that it contains all the required configuration * properties to make the user feature work properly. If some properties are missing they are created and saved in * the database. * * @param context the XWiki Context * @return the XWikiUsers Base Class object containing the properties * @throws XWikiException if an error happens during the save to the datavase */ public BaseClass getUserClass(XWikiContext context) throws XWikiException { XWikiDocument doc; boolean needsUpdate = false; doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "XWikiUsers"), context); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } needsUpdate |= bclass.addTextField("first_name", "First Name", 30); needsUpdate |= bclass.addTextField("last_name", "Last Name", 30); needsUpdate |= bclass.addTextField("email", "e-Mail", 30); needsUpdate |= bclass.addPasswordField("password", "Password", 10); needsUpdate |= bclass.addPasswordField("validkey", "Validation Key", 10); needsUpdate |= bclass.addBooleanField("active", "Active", "active"); needsUpdate |= bclass.addTextField("default_language", "Default Language", 30); needsUpdate |= bclass.addTextField("company", "Company", 30); needsUpdate |= bclass.addTextField("blog", "Blog", 60); needsUpdate |= bclass.addTextField("blogfeed", "Blog Feed", 60); needsUpdate |= bclass.addTextAreaField("comment", "Comment", 40, 5); needsUpdate |= bclass.addStaticListField("imtype", "IM Type", "---|AIM|Yahoo|Jabber|MSN|Skype|ICQ"); needsUpdate |= bclass.addTextField("imaccount", "imaccount", 30); needsUpdate |= bclass.addStaticListField("editor", "Default Editor", "---|Text|Wysiwyg"); needsUpdate |= bclass.addStaticListField("usertype", "User type", "Simple|Advanced"); needsUpdate |= bclass.addBooleanField("accessibility", "Enable extra accessibility features", "yesno"); // New fields for the XWiki 1.0 skin needsUpdate |= bclass.addTextField("skin", "skin", 30); needsUpdate |= bclass.addTextField("avatar", "Avatar", 30); needsUpdate |= bclass.addTextField("phone", "Phone", 30); needsUpdate |= bclass.addTextAreaField("address", "Address", 40, 3); needsUpdate |= setClassDocumentFields(doc, "XWiki User Class"); // Use XWikiUserSheet to display documents having XWikiUsers objects if no other class sheet is specified. SheetBinder classSheetBinder = Utils.getComponent(SheetBinder.class, "class"); if (classSheetBinder.getSheets(doc).isEmpty()) { DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "XWikiUserSheet"); needsUpdate |= classSheetBinder.bind(doc, sheet); } if (needsUpdate) { saveDocument(doc, context); } return bclass; } /** * Verify if the <code>XWiki.GlobalRedirect</code> page exists and that it contains all the required configuration * properties to make the redirection feature work properly. If some properties are missing they are created and * saved in the database. * * @param context the XWiki Context * @return the GlobalRedirect Base Class object containing the properties * @throws XWikiException if an error happens during the save to the datavase */ public BaseClass getRedirectClass(XWikiContext context) throws XWikiException { XWikiDocument doc; boolean needsUpdate = false; doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "GlobalRedirect"), context); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } needsUpdate |= bclass.addTextField("pattern", "Pattern", 30); needsUpdate |= bclass.addTextField("destination", "Destination", 30); needsUpdate |= setClassDocumentFields(doc, "XWiki Global Redirect Class"); if (needsUpdate) { saveDocument(doc, context); } return bclass; } /** * Verify if the <code>XWiki.XWikiPreferences</code> page exists and that it contains all the required configuration * properties to make XWiki work properly. If some properties are missing they are created and saved in the * database. * * @param context the XWiki Context * @return the XWiki Base Class object containing the properties * @throws XWikiException if an error happens during the save to the datavase */ public BaseClass getPrefsClass(XWikiContext context) throws XWikiException { XWikiDocument doc; boolean needsUpdate = false; doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "XWikiPreferences"), context); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } if (!"internal".equals(bclass.getCustomMapping())) { needsUpdate = true; bclass.setCustomMapping("internal"); } needsUpdate |= bclass.addTextField("parent", "Parent Space", 30); needsUpdate |= bclass.addBooleanField("multilingual", "Multi-Lingual", "yesno"); needsUpdate |= bclass.addTextField("default_language", "Default Language", 5); needsUpdate |= bclass.addBooleanField("authenticate_edit", "Authenticated Edit", "yesno"); needsUpdate |= bclass.addBooleanField("authenticate_view", "Authenticated View", "yesno"); needsUpdate |= bclass.addBooleanField("auth_active_check", "Authentication Active Check", "yesno"); needsUpdate |= bclass.addTextField("skin", "Skin", 30); needsUpdate |= bclass.addDBListField("colorTheme", "Color theme", "select doc.fullName, doc.title from XWikiDocument as doc, BaseObject as theme " + "where doc.fullName=theme.name and theme.className='ColorThemes.ColorThemeClass' " + "and doc.fullName<>'ColorThemes.ColorThemeTemplate'"); // This one should not be in the prefs PropertyInterface baseskinProp = bclass.get("baseskin"); if (baseskinProp != null) { bclass.removeField("baseskin"); needsUpdate = true; } needsUpdate |= bclass.addTextField("stylesheet", "Default Stylesheet", 30); needsUpdate |= bclass.addTextField("stylesheets", "Alternative Stylesheet", 60); needsUpdate |= bclass.addBooleanField("accessibility", "Enable extra accessibility features", "yesno"); needsUpdate |= bclass.addStaticListField("editor", "Default Editor", "---|Text|Wysiwyg"); needsUpdate |= bclass.addTextField("webcopyright", "Copyright", 30); needsUpdate |= bclass.addTextField("title", "Title", 30); needsUpdate |= bclass.addTextField("version", "Version", 30); needsUpdate |= bclass.addTextAreaField("meta", "HTTP Meta Info", 60, 8); needsUpdate |= bclass.addTextField("dateformat", "Date Format", 30); // mail needsUpdate |= bclass.addBooleanField("use_email_verification", "Use eMail Verification", "yesno"); needsUpdate |= bclass.addTextField("admin_email", "Admin eMail", 30); needsUpdate |= bclass.addTextField("smtp_server", "SMTP Server", 30); needsUpdate |= bclass.addTextField("smtp_port", "SMTP Port", 5); needsUpdate |= bclass.addTextField("smtp_server_username", "Server username (optional)", 30); needsUpdate |= bclass.addTextField("smtp_server_password", "Server password (optional)", 30); needsUpdate |= bclass.addTextAreaField("javamail_extra_props", "Additional JavaMail properties", 60, 6); needsUpdate |= bclass.addTextAreaField("validation_email_content", "Validation eMail Content", 72, 10); needsUpdate |= bclass.addTextAreaField("confirmation_email_content", "Confirmation eMail Content", 72, 10); needsUpdate |= bclass.addTextAreaField("invitation_email_content", "Invitation eMail Content", 72, 10); needsUpdate |= bclass.addStaticListField("registration_anonymous", "Anonymous", "---|Image|Text"); needsUpdate |= bclass.addStaticListField("registration_registered", "Registered", "---|Image|Text"); needsUpdate |= bclass.addStaticListField("edit_anonymous", "Anonymous", "---|Image|Text"); needsUpdate |= bclass.addStaticListField("edit_registered", "Registered", "---|Image|Text"); needsUpdate |= bclass.addStaticListField("comment_anonymous", "Anonymous", "---|Image|Text"); needsUpdate |= bclass.addStaticListField("comment_registered", "Registered", "---|Image|Text"); needsUpdate |= bclass.addNumberField("upload_maxsize", "Maximum Upload Size", 5, "long"); // Captcha for guest comments needsUpdate |= bclass.addBooleanField("guest_comment_requires_captcha", "Enable CAPTCHA in Comments for Unregistered Users", "select"); // Document editing needsUpdate |= bclass.addTextField("core.defaultDocumentSyntax", "Default document syntax", 60); needsUpdate |= bclass.addBooleanField("xwiki.title.mandatory", "Make document title field mandatory", "yesno"); // for tags needsUpdate |= bclass.addBooleanField("tags", "Activate the tagging", "yesno"); // for backlinks needsUpdate |= bclass.addBooleanField("backlinks", "Activate the backlinks", "yesno"); // New fields for the XWiki 1.0 skin needsUpdate |= bclass.addTextField("leftPanels", "Panels displayed on the left", 60); needsUpdate |= bclass.addTextField("rightPanels", "Panels displayed on the right", 60); needsUpdate |= bclass.addBooleanField("showLeftPanels", "Display the left panel column", "yesno"); needsUpdate |= bclass.addBooleanField("showRightPanels", "Display the right panel column", "yesno"); needsUpdate |= bclass.addTextField("languages", "Supported languages", 30); needsUpdate |= bclass.addTextField("documentBundles", "Internationalization Document Bundles", 60); // Only used by LDAP authentication service needsUpdate |= bclass.addBooleanField("ldap", "Ldap", "yesno"); needsUpdate |= bclass.addTextField("ldap_server", "Ldap server adress", 60); needsUpdate |= bclass.addTextField("ldap_port", "Ldap server port", 60); needsUpdate |= bclass.addTextField("ldap_bind_DN", "Ldap login matching", 60); needsUpdate |= bclass.addTextField("ldap_bind_pass", "Ldap password matching", 60); needsUpdate |= bclass.addBooleanField("ldap_validate_password", "Validate Ldap user/password", "yesno"); needsUpdate |= bclass.addTextField("ldap_user_group", "Ldap group filter", 60); needsUpdate |= bclass.addTextField("ldap_exclude_group", "Ldap group to exclude", 60); needsUpdate |= bclass.addTextField("ldap_base_DN", "Ldap base DN", 60); needsUpdate |= bclass.addTextField("ldap_UID_attr", "Ldap UID attribute name", 60); needsUpdate |= bclass.addTextField("ldap_fields_mapping", "Ldap user fiels mapping", 60); needsUpdate |= bclass.addBooleanField("ldap_update_user", "Update user from LDAP", "yesno"); needsUpdate |= bclass.addTextAreaField("ldap_group_mapping", "Ldap groups mapping", 60, 5); needsUpdate |= bclass.addTextField("ldap_groupcache_expiration", "LDAP groups members cache", 60); needsUpdate |= bclass.addStaticListField("ldap_mode_group_sync", "LDAP groups sync mode", "|always|create"); needsUpdate |= bclass.addBooleanField("ldap_trylocal", "Try local login", "yesno"); if (((BooleanClass) bclass.get("showLeftPanels")).getDisplayType().equals("checkbox")) { ((BooleanClass) bclass.get("showLeftPanels")).setDisplayType("yesno"); ((BooleanClass) bclass.get("showRightPanels")).setDisplayType("yesno"); needsUpdate = true; } SheetBinder documentSheetBinder = Utils.getComponent(SheetBinder.class, "document"); boolean hasDocumentSheets = documentSheetBinder.getSheets(doc).isEmpty(); needsUpdate |= setClassDocumentFields(doc, "XWiki Preferences"); // Don't use ClassSheet to display XWikiPreferences unless explicitly set. if (!hasDocumentSheets) { DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "ClassSheet"); needsUpdate |= documentSheetBinder.unbind(doc, sheet); } // Use AdminSheet to display documents having XWikiPreferences objects if no other class sheet is specified. SheetBinder classSheetBinder = Utils.getComponent(SheetBinder.class, "class"); if (classSheetBinder.getSheets(doc).isEmpty()) { DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "AdminSheet"); needsUpdate |= classSheetBinder.bind(doc, sheet); } if (needsUpdate) { saveDocument(doc, context); } return bclass; } public BaseClass getGroupClass(XWikiContext context) throws XWikiException { XWikiDocument doc; XWikiDocument template = null; boolean needsUpdate = false; doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "XWikiGroups"), context); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } needsUpdate |= bclass.addTextField("member", "Member", 30); needsUpdate |= setClassDocumentFields(doc, "XWiki Group Class"); // Use XWikiGroupSheet to display documents having XWikiGroups objects if no other class sheet is specified. SheetBinder classSheetBinder = Utils.getComponent(SheetBinder.class, "class"); if (classSheetBinder.getSheets(doc).isEmpty()) { DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "XWikiGroupSheet"); needsUpdate |= classSheetBinder.bind(doc, sheet); } if (needsUpdate) { saveDocument(doc, context); } return bclass; } public BaseClass getRightsClass(String pagename, XWikiContext context) throws XWikiException { XWikiDocument doc; boolean needsUpdate = false; doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, pagename), context); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } PropertyInterface groupsProp = bclass.get("groups"); if ((groupsProp != null) && !(groupsProp instanceof GroupsClass)) { bclass.removeField("groups"); needsUpdate = true; } needsUpdate |= bclass.addGroupsField("groups", "Groups"); PropertyInterface levelsProp = bclass.get("levels"); if ((levelsProp != null) && !(levelsProp instanceof LevelsClass)) { bclass.removeField("levels"); needsUpdate = true; } needsUpdate |= bclass.addLevelsField("levels", "Levels"); PropertyInterface usersProp = bclass.get("users"); if ((usersProp != null) && !(usersProp instanceof UsersClass)) { bclass.removeField("users"); needsUpdate = true; } needsUpdate |= bclass.addUsersField("users", "Users"); PropertyInterface allowProp = bclass.get("allow"); if ((allowProp != null) && (allowProp instanceof NumberClass)) { bclass.removeField("allow"); needsUpdate = true; } needsUpdate |= bclass.addBooleanField("allow", "Allow/Deny", "allow"); BooleanClass afield = (BooleanClass) bclass.get("allow"); if (afield.getDefaultValue() != 1) { afield.setDefaultValue(1); needsUpdate = true; } String title; if (pagename.equals("XWikiGlobalRights")) { title = "XWiki Global Rights Class"; } else { title = "XWiki Rights Class"; } needsUpdate |= setClassDocumentFields(doc, title); if (needsUpdate) { saveDocument(doc, context); } return bclass; } public BaseClass getRightsClass(XWikiContext context) throws XWikiException { return getRightsClass("XWikiRights", context); } public BaseClass getGlobalRightsClass(XWikiContext context) throws XWikiException { return getRightsClass("XWikiGlobalRights", context); } public BaseClass getCommentsClass(XWikiContext context) throws XWikiException { XWikiDocument doc; boolean needsUpdate = false; doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "XWikiComments"), context); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } needsUpdate |= bclass.addTextField("author", "Author", 30); needsUpdate |= bclass.addTextAreaField("highlight", "Highlighted Text", 40, 2); needsUpdate |= bclass.addNumberField("replyto", "Reply To", 5, "integer"); needsUpdate |= bclass.addDateField("date", "Date"); needsUpdate |= bclass.addTextAreaField("comment", "Comment", 40, 5); needsUpdate |= setClassDocumentFields(doc, "XWiki Comment Class"); if (needsUpdate) { saveDocument(doc, context); } return bclass; } public BaseClass getSkinClass(XWikiContext context) throws XWikiException { XWikiDocument doc; boolean needsUpdate = false; doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "XWikiSkins"), context); BaseClass bclass = doc.getXClass(); if (context.get("initdone") != null) { return bclass; } needsUpdate |= bclass.addTextField("name", "Name", 30); needsUpdate |= bclass.addTextField("baseskin", "Base Skin", 30); needsUpdate |= bclass.addTextField("logo", "Logo", 30); needsUpdate |= bclass.addTemplateField("style.css", "Style"); needsUpdate |= bclass.addTemplateField("header.vm", "Header"); needsUpdate |= bclass.addTemplateField("footer.vm", "Footer"); needsUpdate |= bclass.addTemplateField("viewheader.vm", "View Header"); needsUpdate |= bclass.addTemplateField("view.vm", "View"); needsUpdate |= bclass.addTemplateField("edit.vm", "Edit"); needsUpdate |= setClassDocumentFields(doc, "XWiki Skin Class"); // Use XWikiSkinsSheet to display documents having XWikiSkins objects if no other class sheet is specified. SheetBinder classSheetBinder = Utils.getComponent(SheetBinder.class, "class"); if (classSheetBinder.getSheets(doc).isEmpty()) { DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, "XWikiSkinsSheet"); needsUpdate |= classSheetBinder.bind(doc, sheet); } if (needsUpdate) { saveDocument(doc, context); } return bclass; } public int createUser(XWikiContext context) throws XWikiException { return createUser(false, "edit", context); } public int validateUser(boolean withConfirmEmail, XWikiContext context) throws XWikiException { try { XWikiRequest request = context.getRequest(); // Get the user document String username = convertUsername(request.getParameter("xwikiname"), context); if (username.indexOf('.') == -1) { username = "XWiki." + username; } XWikiDocument userDocument = getDocument(username, context); // Get the stored validation key BaseObject userObject = userDocument.getObject("XWiki.XWikiUsers", 0); String storedKey = userObject.getStringValue("validkey"); // Get the validation key from the URL String validationKey = request.getParameter("validkey"); PropertyInterface validationKeyClass = getClass("XWiki.XWikiUsers", context).get("validkey"); if (validationKeyClass instanceof PasswordClass) { validationKey = ((PasswordClass) validationKeyClass).getEquivalentPassword(storedKey, validationKey); } // Compare the two keys if ((!storedKey.equals("") && (storedKey.equals(validationKey)))) { userObject.setIntValue("active", 1); saveDocument(userDocument, context); if (withConfirmEmail) { String email = userObject.getStringValue("email"); String password = userObject.getStringValue("password"); sendValidationEmail(username, password, email, request.getParameter("validkey"), "confirmation_email_content", context); } return 0; } else { return -1; } } catch (Exception e) { e.printStackTrace(); throw new XWikiException(XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_VALIDATE_USER, "Exception while validating user", e, null); } } public int createUser(boolean withValidation, String userRights, XWikiContext context) throws XWikiException { try { XWikiRequest request = context.getRequest(); Map<String, String[]> map = Util.getObject(request, "register"); String content; Syntax syntax; if (!getDefaultDocumentSyntax().equals(Syntax.XWIKI_1_0.toIdString())) { content = "{{include document=\"XWiki.XWikiUserSheet\"/}}"; syntax = Syntax.XWIKI_2_0; } else { content = "#includeForm(\"XWiki.XWikiUserSheet\")"; syntax = Syntax.XWIKI_1_0; } String xwikiname = request.getParameter("xwikiname"); String password2 = request.getParameter("register2_password"); String password = (map.get("password"))[0]; String email = (map.get("email"))[0]; String template = request.getParameter("template"); String parent = request.getParameter("parent"); String validkey = null; if (XWikiRightService.SUPERADMIN_USER.equalsIgnoreCase(xwikiname)) { return -8; } try { if (!context.getUtil().match(this.Param("xwiki.validusername", "/^[a-zA-Z0-9_]+$/"), xwikiname)) { return -4; } } catch (RuntimeException ex) { LOGGER.warn("Invalid regular expression for xwiki.validusername", ex); if (!context.getUtil().match("/^[a-zA-Z0-9_]+$/", xwikiname)) { return -4; } } if ((!password.equals(password2)) || (password.trim().equals(""))) { // TODO: throw wrong password exception return -2; } if ((template != null) && (!template.equals(""))) { XWikiDocument tdoc = getDocument(template, context); if ((!tdoc.isNew())) { content = tdoc.getContent(); syntax = tdoc.getSyntax(); } } if ((parent == null) || (parent.equals(""))) { parent = "XWiki.XWikiUsers"; } if (withValidation) { map.put("active", new String[] { "0" }); validkey = generateValidationKey(16); map.put("validkey", new String[] { validkey }); } else { // Mark user active map.put("active", new String[] { "1" }); } int result = createUser(xwikiname, map, this.relativeEntityReferenceResolver.resolve(parent, EntityType.DOCUMENT), content, syntax, userRights, context); if ((result > 0) && (withValidation)) { // Send the validation email sendValidationEmail(xwikiname, password, email, validkey, "validation_email_content", context); } return result; } catch (XWikiException e) { e.printStackTrace(); throw e; } catch (Exception e) { e.printStackTrace(); throw new XWikiException(XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_CREATE_USER, "Exception while creating user", e, null); } } /** * Method allows to create an empty user with no password (he won't be able to login) This method is usefull for * authentication like LDAP or App Server trusted * * @param xwikiname * @param userRights * @param context * @return true if success * @throws XWikiException */ public boolean createEmptyUser(String xwikiname, String userRights, XWikiContext context) throws XWikiException { Map<String, String> map = new HashMap<String, String>(); map.put("active", "1"); map.put("first_name", xwikiname); if (createUser(xwikiname, map, userRights, context) == 1) { return true; } else { return false; } } public void sendConfirmationEmail(String xwikiname, String password, String email, String message, String contentfield, XWikiContext context) throws XWikiException { sendValidationEmail(xwikiname, password, email, "message", message, contentfield, context); } public void sendValidationEmail(String xwikiname, String password, String email, String validkey, String contentfield, XWikiContext context) throws XWikiException { sendValidationEmail(xwikiname, password, email, "validkey", validkey, contentfield, context); } public void sendValidationEmail(String xwikiname, String password, String email, String addfieldname, String addfieldvalue, String contentfield, XWikiContext context) throws XWikiException { String sender; String content; try { sender = getXWikiPreference("admin_email", context); content = getXWikiPreference(contentfield, context); } catch (Exception e) { throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL, XWikiException.ERROR_XWIKI_EMAIL_CANNOT_GET_VALIDATION_CONFIG, "Exception while reading the validation email config", e, null); } try { VelocityContext vcontext = (VelocityContext) context.get("vcontext"); vcontext.put(addfieldname, addfieldvalue); vcontext.put("email", email); vcontext.put("password", password); vcontext.put("sender", sender); vcontext.put("xwikiname", xwikiname); content = parseContent(content, context); } catch (Exception e) { throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL, XWikiException.ERROR_XWIKI_EMAIL_CANNOT_PREPARE_VALIDATION_EMAIL, "Exception while preparing the validation email", e, null); } // Let's now send the message sendMessage(sender, email, content, context); } /** * @deprecated replaced by the <a href="http://code.xwiki.org/xwiki/bin/view/Plugins/MailSenderPlugin">Mail Sender * Plugin</a> */ @Deprecated public void sendMessage(String sender, String[] recipients, String rawMessage, XWikiContext context) throws XWikiException { LOGGER.trace("Entering sendMessage()"); // We'll be using the MailSender plugin, which has much more advanced capabilities (authentication, TLS). // Since the plugin is in another module, and it depends on the core, we have to use it through reflection in // order to avoid cyclic dependencies. This should be fixed once the mailsender becomes a clean component // instead of a plugin. Object mailSender; Class mailSenderClass; Method mailSenderSendRaw; try { mailSender = getPluginApi("mailsender", context); mailSenderClass = Class.forName("com.xpn.xwiki.plugin.mailsender.MailSenderPluginApi"); // public int sendRawMessage(String from, String to, String rawMessage) mailSenderSendRaw = mailSenderClass.getMethod("sendRawMessage", new Class[] { String.class, String.class, String.class }); } catch (Exception e) { LOGGER.error("Problem getting MailSender via Reflection. Using the old sendMessage mechanism.", e); sendMessageOld(sender, recipients, rawMessage, context); return; } if (LOGGER.isTraceEnabled()) { LOGGER.trace("Sending message = \"" + rawMessage + "\""); } String messageRecipients = StringUtils.join(recipients, ','); try { mailSenderSendRaw.invoke(mailSender, sender, messageRecipients, rawMessage); } catch (InvocationTargetException ite) { Throwable cause = ite.getCause(); if (cause instanceof XWikiException) { throw (XWikiException) cause; } else { throw new RuntimeException(cause); } } catch (Exception e) { // Probably either IllegalAccessException or IllegalArgumentException // Shouldn't happen unless there were an incompatible code change throw new RuntimeException(e); } LOGGER.info("Exiting sendMessage(). It seems everything went ok."); } /** * @deprecated replaced by the <a href="http://code.xwiki.org/xwiki/bin/view/Plugins/MailSenderPlugin">Mail Sender * Plugin</a> */ @Deprecated private void sendMessageOld(String sender, String[] recipient, String message, XWikiContext context) throws XWikiException { SMTPClient smtpc = null; try { String server = getXWikiPreference("smtp_server", context); String port = getXWikiPreference("smtp_port", context); String login = getXWikiPreference("smtp_login", context); if (context.get("debugMail") != null) { StringBuffer msg = new StringBuffer(message); msg.append("\n Recipient: "); msg.append(recipient); recipient = ((String) context.get("debugMail")).split(","); message = msg.toString(); } if ((server == null) || server.equals("")) { server = "127.0.0.1"; } if ((port == null) || (port.equals(""))) { port = "25"; } if ((login == null) || login.equals("")) { login = InetAddress.getLocalHost().getHostName(); } smtpc = new SMTPClient(); smtpc.connect(server, Integer.parseInt(port)); int reply = smtpc.getReplyCode(); if (!SMTPReply.isPositiveCompletion(reply)) { Object[] args = { server, port, Integer.valueOf(reply), smtpc.getReplyString() }; throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL, XWikiException.ERROR_XWIKI_EMAIL_CONNECT_FAILED, "Could not connect to server {0} port {1} error code {2} ({3})", null, args); } if (smtpc.login(login) == false) { reply = smtpc.getReplyCode(); Object[] args = { server, port, Integer.valueOf(reply), smtpc.getReplyString() }; throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL, XWikiException.ERROR_XWIKI_EMAIL_LOGIN_FAILED, "Could not login to mail server {0} port {1} error code {2} ({3})", null, args); } if (smtpc.sendSimpleMessage(sender, recipient, message) == false) { reply = smtpc.getReplyCode(); Object[] args = { server, port, Integer.valueOf(reply), smtpc.getReplyString() }; throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL, XWikiException.ERROR_XWIKI_EMAIL_SEND_FAILED, "Could not send mail to server {0} port {1} error code {2} ({3})", null, args); } } catch (IOException e) { Object[] args = { sender, recipient }; throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL, XWikiException.ERROR_XWIKI_EMAIL_ERROR_SENDING_EMAIL, "Exception while sending email from {0} to {1}", e, args); } finally { if ((smtpc != null) && (smtpc.isConnected())) { try { smtpc.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } } /** * @deprecated replaced by the <a href="http://code.xwiki.org/xwiki/bin/view/Plugins/MailSenderPlugin">Mail Sender * Plugin</a> */ @Deprecated public void sendMessage(String sender, String recipient, String message, XWikiContext context) throws XWikiException { String[] recip = recipient.split(","); sendMessage(sender, recip, message, context); } public String generateRandomString(int size) { return RandomStringUtils.randomAlphanumeric(size); } public String generateValidationKey(int size) { return generateRandomString(size); } /** * Create a new user. * * @param userName the name of the user (without the space) * @param map extra datas to add to user profile object * @param context the XWiki context * @return <ul> * <li>1: ok</li> * <li>-3: user already exists</li> * </ul> * @throws XWikiException failed to create the new user */ public int createUser(String userName, Map<String, ?> map, XWikiContext context) throws XWikiException { return createUser(userName, map, "edit", context); } /** * Create a new user. * * @param userName the name of the user (without the space) * @param map extra datas to add to user profile object * @param userRights the right of the user on his own profile page * @param context the XWiki context * @return <ul> * <li>1: ok</li> * <li>-3: user already exists</li> * </ul> * @throws XWikiException failed to create the new user */ public int createUser(String userName, Map<String, ?> map, String userRights, XWikiContext context) throws XWikiException { BaseClass userClass = context.getWiki().getUserClass(context); String content; Syntax syntax; if (!context.getWiki().getDefaultDocumentSyntax().equals(Syntax.XWIKI_1_0.toIdString())) { content = "{{include document=\"XWiki.XWikiUserSheet\"/}}"; syntax = Syntax.XWIKI_2_0; } else { content = "#includeForm(\"XWiki.XWikiUserSheet\")"; syntax = Syntax.XWIKI_1_0; } return createUser(userName, map, new EntityReference(userClass.getDocumentReference().getName(), EntityType.DOCUMENT), content, syntax, userRights, context); } /** * @deprecated since 2.4RC1 use * {@link #createUser(String, Map, EntityReference, String, Syntax, String, XWikiContext)} instead */ @Deprecated public int createUser(String userName, Map<String, ?> map, String parent, String content, String syntaxId, String userRights, XWikiContext context) throws XWikiException { Syntax syntax; try { syntax = this.syntaxFactory.createSyntaxFromIdString(syntaxId); } catch (ParseException e) { try { syntax = this.syntaxFactory.createSyntaxFromIdString(getDefaultDocumentSyntax()); } catch (ParseException e1) { // Let's jope that never happen LOGGER.warn("Failed to set parse syntax [" + getDefaultDocumentSyntax() + "]", e); syntax = Syntax.XWIKI_2_0; } } return createUser(userName, map, this.relativeEntityReferenceResolver.resolve(parent, EntityType.DOCUMENT), content, syntax, userRights, context); } /** * Create a new user. * * @param userName the name of the user (without the space) * @param map extra datas to add to user profile object * @param parentReference the parent of the user profile * @param content the content of the user profile * @param syntax the syntax of the provided content * @param userRights the right of the user on his own profile page * @param context the XWiki context * @return <ul> * <li>1: ok</li> * <li>-3: user already exists</li> * </ul> * @throws XWikiException failed to create the new user */ public int createUser(String userName, Map<String, ?> map, EntityReference parentReference, String content, Syntax syntax, String userRights, XWikiContext context) throws XWikiException { BaseClass baseclass = getUserClass(context); try { // TODO: Verify existing user XWikiDocument doc = getDocument(new DocumentReference(context.getDatabase(), "XWiki", userName), context); if (!doc.isNew()) { // TODO: throws Exception return -3; } BaseObject userObject = doc.newXObject( this.localReferenceEntityReferenceSerializer.serialize(baseclass.getDocumentReference()), context); baseclass.fromMap(map, userObject); doc.setParentReference(parentReference); doc.setContent(content); doc.setSyntax(syntax); doc.setCreatorReference(doc.getDocumentReference()); doc.setAuthorReference(doc.getDocumentReference()); protectUserPage(doc.getFullName(), userRights, doc, context); saveDocument(doc, context.getMessageTool().get("core.comment.createdUser"), context); // Now let's add the user to XWiki.XWikiAllGroup setUserDefaultGroup(doc.getFullName(), context); return 1; } catch (Exception e) { Object[] args = { "XWiki." + userName }; throw new XWikiException(XWikiException.MODULE_XWIKI_USER, XWikiException.ERROR_XWIKI_USER_CREATE, "Cannot create user {0}", e, args); } } /** * @deprecated starting with XE 1.8.1 use * {@link #createUser(String, Map, String, String, String, String, XWikiContext)} instead */ @Deprecated public int createUser(String xwikiname, Map map, String parent, String content, String userRights, XWikiContext context) throws XWikiException { return createUser(xwikiname, map, parent, content, Syntax.XWIKI_1_0.toIdString(), userRights, context); } public void setUserDefaultGroup(String fullwikiname, XWikiContext context) throws XWikiException { String groupsPreference = Param("xwiki.users.initialGroups", "XWiki.XWikiAllGroup"); if (groupsPreference != null) { String[] groups = groupsPreference.split(","); for (String groupName : groups) { if (StringUtils.isNotBlank(groupName)) { addUserToGroup(fullwikiname, groupName.trim(), context); } } } } protected void addUserToGroup(String userName, String groupName, XWikiContext context) throws XWikiException { BaseClass groupClass = getGroupClass(context); XWikiDocument groupDoc = getDocument(groupName, context); BaseObject memberObject = groupDoc.newXObject( this.localReferenceEntityReferenceSerializer.serialize(groupClass.getDocumentReference()), context); memberObject.setStringValue("member", userName); if (groupDoc.isNew()) { saveDocument(groupDoc, context.getMessageTool().get("core.comment.addedUserToGroup"), context); } else { // TODO Fix use of deprecated call. getHibernateStore().saveXWikiObject(memberObject, context, true); } try { XWikiGroupService gservice = getGroupService(context); gservice.addUserToGroup(userName, context.getDatabase(), groupName, context); } catch (Exception e) { LOGGER.error("Failed to update group service cache", e); } } /** * @deprecated replaced by {@link #setUserDefaultGroup(String fullwikiname, XWikiContext context)} * @param context * @param fullwikiname * @throws XWikiException */ @Deprecated public void SetUserDefaultGroup(XWikiContext context, String fullwikiname) throws XWikiException { setUserDefaultGroup(fullwikiname, context); } public void protectUserPage(String userName, String userRights, XWikiDocument doc, XWikiContext context) throws XWikiException { BaseClass rclass = getRightsClass(context); EntityReference rightClassReference = this.localReferenceEntityReferenceSerializer .serialize(rclass.getDocumentReference()); // Add protection to the page BaseObject newrightsobject = doc.newXObject(rightClassReference, context); newrightsobject.setLargeStringValue("groups", "XWiki.XWikiAdminGroup"); newrightsobject.setStringValue("levels", userRights); newrightsobject.setIntValue("allow", 1); BaseObject newuserrightsobject = doc.newXObject(rightClassReference, context); newuserrightsobject.setLargeStringValue("users", userName); newuserrightsobject.setStringValue("levels", userRights); newuserrightsobject.setIntValue("allow", 1); } /** * @deprecated replaced by {@link #protectUserPage(String,String,XWikiDocument,XWikiContext)} * @param context * @param fullwikiname * @param userRights * @param doc * @throws XWikiException */ @Deprecated public void ProtectUserPage(XWikiContext context, String fullwikiname, String userRights, XWikiDocument doc) throws XWikiException { protectUserPage(fullwikiname, userRights, doc, context); } public User getUser(XWikiContext context) { XWikiUser xwikiUser = context.getXWikiUser(); User user = new User(xwikiUser, context); return user; } public User getUser(String username, XWikiContext context) { XWikiUser xwikiUser = new XWikiUser(username); User user = new User(xwikiUser, context); return user; } /** * Prepares the localized resources, according to the selected language. From any point in the code (java, velocity * or groovy) the "msg" parameter holds an instance of the localized resource bundle, and the "locale" parameter * holds the current locale settings. * * @param context The request context. */ public void prepareResources(XWikiContext context) { if (context.get("msg") == null) { // String ilanguage = getInterfaceLanguagePreference(context); String dlanguage = getLanguagePreference(context); Locale locale = new Locale(dlanguage); context.put("locale", locale); if (context.getResponse() != null) { context.getResponse().setLocale(locale); } ResourceBundle bundle = ResourceBundle.getBundle("ApplicationResources", locale); if (bundle == null) { bundle = ResourceBundle.getBundle("ApplicationResources"); } XWikiMessageTool msg = new XWikiMessageTool(bundle, context); context.put("msg", msg); VelocityContext vcontext = ((VelocityContext) context.get("vcontext")); if (vcontext != null) { vcontext.put("msg", msg); vcontext.put("locale", locale); } @SuppressWarnings("unchecked") Map<String, Object> gcontext = (Map<String, Object>) context.get("gcontext"); if (gcontext != null) { gcontext.put("msg", msg); gcontext.put("locale", locale); } } } public XWikiUser checkAuth(XWikiContext context) throws XWikiException { return getAuthService().checkAuth(context); } public boolean checkAccess(String action, XWikiDocument doc, XWikiContext context) throws XWikiException { if (action.equals("skin") && (doc.getSpace().equals("skins") || doc.getSpace().equals("resources"))) { // We still need to call checkAuth to set the proper user. XWikiUser user = checkAuth(context); if (user != null) { context.setUser(user.getUser()); } return true; } return getRightService().checkAccess(action, doc, context); } /** * @deprecated replaced by {@link #include(String topic, boolean isForm, XWikiContext context)} * @param topic * @param context * @param isForm * @return * @throws XWikiException */ @Deprecated public String include(String topic, XWikiContext context, boolean isForm) throws XWikiException { return include(topic, isForm, context); } public String include(String topic, boolean isForm, XWikiContext context) throws XWikiException { String database = null, incdatabase = null; String prefixedTopic, localTopic; // Save current documents in the Velocity and Groovy contexts Document currentdoc = null, currentcdoc = null, currenttdoc = null; Document gcurrentdoc = null, gcurrentcdoc = null, gcurrenttdoc = null; VelocityContext vcontext = (VelocityContext) context.get("vcontext"); String currentDocName = context.getDatabase() + ":" + context.getDoc().getFullName(); if (vcontext != null) { currentdoc = (Document) vcontext.get("doc"); currentcdoc = (Document) vcontext.get("cdoc"); currenttdoc = (Document) vcontext.get("tdoc"); } @SuppressWarnings("unchecked") Map<String, Object> gcontext = (Map<String, Object>) context.get("gcontext"); if (gcontext != null) { gcurrentdoc = (Document) gcontext.get("doc"); gcurrentcdoc = (Document) gcontext.get("cdoc"); gcurrenttdoc = (Document) gcontext.get("tdoc"); } try { int i0 = topic.indexOf(':'); if (i0 != -1) { incdatabase = topic.substring(0, i0); database = context.getDatabase(); context.setDatabase(incdatabase); prefixedTopic = topic; localTopic = topic.substring(i0 + 1); } else { prefixedTopic = context.getDatabase() + ":" + topic; localTopic = topic; } XWikiDocument doc = null; try { LOGGER.debug("Including Topic " + topic); try { @SuppressWarnings("unchecked") Set<String> includedDocs = (Set<String>) context.get("included_docs"); if (includedDocs == null) { includedDocs = new HashSet<String>(); context.put("included_docs", includedDocs); } if (includedDocs.contains(prefixedTopic) || currentDocName.equals(prefixedTopic)) { LOGGER.warn("Error on too many recursive includes for topic " + topic); return "Cannot make recursive include"; } includedDocs.add(prefixedTopic); } catch (Exception e) { } // Get document to include doc = getDocument(((XWikiDocument) context.get("doc")).getSpace(), localTopic, context); if (checkAccess("view", doc, context) == false) { throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access to this document is denied: " + doc); } } catch (XWikiException e) { LOGGER.warn("Exception Including Topic " + topic, e); return "Topic " + topic + " does not exist"; } XWikiDocument contentdoc = doc.getTranslatedDocument(context); String result; if (isForm) { // We do everything in the context of the including document if (database != null) { context.setDatabase(database); } // Allow including document in the XWiki Syntax 1.0 but also other syntaxes using the new rendering. if (contentdoc.getSyntax().equals(Syntax.XWIKI_1_0)) { result = getRenderingEngine().renderText(contentdoc.getContent(), contentdoc, (XWikiDocument) context.get("doc"), context); } else { // Note: the Script macro in the new rendering checks for programming rights for the document in // the xwiki context. result = getRenderedContent(contentdoc, (XWikiDocument) context.get("doc"), context); } } else { // We stay in the included document context // Allow including document in the XWiki Syntax 1.0 but also other syntaxes using the new rendering. if (contentdoc.getSyntax().equals(Syntax.XWIKI_1_0)) { result = getRenderingEngine().renderText(contentdoc.getContent(), contentdoc, doc, context); } else { // Since the Script macro checks for programming rights in the current document, we need to // temporarily set the contentdoc as the current doc before rendering it. XWikiDocument originalDoc = null; try { originalDoc = context.getDoc(); context.put("doc", doc); result = getRenderedContent(contentdoc, doc, context); } finally { context.put("doc", originalDoc); } } } try { @SuppressWarnings("unchecked") Set<String> includedDocs = (Set<String>) context.get("included_docs"); if (includedDocs != null) { includedDocs.remove(prefixedTopic); } } catch (Exception e) { } return result; } finally { if (database != null) { context.setDatabase(database); } if (currentdoc != null) { if (vcontext != null) { vcontext.put("doc", currentdoc); } } if (gcurrentdoc != null) { if (gcontext != null) { gcontext.put("doc", gcurrentdoc); } } if (currentcdoc != null) { if (vcontext != null) { vcontext.put("cdoc", currentcdoc); } } if (gcurrentcdoc != null) { if (gcontext != null) { gcontext.put("cdoc", gcurrentcdoc); } } if (currenttdoc != null) { if (vcontext != null) { vcontext.put("tdoc", currenttdoc); } } if (gcurrenttdoc != null) { if (gcontext != null) { gcontext.put("tdoc", gcurrenttdoc); } } } } /** * Render content from the passed included document, setting the correct security doc (sdoc) and including doc * (idoc). Note that this is needed for 2.0 syntax only since in 1.0 syntax the idoc and sdoc are set by * {@link com.xpn.xwiki.render.XWikiRenderingEngine#renderText}. * * @since 2.2M2 */ private String getRenderedContent(XWikiDocument includedDoc, XWikiDocument includingDoc, XWikiContext context) throws XWikiException { String result; XWikiDocument idoc = (XWikiDocument) context.get("idoc"); XWikiDocument sdoc = (XWikiDocument) context.get("sdoc"); context.put("idoc", includingDoc); context.put("sdoc", includedDoc); try { result = includedDoc.getRenderedContent(Syntax.XHTML_1_0, false, context); } finally { // Remove including doc or set the previous one if (idoc == null) { context.remove("idoc"); } else { context.put("idoc", idoc); } // Remove security doc or set the previous one if (sdoc == null) { context.remove("sdoc"); } else { context.put("sdoc", sdoc); } } return result; } public void deleteDocument(XWikiDocument doc, XWikiContext context) throws XWikiException { deleteDocument(doc, true, context); } public void deleteDocument(XWikiDocument doc, boolean totrash, XWikiContext context) throws XWikiException { ObservationManager om = Utils.getComponent(ObservationManager.class); // Inform notification mechanisms that a document is about to be deleted // Note that for the moment the event being send is a bridge event, as we are still passing around // an XWikiDocument as source and an XWikiContext as data. om.notify(new DocumentDeletingEvent(doc.getDocumentReference()), new XWikiDocument(doc.getDocumentReference()), context); if (hasRecycleBin(context) && totrash) { getRecycleBinStore().saveToRecycleBin(doc, context.getUser(), new Date(), context, true); } getStore().deleteXWikiDoc(doc, context); try { // Inform notification mecanisms that a document has been deleted // Note that for the moment the event being send is a bridge event, as we are still passing around // an XWikiDocument as source and an XWikiContext as data. // The source document is a new empty XWikiDocument to follow // DocumentUpdatedEvent policy: source document in new document and the old version is available using // doc.getOriginalDocument() if (om != null) { XWikiDocument blankDoc = new XWikiDocument(doc.getDocumentReference()); // Again to follow general event policy, new document author is the user who modified the document (here // the modification is delete) blankDoc.setOriginalDocument(doc); blankDoc.setAuthor(context.getUser()); blankDoc.setContentAuthor(context.getUser()); om.notify(new DocumentDeletedEvent(doc.getDocumentReference()), blankDoc, context); } } catch (Exception ex) { LOGGER.error( "Failed to send document delete notifications for document [" + doc.getPrefixedFullName() + "]", ex); } } public String getDatabase() { return this.database; } public void setDatabase(String database) { this.database = database; } public void gc() { System.gc(); } public long freeMemory() { return Runtime.getRuntime().freeMemory(); } public long totalMemory() { return Runtime.getRuntime().totalMemory(); } public long maxMemory() { return Runtime.getRuntime().maxMemory(); } public String[] split(String str, String sep) { return StringUtils.split(str, sep); } public String printStrackTrace(Throwable e) { StringWriter strwriter = new StringWriter(); PrintWriter writer = new PrintWriter(strwriter); e.printStackTrace(writer); return strwriter.toString(); } /** * @since 2.2M2 */ public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference, XWikiContext context) throws XWikiException { return copyDocument(sourceDocumentReference, targetDocumentReference, null, true, context); } /** * @since 2.2M2 */ public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference, boolean reset, XWikiContext context) throws XWikiException { return copyDocument(sourceDocumentReference, targetDocumentReference, null, reset, context); } /** * @since 2.2M2 */ public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference, boolean reset, boolean force, boolean resetCreationData, XWikiContext context) throws XWikiException { return copyDocument(sourceDocumentReference, targetDocumentReference, null, reset, force, resetCreationData, context); } /** * @since 2.2M2 */ public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference, String wikilanguage, XWikiContext context) throws XWikiException { return copyDocument(sourceDocumentReference, targetDocumentReference, wikilanguage, true, context); } /** * @since 2.2M2 */ public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference, String wikilanguage, boolean reset, XWikiContext context) throws XWikiException { return copyDocument(sourceDocumentReference, targetDocumentReference, wikilanguage, reset, false, context); } /** * @since 2.2M2 */ public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference, String wikilanguage, boolean reset, boolean force, XWikiContext context) throws XWikiException { return copyDocument(sourceDocumentReference, targetDocumentReference, wikilanguage, reset, force, false, context); } /** * @since 2.2M2 */ public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference, String wikilanguage, boolean reset, boolean force, boolean resetCreationData, XWikiContext context) throws XWikiException { String db = context.getDatabase(); String sourceWiki = sourceDocumentReference.getWikiReference().getName(); String targetWiki = targetDocumentReference.getWikiReference().getName(); String sourceStringReference = this.defaultEntityReferenceSerializer.serialize(sourceDocumentReference); try { context.setDatabase(sourceWiki); XWikiDocument sdoc = getDocument(sourceDocumentReference, context); if (!sdoc.isNew()) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Copying document [" + sourceDocumentReference + "] to [" + targetDocumentReference + "]"); } // Let's switch to the other database to verify if the document already exists context.setDatabase(targetWiki); XWikiDocument tdoc = getDocument(targetDocumentReference, context); // There is already an existing document if (!tdoc.isNew()) { if (force) { // We need to delete the previous document deleteDocument(tdoc, context); } else { return false; } } // Let's switch back again to the original db context.setDatabase(sourceWiki); if (wikilanguage == null) { tdoc = sdoc.copyDocument(targetDocumentReference, context); // forget past versions if (reset) { tdoc.setNew(true); tdoc.setVersion("1.1"); } if (resetCreationData) { Date now = new Date(); tdoc.setCreationDate(now); tdoc.setContentUpdateDate(now); tdoc.setDate(now); tdoc.setCreator(context.getUser()); tdoc.setAuthor(context.getUser()); } // We don't want to trigger a new version otherwise the version number will be wrong tdoc.setMetaDataDirty(false); tdoc.setContentDirty(false); saveDocument(tdoc, "Copied from " + sourceStringReference, context); if (!reset) { context.setDatabase(sourceWiki); XWikiDocumentArchive txda = getVersioningStore().getXWikiDocumentArchive(sdoc, context); context.setDatabase(targetWiki); txda = txda.clone(tdoc.getId(), context); getVersioningStore().saveXWikiDocArchive(txda, true, context); } else { getVersioningStore().resetRCSArchive(tdoc, true, context); } context.setDatabase(targetWiki); for (XWikiAttachment attachment : tdoc.getAttachmentList()) { getAttachmentStore().saveAttachmentContent(attachment, false, context, true); } // Now we need to copy the translations context.setDatabase(sourceWiki); List<String> tlist = sdoc.getTranslationList(context); for (String clanguage : tlist) { XWikiDocument stdoc = sdoc.getTranslatedDocument(clanguage, context); if (LOGGER.isInfoEnabled()) { LOGGER.info("Copying document [" + sourceWiki + "], language [" + clanguage + "] to [" + targetDocumentReference + "]"); } context.setDatabase(targetWiki); XWikiDocument ttdoc = tdoc.getTranslatedDocument(clanguage, context); // There is already an existing document if (ttdoc != tdoc) { return false; } // Let's switch back again to the original db context.setDatabase(sourceWiki); ttdoc = stdoc.copyDocument(targetDocumentReference, context); // forget past versions if (reset) { ttdoc.setNew(true); ttdoc.setVersion("1.1"); } if (resetCreationData) { Date now = new Date(); ttdoc.setCreationDate(now); ttdoc.setContentUpdateDate(now); ttdoc.setDate(now); ttdoc.setCreator(context.getUser()); ttdoc.setAuthor(context.getUser()); } // we don't want to trigger a new version // otherwise the version number will be wrong tdoc.setMetaDataDirty(false); tdoc.setContentDirty(false); saveDocument(ttdoc, "Copied from " + sourceStringReference, context); if (!reset) { context.setDatabase(sourceWiki); XWikiDocumentArchive txda = getVersioningStore().getXWikiDocumentArchive(sdoc, context); context.setDatabase(targetWiki); txda = txda.clone(tdoc.getId(), context); getVersioningStore().saveXWikiDocArchive(txda, true, context); } else { getVersioningStore().resetRCSArchive(tdoc, true, context); } } } else { // We want only one language in the end XWikiDocument stdoc = sdoc.getTranslatedDocument(wikilanguage, context); tdoc = stdoc.copyDocument(targetDocumentReference, context); // forget language tdoc.setDefaultLanguage(wikilanguage); tdoc.setLanguage(""); // forget past versions if (reset) { tdoc.setNew(true); tdoc.setVersion("1.1"); } if (resetCreationData) { Date now = new Date(); tdoc.setCreationDate(now); tdoc.setContentUpdateDate(now); tdoc.setDate(now); tdoc.setCreator(context.getUser()); tdoc.setAuthor(context.getUser()); } // we don't want to trigger a new version // otherwise the version number will be wrong tdoc.setMetaDataDirty(false); tdoc.setContentDirty(false); saveDocument(tdoc, "Copied from " + sourceStringReference, context); if (!reset) { context.setDatabase(sourceWiki); XWikiDocumentArchive txda = getVersioningStore().getXWikiDocumentArchive(sdoc, context); context.setDatabase(targetWiki); txda = txda.clone(tdoc.getId(), context); getVersioningStore().saveXWikiDocArchive(txda, true, context); } else { getVersioningStore().resetRCSArchive(tdoc, true, context); } context.setDatabase(targetWiki); for (XWikiAttachment attachment : tdoc.getAttachmentList()) { getAttachmentStore().saveAttachmentContent(attachment, false, context, true); } } } return true; } finally { context.setDatabase(db); } } public int copySpaceBetweenWikis(String space, String sourceWiki, String targetWiki, String language, XWikiContext context) throws XWikiException { return copySpaceBetweenWikis(space, sourceWiki, targetWiki, language, false, context); } public int copySpaceBetweenWikis(String space, String sourceWiki, String targetWiki, String language, boolean clean, XWikiContext context) throws XWikiException { String db = context.getDatabase(); int nb = 0; // Workaround for XWIKI-3915: Do not use XWikiStoreInterface#searchDocumentNames since currently it has the // side effect of hidding hidden documents and no other workaround exists than directly using // XWikiStoreInterface#search directly String sql = "select distinct doc.fullName from XWikiDocument as doc"; List<String> parameters = new ArrayList<String>(); if (space != null) { sql += " where doc.space = ?"; parameters.add(space); } if (clean) { try { context.setDatabase(targetWiki); List<String> list = getStore().search(sql, 0, 0, parameters, context); if (LOGGER.isInfoEnabled()) { LOGGER.info("Deleting " + list.size() + " documents from wiki " + targetWiki); } for (String docname : list) { XWikiDocument doc = getDocument(docname, context); deleteDocument(doc, context); } } finally { context.setDatabase(db); } } try { context.setDatabase(sourceWiki); List<String> list = getStore().search(sql, 0, 0, context); if (LOGGER.isInfoEnabled()) { LOGGER.info( "Copying " + list.size() + " documents from wiki " + sourceWiki + " to wiki " + targetWiki); } WikiReference sourceWikiReference = new WikiReference(sourceWiki); WikiReference targetWikiReference = new WikiReference(targetWiki); for (String docname : list) { DocumentReference sourceDocumentReference = this.currentMixedDocumentReferenceResolver .resolve(docname); sourceDocumentReference.setWikiReference(sourceWikiReference); DocumentReference targetDocumentReference = new DocumentReference(sourceDocumentReference.clone()); targetDocumentReference.setWikiReference(targetWikiReference); copyDocument(sourceDocumentReference, targetDocumentReference, language, context); nb++; } return nb; } finally { context.setDatabase(db); } } /** * Copy an entire wiki to a target wiki. * <p> * It does not override document already existing in target wiki. * * @param sourceWiki the source wiki identifier * @param targetWiki the target wiki identifier * @param language the language to copy * @param context the XWiki context * @return the number of copied documents * @throws XWikiException failed to copy wiki */ public int copyWiki(String sourceWiki, String targetWiki, String language, XWikiContext context) throws XWikiException { return copyWiki(sourceWiki, targetWiki, language, false, context); } /** * Copy an entire wiki to a target wiki. * * @param sourceWiki the source wiki identifier * @param targetWiki the target wiki identifier * @param language the language to copy * @param clean clean the target wiki before copying * @param context the XWiki context * @return the number of copied documents * @throws XWikiException failed to copy wiki */ public int copyWiki(String sourceWiki, String targetWiki, String language, boolean clean, XWikiContext context) throws XWikiException { return copySpaceBetweenWikis(null, sourceWiki, targetWiki, language, clean, context); } /** * @deprecated use WikiManager plugin instead */ @Deprecated public int createNewWiki(String wikiName, String wikiUrl, String wikiAdmin, String baseWikiName, String description, String wikilanguage, boolean failOnExist, XWikiContext context) throws XWikiException { String database = context.getDatabase(); wikiName = wikiName.toLowerCase(); try { XWikiDocument userdoc = getDocument(wikiAdmin, context); // User does not exist if (userdoc.isNew()) { if (LOGGER.isErrorEnabled()) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "user does not exist"); } return -2; } // User is not active if (!(userdoc.getIntValue("XWiki.XWikiUsers", "active") == 1)) { if (LOGGER.isErrorEnabled()) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "user is not active"); } return -3; } String wikiForbiddenList = Param("xwiki.virtual.reserved_wikis"); if (Util.contains(wikiName, wikiForbiddenList, ", ")) { if (LOGGER.isErrorEnabled()) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki name is forbidden"); } return -4; } String wikiServerPage = "XWikiServer" + wikiName.substring(0, 1).toUpperCase() + wikiName.substring(1); // Verify is server page already exist XWikiDocument serverdoc = getDocument(SYSTEM_SPACE, wikiServerPage, context); if (serverdoc.isNew()) { // clear entry in virtual wiki cache this.virtualWikiMap.remove(wikiUrl); // Create Wiki Server page serverdoc.setStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, "server", wikiUrl); serverdoc.setStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, "owner", wikiAdmin); if (description != null) { serverdoc.setLargeStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, "description", description); } if (wikilanguage != null) { serverdoc.setStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, "language", wikilanguage); } if (!getDefaultDocumentSyntax().equals(Syntax.XWIKI_1_0.toIdString())) { serverdoc.setContent("{{include document=\"XWiki.XWikiServerForm\"/}}\n"); serverdoc.setSyntax(Syntax.XWIKI_2_0); } else { serverdoc.setContent("#includeForm(\"XWiki.XWikiServerForm\")\n"); serverdoc.setSyntax(Syntax.XWIKI_1_0); } serverdoc.setParentReference(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE); saveDocument(serverdoc, context); } else { // If we are not allowed to continue if server page already exists if (failOnExist) { if (LOGGER.isErrorEnabled()) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki server page already exists"); } return -5; } else if (LOGGER.isWarnEnabled()) { LOGGER.warn("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki server page already exists"); } } // Create wiki database try { context.setDatabase(getDatabase()); getStore().createWiki(wikiName, context); } catch (XWikiException e) { if (LOGGER.isErrorEnabled()) { if (e.getCode() == 10010) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki database already exists"); } else if (e.getCode() == 10011) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki database creation failed"); } else { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki database creation threw exception", e); } } } catch (Exception e) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki database creation threw exception", e); } try { updateDatabase(wikiName, true, false, context); } catch (Exception e) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki database shema update threw exception", e); return -6; } // Copy base wiki int nb = copyWiki(baseWikiName, wikiName, wikilanguage, context); // Save the number of docs copied in the context context.put("nbdocs", Integer.valueOf(nb)); // Create user page in his wiki // Let's not create it anymore.. this makes the creator loose // super admin rights on his wiki // copyDocument(wikiAdmin, getDatabase(), wikiName, wikilanguage, context); // Modify rights in user wiki context.setDatabase(wikiName); /* * XWikiDocument wikiprefdoc = getDocument("XWiki.XWikiPreferences", context); * wikiprefdoc.setStringValue("XWiki.XWikiGlobalRights", "users", wikiAdmin); * wikiprefdoc.setStringValue("XWiki.XWikiGlobalRights", "levels", "admin, edit"); * wikiprefdoc.setIntValue("XWiki.XWikiGlobalRights", "allow", 1); saveDocument(wikiprefdoc, context); */ return 1; } catch (Exception e) { LOGGER.error("Wiki creation (" + wikiName + "," + wikiUrl + "," + wikiAdmin + ") failed: " + "wiki creation threw exception", e); return -10; } finally { context.setDatabase(database); } } public String getEncoding() { return Param("xwiki.encoding", "UTF-8"); } public URL getServerURL(String database, XWikiContext context) throws MalformedURLException { String serverurl = null; // In virtual wiki path mode the server is the standard one if ("1".equals(Param("xwiki.virtual.usepath", "0"))) { return null; } if (database != null) { String db = context.getDatabase(); try { context.setDatabase(getDatabase()); XWikiDocument doc = getDocument("XWiki.XWikiServer" + StringUtils.capitalize(database), context); BaseObject serverobject = doc.getXObject(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE); if (serverobject != null) { String server = serverobject.getStringValue("server"); if (server != null) { String protocol = context.getWiki().Param("xwiki.url.protocol", null); if (protocol == null) { int iSecure = serverobject.getIntValue("secure", -1); // Check the request object if the "secure" property is undefined. boolean secure = iSecure == 1 || (iSecure < 0 && context.getRequest().isSecure()); protocol = secure ? "https" : "http"; } long port = context.getURL().getPort(); if (port == 80 || port == 443) { port = -1; } if (port != -1) { serverurl = protocol + "://" + server + ":" + port + "/"; } else { serverurl = protocol + "://" + server + "/"; } } } } catch (Exception ex) { } finally { context.setDatabase(db); } } if (serverurl != null) { return new URL(serverurl); } else { return null; } } public String getServletPath(String wikiName, XWikiContext context) { // unless we are in virtual wiki path mode we should return null if (!context.getMainXWiki().equalsIgnoreCase(wikiName) && "1".equals(Param("xwiki.virtual.usepath", "0"))) { String database = context.getDatabase(); try { context.setDatabase(context.getMainXWiki()); XWikiDocument doc = getDocument(getServerWikiPage(wikiName), context); BaseObject serverobject = doc.getXObject(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE); if (serverobject != null) { String server = serverobject.getStringValue("server"); return "wiki/" + server + "/"; } } catch (Exception e) { LOGGER.error("Failed to get URL for provided wiki [" + wikiName + "]", e); } finally { context.setDatabase(database); } } String servletPath = Param("xwiki.servletpath", ""); if (context.getRequest() != null) { if (StringUtils.isEmpty(servletPath)) { String currentServletpath = context.getRequest().getServletPath(); if (currentServletpath != null && currentServletpath.startsWith("/bin")) { servletPath = "bin/"; } else { servletPath = Param("xwiki.defaultservletpath", "bin/"); } } } return servletPath; } public String getWebAppPath(XWikiContext context) { String path = context.getURL().getPath(); String contextPath = Param("xwiki.webapppath", ""); if (contextPath.equals("")) { try { contextPath = context.getRequest().getContextPath(); // TODO We're using URL parts in a wrong way, since contextPath and servletPath are // returned with a leading /, while we need a trailing /. This code moves the / from // the beginning to the end. // If the app is deployed as the ROOT ap, then there's no need to move the /. if (contextPath.length() > 0) { contextPath = contextPath.substring(1) + "/"; } } catch (Exception e) { contextPath = path.substring(0, path.indexOf('/', 1) + 1); } } return contextPath; } /** * @since 2.2.1 */ public String getURL(DocumentReference documentReference, String action, String queryString, String anchor, XWikiContext context) { XWikiDocument doc = new XWikiDocument(documentReference); URL url = context.getURLFactory().createURL(doc.getSpace(), doc.getName(), action, queryString, anchor, doc.getDatabase(), context); return context.getURLFactory().getURL(url, context); } /** * @deprecated since 2.2.1 use {@link #getURL(DocumentReference, String, String, String, XWikiContext)} */ @Deprecated public String getURL(String fullname, String action, String queryString, String anchor, XWikiContext context) { XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname)); URL url = context.getURLFactory().createURL(doc.getSpace(), doc.getName(), action, queryString, anchor, doc.getDatabase(), context); return context.getURLFactory().getURL(url, context); } public String getURL(String fullname, String action, String querystring, XWikiContext context) { return getURL(fullname, action, querystring, null, context); } /** * @since 2.3M2 */ public String getURL(DocumentReference reference, String action, XWikiContext context) { return getURL(reference, action, null, null, context); } /** * @deprecated since 2.3M2 use {@link #getURL(DocumentReference, String, XWikiContext)} */ @Deprecated public String getURL(String fullname, String action, XWikiContext context) { return getURL(fullname, action, null, null, context); } public String getExternalURL(String fullname, String action, XWikiContext context) throws XWikiException { XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname)); URL url = context.getURLFactory().createExternalURL(doc.getSpace(), doc.getName(), action, null, null, doc.getDatabase(), context); return url.toString(); } public String getExternalURL(String fullname, String action, String querystring, XWikiContext context) throws XWikiException { XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname)); URL url = context.getURLFactory().createExternalURL(doc.getSpace(), doc.getName(), action, querystring, null, doc.getDatabase(), context); return url.toString(); } public String getAttachmentURL(String fullname, String filename, XWikiContext context) throws XWikiException { return getAttachmentURL(fullname, filename, null, context); } /** * @since 2.5RC1 */ public String getAttachmentURL(String fullname, String filename, String queryString, XWikiContext context) throws XWikiException { XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname)); return doc.getAttachmentURL(filename, "download", queryString, context); } // Usefull date functions public Date getCurrentDate() { return new Date(); } public int getTimeDelta(long time) { Date ctime = new Date(); return (int) (ctime.getTime() - time); } public Date getDate(long time) { return new Date(time); } public boolean isMultiLingual(XWikiContext context) { return "1".equals(getXWikiPreference("multilingual", "1", context)); } /** * @return true for multi-wiki/false for mono-wiki */ public boolean isVirtualMode() { return "1".equals(Param("xwiki.virtual")); } public boolean isLDAP() { return "1".equals(Param("xwiki.authentication.ldap")); } public int checkActive(XWikiContext context) throws XWikiException { return checkActive(context.getUser(), context); } public int checkActive(String user, XWikiContext context) throws XWikiException { int active = 1; // These users are necessarily active if (user.equals(XWikiRightService.GUEST_USER_FULLNAME) || (user.equals(XWikiRightService.SUPERADMIN_USER_FULLNAME))) { return active; } String checkactivefield = getXWikiPreference("auth_active_check", context); if (checkactivefield.equals("1")) { XWikiDocument userdoc = getDocument(user, context); active = userdoc.getIntValue("XWiki.XWikiUsers", "active"); } return active; } /** * @since 2.3M1 */ public DocumentReference getDocumentReference(XWikiRequest request, XWikiContext context) { DocumentReference reference; if (context.getMode() == XWikiContext.MODE_PORTLET) { if (request.getParameter("topic") != null) { reference = this.currentMixedDocumentReferenceResolver.resolve(request.getParameter("topic")); } else { // Point to this wiki's home page reference = new DocumentReference(context.getDatabase(), this.defaultEntityReferenceValueProvider.getDefaultValue(EntityType.SPACE), this.defaultEntityReferenceValueProvider.getDefaultValue(EntityType.DOCUMENT)); } } else if (context.getMode() == XWikiContext.MODE_XMLRPC) { reference = new DocumentReference(context.getDatabase(), context.getDoc().getDocumentReference().getLastSpaceReference().getName(), context.getDoc().getDocumentReference().getName()); } else { String action = context.getAction(); if ((request.getParameter("topic") != null) && (action.equals("edit") || action.equals("inline"))) { reference = this.currentMixedDocumentReferenceResolver.resolve(request.getParameter("topic")); } else { // TODO: Introduce a XWikiURL class in charge of getting the information relevant // to XWiki from a request URL (action, space, document name, file, etc) // Important: We cannot use getPathInfo() as the container encodes it and different // containers encode it differently, depending on their internal behavior and how // they are configured. Thus to make this container-proof we use the // getRequestURI() which isn't modified by the container and is thus only // URL-encoded. // Note: Ideally we should modify the getDocumentNameFromPath method but in order // not to introduce any new bug right now we're reconstructing a path info that we // pass to it using the following algorithm: // path info = requestURI - (contextPath + servletPath) String path = request.getRequestURI(); // Remove the (eventual) context path from the URI, usually /xwiki path = stripSegmentFromPath(path, request.getContextPath()); // Remove the (eventual) servlet path from the URI, usually /bin String servletPath = request.getServletPath(); path = stripSegmentFromPath(path, servletPath); // We need to get rid of the wiki name in case of a XEM in usepath mode if ("1".equals(Param("xwiki.virtual.usepath", "0")) && servletPath.equals("/" + Param("xwiki.virtual.usepath.servletpath", "wiki"))) { // Virtual mode, skip the wiki name if (path.indexOf('/', 1) < 0) { path = ""; } else { path = path.substring(path.indexOf('/', 1)); } } // Fix error in some containers, which don't hide the jsessionid parameter from the URL if (path.indexOf(";jsessionid=") != -1) { path = path.substring(0, path.indexOf(";jsessionid=")); } reference = getDocumentReferenceFromPath(path, context); } } return reference; } /** * @deprecated since 2.3M1 use {@link #getDocumentReferenceFromPath(String, XWikiContext)} instead */ @Deprecated public String getDocumentName(XWikiRequest request, XWikiContext context) { return this.localStringEntityReferenceSerializer.serialize(getDocumentReference(request, context)); } /** * Helper method, removes a predefined path segment (the context path or the servel path) from the start of the * requested URI and returns the remainder. This method is needed because special characters in the path can be * URL-encoded, depending on whether the request is forwarded through the request dispatcher or not, and also * depending on the client (some browsers encode -, while some don't). * * @param path the path, as taken from the requested URI * @param segment the segment to remove, as reported by the container * @return the path with the specified segment trimmed from its start */ public static String stripSegmentFromPath(String path, String segment) { if (!path.startsWith(segment)) { // The context path probably contains special characters that are encoded in the URL try { segment = URIUtil.encodePath(segment); } catch (URIException e) { LOGGER.warn("Invalid path: [" + segment + "]"); } } if (!path.startsWith(segment)) { // Some clients also encode -, although it's allowed in the path segment = segment.replaceAll("-", "%2D"); } if (!path.startsWith(segment)) { // Can't find the context path in the URL (shouldn't happen), just skip to the next path segment return path.substring(path.indexOf('/', 1)); } return path.substring(segment.length()); } public boolean prepareDocuments(XWikiRequest request, XWikiContext context, VelocityContext vcontext) throws XWikiException { XWikiDocument doc; context.getWiki().prepareResources(context); DocumentReference reference = getDocumentReference(request, context); if (context.getAction().equals("register")) { setPhonyDocument(reference, context, vcontext); doc = context.getDoc(); } else { try { doc = getDocument(reference, context); } catch (XWikiException e) { doc = context.getDoc(); if (context.getAction().equals("delete")) { if (doc == null) { setPhonyDocument(reference, context, vcontext); } if (!checkAccess("admin", doc, context)) { throw e; } } else { throw e; } } } // We need to check rights before we look for translations // Otherwise we don't have the user language if (checkAccess(context.getAction(), doc, context) == false) { Object[] args = { doc.getFullName(), context.getUser() }; setPhonyDocument(reference, context, vcontext); throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Access to document {0} has been denied to user {1}", null, args); } else if (checkActive(context) == 0) { // if auth_active_check, check if user is inactive boolean allow = false; String action = context.getAction(); /* * Allow inactive users to see skins, ressources, SSX, JSX and downloads they could have seen as guest. The * rational behind this behaviour is that inactive users should be able to access the same UI that guests * are used to see, including custom icons, panels, and so on... */ if ((action.equals("skin") && (doc.getSpace().equals("skins") || doc.getSpace().equals("resources"))) || ((action.equals("skin") || action.equals("download") || action.equals("ssx") || action.equals("jsx")) && getRightService().hasAccessLevel("view", XWikiRightService.GUEST_USER_FULLNAME, doc.getPrefixedFullName(), context)) || ((action.equals("view") && doc.getFullName().equals("XWiki.AccountValidation")))) { allow = true; } else { String allowed = Param("xwiki.inactiveuser.allowedpages", ""); if (context.getAction().equals("view") && !allowed.equals("")) { String[] allowedList = StringUtils.split(allowed, " ,"); for (int i = 0; i < allowedList.length; i++) { if (allowedList[i].equals(doc.getFullName())) { allow = true; break; } } } } if (!allow) { Object[] args = { context.getUser() }; setPhonyDocument(reference, context, vcontext); throw new XWikiException(XWikiException.MODULE_XWIKI_USER, XWikiException.ERROR_XWIKI_USER_INACTIVE, "User {0} account is inactive", null, args); } } context.put("doc", doc); vcontext.put("doc", doc.newDocument(context)); vcontext.put("cdoc", vcontext.get("doc")); XWikiDocument tdoc = doc.getTranslatedDocument(context); try { String rev = (String) context.get("rev"); if (StringUtils.isNotEmpty(rev)) { tdoc = getDocument(tdoc, rev, context); } } catch (Exception ex) { // Invalid version, just use the most recent one } context.put("tdoc", tdoc); vcontext.put("tdoc", tdoc.newDocument(context)); return true; } /** * @since 2.3M1 */ public void setPhonyDocument(DocumentReference reference, XWikiContext context, VelocityContext vcontext) { XWikiDocument doc = new XWikiDocument(reference); doc.setElements(XWikiDocument.HAS_ATTACHMENTS | XWikiDocument.HAS_OBJECTS); doc.setStore(getStore()); context.put("doc", doc); vcontext.put("doc", doc.newDocument(context)); vcontext.put("cdoc", vcontext.get("doc")); vcontext.put("tdoc", vcontext.get("doc")); } /** * @deprecated since 2.3M1 use {@link #setPhonyDocument(DocumentReference, XWikiContext, VelocityContext)} */ @Deprecated public void setPhonyDocument(String docName, XWikiContext context, VelocityContext vcontext) { setPhonyDocument(this.currentMixedDocumentReferenceResolver.resolve(docName), context, vcontext); } public XWikiEngineContext getEngineContext() { return this.engine_context; } public void setEngineContext(XWikiEngineContext engine_context) { this.engine_context = engine_context; } public URLPatternMatcher getUrlPatternMatcher() { return this.urlPatternMatcher; } public void setUrlPatternMatcher(URLPatternMatcher urlPatternMatcher) { this.urlPatternMatcher = urlPatternMatcher; } public void setAuthService(XWikiAuthService authService) { this.authService = authService; } public void setRightService(XWikiRightService rightService) { this.rightService = rightService; } public XWikiGroupService getGroupService(XWikiContext context) throws XWikiException { synchronized (this.GROUP_SERVICE_LOCK) { if (this.groupService == null) { String groupClass = Param("xwiki.authentication.groupclass", "com.xpn.xwiki.user.impl.xwiki.XWikiGroupServiceImpl"); try { this.groupService = (XWikiGroupService) Class.forName(groupClass).newInstance(); } catch (Exception e) { LOGGER.error("Failed to instantiate custom group service class: " + e.getMessage(), e); this.groupService = new XWikiGroupServiceImpl(); } this.groupService.init(this, context); } return this.groupService; } } public void setGroupService(XWikiGroupService groupService) { this.groupService = groupService; } // added some log statements to make debugging easier - LBlaze 2005.06.02 public XWikiAuthService getAuthService() { synchronized (this.AUTH_SERVICE_LOCK) { if (this.authService == null) { LOGGER.info("Initializing AuthService..."); String authClass = Param("xwiki.authentication.authclass"); if (StringUtils.isNotEmpty(authClass)) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Using custom AuthClass " + authClass + "."); } } else { if (isLDAP()) { authClass = "com.xpn.xwiki.user.impl.LDAP.XWikiLDAPAuthServiceImpl"; } else { authClass = "com.xpn.xwiki.user.impl.xwiki.XWikiAuthServiceImpl"; } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Using default AuthClass " + authClass + "."); } } try { this.authService = (XWikiAuthService) Class.forName(authClass).newInstance(); LOGGER.debug("Initialized AuthService using Relfection."); } catch (Exception e) { LOGGER.warn("Failed to initialize AuthService " + authClass + " using Reflection, trying default implementations using 'new'.", e); if (isLDAP()) { this.authService = new XWikiLDAPAuthServiceImpl(); } else { this.authService = new XWikiAuthServiceImpl(); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Initialized AuthService " + this.authService.getClass().getName() + " using 'new'."); } } } return this.authService; } } // added some log statements to make debugging easier - LBlaze 2005.06.02 public XWikiRightService getRightService() { synchronized (this.RIGHT_SERVICE_LOCK) { if (this.rightService == null) { LOGGER.info("Initializing RightService..."); String rightsClass = Param("xwiki.authentication.rightsclass"); if (rightsClass != null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Using custom RightsClass " + rightsClass + "."); } } else { rightsClass = "com.xpn.xwiki.user.impl.xwiki.XWikiRightServiceImpl"; if (LOGGER.isDebugEnabled()) { LOGGER.debug("Using default RightsClass " + rightsClass + "."); } } try { this.rightService = (XWikiRightService) Class.forName(rightsClass).newInstance(); LOGGER.debug("Initialized RightService using Reflection."); } catch (Exception e) { LOGGER.warn("Failed to initialize RightService " + rightsClass + " using Reflection, trying default implementation using 'new'.", e); this.rightService = new XWikiRightServiceImpl(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Initialized RightService " + this.rightService.getClass().getName() + " using 'new'."); } } } return this.rightService; } } public XWikiStatsService getStatsService(XWikiContext context) { synchronized (this.STATS_SERVICE_LOCK) { if (this.statsService == null) { if ("1".equals(Param("xwiki.stats", "1"))) { String storeClass = Param("xwiki.stats.class", "com.xpn.xwiki.stats.impl.XWikiStatsServiceImpl"); try { this.statsService = (XWikiStatsService) Class.forName(storeClass).newInstance(); } catch (Exception e) { e.printStackTrace(); this.statsService = new XWikiStatsServiceImpl(); } this.statsService.init(context); } } return this.statsService; } } public XWikiURLFactoryService getURLFactoryService() { if (this.urlFactoryService == null) { synchronized (this.URLFACTORY_SERVICE_LOCK) { if (this.urlFactoryService == null) { LOGGER.info("Initializing URLFactory Service..."); XWikiURLFactoryService factoryService = null; String urlFactoryServiceClass = Param("xwiki.urlfactory.serviceclass"); if (urlFactoryServiceClass != null) { try { if (LOGGER.isDebugEnabled()) { LOGGER.debug( "Using custom URLFactory Service Class [" + urlFactoryServiceClass + "]"); } factoryService = (XWikiURLFactoryService) Class.forName(urlFactoryServiceClass) .getConstructor(new Class<?>[] { XWiki.class }) .newInstance(new Object[] { this }); } catch (Exception e) { factoryService = null; LOGGER.warn("Failed to initialize URLFactory Service [" + urlFactoryServiceClass + "]", e); } } if (factoryService == null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Using default URLFactory Service Class [" + urlFactoryServiceClass + "]"); } factoryService = new XWikiURLFactoryServiceImpl(this); } // Set the urlFactoryService object in one assignment to prevent threading // issues when checking for // null above. this.urlFactoryService = factoryService; } } } return this.urlFactoryService; } public XWikiCriteriaService getCriteriaService(XWikiContext context) { return this.criteriaService; } public ZipOutputStream getZipOutputStream(XWikiContext context) throws IOException { return new ZipOutputStream(context.getResponse().getOutputStream()); } private Map<String, SearchEngineRule> getSearchEngineRules(XWikiContext context) { // We currently hardcode the rules // We will put them in the preferences soon Map<String, SearchEngineRule> map = new HashMap<String, SearchEngineRule>(); map.put("Google", new SearchEngineRule("google.", "s/(^|.*&)q=(.*?)(&.*|$)/$2/")); map.put("MSN", new SearchEngineRule("search.msn.", "s/(^|.*&)q=(.*?)(&.*|$)/$2/")); map.put("Yahoo", new SearchEngineRule("search.yahoo.", "s/(^|.*&)p=(.*?)(&.*|$)/$2/")); map.put("Voila", new SearchEngineRule("voila.fr", "s/(^|.*&)kw=(.*?)(&.*|$)/$2/")); return map; } public String getRefererText(String referer, XWikiContext context) { try { URL url = new URL(referer); Map<String, SearchEngineRule> searchengines = getSearchEngineRules(context); if (searchengines != null) { for (SearchEngineRule senginerule : searchengines.values()) { String host = url.getHost(); int i1 = host.indexOf(senginerule.getHost()); if (i1 != -1) { String query = context.getUtil().substitute(senginerule.getRegEx(), url.getQuery()); if ((query != null) && (!query.equals(""))) { // We return the query text instead of the full referer return host.substring(i1) + ":" + query; } } } } } catch (Exception e) { } String result = referer.substring(referer.indexOf("://") + 3); if (result.endsWith("/")) { return result.substring(0, result.length() - 1); } else { return result; } } public boolean isMySQL() { if (getHibernateStore() == null) { return false; } Object dialect = getHibernateStore().getConfiguration().getProperties().get("dialect"); return "org.hibernate.dialect.MySQLDialect".equals(dialect) || "net.sf.hibernate.dialect.MySQLDialect".equals(dialect); } public String getFullNameSQL() { return getFullNameSQL(true); } public String getFullNameSQL(boolean newFullName) { if (newFullName) { return "doc.fullName"; } if (this.fullNameSQL == null) { if (isMySQL()) { this.fullNameSQL = "CONCAT(doc.space,'.',doc.name)"; } else { this.fullNameSQL = "doc.space||'.'||doc.name"; } } return this.fullNameSQL; } public String getDocName(String docname) { return docname.substring(docname.indexOf('.') + 1); } public String getUserName(String user, XWikiContext context) { return getUserName(user, null, true, context); } public String getUserName(String user, String format, XWikiContext context) { return getUserName(user, format, true, context); } public String getUserName(String user, String format, boolean link, XWikiContext context) { if (StringUtils.isBlank(user)) { return ""; } XWikiDocument userdoc = null; try { userdoc = getDocument(user, context); if (userdoc == null) { return XMLUtils.escape(user); } BaseObject userobj = userdoc.getObject("XWiki.XWikiUsers"); if (userobj == null) { return XMLUtils.escape(userdoc.getDocumentReference().getName()); } Set<String> proplist = userobj.getPropertyList(); String text; if (format == null) { text = userobj.getStringValue("first_name") + " " + userobj.getStringValue("last_name"); if (StringUtils.isBlank(text)) { text = userdoc.getDocumentReference().getName(); } } else { VelocityContext vcontext = new VelocityContext(); for (String propname : proplist) { vcontext.put(propname, userobj.getStringValue(propname)); } text = XWikiVelocityRenderer.evaluate(format, "<username formatting code in " + context.getDoc().getDocumentReference() + ">", vcontext, context); } text = XMLUtils.escape(text.trim()); if (link) { text = "<span class=\"wikilink\"><a href=\"" + userdoc.getURL("view", context) + "\">" + text + "</a></span>"; } return text; } catch (Exception e) { LOGGER.error("Failed to get user profile page", e); if (userdoc != null) { return userdoc.getDocumentReference().getName(); } return user; } } public boolean hasCentralizedAuthentication(XWikiContext context) { String bl = getXWikiPreference("authentication_centralized", "", context); if ("1".equals(bl)) { return true; } if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.authentication.centralized", "0")); } public String getLocalUserName(String user, XWikiContext context) { if (hasCentralizedAuthentication(context)) { return getUserName(user, null, true, context); } else { return getUserName(user.substring(user.indexOf(':') + 1), null, true, context); } } public String getLocalUserName(String user, String format, XWikiContext context) { if (hasCentralizedAuthentication(context)) { return getUserName(user, format, true, context); } else { return getUserName(user.substring(user.indexOf(':') + 1), format, true, context); } } public String getLocalUserName(String user, String format, boolean link, XWikiContext context) { if (hasCentralizedAuthentication(context)) { return getUserName(user, format, link, context); } else { return getUserName(user.substring(user.indexOf(':') + 1), format, link, context); } } public String formatDate(Date date, String format, XWikiContext context) { if (date == null) { return ""; } String xformat = format; String defaultFormat = "yyyy/MM/dd HH:mm"; if (format == null) { xformat = getXWikiPreference("dateformat", defaultFormat, context); } try { DateFormatSymbols formatSymbols = null; try { String language = getLanguagePreference(context); formatSymbols = new DateFormatSymbols(new Locale(language)); } catch (Exception e2) { String language = getXWikiPreference("default_language", context); if ((language != null) && (!language.equals(""))) { formatSymbols = new DateFormatSymbols(new Locale(language)); } } SimpleDateFormat sdf; if (formatSymbols != null) { sdf = new SimpleDateFormat(xformat, formatSymbols); } else { sdf = new SimpleDateFormat(xformat); } try { sdf.setTimeZone(TimeZone.getTimeZone(getUserTimeZone(context))); } catch (Exception e) { } return sdf.format(date); } catch (Exception e) { LOGGER.info("Failed to format date [" + date + "] with pattern [" + xformat + "]: " + e.getMessage()); if (format == null) { if (xformat.equals(defaultFormat)) { return date.toString(); } else { return formatDate(date, defaultFormat, context); } } else { return formatDate(date, null, context); } } } /* * Allow to read user setting providing the user timezone All dates will be expressed with this timezone */ public String getUserTimeZone(XWikiContext context) { String tz = getUserPreference("timezone", context); if ((tz == null) || (tz.equals(""))) { String defaultTz = TimeZone.getDefault().getID(); return Param("xwiki.timezone", defaultTz); } else { return tz; } } /** * @deprecated since 2.2.1 use {@link #exists(DocumentReference, XWikiContext)} */ @Deprecated public boolean exists(String fullname, XWikiContext context) { String server = null, database = null; try { XWikiDocument doc = new XWikiDocument(); doc.setFullName(fullname, context); server = doc.getDatabase(); if (server != null) { database = context.getDatabase(); context.setDatabase(server); } return getStore().exists(doc, context); } catch (XWikiException e) { return false; } finally { if ((server != null) && (database != null)) { context.setDatabase(database); } } } public boolean exists(DocumentReference documentReference, XWikiContext context) { String server = null, database = null; try { XWikiDocument doc = new XWikiDocument(documentReference); server = doc.getDatabase(); if (server != null) { database = context.getDatabase(); context.setDatabase(server); } return getStore().exists(doc, context); } catch (XWikiException e) { return false; } finally { if ((server != null) && (database != null)) { context.setDatabase(database); } } } public String getAdType(XWikiContext context) { String adtype = ""; if (isVirtualMode()) { XWikiDocument wikiServer = context.getWikiServer(); if (wikiServer != null) { adtype = wikiServer.getStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, "adtype"); } } else { adtype = getXWikiPreference("adtype", "", context); } if (adtype.equals("")) { adtype = Param("xwiki.ad.type", ""); } return adtype; } public String getAdClientId(XWikiContext context) { final String defaultadclientid = "pub-2778691407285481"; String adclientid = ""; if (isVirtualMode()) { XWikiDocument wikiServer = context.getWikiServer(); if (wikiServer != null) { adclientid = wikiServer.getStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, "adclientid"); } } else { adclientid = getXWikiPreference("adclientid", "", context); } if (adclientid.equals("")) { adclientid = Param("xwiki.ad.clientid", ""); } if (adclientid.equals("")) { adclientid = defaultadclientid; } return adclientid; } public XWikiPluginInterface getPlugin(String name, XWikiContext context) { XWikiPluginManager plugins = getPluginManager(); Vector<String> pluginlist = plugins.getPlugins(); for (String pluginname : pluginlist) { if (pluginname.equals(name)) { return plugins.getPlugin(pluginname); } } return null; } public Api getPluginApi(String name, XWikiContext context) { XWikiPluginInterface plugin = getPlugin(name, context); if (plugin != null) { return plugin.getPluginApi(plugin, context); } return null; } /** * @return the cache factory. * @since 1.5M2. * @deprecated Since 1.7M1, use {@link CacheManager} component instead using {@link Utils#getComponent(Class)} */ @Deprecated public CacheFactory getCacheFactory() { CacheFactory cacheFactory; String cacheHint = Param("xwiki.cache.cachefactory.hint", null); if (StringUtils.isEmpty(cacheHint) || Utils.getComponent(CacheFactory.class, cacheHint) == null) { CacheManager cacheManager = Utils.getComponent(CacheManager.class); try { cacheFactory = cacheManager.getCacheFactory(); } catch (ComponentLookupException e) { throw new RuntimeException("Failed to get cache factory component", e); } } else { cacheFactory = Utils.getComponent(CacheFactory.class, cacheHint); } return cacheFactory; } /** * @return the cache factory creating local caches. * @since 1.5M2. * @deprecated Since 1.7M1, use {@link CacheManager} component instead using {@link Utils#getComponent(Class)} */ @Deprecated public CacheFactory getLocalCacheFactory() { CacheFactory localCacheFactory; String localCacheHint = Param("xwiki.cache.cachefactory.local.hint", null); if (StringUtils.isEmpty(localCacheHint) || Utils.getComponent(CacheFactory.class, localCacheHint) == null) { CacheManager cacheManager = Utils.getComponent(CacheManager.class); try { localCacheFactory = cacheManager.getLocalCacheFactory(); } catch (ComponentLookupException e) { throw new RuntimeException("Failed to get local cache factory component", e); } } else { localCacheFactory = Utils.getComponent(CacheFactory.class, localCacheHint); } return localCacheFactory; } public int getHttpTimeout(XWikiContext context) { int defaulttimeout = 60000; return (context == null) ? defaulttimeout : (int) context.getWiki().ParamAsLong("xwiki.http.timeout", defaulttimeout); } public String getHttpUserAgent(XWikiContext context) { if (context != null) { return context.getWiki().Param("xwiki.http.useragent", "XWikiBot/1.0"); } else { return "XWikiBot/1.0"; } } public String getURLContent(String surl, XWikiContext context) throws IOException { return getURLContent(surl, getHttpTimeout(context), getHttpUserAgent(context)); } public String getURLContent(String surl, int timeout, String userAgent) throws IOException { String content; HttpClient client = getHttpClient(timeout, userAgent); GetMethod get = new GetMethod(surl); try { client.executeMethod(get); content = get.getResponseBodyAsString(); } finally { // Release any connection resources used by the method get.releaseConnection(); } return content; } public String getURLContent(String surl, String username, String password, XWikiContext context) throws IOException { return getURLContent(surl, username, password, getHttpTimeout(context), getHttpUserAgent(context)); } public String getURLContent(String surl, String username, String password, int timeout, String userAgent) throws IOException { HttpClient client = getHttpClient(timeout, userAgent); // pass our credentials to HttpClient, they will only be used for // authenticating to servers with realm "realm", to authenticate agains // an arbitrary realm change this to null. client.getState().setCredentials(new AuthScope(null, -1, null), new UsernamePasswordCredentials(username, password)); // create a GET method that reads a file over HTTPS, we're assuming // that this file requires basic authentication using the realm above. GetMethod get = new GetMethod(surl); try { // Tell the GET method to automatically handle authentication. The // method will use any appropriate credentials to handle basic // authentication requests. Setting this value to false will cause // any request for authentication to return with a status of 401. // It will then be up to the client to handle the authentication. get.setDoAuthentication(true); // execute the GET client.executeMethod(get); // print the status and response return get.getResponseBodyAsString(); } finally { // release any connection resources used by the method get.releaseConnection(); } } public byte[] getURLContentAsBytes(String surl, XWikiContext context) throws IOException { return getURLContentAsBytes(surl, getHttpTimeout(context), getHttpUserAgent(context)); } public byte[] getURLContentAsBytes(String surl, int timeout, String userAgent) throws IOException { HttpClient client = getHttpClient(timeout, userAgent); // create a GET method that reads a file over HTTPS, we're assuming // that this file requires basic authentication using the realm above. GetMethod get = new GetMethod(surl); try { // execute the GET client.executeMethod(get); // print the status and response return get.getResponseBody(); } finally { // release any connection resources used by the method get.releaseConnection(); } } public byte[] getURLContentAsBytes(String surl, String username, String password, XWikiContext context) throws IOException { return getURLContentAsBytes(surl, username, password, getHttpTimeout(context), getHttpUserAgent(context)); } public byte[] getURLContentAsBytes(String surl, String username, String password, int timeout, String userAgent) throws IOException { HttpClient client = getHttpClient(timeout, userAgent); // pass our credentials to HttpClient, they will only be used for // authenticating to servers with realm "realm", to authenticate agains // an arbitrary realm change this to null. client.getState().setCredentials(new AuthScope(null, -1, null), new UsernamePasswordCredentials(username, password)); // create a GET method that reads a file over HTTPS, we're assuming // that this file requires basic authentication using the realm above. GetMethod get = new GetMethod(surl); try { // Tell the GET method to automatically handle authentication. The // method will use any appropriate credentials to handle basic // authentication requests. Setting this value to false will cause // any request for authentication to return with a status of 401. // It will then be up to the client to handle the authentication. get.setDoAuthentication(true); // execute the GET client.executeMethod(get); // print the status and response return get.getResponseBody(); } finally { // release any connection resources used by the method get.releaseConnection(); } } public List<String> getSpaces(XWikiContext context) throws XWikiException { try { return getStore().getQueryManager().getNamedQuery("getSpaces").execute(); } catch (QueryException ex) { throw new XWikiException(0, 0, ex.getMessage(), ex); } } public List<String> getSpaceDocsName(String spaceName, XWikiContext context) throws XWikiException { try { return getStore().getQueryManager().getNamedQuery("getSpaceDocsName").bindValue("space", spaceName) .execute(); } catch (QueryException ex) { throw new XWikiException(0, 0, ex.getMessage(), ex); } } public List<String> getIncludedMacros(String defaultSpace, String content, XWikiContext context) { List<String> list; try { String pattern = "#includeMacros[ ]*\\([ ]*([\"'])(.*?)\\1[ ]*\\)"; list = context.getUtil().getUniqueMatches(content, pattern, 2); for (int i = 0; i < list.size(); i++) { String name = list.get(i); if (name.indexOf('.') == -1) { list.set(i, defaultSpace + "." + name); } } } catch (Exception e) { // This should never happen LOGGER.error("Failed to extract #includeMacros targets from provided content [" + content + "]", e); list = Collections.emptyList(); } return list; } public String getFlash(String url, String width, String height, XWikiContext context) { VelocityContext vorigcontext = ((VelocityContext) context.get("vcontext")); try { VelocityContext vcontext = (VelocityContext) vorigcontext.clone(); vcontext.put("flashurl", url); vcontext.put("width", width); vcontext.put("height", height); context.put("vcontext", vcontext); return parseTemplate("flash.vm", context); } finally { context.put("vcontext", vorigcontext); } } /** * accessor for the isReadOnly instance var. * * @see #isReadOnly */ public boolean isReadOnly() { return this.isReadOnly; } public void setReadOnly(boolean readOnly) { this.isReadOnly = readOnly; } public void deleteAllDocuments(XWikiDocument doc, XWikiContext context) throws XWikiException { deleteAllDocuments(doc, true, context); } public void deleteAllDocuments(XWikiDocument doc, boolean totrash, XWikiContext context) throws XWikiException { // Delete all documents for (String lang : doc.getTranslationList(context)) { XWikiDocument tdoc = doc.getTranslatedDocument(lang, context); deleteDocument(tdoc, totrash, context); } deleteDocument(doc, context); } public void refreshLinks(XWikiContext context) throws XWikiException { try { // refreshes all Links of each doc of the wiki List<String> docs = getStore().getQueryManager().getNamedQuery("getAllDocuments").execute(); for (int i = 0; i < docs.size(); i++) { XWikiDocument myDoc = this.getDocument(docs.get(i), context); myDoc.getStore().saveLinks(myDoc, context, true); } } catch (QueryException ex) { throw new XWikiException(0, 0, ex.getMessage(), ex); } } public boolean hasBacklinks(XWikiContext context) { if (this.hasBacklinks == null) { this.hasBacklinks = "1".equals(getXWikiPreference("backlinks", "xwiki.backlinks", "0", context)); } return this.hasBacklinks; } public boolean hasTags(XWikiContext context) { return "1".equals(getXWikiPreference("tags", "xwiki.tags", "0", context)); } public boolean hasCustomMappings() { return "1".equals(Param("xwiki.store.hibernate.custommapping", "1")); } public boolean hasDynamicCustomMappings() { return "1".equals(Param("xwiki.store.hibernate.custommapping.dynamic", "0")); } public String getDefaultSpace(XWikiContext context) { String defaultSpace = getXWikiPreference("defaultweb", "", context); if (StringUtils.isEmpty(defaultSpace)) { return Param("xwiki.defaultweb", DEFAULT_HOME_SPACE); } return defaultSpace; } public boolean skipDefaultSpaceInURLs(XWikiContext context) { String bl = getXWikiPreference("usedefaultweb", "", context); if ("1".equals(bl)) { return true; } if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.usedefaultweb", "0")); } public boolean showViewAction(XWikiContext context) { String bl = getXWikiPreference("showviewaction", "", context); if ("1".equals(bl)) { return true; } else if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.showviewaction", "1")); } public boolean useDefaultAction(XWikiContext context) { String bl = getXWikiPreference("usedefaultaction", "", context); if ("1".equals(bl)) { return true; } if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.usedefaultaction", "0")); } public String getDefaultPage(XWikiContext context) { String defaultPage = getXWikiPreference("defaultpage", "", context); if (StringUtils.isEmpty(defaultPage)) { return Param("xwiki.defaultpage", DEFAULT_HOME_SPACE); } return defaultPage; } public boolean hasEditComment(XWikiContext context) { String bl = getXWikiPreference("editcomment", "", context); if ("1".equals(bl)) { return true; } if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.editcomment", "0")); } public boolean isEditCommentFieldHidden(XWikiContext context) { String bl = getXWikiPreference("editcomment_hidden", "", context); if ("1".equals(bl)) { return true; } if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.editcomment.hidden", "0")); } public boolean isEditCommentSuggested(XWikiContext context) { String bl = getXWikiPreference("editcomment_suggested", "", context); if ("1".equals(bl)) { return true; } if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.editcomment.suggested", "0")); } public boolean isEditCommentMandatory(XWikiContext context) { String bl = getXWikiPreference("editcomment_mandatory", "", context); if ("1".equals(bl)) { return true; } if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.editcomment.mandatory", "0")); } /** * @see com.xpn.xwiki.api.XWiki#hasMinorEdit() */ public boolean hasMinorEdit(XWikiContext context) { String bl = getXWikiPreference("minoredit", "", context); if ("1".equals(bl)) { return true; } if ("0".equals(bl)) { return false; } return "1".equals(Param("xwiki.minoredit", "1")); } /** * @see com.xpn.xwiki.api.XWiki#hasRecycleBin() * @param context maybe will be useful */ public boolean hasRecycleBin(XWikiContext context) { return "1".equals(Param("xwiki.recyclebin", "1")); } /** * Indicates whether deleted attachments are stored in a recycle bin or not. This can be configured using the key * <var>storage.attachment.recyclebin</var>. * * @param context The current {@link XWikiContext context}, maybe will be useful. */ public boolean hasAttachmentRecycleBin(XWikiContext context) { return "1".equals(Param("storage.attachment.recyclebin", "1")); } /** * @deprecated use {@link XWikiDocument#rename(String, XWikiContext)} instead */ @Deprecated public XWikiDocument renamePage(XWikiDocument doc, String newFullName, XWikiContext context) throws XWikiException { if (context.getWiki().exists(newFullName, context)) { XWikiDocument delDoc = context.getWiki().getDocument(newFullName, context); context.getWiki().deleteDocument(delDoc, context); } XWikiDocument renamedDoc = doc.copyDocument(newFullName, context); saveDocument(renamedDoc, context); renamedDoc.saveAllAttachments(context); deleteDocument(doc, context); return renamedDoc; } /** * @deprecated use {@link XWikiDocument#rename(String, XWikiContext)} instead */ @Deprecated public XWikiDocument renamePage(XWikiDocument doc, XWikiContext context, String newFullName) throws XWikiException { return renamePage(doc, newFullName, context); } /** * @since 2.2M2 */ public BaseClass getXClass(DocumentReference documentReference, XWikiContext context) throws XWikiException { // Used to avoid recursive loading of documents if there are recursives usage of classes BaseClass bclass = context.getBaseClass(documentReference); if (bclass != null) { return bclass; } return getDocument(documentReference, context).getXClass(); } /** * @deprecated since 2.2M2 use {@link #getXClass(DocumentReference, XWikiContext)} */ @Deprecated public BaseClass getClass(String fullName, XWikiContext context) throws XWikiException { DocumentReference reference = null; if (StringUtils.isNotEmpty(fullName)) { reference = this.currentMixedDocumentReferenceResolver.resolve(fullName); } return getXClass(reference, context); } public String getEditorPreference(XWikiContext context) { String pref = getUserPreference("editor", context); if (pref.equals("---")) { pref = getSpacePreference("editor", context); } if (pref.equals("")) { pref = Param("xwiki.editor", ""); } return pref.toLowerCase(); } /** * Privileged API to retrieve an object instantiated from groovy code in a String. Note that Groovy scripts * compilation is cached. * * @param script the Groovy class definition string (public class MyClass { ... }) * @return An object instantiating this class * @throws XWikiException */ public Object parseGroovyFromString(String script, XWikiContext context) throws XWikiException { if (getRenderingEngine().getRenderer("groovy") == null) { return null; } else { return ((XWikiGroovyRenderer) getRenderingEngine().getRenderer("groovy")).parseGroovyFromString(script, context); } } /** * Privileged API to retrieve an object instantiated from groovy code in a String, using a classloader including all * JAR files located in the passed page as attachments. Note that Groovy scripts compilation is cached * * @param script the Groovy class definition string (public class MyClass { ... }) * @return An object instantiating this class * @throws XWikiException */ public Object parseGroovyFromString(String script, String jarWikiPage, XWikiContext context) throws XWikiException { if (getRenderingEngine().getRenderer("groovy") == null) { return null; } XWikiPageClassLoader pcl = new XWikiPageClassLoader(jarWikiPage, context); Object prevParentClassLoader = context.get("parentclassloader"); try { context.put("parentclassloader", pcl); return parseGroovyFromString(script, context); } finally { if (prevParentClassLoader == null) { context.remove("parentclassloader"); } else { context.put("parentclassloader", prevParentClassLoader); } } } public Object parseGroovyFromPage(String fullname, XWikiContext context) throws XWikiException { return parseGroovyFromString(context.getWiki().getDocument(fullname, context).getContent(), context); } public Object parseGroovyFromPage(String fullName, String jarWikiPage, XWikiContext context) throws XWikiException { return parseGroovyFromString(context.getWiki().getDocument(fullName, context).getContent(), jarWikiPage, context); } public String getMacroList(XWikiContext context) { String macrosmapping = ""; XWiki xwiki = context.getWiki(); try { macrosmapping = getResourceContent(MACROS_FILE); } catch (IOException e) { } macrosmapping += "\r\n" + xwiki.getXWikiPreference("macros_mapping", "", context); return macrosmapping; } // This functions adds an object from an new object creation form public BaseObject getObjectFromRequest(String className, XWikiContext context) throws XWikiException { Map<String, String[]> map = Util.getObject(context.getRequest(), className); BaseClass bclass = context.getWiki().getClass(className, context); BaseObject newobject = (BaseObject) bclass.fromMap(map, context); return newobject; } public String getConvertingUserNameType(XWikiContext context) { if (StringUtils.isNotBlank(context.getWiki().getXWikiPreference("convertmail", context))) { return context.getWiki().getXWikiPreference("convertmail", "0", context); } return context.getWiki().Param("xwiki.authentication.convertemail", "0"); } public String convertUsername(String username, XWikiContext context) { if (username == null) { return null; } if (getConvertingUserNameType(context).equals("1") && (username.indexOf('@') != -1)) { String id = "" + username.hashCode(); id = id.replace("-", ""); if (username.length() > 1) { int i1 = username.indexOf('@'); id = "" + username.charAt(0) + username.substring(i1 + 1, i1 + 2) + username.charAt(username.length() - 1) + id; } return id; } else if (getConvertingUserNameType(context).equals("2")) { return username.replaceAll("[\\.\\@]", "_"); } else { return username; } } public boolean hasSectionEdit(XWikiContext context) { return (context.getWiki().ParamAsLong("xwiki.section.edit", 0) == 1); } /** * @return The maximum section depth for which section editing is available. This can be customized through the * {@code xwiki.section.depth} configuration property. Defaults to 2 when not defined. */ public long getSectionEditingDepth() { return ParamAsLong("xwiki.section.depth", 2); } public boolean hasCaptcha(XWikiContext context) { return (getXWikiPreferenceAsInt("captcha_enabled", "xwiki.plugin.captcha", 0, context) == 1); } public String getWysiwygToolbars(XWikiContext context) { return context.getWiki().Param("xwiki.wysiwyg.toolbars", ""); } public String clearName(String name, XWikiContext context) { return clearName(name, true, true, context); } public String clearName(String name, boolean stripDots, boolean ascii, XWikiContext context) { String temp = name; temp = temp.replaceAll( "[\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u0100\u0102\u0104\u01cd\u01de\u01e0\u01fa\u0200\u0202\u0226]", "A"); temp = temp.replaceAll( "[\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u0101\u0103\u0105\u01ce\u01df\u01e1\u01fb\u0201\u0203\u0227]", "a"); temp = temp.replaceAll("[\u00c6\u01e2\u01fc]", "AE"); temp = temp.replaceAll("[\u00e6\u01e3\u01fd]", "ae"); temp = temp.replaceAll("[\u008c\u0152]", "OE"); temp = temp.replaceAll("[\u009c\u0153]", "oe"); temp = temp.replaceAll("[\u00c7\u0106\u0108\u010a\u010c]", "C"); temp = temp.replaceAll("[\u00e7\u0107\u0109\u010b\u010d]", "c"); temp = temp.replaceAll("[\u00d0\u010e\u0110]", "D"); temp = temp.replaceAll("[\u00f0\u010f\u0111]", "d"); temp = temp.replaceAll("[\u00c8\u00c9\u00ca\u00cb\u0112\u0114\u0116\u0118\u011a\u0204\u0206\u0228]", "E"); temp = temp.replaceAll("[\u00e8\u00e9\u00ea\u00eb\u0113\u0115\u0117\u0119\u011b\u01dd\u0205\u0207\u0229]", "e"); temp = temp.replaceAll("[\u011c\u011e\u0120\u0122\u01e4\u01e6\u01f4]", "G"); temp = temp.replaceAll("[\u011d\u011f\u0121\u0123\u01e5\u01e7\u01f5]", "g"); temp = temp.replaceAll("[\u0124\u0126\u021e]", "H"); temp = temp.replaceAll("[\u0125\u0127\u021f]", "h"); temp = temp.replaceAll("[\u00cc\u00cd\u00ce\u00cf\u0128\u012a\u012c\u012e\u0130\u01cf\u0208\u020a]", "I"); temp = temp.replaceAll("[\u00ec\u00ed\u00ee\u00ef\u0129\u012b\u012d\u012f\u0131\u01d0\u0209\u020b]", "i"); temp = temp.replaceAll("[\u0132]", "IJ"); temp = temp.replaceAll("[\u0133]", "ij"); temp = temp.replaceAll("[\u0134]", "J"); temp = temp.replaceAll("[\u0135]", "j"); temp = temp.replaceAll("[\u0136\u01e8]", "K"); temp = temp.replaceAll("[\u0137\u0138\u01e9]", "k"); temp = temp.replaceAll("[\u0139\u013b\u013d\u013f\u0141]", "L"); temp = temp.replaceAll("[\u013a\u013c\u013e\u0140\u0142\u0234]", "l"); temp = temp.replaceAll("[\u00d1\u0143\u0145\u0147\u014a\u01f8]", "N"); temp = temp.replaceAll("[\u00f1\u0144\u0146\u0148\u0149\u014b\u01f9\u0235]", "n"); temp = temp.replaceAll( "[\u00d2\u00d3\u00d4\u00d5\u00d6\u00d8\u014c\u014e\u0150\u01d1\u01ea\u01ec\u01fe\u020c\u020e\u022a\u022c" + "\u022e\u0230]", "O"); temp = temp.replaceAll( "[\u00f2\u00f3\u00f4\u00f5\u00f6\u00f8\u014d\u014f\u0151\u01d2\u01eb\u01ed\u01ff\u020d\u020f\u022b\u022d" + "\u022f\u0231]", "o"); temp = temp.replaceAll("[\u0156\u0158\u0210\u0212]", "R"); temp = temp.replaceAll("[\u0157\u0159\u0211\u0213]", "r"); temp = temp.replaceAll("[\u015a\u015c\u015e\u0160\u0218]", "S"); temp = temp.replaceAll("[\u015b\u015d\u015f\u0161\u0219]", "s"); temp = temp.replaceAll("[\u00de\u0162\u0164\u0166\u021a]", "T"); temp = temp.replaceAll("[\u00fe\u0163\u0165\u0167\u021b\u0236]", "t"); temp = temp.replaceAll( "[\u00d9\u00da\u00db\u00dc\u0168\u016a\u016c\u016e\u0170\u0172\u01d3\u01d5\u01d7\u01d9\u01db\u0214\u0216]", "U"); temp = temp.replaceAll( "[\u00f9\u00fa\u00fb\u00fc\u0169\u016b\u016d\u016f\u0171\u0173\u01d4\u01d6\u01d8\u01da\u01dc\u0215\u0217]", "u"); temp = temp.replaceAll("[\u0174]", "W"); temp = temp.replaceAll("[\u0175]", "w"); temp = temp.replaceAll("[\u00dd\u0176\u0178\u0232]", "Y"); temp = temp.replaceAll("[\u00fd\u00ff\u0177\u0233]", "y"); temp = temp.replaceAll("[\u0179\u017b\u017d]", "Z"); temp = temp.replaceAll("[\u017a\u017c\u017e]", "z"); temp = temp.replaceAll("[\u00df]", "SS"); temp = temp.replaceAll("[_':,;\\\\/]", " "); name = temp; name = name.replaceAll("\\s+", ""); name = name.replaceAll("[\\(\\)]", " "); if (stripDots) { name = name.replaceAll("[\\.]", ""); } if (ascii) { name = name.replaceAll("[^a-zA-Z0-9\\-_\\.]", ""); } if (name.length() > 250) { name = name.substring(0, 250); } return name; } public String getUniquePageName(String space, XWikiContext context) { String pageName = generateRandomString(16); return getUniquePageName(space, pageName, context); } public String getUniquePageName(String space, String name, XWikiContext context) { String pageName = clearName(name, context); if (exists(space + "." + pageName, context)) { int i = 0; while (exists(space + "." + pageName + "_" + i, context)) { i++; } return pageName + "_" + i; } return pageName; } public String displaySearch(String fieldname, String className, XWikiCriteria criteria, XWikiContext context) throws XWikiException { return displaySearch(fieldname, className, "", criteria, context); } public String displaySearch(String fieldname, String className, XWikiContext context) throws XWikiException { return displaySearch(fieldname, className, "", new XWikiCriteria(), context); } public String displaySearch(String fieldname, String className, String prefix, XWikiCriteria criteria, XWikiContext context) throws XWikiException { BaseClass bclass = getDocument(className, context).getXClass(); PropertyClass pclass = (PropertyClass) bclass.get(fieldname); if (criteria == null) { criteria = new XWikiCriteria(); } if (pclass == null) { return ""; } else { return pclass.displaySearch(fieldname, prefix + className + "_", criteria, context); } } public String displaySearchColumns(String className, XWikiQuery query, XWikiContext context) throws XWikiException { return displaySearchColumns(className, "", query, context); } public String displaySearchColumns(String className, String prefix, XWikiQuery query, XWikiContext context) throws XWikiException { BaseClass bclass = getDocument(className, context).getXClass(); if (query == null) { query = new XWikiQuery(); } return bclass.displaySearchColumns(className + "_" + prefix, query, context); } public String displaySearchOrder(String className, XWikiQuery query, XWikiContext context) throws XWikiException { return displaySearchOrder(className, "", query, context); } public String displaySearchOrder(String className, String prefix, XWikiQuery query, XWikiContext context) throws XWikiException { BaseClass bclass = getDocument(className, context).getXClass(); if (query == null) { query = new XWikiQuery(); } return bclass.displaySearchOrder(className + "_" + prefix, query, context); } public <T> List<T> search(XWikiQuery query, XWikiContext context) throws XWikiException { QueryPlugin qp = (QueryPlugin) getPlugin("query", context); if (qp == null) { return null; } return qp.search(query); } public XWikiQuery createQueryFromRequest(String className, XWikiContext context) throws XWikiException { return new XWikiQuery(context.getRequest(), className, context); } public String searchAsTable(XWikiQuery query, XWikiContext context) throws XWikiException { QueryPlugin qp = (QueryPlugin) getPlugin("query", context); if (qp == null) { return null; } List<String> list = qp.search(query); String result = "{table}\r\n"; List<String> headerColumns = new ArrayList<String>(); List<String> displayProperties = query.getDisplayProperties(); for (String propname : displayProperties) { PropertyClass pclass = getPropertyClassFromName(propname, context); if (pclass != null) { headerColumns.add(pclass.getPrettyName()); } else { if (propname.startsWith("doc.")) { propname = propname.substring(4); headerColumns.add(XWikiDocument.getInternalPropertyName(propname, context)); } else { headerColumns.add(propname); } } } result += StringUtils.join(headerColumns.toArray(), " | ") + "\r\n"; for (String docname : list) { List<String> rowColumns = new ArrayList<String>(); XWikiDocument doc = getDocument(docname, context); for (String propname : displayProperties) { PropertyClass pclass = getPropertyClassFromName(propname, context); if (pclass == null) { if (propname.startsWith("doc.")) { propname = propname.substring(4); } String value = doc.getInternalProperty(propname); rowColumns.add((value == null) ? " " : value); } else { BaseObject bobj = doc.getObject(pclass.getObject().getName()); rowColumns.add(doc.display(pclass.getName(), "view", bobj, context)); } } result += StringUtils.join(rowColumns.toArray(), " | ") + "\r\n"; } result += "{table}\r\n"; return result; } public PropertyClass getPropertyClassFromName(String propPath, XWikiContext context) { int i1 = propPath.indexOf('_'); if (i1 == -1) { return null; } else { String className = propPath.substring(0, i1); String propName = propPath.substring(i1 + 1); try { return (PropertyClass) getDocument(className, context).getXClass().get(propName); } catch (XWikiException e) { return null; } } } public boolean validateDocument(XWikiDocument doc, XWikiContext context) throws XWikiException { return doc.validate(context); } public String addTooltip(String html, String message, String params, XWikiContext context) { StringBuffer buffer = new StringBuffer(); buffer.append("<span class=\"tooltip_span\" onmouseover=\""); buffer.append(params); buffer.append("; return escape('"); buffer.append(message.replaceAll("'", "\\'")); buffer.append("');\">"); buffer.append(html); buffer.append("</span>"); return buffer.toString(); } public String addTooltipJS(XWikiContext context) { StringBuffer buffer = new StringBuffer(); buffer.append("<script type=\"text/javascript\" src=\""); buffer.append(getSkinFile("ajax/wzToolTip.js", context)); buffer.append("\"></script>"); // buffer.append("<div id=\"dhtmltooltip\"></div>"); return buffer.toString(); } public String addTooltip(String html, String message, XWikiContext context) { return addTooltip(html, message, "this.WIDTH='300'", context); } public void renamePage(String fullName, String newFullName, XWikiContext context) throws XWikiException { renamePage(context.getWiki().getDocument(fullName, context), newFullName, context); } public String addMandatory(XWikiContext context) { String star = "<span class=\"mandatoryParenthesis\"> (</span><span class=\"mandatoryDot\">∗</span><span class=\"mandatoryParenthesis\">) </span>"; return context.getWiki().getXWikiPreference("mandatory_display", star, context); } /** * @since 2.3M1 */ public boolean hasVersioning(XWikiContext context) { return ("1".equals(context.getWiki().Param("xwiki.store.versioning", "1"))); } /** * @deprecated since 2.3M1 use {@link #hasVersioning(XWikiContext)} instead */ @Deprecated public boolean hasVersioning(String fullName, XWikiContext context) { return hasVersioning(context); } public boolean hasAttachmentVersioning(XWikiContext context) { return ("1".equals(context.getWiki().Param("xwiki.store.attachment.versioning", "1"))); } public String getExternalAttachmentURL(String fullName, String filename, XWikiContext context) { XWikiDocument doc = new XWikiDocument(); doc.setFullName(fullName, context); return doc.getExternalAttachmentURL(filename, "download", context); } public int getMaxRecursiveSpaceChecks(XWikiContext context) { int max = getXWikiPreferenceAsInt("rights_maxrecursivespacechecks", -1, context); if (max == -1) { return (int) ParamAsLong("xwiki.rights.maxrecursivespacechecks", 0); } else { return max; } } /** * Get the XWiki temporary filesystem directory (deleted on exit) * * @param context * @return temporary directory * @since 1.1 Milestone 4 */ public File getTempDirectory(XWikiContext context) { // if tempDir has already been set, return it if (tempDir != null) { return tempDir; } // xwiki.cfg String dirPath = context.getWiki().Param("xwiki.temp.dir"); if (dirPath != null) { try { tempDir = new File(dirPath.replaceAll("\\s+$", "")); if (tempDir.isDirectory() && tempDir.canWrite()) { tempDir.deleteOnExit(); return tempDir; } } catch (Exception e) { tempDir = null; LOGGER.warn("xwiki.temp.dir set in xwiki.cfg : " + dirPath + " does not exist or is not writable", e); } } Object jsct = context.getEngineContext().getAttribute("javax.servlet.context.tempdir"); // javax.servlet.context.tempdir (File) if (jsct != null && (jsct instanceof File)) { tempDir = (File) jsct; if (tempDir.isDirectory() && tempDir.canWrite()) { return tempDir; } } // javax.servlet.context.tempdir (String) if (jsct != null && (jsct instanceof String)) { tempDir = new File((String) jsct); if (tempDir.isDirectory() && tempDir.canWrite()) { return tempDir; } } // Let's make a tempdir in java.io.tmpdir tempDir = new File(System.getProperty("java.io.tmpdir"), "xwikiTemp"); if (tempDir.exists()) { tempDir.deleteOnExit(); } else { tempDir.mkdir(); tempDir.deleteOnExit(); } return tempDir; } /** * Get a new directory in the xwiki work directory * * @param subdir desired directory name * @param context * @return work subdirectory * @since 1.1 Milestone 4 */ public File getWorkSubdirectory(String subdir, XWikiContext context) { File fdir = new File(this.getWorkDirectory(context).getAbsolutePath(), subdir); if (!fdir.exists()) { fdir.mkdir(); } return fdir; } /** * Get the XWiki work directory * * @param context * @return work directory * @since 1.1 Milestone 4 */ public File getWorkDirectory(XWikiContext context) { String dirPath; // if workDir has already been set, return it if (workDir != null) { return workDir; } // xwiki.cfg dirPath = context.getWiki().Param("xwiki.work.dir"); if (dirPath != null) { try { workDir = new File(dirPath.replaceAll("\\s+$", "")); if (workDir.exists()) { if (workDir.isDirectory() && workDir.canWrite()) { return workDir; } } else { workDir.mkdir(); return workDir; } } catch (Exception e) { LOGGER.warn("xwiki.work.dir set in xwiki.cfg : " + dirPath + " does not exist or is not writable", e); workDir = null; } } // No choices left, retreiving the temp directory this.workDir = this.getTempDirectory(context); return this.workDir; } public XWikiDocument rollback(final XWikiDocument tdoc, String rev, XWikiContext context) throws XWikiException { LOGGER.debug("Rolling back [" + tdoc + "] to version " + rev); // Let's clone rolledbackDoc since we might modify it XWikiDocument rolledbackDoc = getDocument(tdoc, rev, context).clone(); if ("1".equals(context.getWiki().Param("xwiki.store.rollbackattachmentwithdocuments", "1"))) { // Attachment handling strategy: // - Two lists: Old Attachments, Current Attachments // Goals: // 1. Attachments that are only in OA must be restored from the trash // 2. Attachments that are only in CA must be sent to the trash // 3. Attachments that are in both lists should be reverted to the right version // 4. Gotcha: deleted and re-uploaded attachments should be both trashed and restored. // Plan: // - Construct three lists: to restore, to delete, to revert // - Iterate over OA. // -- If the attachment is not in CA, add it to the restore list // -- If it is in CA, but the date of the first version of the current attachment is after the date of the // restored document version, add it to both the restore & delete lists // -- Otherwise, add it to the revert list // - Iterate over CA // -- If the attachment is not in OA, add it to the delete list List<XWikiAttachment> oldAttachments = rolledbackDoc.getAttachmentList(); List<XWikiAttachment> currentAttachments = tdoc.getAttachmentList(); List<XWikiAttachment> toRestore = new ArrayList<XWikiAttachment>(); List<XWikiAttachment> toTrash = new ArrayList<XWikiAttachment>(); List<XWikiAttachment> toRevert = new ArrayList<XWikiAttachment>(); // First step, determine what to do with each attachment LOGGER.debug("Checking attachments"); for (XWikiAttachment oldAttachment : oldAttachments) { String filename = oldAttachment.getFilename(); XWikiAttachment equivalentAttachment = tdoc.getAttachment(filename); if (equivalentAttachment == null) { // Deleted attachment LOGGER.debug("Deleted attachment: " + filename); toRestore.add(oldAttachment); continue; } XWikiAttachment equivalentAttachmentRevision = equivalentAttachment .getAttachmentRevision(oldAttachment.getVersion(), context); if (equivalentAttachmentRevision == null || !equivalentAttachmentRevision.getDate().equals(oldAttachment.getDate())) { // Recreated attachment LOGGER.debug("Recreated attachment: " + filename); // If the attachment trash is not available, don't lose the existing attachment if (getAttachmentRecycleBinStore() != null) { toTrash.add(equivalentAttachment); toRestore.add(oldAttachment); } continue; } if (!StringUtils.equals(oldAttachment.getVersion(), equivalentAttachment.getVersion())) { // Updated attachment LOGGER.debug("Updated attachment: " + filename); toRevert.add(equivalentAttachment); } } for (XWikiAttachment attachment : currentAttachments) { if (rolledbackDoc.getAttachment(attachment.getFilename()) == null) { LOGGER.debug("New attachment: " + attachment.getFilename()); toTrash.add(attachment); } } // Second step, treat each affected attachment // Delete new attachments if (context.getWiki().hasAttachmentRecycleBin(context)) { for (XWikiAttachment attachmentToDelete : toTrash) { // Nothing needed for the reverted document, but let's send the extra attachments to the trash context.getWiki().getAttachmentRecycleBinStore().saveToRecycleBin(attachmentToDelete, context.getUser(), new Date(), context, true); } } // Revert updated attachments to the old version for (XWikiAttachment attachmentToRevert : toRevert) { String oldAttachmentVersion = rolledbackDoc.getAttachment(attachmentToRevert.getFilename()) .getVersion(); XWikiAttachment oldAttachmentRevision = attachmentToRevert .getAttachmentRevision(oldAttachmentVersion, context); if (oldAttachmentRevision == null) { // Previous version is lost, just leave the current version in place replaceAttachmentInPlace(rolledbackDoc, attachmentToRevert); continue; } // We can't just leave the old version in place, since it will break the revision history, given the // current implementation, so we set the attachment version to the most recent version, mark the content // as dirty, and the storage will automatically bump up the version number. // This is a hack, to be fixed once the storage doesn't take care of updating the history and version, // and once the current attachment version can point to an existing version from the history. oldAttachmentRevision.setVersion(attachmentToRevert.getVersion()); oldAttachmentRevision.setMetaDataDirty(true); oldAttachmentRevision.getAttachment_content().setContentDirty(true); replaceAttachmentInPlace(rolledbackDoc, oldAttachmentRevision); } // Restore deleted attachments from the trash if (getAttachmentRecycleBinStore() != null) { for (XWikiAttachment attachmentToRestore : toRestore) { // There might be multiple versions of the attachment in the trash, search for the right one List<DeletedAttachment> deletedVariants = getAttachmentRecycleBinStore() .getAllDeletedAttachments(attachmentToRestore, context, true); DeletedAttachment correctVariant = null; for (DeletedAttachment variant : deletedVariants) { // Reverse chronological order if (variant.getDate().before(rolledbackDoc.getDate())) { break; } correctVariant = variant; } if (correctVariant == null) { // Not found in the trash, nothing left to do continue; } XWikiAttachment restoredAttachment = correctVariant.restoreAttachment(null, context); XWikiAttachment restoredAttachmentRevision = restoredAttachment .getAttachmentRevision(attachmentToRestore.getVersion(), context); if (restoredAttachmentRevision != null) { restoredAttachmentRevision .setAttachment_archive(restoredAttachment.getAttachment_archive()); restoredAttachmentRevision.getAttachment_archive() .setAttachment(restoredAttachmentRevision); restoredAttachmentRevision.setVersion(restoredAttachment.getVersion()); restoredAttachmentRevision.setMetaDataDirty(true); restoredAttachmentRevision.getAttachment_content().setContentDirty(true); replaceAttachmentInPlace(rolledbackDoc, restoredAttachmentRevision); } else { // This particular version is lost, update to the one available replaceAttachmentInPlace(rolledbackDoc, restoredAttachment); } } } else { // No trash, can't restore. Remove the attachment references, so that the document is not broken for (XWikiAttachment attachmentToRestore : toRestore) { rolledbackDoc.getAttachmentList().remove(attachmentToRestore); } } } // now we save the final document.. String username = context.getUser(); rolledbackDoc.setAuthor(username); rolledbackDoc.setRCSVersion(tdoc.getRCSVersion()); rolledbackDoc.setVersion(tdoc.getVersion()); rolledbackDoc.setContentDirty(true); List<Object> params = new ArrayList<Object>(); params.add(rev); saveDocument(rolledbackDoc, context.getMessageTool().get("core.comment.rollback", params), context); return rolledbackDoc; } private void replaceAttachmentInPlace(XWikiDocument doc, XWikiAttachment attachment) { for (ListIterator<XWikiAttachment> it = doc.getAttachmentList().listIterator(); it.hasNext();) { if (StringUtils.equals(it.next().getFilename(), attachment.getFilename())) { it.remove(); it.add(attachment); break; } } } /** * @return the ids of configured syntaxes for this wiki (eg "xwiki/1.0", "xwiki/2.0", "mediawiki/1.0", etc) */ public List<String> getConfiguredSyntaxes() { return this.configuredSyntaxes; } /** * @return the syntax id of the syntax to use when creating new documents. */ public String getDefaultDocumentSyntax() { // TODO: Fix this method to return a Syntax object instead of a String return Utils.getComponent(CoreConfiguration.class).getDefaultDocumentSyntax().toIdString(); } /** * Set the fields of the class document passed as parameter. Can generate content for both XWiki Syntax 1.0 and * XWiki Syntax 2.0. If new documents are set to be created in XWiki Syntax 1.0 then generate XWiki 1.0 Syntax * otherwise generate XWiki Syntax 2.0. * * @param title the page title to set * @return true if the document has been modified, false otherwise */ private boolean setClassDocumentFields(XWikiDocument doc, String title) { boolean needsUpdate = false; if (StringUtils.isBlank(doc.getCreator())) { needsUpdate = true; doc.setCreator(XWikiRightService.SUPERADMIN_USER); } if (StringUtils.isBlank(doc.getAuthor())) { needsUpdate = true; doc.setAuthor(doc.getCreator()); } if (StringUtils.isBlank(doc.getParent())) { needsUpdate = true; doc.setParent("XWiki.XWikiClasses"); } if (StringUtils.isBlank(doc.getTitle())) { needsUpdate = true; doc.setTitle(title); } // Use ClassSheet to display the class document if no other sheet is explicitly specified. SheetBinder documentSheetBinder = Utils.getComponent(SheetBinder.class, "document"); if (documentSheetBinder.getSheets(doc).isEmpty()) { String wikiName = doc.getDocumentReference().getWikiReference().getName(); DocumentReference sheet = new DocumentReference(wikiName, SYSTEM_SPACE, "ClassSheet"); needsUpdate |= documentSheetBinder.bind(doc, sheet); } return needsUpdate; } /** * Get the syntax of the document currently being executed. * <p> * The document currently being executed is not the same than the context document since when including a page with * velocity #includeForm(), method for example the context doc is the includer document even if includeForm() fully * execute and render the included document before insert it in the includer document. * <p> * If the current document can't be found, the method assume that the executed document is the context document * (it's generally the case when a document is directly rendered with * {@link XWikiDocument#getRenderedContent(XWikiContext)} for example). * * @param defaultSyntaxId the default value to return if no document can be found * @return the syntax identifier */ public String getCurrentContentSyntaxId(String defaultSyntaxId, XWikiContext context) { String syntaxId = getCurrentContentSyntaxIdInternal(context); if (syntaxId == null) { syntaxId = defaultSyntaxId; } return syntaxId; } /** * Get the syntax of the document currently being executed. * <p> * The document currently being executed is not the same than the context document since when including a page with * velocity #includeForm(), method for example the context doc is the includer document even if includeForm() fully * execute and render the included document before insert it in the includer document. * <p> * If the current document can't be found, the method assume that the executed document is the context document * (it's generally the case when a document is directly rendered with * {@link XWikiDocument#getRenderedContent(XWikiContext)} for example). * * @return the syntax identifier */ public String getCurrentContentSyntaxId(XWikiContext context) { String syntaxId = getCurrentContentSyntaxIdInternal(context); if (syntaxId == null) { throw new RuntimeException("Cannot get the current syntax since there's no current document set"); } return syntaxId; } private String getCurrentContentSyntaxIdInternal(XWikiContext context) { String syntaxId = null; if (context.get("sdoc") != null) { // The content document syntaxId = ((XWikiDocument) context.get("sdoc")).getSyntax().toIdString(); } else if (context.getDoc() != null) { // The context document syntaxId = context.getDoc().getSyntax().toIdString(); } return syntaxId; } /** * @return true if title handling should be using the compatibility mode or not. When the compatibility mode is * active, if the document's content first header (level 1 or level 2) matches the document's title the * first header is stripped. */ public boolean isTitleInCompatibilityMode() { return "1".equals(Param("xwiki.title.compatibility", "0")); } /** * {@inheritDoc} * * @see org.xwiki.observation.EventListener#onEvent(org.xwiki.observation.event.Event, java.lang.Object, * java.lang.Object) */ public void onEvent(Event event, Object source, Object data) { XWikiDocument doc = (XWikiDocument) source; XWikiContext context = (XWikiContext) data; if (event instanceof XObjectPropertyEvent) { EntityReference reference = ((XObjectPropertyEvent) event).getReference(); String modifiedProperty = reference.getName(); if ("plugins".equals(modifiedProperty)) { onPluginPreferenceEvent(event, doc, context); } else if ("backlinks".equals(modifiedProperty)) { this.hasBacklinks = doc.getXObject((ObjectReference) reference.getParent()).getIntValue("backlinks", (int) ParamAsLong("xwiki.backlinks", 0)) == 1; } } else if (event instanceof XObjectEvent) { onServerObjectEvent(event, doc, context); } } private void onServerObjectEvent(Event event, XWikiDocument doc, XWikiContext context) { flushVirtualWikis(doc.getOriginalDocument()); flushVirtualWikis(doc); } private void onPluginPreferenceEvent(Event event, XWikiDocument doc, XWikiContext context) { if (!isVirtualMode()) { // If the XWikiPreferences plugin propery is modified, reload all plugins. preparePlugins(context); } } /** * The reference to match class XWiki.XWikiServerClass on whatever wiki. */ private static final RegexEntityReference SERVERCLASS_REFERENCE = new RegexEntityReference( Pattern.compile(".*:XWiki.XWikiServerClass\\[\\d*\\]"), EntityType.OBJECT); /** * The reference to match properties "plugins" and "backlinks" of class XWiki.XWikiPreference on whatever wiki. */ private static final RegexEntityReference XWIKIPREFERENCE_PROPERTY_REFERENCE = new RegexEntityReference( Pattern.compile("plugins|backlinks"), EntityType.OBJECT_PROPERTY, new RegexEntityReference(Pattern.compile(".*:XWiki.XWikiPreferences\\[\\d*\\]"), EntityType.OBJECT)); private static final List<Event> LISTENER_EVENTS = new ArrayList<Event>() { { add(new XObjectAddedEvent(SERVERCLASS_REFERENCE)); add(new XObjectDeletedEvent(SERVERCLASS_REFERENCE)); add(new XObjectUpdatedEvent(SERVERCLASS_REFERENCE)); add(new XObjectPropertyAddedEvent(XWIKIPREFERENCE_PROPERTY_REFERENCE)); add(new XObjectPropertyDeletedEvent(XWIKIPREFERENCE_PROPERTY_REFERENCE)); add(new XObjectPropertyUpdatedEvent(XWIKIPREFERENCE_PROPERTY_REFERENCE)); } }; public List<Event> getEvents() { return LISTENER_EVENTS; } public String getName() { return "xwiki-core"; } }