Package de.innovationgate.wgpublisher.url

Source Code of de.innovationgate.wgpublisher.url.DefaultURLBuilder

/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA 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 OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

package de.innovationgate.wgpublisher.url;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import de.innovationgate.utils.URLBuilder;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGContent;
import de.innovationgate.webgate.api.WGDatabase;
import de.innovationgate.webgate.api.WGException;
import de.innovationgate.webgate.api.WGFileContainer;
import de.innovationgate.webgate.api.WGLanguage;
import de.innovationgate.webgate.api.WGUnavailableException;
import de.innovationgate.wga.config.VirtualHost;
import de.innovationgate.wgpublisher.AccessException;
import de.innovationgate.wgpublisher.AuthenticationException;
import de.innovationgate.wgpublisher.WGACore;
import de.innovationgate.wgpublisher.WGAVirtualHostingFilter;
import de.innovationgate.wgpublisher.WGPDispatcher;
import de.innovationgate.wgpublisher.WGPRequestPath;
import de.innovationgate.wgpublisher.lang.LanguageBehaviour;
import de.innovationgate.wgpublisher.lang.LanguageBehaviourTools;
import de.innovationgate.wgpublisher.lang.WebTMLLanguageChooser;
import de.innovationgate.wgpublisher.webtml.Base;
import de.innovationgate.wgpublisher.webtml.BaseTagStatus;
import de.innovationgate.wgpublisher.webtml.utils.HttpErrorException;
import de.innovationgate.wgpublisher.webtml.utils.TMLAction;
import de.innovationgate.wgpublisher.webtml.utils.TMLActionLink;
import de.innovationgate.wgpublisher.webtml.utils.TMLContext;

public class DefaultURLBuilder implements WGAURLBuilder {
   
    private boolean _titlePathAllowed = true;
   
   
    public String buildContentURL(TMLContext context, String mediaKey, String layoutKey, boolean ignoreVirtualLink) throws UnsupportedEncodingException, WGAPIException {
        String url = innerBuildContentURL(context, mediaKey, layoutKey, ignoreVirtualLink);
        return rewriteURL(url, context.getrequest(), context.getwgacore(), context.content().isVirtual());
    }


    protected String innerBuildContentURL(TMLContext context, String mediaKey, String layoutKey, boolean ignoreVirtualLink) throws UnsupportedEncodingException, WGAPIException {

        BaseTagStatus tag = context.getDesignContext().getTag();
        if (tag == null) {
            return null;
        }

        String completeUrl = null;
       
        if (mediaKey == null) {
            mediaKey = tag.getMainMediaKey();
        }

        // If content is dummy, return a layout url instead. Use the design of the current request, if none specified.
        if (context.content().isDummy()) {
            if (layoutKey == null || layoutKey.equals("default")) {
                layoutKey = (String) context.getrequest().getAttribute(WGACore.ATTRIB_OUTER_DESIGN);
            }
            return buildLayoutURL(context, null, mediaKey, layoutKey);
        }

        // Virtual link
        if (context.content().isVirtual() && !ignoreVirtualLink) {
           
            // Virtual links adressing content are treated internally, so the resulting link will match the current content URL policy
            if (WGContent.VIRTUALLINKTYPE_CONTENT.equals(context.content().getVirtualLinkType()) ||
                    WGContent.VIRTUALLINKTYPE_UNIQUENAME.equals(context.content().getVirtualLinkType())) {
                List elements = WGUtils.deserializeCollection(context.content().getVirtualLink(), "/");
                String docID = (String) elements.get(elements.size() - 1);
                TMLContext targetContext = context.context("docid:" + docID, false);
                if (targetContext != null) {
                    completeUrl = targetContext.contenturl(mediaKey, layoutKey);
                }
                else {
                    completeUrl = WGPDispatcher.buildVirtualLink(context.content(), context.getrequest(), mediaKey, layoutKey);
                }
            }
           
            // All other virtual link types are coped with by WGPDispatcher
            else {
                completeUrl = WGPDispatcher.buildVirtualLink(context.content(), context.getrequest(), mediaKey, layoutKey);
            }
        }
       
        // Normal content URL
        else {

            // Default layoutkey or expand local references
            if (layoutKey == null) {
                layoutKey = "default";
            }
            else {
                layoutKey = context.resolveDesignReference(layoutKey);
            }
           
            // Title path URL if there is a title path manager, the document is released and default layout is used
            TitlePathManager tpm = (TitlePathManager) context.db().getAttribute(WGACore.DBATTRIB_TITLEPATHMANAGER);
            if (isTitlePathAllowed() && context.isbrowserinterface() == false && tpm != null && tpm.isGenerateTitlePathURLs() && layoutKey.equals("default") && context.content().getStatus().equals(WGContent.STATUS_RELEASE)) {
                completeUrl = buildTitlePathURL(context, mediaKey, tpm);
            }
           
            // Standard URL if there is no title path manager or the title path creation failed/is not allowed
            if (completeUrl == null) {
                completeUrl = buildStandardContentURL(context, mediaKey, layoutKey);
            }
        }

        // Test, if there is a link action defined, that redirects content links to the specified action
        String linkAction = (String) context.option(Base.OPTION_LINK_ACTION);
        if (linkAction != null && !ignoreVirtualLink) {
            List params = new ArrayList();
            params.add("content");
            params.add(mediaKey);
            params.add(layoutKey);
            params.add(completeUrl);
            TMLAction tmlAction = context.getActionByID(linkAction, context.getDesignDBKey());
            if (tmlAction != null) {
                return context.getURLBuilder().buildActionURL(context, tmlAction, params, null, context.getpath());
            }
            else {
                return "";
            }
        }
        else {
            return completeUrl;
        }
       
    }

    private String buildTitlePathURL(TMLContext context, String mediaKey, TitlePathManager tpm) throws WGAPIException, UnsupportedEncodingException {
       
        List path = tpm.buildTitlePath(context.content(), mediaKey, new WebTMLLanguageChooser(context.db(), context));
        if (path == null) {
            return null;
        }
       
        // Add base path
        path.add(0, buildBasePath(context));
        return WGUtils.serializeCollection(path, "/");
       
    }



    private String buildStandardContentURL(TMLContext context, String mediaKey, String layoutKey) throws WGAPIException {
        StringBuffer url = new StringBuffer();
       
        // Base path up to layout key
        url.append(buildBasePath(context)).append("/");
        url.append(mediaKey).append("/");
        url.append(layoutKey).append("/");
       
        String contentKey = WGPDispatcher.buildContentURLID(context.content(), mediaKey, context.isbrowserinterface());
        url.append(contentKey);
       
        return url.toString();
    }

    public String buildLayoutURL(TMLContext context, String dbKey, String mediaKey, String layoutKey) throws UnsupportedEncodingException, WGAPIException {
        String url = innerBuildLayoutURL(context, dbKey, mediaKey, layoutKey);
        return rewriteURL(url, context.getrequest(), context.getwgacore(), false);
    }

    protected String innerBuildLayoutURL(TMLContext context, String dbKey, String mediaKey, String layoutKey) throws UnsupportedEncodingException, WGAPIException {
       
        BaseTagStatus tag = context.getDesignContext().getTag();
        if (tag == null) {
            return null;
        }

        // Defaulting of media and layout key
        if (mediaKey == null) {
            mediaKey = tag.getMainMediaKey();
        }

        if (layoutKey == null) {
            layoutKey = "default";
        }
        else {
            layoutKey = context.resolveDesignReference(layoutKey);
        }

        // Base path
        StringBuffer url = new StringBuffer();
        url.append(context.getEnvironment().getPublisherURL());
        url.append("/");
       
        // DB determination
        String designdbKey = dbKey;
        if (designdbKey == null) {
            designdbKey = context.getDesignDBKey();
        }
        if (designdbKey == null) {
            designdbKey = context.db().getDbReference();
        }
        url.append(designdbKey).append("/");
       
        // Determining target language
       
        String targetLanguage = context.getpreferredlanguage(); // Fallback value
       
        try {
            WGDatabase targetDB = context.db(designdbKey);
            if (targetDB != null && targetDB.isSessionOpen()) {
                LanguageBehaviour langBehaviour = LanguageBehaviourTools.retrieve(targetDB);
                WGLanguage lang = langBehaviour.webtmlSelectDatabaseLanguage(targetDB, context);
                if (lang != null) {
                    targetLanguage = lang.getName();
                }
            }
        }
        catch (WGException e) {
            context.getlog().error("Exception determining target language for layout URL", e);
        }
       
        // Media and layout key
        url.append(mediaKey).append("/");
        url.append(WGPDispatcher.buildLayoutURLID(context.getwgacore().getContentdbs().get(designdbKey), layoutKey, targetLanguage, mediaKey));

        // Test, if there is a link action defined, that redirects content links to the specified action
        String linkAction = (String) context.option(Base.OPTION_LINK_ACTION);
        if (linkAction != null) {
            List params = new ArrayList();
            params.add("layout");
            params.add(mediaKey);
            params.add(layoutKey);
            params.add(url.toString());
            TMLAction tmlAction = context.getActionByID(linkAction, designdbKey);
            if (tmlAction != null) {
                return context.getURLBuilder().buildActionURL(context, tmlAction, params, null, null);
            }
            else {
                return "";
            }           
        }
        else {
            return url.toString();
        }
    }
   
    private String buildBasePath(TMLContext context) {
        StringBuffer url = new StringBuffer();
        url.append(context.getEnvironment().getPublisherURL());
        url.append("/");
        url.append(context.getdocument().getDatabase().getAttribute(WGACore.DBATTRIB_DBKEY).toString());
        return url.toString();
    }
   
    public String buildActionURL(TMLContext context, TMLAction action, List params, String portletMode, String portletContext) throws WGAPIException, UnsupportedEncodingException {
        String url = innerBuildActionURL(context, action, params, portletMode, portletContext);
        return rewriteURL(url, context.getrequest(), context.getwgacore(), false);
    }
   
    protected String innerBuildActionURL(TMLContext context, TMLAction action, List params, String portletMode, String portletContext) throws WGAPIException, UnsupportedEncodingException {
       
        BaseTagStatus tag = context.getDesignContext().getTag();
        if (tag == null) {
            return null;
        }
       
       
        TMLActionLink actionLink = action.createActionLink(params, context);
        actionLink.setPortletmode(portletMode);
        if (portletContext != null) {
            actionLink.setPortletContextPath(context, portletContext);
        }
              
        String encodedActionLink = actionLink.getEncodedString(context.getwgacore());

        // Retrieve relevant form.
        String formID = tag.getRelevantForm();

        // Inside a form we use javascript to post the action
        if (formID != null) {
            StringBuffer jsUrl = new StringBuffer();
            jsUrl.append("javascript:document.forms['" + formID + "'].$formaction.value ='" + encodedActionLink + "';");
            jsUrl.append("document.forms['" + formID + "'].submit();");

            return jsUrl.toString();
        }
       
        // Outside we use a simple action link
        else {
            try {
                URLBuilder builder = new URLBuilder(new java.net.URL(tag.getRequestURL()));
                builder.setParameterEncoding(context.getwgacore().getCharacterEncoding());
                builder.setParameter("$action", encodedActionLink);
                return builder.rebuild(false);
            }
            catch (MalformedURLException exc) {
                context.getlog().error("Error building action URL", exc);
                return null;
            }
        }
       
    }

    public boolean isTitlePathAllowed() {
        return _titlePathAllowed;
    }

    public void setTitlePathAllowed(boolean titlePathAllowed) {
        _titlePathAllowed = titlePathAllowed;
    }

    public String buildHomepageURL(WGDatabase db, HttpServletRequest request) throws WGException {
        String url = innerBuildHomepageURL(db, request);
        if (url != null) {
        return rewriteURL(url, request, WGACore.retrieve(request.getSession().getServletContext()), false);
    }
        else {
           return null;
        }
    }
   
  protected String innerBuildHomepageURL(WGDatabase db, HttpServletRequest request) throws WGException {
        String homepage = (String) db.getAttribute(WGACore.DBATTRIB_HOME_PAGE);
        WGACore core = WGACore.retrieve(request.getSession().getServletContext());
        WGPDispatcher dispatcher = core.getDispatcher();
        // First try: if db homepage attribute set - redirect to homepage
        if (homepage != null && !homepage.trim().equals("")) {
             return dispatcher.getPublisherURL(request) + "/" + db.getDbReference().toLowerCase() + "/" + homepage;
        }

        // Try to find a document named "home" in the relevant languages
        db = core.openContentDB(db, request, false);
        if (db.isSessionOpen()) {
           
            LanguageBehaviour langBehaviour = LanguageBehaviourTools.retrieve(db);
            WGContent content = langBehaviour.requestSelectContentForName(db, request, "home", false);
            if (content != null && content.mayBePublished(false, WGContent.DISPLAYTYPE_NONE)) {
                return dispatcher.getPublisherURL(request) + "/" + db.getDbReference().toLowerCase() + "/home";
            }
        }
    return null;
  }
 
    public String buildFileURL(TMLContext context, String dbKey, String containerName, String fileName) throws UnsupportedEncodingException, WGAPIException {
        String url = innerBuildFileURL(context, dbKey, containerName, fileName);
        return rewriteURL(url, context.getrequest(), context.getwgacore(), false);
    }

    protected String innerBuildFileURL(TMLContext context, String dbKey, String containerName, String fileName) throws UnsupportedEncodingException, WGAPIException {
       
        if (fileName == null) {
            context.addwarning("Missing file name for URL");
            return null;
        }
       
        if (context.iswebenvironment()) {
            containerName = context.resolveDesignReference(containerName);
        }
       
        // Basic path
        StringBuffer url = new StringBuffer();
        url.append(context.getEnvironment().getPublisherURL());
        url.append("/");
       
        // Determine containing database
        boolean containerIsContext = false;
        try {
       
            // If no container name given we will use the current content document in context
            if (containerName == null || containerName.equals("this")) {
                containerName = context.content().getContentKey(false).toString();
                containerIsContext = true;
                url.append(context.db().getDbReference());
            }
           
            // Explicit database addressed
            else if (dbKey != null) {
                WGDatabase designDB = context.db(context.resolveDBKey(dbKey));
                       
                if (designDB != null) {
                    url.append(designDB.getDbReference());
                }
                else {
                    context.addwarning("Unknown design db: " + dbKey);
                    return null;
                }
            }
           
            // No database addressed. Try to find file in file container of design db. Else we use the current context db
            else {
                WGFileContainer container = null;
               
                WGDatabase designDB = context.designdb();
                if (designDB != null && designDB.isSessionOpen()) {
                    container = designDB.getFileContainer(containerName);
                }

                if (container != null) {
                    url.append(designDB.getDbReference());
                }
                else {
                    url.append(context.db().getDbReference());
                }
            }
           
        }
        catch (WGException e) {
            context.addwarning("Error opening design db: " + e.getClass().getName() + " - " + e.getMessage());
            context.getlog().error("Error opening design db", e);
            return null;
        }
       
        // Address nested containers in URL form with slashes instead of colons, encode only the elements
        List<String> containerPath = new ArrayList<String>();
        for (String elem : containerName.split(":")) {
            containerPath.add(URLEncoder.encode(elem, context.getwgacore().getCharacterEncoding()));
        }
        String containerURL = WGUtils.serializeCollection(containerPath, "/");
       
        // Encode file path elements, but not the slashes
        List<String> filePath = new ArrayList<String>();
        for (String elem : fileName.split("/")) {
            filePath.add(URLEncoder.encode(elem, context.getwgacore().getCharacterEncoding()));
        }
        String fileURL = WGUtils.serializeCollection(filePath, "/");
       
        // if content doc addressed and filename contains ".zip/", we use the ~file-Syntax relative to the content URL so file URL will be relative to the content document URL (if not titlepath)
        if (containerIsContext && fileName.toLowerCase().indexOf(".zip/") != -1) {
            url = new StringBuffer();
            url.append(context.contenturl());
            url.append("/~file/");
            url.append(fileURL);           
        }
       
        // Normal syntax with qualifying "/file/" URL part
        else {
            url.append("/file/").append(containerURL).append("/").append(fileURL);
        }
        return url.toString();
       
    }
   
   
    public String rewriteURL(String url, HttpServletRequest request, WGACore core) {
        return rewriteURL(url, request, core, true);
    }
   
    public String rewriteURL(String url, HttpServletRequest request, WGACore core, boolean isVirtual) {
       
        // Cannot rewrite if no request available
        if (request == null) {
            return url;
        }
       
        VirtualHost vHost = WGAVirtualHostingFilter.findMatchingHost(core.getWgaConfiguration(), request);
        if (vHost == null) {
            return url;
        } else {
            URLBuilder builder = parseURL(core, request, url);
            if (builder != null) {
                String path = builder.getPath().substring(request.getContextPath().length());
                if (path.startsWith("/")) {
                    path = path.substring(1);
                }
                if (path.indexOf("/") != -1) {
                    String targetDBKey = path.substring(0, path.indexOf("/"));
                   
                    // skip vhosts processing for plugins
                    if (targetDBKey.startsWith("plugin-")) {
                        return url;
                    }
                   
                    // first check if default database is requested and if we have to hide it from url
                    if (vHost.isHideDefaultDatabaseInURL() && vHost.getDefaultDatabase() != null) {
                        String defaultDBKey = WGAVirtualHostingFilter.getDefaultDBKey(core, vHost);
                        if (defaultDBKey != null && targetDBKey.equalsIgnoreCase(defaultDBKey)) {
                            // default db requested - remove from path
                            builder.setPath(path.substring(defaultDBKey.length()));
                            try {
                                return builder.rebuild(false).toString();
                            }
                            catch (UnsupportedEncodingException e) {
                                core.getLog().error("Unable to rewrite url '" + url + "'.");
                            }
                        }
                    }
                   
                    if (!WGAVirtualHostingFilter.isDBKeyAllowed(core.getWgaConfiguration(), vHost, targetDBKey)) {                     
                        // we have to find the best matching host for this db and create an absolute url here                       
                        VirtualHost preferredHost = WGAVirtualHostingFilter.findPreferredHostForDatabase(core.getWgaConfiguration(), targetDBKey);
                        if (preferredHost != null) {
                            builder.setHost(preferredHost.getServername());
                            if (preferredHost.isHideDefaultDatabaseInURL() && preferredHost.getDefaultDatabase() != null) {
                                String defaultDBKey = WGAVirtualHostingFilter.getDefaultDBKey(core, preferredHost);
                                if (defaultDBKey != null && targetDBKey.equalsIgnoreCase(defaultDBKey)) {
                                 // default db requested - remove from path
                                    builder.setPath(path.substring(defaultDBKey.length()));
                                }
                            }
                            try {
                                return builder.rebuild(true).toString();
                            }
                            catch (UnsupportedEncodingException e) {
                                core.getLog().error("Unable to rewrite url '" + url + "'.");
                            }
                        }
                    }
                }
            }           
        }       
        return url;
    }

    private URLBuilder parseURL(WGACore core, HttpServletRequest request, String url) {
        URLBuilder builder = null;
        try {
            if (url.contains("://")) {
                builder = new URLBuilder(new URL(url));
            } else {
                URL urlObj = new URL(request.getRequestURL().toString());
                String path = null;
                String query = null;
                if (url.contains("?")) {
                    String[] tokens = url.split("\\?");
                    path = tokens[0];
                    query = tokens[1];
                } else {
                    path = url;
                }
                builder = new URLBuilder(urlObj.getProtocol(), urlObj.getPort(), urlObj.getHost(), path, null);
                if (query != null) {
                    builder.addQueryString(query, core.getCharacterEncoding());
                }
            }
        }
        catch (Exception e) {
            core.getLog().error("URLBuilder creating failed for url '" + url + "'.", e);
        }
        return builder;
    }

}
TOP

Related Classes of de.innovationgate.wgpublisher.url.DefaultURLBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.