1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
58
59
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
77
78 public static Pattern UUID_PATTERN = Pattern.compile("\\$\\{link:\\{uuid:\\{([^\\}]*)\\},"
79
80
81
82
83 + "repository:\\{([^\\}]*)\\}," + "(workspace:\\{[^\\}]*\\},)?"
84
85
86
87 + "(path|handle):\\{([^\\}]*)\\}"
88
89 + "(,nodeData:\\{([^\\}]*)\\},"
90
91 + "extension:\\{([^\\}]*)\\})?"
92
93 + "\\}\\}"
94 + "(#([^\\?\"]*))?"
95 + "(\\?([^\"]*))?");
96
97 protected static final Pattern LINK_PATTERN = Pattern.compile("(/[^\\.\"#\\?]*)" +
98
99 "(\\.([\\w[^#\\?]]+))?" +
100 "(#([^\\?\"]*))?" +
101 "(\\?([^\"]*))?"
102 );
103
104
105
106
107 private static Logger log = LoggerFactory.getLogger(UUIDLink.class);
108
109
110
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
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
171 if (hm.isNodeData(StringUtils.substringBeforeLast(path, "/"))) {
172 fileName = StringUtils.substringAfterLast(path, "/");
173 path = StringUtils.substringBeforeLast(path, "/");
174 }
175
176
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() + "},"
199 + "nodeData:{" + StringUtils.defaultString(getNodeDataName()) + "},"
200 + "extension:{" + StringUtils.defaultString(getExtension()) + "}"
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
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 }