]> git.argeo.org Git - lgpl/argeo-commons.git/blob - server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrResourceAdapter.java
Synchronize login
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jcr / src / main / java / org / argeo / jcr / JcrResourceAdapter.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.argeo.jcr;
18
19 import java.io.InputStream;
20 import java.util.ArrayList;
21 import java.util.Calendar;
22 import java.util.List;
23
24 import javax.jcr.Binary;
25 import javax.jcr.Node;
26 import javax.jcr.Property;
27 import javax.jcr.RepositoryException;
28 import javax.jcr.Session;
29 import javax.jcr.nodetype.NodeType;
30 import javax.jcr.version.Version;
31 import javax.jcr.version.VersionHistory;
32 import javax.jcr.version.VersionIterator;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.argeo.ArgeoException;
37
38 /**
39 * Bridge Spring resources and JCR folder / files semantics (nt:folder /
40 * nt:file), supporting versioning as well.
41 */
42 public class JcrResourceAdapter {
43 private final static Log log = LogFactory.getLog(JcrResourceAdapter.class);
44
45 private Session session;
46
47 private Boolean versioning = true;
48 private String defaultEncoding = "UTF-8";
49
50 // private String restoreBase = "/.restore";
51
52 public JcrResourceAdapter() {
53 }
54
55 public JcrResourceAdapter(Session session) {
56 this.session = session;
57 }
58
59 public void mkdirs(String path) {
60 JcrUtils.mkdirs(session(), path, NodeType.NT_FOLDER,
61 NodeType.NT_FOLDER, versioning);
62 }
63
64 public void create(String path, InputStream in, String mimeType) {
65 try {
66 if (session().itemExists(path)) {
67 throw new ArgeoException("Node " + path + " already exists.");
68 }
69
70 int index = path.lastIndexOf('/');
71 String parentPath = path.substring(0, index);
72 if (parentPath.equals(""))
73 parentPath = "/";
74 String fileName = path.substring(index + 1);
75 if (!session().itemExists(parentPath))
76 throw new ArgeoException("Parent folder of node " + path
77 + " does not exist: " + parentPath);
78
79 Node folderNode = (Node) session().getItem(parentPath);
80 Node fileNode = folderNode.addNode(fileName, "nt:file");
81
82 Node contentNode = fileNode.addNode(Property.JCR_CONTENT,
83 "nt:resource");
84 if (mimeType != null)
85 contentNode.setProperty(Property.JCR_MIMETYPE, mimeType);
86 contentNode.setProperty(Property.JCR_ENCODING, defaultEncoding);
87 Binary binary = session().getValueFactory().createBinary(in);
88 contentNode.setProperty(Property.JCR_DATA, binary);
89 JcrUtils.closeQuietly(binary);
90 Calendar lastModified = Calendar.getInstance();
91 // lastModified.setTimeInMillis(file.lastModified());
92 contentNode.setProperty(Property.JCR_LAST_MODIFIED, lastModified);
93 // resNode.addMixin("mix:referenceable");
94
95 if (versioning)
96 fileNode.addMixin("mix:versionable");
97
98 session().save();
99
100 if (versioning)
101 session().getWorkspace().getVersionManager()
102 .checkin(fileNode.getPath());
103
104 if (log.isDebugEnabled())
105 log.debug("Created " + path);
106 } catch (Exception e) {
107 throw new ArgeoException("Cannot create node for " + path, e);
108 }
109
110 }
111
112 public void update(String path, InputStream in) {
113 try {
114
115 if (!session().itemExists(path)) {
116 String type = null;
117 // FIXME: using javax.activation leads to conflict between Java
118 // 1.5 and 1.6 (since javax.activation was included in Java 1.6)
119 // String type = new MimetypesFileTypeMap()
120 // .getContentType(FilenameUtils.getName(path));
121 create(path, in, type);
122 return;
123 }
124
125 Node fileNode = (Node) session().getItem(path);
126 Node contentNode = fileNode.getNode(Property.JCR_CONTENT);
127 if (versioning)
128 session().getWorkspace().getVersionManager()
129 .checkout(fileNode.getPath());
130 Binary binary = session().getValueFactory().createBinary(in);
131 contentNode.setProperty(Property.JCR_DATA, binary);
132 JcrUtils.closeQuietly(binary);
133 Calendar lastModified = Calendar.getInstance();
134 // lastModified.setTimeInMillis(file.lastModified());
135 contentNode.setProperty(Property.JCR_LAST_MODIFIED, lastModified);
136
137 session().save();
138 if (versioning)
139 session().getWorkspace().getVersionManager()
140 .checkin(fileNode.getPath());
141
142 if (log.isDebugEnabled())
143 log.debug("Updated " + path);
144 } catch (Exception e) {
145 throw new ArgeoException("Cannot update node " + path, e);
146 }
147 }
148
149 public List<Calendar> listVersions(String path) {
150 if (!versioning)
151 throw new ArgeoException("Versioning is not activated");
152
153 try {
154 List<Calendar> versions = new ArrayList<Calendar>();
155 Node fileNode = (Node) session().getItem(path);
156 VersionHistory history = session().getWorkspace()
157 .getVersionManager().getVersionHistory(fileNode.getPath());
158 for (VersionIterator it = history.getAllVersions(); it.hasNext();) {
159 Version version = (Version) it.next();
160 versions.add(version.getCreated());
161 if (log.isTraceEnabled()) {
162 log.debug(version);
163 // debug(version);
164 }
165 }
166 return versions;
167 } catch (Exception e) {
168 throw new ArgeoException("Cannot list version of node " + path, e);
169 }
170 }
171
172 public InputStream retrieve(String path) {
173 try {
174 Node node = (Node) session().getItem(
175 path + "/" + Property.JCR_CONTENT);
176 Property property = node.getProperty(Property.JCR_DATA);
177 return property.getBinary().getStream();
178 } catch (Exception e) {
179 throw new ArgeoException("Cannot retrieve " + path, e);
180 }
181 }
182
183 public synchronized InputStream retrieve(String path, Integer revision) {
184 if (!versioning)
185 throw new ArgeoException("Versioning is not activated");
186
187 try {
188 Node fileNode = (Node) session().getItem(path);
189 VersionHistory history = session().getWorkspace()
190 .getVersionManager().getVersionHistory(fileNode.getPath());
191 int count = 0;
192 Version version = null;
193 for (VersionIterator it = history.getAllVersions(); it.hasNext();) {
194 version = (Version) it.next();
195 if (count == revision + 1) {
196 InputStream in = fromVersion(version);
197 if (log.isDebugEnabled())
198 log.debug("Retrieved " + path + " at revision "
199 + revision);
200 return in;
201 }
202 count++;
203 }
204 } catch (Exception e) {
205 throw new ArgeoException("Cannot retrieve version " + revision
206 + " of " + path, e);
207 }
208
209 throw new ArgeoException("Version " + revision
210 + " does not exist for node " + path);
211 }
212
213 protected InputStream fromVersion(Version version)
214 throws RepositoryException {
215 Node frozenNode = version.getNode("jcr:frozenNode");
216 InputStream in = frozenNode.getNode(Property.JCR_CONTENT)
217 .getProperty(Property.JCR_DATA).getBinary().getStream();
218 return in;
219 }
220
221 protected Session session() {
222 return session;
223 }
224
225 public void setVersioning(Boolean versioning) {
226 this.versioning = versioning;
227 }
228
229 public void setDefaultEncoding(String defaultEncoding) {
230 this.defaultEncoding = defaultEncoding;
231 }
232
233 protected String fill(Integer number) {
234 int size = 4;
235 String str = number.toString();
236 for (int i = str.length(); i < size; i++) {
237 str = "0" + str;
238 }
239 return str;
240 }
241
242 public void setSession(Session session) {
243 this.session = session;
244 }
245
246 }