View Javadoc

1   /**
2    * This file Copyright (c) 2003-2010 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.cms.link;
35  
36  import info.magnolia.cms.beans.config.ContentRepository;
37  import info.magnolia.cms.beans.config.ServerConfiguration;
38  import info.magnolia.cms.beans.config.URI2RepositoryManager;
39  import info.magnolia.cms.beans.runtime.File;
40  import info.magnolia.cms.core.Content;
41  import info.magnolia.cms.core.HierarchyManager;
42  import info.magnolia.cms.core.NodeData;
43  import info.magnolia.cms.i18n.I18nContentSupportFactory;
44  import info.magnolia.context.MgnlContext;
45  
46  import java.util.regex.Matcher;
47  import java.util.regex.Pattern;
48  
49  import javax.jcr.PropertyType;
50  import javax.jcr.RepositoryException;
51  
52  import org.apache.commons.lang.StringUtils;
53  import org.slf4j.Logger;
54  import org.slf4j.LoggerFactory;
55  
56  /**
57   * @author philipp
58   * @version $Id: UUIDLink.java 32667 2010-03-13 00:37:06Z gjoseph $
59   * @deprecated since 4.0 use {@link info.magnolia.link.Link} instead
60   */
61  public class UUIDLink {
62  
63      private String repository;
64      private String handle;
65      private String uuid;
66      private String nodeDataName;
67      private String extension;
68      private Content node;
69      private NodeData nodeData;
70      private String fileName;
71      private String fallbackHandle;
72      private String anchor;
73      private String parameters;
74  
75      /**
76       * Pattern to find a magnolia formatted link
77       */
78      public static Pattern UUID_PATTERN = Pattern.compile("\\$\\{link:\\{uuid:\\{([^\\}]*)\\}," // the
79                                                                                                 // uuid
80                                                                                                 // of
81                                                                                                 // the
82                                                                                                 // node
83              + "repository:\\{([^\\}]*)\\}," + "(workspace:\\{[^\\}]*\\},)?" // is
84                                                                              // not
85                                                                              // supported
86                                                                              // anymore
87              + "(path|handle):\\{([^\\}]*)\\}" // fallback handle should not be
88                                                // used unless the uuid is invalid
89              + "(,nodeData:\\{([^\\}]*)\\}," // in case we point to a binary
90                                              // (node data has no uuid!)
91              + "extension:\\{([^\\}]*)\\})?" // the extension to be used in
92                                              // rendering
93              + "\\}\\}" // the handle
94              + "(#([^\\?\"]*))?" // anchor
95              + "(\\?([^\"]*))?"); // parameters
96  
97      protected static final Pattern LINK_PATTERN = Pattern.compile("(/[^\\.\"#\\?]*)" + // the
98                                                                                         // handle
99              "(\\.([\\w[^#\\?]]+))?" + // extension (if any)
100             "(#([^\\?\"]*))?" + // anchor
101             "(\\?([^\"]*))?" // parameters
102     );
103 
104     /**
105      * Logger.
106      */
107     private static Logger log = LoggerFactory.getLogger(UUIDLink.class);
108 
109     /**
110      * Use parseUUIDLink() or parseLink() to initialize the link object
111      */
112     public UUIDLink() {
113     }
114 
115     public UUIDLink parseUUIDLink(String uuidLink) throws UUIDLinkException {
116         Matcher matcher = UUID_PATTERN.matcher(uuidLink);
117         if (matcher.matches()) {
118             initByUUIDPatternMatcher(matcher);
119         } else {
120             throw new UUIDLinkException("can't parse [ " + uuidLink + "]");
121         }
122         return this;
123     }
124 
125     UUIDLink initByUUIDPatternMatcher(Matcher matcher) {
126         uuid = matcher.group(1);
127         repository = StringUtils.defaultIfEmpty(matcher.group(2), ContentRepository.WEBSITE);
128         fallbackHandle = matcher.group(5);
129         nodeDataName = matcher.group(7);
130         extension = matcher.group(8);
131         anchor = matcher.group(10);
132         parameters = matcher.group(12);
133         return this;
134     }
135 
136     public UUIDLink parseLink(String link) throws UUIDLinkException {
137         // ignore context handle if existing
138         link = StringUtils.removeStart(link, MgnlContext.getContextPath());
139 
140         Matcher matcher = LINK_PATTERN.matcher(link);
141         if (matcher.matches()) {
142             String orgHandle = matcher.group(1);
143             orgHandle = I18nContentSupportFactory.getI18nSupport().toRawURI(orgHandle);
144             String repository = URI2RepositoryManager.getInstance().getRepository(orgHandle);
145             String handle = URI2RepositoryManager.getInstance().getHandle(orgHandle);
146             init(repository, handle, matcher.group(3), matcher.group(5), matcher.group(7));
147         } else {
148             throw new UUIDLinkException("can't parse [ " + link + "]");
149         }
150         return this;
151     }
152 
153     public UUIDLink initWithHandle(String repository, String handle) throws UUIDLinkException {
154         init(repository, handle, null, null, null);
155         return this;
156     }
157 
158     protected void init(String repository, String path, String extension, String anchor, String parameters) throws UUIDLinkException {
159         this.repository = repository;
160         this.extension = extension;
161         this.anchor = anchor;
162         this.parameters = parameters;
163 
164         try {
165             HierarchyManager hm = MgnlContext.getHierarchyManager(repository);
166             if (hm.isExist(path) && !hm.isNodeData(path)) {
167                 node = hm.getContent(path);
168             }
169             if (node == null) {
170                 // this is a binary containing the name at the end this name is stored as an attribute but is not part of the handle
171                 if (hm.isNodeData(StringUtils.substringBeforeLast(path, "/"))) {
172                     fileName = StringUtils.substringAfterLast(path, "/");
173                     path = StringUtils.substringBeforeLast(path, "/");
174                 }
175 
176                 // link to the binary node data
177                 if (hm.isNodeData(path)) {
178                     nodeDataName = StringUtils.substringAfterLast(path, "/");
179                     path = StringUtils.substringBeforeLast(path, "/");
180                     node = hm.getContent(path);
181                     nodeData = node.getNodeData(nodeDataName);
182                 }
183             }
184             if (node != null) {
185                 uuid = node.getUUID();
186             }
187             this.handle = path;
188         } catch (RepositoryException e) {
189             throw new UUIDLinkException("can't find node " + path + " in repository " + repository, e);
190         }
191 
192         if (node == null) {
193             throw new UUIDLinkException("can't find node " + path + " in repository " + repository);
194         }
195     }
196 
197     public String toPattern() {
198         return "${link:{" + "uuid:{" + getUUID() + "}," + "repository:{" + getRepository() + "}," + "handle:{" + getHandle() + "}," // original handle represented by the uuid
199                 + "nodeData:{" + StringUtils.defaultString(getNodeDataName()) + "}," // in case of binaries
200                 + "extension:{" + StringUtils.defaultString(getExtension()) + "}" // the extension to use if no extension can be resolved otherwise
201                 + "}}" + (StringUtils.isNotEmpty(getAnchor()) ? "#" + getAnchor() : "") + (StringUtils.isNotEmpty(getParameters()) ? "?" + getParameters() : "");
202     }
203 
204     public String getExtension() {
205         if (StringUtils.isEmpty(this.extension) && this.getNodeData() != null) {
206             if (this.getNodeData().getType() == PropertyType.BINARY) {
207                 File binary = new File(nodeData);
208                 extension = binary.getExtension();
209             }
210         }
211         return StringUtils.defaultIfEmpty(this.extension, ServerConfiguration.getInstance().getDefaultExtension());
212     }
213 
214     public void setExtension(String extension) {
215         this.extension = extension;
216     }
217 
218     public String getFileName() {
219         if (StringUtils.isEmpty(this.fileName) && this.getNodeData() != null) {
220             if (this.getNodeData().getType() == PropertyType.BINARY) {
221                 File binary = new File(nodeData);
222                 fileName = binary.getFileName();
223             }
224         }
225         return fileName;
226     }
227 
228     public void setFileName(String fileName) {
229         this.fileName = fileName;
230     }
231 
232     public Content getNode() {
233 
234         if (this.node == null) {
235             HierarchyManager hm = MgnlContext.getHierarchyManager(repository);
236             if (StringUtils.isNotEmpty(uuid)) {
237                 try {
238                     node = hm.getContentByUUID(uuid);
239                 } catch (RepositoryException e) {
240                     log.warn("can't get node with uuid [{}] will try stored handle [{}]", new String[] { uuid, handle });
241                 }
242             }
243 
244             // uuid is not defined or resolving by uuid failed
245             if (this.node == null && StringUtils.isNotEmpty(handle)) {
246                 try {
247                     node = hm.getContent(handle);
248                 } catch (RepositoryException e1) {
249                     log.warn("can't read node by using handle [{}]", handle);
250                 }
251             }
252         }
253         return this.node;
254     }
255 
256     public void setNode(Content node) {
257         this.node = node;
258     }
259 
260     public NodeData getNodeData() {
261         if (this.nodeData == null && StringUtils.isNotEmpty(this.nodeDataName) && this.getNode() != null) {
262             this.nodeData = this.getNode().getNodeData(this.nodeDataName);
263         }
264         return this.nodeData;
265     }
266 
267     public void setNodeData(NodeData nodeData) {
268         this.nodeData = nodeData;
269     }
270 
271     public String getNodeDataName() {
272         return this.nodeDataName;
273     }
274 
275     public void setNodeDataName(String nodeDataName) {
276         this.nodeDataName = nodeDataName;
277     }
278 
279     public String getHandle() {
280         if (StringUtils.isEmpty(this.handle)) {
281             if (getNode() != null) {
282                 handle = getNode().getHandle();
283             } else {
284                 handle = this.getFallbackHandle();
285             }
286         }
287         return this.handle;
288     }
289 
290     public void setHandle(String path) {
291         this.handle = path;
292     }
293 
294     public String getRepository() {
295         return this.repository;
296     }
297 
298     public void setRepository(String repository) {
299         this.repository = repository;
300     }
301 
302     public String getUUID() {
303         if (StringUtils.isEmpty(this.uuid) && this.getNode() != null) {
304             this.uuid = this.getNode().getUUID();
305         }
306         return this.uuid;
307     }
308 
309     public void setUUID(String uuid) {
310         this.uuid = uuid;
311     }
312 
313     public String getFallbackHandle() {
314         return this.fallbackHandle;
315     }
316 
317     public void setFallbackHandle(String fallbackPath) {
318         this.fallbackHandle = fallbackPath;
319     }
320 
321     public String getAnchor() {
322         return this.anchor;
323     }
324 
325     public void setAnchor(String anchor) {
326         this.anchor = anchor;
327     }
328 
329     public String getParameters() {
330         return this.parameters;
331     }
332 
333     public void setParameters(String parameters) {
334         this.parameters = parameters;
335     }
336 }