Index: ../xwiki-commons/xwiki-commons-core/xwiki-commons-observation/xwiki-commons-observation-api/src/main/java/org/xwiki/observation/event/ApplicationReadyEvent.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>MacRoman =================================================================== --- ../xwiki-commons/xwiki-commons-core/xwiki-commons-observation/xwiki-commons-observation-api/src/main/java/org/xwiki/observation/event/ApplicationReadyEvent.java (revision ) +++ ../xwiki-commons/xwiki-commons-core/xwiki-commons-observation/xwiki-commons-observation-api/src/main/java/org/xwiki/observation/event/ApplicationReadyEvent.java (revision ) @@ -0,0 +1,35 @@ +/* + * 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 org.xwiki.observation.event; + +/** + * An event triggered when the XWiki application is ready to service requests. + * + * @version $Id$ + * @since 4.0M2 + */ +public class ApplicationReadyEvent implements Event +{ + @Override + public boolean matches(Object otherEvent) + { + return this.getClass().isAssignableFrom(otherEvent.getClass()); + } +} Index: xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>MacRoman Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP <+>/*\n * See the NOTICE file distributed with this work for additional\n * information regarding copyright ownership.\n *\n * This is free software; you can redistribute it and/or modify it\n * under the terms of the GNU Lesser General Public License as\n * published by the Free Software Foundation; either version 2.1 of\n * the License, or (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this software; if not, write to the Free\n * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA\n * 02110-1301 USA, or see the FSF site: http://www.fsf.org.\n */\npackage com.xpn.xwiki;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Type;\nimport java.net.InetAddress;\nimport java.net.MalformedURLException;\nimport java.net.URI;\nimport java.net.URL;\nimport java.text.DateFormatSymbols;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Calendar;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.Enumeration;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.ListIterator;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.ResourceBundle;\nimport java.util.Set;\nimport java.util.TimeZone;\nimport java.util.Vector;\nimport java.util.regex.Pattern;\nimport java.util.zip.ZipOutputStream;\n\nimport javax.naming.Context;\nimport javax.naming.InitialContext;\nimport javax.naming.NamingException;\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.httpclient.Credentials;\nimport org.apache.commons.httpclient.HttpClient;\nimport org.apache.commons.httpclient.URIException;\nimport org.apache.commons.httpclient.UsernamePasswordCredentials;\nimport org.apache.commons.httpclient.auth.AuthScope;\nimport org.apache.commons.httpclient.methods.GetMethod;\nimport org.apache.commons.httpclient.util.URIUtil;\nimport org.apache.commons.io.FileUtils;\nimport org.apache.commons.io.IOUtils;\nimport org.apache.commons.lang3.RandomStringUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.commons.lang3.math.NumberUtils;\nimport org.apache.commons.net.smtp.SMTPClient;\nimport org.apache.commons.net.smtp.SMTPReply;\nimport org.apache.velocity.VelocityContext;\nimport org.hibernate.HibernateException;\nimport org.securityfilter.filter.URLPatternMatcher;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.xwiki.bridge.event.DocumentCreatedEvent;\nimport org.xwiki.bridge.event.DocumentCreatingEvent;\nimport org.xwiki.bridge.event.DocumentDeletedEvent;\nimport org.xwiki.bridge.event.DocumentDeletingEvent;\nimport org.xwiki.bridge.event.DocumentUpdatedEvent;\nimport org.xwiki.bridge.event.DocumentUpdatingEvent;\nimport org.xwiki.cache.Cache;\nimport org.xwiki.cache.CacheException;\nimport org.xwiki.cache.CacheFactory;\nimport org.xwiki.cache.CacheManager;\nimport org.xwiki.cache.config.CacheConfiguration;\nimport org.xwiki.cache.eviction.LRUEvictionConfiguration;\nimport org.xwiki.component.manager.ComponentLookupException;\nimport org.xwiki.context.Execution;\nimport org.xwiki.context.ExecutionContext;\nimport org.xwiki.model.EntityType;\nimport org.xwiki.model.reference.DocumentReference;\nimport org.xwiki.model.reference.DocumentReferenceResolver;\nimport org.xwiki.model.reference.EntityReference;\nimport org.xwiki.model.reference.EntityReferenceResolver;\nimport org.xwiki.model.reference.EntityReferenceSerializer;\nimport org.xwiki.model.reference.EntityReferenceValueProvider;\nimport org.xwiki.model.reference.ObjectReference;\nimport org.xwiki.model.reference.RegexEntityReference;\nimport org.xwiki.model.reference.SpaceReference;\nimport org.xwiki.model.reference.WikiReference;\nimport org.xwiki.observation.EventListener;\nimport org.xwiki.observation.ObservationManager;\nimport org.xwiki.observation.event.Event;\nimport org.xwiki.query.QueryException;\nimport org.xwiki.rendering.macro.wikibridge.WikiMacroInitializer;\nimport org.xwiki.rendering.parser.ParseException;\nimport org.xwiki.rendering.syntax.Syntax;\nimport org.xwiki.rendering.syntax.SyntaxFactory;\nimport org.xwiki.sheet.SheetBinder;\nimport org.xwiki.url.XWikiEntityURL;\nimport org.xwiki.url.standard.XWikiURLBuilder;\nimport org.xwiki.xml.XMLUtils;\n\nimport com.xpn.xwiki.api.Api;\nimport com.xpn.xwiki.api.Document;\nimport com.xpn.xwiki.api.User;\nimport com.xpn.xwiki.criteria.api.XWikiCriteriaService;\nimport com.xpn.xwiki.doc.DeletedAttachment;\nimport com.xpn.xwiki.doc.XWikiAttachment;\nimport com.xpn.xwiki.doc.XWikiDeletedDocument;\nimport com.xpn.xwiki.doc.XWikiDocument;\nimport com.xpn.xwiki.doc.XWikiDocumentArchive;\nimport com.xpn.xwiki.internal.event.XObjectAddedEvent;\nimport com.xpn.xwiki.internal.event.XObjectDeletedEvent;\nimport com.xpn.xwiki.internal.event.XObjectEvent;\nimport com.xpn.xwiki.internal.event.XObjectPropertyAddedEvent;\nimport com.xpn.xwiki.internal.event.XObjectPropertyDeletedEvent;\nimport com.xpn.xwiki.internal.event.XObjectPropertyEvent;\nimport com.xpn.xwiki.internal.event.XObjectPropertyUpdatedEvent;\nimport com.xpn.xwiki.internal.event.XObjectUpdatedEvent;\nimport com.xpn.xwiki.objects.BaseObject;\nimport com.xpn.xwiki.objects.PropertyInterface;\nimport com.xpn.xwiki.objects.classes.BaseClass;\nimport com.xpn.xwiki.objects.classes.BooleanClass;\nimport com.xpn.xwiki.objects.classes.GroupsClass;\nimport com.xpn.xwiki.objects.classes.LevelsClass;\nimport com.xpn.xwiki.objects.classes.NumberClass;\nimport com.xpn.xwiki.objects.classes.PasswordClass;\nimport com.xpn.xwiki.objects.classes.PropertyClass;\nimport com.xpn.xwiki.objects.classes.StaticListClass;\nimport com.xpn.xwiki.objects.classes.UsersClass;\nimport com.xpn.xwiki.objects.meta.MetaClass;\nimport com.xpn.xwiki.plugin.XWikiPluginInterface;\nimport com.xpn.xwiki.plugin.XWikiPluginManager;\nimport com.xpn.xwiki.render.DefaultXWikiRenderingEngine;\nimport com.xpn.xwiki.render.XWikiRenderingEngine;\nimport com.xpn.xwiki.render.XWikiVelocityRenderer;\nimport com.xpn.xwiki.render.groovy.XWikiGroovyRenderer;\nimport com.xpn.xwiki.render.groovy.XWikiPageClassLoader;\nimport com.xpn.xwiki.stats.api.XWikiStatsService;\nimport com.xpn.xwiki.stats.impl.SearchEngineRule;\nimport com.xpn.xwiki.stats.impl.XWikiStatsServiceImpl;\nimport com.xpn.xwiki.store.AttachmentRecycleBinStore;\nimport com.xpn.xwiki.store.AttachmentVersioningStore;\nimport com.xpn.xwiki.store.XWikiAttachmentStoreInterface;\nimport com.xpn.xwiki.store.XWikiCacheStore;\nimport com.xpn.xwiki.store.XWikiCacheStoreInterface;\nimport com.xpn.xwiki.store.XWikiHibernateStore;\nimport com.xpn.xwiki.store.XWikiRecycleBinStoreInterface;\nimport com.xpn.xwiki.store.XWikiStoreInterface;\nimport com.xpn.xwiki.store.XWikiVersioningStoreInterface;\nimport com.xpn.xwiki.user.api.XWikiAuthService;\nimport com.xpn.xwiki.user.api.XWikiGroupService;\nimport com.xpn.xwiki.user.api.XWikiRightService;\nimport com.xpn.xwiki.user.api.XWikiUser;\nimport com.xpn.xwiki.user.impl.LDAP.XWikiLDAPAuthServiceImpl;\nimport com.xpn.xwiki.user.impl.xwiki.XWikiAuthServiceImpl;\nimport com.xpn.xwiki.user.impl.xwiki.XWikiGroupServiceImpl;\nimport com.xpn.xwiki.user.impl.xwiki.XWikiRightServiceImpl;\nimport com.xpn.xwiki.util.Util;\nimport com.xpn.xwiki.util.XWikiStubContextProvider;\nimport com.xpn.xwiki.web.Utils;\nimport com.xpn.xwiki.web.XWikiEngineContext;\nimport com.xpn.xwiki.web.XWikiMessageTool;\nimport com.xpn.xwiki.web.XWikiRequest;\nimport com.xpn.xwiki.web.XWikiURLFactory;\nimport com.xpn.xwiki.web.XWikiURLFactoryService;\nimport com.xpn.xwiki.web.XWikiURLFactoryServiceImpl;\nimport com.xpn.xwiki.web.includeservletasstring.IncludeServletAsString;\n\npublic class XWiki implements EventListener\n{\n /** Name of the default wiki. */\n public static final String DEFAULT_MAIN_WIKI = \"xwiki\";\n\n /** Name of the default home space. */\n public static final String DEFAULT_HOME_SPACE = \"Main\";\n\n /** Name of the default system space. */\n public static final String SYSTEM_SPACE = \"XWiki\";\n\n /** Name of the default space homepage. */\n public static final String DEFAULT_SPACE_HOMEPAGE = \"WebHome\";\n\n /** Logging helper object. */\n protected static final Logger LOGGER = LoggerFactory.getLogger(XWiki.class);\n\n /** Frequently used Document reference, the class which holds virtual wiki definitions. */\n private static final DocumentReference VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE = new DocumentReference(\n DEFAULT_MAIN_WIKI, SYSTEM_SPACE, \"XWikiServerClass\");\n\n /** The default encoding, and the internally used encoding when dealing with byte representation of strings. */\n public static final String DEFAULT_ENCODING = \"UTF-8\";\n\n /** XWiki configuration loaded from xwiki.cfg. */\n private XWikiConfig config;\n\n /** The main document storage. */\n private XWikiStoreInterface store;\n\n /** The attachment storage (excluding attachment history). */\n private XWikiAttachmentStoreInterface attachmentStore;\n\n /** Store for attachment archives. */\n private AttachmentVersioningStore attachmentVersioningStore;\n\n /** Document versioning storage. */\n private XWikiVersioningStoreInterface versioningStore;\n\n /** Deleted documents storage. */\n private XWikiRecycleBinStoreInterface recycleBinStore;\n\n /**\n * Storage for deleted attachment.\n * \n * @since 1.4M1\n */\n private AttachmentRecycleBinStore attachmentRecycleBinStore;\n\n private XWikiRenderingEngine renderingEngine;\n\n private XWikiPluginManager pluginManager;\n\n private XWikiAuthService authService;\n\n private XWikiRightService rightService;\n\n private XWikiGroupService groupService;\n\n private XWikiStatsService statsService;\n\n private XWikiURLFactoryService urlFactoryService;\n\n private XWikiCriteriaService criteriaService;\n\n /** Lock object used for the lazy initialization of the authentication service. */\n private final Object AUTH_SERVICE_LOCK = new Object();\n\n /** Lock object used for the lazy initialization of the authorization service. */\n private final Object RIGHT_SERVICE_LOCK = new Object();\n\n /** Lock object used for the lazy initialization of the group management service. */\n private final Object GROUP_SERVICE_LOCK = new Object();\n\n /** Lock object used for the lazy initialization of the statistics service. */\n private final Object STATS_SERVICE_LOCK = new Object();\n\n /** Lock object used for the lazy initialization of the URL Factory service. */\n private final Object URLFACTORY_SERVICE_LOCK = new Object();\n\n private MetaClass metaclass = MetaClass.getMetaClass();\n\n /** Is the wiki running in test mode? Deprecated, was used when running Cactus tests. */\n private boolean test = false;\n\n private String version = null;\n\n private XWikiEngineContext engine_context;\n\n private String database;\n\n private String fullNameSQL;\n\n private URLPatternMatcher urlPatternMatcher = new URLPatternMatcher();\n\n // These are caches in order to improve finding virtual wikis\n private List virtualWikiList = new ArrayList();\n\n /**\n * The cache containing the names of the wikis already initialized.\n */\n private Cache virtualWikiMap;\n\n private boolean isReadOnly = false;\n\n public static final String CFG_ENV_NAME = \"XWikiConfig\";\n\n public static final String MACROS_FILE = \"/templates/macros.txt\";\n\n /**\n * File containing XWiki's version, in the format: ..\n */\n private static final String VERSION_FILE = \"/WEB-INF/version.properties\";\n\n /**\n * Property containing the version value in the {@link #VERSION_FILE} file.\n */\n private static final String VERSION_FILE_PROPERTY = \"version\";\n\n /*\n * i don't like using static variables like, but this avoid making a JNDI lookup with each request ...\n */\n private static String configPath = null;\n\n /*\n * Work directory\n */\n private static File workDir = null;\n\n /*\n * Temp directory\n */\n private static File tempDir = null;\n\n /**\n * List of configured syntax ids.\n */\n private List configuredSyntaxes;\n\n /**\n * Used to convert a proper Document Reference to string (standard form).\n */\n private EntityReferenceSerializer defaultEntityReferenceSerializer = Utils\n .getComponent(EntityReferenceSerializer.TYPE_STRING);\n\n private EntityReferenceSerializer localStringEntityReferenceSerializer = Utils.getComponent(\n EntityReferenceSerializer.TYPE_STRING, \"local\");\n\n private EntityReferenceValueProvider defaultEntityReferenceValueProvider = Utils\n .getComponent((Type) EntityReferenceValueProvider.class);\n\n private EntityReferenceSerializer localReferenceEntityReferenceSerializer = Utils.getComponent(\n EntityReferenceSerializer.TYPE_REFERENCE, \"local\");\n\n /**\n * Used to resolve a string into a proper Document Reference using the current document's reference to fill the\n * blanks, except for the page name for which the default page name is used instead.\n */\n private DocumentReferenceResolver currentMixedDocumentReferenceResolver = Utils.getComponent(\n DocumentReferenceResolver.TYPE_STRING, \"currentmixed\");\n\n private EntityReferenceResolver relativeEntityReferenceResolver = Utils.getComponent(\n EntityReferenceResolver.TYPE_STRING, \"relative\");\n\n private SyntaxFactory syntaxFactory = Utils.getComponent((Type) SyntaxFactory.class);\n\n private XWikiURLBuilder entityXWikiURLBuilder = Utils.getComponent((Type) XWikiURLBuilder.class, \"entity\");\n\n /**\n * Whether backlinks are enabled or not (cached for performance).\n * \n * @since 3.2M2\n */\n private Boolean hasBacklinks;\n\n public static String getConfigPath() throws NamingException\n {\n if (configPath == null) {\n try {\n Context envContext = (Context) new InitialContext().lookup(\"java:comp/env\");\n configPath = (String) envContext.lookup(CFG_ENV_NAME);\n } catch (Exception e) {\n configPath = \"/WEB-INF/xwiki.cfg\";\n LOGGER.debug(\"The xwiki.cfg file will be read from [\" + configPath + \"] because \"\n + \"its location couldn't be read from the JNDI [\" + CFG_ENV_NAME + \"] \"\n + \"variable in [java:comp/env].\");\n }\n }\n\n return configPath;\n }\n\n public static XWiki getMainXWiki(XWikiContext context) throws XWikiException\n {\n String xwikiname = DEFAULT_MAIN_WIKI;\n XWiki xwiki;\n XWikiEngineContext econtext = context.getEngineContext();\n\n context.setMainXWiki(xwikiname);\n\n try {\n xwiki = (XWiki) econtext.getAttribute(xwikiname);\n if (xwiki == null) {\n synchronized (XWiki.class) {\n xwiki = (XWiki) econtext.getAttribute(xwikiname);\n if (xwiki == null) {\n InputStream xwikicfgis = XWiki.readXWikiConfiguration(getConfigPath(), econtext, context);\n xwiki = new XWiki(xwikicfgis, context, context.getEngineContext());\n econtext.setAttribute(xwikiname, xwiki);\n }\n }\n\n context.setWiki(xwiki);\n\n // initialize stub context here instead of during Execution context initialization because during\n // Execution context initialization, the XWikiContext is not fully initialized (does not contains XWiki\n // object) which make it unusable\n Utils. getComponent((Type) XWikiStubContextProvider.class)\n .initialize(context);\n } else {\n context.setWiki(xwiki);\n }\n\n return xwiki;\n } catch (Exception e) {\n throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_INIT_FAILED,\n \"Could not initialize main XWiki context\", e);\n }\n }\n\n /**\n * First try to find the configuration file pointed by the passed location as a file. If it does not exist or if the\n * file cannot be read (for example if the security manager doesn't allow it), then try to load the file as a\n * resource using the Servlet Context and failing that from teh classpath.\n * \n * @param configurationLocation the location where the XWiki configuration file is located (either an absolute or\n * relative file path or a resource location)\n * @return the stream containing the configuration data or null if not found\n * @todo this code should be moved to a Configuration class proper\n */\n private static InputStream readXWikiConfiguration(String configurationLocation, XWikiEngineContext econtext,\n XWikiContext context)\n {\n InputStream xwikicfgis = null;\n\n // First try loading from a file.\n File f = new File(configurationLocation);\n try {\n if (f.exists()) {\n xwikicfgis = new FileInputStream(f);\n }\n } catch (Exception e) {\n // Error loading the file. Most likely, the Security Manager prevented it.\n // We'll try loading it as a resource below.\n LOGGER.debug(\"Failed to load the file [\" + configurationLocation + \"] using direct \"\n + \"file access. The error was [\" + e.getMessage() + \"]. Trying to load it \"\n + \"as a resource using the Servlet Context...\");\n }\n // Second, try loading it as a resource using the Servlet Context\n if (xwikicfgis == null) {\n xwikicfgis = econtext.getResourceAsStream(configurationLocation);\n LOGGER.debug(\"Failed to load the file [\" + configurationLocation + \"] as a resource \"\n + \"using the Servlet Context. Trying to load it as classpath resource...\");\n }\n\n // Third, try loading it from the classloader used to load this current class\n if (xwikicfgis == null) {\n // TODO: Verify if checking on MODE_GWT is correct. I think we should only check for\n // the debug mode and even for that we need to find some better way of doing it so\n // that we don't have hardcoded code only for development debugging purposes.\n if (context.getMode() == XWikiContext.MODE_GWT || context.getMode() == XWikiContext.MODE_GWT_DEBUG) {\n xwikicfgis = XWiki.class.getClassLoader().getResourceAsStream(\"xwiki-gwt.cfg\");\n } else {\n xwikicfgis = XWiki.class.getClassLoader().getResourceAsStream(\"xwiki.cfg\");\n }\n }\n\n LOGGER.debug(\"Failed to load the file [\" + configurationLocation + \"] using any method.\");\n\n // TODO: Should throw an exception instead of return null...\n\n return xwikicfgis;\n }\n\n /**\n * Return the XWiki object (as in \"the Wiki API\") corresponding to the requested wiki.\n * \n * @param context the current context\n * @return an XWiki object configured for the wiki corresponding to the current request\n * @throws XWikiException if the requested URL does not correspond to a real wiki, or if there's an error in the\n * storage\n */\n public static XWiki getXWiki(XWikiContext context) throws XWikiException\n {\n XWiki xwiki = getMainXWiki(context);\n if (!xwiki.isVirtualMode()) {\n return xwiki;\n }\n\n // Host is full.host.name in DNS-based multiwiki, and wikiname in path-based multiwiki.\n String host = \"\";\n // Canonical name of the wiki (database)\n String wikiName = \"\";\n // wikiDefinition should be the document holding the definition of the virtual wiki, a document in the main\n // wiki with a XWiki.XWikiServerClass object attached to it\n DocumentReference wikiDefinition;\n\n XWikiRequest request = context.getRequest();\n try {\n URL requestURL = context.getURL();\n host = requestURL.getHost();\n } catch (Exception e) {\n }\n\n // In path-based multi-wiki, the wiki name is an element of the request path.\n // The url is in the form /xwiki (app name)/wiki (servlet name)/wikiname/\n if (\"1\".equals(xwiki.Param(\"xwiki.virtual.usepath\", \"1\"))) {\n String uri = request.getRequestURI();\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Request uri is: \" + uri);\n }\n // Remove the (eventual) context path from the URI, usually /xwiki\n uri = stripSegmentFromPath(uri, request.getContextPath());\n // Remove the (eventual) servlet path from the URI, usually /wiki\n String servletPath = request.getServletPath();\n uri = stripSegmentFromPath(uri, servletPath);\n\n if (servletPath.equals(\"/\" + xwiki.Param(\"xwiki.virtual.usepath.servletpath\", \"wiki\"))) {\n // Requested path corresponds to a path-based wiki, now the wiki name is between the first and\n // second \"/\"\n host = StringUtils.substringBefore(StringUtils.removeStart(uri, \"/\"), \"/\");\n }\n }\n\n if (StringUtils.isEmpty(host) || host.equals(context.getMainXWiki())) {\n // Can't find any wiki name, return the main wiki\n return xwiki;\n }\n\n wikiDefinition = xwiki.findWikiServer(host, context);\n\n if (wikiDefinition == null) {\n // No definition found based on the full domain name/path wiki name, try to use the first part of the domain\n // name as the wiki name\n String servername = StringUtils.substringBefore(host, \".\");\n\n // As a convenience, allow sites starting with www, localhost or using an\n // IP address not to have to create a XWikiServerXwiki page since we consider\n // in that case that they're pointing to the main wiki.\n if (!\"0\".equals(xwiki.Param(\"xwiki.virtual.autowww\"))\n && (servername.equals(\"www\") || host.equals(\"localhost\") || host\n .matches(\"[0-9]{1,3}(?:\\\\.[0-9]{1,3}){3}\"))) {\n return xwiki;\n }\n\n wikiDefinition =\n new DocumentReference(DEFAULT_MAIN_WIKI, SYSTEM_SPACE, \"XWikiServer\"\n + StringUtils.capitalize(servername));\n }\n\n // Check if this wiki definition exists in the Database\n XWikiDocument doc = xwiki.getDocument(wikiDefinition, context);\n if (doc.isNew()) {\n throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_DOES_NOT_EXIST,\n \"The wiki \" + host + \" does not exist\");\n }\n\n // Set the wiki owner\n String wikiOwner = doc.getStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, \"owner\");\n if (wikiOwner.indexOf(':') == -1) {\n wikiOwner = xwiki.getDatabase() + \":\" + wikiOwner;\n }\n context.setWikiOwner(wikiOwner);\n context.setWikiServer(doc);\n\n wikiName = StringUtils.removeStart(wikiDefinition.getName(), \"XWikiServer\").toLowerCase();\n context.setDatabase(wikiName);\n context.setOriginalDatabase(wikiName);\n\n try {\n // Let's make sure the virtual wikis are upgraded to the latest database version\n xwiki.updateDatabase(wikiName, false, context);\n } catch (HibernateException ex) {\n // Just report it, hopefully the database is in a good enough state\n LOGGER.error(\"Failed to upgrade database: \" + wikiName, ex);\n }\n return xwiki;\n }\n\n public static URL getRequestURL(XWikiRequest request) throws XWikiException\n {\n try {\n StringBuffer requestURL = request.getRequestURL();\n String qs = request.getQueryString();\n if ((qs != null) && (!qs.equals(\"\"))) {\n return new URL(requestURL.toString() + \"?\" + qs);\n } else {\n return new URL(requestURL.toString());\n }\n } catch (Exception e) {\n throw new XWikiException(XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_URL_EXCEPTION,\n \"Exception while getting URL from request\", e);\n }\n }\n\n public static Object callPrivateMethod(Object obj, String methodName)\n {\n return callPrivateMethod(obj, methodName, null, null);\n }\n\n public static Object callPrivateMethod(Object obj, String methodName, Class< ? >[] classes, Object[] args)\n {\n try {\n Method method = obj.getClass().getDeclaredMethod(methodName, classes);\n method.setAccessible(true);\n return method.invoke(obj, args);\n } catch (IllegalAccessException e) {\n e.printStackTrace();\n return null;\n } catch (NoSuchMethodException e) {\n return null;\n } catch (InvocationTargetException e) {\n e.printStackTrace();\n return null;\n }\n }\n\n public static HttpClient getHttpClient(int timeout, String userAgent)\n {\n HttpClient client = new HttpClient();\n\n if (timeout != 0) {\n client.getParams().setSoTimeout(timeout);\n client.getParams().setParameter(\"http.connection.timeout\", Integer.valueOf(timeout));\n }\n\n client.getParams().setParameter(\"http.useragent\", userAgent);\n\n String proxyHost = System.getProperty(\"http.proxyHost\");\n String proxyPort = System.getProperty(\"http.proxyPort\");\n if ((proxyHost != null) && (!proxyHost.equals(\"\"))) {\n int port = 3128;\n if ((proxyPort != null) && (!proxyPort.equals(\"\"))) {\n port = Integer.parseInt(proxyPort);\n }\n client.getHostConfiguration().setProxy(proxyHost, port);\n }\n\n String proxyUser = System.getProperty(\"http.proxyUser\");\n if ((proxyUser != null) && (!proxyUser.equals(\"\"))) {\n String proxyPassword = System.getProperty(\"http.proxyPassword\");\n Credentials defaultcreds = new UsernamePasswordCredentials(proxyUser, proxyPassword);\n client.getState().setProxyCredentials(AuthScope.ANY, defaultcreds);\n }\n\n return client;\n }\n\n public static Object getPrivateField(Object obj, String fieldName)\n {\n try {\n Field field = obj.getClass().getDeclaredField(fieldName);\n field.setAccessible(true);\n return field.get(obj);\n } catch (NoSuchFieldException e) {\n return null;\n } catch (IllegalAccessException e) {\n e.printStackTrace();\n return null;\n } finally {\n }\n }\n\n public static String getServerWikiPage(String servername)\n {\n return \"XWiki.XWikiServer\" + StringUtils.capitalize(servername);\n }\n\n public static String getTextArea(String content, XWikiContext context)\n {\n StringBuilder result = new StringBuilder();\n\n // Forcing a new line after the \");\n\n return result.toString();\n }\n\n /**\n * This provide a way to create an XWiki object without initializing the whole XWiki (including plugins, storage,\n * etc.).\n *

\n * Needed for tools or tests which need XWiki because it is used everywhere in the API.\n *

\n */\n public XWiki()\n {\n\n }\n\n public XWiki(XWikiConfig config, XWikiContext context) throws XWikiException\n {\n this(config, context, null, false);\n }\n\n public XWiki(XWikiConfig config, XWikiContext context, XWikiEngineContext engine_context, boolean noupdate)\n throws XWikiException\n {\n initXWiki(config, context, engine_context, noupdate);\n }\n\n /**\n * @deprecated use {@link #XWiki(XWikiConfig, XWikiContext)} instead\n */\n @Deprecated\n public XWiki(String xwikicfgpath, XWikiContext context) throws XWikiException\n {\n this(xwikicfgpath, context, null, false);\n }\n\n /**\n * @deprecated use {@link #XWiki(XWikiConfig, XWikiContext, XWikiEngineContext, boolean)} instead\n */\n @Deprecated\n public XWiki(String xwikicfgpath, XWikiContext context, XWikiEngineContext engine_context, boolean noupdate)\n throws XWikiException\n {\n try {\n initXWiki(new XWikiConfig(new FileInputStream(xwikicfgpath)), context, engine_context, noupdate);\n } catch (FileNotFoundException e) {\n Object[] args = {xwikicfgpath};\n throw new XWikiException(XWikiException.MODULE_XWIKI_CONFIG,\n XWikiException.ERROR_XWIKI_CONFIG_FILENOTFOUND, \"Configuration file {0} not found\", e, args);\n }\n }\n\n /**\n * @deprecated use {@link #XWiki(XWikiConfig, XWikiContext, XWikiEngineContext, boolean)} instead\n */\n @Deprecated\n public XWiki(InputStream is, XWikiContext context, XWikiEngineContext engine_context) throws XWikiException\n {\n initXWiki(new XWikiConfig(is), context, engine_context, true);\n }\n\n /**\n * Initialize all xwiki subsystems.\n */\n public void initXWiki(XWikiConfig config, XWikiContext context, XWikiEngineContext engine_context, boolean noupdate)\n throws XWikiException\n {\n setDatabase(context.getMainXWiki());\n\n setEngineContext(engine_context);\n context.setWiki(this);\n\n // Prepare the store\n setConfig(config);\n\n XWikiStoreInterface basestore =\n Utils.getComponent(XWikiStoreInterface.class, Param(\"xwiki.store.main.hint\", \"hibernate\"));\n\n // Check if we need to use the cache store..\n boolean nocache = \"0\".equals(Param(\"xwiki.store.cache\", \"1\"));\n if (!nocache) {\n XWikiCacheStoreInterface cachestore = new XWikiCacheStore(basestore, context);\n setStore(cachestore);\n } else {\n setStore(basestore);\n }\n\n setCriteriaService((XWikiCriteriaService) createClassFromConfig(\"xwiki.criteria.class\",\n \"com.xpn.xwiki.criteria.impl.XWikiCriteriaServiceImpl\", context));\n\n setAttachmentStore(Utils. getComponent(\n (Type) XWikiAttachmentStoreInterface.class, Param(\"xwiki.store.attachment.hint\", \"hibernate\")));\n\n setVersioningStore(Utils. getComponent(\n (Type) XWikiVersioningStoreInterface.class, Param(\"xwiki.store.versioning.hint\", \"hibernate\")));\n\n setAttachmentVersioningStore(Utils. getComponent(\n (Type) AttachmentVersioningStore.class,\n hasAttachmentVersioning(context) ? Param(\"xwiki.store.attachment.versioning.hint\", \"hibernate\") : \"void\"));\n\n if (hasRecycleBin(context)) {\n setRecycleBinStore(Utils. getComponent(\n (Type) XWikiRecycleBinStoreInterface.class, Param(\"xwiki.store.recyclebin.hint\", \"hibernate\")));\n }\n\n if (hasAttachmentRecycleBin(context)) {\n setAttachmentRecycleBinStore(Utils. getComponent(\n (Type) AttachmentRecycleBinStore.class, Param(\"xwiki.store.attachment.recyclebin.hint\", \"hibernate\")));\n }\n\n resetRenderingEngine(context);\n\n // Prepare the Plugin Engine\n preparePlugins(context);\n\n // Make sure these classes exists\n if (noupdate) {\n initializeMandatoryClasses(context);\n getStatsService(context);\n }\n\n String ro = Param(\"xwiki.readonly\", \"no\");\n this.isReadOnly = (\"yes\".equalsIgnoreCase(ro) || \"true\".equalsIgnoreCase(ro) || \"1\".equalsIgnoreCase(ro));\n\n // Save the configured syntaxes\n String syntaxes = Param(\"xwiki.rendering.syntaxes\", \"xwiki/1.0\");\n this.configuredSyntaxes = Arrays.asList(StringUtils.split(syntaxes, \" ,\"));\n\n // Initialize all wiki macros.\n // TODO: This is only a temporary work around, we need to use a component-based init mechanism instead. Note\n // that we need DB access to be available (at component initialization) to make this possible.\n registerWikiMacros();\n\n Utils. getComponent((Type) ObservationManager.class).addListener(this);\n }\n\n /**\n * Ensure that mandatory classes (ie classes XWiki needs to work properly) exist and create them if they don't\n * exist.\n */\n private void initializeMandatoryClasses(XWikiContext context) throws XWikiException\n {\n getPrefsClass(context);\n getUserClass(context);\n getTagClass(context);\n getGroupClass(context);\n getRightsClass(context);\n getCommentsClass(context);\n getSkinClass(context);\n getGlobalRightsClass(context);\n getSheetClass(context);\n getEditModeClass(context);\n\n try {\n WikiMacroInitializer wikiMacroInitializer =\n Utils.getComponentManager().lookupComponent(WikiMacroInitializer.class);\n wikiMacroInitializer.installOrUpgradeWikiMacroClasses();\n } catch (Exception ex) {\n LOGGER.error(\"Error while installing / upgrading xwiki classes required for wiki macros.\", ex);\n }\n\n if (context.getDatabase().equals(context.getMainXWiki())\n && \"1\".equals(context.getWiki().Param(\"xwiki.preferences.redirect\"))) {\n getRedirectClass(context);\n }\n }\n\n /**\n * TODO: This is only a temporary work around, we need to use a component-based init mechanism instead. Note that we\n * need DB access to be available (at component initialization) to make this possible.\n *

\n * This method is protected to be able to skip it in unit tests.\n */\n protected void registerWikiMacros()\n {\n try {\n WikiMacroInitializer wikiMacroInitializer =\n Utils.getComponentManager().lookupComponent(WikiMacroInitializer.class);\n wikiMacroInitializer.registerExistingWikiMacros();\n } catch (Exception ex) {\n LOGGER.error(\"Error while registering wiki macros.\", ex);\n }\n }\n\n public XWikiStoreInterface getNotCacheStore()\n {\n XWikiStoreInterface store = getStore();\n if (store instanceof XWikiCacheStoreInterface) {\n store = ((XWikiCacheStoreInterface) store).getStore();\n }\n return store;\n }\n\n public XWikiHibernateStore getHibernateStore()\n {\n XWikiStoreInterface store = getStore();\n if (store instanceof XWikiHibernateStore) {\n return (XWikiHibernateStore) store;\n } else if (store instanceof XWikiCacheStoreInterface) {\n store = ((XWikiCacheStoreInterface) store).getStore();\n if (store instanceof XWikiHibernateStore) {\n return (XWikiHibernateStore) store;\n } else {\n return null;\n }\n } else {\n return null;\n }\n }\n\n public void updateDatabase(String wikiName, XWikiContext context) throws HibernateException, XWikiException\n {\n updateDatabase(wikiName, false, context);\n }\n\n public void updateDatabase(String wikiName, boolean force, XWikiContext context) throws HibernateException,\n XWikiException\n {\n updateDatabase(wikiName, force, true, context);\n }\n\n public void updateDatabase(String wikiName, boolean force, boolean initClasses, XWikiContext context)\n throws HibernateException, XWikiException\n {\n String database = context.getDatabase();\n try {\n List wikiList = getVirtualWikiList();\n\n // Make sure the wiki is updated\n if (force) {\n wikiList.remove(wikiName);\n context.remove(\"initdone\");\n }\n\n context.setDatabase(wikiName);\n synchronized (wikiName) {\n if (!wikiList.contains(wikiName)) {\n wikiList.add(wikiName);\n\n // Make sure these classes exists\n if (initClasses) {\n initializeMandatoryClasses(context);\n getPluginManager().virtualInit(context);\n getRenderingEngine().virtualInit(context);\n }\n }\n }\n\n // Add initdone which will allow to\n // bypass some initializations\n context.put(\"initdone\", \"1\");\n } finally {\n context.setDatabase(database);\n }\n }\n\n /**\n * @return a cached list of all active virtual wikis (i.e. wikis who have been hit by a user request). To get a full\n * list of all virtual wikis database names use {@link #getVirtualWikisDatabaseNames(XWikiContext)}.\n */\n public List getVirtualWikiList()\n {\n return this.virtualWikiList;\n }\n\n /**\n * @return the full list of all database names of all defined virtual wikis. The database names are computed from\n * the names of documents having a XWiki.XWikiServerClass object attached to them by removing the\n * \"XWiki.XWikiServer\" prefix and making it lower case. For example a page named\n * \"XWiki.XWikiServerMyDatabase\" would return \"mydatabase\" as the database name.\n */\n public List getVirtualWikisDatabaseNames(XWikiContext context) throws XWikiException\n {\n String database = context.getDatabase();\n try {\n context.setDatabase(context.getMainXWiki());\n\n String query =\n \", BaseObject as obj where doc.space = 'XWiki' and obj.name=doc.fullName\"\n + \" and obj.name <> 'XWiki.XWikiServerClassTemplate' and obj.className='XWiki.XWikiServerClass' \";\n List documents = getStore().searchDocumentReferences(query, context);\n List databaseNames = new ArrayList(documents.size());\n\n int prefixLength = \"XWikiServer\".length();\n for (DocumentReference document : documents) {\n if (document.getName().startsWith(\"XWikiServer\")) {\n databaseNames.add(document.getName().substring(prefixLength).toLowerCase());\n }\n }\n\n return databaseNames;\n } finally {\n context.setDatabase(database);\n }\n }\n\n /**\n * @return the cache containing the names of the wikis already initialized.\n * @since 1.5M2.\n */\n public Cache getVirtualWikiCache()\n {\n return this.virtualWikiMap;\n }\n\n /**\n * Searches for the document containing the definition of the virtual wiki corresponding to the specified hostname.\n * \n * @param host the hostname, as specified in the request (for example: {@code forge.xwiki.org})\n * @param context the current context\n * @return the name of the document containing the wiki definition, or {@code null} if no wiki corresponds to the\n * hostname\n * @throws XWikiException if a problem occurs while searching the storage\n */\n private DocumentReference findWikiServer(String host, XWikiContext context) throws XWikiException\n {\n this.ensureVirtualWikiMapExists();\n DocumentReference wikiName = this.virtualWikiMap.get(host);\n\n if (wikiName == null) {\n // Not loaded yet, search for it in the main wiki\n String hql =\n \", BaseObject as obj, StringProperty as prop WHERE obj.name=doc.fullName\"\n + \" AND doc.space='XWiki' AND doc.name LIKE 'XWikiServer%'\"\n + \" AND obj.className='XWiki.XWikiServerClass' AND prop.id.id = obj.id\"\n + \" AND prop.id.name = 'server' AND prop.value=?\";\n List parameters = new ArrayList(1);\n parameters.add(host);\n try {\n List list =\n context.getWiki().getStore().searchDocumentReferences(hql, parameters, context);\n if ((list != null) && (list.size() > 0)) {\n wikiName = list.get(0);\n }\n\n this.virtualWikiMap.set(host, wikiName);\n } catch (XWikiException e) {\n LOGGER.warn(\"Error when searching for wiki name from URL host [\" + host + \"]\", e);\n }\n }\n\n return wikiName;\n }\n\n private void ensureVirtualWikiMapExists() throws XWikiException\n {\n synchronized (this) {\n if (this.virtualWikiMap == null) {\n int iCapacity = 1000;\n try {\n String capacity = Param(\"xwiki.virtual.cache.capacity\");\n if (capacity != null) {\n iCapacity = Integer.parseInt(capacity);\n }\n } catch (Exception e) {\n }\n try {\n CacheConfiguration configuration = new CacheConfiguration();\n configuration.setConfigurationId(\"xwiki.virtualwikimap\");\n LRUEvictionConfiguration lru = new LRUEvictionConfiguration();\n lru.setMaxEntries(iCapacity);\n configuration.put(LRUEvictionConfiguration.CONFIGURATIONID, lru);\n\n this.virtualWikiMap = getCacheFactory().newCache(configuration);\n } catch (CacheException e) {\n throw new XWikiException(XWikiException.MODULE_XWIKI_CACHE,\n XWikiException.ERROR_CACHE_INITIALIZING, \"Failed to create new cache\", e);\n }\n }\n }\n }\n\n public String getWikiOwner(String servername, XWikiContext context) throws XWikiException\n {\n String wikiOwner = context.getWikiOwner();\n\n if (!context.isMainWiki(servername)) {\n String serverwikipage = getServerWikiPage(servername);\n\n String currentdatabase = context.getDatabase();\n\n try {\n context.setDatabase(context.getMainXWiki());\n\n XWikiDocument doc = getDocument(serverwikipage, context);\n\n if (doc.isNew()) {\n throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_DOES_NOT_EXIST,\n \"The wiki \" + servername + \" does not exist\");\n }\n\n wikiOwner = doc.getStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, \"owner\");\n if (wikiOwner.indexOf(':') == -1) {\n wikiOwner = context.getMainXWiki() + \":\" + wikiOwner;\n }\n } finally {\n context.setDatabase(currentdatabase);\n }\n }\n\n return wikiOwner;\n }\n\n protected Object createClassFromConfig(String param, String defClass, XWikiContext context) throws XWikiException\n {\n String storeclass = Param(param, defClass);\n try {\n Class< ? >[] classes = new Class< ? >[] {XWikiContext.class};\n Object[] args = new Object[] {context};\n Object result = Class.forName(storeclass).getConstructor(classes).newInstance(args);\n return result;\n } catch (Exception e) {\n Throwable ecause = e;\n if (e instanceof InvocationTargetException) {\n ecause = ((InvocationTargetException) e).getTargetException();\n }\n Object[] args = {param, storeclass};\n throw new XWikiException(XWikiException.MODULE_XWIKI_STORE,\n XWikiException.ERROR_XWIKI_STORE_CLASSINVOCATIONERROR, \"Cannot load class {1} from param {0}\", ecause,\n args);\n }\n }\n\n public void resetRenderingEngine(XWikiContext context) throws XWikiException\n {\n // Prepare the Rendering Engine\n setRenderingEngine(new DefaultXWikiRenderingEngine(this, context));\n }\n\n private void preparePlugins(XWikiContext context)\n {\n setPluginManager(new XWikiPluginManager(getXWikiPreference(\"plugins\", context), context));\n String plugins = Param(\"xwiki.plugins\", \"\");\n if (!plugins.equals(\"\")) {\n getPluginManager().addPlugins(StringUtils.split(plugins, \" ,\"), context);\n }\n }\n\n /**\n * @return the XWiki core version as specified in the {@link #VERSION_FILE} file\n */\n public String getVersion()\n {\n if (this.version == null) {\n try {\n InputStream is = getResourceAsStream(VERSION_FILE);\n XWikiConfig properties = new XWikiConfig(is);\n this.version = properties.getProperty(VERSION_FILE_PROPERTY);\n } catch (Exception e) {\n // Failed to retrieve the version, log a warning and default to \"Unknown\"\n LOGGER.warn(\"Failed to retrieve XWiki's version from [\" + VERSION_FILE + \"], using the [\"\n + VERSION_FILE_PROPERTY + \"] property.\", e);\n this.version = \"Unknown version\";\n }\n }\n return this.version;\n }\n\n public URL getResource(String s) throws MalformedURLException\n {\n return getEngineContext().getResource(s);\n }\n\n public InputStream getResourceAsStream(String s) throws MalformedURLException\n {\n InputStream is = getEngineContext().getResourceAsStream(s);\n if (is == null) {\n is = getEngineContext().getResourceAsStream(\"/\" + s);\n }\n return is;\n }\n\n public String getResourceContent(String name) throws IOException\n {\n InputStream is = null;\n if (getEngineContext() != null) {\n\n try {\n is = getResourceAsStream(name);\n } catch (Exception e) {\n }\n }\n\n if (is == null) {\n // Resources should always be encoded as UTF-8, to reduce the dependency on the system encoding\n return FileUtils.readFileToString(new File(name), DEFAULT_ENCODING);\n }\n\n return IOUtils.toString(is, DEFAULT_ENCODING);\n }\n\n public Date getResourceLastModificationDate(String name)\n {\n try {\n if (getEngineContext() != null) {\n return Util.getFileLastModificationDate(getEngineContext().getRealPath(name));\n }\n } catch (Exception ex) {\n // Probably a SecurityException or the file is not accessible (inside a war)\n LOGGER.info(\"Failed to get file modification date: \" + ex.getMessage());\n }\n return new Date();\n }\n\n public byte[] getResourceContentAsBytes(String name) throws IOException\n {\n InputStream is = null;\n if (getEngineContext() != null) {\n\n try {\n is = getResourceAsStream(name);\n } catch (Exception e) {\n }\n }\n\n if (is == null) {\n return FileUtils.readFileToByteArray(new File(name));\n }\n\n return IOUtils.toByteArray(is);\n }\n\n public boolean resourceExists(String name)\n {\n if (getEngineContext() != null) {\n try {\n if (getResource(name) != null) {\n return true;\n }\n } catch (IOException e) {\n }\n }\n try {\n File file = new File(name);\n return file.exists();\n } catch (Exception e) {\n // Could be running under -security, which prevents calling file.exists().\n }\n return false;\n }\n\n public XWikiConfig getConfig()\n {\n return this.config;\n }\n\n public String getRealPath(String path)\n {\n return getEngineContext().getRealPath(path);\n }\n\n public String Param(String key)\n {\n return Param(key, null);\n }\n\n public String ParamAsRealPath(String key)\n {\n String param = Param(key);\n try {\n return getRealPath(param);\n } catch (Exception e) {\n return param;\n }\n }\n\n public String ParamAsRealPath(String key, XWikiContext context)\n {\n return ParamAsRealPath(key);\n }\n\n public String ParamAsRealPathVerified(String param)\n {\n String path;\n File fpath;\n\n path = Param(param);\n if (path == null) {\n return null;\n }\n\n fpath = new File(path);\n if (fpath.exists()) {\n return path;\n }\n\n path = getRealPath(path);\n if (path == null) {\n return null;\n }\n\n fpath = new File(path);\n if (fpath.exists()) {\n return path;\n } else {\n }\n return null;\n }\n\n public String Param(String key, String default_value)\n {\n if (getConfig() != null) {\n return getConfig().getProperty(key, default_value);\n }\n return default_value;\n }\n\n public long ParamAsLong(String key)\n {\n String param = Param(key);\n return Long.parseLong(param);\n }\n\n public long ParamAsLong(String key, long default_value)\n {\n try {\n return ParamAsLong(key);\n } catch (NumberFormatException e) {\n return default_value;\n }\n }\n\n public XWikiStoreInterface getStore()\n {\n return this.store;\n }\n\n public XWikiAttachmentStoreInterface getAttachmentStore()\n {\n return this.attachmentStore;\n }\n\n public AttachmentVersioningStore getAttachmentVersioningStore()\n {\n return this.attachmentVersioningStore;\n }\n\n public XWikiVersioningStoreInterface getVersioningStore()\n {\n return this.versioningStore;\n }\n\n public XWikiRecycleBinStoreInterface getRecycleBinStore()\n {\n return this.recycleBinStore;\n }\n\n public AttachmentRecycleBinStore getAttachmentRecycleBinStore()\n {\n return this.attachmentRecycleBinStore;\n }\n\n public void saveDocument(XWikiDocument doc, XWikiContext context) throws XWikiException\n {\n // If no comment is provided we should use an empty comment\n saveDocument(doc, \"\", context);\n }\n\n public void saveDocument(XWikiDocument doc, String comment, XWikiContext context) throws XWikiException\n {\n saveDocument(doc, comment, false, context);\n }\n\n public void saveDocument(XWikiDocument doc, String comment, boolean isMinorEdit, XWikiContext context)\n throws XWikiException\n {\n String server = null, database = null;\n try {\n server = doc.getDocumentReference().getWikiReference().getName();\n\n if (server != null) {\n database = context.getDatabase();\n context.setDatabase(server);\n }\n\n // Setting comment & minor edit before saving\n doc.setComment(StringUtils.defaultString(comment));\n doc.setMinorEdit(isMinorEdit);\n\n // We need to save the original document since saveXWikiDoc() will reset it and we\n // need that original document for the notification below.\n XWikiDocument originalDocument = doc.getOriginalDocument();\n // Always use an originalDocument, to provide a consistent behavior. The cases where\n // originalDocument is null are rare (specifically when the XWikiDocument object is\n // manually constructed, and not obtained using the API).\n if (originalDocument == null) {\n originalDocument = new XWikiDocument(doc.getDocumentReference());\n }\n\n ObservationManager om = Utils.getComponent((Type) ObservationManager.class);\n\n // Notify listeners about the document about to be created or updated\n\n // Note that for the moment the event being send is a bridge event, as we are still passing around\n // an XWikiDocument as source and an XWikiContext as data.\n\n if (om != null) {\n if (originalDocument.isNew()) {\n om.notify(new DocumentCreatingEvent(doc.getDocumentReference()), doc, context);\n } else {\n om.notify(new DocumentUpdatingEvent(doc.getDocumentReference()), doc, context);\n }\n }\n\n getStore().saveXWikiDoc(doc, context);\n\n // Since the store#saveXWikiDoc resets originalDocument, we need to temporarily put it\n // back to send notifications.\n XWikiDocument newOriginal = doc.getOriginalDocument();\n\n try {\n doc.setOriginalDocument(originalDocument);\n\n // Notify listeners about the document having been created or updated\n\n // First the legacy notification mechanism\n\n // Then the new observation module\n // Note that for the moment the event being send is a bridge event, as we are still passing around\n // an XWikiDocument as source and an XWikiContext as data.\n // The old version is made available using doc.getOriginalDocument()\n\n if (om != null) {\n if (originalDocument.isNew()) {\n om.notify(new DocumentCreatedEvent(doc.getDocumentReference()), doc, context);\n } else {\n om.notify(new DocumentUpdatedEvent(doc.getDocumentReference()), doc, context);\n }\n }\n } catch (Exception ex) {\n LOGGER.error(\"Failed to send document save notification for document [\"\n + this.defaultEntityReferenceSerializer.serialize(doc.getDocumentReference()) + \"]\", ex);\n } finally {\n doc.setOriginalDocument(newOriginal);\n }\n } finally {\n if ((server != null) && (database != null)) {\n context.setDatabase(database);\n }\n }\n }\n\n public XWikiDocument getDocument(XWikiDocument doc, XWikiContext context) throws XWikiException\n {\n String database = context.getDatabase();\n try {\n if (doc.getDocumentReference().getWikiReference().getName() != null) {\n context.setDatabase(doc.getDocumentReference().getWikiReference().getName());\n }\n\n return getStore().loadXWikiDoc(doc, context);\n } finally {\n context.setDatabase(database);\n }\n }\n\n public XWikiDocument getDocument(XWikiDocument doc, String revision, XWikiContext context) throws XWikiException\n {\n XWikiDocument newdoc;\n\n String database = context.getDatabase();\n try {\n if (doc.getDocumentReference().getWikiReference().getName() != null) {\n context.setDatabase(doc.getDocumentReference().getWikiReference().getName());\n }\n\n if ((revision == null) || revision.equals(\"\")) {\n newdoc = new XWikiDocument(doc.getDocumentReference());\n } else if (revision.equals(doc.getVersion())) {\n newdoc = doc;\n } else {\n newdoc = getVersioningStore().loadXWikiDoc(doc, revision, context);\n }\n } catch (XWikiException e) {\n if (revision.equals(\"1.1\") || revision.equals(\"1.0\")) {\n newdoc = new XWikiDocument(doc.getDocumentReference());\n } else {\n throw e;\n }\n } finally {\n context.setDatabase(database);\n }\n\n return newdoc;\n }\n\n /**\n * @since 2.2M1\n */\n public XWikiDocument getDocument(DocumentReference reference, XWikiContext context) throws XWikiException\n {\n XWikiDocument doc = new XWikiDocument(reference);\n doc.setContentDirty(true);\n return getDocument(doc, context);\n }\n\n /**\n * @deprecated since 2.2M1 use {@link #getDocument(DocumentReference, XWikiContext)} instead\n */\n @Deprecated\n public XWikiDocument getDocument(String fullname, XWikiContext context) throws XWikiException\n {\n XWikiDocument doc = new XWikiDocument();\n doc.setFullName(fullname, context);\n return getDocument(doc, context);\n }\n\n /**\n * @deprecated since 2.2M1 use {@link #getDocument(DocumentReference, XWikiContext)} instead\n */\n @Deprecated\n public XWikiDocument getDocument(String space, String fullname, XWikiContext context) throws XWikiException\n {\n int dotPosition = fullname.lastIndexOf('.');\n if (dotPosition != -1) {\n String spaceFromFullname = fullname.substring(0, dotPosition);\n String name = fullname.substring(dotPosition + 1);\n if (name.equals(\"\")) {\n name = getDefaultPage(context);\n }\n return getDocument(spaceFromFullname + \".\" + name, context);\n } else {\n return getDocument(space + \".\" + fullname, context);\n }\n }\n\n public XWikiDocument getDocumentFromPath(String path, XWikiContext context) throws XWikiException\n {\n return getDocument(getDocumentReferenceFromPath(path, context), context);\n }\n\n /**\n * @since 2.3M1\n */\n public DocumentReference getDocumentReferenceFromPath(String path, XWikiContext context)\n {\n // TODO: Remove this and use XWikiURLFactory instead in XWikiAction and all entry points.\n List segments = new ArrayList();\n for (String segment : path.split(\"/\", -1)) {\n segments.add(Util.decodeURI(segment, context));\n }\n // Remove the first segment if it's empty to cater for cases when the path starts with \"/\"\n if (segments.size() > 0 && segments.get(0).length() == 0) {\n segments.remove(0);\n }\n\n XWikiEntityURL entityURL =\n (XWikiEntityURL) this.entityXWikiURLBuilder.build(new WikiReference(context.getDatabase()), segments);\n\n return new DocumentReference(entityURL.getEntityReference().extractReference(EntityType.DOCUMENT));\n }\n\n /**\n * @deprecated since 2.3M1 use {@link #getDocumentReferenceFromPath(String, XWikiContext)} instead\n */\n @Deprecated\n public String getDocumentNameFromPath(String path, XWikiContext context)\n {\n return this.localStringEntityReferenceSerializer.serialize(getDocumentReferenceFromPath(path, context));\n }\n\n /**\n * @see com.xpn.xwiki.api.XWiki#getDeletedDocuments(String, String)\n */\n public XWikiDeletedDocument[] getDeletedDocuments(String fullname, String lang, XWikiContext context)\n throws XWikiException\n {\n if (hasRecycleBin(context)) {\n XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname));\n doc.setLanguage(lang);\n return getRecycleBinStore().getAllDeletedDocuments(doc, context, true);\n } else {\n return null;\n }\n }\n\n /**\n * @see com.xpn.xwiki.api.XWiki#getDeletedDocument(String, String, String)\n */\n public XWikiDeletedDocument getDeletedDocument(String fullname, String lang, int index, XWikiContext context)\n throws XWikiException\n {\n if (hasRecycleBin(context)) {\n XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname));\n doc.setLanguage(lang);\n return getRecycleBinStore().getDeletedDocument(doc, index, context, true);\n } else {\n return null;\n }\n }\n\n /**\n * Retrieve all the deleted attachments that belonged to a certain document. Note that this does not distinguish\n * between different incarnations of a document name, and it does not require that the document still exists, it\n * returns all the attachments that at the time of their deletion had a document with the specified name as their\n * owner.\n * \n * @param docName the {@link XWikiDocument#getFullName() name} of the owner document\n * @param context the current request context\n * @return A list with all the deleted attachments which belonged to the specified document. If no such attachments\n * are found in the trash, an empty list is returned.\n * @throws XWikiException if an error occurs while loading the attachments\n */\n public List getDeletedAttachments(String docName, XWikiContext context) throws XWikiException\n {\n if (hasAttachmentRecycleBin(context)) {\n XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(docName));\n return getAttachmentRecycleBinStore().getAllDeletedAttachments(doc, context, true);\n }\n return null;\n }\n\n /**\n * Retrieve all the deleted attachments that belonged to a certain document and had the specified name. Multiple\n * versions can be returned since the same file can be uploaded and deleted several times, creating different\n * instances in the trash. Note that this does not distinguish between different incarnations of a document name,\n * and it does not require that the document still exists, it returns all the attachments that at the time of their\n * deletion had a document with the specified name as their owner.\n * \n * @param docName the {@link DeletedAttachment#getDocName() name of the document} the attachment belonged to\n * @param filename the {@link DeletedAttachment#getFilename() name} of the attachment to search for\n * @param context the current request context\n * @return A list with all the deleted attachments which belonged to the specified document and had the specified\n * filename. If no such attachments are found in the trash, an empty list is returned.\n * @throws XWikiException if an error occurs while loading the attachments\n */\n public List getDeletedAttachments(String docName, String filename, XWikiContext context)\n throws XWikiException\n {\n if (hasAttachmentRecycleBin(context)) {\n XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(docName));\n XWikiAttachment attachment = new XWikiAttachment(doc, filename);\n return getAttachmentRecycleBinStore().getAllDeletedAttachments(attachment, context, true);\n }\n return null;\n }\n\n /**\n * Retrieve a specific attachment from the trash.\n * \n * @param id the unique identifier of the entry in the trash\n * @return specified attachment from the trash, {@code null} if not found\n * @throws XWikiException if an error occurs while loading the attachments\n */\n public DeletedAttachment getDeletedAttachment(String id, XWikiContext context) throws XWikiException\n {\n if (hasAttachmentRecycleBin(context)) {\n return getAttachmentRecycleBinStore().getDeletedAttachment(NumberUtils.toLong(id), context, true);\n }\n return null;\n }\n\n public XWikiRenderingEngine getRenderingEngine()\n {\n return this.renderingEngine;\n }\n\n public void setRenderingEngine(XWikiRenderingEngine renderingEngine)\n {\n this.renderingEngine = renderingEngine;\n }\n\n public MetaClass getMetaclass()\n {\n return this.metaclass;\n }\n\n public void setMetaclass(MetaClass metaclass)\n {\n this.metaclass = metaclass;\n }\n\n public List getClassList(XWikiContext context) throws XWikiException\n {\n List result = getStore().getClassList(context);\n Collections.sort(result);\n return result;\n }\n\n /*\n * public String[] getClassList() throws XWikiException { List list = store.getClassList(); String[] array = new\n * String[list.size()]; for (int i=0;i List search(String sql, XWikiContext context) throws XWikiException\n {\n return getStore().search(sql, 0, 0, context);\n }\n\n public List search(String sql, int nb, int start, XWikiContext context) throws XWikiException\n {\n return getStore().search(sql, nb, start, context);\n }\n\n public List search(String sql, Object[][] whereParams, XWikiContext context) throws XWikiException\n {\n return getStore().search(sql, 0, 0, whereParams, context);\n }\n\n public List search(String sql, int nb, int start, Object[][] whereParams, XWikiContext context)\n throws XWikiException\n {\n return getStore().search(sql, nb, start, whereParams, context);\n }\n\n /**\n * Checks if the wiki is running in test mode.\n * \n * @return {@code true} if the wiki is running Cactus tests, {@code false} otherwise\n * @deprecated No longer used.\n */\n @Deprecated\n public boolean isTest()\n {\n return this.test;\n }\n\n /**\n * Marks that the wiki is running in test mode.\n * \n * @param test whether tests are being executed\n * @deprecated No longer used.\n */\n @Deprecated\n public void setTest(boolean test)\n {\n this.test = test;\n }\n\n public String parseContent(String content, XWikiContext context)\n {\n String parsedContent;\n\n if ((content != null) && (!content.equals(\"\"))) {\n parsedContent = context.getWiki().getRenderingEngine().interpretText(content, context.getDoc(), context);\n } else {\n parsedContent = \"\";\n }\n\n return parsedContent;\n }\n\n /**\n * @deprecated use {@link #evaluateTemplate(String, XWikiContext)} instead\n */\n @Deprecated\n public String parseTemplate(String template, XWikiContext context)\n {\n String result = \"\";\n\n try {\n result = evaluateTemplate(template, context);\n } catch (Exception e) {\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Exception while parsing template [\" + template + \"] from /templates/\", e);\n }\n }\n\n return result;\n }\n\n /**\n * Evaluate provided template content using velocity engine.\n * \n * @param template the template to evaluate\n * @param context the XWiki context\n * @return the return of the velocity script\n * @throws IOException failed to get the template content\n * @since 2.2.2\n */\n public String evaluateTemplate(String template, XWikiContext context) throws IOException\n {\n try {\n String skin = getSkin(context);\n String result = parseTemplate(template, skin, context);\n if (result != null) {\n return result;\n }\n\n // If we could not find the template in the skin\n // let's try in the base skin (as long as the base skin is not the same as the skin)\n String baseskin = getBaseSkin(context);\n if (!skin.equals(baseskin)) {\n result = parseTemplate(template, baseskin, context);\n if (result != null) {\n return result;\n }\n }\n\n // If we still could not find the template in the skin or in the base skin\n // let's try in the default base skin (as long as the default base skin is not the same\n // as the skin or the base skin\n String defaultbaseskin = getDefaultBaseSkin(context);\n if ((!baseskin.equals(defaultbaseskin)) && (!skin.equals(defaultbaseskin))) {\n result = parseTemplate(template, defaultbaseskin, context);\n if (result != null) {\n return result;\n }\n }\n } catch (Exception ex) {\n LOGGER.debug(\"Exception while parsing template [{}] from skin\", template, ex);\n }\n\n // Prevent inclusion of templates from other directories\n template = URI.create(\"/templates/\" + template).normalize().toString();\n if (!template.startsWith(\"/templates/\")) {\n LOGGER.warn(\"Direct access to template file [{}] refused. Possible break-in attempt!\", template);\n return \"\";\n }\n\n String content = getResourceContent(template);\n return XWikiVelocityRenderer.evaluate(content, template, (VelocityContext) context.get(\"vcontext\"), context);\n }\n\n public String parseTemplate(String template, String skin, XWikiContext context)\n {\n try {\n XWikiDocument doc = getDocument(skin, context);\n if (!doc.isNew()) {\n // Try parsing the object property\n BaseObject object =\n doc.getXObject(new DocumentReference(doc.getDocumentReference().getWikiReference().getName(),\n SYSTEM_SPACE, \"XWikiSkins\"));\n if (object != null) {\n String content = object.getStringValue(template);\n if (StringUtils.isNotBlank(content)) {\n // Let's use this template\n // Use \"\" as namespace to register macros in global namespace. That way it\n // can be used in a renderer content not parsed at the same level.\n return XWikiVelocityRenderer.evaluate(content, \"\", (VelocityContext) context.get(\"vcontext\"),\n context);\n }\n }\n // Try parsing a document attachment\n XWikiAttachment attachment = doc.getAttachment(template);\n if (attachment != null) {\n // It's impossible to know the real attachemtn encoding, but let's assume that they respect the\n // standard and use UTF-8 (which is required for the files located on the filesystem)\n String content = IOUtils.toString(attachment.getContentInputStream(context), DEFAULT_ENCODING);\n if (StringUtils.isNotBlank(content)) {\n // Let's use this template\n // Use \"\" as namespace to register macros in global namespace. That way it\n // can be used in a renderer content not parsed at the same level.\n return XWikiVelocityRenderer.evaluate(content, \"\", (VelocityContext) context.get(\"vcontext\"),\n context);\n }\n }\n }\n } catch (Exception e) {\n }\n\n // Try parsing a file located in the directory with the same name.\n try {\n String path = \"/skins/\" + skin + \"/\" + template;\n // We must make sure the file is taken from the skins directory, otherwise people might\n // try to read things from WEB-INF.\n path = URI.create(path).normalize().toString();\n // This is a safe assumption, as templates found under /templates/ are treated\n // separately, and there is no need to have templates in another place.\n if (path.startsWith(\"/skins/\")) {\n String content = getResourceContent(path);\n // Use \"\" as namespace to register macros in global namespace. That way it can be\n // used in a renderer content not parsed at the same level.\n return XWikiVelocityRenderer.evaluate(content, \"\", (VelocityContext) context.get(\"vcontext\"), context);\n } else {\n LOGGER.warn(\"Illegal access, tried to use file [\" + path + \"] as a template.\"\n + \" Possible break-in attempt!\");\n }\n } catch (Exception e) {\n }\n\n return null;\n }\n\n public String renderTemplate(String template, String skin, XWikiContext context)\n {\n try {\n return getRenderingEngine().getRenderer(\"wiki\").render(parseTemplate(template, skin, context),\n context.getDoc(), context.getDoc(), context);\n } catch (Exception ex) {\n LOGGER.error(\"Failed to render template [\" + template + \"] for skin [\" + skin + \"]\", ex);\n return parseTemplate(template, skin, context);\n }\n }\n\n public String renderTemplate(String template, XWikiContext context)\n {\n try {\n return getRenderingEngine().getRenderer(\"wiki\").render(parseTemplate(template, context), context.getDoc(),\n context.getDoc(), context);\n } catch (Exception ex) {\n LOGGER.error(\"Failed to render template [\" + template + \"]\", ex);\n return parseTemplate(template, context);\n }\n }\n\n /**\n * Designed to include dynamic content, such as Servlets or JSPs, inside Velocity templates; works by creating a\n * RequestDispatcher, buffering the output, then returning it as a string.\n * \n * @author LBlaze\n */\n public String invokeServletAndReturnAsString(String url, XWikiContext xwikiContext)\n {\n\n HttpServletRequest servletRequest = xwikiContext.getRequest();\n HttpServletResponse servletResponse = xwikiContext.getResponse();\n\n try {\n return IncludeServletAsString.invokeServletAndReturnAsString(url, servletRequest, servletResponse);\n } catch (Exception e) {\n LOGGER.warn(\"Exception including url: \" + url, e);\n return \"Exception including \\\"\" + url + \"\\\", see logs for details.\";\n }\n\n }\n\n /**\n * @param iconName the standard name of an icon (it's not the name of the file on the filesystem, it's a generic\n * name, for example \"success\" for a success icon\n * @return the URL to the icon resource\n * @since 2.6M1\n */\n public String getIconURL(String iconName, XWikiContext context)\n {\n // TODO: Do a better mapping between generic icon name and physical resource name, especially to be independent\n // of the underlying icon library. Right now we assume it's the Silk icon library.\n return getSkinFile(\"icons/silk/\" + iconName + \".gif\", context);\n }\n\n public String getSkinFile(String filename, XWikiContext context)\n {\n return getSkinFile(filename, false, context);\n }\n\n public String getSkinFile(String filename, boolean forceSkinAction, XWikiContext context)\n {\n XWikiURLFactory urlf = context.getURLFactory();\n\n try {\n // Try in the specified skin\n String skin = getSkin(context);\n String result = getSkinFile(filename, skin, forceSkinAction, context);\n if (result != null) {\n return result;\n }\n // Try in the parent skin\n String baseskin = getBaseSkin(context);\n if (!skin.equals(baseskin)) {\n result = getSkinFile(filename, baseskin, forceSkinAction, context);\n if (result != null) {\n return result;\n }\n }\n } catch (Exception e) {\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Exception while getting skin file [\" + filename + \"]\", e);\n }\n }\n\n // If all else fails, use the default base skin, even if the URLs could be invalid.\n URL url;\n if (forceSkinAction) {\n url = urlf.createSkinURL(filename, \"skins\", getDefaultBaseSkin(context), context);\n } else {\n url = urlf.createSkinURL(filename, getDefaultBaseSkin(context), context);\n }\n return urlf.getURL(url, context);\n }\n\n public String getSkinFile(String filename, String skin, XWikiContext context)\n {\n return getSkinFile(filename, skin, false, context);\n }\n\n public String getSkinFile(String filename, String skin, boolean forceSkinAction, XWikiContext context)\n {\n XWikiURLFactory urlf = context.getURLFactory();\n try {\n XWikiDocument doc = getDocument(skin, context);\n if (!doc.isNew()) {\n // Look for an object property\n BaseObject object =\n doc.getXObject(new DocumentReference(doc.getDocumentReference().getWikiReference().getName(),\n SYSTEM_SPACE, \"XWikiSkins\"));\n if (object != null) {\n String content = object.getStringValue(filename);\n if (StringUtils.isNotBlank(content)) {\n URL url =\n urlf.createSkinURL(filename, doc.getSpace(), doc.getName(), doc.getDatabase(), context);\n return urlf.getURL(url, context);\n }\n }\n\n // Look for an attachment\n String shortName = StringUtils.replaceChars(filename, '/', '.');\n XWikiAttachment attachment = doc.getAttachment(shortName);\n if (attachment != null) {\n return doc.getAttachmentURL(shortName, \"skin\", context);\n }\n }\n\n // Look for a skin file\n String path = \"/skins/\" + skin + \"/\" + filename;\n if (resourceExists(path)) {\n URL url;\n\n if (forceSkinAction) {\n url = urlf.createSkinURL(filename, \"skins\", skin, context);\n } else {\n url = urlf.createSkinURL(filename, skin, context);\n }\n return urlf.getURL(url, context);\n }\n\n // Look for a resource file\n path = \"/resources/\" + filename;\n if (resourceExists(path)) {\n URL url;\n url = urlf.createResourceURL(filename, forceSkinAction, context);\n return urlf.getURL(url, context);\n }\n\n } catch (Exception e) {\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Exception while getting skin file [\" + filename + \"] from skin [\" + skin + \"]\", e);\n }\n }\n\n return null;\n }\n\n public String getSkin(XWikiContext context)\n {\n String skin = \"\";\n try {\n // Try to get it from context\n skin = (String) context.get(\"skin\");\n if (skin != null) {\n return skin;\n }\n\n // Try to get it from URL\n if (context.getRequest() != null) {\n skin = context.getRequest().getParameter(\"skin\");\n if (LOGGER.isDebugEnabled()) {\n if (skin != null && !skin.equals(\"\")) {\n LOGGER.debug(\"Requested skin in the URL: [\" + skin + \"]\");\n }\n }\n }\n\n if ((skin == null) || (skin.equals(\"\"))) {\n skin = getUserPreference(\"skin\", context);\n if (LOGGER.isDebugEnabled()) {\n if (skin != null && !skin.equals(\"\")) {\n LOGGER.debug(\"Configured skin in user preferences: [\" + skin + \"]\");\n }\n }\n }\n if (skin == null || skin.equals(\"\")) {\n skin = Param(\"xwiki.defaultskin\");\n if (LOGGER.isDebugEnabled()) {\n if (skin != null && !skin.equals(\"\")) {\n LOGGER.debug(\"Configured default skin in preferences: [\" + skin + \"]\");\n }\n }\n }\n if (skin == null || skin.equals(\"\")) {\n skin = getDefaultBaseSkin(context);\n if (LOGGER.isDebugEnabled()) {\n if (skin != null && !skin.equals(\"\")) {\n LOGGER.debug(\"Configured default base skin in preferences: [\" + skin + \"]\");\n }\n }\n }\n } catch (Exception e) {\n LOGGER.debug(\"Exception while determining current skin\", e);\n skin = getDefaultBaseSkin(context);\n }\n try {\n if (skin.indexOf('.') != -1) {\n if (!getRightService().hasAccessLevel(\"view\", context.getUser(), skin, context)) {\n LOGGER.debug(\"Cannot access configured skin due to access rights, using the default skin.\");\n skin = Param(\"xwiki.defaultskin\", getDefaultBaseSkin(context));\n }\n }\n } catch (XWikiException e) {\n // if it fails here, let's just ignore it\n LOGGER.debug(\"Exception while determining current skin\", e);\n }\n\n context.put(\"skin\", skin);\n return skin;\n }\n\n public String getSkinPreference(String prefname, XWikiContext context)\n {\n return getSkinPreference(prefname, \"\", context);\n }\n\n public String getSkinPreference(String prefname, String default_value, XWikiContext context)\n {\n try {\n String skin = getSkin(context);\n String oldskin = skin;\n String value = context.getWiki().getDocument(skin, context).getStringValue(\"XWiki.XWikiSkins\", prefname);\n if (value == null || \"\".equals(value)) {\n skin = getBaseSkin(context);\n if (!oldskin.equals(skin)) {\n value = context.getWiki().getDocument(skin, context).getStringValue(\"XWiki.XWikiSkins\", prefname);\n oldskin = skin;\n }\n }\n if (value == null || \"\".equals(value)) {\n skin = getDefaultBaseSkin(context);\n if (!oldskin.equals(skin)) {\n value = context.getWiki().getDocument(skin, context).getStringValue(\"XWiki.XWikiSkins\", prefname);\n }\n }\n if (value == null || \"\".equals(value)) {\n value = default_value;\n }\n return value;\n } catch (XWikiException ex) {\n LOGGER.warn(\"\", ex);\n }\n return default_value;\n }\n\n public String getDefaultBaseSkin(XWikiContext context)\n {\n String defaultbaseskin = Param(\"xwiki.defaultbaseskin\", \"\");\n if (defaultbaseskin.equals(\"\")) {\n defaultbaseskin = Param(\"xwiki.defaultskin\", \"colibri\");\n }\n return defaultbaseskin;\n }\n\n public String getBaseSkin(XWikiContext context)\n {\n return getBaseSkin(context, false);\n }\n\n public String getBaseSkin(XWikiContext context, boolean fromRenderSkin)\n {\n String baseskin = \"\";\n try {\n // Try to get it from context\n baseskin = (String) context.get(\"baseskin\");\n if (baseskin != null) {\n return baseskin;\n } else {\n baseskin = \"\";\n }\n\n // Let's get the base skin doc itself\n if (fromRenderSkin) {\n baseskin = context.getDoc().getStringValue(\"XWiki.XWikiSkins\", \"baseskin\");\n }\n\n if (baseskin.equals(\"\")) {\n // Let's get the base skin from the skin itself\n String skin = getSkin(context);\n baseskin = getBaseSkin(skin, context);\n }\n if (baseskin.equals(\"\")) {\n baseskin = getDefaultBaseSkin(context);\n }\n } catch (Exception e) {\n baseskin = getDefaultBaseSkin(context);\n LOGGER.debug(\"Exception while determining base skin\", e);\n }\n context.put(\"baseskin\", baseskin);\n return baseskin;\n }\n\n /**\n * @param skin the full name of the skin document for which to return the base skin. For example :\n * XWiki.DefaultSkin\n * @param context the XWiki context\n * @return if found, the name of the base skin the asked skin inherits from. If not found, returns an empty string.\n * @since 2.0.2\n * @since 2.1M1\n */\n public String getBaseSkin(String skin, XWikiContext context)\n {\n if (context.getWiki().exists(skin, context)) {\n try {\n return getDocument(skin, context).getStringValue(\"XWiki.XWikiSkins\", \"baseskin\");\n } catch (XWikiException e) {\n // Do nothing and let return the empty string.\n }\n }\n return \"\";\n }\n\n public String getSpaceCopyright(XWikiContext context)\n {\n String defaultValue = \"Copyright 2004-\" + Calendar.getInstance().get(Calendar.YEAR) + \" XWiki\";\n return getSpacePreference(\"webcopyright\", defaultValue, context);\n }\n\n public String getXWikiPreference(String prefname, XWikiContext context)\n {\n return getXWikiPreference(prefname, \"\", context);\n }\n\n /**\n * Obtain a preference value for the wiki, looking up first in the XWiki.XWikiPreferences document, then fallbacking\n * on a config parameter when the first lookup gives an empty string, then returning the default value if the config\n * parameter returned itself an empty string.\n * \n * @param prefname the parameter to look for in the XWiki.XWikiPreferences object corresponding to the context's\n * language in the XWiki.XWikiPreferences document of the wiki (or the first XWiki.XWikiPreferences\n * object contained, if the one for the context'ds language could not be found).\n * @param fallback_param the parameter in xwiki.cfg to fallback on, in case the XWiki.XWikiPreferences object gave\n * no result\n * @param default_value the default value to fallback on, in case both XWiki.XWikiPreferences and the fallback\n * xwiki.cfg parameter gave no result\n */\n public String getXWikiPreference(String prefname, String fallback_param, String default_value, XWikiContext context)\n {\n try {\n DocumentReference xwikiPreferencesReference =\n new DocumentReference(\"XWikiPreferences\", new SpaceReference(SYSTEM_SPACE, new WikiReference(\n context.getDatabase())));\n XWikiDocument doc = getDocument(xwikiPreferencesReference, context);\n // First we try to get a translated preference object\n BaseObject object =\n doc.getXObject(xwikiPreferencesReference, \"default_language\", context.getLanguage(), true);\n String result = \"\";\n\n if (object != null) {\n try {\n result = object.getStringValue(prefname);\n } catch (Exception e) {\n LOGGER.warn(\"Exception while getting wiki preference [\" + prefname + \"]\", e);\n }\n }\n // If empty we take it from the default pref object\n if (result.equals(\"\")) {\n object = doc.getXObject();\n if (object != null) {\n result = object.getStringValue(prefname);\n }\n }\n\n if (!result.equals(\"\")) {\n return result;\n }\n } catch (Exception e) {\n LOGGER.warn(\"Exception while getting wiki preference [\" + prefname + \"]\", e);\n }\n return Param(fallback_param, default_value);\n }\n\n public String getXWikiPreference(String prefname, String default_value, XWikiContext context)\n {\n return getXWikiPreference(prefname, \"\", default_value, context);\n }\n\n public String getSpacePreference(String preference, XWikiContext context)\n {\n return getSpacePreference(preference, \"\", context);\n }\n\n public String getSpacePreference(String preference, String defaultValue, XWikiContext context)\n {\n XWikiDocument currentdoc = (XWikiDocument) context.get(\"doc\");\n return getSpacePreference(preference, (currentdoc == null) ? null : currentdoc.getSpace(), defaultValue,\n context);\n }\n\n public String getSpacePreference(String preference, String space, String defaultValue, XWikiContext context)\n {\n // If there's no space defined then don't return space preferences (since it'll usually mean that the current\n // doc is not set).\n if (space != null) {\n try {\n XWikiDocument doc = getDocument(space + \".WebPreferences\", context);\n\n // First we try to get a translated preference object\n DocumentReference xwikiPreferencesReference =\n new DocumentReference(\"XWikiPreferences\", new SpaceReference(SYSTEM_SPACE, new WikiReference(\n context.getDatabase())));\n BaseObject object =\n doc.getXObject(xwikiPreferencesReference, \"default_language\", context.getLanguage(), true);\n String result = \"\";\n if (object != null) {\n try {\n result = object.getStringValue(preference);\n } catch (Exception e) {\n LOGGER.warn(\"Exception while getting space preference [\" + preference + \"]\", e);\n }\n }\n\n if (!result.equals(\"\")) {\n return result;\n }\n } catch (Exception e) {\n LOGGER.warn(\"Exception while getting space preference [\" + preference + \"]\", e);\n }\n }\n return getXWikiPreference(preference, defaultValue, context);\n }\n\n public String getUserPreference(String prefname, XWikiContext context)\n {\n try {\n String user = context.getUser();\n XWikiDocument userdoc = getDocument(user, context);\n if (userdoc != null) {\n String result = userdoc.getStringValue(\"XWiki.XWikiUsers\", prefname);\n if ((!result.equals(\"\")) && (!result.equals(\"---\"))) {\n return result;\n }\n }\n } catch (Exception e) {\n LOGGER.warn(\"Exception while getting user preference [\" + prefname + \"]\", e);\n }\n\n return getSpacePreference(prefname, context);\n }\n\n public String getUserPreferenceFromCookie(String prefname, XWikiContext context)\n {\n Cookie[] cookies = context.getRequest().getCookies();\n if (cookies == null) {\n return null;\n }\n for (int i = 0; i < cookies.length; i++) {\n String name = cookies[i].getName();\n if (name.equals(prefname)) {\n String value = cookies[i].getValue();\n if (!value.trim().equals(\"\")) {\n return value;\n } else {\n break;\n }\n }\n }\n return null;\n }\n\n public String getUserPreference(String prefname, boolean useCookie, XWikiContext context)\n {\n // First we look in the cookies\n if (useCookie) {\n String result = Util.normalizeLanguage(getUserPreferenceFromCookie(prefname, context));\n if (result != null) {\n return result;\n }\n }\n return getUserPreference(prefname, context);\n }\n\n /**\n * @deprecated use {@link #getLanguagePreference(XWikiContext)} instead\n */\n @Deprecated\n public String getDocLanguagePreference(XWikiContext context)\n {\n return getLanguagePreference(context);\n }\n\n /**\n * First try to find the current language in use from the XWiki context. If none is used and if the wiki is not\n * multilingual use the default language defined in the XWiki preferences. If the wiki is multilingual try to get\n * the language passed in the request. If none was passed try to get it from a cookie. If no language cookie exists\n * then use the user default language and barring that use the browser's \"Accept-Language\" header sent in HTTP\n * request. If none is defined use the default language.\n * \n * @return the language to use\n */\n public String getLanguagePreference(XWikiContext context)\n {\n // First we try to get the language from the XWiki Context. This is the current language\n // being used.\n String language = context.getLanguage();\n if (language != null) {\n return language;\n }\n\n String defaultLanguage = getDefaultLanguage(context);\n\n // If the wiki is non multilingual then the language is the default language.\n if (!context.getWiki().isMultiLingual(context)) {\n language = defaultLanguage;\n context.setLanguage(language);\n return language;\n }\n\n // As the wiki is multilingual try to find the language to use from the request by looking\n // for a language parameter. If the language value is \"default\" use the default language\n // from the XWiki preferences settings. Otherwise set a cookie to remember the language\n // in use.\n try {\n language = Util.normalizeLanguage(context.getRequest().getParameter(\"language\"));\n if ((language != null) && (!language.equals(\"\"))) {\n if (language.equals(\"default\")) {\n // forgetting language cookie\n Cookie cookie = new Cookie(\"language\", \"\");\n cookie.setMaxAge(0);\n cookie.setPath(\"/\");\n context.getResponse().addCookie(cookie);\n language = defaultLanguage;\n } else {\n // setting language cookie\n Cookie cookie = new Cookie(\"language\", language);\n cookie.setMaxAge(60 * 60 * 24 * 365 * 10);\n cookie.setPath(\"/\");\n context.getResponse().addCookie(cookie);\n }\n context.setLanguage(language);\n return language;\n }\n } catch (Exception e) {\n }\n\n // As no language parameter was passed in the request, try to get the language to use\n // from a cookie.\n try {\n // First we get the language from the cookie\n language = Util.normalizeLanguage(getUserPreferenceFromCookie(\"language\", context));\n if ((language != null) && (!language.equals(\"\"))) {\n context.setLanguage(language);\n return language;\n }\n } catch (Exception e) {\n }\n\n // Next from the default user preference\n try {\n String user = context.getUser();\n XWikiDocument userdoc = null;\n userdoc = getDocument(user, context);\n if (userdoc != null) {\n language = Util.normalizeLanguage(userdoc.getStringValue(\"XWiki.XWikiUsers\", \"default_language\"));\n if (!language.equals(\"\")) {\n context.setLanguage(language);\n return language;\n }\n }\n } catch (XWikiException e) {\n }\n\n // If the default language is preferred, and since the user didn't explicitly ask for a\n // language already, then use the default wiki language.\n if (Param(\"xwiki.language.preferDefault\", \"0\").equals(\"1\")\n || getSpacePreference(\"preferDefaultLanguage\", \"0\", context).equals(\"1\")) {\n language = defaultLanguage;\n context.setLanguage(language);\n return language;\n }\n\n // Then from the navigator language setting\n if (context.getRequest() != null) {\n String acceptHeader = context.getRequest().getHeader(\"Accept-Language\");\n // If the client didn't specify some languages, skip this phase\n if ((acceptHeader != null) && (!acceptHeader.equals(\"\"))) {\n List acceptedLanguages = getAcceptedLanguages(context.getRequest());\n // We can force one of the configured languages to be accepted\n if (Param(\"xwiki.language.forceSupported\", \"0\").equals(\"1\")) {\n List available = Arrays.asList(getXWikiPreference(\"languages\", context).split(\"[, |]\"));\n // Filter only configured languages\n acceptedLanguages.retainAll(available);\n }\n if (acceptedLanguages.size() > 0) {\n // Use the \"most-preferred\" language, as requested by the client.\n context.setLanguage(acceptedLanguages.get(0));\n return acceptedLanguages.get(0);\n }\n // If none of the languages requested by the client is acceptable, skip to next\n // phase (use default language).\n }\n }\n\n // Finally, use the default language from the global preferences.\n context.setLanguage(defaultLanguage);\n return defaultLanguage;\n }\n\n /**\n * Construct a list of language codes (ISO 639-1) from the Accept-Languages header. This method filters out some\n * bugs in different browsers or containers, like returning '*' as a language (Jetty) or using '_' as a\n * language--country delimiter (some versions of Opera).\n * \n * @param request The client request.\n * @return A list of language codes, in the client preference order; might be empty if the header is not well\n * formed.\n */\n @SuppressWarnings(\"unchecked\")\n private List getAcceptedLanguages(XWikiRequest request)\n {\n List result = new ArrayList();\n Enumeration e = request.getLocales();\n while (e.hasMoreElements()) {\n String language = e.nextElement().getLanguage().toLowerCase();\n // All language codes should have 2 letters.\n if (StringUtils.isAlpha(language)) {\n result.add(language);\n }\n }\n return result;\n }\n\n public String getDefaultLanguage(XWikiContext context)\n {\n // Find out what is the default language from the XWiki preferences settings.\n String defaultLanguage = context.getWiki().getXWikiPreference(\"default_language\", \"\", context);\n if (StringUtils.isBlank(defaultLanguage)) {\n defaultLanguage = \"en\";\n }\n return Util.normalizeLanguage(defaultLanguage);\n }\n\n public String getDocLanguagePreferenceNew(XWikiContext context)\n {\n // Get context language\n String contextLanguage = context.getLanguage();\n // If the language exists in the context, it was previously set by another call\n if (contextLanguage != null && contextLanguage != \"\") {\n return contextLanguage;\n }\n\n String language = \"\", requestLanguage = \"\", userPreferenceLanguage = \"\", navigatorLanguage = \"\", cookieLanguage =\n \"\";\n boolean setCookie = false;\n\n if (!context.getWiki().isMultiLingual(context)) {\n language = context.getWiki().getXWikiPreference(\"default_language\", \"\", context);\n context.setLanguage(language);\n return language;\n }\n\n // Get request language\n try {\n requestLanguage = Util.normalizeLanguage(context.getRequest().getParameter(\"language\"));\n } catch (Exception ex) {\n }\n\n // Get user preference\n try {\n String user = context.getUser();\n XWikiDocument userdoc = getDocument(user, context);\n if (userdoc != null) {\n userPreferenceLanguage = userdoc.getStringValue(\"XWiki.XWikiUsers\", \"default_language\");\n }\n } catch (XWikiException e) {\n }\n\n // Get navigator language setting\n if (context.getRequest() != null) {\n String accept = context.getRequest().getHeader(\"Accept-Language\");\n if ((accept != null) && (!accept.equals(\"\"))) {\n String[] alist = StringUtils.split(accept, \",;-\");\n if ((alist != null) && !(alist.length == 0)) {\n context.setLanguage(alist[0]);\n navigatorLanguage = alist[0];\n }\n }\n }\n\n // Get language from cookie\n try {\n cookieLanguage = Util.normalizeLanguage(getUserPreferenceFromCookie(\"language\", context));\n } catch (Exception e) {\n }\n\n // Determine which language to use\n // First we get the language from the request\n if ((requestLanguage != null) && (!requestLanguage.equals(\"\"))) {\n if (requestLanguage.equals(\"default\")) {\n setCookie = true;\n } else {\n language = requestLanguage;\n context.setLanguage(language);\n Cookie cookie = new Cookie(\"language\", language);\n cookie.setMaxAge(60 * 60 * 24 * 365 * 10);\n cookie.setPath(\"/\");\n context.getResponse().addCookie(cookie);\n return language;\n }\n }\n // Next we get the language from the cookie\n if (cookieLanguage != null && cookieLanguage != \"\") {\n language = cookieLanguage;\n }\n // Next from the default user preference\n else if (userPreferenceLanguage != null && userPreferenceLanguage != \"\") {\n language = userPreferenceLanguage;\n }\n // Then from the navigator language setting\n else if (navigatorLanguage != null && navigatorLanguage != \"\") {\n language = navigatorLanguage;\n }\n context.setLanguage(language);\n if (setCookie) {\n Cookie cookie = new Cookie(\"language\", language);\n cookie.setMaxAge(60 * 60 * 24 * 365 * 10);\n cookie.setPath(\"/\");\n context.getResponse().addCookie(cookie);\n }\n return language;\n }\n\n public String getInterfaceLanguagePreference(XWikiContext context)\n {\n String language = \"\", requestLanguage = \"\", userPreferenceLanguage = \"\", navigatorLanguage = \"\", cookieLanguage =\n \"\", contextLanguage = \"\";\n boolean setCookie = false;\n\n if (!context.getWiki().isMultiLingual(context)) {\n language = Util.normalizeLanguage(context.getWiki().getXWikiPreference(\"default_language\", \"\", context));\n context.setInterfaceLanguage(language);\n return language;\n }\n\n // Get request language\n try {\n requestLanguage = Util.normalizeLanguage(context.getRequest().getParameter(\"interfacelanguage\"));\n } catch (Exception ex) {\n }\n\n // Get context language\n contextLanguage = context.getInterfaceLanguage();\n\n // Get user preference\n try {\n String user = context.getUser();\n XWikiDocument userdoc = null;\n userdoc = getDocument(user, context);\n if (userdoc != null) {\n userPreferenceLanguage = userdoc.getStringValue(\"XWiki.XWikiUsers\", \"default_interface_language\");\n }\n } catch (XWikiException e) {\n }\n\n // Get navigator language setting\n if (context.getRequest() != null) {\n String accept = context.getRequest().getHeader(\"Accept-Language\");\n if ((accept != null) && (!accept.equals(\"\"))) {\n String[] alist = StringUtils.split(accept, \",;-\");\n if ((alist != null) && !(alist.length == 0)) {\n context.setLanguage(alist[0]);\n navigatorLanguage = alist[0];\n }\n }\n }\n\n // Get language from cookie\n try {\n cookieLanguage = Util.normalizeLanguage(getUserPreferenceFromCookie(\"interfacelanguage\", context));\n } catch (Exception e) {\n }\n\n // Determine which language to use\n // First we get the language from the request\n if ((requestLanguage != null) && (!requestLanguage.equals(\"\"))) {\n if (requestLanguage.equals(\"default\")) {\n setCookie = true;\n } else {\n language = requestLanguage;\n context.setLanguage(language);\n Cookie cookie = new Cookie(\"interfacelanguage\", language);\n cookie.setMaxAge(60 * 60 * 24 * 365 * 10);\n cookie.setPath(\"/\");\n context.getResponse().addCookie(cookie);\n return language;\n }\n }\n // Next we get the language from the context\n if (contextLanguage != null && contextLanguage != \"\") {\n language = contextLanguage;\n }\n // Next we get the language from the cookie\n else if (cookieLanguage != null && cookieLanguage != \"\") {\n language = cookieLanguage;\n }\n // Next from the default user preference\n else if (userPreferenceLanguage != null && userPreferenceLanguage != \"\") {\n language = userPreferenceLanguage;\n }\n // Then from the navigator language setting\n else if (navigatorLanguage != null && navigatorLanguage != \"\") {\n language = navigatorLanguage;\n }\n context.setLanguage(language);\n if (setCookie) {\n Cookie cookie = new Cookie(\"interfacelanguage\", language);\n cookie.setMaxAge(60 * 60 * 24 * 365 * 10);\n cookie.setPath(\"/\");\n context.getResponse().addCookie(cookie);\n }\n return language;\n }\n\n public long getXWikiPreferenceAsLong(String preference, XWikiContext context)\n {\n return Long.parseLong(getXWikiPreference(preference, context));\n }\n\n public long getSpacePreferenceAsLong(String preference, XWikiContext context)\n {\n return Long.parseLong(getSpacePreference(preference, context));\n }\n\n public long getXWikiPreferenceAsLong(String preference, long defaultValue, XWikiContext context)\n {\n return NumberUtils.toLong((getXWikiPreference(preference, context)), defaultValue);\n }\n\n public long getXWikiPreferenceAsLong(String preference, String fallbackParameter, long defaultValue,\n XWikiContext context)\n {\n return NumberUtils.toLong(getXWikiPreference(preference, fallbackParameter, \"\", context), defaultValue);\n }\n\n public long getSpacePreferenceAsLong(String preference, long defaultValue, XWikiContext context)\n {\n return NumberUtils.toLong(getSpacePreference(preference, context), defaultValue);\n }\n\n public long getUserPreferenceAsLong(String preference, XWikiContext context)\n {\n return Long.parseLong(getUserPreference(preference, context));\n }\n\n public int getXWikiPreferenceAsInt(String preference, XWikiContext context)\n {\n return Integer.parseInt(getXWikiPreference(preference, context));\n }\n\n public int getSpacePreferenceAsInt(String preference, XWikiContext context)\n {\n return Integer.parseInt(getSpacePreference(preference, context));\n }\n\n public int getXWikiPreferenceAsInt(String preference, int defaultValue, XWikiContext context)\n {\n return NumberUtils.toInt(getXWikiPreference(preference, context), defaultValue);\n }\n\n public int getXWikiPreferenceAsInt(String preference, String fallbackParameter, int defaultValue,\n XWikiContext context)\n {\n return NumberUtils.toInt(getXWikiPreference(preference, fallbackParameter, \"\", context), defaultValue);\n }\n\n public int getSpacePreferenceAsInt(String preference, int defaultValue, XWikiContext context)\n {\n return NumberUtils.toInt(getSpacePreference(preference, context), defaultValue);\n }\n\n public int getUserPreferenceAsInt(String prefname, XWikiContext context)\n {\n return Integer.parseInt(getUserPreference(prefname, context));\n }\n\n /**\n * Get XWiki context from execution context.\n * \n * @return the XWiki context for the current thread\n */\n private XWikiContext getXWikiContext()\n {\n Execution execution = Utils.getComponent((Type) Execution.class);\n\n ExecutionContext ec = execution.getContext();\n\n return ec != null ? (XWikiContext) ec.getProperty(\"xwikicontext\") : null;\n }\n\n /**\n * @deprecated user {@link #flushCache(XWikiContext)} instead\n */\n @Deprecated\n public void flushCache()\n {\n flushCache(getXWikiContext());\n }\n\n public void flushCache(XWikiContext context)\n {\n // We need to flush the virtual wiki list\n this.virtualWikiList = new ArrayList();\n // We need to flush the server Cache\n if (this.virtualWikiMap != null) {\n this.virtualWikiMap.dispose();\n this.virtualWikiMap = null;\n }\n\n // We need to flush the group service cache\n if (this.groupService != null) {\n this.groupService.flushCache();\n }\n\n // If we use the Cache Store layer.. we need to flush it\n XWikiStoreInterface store = getStore();\n if ((store != null) && (store instanceof XWikiCacheStoreInterface)) {\n ((XWikiCacheStoreInterface) getStore()).flushCache();\n }\n // Flush renderers.. Groovy renderer has a cache\n XWikiRenderingEngine rengine = getRenderingEngine();\n if (rengine != null) {\n rengine.flushCache();\n }\n\n XWikiPluginManager pmanager = getPluginManager();\n if (pmanager != null) {\n pmanager.flushCache(context);\n }\n\n // Make sure we call all classes flushCache function\n try {\n List classes = getClassList(context);\n for (int i = 0; i < classes.size(); i++) {\n String className = classes.get(i);\n try {\n getClass(className, context).flushCache();\n } catch (Exception e) {\n }\n }\n } catch (Exception e) {\n }\n\n }\n\n public XWikiPluginManager getPluginManager()\n {\n return this.pluginManager;\n }\n\n public void setPluginManager(XWikiPluginManager pluginManager)\n {\n this.pluginManager = pluginManager;\n }\n\n public void setConfig(XWikiConfig config)\n {\n this.config = config;\n }\n\n public void setStore(XWikiStoreInterface store)\n {\n this.store = store;\n }\n\n public void setAttachmentStore(XWikiAttachmentStoreInterface attachmentStore)\n {\n this.attachmentStore = attachmentStore;\n }\n\n public void setAttachmentVersioningStore(AttachmentVersioningStore avStore)\n {\n this.attachmentVersioningStore = avStore;\n }\n\n public void setVersioningStore(XWikiVersioningStoreInterface versioningStore)\n {\n this.versioningStore = versioningStore;\n }\n\n public void setRecycleBinStore(XWikiRecycleBinStoreInterface recycleBinStore)\n {\n this.recycleBinStore = recycleBinStore;\n }\n\n public void setAttachmentRecycleBinStore(AttachmentRecycleBinStore attachmentRecycleBinStore)\n {\n this.attachmentRecycleBinStore = attachmentRecycleBinStore;\n }\n\n public void setCriteriaService(XWikiCriteriaService criteriaService)\n {\n this.criteriaService = criteriaService;\n }\n\n public void setVersion(String version)\n {\n this.version = version;\n }\n\n private void flushVirtualWikis(XWikiDocument doc)\n {\n List bobjects = doc.getXObjects(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE);\n if (bobjects != null) {\n for (BaseObject bobj : bobjects) {\n if (bobj != null) {\n String host = bobj.getStringValue(\"server\");\n if (StringUtils.isNotEmpty(host)) {\n if (this.virtualWikiMap != null) {\n if (this.virtualWikiMap.get(host) != null) {\n this.virtualWikiMap.remove(host);\n }\n }\n }\n }\n }\n }\n }\n\n /**\n * Verify if the XWiki.TagClass page exists and that it contains all the required configuration\n * properties to make the tag feature work properly. If some properties are missing they are created and saved in\n * the database.\n * \n * @param context the XWiki Context\n * @return the TagClass Base Class object containing the properties\n * @throws XWikiException if an error happens during the save to the datavase\n */\n public BaseClass getTagClass(XWikiContext context) throws XWikiException\n {\n XWikiDocument doc;\n boolean needsUpdate = false;\n\n doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"TagClass\"), context);\n\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n needsUpdate |=\n bclass.addStaticListField(XWikiConstant.TAG_CLASS_PROP_TAGS, \"Tags\", 30, true, true, \"\", \"input\", \"|,\");\n StaticListClass tagClass = (StaticListClass) bclass.get(XWikiConstant.TAG_CLASS_PROP_TAGS);\n if (tagClass.isRelationalStorage() == false) {\n tagClass.setRelationalStorage(true);\n needsUpdate = true;\n }\n needsUpdate |= setClassDocumentFields(doc, \"XWiki Tag Class\");\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n return bclass;\n }\n\n /**\n * Verify if the XWiki.SheetClass page exists and that it contains all the required configuration\n * properties to make the sheet feature work properly. If some properties are missing they are created and saved in\n * the database. SheetClass is used to a page as a sheet. When a page is tagged as a sheet and that page is included\n * in another page using the include macro then editing it triggers automatic inline edition (for XWiki Syntax 2.0\n * only - for XWiki Syntax 1.0 automatic inline edition is triggered using #includeForm).\n * \n * @param context the XWiki Context\n * @return the SheetClass Base Class object containing the properties\n * @throws XWikiException if an error happens during the save to the database\n * @deprecated since 3.1M2 edit mode class should be used for this purpose, not the sheet class\n * @see #getEditModeClass(XWikiContext)\n */\n @Deprecated\n public BaseClass getSheetClass(XWikiContext context) throws XWikiException\n {\n XWikiDocument doc =\n getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"SheetClass\"), context);\n boolean needsUpdate = doc.isNew();\n\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n // Note: Ideally we don't want a special field in the sheet class but XWiki classes must have at\n // least one field or they're not saved. Thus we are introducing a \"defaultEditMode\" which will\n // tell what edit mode to use. If empty it'll default to \"inline\".\n needsUpdate |= bclass.addTextField(\"defaultEditMode\", \"Default Edit Mode\", 15);\n\n if (doc.isNew()) {\n needsUpdate |= setClassDocumentFields(doc, \"XWiki Sheet Class\");\n doc.setContent(doc.getContent() + \"\\n\\nClass that should be used to recognize sheet pages.\");\n }\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n return bclass;\n }\n\n /**\n * Verify if the {@code XWiki.EditModeClass} page exists and that it contains all the required configuration\n * properties to make the edit mode feature work properly. If some properties are missing they are created and saved\n * in the database. EditModeClass is used to specify the default edit mode of a page. It can also be used to mark a\n * page as a sheet. When a page is marked as a sheet and that page is included in another page using the include\n * macro then editing it triggers automatic inline edition (for XWiki Syntax 2.0 only - for XWiki Syntax 1.0\n * automatic inline edition is triggered using #includeForm). It replaces and enhances the SheetClass mechanism (see\n * {@link #getSheetClass(XWikiContext)}).\n * \n * @param context the XWiki Context\n * @return the EditModeClass Base Class object containing the properties\n * @throws XWikiException if an error happens during the save to the database\n * @since 3.1M2\n */\n public BaseClass getEditModeClass(XWikiContext context) throws XWikiException\n {\n DocumentReference classReference =\n new DocumentReference(context.getDatabase(), XWikiConstant.EDIT_MODE_CLASS.getParent().getName(),\n XWikiConstant.EDIT_MODE_CLASS.getName());\n XWikiDocument doc = getDocument(classReference, context);\n\n boolean needsUpdate = doc.isNew();\n\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n needsUpdate |= bclass.addTextField(\"defaultEditMode\", \"Default Edit Mode\", 15);\n\n if (doc.isNew()) {\n needsUpdate |= setClassDocumentFields(doc, \"XWiki Edit Mode Class\");\n doc.setContent(\"Class that should be used to specify the edit mode of a page.\");\n }\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n return bclass;\n }\n\n /**\n * Verify if the XWiki.XWikiUsers page exists and that it contains all the required configuration\n * properties to make the user feature work properly. If some properties are missing they are created and saved in\n * the database.\n * \n * @param context the XWiki Context\n * @return the XWikiUsers Base Class object containing the properties\n * @throws XWikiException if an error happens during the save to the datavase\n */\n public BaseClass getUserClass(XWikiContext context) throws XWikiException\n {\n XWikiDocument doc;\n boolean needsUpdate = false;\n\n doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"XWikiUsers\"), context);\n\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n needsUpdate |= bclass.addTextField(\"first_name\", \"First Name\", 30);\n needsUpdate |= bclass.addTextField(\"last_name\", \"Last Name\", 30);\n needsUpdate |= bclass.addTextField(\"email\", \"e-Mail\", 30);\n needsUpdate |= bclass.addPasswordField(\"password\", \"Password\", 10);\n needsUpdate |= bclass.addPasswordField(\"validkey\", \"Validation Key\", 10);\n needsUpdate |= bclass.addBooleanField(\"active\", \"Active\", \"active\");\n needsUpdate |= bclass.addTextField(\"default_language\", \"Default Language\", 30);\n needsUpdate |= bclass.addTextField(\"company\", \"Company\", 30);\n needsUpdate |= bclass.addTextField(\"blog\", \"Blog\", 60);\n needsUpdate |= bclass.addTextField(\"blogfeed\", \"Blog Feed\", 60);\n needsUpdate |= bclass.addTextAreaField(\"comment\", \"Comment\", 40, 5);\n needsUpdate |= bclass.addStaticListField(\"imtype\", \"IM Type\", \"---|AIM|Yahoo|Jabber|MSN|Skype|ICQ\");\n needsUpdate |= bclass.addTextField(\"imaccount\", \"imaccount\", 30);\n needsUpdate |= bclass.addStaticListField(\"editor\", \"Default Editor\", \"---|Text|Wysiwyg\");\n needsUpdate |= bclass.addStaticListField(\"usertype\", \"User type\", \"Simple|Advanced\");\n needsUpdate |= bclass.addBooleanField(\"accessibility\", \"Enable extra accessibility features\", \"yesno\");\n\n // New fields for the XWiki 1.0 skin\n needsUpdate |= bclass.addTextField(\"skin\", \"skin\", 30);\n needsUpdate |= bclass.addTextField(\"avatar\", \"Avatar\", 30);\n needsUpdate |= bclass.addTextField(\"phone\", \"Phone\", 30);\n needsUpdate |= bclass.addTextAreaField(\"address\", \"Address\", 40, 3);\n needsUpdate |= setClassDocumentFields(doc, \"XWiki User Class\");\n\n // Use XWikiUserSheet to display documents having XWikiUsers objects if no other class sheet is specified.\n SheetBinder classSheetBinder = Utils.getComponent((Type) SheetBinder.class, \"class\");\n if (classSheetBinder.getSheets(doc).isEmpty()) {\n DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"XWikiUserSheet\");\n needsUpdate |= classSheetBinder.bind(doc, sheet);\n }\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n\n return bclass;\n }\n\n /**\n * Verify if the XWiki.GlobalRedirect page exists and that it contains all the required configuration\n * properties to make the redirection feature work properly. If some properties are missing they are created and\n * saved in the database.\n * \n * @param context the XWiki Context\n * @return the GlobalRedirect Base Class object containing the properties\n * @throws XWikiException if an error happens during the save to the datavase\n */\n public BaseClass getRedirectClass(XWikiContext context) throws XWikiException\n {\n XWikiDocument doc;\n boolean needsUpdate = false;\n\n doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"GlobalRedirect\"), context);\n\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n needsUpdate |= bclass.addTextField(\"pattern\", \"Pattern\", 30);\n needsUpdate |= bclass.addTextField(\"destination\", \"Destination\", 30);\n needsUpdate |= setClassDocumentFields(doc, \"XWiki Global Redirect Class\");\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n return bclass;\n }\n\n /**\n * Verify if the XWiki.XWikiPreferences page exists and that it contains all the required configuration\n * properties to make XWiki work properly. If some properties are missing they are created and saved in the\n * database.\n * \n * @param context the XWiki Context\n * @return the XWiki Base Class object containing the properties\n * @throws XWikiException if an error happens during the save to the datavase\n */\n public BaseClass getPrefsClass(XWikiContext context) throws XWikiException\n {\n XWikiDocument doc;\n boolean needsUpdate = false;\n\n doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"XWikiPreferences\"), context);\n\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n if (!\"internal\".equals(bclass.getCustomMapping())) {\n needsUpdate = true;\n bclass.setCustomMapping(\"internal\");\n }\n\n needsUpdate |= bclass.addTextField(\"parent\", \"Parent Space\", 30);\n needsUpdate |= bclass.addBooleanField(\"multilingual\", \"Multi-Lingual\", \"yesno\");\n needsUpdate |= bclass.addTextField(\"default_language\", \"Default Language\", 5);\n needsUpdate |= bclass.addBooleanField(\"authenticate_edit\", \"Authenticated Edit\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"authenticate_view\", \"Authenticated View\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"auth_active_check\", \"Authentication Active Check\", \"yesno\");\n\n needsUpdate |= bclass.addTextField(\"skin\", \"Skin\", 30);\n needsUpdate |=\n bclass.addDBListField(\"colorTheme\", \"Color theme\",\n \"select doc.fullName, doc.title from XWikiDocument as doc, BaseObject as theme \"\n + \"where doc.fullName=theme.name and theme.className='ColorThemes.ColorThemeClass' \"\n + \"and doc.fullName<>'ColorThemes.ColorThemeTemplate'\");\n // This one should not be in the prefs\n PropertyInterface baseskinProp = bclass.get(\"baseskin\");\n if (baseskinProp != null) {\n bclass.removeField(\"baseskin\");\n needsUpdate = true;\n }\n needsUpdate |= bclass.addTextField(\"stylesheet\", \"Default Stylesheet\", 30);\n needsUpdate |= bclass.addTextField(\"stylesheets\", \"Alternative Stylesheet\", 60);\n needsUpdate |= bclass.addBooleanField(\"accessibility\", \"Enable extra accessibility features\", \"yesno\");\n\n needsUpdate |= bclass.addStaticListField(\"editor\", \"Default Editor\", \"---|Text|Wysiwyg\");\n\n needsUpdate |= bclass.addTextField(\"webcopyright\", \"Copyright\", 30);\n needsUpdate |= bclass.addTextField(\"title\", \"Title\", 30);\n needsUpdate |= bclass.addTextField(\"version\", \"Version\", 30);\n needsUpdate |= bclass.addTextAreaField(\"meta\", \"HTTP Meta Info\", 60, 8);\n needsUpdate |= bclass.addTextField(\"dateformat\", \"Date Format\", 30);\n\n // mail\n needsUpdate |= bclass.addBooleanField(\"use_email_verification\", \"Use eMail Verification\", \"yesno\");\n needsUpdate |= bclass.addTextField(\"admin_email\", \"Admin eMail\", 30);\n needsUpdate |= bclass.addTextField(\"smtp_server\", \"SMTP Server\", 30);\n needsUpdate |= bclass.addTextField(\"smtp_port\", \"SMTP Port\", 5);\n needsUpdate |= bclass.addTextField(\"smtp_server_username\", \"Server username (optional)\", 30);\n needsUpdate |= bclass.addTextField(\"smtp_server_password\", \"Server password (optional)\", 30);\n needsUpdate |= bclass.addTextAreaField(\"javamail_extra_props\", \"Additional JavaMail properties\", 60, 6);\n needsUpdate |= bclass.addTextAreaField(\"validation_email_content\", \"Validation eMail Content\", 72, 10);\n needsUpdate |= bclass.addTextAreaField(\"confirmation_email_content\", \"Confirmation eMail Content\", 72, 10);\n needsUpdate |= bclass.addTextAreaField(\"invitation_email_content\", \"Invitation eMail Content\", 72, 10);\n\n needsUpdate |= bclass.addStaticListField(\"registration_anonymous\", \"Anonymous\", \"---|Image|Text\");\n needsUpdate |= bclass.addStaticListField(\"registration_registered\", \"Registered\", \"---|Image|Text\");\n needsUpdate |= bclass.addStaticListField(\"edit_anonymous\", \"Anonymous\", \"---|Image|Text\");\n needsUpdate |= bclass.addStaticListField(\"edit_registered\", \"Registered\", \"---|Image|Text\");\n needsUpdate |= bclass.addStaticListField(\"comment_anonymous\", \"Anonymous\", \"---|Image|Text\");\n needsUpdate |= bclass.addStaticListField(\"comment_registered\", \"Registered\", \"---|Image|Text\");\n\n needsUpdate |= bclass.addNumberField(\"upload_maxsize\", \"Maximum Upload Size\", 5, \"long\");\n\n // Captcha for guest comments\n needsUpdate |=\n bclass.addBooleanField(\"guest_comment_requires_captcha\",\n \"Enable CAPTCHA in Comments for Unregistered Users\", \"select\");\n\n // Document editing\n needsUpdate |= bclass.addTextField(\"core.defaultDocumentSyntax\", \"Default document syntax\", 60);\n needsUpdate |= bclass.addBooleanField(\"xwiki.title.mandatory\", \"Make document title field mandatory\", \"yesno\");\n\n // for tags\n needsUpdate |= bclass.addBooleanField(\"tags\", \"Activate the tagging\", \"yesno\");\n\n // for backlinks\n needsUpdate |= bclass.addBooleanField(\"backlinks\", \"Activate the backlinks\", \"yesno\");\n\n // New fields for the XWiki 1.0 skin\n needsUpdate |= bclass.addTextField(\"leftPanels\", \"Panels displayed on the left\", 60);\n needsUpdate |= bclass.addTextField(\"rightPanels\", \"Panels displayed on the right\", 60);\n needsUpdate |= bclass.addBooleanField(\"showLeftPanels\", \"Display the left panel column\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"showRightPanels\", \"Display the right panel column\", \"yesno\");\n needsUpdate |= bclass.addTextField(\"languages\", \"Supported languages\", 30);\n needsUpdate |= bclass.addTextField(\"documentBundles\", \"Internationalization Document Bundles\", 60);\n\n // Only used by LDAP authentication service\n\n needsUpdate |= bclass.addBooleanField(\"ldap\", \"Ldap\", \"yesno\");\n needsUpdate |= bclass.addTextField(\"ldap_server\", \"Ldap server adress\", 60);\n needsUpdate |= bclass.addTextField(\"ldap_port\", \"Ldap server port\", 60);\n needsUpdate |= bclass.addTextField(\"ldap_bind_DN\", \"Ldap login matching\", 60);\n needsUpdate |= bclass.addTextField(\"ldap_bind_pass\", \"Ldap password matching\", 60);\n needsUpdate |= bclass.addBooleanField(\"ldap_validate_password\", \"Validate Ldap user/password\", \"yesno\");\n needsUpdate |= bclass.addTextField(\"ldap_user_group\", \"Ldap group filter\", 60);\n needsUpdate |= bclass.addTextField(\"ldap_exclude_group\", \"Ldap group to exclude\", 60);\n needsUpdate |= bclass.addTextField(\"ldap_base_DN\", \"Ldap base DN\", 60);\n needsUpdate |= bclass.addTextField(\"ldap_UID_attr\", \"Ldap UID attribute name\", 60);\n needsUpdate |= bclass.addTextField(\"ldap_fields_mapping\", \"Ldap user fiels mapping\", 60);\n needsUpdate |= bclass.addBooleanField(\"ldap_update_user\", \"Update user from LDAP\", \"yesno\");\n needsUpdate |= bclass.addTextAreaField(\"ldap_group_mapping\", \"Ldap groups mapping\", 60, 5);\n needsUpdate |= bclass.addTextField(\"ldap_groupcache_expiration\", \"LDAP groups members cache\", 60);\n needsUpdate |= bclass.addStaticListField(\"ldap_mode_group_sync\", \"LDAP groups sync mode\", \"|always|create\");\n needsUpdate |= bclass.addBooleanField(\"ldap_trylocal\", \"Try local login\", \"yesno\");\n\n if (((BooleanClass) bclass.get(\"showLeftPanels\")).getDisplayType().equals(\"checkbox\")) {\n ((BooleanClass) bclass.get(\"showLeftPanels\")).setDisplayType(\"yesno\");\n ((BooleanClass) bclass.get(\"showRightPanels\")).setDisplayType(\"yesno\");\n needsUpdate = true;\n }\n\n needsUpdate |= bclass.addBooleanField(\"showannotations\", \"Show document annotations\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"showcomments\", \"Show document comments\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"showattachments\", \"Show document attachments\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"showhistory\", \"Show document history\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"showinformation\", \"Show document information\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"editcomment\", \"Enable version summary\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"editcomment_mandatory\", \"Make version summary mandatory\", \"yesno\");\n needsUpdate |= bclass.addBooleanField(\"minoredit\", \"Enable minor edits\", \"yesno\");\n\n SheetBinder documentSheetBinder = Utils.getComponent((Type) SheetBinder.class, \"document\");\n boolean withoutDocumentSheets = documentSheetBinder.getSheets(doc).isEmpty();\n if (withoutDocumentSheets) {\n // Bind a document sheet to prevent the default class sheet from being used.\n documentSheetBinder.bind(doc, doc.getDocumentReference());\n }\n needsUpdate |= setClassDocumentFields(doc, \"XWiki Preferences\");\n if (withoutDocumentSheets) {\n // Unbind the document sheet we bound earlier.\n documentSheetBinder.unbind(doc, doc.getDocumentReference());\n }\n\n // Use AdminSheet to display documents having XWikiPreferences objects if no other class sheet is specified.\n SheetBinder classSheetBinder = Utils.getComponent((Type) SheetBinder.class, \"class\");\n if (classSheetBinder.getSheets(doc).isEmpty()) {\n DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"AdminSheet\");\n needsUpdate |= classSheetBinder.bind(doc, sheet);\n }\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n return bclass;\n }\n\n public BaseClass getGroupClass(XWikiContext context) throws XWikiException\n {\n XWikiDocument doc;\n XWikiDocument template = null;\n boolean needsUpdate = false;\n\n doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"XWikiGroups\"), context);\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n needsUpdate |= bclass.addTextField(\"member\", \"Member\", 30);\n needsUpdate |= setClassDocumentFields(doc, \"XWiki Group Class\");\n\n // Use XWikiGroupSheet to display documents having XWikiGroups objects if no other class sheet is specified.\n SheetBinder classSheetBinder = Utils.getComponent((Type) SheetBinder.class, \"class\");\n if (classSheetBinder.getSheets(doc).isEmpty()) {\n DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"XWikiGroupSheet\");\n needsUpdate |= classSheetBinder.bind(doc, sheet);\n }\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n\n return bclass;\n }\n\n public BaseClass getRightsClass(String pagename, XWikiContext context) throws XWikiException\n {\n XWikiDocument doc;\n boolean needsUpdate = false;\n\n doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, pagename), context);\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n PropertyInterface groupsProp = bclass.get(\"groups\");\n if ((groupsProp != null) && !(groupsProp instanceof GroupsClass)) {\n bclass.removeField(\"groups\");\n needsUpdate = true;\n }\n needsUpdate |= bclass.addGroupsField(\"groups\", \"Groups\");\n\n PropertyInterface levelsProp = bclass.get(\"levels\");\n if ((levelsProp != null) && !(levelsProp instanceof LevelsClass)) {\n bclass.removeField(\"levels\");\n needsUpdate = true;\n }\n needsUpdate |= bclass.addLevelsField(\"levels\", \"Levels\");\n\n PropertyInterface usersProp = bclass.get(\"users\");\n if ((usersProp != null) && !(usersProp instanceof UsersClass)) {\n bclass.removeField(\"users\");\n needsUpdate = true;\n }\n needsUpdate |= bclass.addUsersField(\"users\", \"Users\");\n\n PropertyInterface allowProp = bclass.get(\"allow\");\n if ((allowProp != null) && (allowProp instanceof NumberClass)) {\n bclass.removeField(\"allow\");\n needsUpdate = true;\n }\n needsUpdate |= bclass.addBooleanField(\"allow\", \"Allow/Deny\", \"allow\");\n BooleanClass afield = (BooleanClass) bclass.get(\"allow\");\n if (afield.getDefaultValue() != 1) {\n afield.setDefaultValue(1);\n needsUpdate = true;\n }\n\n String title;\n if (pagename.equals(\"XWikiGlobalRights\")) {\n title = \"XWiki Global Rights Class\";\n } else {\n title = \"XWiki Rights Class\";\n }\n\n needsUpdate |= setClassDocumentFields(doc, title);\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n return bclass;\n }\n\n public BaseClass getRightsClass(XWikiContext context) throws XWikiException\n {\n return getRightsClass(\"XWikiRights\", context);\n }\n\n public BaseClass getGlobalRightsClass(XWikiContext context) throws XWikiException\n {\n return getRightsClass(\"XWikiGlobalRights\", context);\n }\n\n public BaseClass getCommentsClass(XWikiContext context) throws XWikiException\n {\n XWikiDocument doc;\n boolean needsUpdate = false;\n\n doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"XWikiComments\"), context);\n\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n needsUpdate |= bclass.addTextField(\"author\", \"Author\", 30);\n needsUpdate |= bclass.addTextAreaField(\"highlight\", \"Highlighted Text\", 40, 2);\n needsUpdate |= bclass.addNumberField(\"replyto\", \"Reply To\", 5, \"integer\");\n needsUpdate |= bclass.addDateField(\"date\", \"Date\");\n needsUpdate |= bclass.addTextAreaField(\"comment\", \"Comment\", 40, 5);\n needsUpdate |= setClassDocumentFields(doc, \"XWiki Comment Class\");\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n return bclass;\n }\n\n public BaseClass getSkinClass(XWikiContext context) throws XWikiException\n {\n XWikiDocument doc;\n boolean needsUpdate = false;\n\n doc = getDocument(new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"XWikiSkins\"), context);\n\n BaseClass bclass = doc.getXClass();\n if (context.get(\"initdone\") != null) {\n return bclass;\n }\n\n needsUpdate |= bclass.addTextField(\"name\", \"Name\", 30);\n needsUpdate |= bclass.addTextField(\"baseskin\", \"Base Skin\", 30);\n needsUpdate |= bclass.addTextField(\"logo\", \"Logo\", 30);\n needsUpdate |= bclass.addTemplateField(\"style.css\", \"Style\");\n needsUpdate |= bclass.addTemplateField(\"header.vm\", \"Header\");\n needsUpdate |= bclass.addTemplateField(\"footer.vm\", \"Footer\");\n needsUpdate |= bclass.addTemplateField(\"viewheader.vm\", \"View Header\");\n needsUpdate |= bclass.addTemplateField(\"view.vm\", \"View\");\n needsUpdate |= bclass.addTemplateField(\"edit.vm\", \"Edit\");\n needsUpdate |= setClassDocumentFields(doc, \"XWiki Skin Class\");\n\n // Use XWikiSkinsSheet to display documents having XWikiSkins objects if no other class sheet is specified.\n SheetBinder classSheetBinder = Utils.getComponent((Type) SheetBinder.class, \"class\");\n if (classSheetBinder.getSheets(doc).isEmpty()) {\n DocumentReference sheet = new DocumentReference(context.getDatabase(), SYSTEM_SPACE, \"XWikiSkinsSheet\");\n needsUpdate |= classSheetBinder.bind(doc, sheet);\n }\n\n if (needsUpdate) {\n saveDocument(doc, context);\n }\n return bclass;\n }\n\n public int createUser(XWikiContext context) throws XWikiException\n {\n return createUser(false, \"edit\", context);\n }\n\n public int validateUser(boolean withConfirmEmail, XWikiContext context) throws XWikiException\n {\n try {\n XWikiRequest request = context.getRequest();\n // Get the user document\n String username = convertUsername(request.getParameter(\"xwikiname\"), context);\n if (username.indexOf('.') == -1) {\n username = \"XWiki.\" + username;\n }\n XWikiDocument userDocument = getDocument(username, context);\n\n // Get the stored validation key\n BaseObject userObject = userDocument.getObject(\"XWiki.XWikiUsers\", 0);\n String storedKey = userObject.getStringValue(\"validkey\");\n\n // Get the validation key from the URL\n String validationKey = request.getParameter(\"validkey\");\n PropertyInterface validationKeyClass = getClass(\"XWiki.XWikiUsers\", context).get(\"validkey\");\n if (validationKeyClass instanceof PasswordClass) {\n validationKey = ((PasswordClass) validationKeyClass).getEquivalentPassword(storedKey, validationKey);\n }\n\n // Compare the two keys\n if ((!storedKey.equals(\"\") && (storedKey.equals(validationKey)))) {\n userObject.setIntValue(\"active\", 1);\n saveDocument(userDocument, context);\n\n if (withConfirmEmail) {\n String email = userObject.getStringValue(\"email\");\n String password = userObject.getStringValue(\"password\");\n sendValidationEmail(username, password, email, request.getParameter(\"validkey\"),\n \"confirmation_email_content\", context);\n }\n\n return 0;\n } else {\n return -1;\n }\n } catch (Exception e) {\n e.printStackTrace();\n throw new XWikiException(XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_VALIDATE_USER,\n \"Exception while validating user\", e, null);\n }\n }\n\n public int createUser(boolean withValidation, String userRights, XWikiContext context) throws XWikiException\n {\n try {\n XWikiRequest request = context.getRequest();\n Map map = Util.getObject(request, \"register\");\n\n String content;\n Syntax syntax;\n if (!getDefaultDocumentSyntax().equals(Syntax.XWIKI_1_0.toIdString())) {\n content = \"{{include document=\\\"XWiki.XWikiUserSheet\\\"/}}\";\n syntax = Syntax.XWIKI_2_0;\n } else {\n content = \"#includeForm(\\\"XWiki.XWikiUserSheet\\\")\";\n syntax = Syntax.XWIKI_1_0;\n }\n\n String xwikiname = request.getParameter(\"xwikiname\");\n String password2 = request.getParameter(\"register2_password\");\n String password = (map.get(\"password\"))[0];\n String email = (map.get(\"email\"))[0];\n String template = request.getParameter(\"template\");\n String parent = request.getParameter(\"parent\");\n String validkey = null;\n\n if (XWikiRightService.SUPERADMIN_USER.equalsIgnoreCase(xwikiname)) {\n return -8;\n }\n try {\n if (!context.getUtil().match(this.Param(\"xwiki.validusername\", \"/^[a-zA-Z0-9_]+$/\"), xwikiname)) {\n return -4;\n }\n } catch (RuntimeException ex) {\n LOGGER.warn(\"Invalid regular expression for xwiki.validusername\", ex);\n if (!context.getUtil().match(\"/^[a-zA-Z0-9_]+$/\", xwikiname)) {\n return -4;\n }\n }\n\n if ((!password.equals(password2)) || (password.trim().equals(\"\"))) {\n // TODO: throw wrong password exception\n return -2;\n }\n\n if ((template != null) && (!template.equals(\"\"))) {\n XWikiDocument tdoc = getDocument(template, context);\n if ((!tdoc.isNew())) {\n content = tdoc.getContent();\n syntax = tdoc.getSyntax();\n }\n }\n\n if ((parent == null) || (parent.equals(\"\"))) {\n parent = \"XWiki.XWikiUsers\";\n }\n\n if (withValidation) {\n map.put(\"active\", new String[] {\"0\"});\n validkey = generateValidationKey(16);\n map.put(\"validkey\", new String[] {validkey});\n\n } else {\n // Mark user active\n map.put(\"active\", new String[] {\"1\"});\n }\n\n int result =\n createUser(xwikiname, map, this.relativeEntityReferenceResolver.resolve(parent, EntityType.DOCUMENT),\n content, syntax, userRights, context);\n\n if ((result > 0) && (withValidation)) {\n // Send the validation email\n sendValidationEmail(xwikiname, password, email, validkey, \"validation_email_content\", context);\n }\n\n return result;\n } catch (XWikiException e) {\n e.printStackTrace();\n throw e;\n } catch (Exception e) {\n e.printStackTrace();\n throw new XWikiException(XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_CREATE_USER,\n \"Exception while creating user\", e, null);\n }\n }\n\n /**\n * Method allows to create an empty user with no password (he won't be able to login) This method is usefull for\n * authentication like LDAP or App Server trusted\n * \n * @param xwikiname\n * @param userRights\n * @param context\n * @return true if success\n * @throws XWikiException\n */\n public boolean createEmptyUser(String xwikiname, String userRights, XWikiContext context) throws XWikiException\n {\n Map map = new HashMap();\n map.put(\"active\", \"1\");\n map.put(\"first_name\", xwikiname);\n\n if (createUser(xwikiname, map, userRights, context) == 1) {\n return true;\n } else {\n return false;\n }\n }\n\n public void sendConfirmationEmail(String xwikiname, String password, String email, String message,\n String contentfield, XWikiContext context) throws XWikiException\n {\n sendValidationEmail(xwikiname, password, email, \"message\", message, contentfield, context);\n }\n\n public void sendValidationEmail(String xwikiname, String password, String email, String validkey,\n String contentfield, XWikiContext context) throws XWikiException\n {\n sendValidationEmail(xwikiname, password, email, \"validkey\", validkey, contentfield, context);\n }\n\n public void sendValidationEmail(String xwikiname, String password, String email, String addfieldname,\n String addfieldvalue, String contentfield, XWikiContext context) throws XWikiException\n {\n String sender;\n String content;\n\n try {\n sender = getXWikiPreference(\"admin_email\", context);\n content = getXWikiPreference(contentfield, context);\n } catch (Exception e) {\n throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL,\n XWikiException.ERROR_XWIKI_EMAIL_CANNOT_GET_VALIDATION_CONFIG,\n \"Exception while reading the validation email config\", e, null);\n\n }\n\n try {\n VelocityContext vcontext = (VelocityContext) context.get(\"vcontext\");\n vcontext.put(addfieldname, addfieldvalue);\n vcontext.put(\"email\", email);\n vcontext.put(\"password\", password);\n vcontext.put(\"sender\", sender);\n vcontext.put(\"xwikiname\", xwikiname);\n content = parseContent(content, context);\n } catch (Exception e) {\n throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL,\n XWikiException.ERROR_XWIKI_EMAIL_CANNOT_PREPARE_VALIDATION_EMAIL,\n \"Exception while preparing the validation email\", e, null);\n\n }\n\n // Let's now send the message\n sendMessage(sender, email, content, context);\n }\n\n /**\n * @deprecated replaced by the Mail Sender\n * Plugin\n */\n @Deprecated\n public void sendMessage(String sender, String[] recipients, String rawMessage, XWikiContext context)\n throws XWikiException\n {\n LOGGER.trace(\"Entering sendMessage()\");\n\n // We'll be using the MailSender plugin, which has much more advanced capabilities (authentication, TLS).\n // Since the plugin is in another module, and it depends on the core, we have to use it through reflection in\n // order to avoid cyclic dependencies. This should be fixed once the mailsender becomes a clean component\n // instead of a plugin.\n Object mailSender;\n Class mailSenderClass;\n Method mailSenderSendRaw;\n\n try {\n mailSender = getPluginApi(\"mailsender\", context);\n mailSenderClass = Class.forName(\"com.xpn.xwiki.plugin.mailsender.MailSenderPluginApi\");\n\n // public int sendRawMessage(String from, String to, String rawMessage)\n mailSenderSendRaw =\n mailSenderClass.getMethod(\"sendRawMessage\", new Class[] {String.class, String.class, String.class});\n } catch (Exception e) {\n LOGGER.error(\"Problem getting MailSender via Reflection. Using the old sendMessage mechanism.\", e);\n sendMessageOld(sender, recipients, rawMessage, context);\n return;\n }\n\n if (LOGGER.isTraceEnabled()) {\n LOGGER.trace(\"Sending message = \\\"\" + rawMessage + \"\\\"\");\n }\n\n String messageRecipients = StringUtils.join(recipients, ',');\n\n try {\n mailSenderSendRaw.invoke(mailSender, sender, messageRecipients, rawMessage);\n } catch (InvocationTargetException ite) {\n Throwable cause = ite.getCause();\n if (cause instanceof XWikiException) {\n throw (XWikiException) cause;\n } else {\n throw new RuntimeException(cause);\n }\n } catch (Exception e) {\n // Probably either IllegalAccessException or IllegalArgumentException\n // Shouldn't happen unless there were an incompatible code change\n throw new RuntimeException(e);\n }\n\n LOGGER.info(\"Exiting sendMessage(). It seems everything went ok.\");\n }\n\n /**\n * @deprecated replaced by the Mail Sender\n * Plugin\n */\n @Deprecated\n private void sendMessageOld(String sender, String[] recipient, String message, XWikiContext context)\n throws XWikiException\n {\n SMTPClient smtpc = null;\n try {\n String server = getXWikiPreference(\"smtp_server\", context);\n String port = getXWikiPreference(\"smtp_port\", context);\n String login = getXWikiPreference(\"smtp_login\", context);\n\n if (context.get(\"debugMail\") != null) {\n StringBuffer msg = new StringBuffer(message);\n msg.append(\"\\n Recipient: \");\n msg.append(recipient);\n recipient = ((String) context.get(\"debugMail\")).split(\",\");\n message = msg.toString();\n }\n\n if ((server == null) || server.equals(\"\")) {\n server = \"127.0.0.1\";\n }\n if ((port == null) || (port.equals(\"\"))) {\n port = \"25\";\n }\n if ((login == null) || login.equals(\"\")) {\n login = InetAddress.getLocalHost().getHostName();\n }\n\n smtpc = new SMTPClient();\n smtpc.connect(server, Integer.parseInt(port));\n int reply = smtpc.getReplyCode();\n if (!SMTPReply.isPositiveCompletion(reply)) {\n Object[] args = {server, port, Integer.valueOf(reply), smtpc.getReplyString()};\n throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL,\n XWikiException.ERROR_XWIKI_EMAIL_CONNECT_FAILED,\n \"Could not connect to server {0} port {1} error code {2} ({3})\", null, args);\n }\n\n if (smtpc.login(login) == false) {\n reply = smtpc.getReplyCode();\n Object[] args = {server, port, Integer.valueOf(reply), smtpc.getReplyString()};\n throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL,\n XWikiException.ERROR_XWIKI_EMAIL_LOGIN_FAILED,\n \"Could not login to mail server {0} port {1} error code {2} ({3})\", null, args);\n }\n\n if (smtpc.sendSimpleMessage(sender, recipient, message) == false) {\n reply = smtpc.getReplyCode();\n Object[] args = {server, port, Integer.valueOf(reply), smtpc.getReplyString()};\n throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL,\n XWikiException.ERROR_XWIKI_EMAIL_SEND_FAILED,\n \"Could not send mail to server {0} port {1} error code {2} ({3})\", null, args);\n }\n\n } catch (IOException e) {\n Object[] args = {sender, recipient};\n throw new XWikiException(XWikiException.MODULE_XWIKI_EMAIL,\n XWikiException.ERROR_XWIKI_EMAIL_ERROR_SENDING_EMAIL, \"Exception while sending email from {0} to {1}\",\n e, args);\n } finally {\n if ((smtpc != null) && (smtpc.isConnected())) {\n try {\n smtpc.disconnect();\n } catch (IOException e) {\n e.printStackTrace();\n }\n }\n }\n }\n\n /**\n * @deprecated replaced by the Mail Sender\n * Plugin\n */\n @Deprecated\n public void sendMessage(String sender, String recipient, String message, XWikiContext context)\n throws XWikiException\n {\n String[] recip = recipient.split(\",\");\n sendMessage(sender, recip, message, context);\n }\n\n public String generateRandomString(int size)\n {\n return RandomStringUtils.randomAlphanumeric(size);\n }\n\n public String generateValidationKey(int size)\n {\n return generateRandomString(size);\n }\n\n /**\n * Create a new user.\n * \n * @param userName the name of the user (without the space)\n * @param map extra datas to add to user profile object\n * @param context the XWiki context\n * @return

    \n *
  • 1: ok
  • \n *
  • -3: user already exists
  • \n *
\n * @throws XWikiException failed to create the new user\n */\n public int createUser(String userName, Map map, XWikiContext context) throws XWikiException\n {\n return createUser(userName, map, \"edit\", context);\n }\n\n /**\n * Create a new user.\n * \n * @param userName the name of the user (without the space)\n * @param map extra datas to add to user profile object\n * @param userRights the right of the user on his own profile page\n * @param context the XWiki context\n * @return
    \n *
  • 1: ok
  • \n *
  • -3: user already exists
  • \n *
\n * @throws XWikiException failed to create the new user\n */\n public int createUser(String userName, Map map, String userRights, XWikiContext context)\n throws XWikiException\n {\n BaseClass userClass = context.getWiki().getUserClass(context);\n\n String content;\n Syntax syntax;\n if (!context.getWiki().getDefaultDocumentSyntax().equals(Syntax.XWIKI_1_0.toIdString())) {\n content = \"{{include document=\\\"XWiki.XWikiUserSheet\\\"/}}\";\n syntax = Syntax.XWIKI_2_0;\n } else {\n content = \"#includeForm(\\\"XWiki.XWikiUserSheet\\\")\";\n syntax = Syntax.XWIKI_1_0;\n }\n\n return createUser(userName, map, new EntityReference(userClass.getDocumentReference().getName(),\n EntityType.DOCUMENT), content, syntax, userRights, context);\n }\n\n /**\n * @deprecated since 2.4RC1 use\n * {@link #createUser(String, Map, EntityReference, String, Syntax, String, XWikiContext)} instead\n */\n @Deprecated\n public int createUser(String userName, Map map, String parent, String content, String syntaxId,\n String userRights, XWikiContext context) throws XWikiException\n {\n Syntax syntax;\n\n try {\n syntax = this.syntaxFactory.createSyntaxFromIdString(syntaxId);\n } catch (ParseException e) {\n try {\n syntax = this.syntaxFactory.createSyntaxFromIdString(getDefaultDocumentSyntax());\n } catch (ParseException e1) {\n // Let's jope that never happen\n LOGGER.warn(\"Failed to set parse syntax [\" + getDefaultDocumentSyntax() + \"]\", e);\n\n syntax = Syntax.XWIKI_2_0;\n }\n }\n\n return createUser(userName, map, this.relativeEntityReferenceResolver.resolve(parent, EntityType.DOCUMENT),\n content, syntax, userRights, context);\n }\n\n /**\n * Create a new user.\n * \n * @param userName the name of the user (without the space)\n * @param map extra datas to add to user profile object\n * @param parentReference the parent of the user profile\n * @param content the content of the user profile\n * @param syntax the syntax of the provided content\n * @param userRights the right of the user on his own profile page\n * @param context the XWiki context\n * @return
    \n *
  • 1: ok
  • \n *
  • -3: user already exists
  • \n *
\n * @throws XWikiException failed to create the new user\n */\n public int createUser(String userName, Map map, EntityReference parentReference, String content,\n Syntax syntax, String userRights, XWikiContext context) throws XWikiException\n {\n BaseClass baseclass = getUserClass(context);\n\n try {\n // TODO: Verify existing user\n XWikiDocument doc = getDocument(new DocumentReference(context.getDatabase(), \"XWiki\", userName), context);\n\n if (!doc.isNew()) {\n // TODO: throws Exception\n return -3;\n }\n\n BaseObject userObject =\n doc.newXObject(\n this.localReferenceEntityReferenceSerializer.serialize(baseclass.getDocumentReference()), context);\n baseclass.fromMap(map, userObject);\n\n doc.setParentReference(parentReference);\n doc.setContent(content);\n doc.setSyntax(syntax);\n doc.setCreatorReference(doc.getDocumentReference());\n doc.setAuthorReference(doc.getDocumentReference());\n\n protectUserPage(doc.getFullName(), userRights, doc, context);\n\n saveDocument(doc, context.getMessageTool().get(\"core.comment.createdUser\"), context);\n\n // Now let's add the user to XWiki.XWikiAllGroup\n setUserDefaultGroup(doc.getFullName(), context);\n\n return 1;\n } catch (Exception e) {\n Object[] args = {\"XWiki.\" + userName};\n throw new XWikiException(XWikiException.MODULE_XWIKI_USER, XWikiException.ERROR_XWIKI_USER_CREATE,\n \"Cannot create user {0}\", e, args);\n }\n }\n\n /**\n * @deprecated starting with XE 1.8.1 use\n * {@link #createUser(String, Map, String, String, String, String, XWikiContext)} instead\n */\n @Deprecated\n public int createUser(String xwikiname, Map map, String parent, String content, String userRights,\n XWikiContext context) throws XWikiException\n {\n return createUser(xwikiname, map, parent, content, Syntax.XWIKI_1_0.toIdString(), userRights, context);\n }\n\n public void setUserDefaultGroup(String fullwikiname, XWikiContext context) throws XWikiException\n {\n String groupsPreference = Param(\"xwiki.users.initialGroups\", \"XWiki.XWikiAllGroup\");\n\n if (groupsPreference != null) {\n String[] groups = groupsPreference.split(\",\");\n for (String groupName : groups) {\n if (StringUtils.isNotBlank(groupName)) {\n addUserToGroup(fullwikiname, groupName.trim(), context);\n }\n }\n }\n }\n\n protected void addUserToGroup(String userName, String groupName, XWikiContext context) throws XWikiException\n {\n BaseClass groupClass = getGroupClass(context);\n XWikiDocument groupDoc = getDocument(groupName, context);\n\n BaseObject memberObject =\n groupDoc.newXObject(\n this.localReferenceEntityReferenceSerializer.serialize(groupClass.getDocumentReference()), context);\n\n memberObject.setStringValue(\"member\", userName);\n\n if (groupDoc.isNew()) {\n saveDocument(groupDoc, context.getMessageTool().get(\"core.comment.addedUserToGroup\"), context);\n } else {\n // TODO Fix use of deprecated call.\n getHibernateStore().saveXWikiObject(memberObject, context, true);\n }\n\n try {\n XWikiGroupService gservice = getGroupService(context);\n gservice.addUserToGroup(userName, context.getDatabase(), groupName, context);\n } catch (Exception e) {\n LOGGER.error(\"Failed to update group service cache\", e);\n }\n }\n\n /**\n * @deprecated replaced by {@link #setUserDefaultGroup(String fullwikiname, XWikiContext context)}\n * @param context\n * @param fullwikiname\n * @throws XWikiException\n */\n @Deprecated\n public void SetUserDefaultGroup(XWikiContext context, String fullwikiname) throws XWikiException\n {\n setUserDefaultGroup(fullwikiname, context);\n }\n\n public void protectUserPage(String userName, String userRights, XWikiDocument doc, XWikiContext context)\n throws XWikiException\n {\n BaseClass rclass = getRightsClass(context);\n\n EntityReference rightClassReference =\n this.localReferenceEntityReferenceSerializer.serialize(rclass.getDocumentReference());\n\n // Add protection to the page\n BaseObject newrightsobject = doc.newXObject(rightClassReference, context);\n newrightsobject.setLargeStringValue(\"groups\", \"XWiki.XWikiAdminGroup\");\n newrightsobject.setStringValue(\"levels\", userRights);\n newrightsobject.setIntValue(\"allow\", 1);\n\n BaseObject newuserrightsobject = doc.newXObject(rightClassReference, context);\n newuserrightsobject.setLargeStringValue(\"users\", userName);\n newuserrightsobject.setStringValue(\"levels\", userRights);\n newuserrightsobject.setIntValue(\"allow\", 1);\n }\n\n /**\n * @deprecated replaced by {@link #protectUserPage(String,String,XWikiDocument,XWikiContext)}\n * @param context\n * @param fullwikiname\n * @param userRights\n * @param doc\n * @throws XWikiException\n */\n @Deprecated\n public void ProtectUserPage(XWikiContext context, String fullwikiname, String userRights, XWikiDocument doc)\n throws XWikiException\n {\n protectUserPage(fullwikiname, userRights, doc, context);\n }\n\n public User getUser(XWikiContext context)\n {\n XWikiUser xwikiUser = context.getXWikiUser();\n User user = new User(xwikiUser, context);\n return user;\n }\n\n public User getUser(String username, XWikiContext context)\n {\n XWikiUser xwikiUser = new XWikiUser(username);\n User user = new User(xwikiUser, context);\n return user;\n }\n\n /**\n * Prepares the localized resources, according to the selected language. From any point in the code (java, velocity\n * or groovy) the \"msg\" parameter holds an instance of the localized resource bundle, and the \"locale\" parameter\n * holds the current locale settings.\n * \n * @param context The request context.\n */\n public void prepareResources(XWikiContext context)\n {\n if (context.get(\"msg\") == null) {\n // String ilanguage = getInterfaceLanguagePreference(context);\n String dlanguage = getLanguagePreference(context);\n Locale locale = new Locale(dlanguage);\n context.put(\"locale\", locale);\n if (context.getResponse() != null) {\n context.getResponse().setLocale(locale);\n }\n ResourceBundle bundle = ResourceBundle.getBundle(\"ApplicationResources\", locale);\n if (bundle == null) {\n bundle = ResourceBundle.getBundle(\"ApplicationResources\");\n }\n XWikiMessageTool msg = new XWikiMessageTool(bundle, context);\n context.put(\"msg\", msg);\n VelocityContext vcontext = ((VelocityContext) context.get(\"vcontext\"));\n if (vcontext != null) {\n vcontext.put(\"msg\", msg);\n vcontext.put(\"locale\", locale);\n }\n @SuppressWarnings(\"unchecked\")\n Map gcontext = (Map) context.get(\"gcontext\");\n if (gcontext != null) {\n gcontext.put(\"msg\", msg);\n gcontext.put(\"locale\", locale);\n }\n }\n }\n\n public XWikiUser checkAuth(XWikiContext context) throws XWikiException\n {\n return getAuthService().checkAuth(context);\n }\n\n public boolean checkAccess(String action, XWikiDocument doc, XWikiContext context) throws XWikiException\n {\n if (action.equals(\"skin\") && (doc.getSpace().equals(\"skins\") || doc.getSpace().equals(\"resources\"))) {\n // We still need to call checkAuth to set the proper user.\n XWikiUser user = checkAuth(context);\n if (user != null) {\n context.setUser(user.getUser());\n }\n return true;\n }\n return getRightService().checkAccess(action, doc, context);\n }\n\n /**\n * @deprecated replaced by {@link #include(String topic, boolean isForm, XWikiContext context)}\n * @param topic\n * @param context\n * @param isForm\n * @return\n * @throws XWikiException\n */\n @Deprecated\n public String include(String topic, XWikiContext context, boolean isForm) throws XWikiException\n {\n return include(topic, isForm, context);\n }\n\n public String include(String topic, boolean isForm, XWikiContext context) throws XWikiException\n {\n String database = null, incdatabase = null;\n String prefixedTopic, localTopic;\n\n // Save current documents in the Velocity and Groovy contexts\n Document currentdoc = null, currentcdoc = null, currenttdoc = null;\n Document gcurrentdoc = null, gcurrentcdoc = null, gcurrenttdoc = null;\n VelocityContext vcontext = (VelocityContext) context.get(\"vcontext\");\n String currentDocName = context.getDatabase() + \":\" + context.getDoc().getFullName();\n if (vcontext != null) {\n currentdoc = (Document) vcontext.get(\"doc\");\n currentcdoc = (Document) vcontext.get(\"cdoc\");\n currenttdoc = (Document) vcontext.get(\"tdoc\");\n }\n @SuppressWarnings(\"unchecked\")\n Map gcontext = (Map) context.get(\"gcontext\");\n if (gcontext != null) {\n gcurrentdoc = (Document) gcontext.get(\"doc\");\n gcurrentcdoc = (Document) gcontext.get(\"cdoc\");\n gcurrenttdoc = (Document) gcontext.get(\"tdoc\");\n }\n\n try {\n int i0 = topic.indexOf(':');\n if (i0 != -1) {\n incdatabase = topic.substring(0, i0);\n database = context.getDatabase();\n context.setDatabase(incdatabase);\n prefixedTopic = topic;\n localTopic = topic.substring(i0 + 1);\n } else {\n prefixedTopic = context.getDatabase() + \":\" + topic;\n localTopic = topic;\n }\n\n XWikiDocument doc = null;\n try {\n LOGGER.debug(\"Including Topic \" + topic);\n try {\n @SuppressWarnings(\"unchecked\")\n Set includedDocs = (Set) context.get(\"included_docs\");\n if (includedDocs == null) {\n includedDocs = new HashSet();\n context.put(\"included_docs\", includedDocs);\n }\n\n if (includedDocs.contains(prefixedTopic) || currentDocName.equals(prefixedTopic)) {\n LOGGER.warn(\"Error on too many recursive includes for topic \" + topic);\n return \"Cannot make recursive include\";\n }\n includedDocs.add(prefixedTopic);\n } catch (Exception e) {\n }\n\n // Get document to include\n doc = getDocument(((XWikiDocument) context.get(\"doc\")).getSpace(), localTopic, context);\n\n if (checkAccess(\"view\", doc, context) == false) {\n throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS,\n XWikiException.ERROR_XWIKI_ACCESS_DENIED, \"Access to this document is denied: \" + doc);\n }\n } catch (XWikiException e) {\n LOGGER.warn(\"Exception Including Topic \" + topic, e);\n return \"Topic \" + topic + \" does not exist\";\n }\n\n XWikiDocument contentdoc = doc.getTranslatedDocument(context);\n\n String result;\n if (isForm) {\n // We do everything in the context of the including document\n if (database != null) {\n context.setDatabase(database);\n }\n\n // Allow including document in the XWiki Syntax 1.0 but also other syntaxes using the new rendering.\n if (contentdoc.getSyntax().equals(Syntax.XWIKI_1_0)) {\n result =\n getRenderingEngine().renderText(contentdoc.getContent(), contentdoc,\n (XWikiDocument) context.get(\"doc\"), context);\n } else {\n // Note: the Script macro in the new rendering checks for programming rights for the document in\n // the xwiki context.\n result = getRenderedContent(contentdoc, (XWikiDocument) context.get(\"doc\"), context);\n }\n } else {\n // We stay in the included document context\n\n // Allow including document in the XWiki Syntax 1.0 but also other syntaxes using the new rendering.\n if (contentdoc.getSyntax().equals(Syntax.XWIKI_1_0)) {\n result = getRenderingEngine().renderText(contentdoc.getContent(), contentdoc, doc, context);\n } else {\n // Since the Script macro checks for programming rights in the current document, we need to\n // temporarily set the contentdoc as the current doc before rendering it.\n XWikiDocument originalDoc = null;\n try {\n originalDoc = context.getDoc();\n context.put(\"doc\", doc);\n result = getRenderedContent(contentdoc, doc, context);\n } finally {\n context.put(\"doc\", originalDoc);\n }\n }\n }\n try {\n @SuppressWarnings(\"unchecked\")\n Set includedDocs = (Set) context.get(\"included_docs\");\n if (includedDocs != null) {\n includedDocs.remove(prefixedTopic);\n }\n } catch (Exception e) {\n }\n return result;\n } finally {\n if (database != null) {\n context.setDatabase(database);\n }\n\n if (currentdoc != null) {\n if (vcontext != null) {\n vcontext.put(\"doc\", currentdoc);\n }\n }\n if (gcurrentdoc != null) {\n if (gcontext != null) {\n gcontext.put(\"doc\", gcurrentdoc);\n }\n }\n if (currentcdoc != null) {\n if (vcontext != null) {\n vcontext.put(\"cdoc\", currentcdoc);\n }\n }\n if (gcurrentcdoc != null) {\n if (gcontext != null) {\n gcontext.put(\"cdoc\", gcurrentcdoc);\n }\n }\n if (currenttdoc != null) {\n if (vcontext != null) {\n vcontext.put(\"tdoc\", currenttdoc);\n }\n }\n if (gcurrenttdoc != null) {\n if (gcontext != null) {\n gcontext.put(\"tdoc\", gcurrenttdoc);\n }\n }\n }\n }\n\n /**\n * Render content from the passed included document, setting the correct security doc (sdoc) and including doc\n * (idoc). Note that this is needed for 2.0 syntax only since in 1.0 syntax the idoc and sdoc are set by\n * {@link com.xpn.xwiki.render.XWikiRenderingEngine#renderText}.\n * \n * @since 2.2M2\n */\n private String getRenderedContent(XWikiDocument includedDoc, XWikiDocument includingDoc, XWikiContext context)\n throws XWikiException\n {\n String result;\n XWikiDocument idoc = (XWikiDocument) context.get(\"idoc\");\n XWikiDocument sdoc = (XWikiDocument) context.get(\"sdoc\");\n\n context.put(\"idoc\", includingDoc);\n context.put(\"sdoc\", includedDoc);\n try {\n result = includedDoc.getRenderedContent(Syntax.XHTML_1_0, false, context);\n } finally {\n // Remove including doc or set the previous one\n if (idoc == null) {\n context.remove(\"idoc\");\n } else {\n context.put(\"idoc\", idoc);\n }\n\n // Remove security doc or set the previous one\n if (sdoc == null) {\n context.remove(\"sdoc\");\n } else {\n context.put(\"sdoc\", sdoc);\n }\n }\n\n return result;\n }\n\n public void deleteDocument(XWikiDocument doc, XWikiContext context) throws XWikiException\n {\n deleteDocument(doc, true, context);\n }\n\n public void deleteDocument(XWikiDocument doc, boolean totrash, XWikiContext context) throws XWikiException\n {\n ObservationManager om = Utils.getComponent(ObservationManager.class);\n\n // Inform notification mechanisms that a document is about to be deleted\n // Note that for the moment the event being send is a bridge event, as we are still passing around\n // an XWikiDocument as source and an XWikiContext as data.\n om.notify(new DocumentDeletingEvent(doc.getDocumentReference()), new XWikiDocument(doc.getDocumentReference()),\n context);\n\n if (hasRecycleBin(context) && totrash) {\n getRecycleBinStore().saveToRecycleBin(doc, context.getUser(), new Date(), context, true);\n }\n\n getStore().deleteXWikiDoc(doc, context);\n\n try {\n // Inform notification mecanisms that a document has been deleted\n // Note that for the moment the event being send is a bridge event, as we are still passing around\n // an XWikiDocument as source and an XWikiContext as data.\n // The source document is a new empty XWikiDocument to follow\n // DocumentUpdatedEvent policy: source document in new document and the old version is available using\n // doc.getOriginalDocument()\n if (om != null) {\n XWikiDocument blankDoc = new XWikiDocument(doc.getDocumentReference());\n // Again to follow general event policy, new document author is the user who modified the document (here\n // the modification is delete)\n blankDoc.setOriginalDocument(doc);\n blankDoc.setAuthor(context.getUser());\n blankDoc.setContentAuthor(context.getUser());\n om.notify(new DocumentDeletedEvent(doc.getDocumentReference()), blankDoc, context);\n }\n } catch (Exception ex) {\n LOGGER.error(\"Failed to send document delete notifications for document [\" + doc.getPrefixedFullName()\n + \"]\", ex);\n }\n }\n\n public String getDatabase()\n {\n return this.database;\n }\n\n public void setDatabase(String database)\n {\n this.database = database;\n }\n\n public void gc()\n {\n System.gc();\n }\n\n public long freeMemory()\n {\n return Runtime.getRuntime().freeMemory();\n }\n\n public long totalMemory()\n {\n return Runtime.getRuntime().totalMemory();\n }\n\n public long maxMemory()\n {\n return Runtime.getRuntime().maxMemory();\n }\n\n public String[] split(String str, String sep)\n {\n return StringUtils.split(str, sep);\n }\n\n public String printStrackTrace(Throwable e)\n {\n StringWriter strwriter = new StringWriter();\n PrintWriter writer = new PrintWriter(strwriter);\n e.printStackTrace(writer);\n\n return strwriter.toString();\n }\n\n /**\n * @since 2.2M2\n */\n public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference,\n XWikiContext context) throws XWikiException\n {\n return copyDocument(sourceDocumentReference, targetDocumentReference, null, true, context);\n }\n\n /**\n * @since 2.2M2\n */\n public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference,\n boolean reset, XWikiContext context) throws XWikiException\n {\n return copyDocument(sourceDocumentReference, targetDocumentReference, null, reset, context);\n }\n\n /**\n * @since 2.2M2\n */\n public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference,\n boolean reset, boolean force, boolean resetCreationData, XWikiContext context) throws XWikiException\n {\n return copyDocument(sourceDocumentReference, targetDocumentReference, null, reset, force, resetCreationData,\n context);\n }\n\n /**\n * @since 2.2M2\n */\n public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference,\n String wikilanguage, XWikiContext context) throws XWikiException\n {\n return copyDocument(sourceDocumentReference, targetDocumentReference, wikilanguage, true, context);\n }\n\n /**\n * @since 2.2M2\n */\n public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference,\n String wikilanguage, boolean reset, XWikiContext context) throws XWikiException\n {\n return copyDocument(sourceDocumentReference, targetDocumentReference, wikilanguage, reset, false, context);\n }\n\n /**\n * @since 2.2M2\n */\n public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference,\n String wikilanguage, boolean reset, boolean force, XWikiContext context) throws XWikiException\n {\n return copyDocument(sourceDocumentReference, targetDocumentReference, wikilanguage, reset, force, false,\n context);\n }\n\n /**\n * @since 2.2M2\n */\n public boolean copyDocument(DocumentReference sourceDocumentReference, DocumentReference targetDocumentReference,\n String wikilanguage, boolean reset, boolean force, boolean resetCreationData, XWikiContext context)\n throws XWikiException\n {\n String db = context.getDatabase();\n String sourceWiki = sourceDocumentReference.getWikiReference().getName();\n String targetWiki = targetDocumentReference.getWikiReference().getName();\n\n String sourceStringReference = this.defaultEntityReferenceSerializer.serialize(sourceDocumentReference);\n\n try {\n context.setDatabase(sourceWiki);\n XWikiDocument sdoc = getDocument(sourceDocumentReference, context);\n if (!sdoc.isNew()) {\n if (LOGGER.isInfoEnabled()) {\n LOGGER.info(\"Copying document [\" + sourceDocumentReference + \"] to [\" + targetDocumentReference\n + \"]\");\n }\n\n // Let's switch to the other database to verify if the document already exists\n context.setDatabase(targetWiki);\n XWikiDocument tdoc = getDocument(targetDocumentReference, context);\n // There is already an existing document\n if (!tdoc.isNew()) {\n if (force) {\n // We need to delete the previous document\n deleteDocument(tdoc, context);\n } else {\n return false;\n }\n }\n\n // Let's switch back again to the original db\n context.setDatabase(sourceWiki);\n\n if (wikilanguage == null) {\n tdoc = sdoc.copyDocument(targetDocumentReference, context);\n // forget past versions\n if (reset) {\n tdoc.setNew(true);\n tdoc.setVersion(\"1.1\");\n }\n if (resetCreationData) {\n Date now = new Date();\n tdoc.setCreationDate(now);\n tdoc.setContentUpdateDate(now);\n tdoc.setDate(now);\n tdoc.setCreator(context.getUser());\n tdoc.setAuthor(context.getUser());\n }\n\n // We don't want to trigger a new version otherwise the version number will be wrong\n tdoc.setMetaDataDirty(false);\n tdoc.setContentDirty(false);\n\n saveDocument(tdoc, \"Copied from \" + sourceStringReference, context);\n\n if (!reset) {\n context.setDatabase(sourceWiki);\n XWikiDocumentArchive txda = getVersioningStore().getXWikiDocumentArchive(sdoc, context);\n context.setDatabase(targetWiki);\n txda = txda.clone(tdoc.getId(), context);\n getVersioningStore().saveXWikiDocArchive(txda, true, context);\n } else {\n getVersioningStore().resetRCSArchive(tdoc, true, context);\n }\n\n context.setDatabase(targetWiki);\n for (XWikiAttachment attachment : tdoc.getAttachmentList()) {\n getAttachmentStore().saveAttachmentContent(attachment, false, context, true);\n }\n\n // Now we need to copy the translations\n context.setDatabase(sourceWiki);\n List tlist = sdoc.getTranslationList(context);\n for (String clanguage : tlist) {\n XWikiDocument stdoc = sdoc.getTranslatedDocument(clanguage, context);\n if (LOGGER.isInfoEnabled()) {\n LOGGER.info(\"Copying document [\" + sourceWiki + \"], language [\" + clanguage + \"] to [\"\n + targetDocumentReference + \"]\");\n }\n\n context.setDatabase(targetWiki);\n XWikiDocument ttdoc = tdoc.getTranslatedDocument(clanguage, context);\n\n // There is already an existing document\n if (ttdoc != tdoc) {\n return false;\n }\n\n // Let's switch back again to the original db\n context.setDatabase(sourceWiki);\n\n ttdoc = stdoc.copyDocument(targetDocumentReference, context);\n\n // forget past versions\n if (reset) {\n ttdoc.setNew(true);\n ttdoc.setVersion(\"1.1\");\n }\n if (resetCreationData) {\n Date now = new Date();\n ttdoc.setCreationDate(now);\n ttdoc.setContentUpdateDate(now);\n ttdoc.setDate(now);\n ttdoc.setCreator(context.getUser());\n ttdoc.setAuthor(context.getUser());\n }\n\n // we don't want to trigger a new version\n // otherwise the version number will be wrong\n tdoc.setMetaDataDirty(false);\n tdoc.setContentDirty(false);\n\n saveDocument(ttdoc, \"Copied from \" + sourceStringReference, context);\n\n if (!reset) {\n context.setDatabase(sourceWiki);\n XWikiDocumentArchive txda = getVersioningStore().getXWikiDocumentArchive(sdoc, context);\n context.setDatabase(targetWiki);\n txda = txda.clone(tdoc.getId(), context);\n getVersioningStore().saveXWikiDocArchive(txda, true, context);\n } else {\n getVersioningStore().resetRCSArchive(tdoc, true, context);\n }\n }\n } else {\n // We want only one language in the end\n XWikiDocument stdoc = sdoc.getTranslatedDocument(wikilanguage, context);\n\n tdoc = stdoc.copyDocument(targetDocumentReference, context);\n\n // forget language\n tdoc.setDefaultLanguage(wikilanguage);\n tdoc.setLanguage(\"\");\n // forget past versions\n if (reset) {\n tdoc.setNew(true);\n tdoc.setVersion(\"1.1\");\n }\n if (resetCreationData) {\n Date now = new Date();\n tdoc.setCreationDate(now);\n tdoc.setContentUpdateDate(now);\n tdoc.setDate(now);\n tdoc.setCreator(context.getUser());\n tdoc.setAuthor(context.getUser());\n }\n\n // we don't want to trigger a new version\n // otherwise the version number will be wrong\n tdoc.setMetaDataDirty(false);\n tdoc.setContentDirty(false);\n\n saveDocument(tdoc, \"Copied from \" + sourceStringReference, context);\n\n if (!reset) {\n context.setDatabase(sourceWiki);\n XWikiDocumentArchive txda = getVersioningStore().getXWikiDocumentArchive(sdoc, context);\n context.setDatabase(targetWiki);\n txda = txda.clone(tdoc.getId(), context);\n getVersioningStore().saveXWikiDocArchive(txda, true, context);\n } else {\n getVersioningStore().resetRCSArchive(tdoc, true, context);\n }\n\n context.setDatabase(targetWiki);\n for (XWikiAttachment attachment : tdoc.getAttachmentList()) {\n getAttachmentStore().saveAttachmentContent(attachment, false, context, true);\n }\n }\n }\n return true;\n } finally {\n context.setDatabase(db);\n }\n }\n\n public int copySpaceBetweenWikis(String space, String sourceWiki, String targetWiki, String language,\n XWikiContext context) throws XWikiException\n {\n return copySpaceBetweenWikis(space, sourceWiki, targetWiki, language, false, context);\n }\n\n public int copySpaceBetweenWikis(String space, String sourceWiki, String targetWiki, String language,\n boolean clean, XWikiContext context) throws XWikiException\n {\n String db = context.getDatabase();\n int nb = 0;\n // Workaround for XWIKI-3915: Do not use XWikiStoreInterface#searchDocumentNames since currently it has the\n // side effect of hidding hidden documents and no other workaround exists than directly using\n // XWikiStoreInterface#search directly\n String sql = \"select distinct doc.fullName from XWikiDocument as doc\";\n List parameters = new ArrayList();\n if (space != null) {\n sql += \" where doc.space = ?\";\n parameters.add(space);\n }\n\n if (clean) {\n try {\n context.setDatabase(targetWiki);\n List list = getStore().search(sql, 0, 0, parameters, context);\n if (LOGGER.isInfoEnabled()) {\n LOGGER.info(\"Deleting \" + list.size() + \" documents from wiki \" + targetWiki);\n }\n\n for (String docname : list) {\n XWikiDocument doc = getDocument(docname, context);\n deleteDocument(doc, context);\n }\n } finally {\n context.setDatabase(db);\n }\n }\n\n try {\n context.setDatabase(sourceWiki);\n List list = getStore().search(sql, 0, 0, context);\n if (LOGGER.isInfoEnabled()) {\n LOGGER.info(\"Copying \" + list.size() + \" documents from wiki \" + sourceWiki + \" to wiki \" + targetWiki);\n }\n\n WikiReference sourceWikiReference = new WikiReference(sourceWiki);\n WikiReference targetWikiReference = new WikiReference(targetWiki);\n for (String docname : list) {\n DocumentReference sourceDocumentReference = this.currentMixedDocumentReferenceResolver.resolve(docname);\n sourceDocumentReference =\n sourceDocumentReference.replaceParent(sourceDocumentReference.getWikiReference(),\n sourceWikiReference);\n DocumentReference targetDocumentReference =\n sourceDocumentReference.replaceParent(sourceWikiReference, targetWikiReference);\n copyDocument(sourceDocumentReference, targetDocumentReference, language, context);\n nb++;\n }\n return nb;\n } finally {\n context.setDatabase(db);\n }\n }\n\n /**\n * Copy an entire wiki to a target wiki.\n *

\n * It does not override document already existing in target wiki.\n * \n * @param sourceWiki the source wiki identifier\n * @param targetWiki the target wiki identifier\n * @param language the language to copy\n * @param context the XWiki context\n * @return the number of copied documents\n * @throws XWikiException failed to copy wiki\n */\n public int copyWiki(String sourceWiki, String targetWiki, String language, XWikiContext context)\n throws XWikiException\n {\n return copyWiki(sourceWiki, targetWiki, language, false, context);\n }\n\n /**\n * Copy an entire wiki to a target wiki.\n * \n * @param sourceWiki the source wiki identifier\n * @param targetWiki the target wiki identifier\n * @param language the language to copy\n * @param clean clean the target wiki before copying\n * @param context the XWiki context\n * @return the number of copied documents\n * @throws XWikiException failed to copy wiki\n */\n public int copyWiki(String sourceWiki, String targetWiki, String language, boolean clean, XWikiContext context)\n throws XWikiException\n {\n return copySpaceBetweenWikis(null, sourceWiki, targetWiki, language, clean, context);\n }\n\n /**\n * @deprecated use WikiManager plugin instead\n */\n @Deprecated\n public int createNewWiki(String wikiName, String wikiUrl, String wikiAdmin, String baseWikiName,\n String description, String wikilanguage, boolean failOnExist, XWikiContext context) throws XWikiException\n {\n String database = context.getDatabase();\n wikiName = wikiName.toLowerCase();\n\n try {\n XWikiDocument userdoc = getDocument(wikiAdmin, context);\n\n // User does not exist\n if (userdoc.isNew()) {\n if (LOGGER.isErrorEnabled()) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"user does not exist\");\n }\n return -2;\n }\n\n // User is not active\n if (!(userdoc.getIntValue(\"XWiki.XWikiUsers\", \"active\") == 1)) {\n if (LOGGER.isErrorEnabled()) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"user is not active\");\n }\n return -3;\n }\n\n String wikiForbiddenList = Param(\"xwiki.virtual.reserved_wikis\");\n if (Util.contains(wikiName, wikiForbiddenList, \", \")) {\n if (LOGGER.isErrorEnabled()) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki name is forbidden\");\n }\n return -4;\n }\n\n String wikiServerPage = \"XWikiServer\" + wikiName.substring(0, 1).toUpperCase() + wikiName.substring(1);\n // Verify is server page already exist\n XWikiDocument serverdoc = getDocument(SYSTEM_SPACE, wikiServerPage, context);\n if (serverdoc.isNew()) {\n // clear entry in virtual wiki cache\n this.virtualWikiMap.remove(wikiUrl);\n\n // Create Wiki Server page\n serverdoc.setStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, \"server\", wikiUrl);\n serverdoc.setStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, \"owner\", wikiAdmin);\n if (description != null) {\n serverdoc.setLargeStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, \"description\", description);\n }\n if (wikilanguage != null) {\n serverdoc.setStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, \"language\", wikilanguage);\n }\n if (!getDefaultDocumentSyntax().equals(Syntax.XWIKI_1_0.toIdString())) {\n serverdoc.setContent(\"{{include document=\\\"XWiki.XWikiServerForm\\\"/}}\\n\");\n serverdoc.setSyntax(Syntax.XWIKI_2_0);\n } else {\n serverdoc.setContent(\"#includeForm(\\\"XWiki.XWikiServerForm\\\")\\n\");\n serverdoc.setSyntax(Syntax.XWIKI_1_0);\n }\n serverdoc.setParentReference(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE);\n saveDocument(serverdoc, context);\n } else {\n // If we are not allowed to continue if server page already exists\n if (failOnExist) {\n if (LOGGER.isErrorEnabled()) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki server page already exists\");\n }\n return -5;\n } else if (LOGGER.isWarnEnabled()) {\n LOGGER.warn(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki server page already exists\");\n }\n }\n\n // Create wiki database\n try {\n context.setDatabase(getDatabase());\n getStore().createWiki(wikiName, context);\n } catch (XWikiException e) {\n if (LOGGER.isErrorEnabled()) {\n if (e.getCode() == 10010) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki database already exists\");\n } else if (e.getCode() == 10011) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki database creation failed\");\n } else {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki database creation threw exception\", e);\n }\n }\n } catch (Exception e) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki database creation threw exception\", e);\n }\n\n try {\n updateDatabase(wikiName, true, false, context);\n } catch (Exception e) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki database shema update threw exception\", e);\n return -6;\n }\n\n // Copy base wiki\n int nb = copyWiki(baseWikiName, wikiName, wikilanguage, context);\n // Save the number of docs copied in the context\n context.put(\"nbdocs\", Integer.valueOf(nb));\n\n // Create user page in his wiki\n // Let's not create it anymore.. this makes the creator loose\n // super admin rights on his wiki\n // copyDocument(wikiAdmin, getDatabase(), wikiName, wikilanguage, context);\n\n // Modify rights in user wiki\n context.setDatabase(wikiName);\n /*\n * XWikiDocument wikiprefdoc = getDocument(\"XWiki.XWikiPreferences\", context);\n * wikiprefdoc.setStringValue(\"XWiki.XWikiGlobalRights\", \"users\", wikiAdmin);\n * wikiprefdoc.setStringValue(\"XWiki.XWikiGlobalRights\", \"levels\", \"admin, edit\");\n * wikiprefdoc.setIntValue(\"XWiki.XWikiGlobalRights\", \"allow\", 1); saveDocument(wikiprefdoc, context);\n */\n return 1;\n } catch (Exception e) {\n LOGGER.error(\"Wiki creation (\" + wikiName + \",\" + wikiUrl + \",\" + wikiAdmin + \") failed: \"\n + \"wiki creation threw exception\", e);\n return -10;\n } finally {\n context.setDatabase(database);\n }\n }\n\n public String getEncoding()\n {\n return Param(\"xwiki.encoding\", \"UTF-8\");\n }\n\n public URL getServerURL(String database, XWikiContext context) throws MalformedURLException\n {\n String serverurl = null;\n\n // In virtual wiki path mode the server is the standard one\n if (\"1\".equals(Param(\"xwiki.virtual.usepath\", \"1\"))) {\n return null;\n }\n\n if (database != null) {\n String db = context.getDatabase();\n try {\n context.setDatabase(getDatabase());\n XWikiDocument doc = getDocument(\"XWiki.XWikiServer\" + StringUtils.capitalize(database), context);\n BaseObject serverobject = doc.getXObject(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE);\n if (serverobject != null) {\n String server = serverobject.getStringValue(\"server\");\n if (server != null) {\n String protocol = context.getWiki().Param(\"xwiki.url.protocol\", null);\n if (protocol == null) {\n int iSecure = serverobject.getIntValue(\"secure\", -1);\n // Check the request object if the \"secure\" property is undefined.\n boolean secure = iSecure == 1 || (iSecure < 0 && context.getRequest().isSecure());\n protocol = secure ? \"https\" : \"http\";\n }\n long port = context.getURL().getPort();\n if (port == 80 || port == 443) {\n port = -1;\n }\n if (port != -1) {\n serverurl = protocol + \"://\" + server + \":\" + port + \"/\";\n } else {\n serverurl = protocol + \"://\" + server + \"/\";\n }\n }\n }\n } catch (Exception ex) {\n } finally {\n context.setDatabase(db);\n }\n }\n\n if (serverurl != null) {\n return new URL(serverurl);\n } else {\n return null;\n }\n }\n\n public String getServletPath(String wikiName, XWikiContext context)\n {\n // unless we are in virtual wiki path mode we should return null\n if (!context.getMainXWiki().equalsIgnoreCase(wikiName) && \"1\".equals(Param(\"xwiki.virtual.usepath\", \"1\"))) {\n String database = context.getDatabase();\n try {\n context.setDatabase(context.getMainXWiki());\n XWikiDocument doc = getDocument(getServerWikiPage(wikiName), context);\n BaseObject serverobject = doc.getXObject(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE);\n if (serverobject != null) {\n String server = serverobject.getStringValue(\"server\");\n return \"wiki/\" + server + \"/\";\n }\n } catch (Exception e) {\n LOGGER.error(\"Failed to get URL for provided wiki [\" + wikiName + \"]\", e);\n } finally {\n context.setDatabase(database);\n }\n }\n\n String servletPath = Param(\"xwiki.servletpath\", \"\");\n\n if (context.getRequest() != null) {\n if (StringUtils.isEmpty(servletPath)) {\n String currentServletpath = context.getRequest().getServletPath();\n if (currentServletpath != null && currentServletpath.startsWith(\"/bin\")) {\n servletPath = \"bin/\";\n } else {\n servletPath = Param(\"xwiki.defaultservletpath\", \"bin/\");\n }\n }\n }\n\n return servletPath;\n }\n\n public String getWebAppPath(XWikiContext context)\n {\n String path = context.getURL().getPath();\n String contextPath = Param(\"xwiki.webapppath\", \"\");\n if (contextPath.equals(\"\")) {\n try {\n contextPath = context.getRequest().getContextPath();\n // TODO We're using URL parts in a wrong way, since contextPath and servletPath are\n // returned with a leading /, while we need a trailing /. This code moves the / from\n // the beginning to the end.\n // If the app is deployed as the ROOT ap, then there's no need to move the /.\n if (contextPath.length() > 0) {\n contextPath = contextPath.substring(1) + \"/\";\n }\n } catch (Exception e) {\n contextPath = path.substring(0, path.indexOf('/', 1) + 1);\n }\n }\n\n return contextPath;\n }\n\n /**\n * @since 2.2.1\n */\n public String getURL(DocumentReference documentReference, String action, String queryString, String anchor,\n XWikiContext context)\n {\n XWikiDocument doc = new XWikiDocument(documentReference);\n\n URL url =\n context.getURLFactory().createURL(doc.getSpace(), doc.getName(), action, queryString, anchor,\n doc.getDatabase(), context);\n return context.getURLFactory().getURL(url, context);\n }\n\n /**\n * @deprecated since 2.2.1 use {@link #getURL(DocumentReference, String, String, String, XWikiContext)}\n */\n @Deprecated\n public String getURL(String fullname, String action, String queryString, String anchor, XWikiContext context)\n {\n XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname));\n\n URL url =\n context.getURLFactory().createURL(doc.getSpace(), doc.getName(), action, queryString, anchor,\n doc.getDatabase(), context);\n return context.getURLFactory().getURL(url, context);\n }\n\n public String getURL(String fullname, String action, String querystring, XWikiContext context)\n {\n return getURL(fullname, action, querystring, null, context);\n }\n\n /**\n * @since 2.3M2\n */\n public String getURL(DocumentReference reference, String action, XWikiContext context)\n {\n return getURL(reference, action, null, null, context);\n }\n\n /**\n * @deprecated since 2.3M2 use {@link #getURL(DocumentReference, String, XWikiContext)}\n */\n @Deprecated\n public String getURL(String fullname, String action, XWikiContext context)\n {\n return getURL(fullname, action, null, null, context);\n }\n\n public String getExternalURL(String fullname, String action, XWikiContext context) throws XWikiException\n {\n XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname));\n\n URL url =\n context.getURLFactory().createExternalURL(doc.getSpace(), doc.getName(), action, null, null,\n doc.getDatabase(), context);\n return url.toString();\n }\n\n public String getExternalURL(String fullname, String action, String querystring, XWikiContext context)\n throws XWikiException\n {\n XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname));\n\n URL url =\n context.getURLFactory().createExternalURL(doc.getSpace(), doc.getName(), action, querystring, null,\n doc.getDatabase(), context);\n return url.toString();\n }\n\n public String getAttachmentURL(String fullname, String filename, XWikiContext context) throws XWikiException\n {\n return getAttachmentURL(fullname, filename, null, context);\n }\n\n /**\n * @since 2.5RC1\n */\n public String getAttachmentURL(String fullname, String filename, String queryString, XWikiContext context)\n throws XWikiException\n {\n XWikiDocument doc = new XWikiDocument(this.currentMixedDocumentReferenceResolver.resolve(fullname));\n return doc.getAttachmentURL(filename, \"download\", queryString, context);\n }\n\n // Usefull date functions\n\n public Date getCurrentDate()\n {\n return new Date();\n }\n\n public int getTimeDelta(long time)\n {\n Date ctime = new Date();\n return (int) (ctime.getTime() - time);\n }\n\n public Date getDate(long time)\n {\n return new Date(time);\n }\n\n public boolean isMultiLingual(XWikiContext context)\n {\n return \"1\".equals(getXWikiPreference(\"multilingual\", \"1\", context));\n }\n\n /**\n * @return true for multi-wiki/false for mono-wiki\n */\n public boolean isVirtualMode()\n {\n return \"1\".equals(Param(\"xwiki.virtual\"));\n }\n\n public boolean isLDAP()\n {\n return \"1\".equals(Param(\"xwiki.authentication.ldap\"));\n }\n\n public int checkActive(XWikiContext context) throws XWikiException\n {\n return checkActive(context.getUser(), context);\n }\n\n public int checkActive(String user, XWikiContext context) throws XWikiException\n {\n int active = 1;\n\n // These users are necessarily active\n if (user.equals(XWikiRightService.GUEST_USER_FULLNAME)\n || (user.equals(XWikiRightService.SUPERADMIN_USER_FULLNAME))) {\n return active;\n }\n\n String checkactivefield = getXWikiPreference(\"auth_active_check\", context);\n if (checkactivefield.equals(\"1\")) {\n XWikiDocument userdoc = getDocument(user, context);\n active = userdoc.getIntValue(\"XWiki.XWikiUsers\", \"active\");\n }\n\n return active;\n }\n\n /**\n * @since 2.3M1\n */\n public DocumentReference getDocumentReference(XWikiRequest request, XWikiContext context)\n {\n DocumentReference reference;\n if (context.getMode() == XWikiContext.MODE_PORTLET) {\n if (request.getParameter(\"topic\") != null) {\n reference = this.currentMixedDocumentReferenceResolver.resolve(request.getParameter(\"topic\"));\n } else {\n // Point to this wiki's home page\n reference =\n new DocumentReference(context.getDatabase(),\n this.defaultEntityReferenceValueProvider.getDefaultValue(EntityType.SPACE),\n this.defaultEntityReferenceValueProvider.getDefaultValue(EntityType.DOCUMENT));\n }\n } else if (context.getMode() == XWikiContext.MODE_XMLRPC) {\n reference =\n new DocumentReference(context.getDatabase(), context.getDoc().getDocumentReference()\n .getLastSpaceReference().getName(), context.getDoc().getDocumentReference().getName());\n } else {\n String action = context.getAction();\n if ((request.getParameter(\"topic\") != null) && (action.equals(\"edit\") || action.equals(\"inline\"))) {\n reference = this.currentMixedDocumentReferenceResolver.resolve(request.getParameter(\"topic\"));\n } else {\n // TODO: Introduce a XWikiURL class in charge of getting the information relevant\n // to XWiki from a request URL (action, space, document name, file, etc)\n\n // Important: We cannot use getPathInfo() as the container encodes it and different\n // containers encode it differently, depending on their internal behavior and how\n // they are configured. Thus to make this container-proof we use the\n // getRequestURI() which isn't modified by the container and is thus only\n // URL-encoded.\n\n // Note: Ideally we should modify the getDocumentNameFromPath method but in order\n // not to introduce any new bug right now we're reconstructing a path info that we\n // pass to it using the following algorithm:\n // path info = requestURI - (contextPath + servletPath)\n\n String path = request.getRequestURI();\n\n // Remove the (eventual) context path from the URI, usually /xwiki\n path = stripSegmentFromPath(path, request.getContextPath());\n\n // Remove the (eventual) servlet path from the URI, usually /bin\n String servletPath = request.getServletPath();\n path = stripSegmentFromPath(path, servletPath);\n\n // We need to get rid of the wiki name in case of a XEM in usepath mode\n if (\"1\".equals(Param(\"xwiki.virtual.usepath\", \"1\"))\n && servletPath.equals(\"/\" + Param(\"xwiki.virtual.usepath.servletpath\", \"wiki\"))) {\n // Virtual mode, skip the wiki name\n if (path.indexOf('/', 1) < 0) {\n path = \"\";\n } else {\n path = path.substring(path.indexOf('/', 1));\n }\n }\n\n // Fix error in some containers, which don't hide the jsessionid parameter from the URL\n if (path.indexOf(\";jsessionid=\") != -1) {\n path = path.substring(0, path.indexOf(\";jsessionid=\"));\n }\n reference = getDocumentReferenceFromPath(path, context);\n }\n }\n\n return reference;\n }\n\n /**\n * @deprecated since 2.3M1 use {@link #getDocumentReferenceFromPath(String, XWikiContext)} instead\n */\n @Deprecated\n public String getDocumentName(XWikiRequest request, XWikiContext context)\n {\n return this.localStringEntityReferenceSerializer.serialize(getDocumentReference(request, context));\n }\n\n /**\n * Helper method, removes a predefined path segment (the context path or the servel path) from the start of the\n * requested URI and returns the remainder. This method is needed because special characters in the path can be\n * URL-encoded, depending on whether the request is forwarded through the request dispatcher or not, and also\n * depending on the client (some browsers encode -, while some don't).\n * \n * @param path the path, as taken from the requested URI\n * @param segment the segment to remove, as reported by the container\n * @return the path with the specified segment trimmed from its start\n */\n public static String stripSegmentFromPath(String path, String segment)\n {\n if (!path.startsWith(segment)) {\n // The context path probably contains special characters that are encoded in the URL\n try {\n segment = URIUtil.encodePath(segment);\n } catch (URIException e) {\n LOGGER.warn(\"Invalid path: [\" + segment + \"]\");\n }\n }\n if (!path.startsWith(segment)) {\n // Some clients also encode -, although it's allowed in the path\n segment = segment.replaceAll(\"-\", \"%2D\");\n }\n if (!path.startsWith(segment)) {\n // Can't find the context path in the URL (shouldn't happen), just skip to the next path segment\n return path.substring(path.indexOf('/', 1));\n }\n return path.substring(segment.length());\n }\n\n public boolean prepareDocuments(XWikiRequest request, XWikiContext context, VelocityContext vcontext)\n throws XWikiException\n {\n XWikiDocument doc;\n context.getWiki().prepareResources(context);\n DocumentReference reference = getDocumentReference(request, context);\n if (context.getAction().equals(\"register\")) {\n setPhonyDocument(reference, context, vcontext);\n doc = context.getDoc();\n } else {\n try {\n doc = getDocument(reference, context);\n } catch (XWikiException e) {\n doc = context.getDoc();\n if (context.getAction().equals(\"delete\")) {\n if (doc == null) {\n setPhonyDocument(reference, context, vcontext);\n }\n if (!checkAccess(\"admin\", doc, context)) {\n throw e;\n }\n } else {\n throw e;\n }\n }\n }\n\n // We need to check rights before we look for translations\n // Otherwise we don't have the user language\n if (checkAccess(context.getAction(), doc, context) == false) {\n Object[] args = {doc.getFullName(), context.getUser()};\n setPhonyDocument(reference, context, vcontext);\n throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,\n \"Access to document {0} has been denied to user {1}\", null, args);\n } else if (checkActive(context) == 0) { // if auth_active_check, check if user is inactive\n boolean allow = false;\n String action = context.getAction();\n /*\n * Allow inactive users to see skins, ressources, SSX, JSX and downloads they could have seen as guest. The\n * rational behind this behaviour is that inactive users should be able to access the same UI that guests\n * are used to see, including custom icons, panels, and so on...\n */\n if ((action.equals(\"skin\") && (doc.getSpace().equals(\"skins\") || doc.getSpace().equals(\"resources\")))\n || ((action.equals(\"skin\") || action.equals(\"download\") || action.equals(\"ssx\") || action.equals(\"jsx\")) && getRightService()\n .hasAccessLevel(\"view\", XWikiRightService.GUEST_USER_FULLNAME, doc.getPrefixedFullName(), context))\n || ((action.equals(\"view\") && doc.getFullName().equals(\"XWiki.AccountValidation\")))) {\n allow = true;\n } else {\n String allowed = Param(\"xwiki.inactiveuser.allowedpages\", \"\");\n if (context.getAction().equals(\"view\") && !allowed.equals(\"\")) {\n String[] allowedList = StringUtils.split(allowed, \" ,\");\n for (int i = 0; i < allowedList.length; i++) {\n if (allowedList[i].equals(doc.getFullName())) {\n allow = true;\n break;\n }\n }\n }\n }\n if (!allow) {\n Object[] args = {context.getUser()};\n setPhonyDocument(reference, context, vcontext);\n throw new XWikiException(XWikiException.MODULE_XWIKI_USER, XWikiException.ERROR_XWIKI_USER_INACTIVE,\n \"User {0} account is inactive\", null, args);\n }\n }\n\n context.put(\"doc\", doc);\n vcontext.put(\"doc\", doc.newDocument(context));\n vcontext.put(\"cdoc\", vcontext.get(\"doc\"));\n XWikiDocument tdoc = doc.getTranslatedDocument(context);\n try {\n String rev = (String) context.get(\"rev\");\n if (StringUtils.isNotEmpty(rev)) {\n tdoc = getDocument(tdoc, rev, context);\n }\n } catch (Exception ex) {\n // Invalid version, just use the most recent one\n }\n context.put(\"tdoc\", tdoc);\n vcontext.put(\"tdoc\", tdoc.newDocument(context));\n\n return true;\n }\n\n /**\n * @since 2.3M1\n */\n public void setPhonyDocument(DocumentReference reference, XWikiContext context, VelocityContext vcontext)\n {\n XWikiDocument doc = new XWikiDocument(reference);\n doc.setElements(XWikiDocument.HAS_ATTACHMENTS | XWikiDocument.HAS_OBJECTS);\n doc.setStore(getStore());\n context.put(\"doc\", doc);\n vcontext.put(\"doc\", doc.newDocument(context));\n vcontext.put(\"cdoc\", vcontext.get(\"doc\"));\n vcontext.put(\"tdoc\", vcontext.get(\"doc\"));\n }\n\n /**\n * @deprecated since 2.3M1 use {@link #setPhonyDocument(DocumentReference, XWikiContext, VelocityContext)}\n */\n @Deprecated\n public void setPhonyDocument(String docName, XWikiContext context, VelocityContext vcontext)\n {\n setPhonyDocument(this.currentMixedDocumentReferenceResolver.resolve(docName), context, vcontext);\n }\n\n public XWikiEngineContext getEngineContext()\n {\n return this.engine_context;\n }\n\n public void setEngineContext(XWikiEngineContext engine_context)\n {\n this.engine_context = engine_context;\n }\n\n public URLPatternMatcher getUrlPatternMatcher()\n {\n return this.urlPatternMatcher;\n }\n\n public void setUrlPatternMatcher(URLPatternMatcher urlPatternMatcher)\n {\n this.urlPatternMatcher = urlPatternMatcher;\n }\n\n public void setAuthService(XWikiAuthService authService)\n {\n this.authService = authService;\n }\n\n public void setRightService(XWikiRightService rightService)\n {\n this.rightService = rightService;\n }\n\n public XWikiGroupService getGroupService(XWikiContext context) throws XWikiException\n {\n synchronized (this.GROUP_SERVICE_LOCK) {\n if (this.groupService == null) {\n String groupClass =\n Param(\"xwiki.authentication.groupclass\", \"com.xpn.xwiki.user.impl.xwiki.XWikiGroupServiceImpl\");\n\n try {\n this.groupService = (XWikiGroupService) Class.forName(groupClass).newInstance();\n } catch (Exception e) {\n LOGGER.error(\"Failed to instantiate custom group service class: \" + e.getMessage(), e);\n this.groupService = new XWikiGroupServiceImpl();\n }\n this.groupService.init(this, context);\n }\n\n return this.groupService;\n }\n }\n\n public void setGroupService(XWikiGroupService groupService)\n {\n this.groupService = groupService;\n }\n\n // added some log statements to make debugging easier - LBlaze 2005.06.02\n public XWikiAuthService getAuthService()\n {\n synchronized (this.AUTH_SERVICE_LOCK) {\n if (this.authService == null) {\n\n LOGGER.info(\"Initializing AuthService...\");\n\n String authClass = Param(\"xwiki.authentication.authclass\");\n if (StringUtils.isNotEmpty(authClass)) {\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Using custom AuthClass \" + authClass + \".\");\n }\n } else {\n if (isLDAP()) {\n authClass = \"com.xpn.xwiki.user.impl.LDAP.XWikiLDAPAuthServiceImpl\";\n } else {\n authClass = \"com.xpn.xwiki.user.impl.xwiki.XWikiAuthServiceImpl\";\n }\n\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Using default AuthClass \" + authClass + \".\");\n }\n }\n\n try {\n this.authService = (XWikiAuthService) Class.forName(authClass).newInstance();\n LOGGER.debug(\"Initialized AuthService using Relfection.\");\n } catch (Exception e) {\n LOGGER.warn(\"Failed to initialize AuthService \" + authClass\n + \" using Reflection, trying default implementations using 'new'.\", e);\n\n if (isLDAP()) {\n this.authService = new XWikiLDAPAuthServiceImpl();\n } else {\n this.authService = new XWikiAuthServiceImpl();\n }\n\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Initialized AuthService \" + this.authService.getClass().getName()\n + \" using 'new'.\");\n }\n }\n }\n\n return this.authService;\n }\n }\n\n // added some log statements to make debugging easier - LBlaze 2005.06.02\n public XWikiRightService getRightService()\n {\n synchronized (this.RIGHT_SERVICE_LOCK) {\n if (this.rightService == null) {\n LOGGER.info(\"Initializing RightService...\");\n\n String rightsClass = Param(\"xwiki.authentication.rightsclass\");\n if (rightsClass != null) {\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Using custom RightsClass \" + rightsClass + \".\");\n }\n } else {\n rightsClass = \"com.xpn.xwiki.user.impl.xwiki.XWikiRightServiceImpl\";\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Using default RightsClass \" + rightsClass + \".\");\n }\n }\n\n try {\n this.rightService = (XWikiRightService) Class.forName(rightsClass).newInstance();\n LOGGER.debug(\"Initialized RightService using Reflection.\");\n } catch (Exception e) {\n LOGGER.warn(\"Failed to initialize RightService \" + rightsClass\n + \" using Reflection, trying default implementation using 'new'.\", e);\n\n this.rightService = new XWikiRightServiceImpl();\n\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Initialized RightService \" + this.rightService.getClass().getName()\n + \" using 'new'.\");\n }\n }\n }\n\n return this.rightService;\n }\n }\n\n public XWikiStatsService getStatsService(XWikiContext context)\n {\n synchronized (this.STATS_SERVICE_LOCK) {\n if (this.statsService == null) {\n if (\"1\".equals(Param(\"xwiki.stats\", \"1\"))) {\n String storeClass = Param(\"xwiki.stats.class\", \"com.xpn.xwiki.stats.impl.XWikiStatsServiceImpl\");\n try {\n this.statsService = (XWikiStatsService) Class.forName(storeClass).newInstance();\n } catch (Exception e) {\n e.printStackTrace();\n this.statsService = new XWikiStatsServiceImpl();\n }\n\n this.statsService.init(context);\n }\n }\n\n return this.statsService;\n }\n }\n\n public XWikiURLFactoryService getURLFactoryService()\n {\n if (this.urlFactoryService == null) {\n synchronized (this.URLFACTORY_SERVICE_LOCK) {\n if (this.urlFactoryService == null) {\n LOGGER.info(\"Initializing URLFactory Service...\");\n\n XWikiURLFactoryService factoryService = null;\n\n String urlFactoryServiceClass = Param(\"xwiki.urlfactory.serviceclass\");\n if (urlFactoryServiceClass != null) {\n try {\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Using custom URLFactory Service Class [\" + urlFactoryServiceClass + \"]\");\n }\n factoryService =\n (XWikiURLFactoryService) Class.forName(urlFactoryServiceClass)\n .getConstructor(new Class< ? >[] {XWiki.class}).newInstance(new Object[] {this});\n } catch (Exception e) {\n factoryService = null;\n LOGGER.warn(\"Failed to initialize URLFactory Service [\" + urlFactoryServiceClass + \"]\", e);\n }\n }\n if (factoryService == null) {\n if (LOGGER.isDebugEnabled()) {\n LOGGER.debug(\"Using default URLFactory Service Class [\" + urlFactoryServiceClass + \"]\");\n }\n factoryService = new XWikiURLFactoryServiceImpl(this);\n }\n\n // Set the urlFactoryService object in one assignment to prevent threading\n // issues when checking for\n // null above.\n this.urlFactoryService = factoryService;\n }\n }\n }\n\n return this.urlFactoryService;\n }\n\n public XWikiCriteriaService getCriteriaService(XWikiContext context)\n {\n return this.criteriaService;\n }\n\n public ZipOutputStream getZipOutputStream(XWikiContext context) throws IOException\n {\n return new ZipOutputStream(context.getResponse().getOutputStream());\n }\n\n private Map getSearchEngineRules(XWikiContext context)\n {\n // We currently hardcode the rules\n // We will put them in the preferences soon\n Map map = new HashMap();\n map.put(\"Google\", new SearchEngineRule(\"google.\", \"s/(^|.*&)q=(.*?)(&.*|$)/$2/\"));\n map.put(\"MSN\", new SearchEngineRule(\"search.msn.\", \"s/(^|.*&)q=(.*?)(&.*|$)/$2/\"));\n map.put(\"Yahoo\", new SearchEngineRule(\"search.yahoo.\", \"s/(^|.*&)p=(.*?)(&.*|$)/$2/\"));\n map.put(\"Voila\", new SearchEngineRule(\"voila.fr\", \"s/(^|.*&)kw=(.*?)(&.*|$)/$2/\"));\n\n return map;\n }\n\n public String getRefererText(String referer, XWikiContext context)\n {\n try {\n URL url = new URL(referer);\n Map searchengines = getSearchEngineRules(context);\n if (searchengines != null) {\n for (SearchEngineRule senginerule : searchengines.values()) {\n String host = url.getHost();\n int i1 = host.indexOf(senginerule.getHost());\n if (i1 != -1) {\n String query = context.getUtil().substitute(senginerule.getRegEx(), url.getQuery());\n if ((query != null) && (!query.equals(\"\"))) {\n // We return the query text instead of the full referer\n return host.substring(i1) + \":\" + query;\n }\n }\n }\n }\n } catch (Exception e) {\n }\n\n String result = referer.substring(referer.indexOf(\"://\") + 3);\n if (result.endsWith(\"/\")) {\n return result.substring(0, result.length() - 1);\n } else {\n return result;\n }\n }\n\n public boolean isMySQL()\n {\n if (getHibernateStore() == null) {\n return false;\n }\n\n Object dialect = getHibernateStore().getConfiguration().getProperties().get(\"dialect\");\n return \"org.hibernate.dialect.MySQLDialect\".equals(dialect)\n || \"net.sf.hibernate.dialect.MySQLDialect\".equals(dialect);\n }\n\n public String getFullNameSQL()\n {\n return getFullNameSQL(true);\n }\n\n public String getFullNameSQL(boolean newFullName)\n {\n if (newFullName) {\n return \"doc.fullName\";\n }\n\n if (this.fullNameSQL == null) {\n if (isMySQL()) {\n this.fullNameSQL = \"CONCAT(doc.space,'.',doc.name)\";\n } else {\n this.fullNameSQL = \"doc.space||'.'||doc.name\";\n }\n }\n\n return this.fullNameSQL;\n }\n\n public String getDocName(String docname)\n {\n return docname.substring(docname.indexOf('.') + 1);\n }\n\n public String getUserName(String user, XWikiContext context)\n {\n return getUserName(user, null, true, context);\n }\n\n public String getUserName(String user, String format, XWikiContext context)\n {\n return getUserName(user, format, true, context);\n }\n\n public String getUserName(String user, String format, boolean link, XWikiContext context)\n {\n if (StringUtils.isBlank(user)) {\n return \"\";\n }\n XWikiDocument userdoc = null;\n try {\n userdoc = getDocument(user, context);\n if (userdoc == null) {\n return XMLUtils.escape(user);\n }\n\n BaseObject userobj = userdoc.getObject(\"XWiki.XWikiUsers\");\n if (userobj == null) {\n return XMLUtils.escape(userdoc.getDocumentReference().getName());\n }\n\n Set proplist = userobj.getPropertyList();\n String text;\n\n if (format == null) {\n text = userobj.getStringValue(\"first_name\") + \" \" + userobj.getStringValue(\"last_name\");\n if (StringUtils.isBlank(text)) {\n text = userdoc.getDocumentReference().getName();\n }\n } else {\n VelocityContext vcontext = new VelocityContext();\n for (String propname : proplist) {\n vcontext.put(propname, userobj.getStringValue(propname));\n }\n text =\n XWikiVelocityRenderer.evaluate(format, \"\", vcontext, context);\n }\n\n text = XMLUtils.escape(text.trim());\n\n if (link) {\n text =\n \"\" + text\n + \"\";\n }\n return text;\n } catch (Exception e) {\n LOGGER.error(\"Failed to get user profile page\", e);\n\n if (userdoc != null) {\n return userdoc.getDocumentReference().getName();\n }\n\n return user;\n }\n }\n\n public boolean hasCentralizedAuthentication(XWikiContext context)\n {\n String bl = getXWikiPreference(\"authentication_centralized\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n }\n\n if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.authentication.centralized\", \"0\"));\n }\n\n public String getLocalUserName(String user, XWikiContext context)\n {\n if (hasCentralizedAuthentication(context)) {\n return getUserName(user, null, true, context);\n } else {\n return getUserName(user.substring(user.indexOf(':') + 1), null, true, context);\n }\n }\n\n public String getLocalUserName(String user, String format, XWikiContext context)\n {\n if (hasCentralizedAuthentication(context)) {\n return getUserName(user, format, true, context);\n } else {\n return getUserName(user.substring(user.indexOf(':') + 1), format, true, context);\n }\n }\n\n public String getLocalUserName(String user, String format, boolean link, XWikiContext context)\n {\n if (hasCentralizedAuthentication(context)) {\n return getUserName(user, format, link, context);\n } else {\n return getUserName(user.substring(user.indexOf(':') + 1), format, link, context);\n }\n }\n\n public String formatDate(Date date, String format, XWikiContext context)\n {\n if (date == null) {\n return \"\";\n }\n String xformat = format;\n String defaultFormat = \"yyyy/MM/dd HH:mm\";\n\n if (format == null) {\n xformat = getXWikiPreference(\"dateformat\", defaultFormat, context);\n }\n\n try {\n DateFormatSymbols formatSymbols = null;\n try {\n String language = getLanguagePreference(context);\n formatSymbols = new DateFormatSymbols(new Locale(language));\n } catch (Exception e2) {\n String language = getXWikiPreference(\"default_language\", context);\n if ((language != null) && (!language.equals(\"\"))) {\n formatSymbols = new DateFormatSymbols(new Locale(language));\n }\n }\n\n SimpleDateFormat sdf;\n if (formatSymbols != null) {\n sdf = new SimpleDateFormat(xformat, formatSymbols);\n } else {\n sdf = new SimpleDateFormat(xformat);\n }\n\n try {\n sdf.setTimeZone(TimeZone.getTimeZone(getUserTimeZone(context)));\n } catch (Exception e) {\n }\n\n return sdf.format(date);\n } catch (Exception e) {\n LOGGER.info(\"Failed to format date [\" + date + \"] with pattern [\" + xformat + \"]: \" + e.getMessage());\n if (format == null) {\n if (xformat.equals(defaultFormat)) {\n return date.toString();\n } else {\n return formatDate(date, defaultFormat, context);\n }\n } else {\n return formatDate(date, null, context);\n }\n }\n }\n\n /*\n * Allow to read user setting providing the user timezone All dates will be expressed with this timezone\n */\n public String getUserTimeZone(XWikiContext context)\n {\n String tz = getUserPreference(\"timezone\", context);\n if ((tz == null) || (tz.equals(\"\"))) {\n String defaultTz = TimeZone.getDefault().getID();\n return Param(\"xwiki.timezone\", defaultTz);\n } else {\n return tz;\n }\n }\n\n /**\n * @deprecated since 2.2.1 use {@link #exists(DocumentReference, XWikiContext)}\n */\n @Deprecated\n public boolean exists(String fullname, XWikiContext context)\n {\n String server = null, database = null;\n try {\n XWikiDocument doc = new XWikiDocument();\n doc.setFullName(fullname, context);\n server = doc.getDatabase();\n\n if (server != null) {\n database = context.getDatabase();\n context.setDatabase(server);\n }\n\n return getStore().exists(doc, context);\n } catch (XWikiException e) {\n return false;\n } finally {\n if ((server != null) && (database != null)) {\n context.setDatabase(database);\n }\n }\n }\n\n public boolean exists(DocumentReference documentReference, XWikiContext context)\n {\n String server = null, database = null;\n try {\n XWikiDocument doc = new XWikiDocument(documentReference);\n server = doc.getDatabase();\n\n if (server != null) {\n database = context.getDatabase();\n context.setDatabase(server);\n }\n\n return getStore().exists(doc, context);\n } catch (XWikiException e) {\n return false;\n } finally {\n if ((server != null) && (database != null)) {\n context.setDatabase(database);\n }\n }\n }\n\n public String getAdType(XWikiContext context)\n {\n String adtype = \"\";\n if (isVirtualMode()) {\n XWikiDocument wikiServer = context.getWikiServer();\n if (wikiServer != null) {\n adtype = wikiServer.getStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, \"adtype\");\n }\n } else {\n adtype = getXWikiPreference(\"adtype\", \"\", context);\n }\n\n if (adtype.equals(\"\")) {\n adtype = Param(\"xwiki.ad.type\", \"\");\n }\n\n return adtype;\n }\n\n public String getAdClientId(XWikiContext context)\n {\n final String defaultadclientid = \"pub-2778691407285481\";\n String adclientid = \"\";\n if (isVirtualMode()) {\n XWikiDocument wikiServer = context.getWikiServer();\n if (wikiServer != null) {\n adclientid = wikiServer.getStringValue(VIRTUAL_WIKI_DEFINITION_CLASS_REFERENCE, \"adclientid\");\n }\n } else {\n adclientid = getXWikiPreference(\"adclientid\", \"\", context);\n }\n\n if (adclientid.equals(\"\")) {\n adclientid = Param(\"xwiki.ad.clientid\", \"\");\n }\n\n if (adclientid.equals(\"\")) {\n adclientid = defaultadclientid;\n }\n\n return adclientid;\n }\n\n public XWikiPluginInterface getPlugin(String name, XWikiContext context)\n {\n XWikiPluginManager plugins = getPluginManager();\n Vector pluginlist = plugins.getPlugins();\n for (String pluginname : pluginlist) {\n if (pluginname.equals(name)) {\n return plugins.getPlugin(pluginname);\n }\n }\n\n return null;\n }\n\n public Api getPluginApi(String name, XWikiContext context)\n {\n XWikiPluginInterface plugin = getPlugin(name, context);\n if (plugin != null) {\n return plugin.getPluginApi(plugin, context);\n }\n\n return null;\n }\n\n /**\n * @return the cache factory.\n * @since 1.5M2.\n * @deprecated Since 1.7M1, use {@link CacheManager} component instead using {@link Utils#getComponent(Class)}\n */\n @Deprecated\n public CacheFactory getCacheFactory()\n {\n CacheFactory cacheFactory;\n\n String cacheHint = Param(\"xwiki.cache.cachefactory.hint\", null);\n\n if (StringUtils.isEmpty(cacheHint) || Utils.getComponent(CacheFactory.class, cacheHint) == null) {\n CacheManager cacheManager = Utils.getComponent(CacheManager.class);\n try {\n cacheFactory = cacheManager.getCacheFactory();\n } catch (ComponentLookupException e) {\n throw new RuntimeException(\"Failed to get cache factory component\", e);\n }\n } else {\n cacheFactory = Utils.getComponent(CacheFactory.class, cacheHint);\n }\n\n return cacheFactory;\n }\n\n /**\n * @return the cache factory creating local caches.\n * @since 1.5M2.\n * @deprecated Since 1.7M1, use {@link CacheManager} component instead using {@link Utils#getComponent(Class)}\n */\n @Deprecated\n public CacheFactory getLocalCacheFactory()\n {\n CacheFactory localCacheFactory;\n\n String localCacheHint = Param(\"xwiki.cache.cachefactory.local.hint\", null);\n\n if (StringUtils.isEmpty(localCacheHint) || Utils.getComponent(CacheFactory.class, localCacheHint) == null) {\n CacheManager cacheManager = Utils.getComponent(CacheManager.class);\n try {\n localCacheFactory = cacheManager.getLocalCacheFactory();\n } catch (ComponentLookupException e) {\n throw new RuntimeException(\"Failed to get local cache factory component\", e);\n }\n } else {\n localCacheFactory = Utils.getComponent(CacheFactory.class, localCacheHint);\n }\n\n return localCacheFactory;\n }\n\n public int getHttpTimeout(XWikiContext context)\n {\n int defaulttimeout = 60000;\n return (context == null) ? defaulttimeout : (int) context.getWiki().ParamAsLong(\"xwiki.http.timeout\",\n defaulttimeout);\n }\n\n public String getHttpUserAgent(XWikiContext context)\n {\n if (context != null) {\n return context.getWiki().Param(\"xwiki.http.useragent\", \"XWikiBot/1.0\");\n } else {\n return \"XWikiBot/1.0\";\n }\n }\n\n public String getURLContent(String surl, XWikiContext context) throws IOException\n {\n return getURLContent(surl, getHttpTimeout(context), getHttpUserAgent(context));\n }\n\n public String getURLContent(String surl, int timeout, String userAgent) throws IOException\n {\n String content;\n HttpClient client = getHttpClient(timeout, userAgent);\n GetMethod get = new GetMethod(surl);\n\n try {\n client.executeMethod(get);\n content = get.getResponseBodyAsString();\n } finally {\n // Release any connection resources used by the method\n get.releaseConnection();\n }\n\n return content;\n }\n\n public String getURLContent(String surl, String username, String password, XWikiContext context) throws IOException\n {\n return getURLContent(surl, username, password, getHttpTimeout(context), getHttpUserAgent(context));\n }\n\n public String getURLContent(String surl, String username, String password, int timeout, String userAgent)\n throws IOException\n {\n HttpClient client = getHttpClient(timeout, userAgent);\n\n // pass our credentials to HttpClient, they will only be used for\n // authenticating to servers with realm \"realm\", to authenticate agains\n // an arbitrary realm change this to null.\n client.getState().setCredentials(new AuthScope(null, -1, null),\n new UsernamePasswordCredentials(username, password));\n\n // create a GET method that reads a file over HTTPS, we're assuming\n // that this file requires basic authentication using the realm above.\n GetMethod get = new GetMethod(surl);\n\n try {\n // Tell the GET method to automatically handle authentication. The\n // method will use any appropriate credentials to handle basic\n // authentication requests. Setting this value to false will cause\n // any request for authentication to return with a status of 401.\n // It will then be up to the client to handle the authentication.\n get.setDoAuthentication(true);\n\n // execute the GET\n client.executeMethod(get);\n\n // print the status and response\n return get.getResponseBodyAsString();\n } finally {\n // release any connection resources used by the method\n get.releaseConnection();\n }\n }\n\n public byte[] getURLContentAsBytes(String surl, XWikiContext context) throws IOException\n {\n return getURLContentAsBytes(surl, getHttpTimeout(context), getHttpUserAgent(context));\n }\n\n public byte[] getURLContentAsBytes(String surl, int timeout, String userAgent) throws IOException\n {\n HttpClient client = getHttpClient(timeout, userAgent);\n\n // create a GET method that reads a file over HTTPS, we're assuming\n // that this file requires basic authentication using the realm above.\n GetMethod get = new GetMethod(surl);\n\n try {\n // execute the GET\n client.executeMethod(get);\n\n // print the status and response\n return get.getResponseBody();\n } finally {\n // release any connection resources used by the method\n get.releaseConnection();\n }\n }\n\n public byte[] getURLContentAsBytes(String surl, String username, String password, XWikiContext context)\n throws IOException\n {\n return getURLContentAsBytes(surl, username, password, getHttpTimeout(context), getHttpUserAgent(context));\n }\n\n public byte[] getURLContentAsBytes(String surl, String username, String password, int timeout, String userAgent)\n throws IOException\n {\n HttpClient client = getHttpClient(timeout, userAgent);\n\n // pass our credentials to HttpClient, they will only be used for\n // authenticating to servers with realm \"realm\", to authenticate agains\n // an arbitrary realm change this to null.\n client.getState().setCredentials(new AuthScope(null, -1, null),\n new UsernamePasswordCredentials(username, password));\n\n // create a GET method that reads a file over HTTPS, we're assuming\n // that this file requires basic authentication using the realm above.\n GetMethod get = new GetMethod(surl);\n\n try {\n // Tell the GET method to automatically handle authentication. The\n // method will use any appropriate credentials to handle basic\n // authentication requests. Setting this value to false will cause\n // any request for authentication to return with a status of 401.\n // It will then be up to the client to handle the authentication.\n get.setDoAuthentication(true);\n\n // execute the GET\n client.executeMethod(get);\n\n // print the status and response\n return get.getResponseBody();\n } finally {\n // release any connection resources used by the method\n get.releaseConnection();\n }\n }\n\n public List getSpaces(XWikiContext context) throws XWikiException\n {\n try {\n return getStore().getQueryManager().getNamedQuery(\"getSpaces\").execute();\n } catch (QueryException ex) {\n throw new XWikiException(0, 0, ex.getMessage(), ex);\n }\n }\n\n public List getSpaceDocsName(String spaceName, XWikiContext context) throws XWikiException\n {\n try {\n return getStore().getQueryManager().getNamedQuery(\"getSpaceDocsName\").bindValue(\"space\", spaceName)\n .execute();\n } catch (QueryException ex) {\n throw new XWikiException(0, 0, ex.getMessage(), ex);\n }\n }\n\n public List getIncludedMacros(String defaultSpace, String content, XWikiContext context)\n {\n List list;\n\n try {\n String pattern = \"#includeMacros[ ]*\\\\([ ]*([\\\"'])(.*?)\\\\1[ ]*\\\\)\";\n list = context.getUtil().getUniqueMatches(content, pattern, 2);\n for (int i = 0; i < list.size(); i++) {\n String name = list.get(i);\n if (name.indexOf('.') == -1) {\n list.set(i, defaultSpace + \".\" + name);\n }\n }\n } catch (Exception e) {\n // This should never happen\n LOGGER.error(\"Failed to extract #includeMacros targets from provided content [\" + content + \"]\", e);\n\n list = Collections.emptyList();\n }\n\n return list;\n }\n\n public String getFlash(String url, String width, String height, XWikiContext context)\n {\n VelocityContext vorigcontext = ((VelocityContext) context.get(\"vcontext\"));\n try {\n VelocityContext vcontext = (VelocityContext) vorigcontext.clone();\n vcontext.put(\"flashurl\", url);\n vcontext.put(\"width\", width);\n vcontext.put(\"height\", height);\n context.put(\"vcontext\", vcontext);\n\n return parseTemplate(\"flash.vm\", context);\n } finally {\n context.put(\"vcontext\", vorigcontext);\n }\n }\n\n /**\n * accessor for the isReadOnly instance var.\n * \n * @see #isReadOnly\n */\n public boolean isReadOnly()\n {\n return this.isReadOnly;\n }\n\n public void setReadOnly(boolean readOnly)\n {\n this.isReadOnly = readOnly;\n }\n\n public void deleteAllDocuments(XWikiDocument doc, XWikiContext context) throws XWikiException\n {\n deleteAllDocuments(doc, true, context);\n }\n\n public void deleteAllDocuments(XWikiDocument doc, boolean totrash, XWikiContext context) throws XWikiException\n {\n // Delete all documents\n for (String lang : doc.getTranslationList(context)) {\n XWikiDocument tdoc = doc.getTranslatedDocument(lang, context);\n deleteDocument(tdoc, totrash, context);\n }\n\n deleteDocument(doc, context);\n }\n\n public void refreshLinks(XWikiContext context) throws XWikiException\n {\n try {\n // refreshes all Links of each doc of the wiki\n List docs = getStore().getQueryManager().getNamedQuery(\"getAllDocuments\").execute();\n for (int i = 0; i < docs.size(); i++) {\n XWikiDocument myDoc = this.getDocument(docs.get(i), context);\n myDoc.getStore().saveLinks(myDoc, context, true);\n }\n } catch (QueryException ex) {\n throw new XWikiException(0, 0, ex.getMessage(), ex);\n }\n }\n\n public boolean hasBacklinks(XWikiContext context)\n {\n if (this.hasBacklinks == null) {\n this.hasBacklinks = \"1\".equals(getXWikiPreference(\"backlinks\", \"xwiki.backlinks\", \"0\", context));\n }\n return this.hasBacklinks;\n }\n\n public boolean hasTags(XWikiContext context)\n {\n return \"1\".equals(getXWikiPreference(\"tags\", \"xwiki.tags\", \"0\", context));\n }\n\n public boolean hasCustomMappings()\n {\n return \"1\".equals(Param(\"xwiki.store.hibernate.custommapping\", \"1\"));\n }\n\n public boolean hasDynamicCustomMappings()\n {\n return \"1\".equals(Param(\"xwiki.store.hibernate.custommapping.dynamic\", \"0\"));\n }\n\n public String getDefaultSpace(XWikiContext context)\n {\n String defaultSpace = getXWikiPreference(\"defaultweb\", \"\", context);\n if (StringUtils.isEmpty(defaultSpace)) {\n return Param(\"xwiki.defaultweb\", DEFAULT_HOME_SPACE);\n }\n return defaultSpace;\n }\n\n public boolean skipDefaultSpaceInURLs(XWikiContext context)\n {\n String bl = getXWikiPreference(\"usedefaultweb\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n }\n\n if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.usedefaultweb\", \"0\"));\n }\n\n public boolean showViewAction(XWikiContext context)\n {\n String bl = getXWikiPreference(\"showviewaction\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n } else if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.showviewaction\", \"1\"));\n }\n\n public boolean useDefaultAction(XWikiContext context)\n {\n String bl = getXWikiPreference(\"usedefaultaction\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n }\n\n if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.usedefaultaction\", \"0\"));\n }\n\n public String getDefaultPage(XWikiContext context)\n {\n String defaultPage = getXWikiPreference(\"defaultpage\", \"\", context);\n if (StringUtils.isEmpty(defaultPage)) {\n return Param(\"xwiki.defaultpage\", DEFAULT_HOME_SPACE);\n }\n return defaultPage;\n }\n\n public boolean hasEditComment(XWikiContext context)\n {\n String bl = getXWikiPreference(\"editcomment\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n }\n\n if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.editcomment\", \"0\"));\n }\n\n public boolean isEditCommentFieldHidden(XWikiContext context)\n {\n String bl = getXWikiPreference(\"editcomment_hidden\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n }\n\n if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.editcomment.hidden\", \"0\"));\n }\n\n public boolean isEditCommentSuggested(XWikiContext context)\n {\n String bl = getXWikiPreference(\"editcomment_suggested\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n }\n\n if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.editcomment.suggested\", \"0\"));\n }\n\n public boolean isEditCommentMandatory(XWikiContext context)\n {\n String bl = getXWikiPreference(\"editcomment_mandatory\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n }\n\n if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.editcomment.mandatory\", \"0\"));\n }\n\n /**\n * @see com.xpn.xwiki.api.XWiki#hasMinorEdit()\n */\n public boolean hasMinorEdit(XWikiContext context)\n {\n String bl = getXWikiPreference(\"minoredit\", \"\", context);\n if (\"1\".equals(bl)) {\n return true;\n }\n\n if (\"0\".equals(bl)) {\n return false;\n }\n\n return \"1\".equals(Param(\"xwiki.minoredit\", \"1\"));\n }\n\n /**\n * @see com.xpn.xwiki.api.XWiki#hasRecycleBin()\n * @param context maybe will be useful\n */\n public boolean hasRecycleBin(XWikiContext context)\n {\n return \"1\".equals(Param(\"xwiki.recyclebin\", \"1\"));\n }\n\n /**\n * Indicates whether deleted attachments are stored in a recycle bin or not. This can be configured using the key\n * storage.attachment.recyclebin.\n * \n * @param context The current {@link XWikiContext context}, maybe will be useful.\n */\n public boolean hasAttachmentRecycleBin(XWikiContext context)\n {\n return \"1\".equals(Param(\"storage.attachment.recyclebin\", \"1\"));\n }\n\n /**\n * @deprecated use {@link XWikiDocument#rename(String, XWikiContext)} instead\n */\n @Deprecated\n public XWikiDocument renamePage(XWikiDocument doc, String newFullName, XWikiContext context) throws XWikiException\n {\n if (context.getWiki().exists(newFullName, context)) {\n XWikiDocument delDoc = context.getWiki().getDocument(newFullName, context);\n context.getWiki().deleteDocument(delDoc, context);\n }\n\n XWikiDocument renamedDoc = doc.copyDocument(newFullName, context);\n saveDocument(renamedDoc, context);\n renamedDoc.saveAllAttachments(context);\n deleteDocument(doc, context);\n\n return renamedDoc;\n }\n\n /**\n * @deprecated use {@link XWikiDocument#rename(String, XWikiContext)} instead\n */\n @Deprecated\n public XWikiDocument renamePage(XWikiDocument doc, XWikiContext context, String newFullName) throws XWikiException\n {\n return renamePage(doc, newFullName, context);\n }\n\n /**\n * @since 2.2M2\n */\n public BaseClass getXClass(DocumentReference documentReference, XWikiContext context) throws XWikiException\n {\n // Used to avoid recursive loading of documents if there are recursives usage of classes\n BaseClass bclass = context.getBaseClass(documentReference);\n if (bclass != null) {\n return bclass;\n }\n\n return getDocument(documentReference, context).getXClass();\n }\n\n /**\n * @deprecated since 2.2M2 use {@link #getXClass(DocumentReference, XWikiContext)}\n */\n @Deprecated\n public BaseClass getClass(String fullName, XWikiContext context) throws XWikiException\n {\n DocumentReference reference = null;\n if (StringUtils.isNotEmpty(fullName)) {\n reference = this.currentMixedDocumentReferenceResolver.resolve(fullName);\n }\n return getXClass(reference, context);\n }\n\n public String getEditorPreference(XWikiContext context)\n {\n String pref = getUserPreference(\"editor\", context);\n if (pref.equals(\"---\")) {\n pref = getSpacePreference(\"editor\", context);\n }\n\n if (pref.equals(\"\")) {\n pref = Param(\"xwiki.editor\", \"\");\n }\n\n return pref.toLowerCase();\n }\n\n /**\n * Privileged API to retrieve an object instantiated from groovy code in a String. Note that Groovy scripts\n * compilation is cached.\n * \n * @param script the Groovy class definition string (public class MyClass { ... })\n * @return An object instantiating this class\n * @throws XWikiException\n */\n public Object parseGroovyFromString(String script, XWikiContext context) throws XWikiException\n {\n if (getRenderingEngine().getRenderer(\"groovy\") == null) {\n return null;\n } else {\n return ((XWikiGroovyRenderer) getRenderingEngine().getRenderer(\"groovy\")).parseGroovyFromString(script,\n context);\n }\n }\n\n /**\n * Privileged API to retrieve an object instantiated from groovy code in a String, using a classloader including all\n * JAR files located in the passed page as attachments. Note that Groovy scripts compilation is cached\n * \n * @param script the Groovy class definition string (public class MyClass { ... })\n * @return An object instantiating this class\n * @throws XWikiException\n */\n public Object parseGroovyFromString(String script, String jarWikiPage, XWikiContext context) throws XWikiException\n {\n if (getRenderingEngine().getRenderer(\"groovy\") == null) {\n return null;\n }\n\n XWikiPageClassLoader pcl = new XWikiPageClassLoader(jarWikiPage, context);\n Object prevParentClassLoader = context.get(\"parentclassloader\");\n try {\n context.put(\"parentclassloader\", pcl);\n\n return parseGroovyFromString(script, context);\n } finally {\n if (prevParentClassLoader == null) {\n context.remove(\"parentclassloader\");\n } else {\n context.put(\"parentclassloader\", prevParentClassLoader);\n }\n }\n }\n\n public Object parseGroovyFromPage(String fullname, XWikiContext context) throws XWikiException\n {\n return parseGroovyFromString(context.getWiki().getDocument(fullname, context).getContent(), context);\n }\n\n public Object parseGroovyFromPage(String fullName, String jarWikiPage, XWikiContext context) throws XWikiException\n {\n return parseGroovyFromString(context.getWiki().getDocument(fullName, context).getContent(), jarWikiPage,\n context);\n }\n\n public String getMacroList(XWikiContext context)\n {\n String macrosmapping = \"\";\n XWiki xwiki = context.getWiki();\n\n try {\n macrosmapping = getResourceContent(MACROS_FILE);\n } catch (IOException e) {\n }\n\n macrosmapping += \"\\r\\n\" + xwiki.getXWikiPreference(\"macros_mapping\", \"\", context);\n\n return macrosmapping;\n }\n\n // This functions adds an object from an new object creation form\n public BaseObject getObjectFromRequest(String className, XWikiContext context) throws XWikiException\n {\n Map map = Util.getObject(context.getRequest(), className);\n BaseClass bclass = context.getWiki().getClass(className, context);\n BaseObject newobject = (BaseObject) bclass.fromMap(map, context);\n\n return newobject;\n }\n\n public String getConvertingUserNameType(XWikiContext context)\n {\n if (StringUtils.isNotBlank(context.getWiki().getXWikiPreference(\"convertmail\", context))) {\n return context.getWiki().getXWikiPreference(\"convertmail\", \"0\", context);\n }\n\n return context.getWiki().Param(\"xwiki.authentication.convertemail\", \"0\");\n }\n\n public String convertUsername(String username, XWikiContext context)\n {\n if (username == null) {\n return null;\n }\n\n if (getConvertingUserNameType(context).equals(\"1\") && (username.indexOf('@') != -1)) {\n String id = \"\" + username.hashCode();\n id = id.replace(\"-\", \"\");\n if (username.length() > 1) {\n int i1 = username.indexOf('@');\n id =\n \"\" + username.charAt(0) + username.substring(i1 + 1, i1 + 2)\n + username.charAt(username.length() - 1) + id;\n }\n\n return id;\n } else if (getConvertingUserNameType(context).equals(\"2\")) {\n return username.replaceAll(\"[\\\\.\\\\@]\", \"_\");\n } else {\n return username;\n }\n }\n\n public boolean hasSectionEdit(XWikiContext context)\n {\n return (context.getWiki().ParamAsLong(\"xwiki.section.edit\", 0) == 1);\n }\n\n /**\n * @return The maximum section depth for which section editing is available. This can be customized through the\n * {@code xwiki.section.depth} configuration property. Defaults to 2 when not defined.\n */\n public long getSectionEditingDepth()\n {\n return ParamAsLong(\"xwiki.section.depth\", 2);\n }\n\n public boolean hasCaptcha(XWikiContext context)\n {\n return (getXWikiPreferenceAsInt(\"captcha_enabled\", \"xwiki.plugin.captcha\", 0, context) == 1);\n }\n\n public String getWysiwygToolbars(XWikiContext context)\n {\n return context.getWiki().Param(\"xwiki.wysiwyg.toolbars\", \"\");\n }\n\n public String clearName(String name, XWikiContext context)\n {\n return clearName(name, true, true, context);\n }\n\n public String clearName(String name, boolean stripDots, boolean ascii, XWikiContext context)\n {\n String temp = name;\n temp =\n temp.replaceAll(\n \"[\\u00c0\\u00c1\\u00c2\\u00c3\\u00c4\\u00c5\\u0100\\u0102\\u0104\\u01cd\\u01de\\u01e0\\u01fa\\u0200\\u0202\\u0226]\",\n \"A\");\n temp =\n temp.replaceAll(\n \"[\\u00e0\\u00e1\\u00e2\\u00e3\\u00e4\\u00e5\\u0101\\u0103\\u0105\\u01ce\\u01df\\u01e1\\u01fb\\u0201\\u0203\\u0227]\",\n \"a\");\n temp = temp.replaceAll(\"[\\u00c6\\u01e2\\u01fc]\", \"AE\");\n temp = temp.replaceAll(\"[\\u00e6\\u01e3\\u01fd]\", \"ae\");\n temp = temp.replaceAll(\"[\\u008c\\u0152]\", \"OE\");\n temp = temp.replaceAll(\"[\\u009c\\u0153]\", \"oe\");\n temp = temp.replaceAll(\"[\\u00c7\\u0106\\u0108\\u010a\\u010c]\", \"C\");\n temp = temp.replaceAll(\"[\\u00e7\\u0107\\u0109\\u010b\\u010d]\", \"c\");\n temp = temp.replaceAll(\"[\\u00d0\\u010e\\u0110]\", \"D\");\n temp = temp.replaceAll(\"[\\u00f0\\u010f\\u0111]\", \"d\");\n temp = temp.replaceAll(\"[\\u00c8\\u00c9\\u00ca\\u00cb\\u0112\\u0114\\u0116\\u0118\\u011a\\u0204\\u0206\\u0228]\", \"E\");\n temp = temp.replaceAll(\"[\\u00e8\\u00e9\\u00ea\\u00eb\\u0113\\u0115\\u0117\\u0119\\u011b\\u01dd\\u0205\\u0207\\u0229]\", \"e\");\n temp = temp.replaceAll(\"[\\u011c\\u011e\\u0120\\u0122\\u01e4\\u01e6\\u01f4]\", \"G\");\n temp = temp.replaceAll(\"[\\u011d\\u011f\\u0121\\u0123\\u01e5\\u01e7\\u01f5]\", \"g\");\n temp = temp.replaceAll(\"[\\u0124\\u0126\\u021e]\", \"H\");\n temp = temp.replaceAll(\"[\\u0125\\u0127\\u021f]\", \"h\");\n temp = temp.replaceAll(\"[\\u00cc\\u00cd\\u00ce\\u00cf\\u0128\\u012a\\u012c\\u012e\\u0130\\u01cf\\u0208\\u020a]\", \"I\");\n temp = temp.replaceAll(\"[\\u00ec\\u00ed\\u00ee\\u00ef\\u0129\\u012b\\u012d\\u012f\\u0131\\u01d0\\u0209\\u020b]\", \"i\");\n temp = temp.replaceAll(\"[\\u0132]\", \"IJ\");\n temp = temp.replaceAll(\"[\\u0133]\", \"ij\");\n temp = temp.replaceAll(\"[\\u0134]\", \"J\");\n temp = temp.replaceAll(\"[\\u0135]\", \"j\");\n temp = temp.replaceAll(\"[\\u0136\\u01e8]\", \"K\");\n temp = temp.replaceAll(\"[\\u0137\\u0138\\u01e9]\", \"k\");\n temp = temp.replaceAll(\"[\\u0139\\u013b\\u013d\\u013f\\u0141]\", \"L\");\n temp = temp.replaceAll(\"[\\u013a\\u013c\\u013e\\u0140\\u0142\\u0234]\", \"l\");\n temp = temp.replaceAll(\"[\\u00d1\\u0143\\u0145\\u0147\\u014a\\u01f8]\", \"N\");\n temp = temp.replaceAll(\"[\\u00f1\\u0144\\u0146\\u0148\\u0149\\u014b\\u01f9\\u0235]\", \"n\");\n temp =\n temp.replaceAll(\n \"[\\u00d2\\u00d3\\u00d4\\u00d5\\u00d6\\u00d8\\u014c\\u014e\\u0150\\u01d1\\u01ea\\u01ec\\u01fe\\u020c\\u020e\\u022a\\u022c\"\n + \"\\u022e\\u0230]\", \"O\");\n temp =\n temp.replaceAll(\n \"[\\u00f2\\u00f3\\u00f4\\u00f5\\u00f6\\u00f8\\u014d\\u014f\\u0151\\u01d2\\u01eb\\u01ed\\u01ff\\u020d\\u020f\\u022b\\u022d\"\n + \"\\u022f\\u0231]\", \"o\");\n temp = temp.replaceAll(\"[\\u0156\\u0158\\u0210\\u0212]\", \"R\");\n temp = temp.replaceAll(\"[\\u0157\\u0159\\u0211\\u0213]\", \"r\");\n temp = temp.replaceAll(\"[\\u015a\\u015c\\u015e\\u0160\\u0218]\", \"S\");\n temp = temp.replaceAll(\"[\\u015b\\u015d\\u015f\\u0161\\u0219]\", \"s\");\n temp = temp.replaceAll(\"[\\u00de\\u0162\\u0164\\u0166\\u021a]\", \"T\");\n temp = temp.replaceAll(\"[\\u00fe\\u0163\\u0165\\u0167\\u021b\\u0236]\", \"t\");\n temp =\n temp.replaceAll(\n \"[\\u00d9\\u00da\\u00db\\u00dc\\u0168\\u016a\\u016c\\u016e\\u0170\\u0172\\u01d3\\u01d5\\u01d7\\u01d9\\u01db\\u0214\\u0216]\",\n \"U\");\n temp =\n temp.replaceAll(\n \"[\\u00f9\\u00fa\\u00fb\\u00fc\\u0169\\u016b\\u016d\\u016f\\u0171\\u0173\\u01d4\\u01d6\\u01d8\\u01da\\u01dc\\u0215\\u0217]\",\n \"u\");\n temp = temp.replaceAll(\"[\\u0174]\", \"W\");\n temp = temp.replaceAll(\"[\\u0175]\", \"w\");\n temp = temp.replaceAll(\"[\\u00dd\\u0176\\u0178\\u0232]\", \"Y\");\n temp = temp.replaceAll(\"[\\u00fd\\u00ff\\u0177\\u0233]\", \"y\");\n temp = temp.replaceAll(\"[\\u0179\\u017b\\u017d]\", \"Z\");\n temp = temp.replaceAll(\"[\\u017a\\u017c\\u017e]\", \"z\");\n temp = temp.replaceAll(\"[\\u00df]\", \"SS\");\n temp = temp.replaceAll(\"[_':,;\\\\\\\\/]\", \" \");\n name = temp;\n name = name.replaceAll(\"\\\\s+\", \"\");\n name = name.replaceAll(\"[\\\\(\\\\)]\", \" \");\n\n if (stripDots) {\n name = name.replaceAll(\"[\\\\.]\", \"\");\n }\n\n if (ascii) {\n name = name.replaceAll(\"[^a-zA-Z0-9\\\\-_\\\\.]\", \"\");\n }\n\n if (name.length() > 250) {\n name = name.substring(0, 250);\n }\n\n return name;\n\n }\n\n public String getUniquePageName(String space, XWikiContext context)\n {\n String pageName = generateRandomString(16);\n\n return getUniquePageName(space, pageName, context);\n }\n\n public String getUniquePageName(String space, String name, XWikiContext context)\n {\n String pageName = clearName(name, context);\n if (exists(space + \".\" + pageName, context)) {\n int i = 0;\n while (exists(space + \".\" + pageName + \"_\" + i, context)) {\n i++;\n }\n\n return pageName + \"_\" + i;\n }\n\n return pageName;\n }\n\n public PropertyClass getPropertyClassFromName(String propPath, XWikiContext context)\n {\n int i1 = propPath.indexOf('_');\n if (i1 == -1) {\n return null;\n } else {\n String className = propPath.substring(0, i1);\n String propName = propPath.substring(i1 + 1);\n try {\n return (PropertyClass) getDocument(className, context).getXClass().get(propName);\n } catch (XWikiException e) {\n return null;\n }\n }\n }\n\n public boolean validateDocument(XWikiDocument doc, XWikiContext context) throws XWikiException\n {\n return doc.validate(context);\n }\n\n public String addTooltip(String html, String message, String params, XWikiContext context)\n {\n StringBuffer buffer = new StringBuffer();\n buffer.append(\"\");\n buffer.append(html);\n buffer.append(\"\");\n\n return buffer.toString();\n }\n\n public String addTooltipJS(XWikiContext context)\n {\n StringBuffer buffer = new StringBuffer();\n buffer.append(\"\");\n // buffer.append(\"

\");\n\n return buffer.toString();\n }\n\n public String addTooltip(String html, String message, XWikiContext context)\n {\n return addTooltip(html, message, \"this.WIDTH='300'\", context);\n }\n\n public void renamePage(String fullName, String newFullName, XWikiContext context) throws XWikiException\n {\n renamePage(context.getWiki().getDocument(fullName, context), newFullName, context);\n }\n\n public String addMandatory(XWikiContext context)\n {\n String star =\n \" (\";\n return context.getWiki().getXWikiPreference(\"mandatory_display\", star, context);\n }\n\n /**\n * @since 2.3M1\n */\n public boolean hasVersioning(XWikiContext context)\n {\n return (\"1\".equals(context.getWiki().Param(\"xwiki.store.versioning\", \"1\")));\n }\n\n /**\n * @deprecated since 2.3M1 use {@link #hasVersioning(XWikiContext)} instead\n */\n @Deprecated\n public boolean hasVersioning(String fullName, XWikiContext context)\n {\n return hasVersioning(context);\n }\n\n public boolean hasAttachmentVersioning(XWikiContext context)\n {\n return (\"1\".equals(context.getWiki().Param(\"xwiki.store.attachment.versioning\", \"1\")));\n }\n\n public String getExternalAttachmentURL(String fullName, String filename, XWikiContext context)\n {\n XWikiDocument doc = new XWikiDocument();\n doc.setFullName(fullName, context);\n\n return doc.getExternalAttachmentURL(filename, \"download\", context);\n }\n\n public int getMaxRecursiveSpaceChecks(XWikiContext context)\n {\n int max = getXWikiPreferenceAsInt(\"rights_maxrecursivespacechecks\", -1, context);\n if (max == -1) {\n return (int) ParamAsLong(\"xwiki.rights.maxrecursivespacechecks\", 0);\n } else {\n return max;\n }\n }\n\n /**\n * Get the XWiki temporary filesystem directory (deleted on exit)\n * \n * @param context\n * @return temporary directory\n * @since 1.1 Milestone 4\n */\n public File getTempDirectory(XWikiContext context)\n {\n // if tempDir has already been set, return it\n if (tempDir != null) {\n return tempDir;\n }\n\n // xwiki.cfg\n String dirPath = context.getWiki().Param(\"xwiki.temp.dir\");\n if (dirPath != null) {\n try {\n tempDir = new File(dirPath.replaceAll(\"\\\\s+$\", \"\"));\n if (tempDir.isDirectory() && tempDir.canWrite()) {\n tempDir.deleteOnExit();\n return tempDir;\n }\n } catch (Exception e) {\n tempDir = null;\n LOGGER.warn(\"xwiki.temp.dir set in xwiki.cfg : \" + dirPath + \" does not exist or is not writable\", e);\n }\n }\n\n Object jsct = context.getEngineContext().getAttribute(\"javax.servlet.context.tempdir\");\n\n // javax.servlet.context.tempdir (File)\n if (jsct != null && (jsct instanceof File)) {\n tempDir = (File) jsct;\n if (tempDir.isDirectory() && tempDir.canWrite()) {\n return tempDir;\n }\n }\n\n // javax.servlet.context.tempdir (String)\n if (jsct != null && (jsct instanceof String)) {\n tempDir = new File((String) jsct);\n\n if (tempDir.isDirectory() && tempDir.canWrite()) {\n return tempDir;\n }\n }\n\n // Let's make a tempdir in java.io.tmpdir\n tempDir = new File(System.getProperty(\"java.io.tmpdir\"), \"xwikiTemp\");\n\n if (tempDir.exists()) {\n tempDir.deleteOnExit();\n } else {\n tempDir.mkdir();\n tempDir.deleteOnExit();\n }\n\n return tempDir;\n }\n\n /**\n * Get a new directory in the xwiki work directory\n * \n * @param subdir desired directory name\n * @param context\n * @return work subdirectory\n * @since 1.1 Milestone 4\n */\n public File getWorkSubdirectory(String subdir, XWikiContext context)\n {\n File fdir = new File(this.getWorkDirectory(context).getAbsolutePath(), subdir);\n if (!fdir.exists()) {\n fdir.mkdir();\n }\n\n return fdir;\n }\n\n /**\n * Get the XWiki work directory\n * \n * @param context\n * @return work directory\n * @since 1.1 Milestone 4\n */\n public File getWorkDirectory(XWikiContext context)\n {\n String dirPath;\n\n // if workDir has already been set, return it\n if (workDir != null) {\n return workDir;\n }\n\n // xwiki.cfg\n dirPath = context.getWiki().Param(\"xwiki.work.dir\");\n if (dirPath != null) {\n try {\n workDir = new File(dirPath.replaceAll(\"\\\\s+$\", \"\"));\n if (workDir.exists()) {\n if (workDir.isDirectory() && workDir.canWrite()) {\n return workDir;\n }\n } else {\n workDir.mkdir();\n\n return workDir;\n }\n } catch (Exception e) {\n LOGGER.warn(\"xwiki.work.dir set in xwiki.cfg : \" + dirPath + \" does not exist or is not writable\", e);\n\n workDir = null;\n }\n }\n\n // No choices left, retreiving the temp directory\n this.workDir = this.getTempDirectory(context);\n\n return this.workDir;\n }\n\n public XWikiDocument rollback(final XWikiDocument tdoc, String rev, XWikiContext context) throws XWikiException\n {\n LOGGER.debug(\"Rolling back [\" + tdoc + \"] to version \" + rev);\n // Let's clone rolledbackDoc since we might modify it\n XWikiDocument rolledbackDoc = getDocument(tdoc, rev, context).clone();\n\n if (\"1\".equals(context.getWiki().Param(\"xwiki.store.rollbackattachmentwithdocuments\", \"1\"))) {\n // Attachment handling strategy:\n // - Two lists: Old Attachments, Current Attachments\n // Goals:\n // 1. Attachments that are only in OA must be restored from the trash\n // 2. Attachments that are only in CA must be sent to the trash\n // 3. Attachments that are in both lists should be reverted to the right version\n // 4. Gotcha: deleted and re-uploaded attachments should be both trashed and restored.\n // Plan:\n // - Construct three lists: to restore, to delete, to revert\n // - Iterate over OA.\n // -- If the attachment is not in CA, add it to the restore list\n // -- If it is in CA, but the date of the first version of the current attachment is after the date of the\n // restored document version, add it to both the restore & delete lists\n // -- Otherwise, add it to the revert list\n // - Iterate over CA\n // -- If the attachment is not in OA, add it to the delete list\n\n List oldAttachments = rolledbackDoc.getAttachmentList();\n List currentAttachments = tdoc.getAttachmentList();\n List toRestore = new ArrayList();\n List toTrash = new ArrayList();\n List toRevert = new ArrayList();\n\n // First step, determine what to do with each attachment\n LOGGER.debug(\"Checking attachments\");\n\n for (XWikiAttachment oldAttachment : oldAttachments) {\n String filename = oldAttachment.getFilename();\n XWikiAttachment equivalentAttachment = tdoc.getAttachment(filename);\n if (equivalentAttachment == null) {\n // Deleted attachment\n LOGGER.debug(\"Deleted attachment: \" + filename);\n toRestore.add(oldAttachment);\n continue;\n }\n XWikiAttachment equivalentAttachmentRevision =\n equivalentAttachment.getAttachmentRevision(oldAttachment.getVersion(), context);\n if (equivalentAttachmentRevision == null\n || !equivalentAttachmentRevision.getDate().equals(oldAttachment.getDate())) {\n // Recreated attachment\n LOGGER.debug(\"Recreated attachment: \" + filename);\n // If the attachment trash is not available, don't lose the existing attachment\n if (getAttachmentRecycleBinStore() != null) {\n toTrash.add(equivalentAttachment);\n toRestore.add(oldAttachment);\n }\n continue;\n }\n if (!StringUtils.equals(oldAttachment.getVersion(), equivalentAttachment.getVersion())) {\n // Updated attachment\n LOGGER.debug(\"Updated attachment: \" + filename);\n toRevert.add(equivalentAttachment);\n }\n }\n for (XWikiAttachment attachment : currentAttachments) {\n if (rolledbackDoc.getAttachment(attachment.getFilename()) == null) {\n LOGGER.debug(\"New attachment: \" + attachment.getFilename());\n toTrash.add(attachment);\n }\n }\n\n // Second step, treat each affected attachment\n\n // Delete new attachments\n if (context.getWiki().hasAttachmentRecycleBin(context)) {\n for (XWikiAttachment attachmentToDelete : toTrash) {\n // Nothing needed for the reverted document, but let's send the extra attachments to the trash\n context.getWiki().getAttachmentRecycleBinStore()\n .saveToRecycleBin(attachmentToDelete, context.getUser(), new Date(), context, true);\n }\n }\n\n // Revert updated attachments to the old version\n for (XWikiAttachment attachmentToRevert : toRevert) {\n String oldAttachmentVersion =\n rolledbackDoc.getAttachment(attachmentToRevert.getFilename()).getVersion();\n XWikiAttachment oldAttachmentRevision =\n attachmentToRevert.getAttachmentRevision(oldAttachmentVersion, context);\n if (oldAttachmentRevision == null) {\n // Previous version is lost, just leave the current version in place\n replaceAttachmentInPlace(rolledbackDoc, attachmentToRevert);\n continue;\n }\n // We can't just leave the old version in place, since it will break the revision history, given the\n // current implementation, so we set the attachment version to the most recent version, mark the content\n // as dirty, and the storage will automatically bump up the version number.\n // This is a hack, to be fixed once the storage doesn't take care of updating the history and version,\n // and once the current attachment version can point to an existing version from the history.\n oldAttachmentRevision.setVersion(attachmentToRevert.getVersion());\n oldAttachmentRevision.setMetaDataDirty(true);\n oldAttachmentRevision.getAttachment_content().setContentDirty(true);\n replaceAttachmentInPlace(rolledbackDoc, oldAttachmentRevision);\n }\n\n // Restore deleted attachments from the trash\n if (getAttachmentRecycleBinStore() != null) {\n for (XWikiAttachment attachmentToRestore : toRestore) {\n // There might be multiple versions of the attachment in the trash, search for the right one\n List deletedVariants =\n getAttachmentRecycleBinStore().getAllDeletedAttachments(attachmentToRestore, context, true);\n DeletedAttachment correctVariant = null;\n for (DeletedAttachment variant : deletedVariants) { // Reverse chronological order\n if (variant.getDate().before(rolledbackDoc.getDate())) {\n break;\n }\n correctVariant = variant;\n }\n if (correctVariant == null) {\n // Not found in the trash, nothing left to do\n continue;\n }\n XWikiAttachment restoredAttachment = correctVariant.restoreAttachment(null, context);\n XWikiAttachment restoredAttachmentRevision =\n restoredAttachment.getAttachmentRevision(attachmentToRestore.getVersion(), context);\n\n if (restoredAttachmentRevision != null) {\n restoredAttachmentRevision.setAttachment_archive(restoredAttachment.getAttachment_archive());\n restoredAttachmentRevision.getAttachment_archive().setAttachment(restoredAttachmentRevision);\n restoredAttachmentRevision.setVersion(restoredAttachment.getVersion());\n restoredAttachmentRevision.setMetaDataDirty(true);\n restoredAttachmentRevision.getAttachment_content().setContentDirty(true);\n replaceAttachmentInPlace(rolledbackDoc, restoredAttachmentRevision);\n } else {\n // This particular version is lost, update to the one available\n replaceAttachmentInPlace(rolledbackDoc, restoredAttachment);\n }\n }\n } else {\n // No trash, can't restore. Remove the attachment references, so that the document is not broken\n for (XWikiAttachment attachmentToRestore : toRestore) {\n rolledbackDoc.getAttachmentList().remove(attachmentToRestore);\n }\n }\n }\n\n // Special treatment for deleted objects\n rolledbackDoc.addXObjectsToRemoveFromVersion(tdoc);\n\n // now we save the final document..\n rolledbackDoc.setAuthorReference(context.getUserReference());\n rolledbackDoc.setRCSVersion(tdoc.getRCSVersion());\n rolledbackDoc.setVersion(tdoc.getVersion());\n rolledbackDoc.setContentDirty(true);\n List params = new ArrayList();\n params.add(rev);\n\n saveDocument(rolledbackDoc, context.getMessageTool().get(\"core.comment.rollback\", params), context);\n\n return rolledbackDoc;\n }\n\n private void replaceAttachmentInPlace(XWikiDocument doc, XWikiAttachment attachment)\n {\n for (ListIterator it = doc.getAttachmentList().listIterator(); it.hasNext();) {\n if (StringUtils.equals(it.next().getFilename(), attachment.getFilename())) {\n it.remove();\n it.add(attachment);\n break;\n }\n }\n }\n\n /**\n * @return the ids of configured syntaxes for this wiki (eg \"xwiki/1.0\", \"xwiki/2.0\", \"mediawiki/1.0\", etc)\n */\n public List getConfiguredSyntaxes()\n {\n return this.configuredSyntaxes;\n }\n\n /**\n * @return the syntax id of the syntax to use when creating new documents.\n */\n public String getDefaultDocumentSyntax()\n {\n // TODO: Fix this method to return a Syntax object instead of a String\n return Utils.getComponent(CoreConfiguration.class).getDefaultDocumentSyntax().toIdString();\n }\n\n /**\n * Set the fields of the class document passed as parameter. Can generate content for both XWiki Syntax 1.0 and\n * XWiki Syntax 2.0. If new documents are set to be created in XWiki Syntax 1.0 then generate XWiki 1.0 Syntax\n * otherwise generate XWiki Syntax 2.0.\n * \n * @param title the page title to set\n * @return true if the document has been modified, false otherwise\n */\n private boolean setClassDocumentFields(XWikiDocument doc, String title)\n {\n boolean needsUpdate = false;\n\n if (StringUtils.isBlank(doc.getCreator())) {\n needsUpdate = true;\n doc.setCreator(XWikiRightService.SUPERADMIN_USER);\n }\n if (StringUtils.isBlank(doc.getAuthor())) {\n needsUpdate = true;\n doc.setAuthor(doc.getCreator());\n }\n if (StringUtils.isBlank(doc.getParent())) {\n needsUpdate = true;\n doc.setParent(\"XWiki.XWikiClasses\");\n }\n if (StringUtils.isBlank(doc.getTitle())) {\n needsUpdate = true;\n doc.setTitle(title);\n }\n\n // Use ClassSheet to display the class document if no other sheet is explicitly specified.\n SheetBinder documentSheetBinder = Utils.getComponent(SheetBinder.class, \"document\");\n if (documentSheetBinder.getSheets(doc).isEmpty()) {\n String wikiName = doc.getDocumentReference().getWikiReference().getName();\n DocumentReference sheet = new DocumentReference(wikiName, SYSTEM_SPACE, \"ClassSheet\");\n needsUpdate |= documentSheetBinder.bind(doc, sheet);\n }\n\n return needsUpdate;\n }\n\n /**\n * Get the syntax of the document currently being executed.\n *

\n * The document currently being executed is not the same than the context document since when including a page with\n * velocity #includeForm(), method for example the context doc is the includer document even if includeForm() fully\n * execute and render the included document before insert it in the includer document.\n *

\n * If the current document can't be found, the method assume that the executed document is the context document\n * (it's generally the case when a document is directly rendered with\n * {@link XWikiDocument#getRenderedContent(XWikiContext)} for example).\n * \n * @param defaultSyntaxId the default value to return if no document can be found\n * @return the syntax identifier\n */\n public String getCurrentContentSyntaxId(String defaultSyntaxId, XWikiContext context)\n {\n String syntaxId = getCurrentContentSyntaxIdInternal(context);\n\n if (syntaxId == null) {\n syntaxId = defaultSyntaxId;\n }\n\n return syntaxId;\n }\n\n /**\n * Get the syntax of the document currently being executed.\n *

\n * The document currently being executed is not the same than the context document since when including a page with\n * velocity #includeForm(), method for example the context doc is the includer document even if includeForm() fully\n * execute and render the included document before insert it in the includer document.\n *

\n * If the current document can't be found, the method assume that the executed document is the context document\n * (it's generally the case when a document is directly rendered with\n * {@link XWikiDocument#getRenderedContent(XWikiContext)} for example).\n * \n * @return the syntax identifier\n */\n public String getCurrentContentSyntaxId(XWikiContext context)\n {\n String syntaxId = getCurrentContentSyntaxIdInternal(context);\n\n if (syntaxId == null) {\n throw new RuntimeException(\"Cannot get the current syntax since there's no current document set\");\n }\n\n return syntaxId;\n }\n\n private String getCurrentContentSyntaxIdInternal(XWikiContext context)\n {\n String syntaxId = null;\n\n if (context.get(\"sdoc\") != null) {\n // The content document\n syntaxId = ((XWikiDocument) context.get(\"sdoc\")).getSyntax().toIdString();\n } else if (context.getDoc() != null) {\n // The context document\n syntaxId = context.getDoc().getSyntax().toIdString();\n }\n\n return syntaxId;\n }\n\n /**\n * @return true if title handling should be using the compatibility mode or not. When the compatibility mode is\n * active, if the document's content first header (level 1 or level 2) matches the document's title the\n * first header is stripped.\n */\n public boolean isTitleInCompatibilityMode()\n {\n return \"1\".equals(Param(\"xwiki.title.compatibility\", \"0\"));\n }\n\n @Override\n public void onEvent(Event event, Object source, Object data)\n {\n XWikiDocument doc = (XWikiDocument) source;\n XWikiContext context = (XWikiContext) data;\n\n if (event instanceof XObjectPropertyEvent) {\n EntityReference reference = ((XObjectPropertyEvent) event).getReference();\n String modifiedProperty = reference.getName();\n if (\"plugins\".equals(modifiedProperty)) {\n onPluginPreferenceEvent(event, doc, context);\n } else if (\"backlinks\".equals(modifiedProperty)) {\n this.hasBacklinks =\n doc.getXObject((ObjectReference) reference.getParent()).getIntValue(\"backlinks\",\n (int) ParamAsLong(\"xwiki.backlinks\", 0)) == 1;\n }\n } else if (event instanceof XObjectEvent) {\n onServerObjectEvent(event, doc, context);\n }\n }\n\n private void onServerObjectEvent(Event event, XWikiDocument doc, XWikiContext context)\n {\n flushVirtualWikis(doc.getOriginalDocument());\n flushVirtualWikis(doc);\n }\n\n private void onPluginPreferenceEvent(Event event, XWikiDocument doc, XWikiContext context)\n {\n if (!isVirtualMode()) {\n // If the XWikiPreferences plugin propery is modified, reload all plugins.\n preparePlugins(context);\n }\n }\n\n /**\n * The reference to match class XWiki.XWikiServerClass on whatever wiki.\n */\n private static final RegexEntityReference SERVERCLASS_REFERENCE = new RegexEntityReference(\n Pattern.compile(\".*:XWiki.XWikiServerClass\\\\[\\\\d*\\\\]\"), EntityType.OBJECT);\n\n /**\n * The reference to match properties \"plugins\" and \"backlinks\" of class XWiki.XWikiPreference on whatever wiki.\n */\n private static final RegexEntityReference XWIKIPREFERENCE_PROPERTY_REFERENCE = new RegexEntityReference(\n Pattern.compile(\"plugins|backlinks\"), EntityType.OBJECT_PROPERTY, new RegexEntityReference(\n Pattern.compile(\".*:XWiki.XWikiPreferences\\\\[\\\\d*\\\\]\"), EntityType.OBJECT));\n\n private static final List LISTENER_EVENTS = new ArrayList()\n {\n {\n add(new XObjectAddedEvent(SERVERCLASS_REFERENCE));\n add(new XObjectDeletedEvent(SERVERCLASS_REFERENCE));\n add(new XObjectUpdatedEvent(SERVERCLASS_REFERENCE));\n add(new XObjectPropertyAddedEvent(XWIKIPREFERENCE_PROPERTY_REFERENCE));\n add(new XObjectPropertyDeletedEvent(XWIKIPREFERENCE_PROPERTY_REFERENCE));\n add(new XObjectPropertyUpdatedEvent(XWIKIPREFERENCE_PROPERTY_REFERENCE));\n }\n };\n\n public List getEvents()\n {\n return LISTENER_EVENTS;\n }\n\n public String getName()\n {\n return \"xwiki-core\";\n }\n}\n =================================================================== --- xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java (revision 6ddfc45a6aa807ac4b6a9bc9e101c042d0f0dd3d) +++ xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java (revision ) @@ -109,6 +109,7 @@ import org.xwiki.model.reference.WikiReference; import org.xwiki.observation.EventListener; import org.xwiki.observation.ObservationManager; +import org.xwiki.observation.event.ApplicationReadyEvent; import org.xwiki.observation.event.Event; import org.xwiki.query.QueryException; import org.xwiki.rendering.macro.wikibridge.WikiMacroInitializer; @@ -808,7 +809,12 @@ // that we need DB access to be available (at component initialization) to make this possible. registerWikiMacros(); - Utils. getComponent((Type) ObservationManager.class).addListener(this); + ObservationManager observationManager = + Utils. getComponent((Type) ObservationManager.class); + observationManager.addListener(this); + + // Send Event to signal that the application is ready to service requests. + observationManager.notify(new ApplicationReadyEvent(), this); } /**