]> git.argeo.org Git - lgpl/argeo-commons.git/blob - server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/JcrResourceAdapter.java
Improve JCR mapper
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jackrabbit / src / main / java / org / argeo / server / jcr / JcrResourceAdapter.java
1 package org.argeo.server.jcr;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.ArrayList;
6 import java.util.Calendar;
7 import java.util.List;
8
9 import javax.activation.MimetypesFileTypeMap;
10 import javax.jcr.Node;
11 import javax.jcr.Property;
12 import javax.jcr.Repository;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.Session;
15 import javax.jcr.SimpleCredentials;
16 import javax.jcr.version.Version;
17 import javax.jcr.version.VersionHistory;
18 import javax.jcr.version.VersionIterator;
19
20 import org.apache.commons.io.FilenameUtils;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.argeo.ArgeoException;
24 import org.argeo.jcr.JcrUtils;
25 import org.springframework.beans.factory.DisposableBean;
26 import org.springframework.beans.factory.InitializingBean;
27 import org.springframework.core.io.Resource;
28
29 public class JcrResourceAdapter implements InitializingBean, DisposableBean {
30 private final static Log log = LogFactory.getLog(JcrResourceAdapter.class);
31
32 private Repository repository;
33
34 private String username;
35 private String password;
36
37 private Session session;
38
39 private Boolean versioning = true;
40 private String defaultEncoding = "UTF-8";
41
42 // private String restoreBase = "/.restore";
43
44 public void mkdirs(String path) {
45 JcrUtils.mkdirs(session(), path, "nt:folder", versioning);
46 }
47
48 public void create(String path, Resource file, String mimeType) {
49 try {
50 create(path, file.getInputStream(), mimeType);
51 } catch (IOException e) {
52 throw new ArgeoException("Cannot read " + file, e);
53 }
54 }
55
56 public void create(String path, InputStream in, String mimeType) {
57 try {
58 if (session().itemExists(path)) {
59 throw new ArgeoException("Node " + path + " already exists.");
60 }
61
62 int index = path.lastIndexOf('/');
63 String parentPath = path.substring(0, index);
64 if (parentPath.equals(""))
65 parentPath = "/";
66 String fileName = path.substring(index + 1);
67 if (!session().itemExists(parentPath))
68 throw new ArgeoException("Parent folder of node " + path
69 + " does not exist: " + parentPath);
70
71 Node folderNode = (Node) session().getItem(parentPath);
72 Node fileNode = folderNode.addNode(fileName, "nt:file");
73
74 Node contentNode = fileNode.addNode("jcr:content", "nt:resource");
75 if (mimeType != null)
76 contentNode.setProperty("jcr:mimeType", mimeType);
77 contentNode.setProperty("jcr:encoding", defaultEncoding);
78 contentNode.setProperty("jcr:data", in);
79 Calendar lastModified = Calendar.getInstance();
80 // lastModified.setTimeInMillis(file.lastModified());
81 contentNode.setProperty("jcr:lastModified", lastModified);
82 // resNode.addMixin("mix:referenceable");
83
84 if (versioning)
85 fileNode.addMixin("mix:versionable");
86
87 session().save();
88
89 if (versioning)
90 fileNode.checkin();
91
92 if (log.isDebugEnabled())
93 log.debug("Created " + path);
94 } catch (Exception e) {
95 throw new ArgeoException("Cannot create node for " + path, e);
96 }
97
98 }
99
100 public void update(String path, Resource file) {
101 try {
102 update(path, file.getInputStream());
103 } catch (IOException e) {
104 throw new ArgeoException("Cannot read " + file, e);
105 }
106 }
107
108 public void update(String path, InputStream in) {
109 try {
110
111 if (!session().itemExists(path)) {
112 String type = new MimetypesFileTypeMap()
113 .getContentType(FilenameUtils.getName(path));
114 create(path, in, type);
115 return;
116 }
117
118 Node fileNode = (Node) session().getItem(path);
119 Node contentNode = fileNode.getNode("jcr:content");
120 fileNode.checkout();
121 contentNode.setProperty("jcr:data", in);
122 Calendar lastModified = Calendar.getInstance();
123 // lastModified.setTimeInMillis(file.lastModified());
124 contentNode.setProperty("jcr:lastModified", lastModified);
125
126 session().save();
127 fileNode.checkin();
128
129 if (log.isDebugEnabled())
130 log.debug("Updated " + path);
131 } catch (Exception e) {
132 throw new ArgeoException("Cannot update node " + path, e);
133 }
134 }
135
136 public List<Calendar> listVersions(String path) {
137 if (!versioning)
138 throw new ArgeoException("Versioning is not activated");
139
140 try {
141 List<Calendar> versions = new ArrayList<Calendar>();
142 Node fileNode = (Node) session().getItem(path);
143 VersionHistory history = fileNode.getVersionHistory();
144 for (VersionIterator it = history.getAllVersions(); it.hasNext();) {
145 Version version = (Version) it.next();
146 versions.add(version.getCreated());
147 if (log.isTraceEnabled()) {
148 log.debug(version);
149 // debug(version);
150 }
151 }
152 return versions;
153 } catch (Exception e) {
154 throw new ArgeoException("Cannot list version of node " + path, e);
155 }
156 }
157
158 public InputStream retrieve(String path) {
159 try {
160 Node node = (Node) session().getItem(path + "/jcr:content");
161 Property property = node.getProperty("jcr:data");
162 return property.getStream();
163 } catch (Exception e) {
164 throw new ArgeoException("Cannot retrieve " + path, e);
165 }
166 }
167
168 public synchronized InputStream retrieve(String path, Integer revision) {
169 if (!versioning)
170 throw new ArgeoException("Versioning is not activated");
171
172 try {
173 Node fileNode = (Node) session().getItem(path);
174 VersionHistory history = fileNode.getVersionHistory();
175 int count = 0;
176 Version version = null;
177 for (VersionIterator it = history.getAllVersions(); it.hasNext();) {
178 version = (Version) it.next();
179 if (count == revision + 1) {
180 InputStream in = fromVersion(version);
181 if (log.isDebugEnabled())
182 log.debug("Retrieved " + path + " at revision "
183 + revision);
184 return in;
185 }
186 count++;
187 }
188 } catch (Exception e) {
189 throw new ArgeoException("Cannot retrieve version " + revision
190 + " of " + path, e);
191 }
192
193 throw new ArgeoException("Version " + revision
194 + " does not exist for node " + path);
195 }
196
197 protected InputStream fromVersion(Version version)
198 throws RepositoryException {
199 Node frozenNode = version.getNode("jcr:frozenNode");
200 InputStream in = frozenNode.getNode("jcr:content").getProperty(
201 "jcr:data").getStream();
202 return in;
203 }
204
205 protected Session session() {
206 return session;
207 }
208
209 public void afterPropertiesSet() throws Exception {
210 session = repository.login(new SimpleCredentials(username, password
211 .toCharArray()));
212 }
213
214 public void destroy() throws Exception {
215 session.logout();
216 }
217
218 public void setRepository(Repository repository) {
219 this.repository = repository;
220 }
221
222 public void setUsername(String username) {
223 this.username = username;
224 }
225
226 public void setPassword(String password) {
227 this.password = password;
228 }
229
230 public void setVersioning(Boolean versioning) {
231 this.versioning = versioning;
232 }
233
234 public void setDefaultEncoding(String defaultEncoding) {
235 this.defaultEncoding = defaultEncoding;
236 }
237
238 protected String fill(Integer number) {
239 int size = 4;
240 String str = number.toString();
241 for (int i = str.length(); i < size; i++) {
242 str = "0" + str;
243 }
244 return str;
245 }
246 }