Java tutorial
/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.xpn.xwiki.plugin.workspacesmanager.apps; import java.text.MessageFormat; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.api.Object; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.objects.BaseObject; import com.xpn.xwiki.plugin.applicationmanager.ApplicationManagerPlugin; import com.xpn.xwiki.plugin.applicationmanager.ApplicationManagerPluginApi; import com.xpn.xwiki.plugin.applicationmanager.doc.XWikiApplication; import com.xpn.xwiki.plugin.spacemanager.api.SpaceManagerException; import com.xpn.xwiki.plugin.workspacesmanager.WorkspacesManagerException; import com.xpn.xwiki.plugin.workspacesmanager.WorkspacesManagerExtension; /** * The default manager for Workspaces Applications. * * @version $Id$ */ public class DefaultWorkspaceApplicationManager implements WorkspaceApplicationManager { /** * The dot, used as separator between wiki space and page names, in a wiki document full name. */ public static final String XWIKI_SPACE_SEPARATOR = "."; /** * The separator used in a wiki space name to separate the name of the space from the name of the application. */ public static final String XWIKI_WORKSPACE_APPSEPARATOR = "_"; /** * A Single quote. */ private static final String SINGLE_QUOTE = "'"; /** * The wiki name of the document holding the XClass definition for XWiki Workspaces applications. */ private static final String WORKSPACE_APPLICATION_CLASS = "XWiki.XWSApplicationClass"; /** * Log object to log messages in this class. */ private static final Log LOG = LogFactory.getLog(DefaultWorkspaceApplicationManager.class); /** * Set of all existing XWiki Workspaces applications. */ private Set<String> allWorkspacesApps; /** * The API of the XWiki application manager plugin. */ private ApplicationManagerPluginApi xwikiApplicationManagerApi; /** * Lazily instanciate the application manager api. * * @return the {@link ApplicationManagerPluginApi} instance * @param context the {@link com.xpn.xwiki.XWikiContext} at the moment this method is called. */ private ApplicationManagerPluginApi getXWikiApplicationManagerApi(XWikiContext context) { if (xwikiApplicationManagerApi == null) { xwikiApplicationManagerApi = (ApplicationManagerPluginApi) context.getWiki() .getPluginApi(ApplicationManagerPlugin.PLUGIN_NAME, context); } return xwikiApplicationManagerApi; } /** * {@inheritDoc} */ public Map<String, String> getApplicationsForSpace(String spaceName, XWikiContext context) throws WorkspacesManagerException { String hql = "select distinct doc.space from XWikiDocument as doc, XWikiDocument as sp" + ", BaseObject as xws, BaseObject as prefs, StringProperty as parent" + " where sp.space='" + spaceName + "' and sp.name='WebPreferences' and xws.name=sp.fullName" + " and xws.className='" + WorkspacesManagerExtension.WORKSPACE_SPACE_CLASS_NAME + SINGLE_QUOTE + " and prefs.className='XWiki.XWikiPreferences' and prefs.name=doc.fullName" + " and parent.id.id=prefs.id and parent.id.name='parent'" + " and parent.value='" + spaceName + SINGLE_QUOTE; try { List<String> applicationWebs = context.getWiki().getStore().search(hql, 0, 0, context); Map<String, String> result = new HashMap<String, String>(); for (String appWeb : applicationWebs) { // Retrieve the application name based on it URL // Convention for an app web : Space_Spacename_Appname String appName = appWeb .substring(appWeb.lastIndexOf(WorkspacesManagerExtension.XWIKI_WORKSPACE_APPSEPARATOR) + 1); result.put(appName, appWeb); } return result; } catch (XWikiException e) { throw new WorkspacesManagerException(e); } } /** * {@inheritDoc} */ public String getApplicationURL(String spaceName, String appName, String docName, String queryString, XWikiContext context) throws WorkspacesManagerException { try { String appWeb = getApplicationsForSpace(spaceName, context).get(appName); if (appWeb == null || appWeb.equals("")) { throw new WorkspacesManagerException(WorkspacesManagerException.MODULE_PLUGIN_XWS, WorkspacesManagerException.ERROR_XWSMGR_APPNOTFOUNDFORSPACE, "Application could not be found for space"); } return context.getWiki().getURL(appWeb + WorkspacesManagerExtension.XWIKI_SPACE_SEPARATOR + docName, "view", queryString, context); } catch (SpaceManagerException e) { throw new WorkspacesManagerException(e); } catch (XWikiException e) { throw new WorkspacesManagerException(e); } } /** * {@inheritDoc} */ public Set<String> getAvailableApplicationsNames(String spaceName, XWikiContext context) throws WorkspacesManagerException { Set<String> availableApps = getAllWorkspacesApps(context); Set<String> installedApps = getApplicationsForSpace(spaceName, context).keySet(); availableApps.removeAll(installedApps); return availableApps; } /** * @param context the XWiki context at the moment this method is called. * @return a set of all available applications names that can be installed in a workspace. */ private Set<String> getAllWorkspacesApps(XWikiContext context) { if (allWorkspacesApps == null) { allWorkspacesApps = new HashSet<String>(); try { List<XWikiApplication> allApps = getXWikiApplicationManagerApi(context) .getApplicationDocumentList(); for (XWikiApplication app : allApps) { if (app.getObject(WORKSPACE_APPLICATION_CLASS) != null) { allWorkspacesApps.add(app.getAppName()); } } } catch (XWikiException e) { allWorkspacesApps = null; return Collections.emptySet(); } } return allWorkspacesApps; } /** * {@inheritDoc} */ public void removeApplicationFromSpace(String appName, String spaceName, boolean withData, XWikiContext context) throws WorkspacesManagerException { try { XWikiApplication app = getXWikiApplicationManagerApi(context).getApplicationDocument(appName); if (app == null) { throw new WorkspacesManagerException(WorkspacesManagerException.MODULE_PLUGIN_XWS, WorkspacesManagerException.ERROR_XWSMGR_APPNOTFOUND_ON_INSTALL, "Could not find application descriptor when trying to remove application [" + appName + "]" + "from space [" + spaceName + "]"); } String appSpace = spaceName + XWIKI_WORKSPACE_APPSEPARATOR + app.getAppName(); if (!withData) { // not implemented yet. throw new WorkspacesManagerException(); } else { ApplicationManagerExtension ext = getApplicationManagerExtension(app, context); // execute, if needed pre uninstall operations if (ext != null) { ext.preUninstall(appSpace, context); } // remove all documents that belong to the wiki space in which lives the application for (XWikiDocument doc : context.getWiki().getStore() .searchDocuments("where doc.space = '" + appSpace + SINGLE_QUOTE, context)) { context.getWiki().deleteAllDocuments(doc, false, context); } // execute, if needed post uninstall operations if (ext != null) { ext.postUninstall(appSpace, context); } } } catch (XWikiException e) { throw new WorkspacesManagerException(e); } } /** * @param app the application to retrieve the extension for * @param context the XWiki context at the moment this method is called. * @return the {@link ApplicationManagerExtension} corresponding to the passe application */ private ApplicationManagerExtension getApplicationManagerExtension(XWikiApplication app, XWikiContext context) { Object xwsApp = app.getObject(WORKSPACE_APPLICATION_CLASS); if (xwsApp != null) { String cName = (String) xwsApp.get("application_manager_extension"); if (cName != null && !cName.equals("")) { try { java.lang.Object c = Class.forName(cName).newInstance(); if (c instanceof ApplicationManagerExtension) { return (ApplicationManagerExtension) c; } else { String msg = "could not load application manager extension " + " for application [{0}], as provided class [{1}] does not" + " implements ApplicationManagerExtension interface."; msg = MessageFormat.format(msg, new java.lang.Object[] { app.getName(), c.getClass().getName() }); LOG.error(msg); } } catch (Exception e) { LOG.error(e); } } } return null; } /** * Install an application in the given space, by copying or linking documents. Read the list of documents to include * (link) and copy from the {@link ApplicationManagerPlugin} and save their content locally in a wiki space (web) * composed of the space wiki name and the application name. Also make the application web inherits its rights from * the space root space (web). * * @param appName the name of the application to install * @param spaceName the wiki name of the space to install the application in * @param context the XWiki context at the moment this method is called. * @throws WorkspacesManagerException a wrapped error that can occur while searching documents, or manipulating them * (copying, saving) ; or an exception raised by extension pre-install or post-install operations */ public void installApplicationInSpace(String appName, String spaceName, XWikiContext context) throws WorkspacesManagerException { // TODO Note that this method makes a deviant usage of the application // manager plugin and XWiki application objects. // It uses the application field docsToInclude and documents // to make a local installation (as opposed as cross-wiki global // installation, which the application manager is initially designed // for). // In the future, the application manager should be able to // handle local installation/local copy parameters, and the // SpaceManagerPlugin implements a method to install a space // from an application or application list. // get the application manager api try { // Retrieve the application descriptor XWikiApplication app = getXWikiApplicationManagerApi(context).getApplicationDocument(appName); if (app == null) { throw new WorkspacesManagerException(WorkspacesManagerException.MODULE_PLUGIN_XWS, WorkspacesManagerException.ERROR_XWSMGR_APPNOTFOUND_ON_INSTALL, "Could not find application descriptor when trying to install application [" + appName + "]" + "in space [" + spaceName + "]"); } ApplicationManagerExtension ext = getApplicationManagerExtension(app, context); String appSpace = spaceName + XWIKI_WORKSPACE_APPSEPARATOR + app.getAppName(); // execute, if needed pre install operations if (ext != null) { ext.preInstall(appSpace, context); } // Retrieve the application document list Set<String> appDocs = app.getDocumentsNames(false, false); // Retrieve the application documents to include Set<String> docsToInclude = app.getDocsNameToInclude(true); for (String docFullName : appDocs) { // If the doc is not in the include list, // We copy it to the target space if (!docsToInclude.contains(docFullName)) { String docName = docFullName.substring(docFullName.indexOf('.') + 1); String targetDocName = appSpace + XWIKI_SPACE_SEPARATOR + docName; // copy the document, with metadata (dates, author, etc.) reset context.getWiki().copyDocument(docFullName, targetDocName, null, null, null, false, false, true, context); } } for (String docFullName : docsToInclude) { String docName = docFullName.substring(docFullName.indexOf('.') + 1); // Compute the target doc name based on application name, space // name and document // name // EX: Space_Wiki.WebHome for "Space" space name, "Wiki" appname // and "WebHome" doc String targetDocName = appSpace + XWIKI_SPACE_SEPARATOR + docName; XWikiDocument targetDoc = context.getWiki().getDocument(targetDocName, context); // Link the content with the application code targetDoc.setContent( MessageFormat.format("#includeInContext(\"{0}\")", new java.lang.Object[] { docFullName })); // Save the document context.getWiki().saveDocument(targetDoc, context); } if (appDocs.size() > 0) { // if we've installed anything, // make the installed app inherit its right from the Workspace // root web XWikiDocument appPreferences = context.getWiki() .getDocument(appSpace + XWIKI_SPACE_SEPARATOR + "WebPreferences", context); BaseObject pObj = appPreferences.getObject("XWiki.XWikiPreferences", true, context); pObj.setStringValue("parent", spaceName); context.getWiki().saveDocument(appPreferences, context); } // execute, if needed post install operations if (ext != null) { ext.postInstall(appSpace, context); } } catch (XWikiException e) { throw new WorkspacesManagerException(e); } } }