/* * Copyright (C) 2003-2010 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.wiki.service.wysiwyg; import org.exoplatform.container.PortalContainer; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.wiki.mow.core.api.wiki.AttachmentImpl; import org.exoplatform.wiki.mow.core.api.wiki.PageImpl; import org.exoplatform.wiki.resolver.TitleResolver; import org.exoplatform.wiki.service.WikiContext; import org.exoplatform.wiki.utils.Utils; import org.xwiki.component.annotation.Component; import org.xwiki.component.annotation.Requirement; import org.xwiki.context.Execution; import org.xwiki.gwt.wysiwyg.client.wiki.EntityConfig; import org.xwiki.gwt.wysiwyg.client.wiki.URIReference; import org.xwiki.model.EntityType; import org.xwiki.model.reference.EntityReference; import org.xwiki.model.reference.EntityReferenceResolver; import org.xwiki.model.reference.EntityReferenceSerializer; import org.xwiki.rendering.listener.reference.ResourceReference; import org.xwiki.rendering.listener.reference.ResourceType; import org.xwiki.rendering.parser.ResourceReferenceParser; import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer; /** * Created by The eXo Platform SAS * Author : viet nguyen * viet.nguyen@exoplatform.com * Aug 12, 2010 */ @Component public class DefaultLinkService implements LinkService { /** Execution context handler, needed for accessing the WikiContext. */ @Requirement private Execution execution; /** * The component used to serialize XWiki document references. */ @Requirement("compact") private EntityReferenceSerializer<String> entityReferenceSerializer; /** * The component used to resolve an entity reference relative to another * entity reference. */ @Requirement("explicit/reference") private EntityReferenceResolver<EntityReference> explicitReferenceEntityReferenceResolver; /** * The component used to resolve a string entity reference relative to another * entity reference. */ @Requirement("explicit") private EntityReferenceResolver<String> explicitStringEntityReferenceResolver; /** * The component used to serialize link references. * <p> * Note: The link reference syntax is independent of the syntax of the edited * document. The current hint should be replaced with a generic one to avoid * confusion. */ @Requirement("xhtmlmarker") private ResourceReferenceSerializer linkReferenceSerializer; /** * The component used to parser link references. * <p> * Note: The link reference syntax is independent of the syntax of the edited * document. The current hint should be replaced with a generic one to avoid * confusion. */ @Requirement("xhtmlmarker") private ResourceReferenceParser linkReferenceParser; /** * The object used to convert between client and server entity reference. */ private final EntityReferenceConverter entityReferenceConverter = new EntityReferenceConverter(); /** * Log exception. */ private static final Log log = ExoLogger.getLogger(EntityReferenceConverter.class); /** * {@inheritDoc} * * @see LinkService#getEntityConfig(org.xwiki.gwt.wysiwyg.client.wiki.EntityReference, * org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference) */ public EntityConfig getEntityConfig(org.xwiki.gwt.wysiwyg.client.wiki.EntityReference origin, org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference destination) { String url; String destRelativeStrRef; if (org.xwiki.gwt.wysiwyg.client.wiki.EntityReference.EntityType.EXTERNAL == destination.getEntityReference() .getType()) { url = new URIReference(destination.getEntityReference()).getURI(); destRelativeStrRef = url; } else { EntityReference originRef = entityReferenceConverter.convert(origin); EntityReference destRef = entityReferenceConverter.convert(destination.getEntityReference()); destRef = explicitReferenceEntityReferenceResolver.resolve(destRef, destRef.getType(), originRef); destRelativeStrRef = entityReferenceSerializer.serialize(destRef, originRef); url = getEntityURL(destRef); } EntityConfig entityConfig = new EntityConfig(); entityConfig.setUrl(url); entityConfig.setReference(getLinkReference(destination.getType(), destination.isTyped(), destRelativeStrRef)); return entityConfig; } /** * @param entityReference an entity reference * @return the URL to access the specified entity */ private String getEntityURL(EntityReference entityReference) { org.exoplatform.wiki.service.WikiService wservice = (org.exoplatform.wiki.service.WikiService) PortalContainer.getComponent(org.exoplatform.wiki.service.WikiService.class); WikiContext wikiContext = getWikiContext(); WikiContext context = new WikiContext(); context.setPortalURL(wikiContext.getPortalURL()); context.setPortletURI(wikiContext.getPortletURI()); PageImpl page; switch (entityReference.getType()) { case DOCUMENT: String pageId = TitleResolver.getId(entityReference.getName(), false); String wikiOwner = entityReference.getParent().getName(); String wikiType = entityReference.getParent().getParent().getName(); context.setType(wikiType); context.setOwner(wikiOwner); context.setPageId(pageId); try { boolean isPageExisted = wservice.isExisting(wikiType, wikiOwner, pageId); if (isPageExisted) { return Utils.getDocumentURL(context); } } catch (Exception e) { log.error("Exception happen when finding page " + pageId, e); } return null; case ATTACHMENT: String attachmentId = entityReference.getName(); pageId = TitleResolver.getId(entityReference.getParent().getName(), false); wikiOwner = entityReference.getParent().getParent().getName(); wikiType = entityReference.getParent().getParent().getParent().getName(); try { page = (PageImpl) wservice.getExsitedOrNewDraftPageById(wikiType, wikiOwner, pageId); AttachmentImpl att = page.getAttachment(attachmentId); if (att != null) { return att.getDownloadURL(); } } catch (Exception e) { log.error("Exception happen when finding attachment " + attachmentId, e); } return null; default: return null; } } /** * @param clientResourceType the type of linked resource * @param typed {@code true} to include the resource scheme in the link * reference serialization, {@code false} otherwise * @param relativeStringEntityReference a relative string entity reference * @return a link reference that can be used to insert a link to the specified * entity */ private String getLinkReference(org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference.ResourceType clientResourceType, boolean typed, String relativeStringEntityReference) { ResourceType resourceType = new ResourceType(clientResourceType.getScheme()); ResourceReference linkReference = new ResourceReference(relativeStringEntityReference, resourceType); linkReference.setTyped(typed); return linkReferenceSerializer.serialize(linkReference); } /** * {@inheritDoc} * * @see LinkService#parseLinkReference(String, * org.xwiki.gwt.wysiwyg.client.wiki.EntityReference) */ public org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference parseLinkReference(String linkReferenceAsString, org.xwiki.gwt.wysiwyg.client.wiki.EntityReference baseReference) { ResourceReference linkReference = linkReferenceParser.parse(linkReferenceAsString); org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference clientLinkReference = new org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference(); clientLinkReference.setType(org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference.ResourceType.forScheme(linkReference.getType() .getScheme())); clientLinkReference.setTyped(linkReference.isTyped()); clientLinkReference.getParameters().putAll(linkReference.getParameters()); clientLinkReference.setEntityReference(parseEntityReferenceFromResourceReference(linkReference.getReference(), clientLinkReference.getType(), baseReference)); return clientLinkReference; } /** * Parses a client entity reference from a link/resource reference. * * @param stringEntityReference a string entity reference extracted from a * link/resource reference * @param resourceType the type of resource the string entity reference was * extracted from * @param baseReference the client entity reference that is used to resolve * the parsed entity reference relative to * @return an untyped client entity reference */ private org.xwiki.gwt.wysiwyg.client.wiki.EntityReference parseEntityReferenceFromResourceReference(String stringEntityReference, org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference.ResourceType resourceType, org.xwiki.gwt.wysiwyg.client.wiki.EntityReference baseReference) { org.xwiki.gwt.wysiwyg.client.wiki.EntityReference.EntityType entityType; switch (resourceType) { case DOCUMENT: entityType = org.xwiki.gwt.wysiwyg.client.wiki.EntityReference.EntityType.DOCUMENT; break; case ATTACHMENT: entityType = org.xwiki.gwt.wysiwyg.client.wiki.EntityReference.EntityType.ATTACHMENT; break; default: entityType = org.xwiki.gwt.wysiwyg.client.wiki.EntityReference.EntityType.EXTERNAL; break; } if (entityType == org.xwiki.gwt.wysiwyg.client.wiki.EntityReference.EntityType.EXTERNAL) { return new URIReference(stringEntityReference).getEntityReference(); } else { return entityReferenceConverter.convert(explicitStringEntityReferenceResolver.resolve(stringEntityReference, EntityType.valueOf(entityType.toString()), entityReferenceConverter.convert(baseReference))); } } private WikiContext getWikiContext() { return (WikiContext) execution.getContext().getProperty(WikiContext.WIKICONTEXT); } }