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