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 public class UUIDLink {
61
62 private String repository;
63 private String handle;
64 private String uuid;
65 private String nodeDataName;
66 private String extension;
67 private Content node;
68 private NodeData nodeData;
69 private String fileName;
70 private String fallbackHandle;
71 private String anchor;
72 private String parameters;
73
74
75
76
77 public static Pattern UUID_PATTERN = Pattern.compile("\\$\\{link:\\{uuid:\\{([^\\}]*)\\},"
78
79
80
81
82 + "repository:\\{([^\\}]*)\\}," + "(workspace:\\{[^\\}]*\\},)?"
83
84
85
86 + "(path|handle):\\{([^\\}]*)\\}"
87
88 + "(,nodeData:\\{([^\\}]*)\\},"
89
90 + "extension:\\{([^\\}]*)\\})?"
91
92 + "\\}\\}"
93 + "(#([^\\?\"]*))?"
94 + "(\\?([^\"]*))?");
95
96 protected static final Pattern LINK_PATTERN = Pattern.compile("(/[^\\.\"#\\?]*)" +
97
98 "(\\.([\\w[^#\\?]]+))?" +
99 "(#([^\\?\"]*))?" +
100 "(\\?([^\"]*))?"
101 );
102
103
104
105
106 private static Logger log = LoggerFactory.getLogger(UUIDLink.class);
107
108
109
110
111 public UUIDLink() {
112 }
113
114 public UUIDLink parseUUIDLink(String uuidLink) throws UUIDLinkException {
115 Matcher matcher = UUID_PATTERN.matcher(uuidLink);
116 if (matcher.matches()) {
117 initByUUIDPatternMatcher(matcher);
118 } else {
119 throw new UUIDLinkException("can't parse [ " + uuidLink + "]");
120 }
121 return this;
122 }
123
124 UUIDLink initByUUIDPatternMatcher(Matcher matcher) {
125 uuid = matcher.group(1);
126 repository = StringUtils.defaultIfEmpty(matcher.group(2), ContentRepository.WEBSITE);
127 fallbackHandle = matcher.group(5);
128 nodeDataName = matcher.group(7);
129 extension = matcher.group(8);
130 anchor = matcher.group(10);
131 parameters = matcher.group(12);
132 return this;
133 }
134
135 public UUIDLink parseLink(String link) throws UUIDLinkException {
136
137 link = StringUtils.removeStart(link, MgnlContext.getContextPath());
138
139 Matcher matcher = LINK_PATTERN.matcher(link);
140 if (matcher.matches()) {
141 String orgHandle = matcher.group(1);
142 orgHandle = I18nContentSupportFactory.getI18nSupport().toRawURI(orgHandle);
143 String repository = URI2RepositoryManager.getInstance().getRepository(orgHandle);
144 String handle = URI2RepositoryManager.getInstance().getHandle(orgHandle);
145 init(repository, handle, matcher.group(3), matcher.group(5), matcher.group(7));
146 } else {
147 throw new UUIDLinkException("can't parse [ " + link + "]");
148 }
149 return this;
150 }
151
152 public UUIDLink initWithHandle(String repository, String handle) throws UUIDLinkException {
153 init(repository, handle, null, null, null);
154 return this;
155 }
156
157 protected void init(String repository, String path, String extension, String anchor, String parameters) throws UUIDLinkException {
158 this.repository = repository;
159 this.extension = extension;
160 this.anchor = anchor;
161 this.parameters = parameters;
162
163 try {
164 HierarchyManager hm = MgnlContext.getHierarchyManager(repository);
165 if (hm.isExist(path) && !hm.isNodeData(path)) {
166 node = hm.getContent(path);
167 }
168 if (node == null) {
169
170 if (hm.isNodeData(StringUtils.substringBeforeLast(path, "/"))) {
171 fileName = StringUtils.substringAfterLast(path, "/");
172 path = StringUtils.substringBeforeLast(path, "/");
173 }
174
175
176 if (hm.isNodeData(path)) {
177 nodeDataName = StringUtils.substringAfterLast(path, "/");
178 path = StringUtils.substringBeforeLast(path, "/");
179 node = hm.getContent(path);
180 nodeData = node.getNodeData(nodeDataName);
181 }
182 }
183 if (node != null) {
184 uuid = node.getUUID();
185 }
186 this.handle = path;
187 } catch (RepositoryException e) {
188 throw new UUIDLinkException("can't find node " + path + " in repository " + repository, e);
189 }
190
191 if (node == null) {
192 throw new UUIDLinkException("can't find node " + path + " in repository " + repository);
193 }
194 }
195
196 public String toPattern() {
197 return "${link:{" + "uuid:{" + getUUID() + "}," + "repository:{" + getRepository() + "}," + "handle:{" + getHandle() + "},"
198 + "nodeData:{" + StringUtils.defaultString(getNodeDataName()) + "},"
199 + "extension:{" + StringUtils.defaultString(getExtension()) + "}"
200 + "}}" + (StringUtils.isNotEmpty(getAnchor()) ? "#" + getAnchor() : "") + (StringUtils.isNotEmpty(getParameters()) ? "?" + getParameters() : "");
201 }
202
203 public String getExtension() {
204 if (StringUtils.isEmpty(this.extension) && this.getNodeData() != null) {
205 if (this.getNodeData().getType() == PropertyType.BINARY) {
206 File binary = new File(nodeData);
207 extension = binary.getExtension();
208 }
209 }
210 return StringUtils.defaultIfEmpty(this.extension, ServerConfiguration.getInstance().getDefaultExtension());
211 }
212
213 public void setExtension(String extension) {
214 this.extension = extension;
215 }
216
217 public String getFileName() {
218 if (StringUtils.isEmpty(this.fileName) && this.getNodeData() != null) {
219 if (this.getNodeData().getType() == PropertyType.BINARY) {
220 File binary = new File(nodeData);
221 fileName = binary.getFileName();
222 }
223 }
224 return fileName;
225 }
226
227 public void setFileName(String fileName) {
228 this.fileName = fileName;
229 }
230
231 public Content getNode() {
232
233 if (this.node == null) {
234 HierarchyManager hm = MgnlContext.getHierarchyManager(repository);
235 if (StringUtils.isNotEmpty(uuid)) {
236 try {
237 node = hm.getContentByUUID(uuid);
238 } catch (RepositoryException e) {
239 log.warn("can't get node with uuid [{}] will try stored handle [{}]", new String[] { uuid, handle });
240 }
241 }
242
243
244 if (this.node == null && StringUtils.isNotEmpty(handle)) {
245 try {
246 node = hm.getContent(handle);
247 } catch (RepositoryException e1) {
248 log.warn("can't read node by using handle [{}]", handle);
249 }
250 }
251 }
252 return this.node;
253 }
254
255 public void setNode(Content node) {
256 this.node = node;
257 }
258
259 public NodeData getNodeData() {
260 if (this.nodeData == null && StringUtils.isNotEmpty(this.nodeDataName) && this.getNode() != null) {
261 this.nodeData = this.getNode().getNodeData(this.nodeDataName);
262 }
263 return this.nodeData;
264 }
265
266 public void setNodeData(NodeData nodeData) {
267 this.nodeData = nodeData;
268 }
269
270 public String getNodeDataName() {
271 return this.nodeDataName;
272 }
273
274 public void setNodeDataName(String nodeDataName) {
275 this.nodeDataName = nodeDataName;
276 }
277
278 public String getHandle() {
279 if (StringUtils.isEmpty(this.handle)) {
280 if (getNode() != null) {
281 handle = getNode().getHandle();
282 } else {
283 handle = this.getFallbackHandle();
284 }
285 }
286 return this.handle;
287 }
288
289 public void setHandle(String path) {
290 this.handle = path;
291 }
292
293 public String getRepository() {
294 return this.repository;
295 }
296
297 public void setRepository(String repository) {
298 this.repository = repository;
299 }
300
301 public String getUUID() {
302 if (StringUtils.isEmpty(this.uuid) && this.getNode() != null) {
303 this.uuid = this.getNode().getUUID();
304 }
305 return this.uuid;
306 }
307
308 public void setUUID(String uuid) {
309 this.uuid = uuid;
310 }
311
312 public String getFallbackHandle() {
313 return this.fallbackHandle;
314 }
315
316 public void setFallbackHandle(String fallbackPath) {
317 this.fallbackHandle = fallbackPath;
318 }
319
320 public String getAnchor() {
321 return this.anchor;
322 }
323
324 public void setAnchor(String anchor) {
325 this.anchor = anchor;
326 }
327
328 public String getParameters() {
329 return this.parameters;
330 }
331
332 public void setParameters(String parameters) {
333 this.parameters = parameters;
334 }
335 }