001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id: DocumentFileCodec.java 29556 2008-01-23 00:59:39Z jcarsique $
018 */
019
020package org.nuxeo.ecm.platform.url.codec;
021
022import java.io.UnsupportedEncodingException;
023import java.net.URLDecoder;
024import java.util.HashMap;
025import java.util.Map;
026import java.util.regex.Matcher;
027import java.util.regex.Pattern;
028
029import org.apache.commons.logging.Log;
030import org.apache.commons.logging.LogFactory;
031import org.nuxeo.common.utils.StringUtils;
032import org.nuxeo.common.utils.URIUtils;
033import org.nuxeo.ecm.core.api.DocumentLocation;
034import org.nuxeo.ecm.core.api.DocumentModel;
035import org.nuxeo.ecm.core.api.DocumentRef;
036import org.nuxeo.ecm.core.api.IdRef;
037import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl;
038import org.nuxeo.ecm.core.utils.DocumentModelUtils;
039import org.nuxeo.ecm.platform.url.DocumentViewImpl;
040import org.nuxeo.ecm.platform.url.api.DocumentView;
041import org.nuxeo.ecm.platform.url.service.AbstractDocumentViewCodec;
042
043public class DocumentFileCodec extends AbstractDocumentViewCodec {
044
045    public static final String FILE_PROPERTY_PATH_KEY = "FILE_PROPERTY_PATH";
046
047    /**
048     * @deprecated soon will be part of the file property, passed as parameter for now
049     */
050    @Deprecated
051    public static final String FILENAME_PROPERTY_PATH_KEY = "FILENAME_PROPERTY_PATH";
052
053    public static final String FILENAME_KEY = "FILENAME";
054
055    private static final Log log = LogFactory.getLog(DocumentFileCodec.class);
056
057    // nxdoc/server/docId/property_path/filename/?requestParams
058    public static final String URLPattern = "/(\\w+)/([a-zA-Z_0-9\\-]+)(/([a-zA-Z_0-9/:\\-\\.\\]\\[]*))+(/([^\\?]*))+(\\?)?(.*)?";
059
060    public DocumentFileCodec() {
061    }
062
063    public DocumentFileCodec(String prefix) {
064        this.prefix = prefix;
065    }
066
067    @Override
068    public String getUrlFromDocumentView(DocumentView docView) {
069        DocumentLocation docLoc = docView.getDocumentLocation();
070        String filepath = docView.getParameter(FILE_PROPERTY_PATH_KEY);
071        String filename = docView.getParameter(FILENAME_KEY);
072        if (docLoc != null && filepath != null && filename != null) {
073            StringBuilder buf = new StringBuilder();
074            buf.append(getPrefix());
075            buf.append("/");
076            buf.append(docLoc.getServerName());
077            buf.append("/");
078            buf.append(docLoc.getDocRef().toString());
079            buf.append("/");
080            buf.append(filepath);
081            buf.append("/");
082            buf.append(URIUtils.quoteURIPathToken(filename));
083            String uri = buf.toString();
084            Map<String, String> requestParams = new HashMap<String, String>(docView.getParameters());
085            requestParams.remove(FILE_PROPERTY_PATH_KEY);
086            requestParams.remove(FILENAME_KEY);
087            return URIUtils.addParametersToURIQuery(uri, requestParams);
088        }
089        return null;
090    }
091
092    /**
093     * Extracts document location from a Zope-like URL ie : server/path_or_docId/view_id/tab_id .
094     */
095    @Override
096    public DocumentView getDocumentViewFromUrl(String url) {
097        final Pattern pattern = Pattern.compile(getPrefix() + URLPattern);
098        Matcher m = pattern.matcher(url);
099        if (m.matches()) {
100            if (m.groupCount() >= 4) {
101
102                // for debug
103                // for (int i = 1; i < m.groupCount() + 1; i++) {
104                // System.err.println(i + ": " + m.group(i));
105                // }
106
107                final String server = m.group(1);
108                String uuid = m.group(2);
109                final DocumentRef docRef = new IdRef(uuid);
110
111                // get other parameters
112
113                Map<String, String> params = new HashMap<String, String>();
114                if (m.groupCount() >= 4) {
115                    String filePropertyPath = m.group(4);
116                    params.put(FILE_PROPERTY_PATH_KEY, filePropertyPath);
117                }
118
119                if (m.groupCount() >= 6) {
120                    String filename = m.group(6);
121                    try {
122                        filename = URLDecoder.decode(filename, "UTF-8");
123                    } catch (UnsupportedEncodingException e) {
124                        filename = StringUtils.toAscii(filename);
125                    }
126                    int jsessionidIndex = filename.indexOf(";jsessionid");
127                    if (jsessionidIndex != -1) {
128                        filename = filename.substring(0, jsessionidIndex);
129                    }
130                    params.put(FILENAME_KEY, filename);
131                }
132
133                if (m.groupCount() >= 8) {
134                    String query = m.group(8);
135                    Map<String, String> requestParams = URIUtils.getRequestParameters(query);
136                    if (requestParams != null) {
137                        params.putAll(requestParams);
138                    }
139                }
140
141                final DocumentLocation docLoc = new DocumentLocationImpl(server, docRef);
142
143                return new DocumentViewImpl(docLoc, null, params);
144            }
145        }
146
147        return null;
148    }
149
150    public static String getFilename(DocumentModel doc, DocumentView docView) {
151        String filename = docView.getParameter(FILENAME_KEY);
152        if (filename == null) {
153            // try to get it from document
154            String propertyPath = docView.getParameter(FILENAME_PROPERTY_PATH_KEY);
155            String propertyName = DocumentModelUtils.decodePropertyName(propertyPath);
156            if (propertyName != null) {
157                filename = (String) DocumentModelUtils.getPropertyValue(doc, propertyName);
158            }
159        }
160        return filename;
161    }
162
163}