/* * 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.component.wiki.internal.bridge; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Singleton; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; import org.xwiki.component.descriptor.ComponentDescriptor; import org.xwiki.component.descriptor.DefaultComponentDescriptor; import org.xwiki.component.util.ReflectionUtils; import org.xwiki.component.wiki.WikiComponentException; import org.xwiki.component.wiki.WikiComponentScope; import org.xwiki.component.wiki.internal.WikiComponentConstants; import org.xwiki.model.reference.DocumentReference; import org.xwiki.rendering.block.XDOM; import org.xwiki.rendering.syntax.Syntax; import org.xwiki.security.authorization.AuthorizationManager; import org.xwiki.security.authorization.Right; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.objects.BaseObject; /** * A bridge between Wiki Components and the old model. * * @version $Id: 4500597cbe28ca6eea524bcd276ff93c56d8ae9e $ * @since 4.3M2 */ @Component @Singleton public class DefaultWikiComponentBridge implements WikiComponentConstants, WikiComponentBridge { /** * The logger to log. */ @Inject protected Logger logger; @Inject private Provider<XWikiContext> xcontextProvider; /** * The rendering bridge. */ @Inject private ContentParser renderingBridge; @Inject private AuthorizationManager authorization; @Override public Syntax getSyntax(DocumentReference reference) throws WikiComponentException { XWikiDocument componentDocument = this.getDocument(reference); return componentDocument.getSyntax(); } @Override public Type getRoleType(DocumentReference reference) throws WikiComponentException { BaseObject componentObject = getComponentObject(reference); String role = componentObject.getStringValue(COMPONENT_ROLE_TYPE_FIELD); Type roleType; try { roleType = ReflectionUtils.unserializeType(role, Thread.currentThread().getContextClassLoader()); } catch (ClassNotFoundException e) { throw new WikiComponentException(String.format("The role type [%s] does not exist", role), e); } return roleType; } @Override public String getRoleHint(DocumentReference reference) throws WikiComponentException { BaseObject componentObject = getComponentObject(reference); return StringUtils.defaultIfEmpty(componentObject.getStringValue(COMPONENT_ROLE_HINT_FIELD), "default"); } @Override public DocumentReference getAuthorReference(DocumentReference reference) throws WikiComponentException { XWikiDocument componentDocument = this.getDocument(reference); return componentDocument.getAuthorReference(); } @Override public WikiComponentScope getScope(DocumentReference reference) throws WikiComponentException { BaseObject componentObject = getComponentObject(reference); return WikiComponentScope.fromString(componentObject.getStringValue(COMPONENT_SCOPE_FIELD)); } @Override public Map<String, XDOM> getHandledMethods(DocumentReference reference) throws WikiComponentException { Map<String, XDOM> handledMethods = new HashMap<String, XDOM>(); XWikiDocument componentDocument = this.getDocument(reference); if (componentDocument.getObjectNumbers(METHOD_CLASS) > 0) { for (BaseObject method : componentDocument.getObjects(METHOD_CLASS)) { if (!StringUtils.isBlank(method.getStringValue(METHOD_NAME_FIELD))) { handledMethods.put(method.getStringValue(METHOD_NAME_FIELD), renderingBridge.parse( method.getStringValue(METHOD_CODE_FIELD), this.getSyntax(reference), reference)); } } } return handledMethods; } @Override public List<Class< ? >> getDeclaredInterfaces(DocumentReference reference) throws WikiComponentException { List<Class< ? >> interfaces = new ArrayList<Class< ? >>(); XWikiDocument componentDocument = this.getDocument(reference); if (componentDocument.getObjectNumbers(INTERFACE_CLASS) > 0) { for (BaseObject iface : componentDocument.getObjects(INTERFACE_CLASS)) { if (!StringUtils.isBlank(iface.getStringValue(INTERFACE_NAME_FIELD))) { try { Class< ? > implemented = Class.forName(iface.getStringValue(INTERFACE_NAME_FIELD)); interfaces.add(implemented); } catch (Exception e) { this.logger.warn("Interface [{}] not found, declared for wiki component [{}]", iface.getStringValue(INTERFACE_NAME_FIELD), componentDocument.getDocumentReference()); } } } } return interfaces; } @Override public Map<String, ComponentDescriptor> getDependencies(DocumentReference reference) throws WikiComponentException { Map<String, ComponentDescriptor> dependencies = new HashMap<String, ComponentDescriptor>(); XWikiDocument componentDocument = this.getDocument(reference); if (componentDocument.getObjectNumbers(DEPENDENCY_CLASS) > 0) { for (BaseObject dependency : componentDocument.getObjects(DEPENDENCY_CLASS)) { try { DefaultComponentDescriptor cd = new DefaultComponentDescriptor(); cd.setRoleType(ReflectionUtils.unserializeType( dependency.getStringValue(COMPONENT_ROLE_TYPE_FIELD), Thread.currentThread() .getContextClassLoader())); cd.setRoleHint(dependency.getStringValue(COMPONENT_ROLE_HINT_FIELD)); dependencies.put(dependency.getStringValue(DEPENDENCY_BINDING_NAME_FIELD), cd); } catch (Exception e) { this.logger.warn("Interface [{}] not found, declared as dependency for wiki component [{}]", dependency.getStringValue(COMPONENT_ROLE_TYPE_FIELD), componentDocument.getDocumentReference()); } } } return dependencies; } @Override public boolean hasProgrammingRights(DocumentReference reference) throws WikiComponentException { XWikiDocument document = getDocument(reference); return this.authorization.hasAccess(Right.PROGRAM, document.getAuthorReference(), null); } /** * Get the main component object from a wiki component document. * * @param reference a reference to the document holding the component * @return the object defining the component * @throws WikiComponentException if the document can't be retrieved */ private BaseObject getComponentObject(DocumentReference reference) throws WikiComponentException { XWikiDocument componentDocument = this.getDocument(reference); BaseObject componentObject = componentDocument.getObject(COMPONENT_CLASS); if (componentObject == null) { throw new WikiComponentException(String.format("No component object could be found in document [%s]", reference)); } return componentObject; } /** * Get a XWikiDocument from a reference. * * @param reference a document reference * @return the corresponding XWikiDocument object * @throws WikiComponentException if the document can't be retrieved */ protected XWikiDocument getDocument(DocumentReference reference) throws WikiComponentException { try { XWikiContext xcontext = this.xcontextProvider.get(); return xcontext.getWiki().getDocument(reference, xcontext); } catch (XWikiException e) { throw new WikiComponentException(String.format("Failed to retrieve the document [%s]", reference), e); } } }