1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.client.bindings.spi.atompub;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.math.BigInteger;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.xml.stream.XMLStreamException;
30
31 import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
32 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomElement;
33 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomEntry;
34 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomFeed;
35 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomLink;
36 import org.apache.chemistry.opencmis.client.bindings.spi.http.Output;
37 import org.apache.chemistry.opencmis.client.bindings.spi.http.Response;
38 import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
39 import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
40 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
41 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
42 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList;
43 import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException;
44 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
45 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
46 import org.apache.chemistry.opencmis.commons.impl.Constants;
47 import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
48 import org.apache.chemistry.opencmis.commons.impl.dataobjects.TypeDefinitionContainerImpl;
49 import org.apache.chemistry.opencmis.commons.impl.dataobjects.TypeDefinitionListImpl;
50 import org.apache.chemistry.opencmis.commons.spi.RepositoryService;
51
52
53
54
55 public class RepositoryServiceImpl extends AbstractAtomPubService implements RepositoryService {
56
57
58
59
60 public RepositoryServiceImpl(BindingSession session) {
61 setSession(session);
62 }
63
64 @Override
65 public List<RepositoryInfo> getRepositoryInfos(ExtensionsData extension) {
66 return getRepositoriesInternal(null);
67 }
68
69 @Override
70 public RepositoryInfo getRepositoryInfo(String repositoryId, ExtensionsData extension) {
71 List<RepositoryInfo> repositoryInfos = getRepositoriesInternal(repositoryId);
72
73 if (repositoryInfos.isEmpty()) {
74 throw new CmisObjectNotFoundException("Repository '" + repositoryId + "' not found!");
75 }
76
77
78 for (RepositoryInfo info : repositoryInfos) {
79 if (info.getId() == null) {
80 continue;
81 }
82
83 if (info.getId().equals(repositoryId)) {
84 return info;
85 }
86 }
87
88 throw new CmisObjectNotFoundException("Repository '" + repositoryId + "' not found!");
89 }
90
91 @Override
92 public TypeDefinition getTypeDefinition(String repositoryId, String typeId, ExtensionsData extension) {
93 return getTypeDefinitionInternal(repositoryId, typeId);
94 }
95
96 @Override
97 public TypeDefinitionList getTypeChildren(String repositoryId, String typeId, Boolean includePropertyDefinitions,
98 BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
99 TypeDefinitionListImpl result = new TypeDefinitionListImpl();
100
101
102 String link = null;
103 if (typeId == null) {
104 link = loadCollection(repositoryId, Constants.COLLECTION_TYPES);
105 } else {
106 link = loadTypeLink(repositoryId, typeId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
107 }
108
109 if (link == null) {
110 throw new CmisObjectNotFoundException("Unknown repository or type!");
111 }
112
113 UrlBuilder url = new UrlBuilder(link);
114 url.addParameter(Constants.PARAM_PROPERTY_DEFINITIONS, includePropertyDefinitions);
115 url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
116 url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
117
118
119 Response resp = read(url);
120 AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
121
122
123 for (AtomElement element : feed.getElements()) {
124 if (element.getObject() instanceof AtomLink) {
125 if (isNextLink(element)) {
126 result.setHasMoreItems(Boolean.TRUE);
127 }
128 } else if (isInt(NAME_NUM_ITEMS, element)) {
129 result.setNumItems((BigInteger) element.getObject());
130 }
131 }
132
133 result.setList(new ArrayList<TypeDefinition>(feed.getEntries().size()));
134
135
136 if (!feed.getEntries().isEmpty()) {
137 for (AtomEntry entry : feed.getEntries()) {
138 TypeDefinition child = null;
139
140 lockTypeLinks();
141 try {
142
143 for (AtomElement element : entry.getElements()) {
144 if (element.getObject() instanceof AtomLink) {
145 addTypeLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
146 } else if (element.getObject() instanceof TypeDefinition) {
147 child = (TypeDefinition) element.getObject();
148 }
149 }
150 } finally {
151 unlockTypeLinks();
152 }
153
154 if (child != null) {
155 result.getList().add(child);
156 }
157 }
158 }
159
160 return result;
161 }
162
163 @Override
164 public List<TypeDefinitionContainer> getTypeDescendants(String repositoryId, String typeId, BigInteger depth,
165 Boolean includePropertyDefinitions, ExtensionsData extension) {
166 List<TypeDefinitionContainer> result = new ArrayList<TypeDefinitionContainer>();
167
168
169 String link = null;
170 if (typeId == null) {
171 link = loadRepositoryLink(repositoryId, Constants.REP_REL_TYPEDESC);
172 } else {
173 link = loadTypeLink(repositoryId, typeId, Constants.REL_DOWN, Constants.MEDIATYPE_DESCENDANTS);
174 }
175
176 if (link == null) {
177 throw new CmisObjectNotFoundException("Unknown repository or type!");
178 }
179
180 UrlBuilder url = new UrlBuilder(link);
181 url.addParameter(Constants.PARAM_DEPTH, depth);
182 url.addParameter(Constants.PARAM_PROPERTY_DEFINITIONS, includePropertyDefinitions);
183
184
185 Response resp = read(url);
186 AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
187
188
189 addTypeDescendantsLevel(repositoryId, feed, result);
190
191 return result;
192 }
193
194
195
196
197 private void addTypeDescendantsLevel(String repositoryId, AtomFeed feed, List<TypeDefinitionContainer> containerList) {
198 if (feed == null || feed.getEntries().isEmpty()) {
199 return;
200 }
201
202
203 for (AtomEntry entry : feed.getEntries()) {
204 TypeDefinitionContainerImpl childContainer = null;
205 List<TypeDefinitionContainer> childContainerList = new ArrayList<TypeDefinitionContainer>();
206
207
208 lockTypeLinks();
209 try {
210 for (AtomElement element : entry.getElements()) {
211 if (element.getObject() instanceof AtomLink) {
212 addTypeLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
213 } else if (element.getObject() instanceof TypeDefinition) {
214 childContainer = new TypeDefinitionContainerImpl((TypeDefinition) element.getObject());
215 } else if (element.getObject() instanceof AtomFeed) {
216 addTypeDescendantsLevel(repositoryId, (AtomFeed) element.getObject(), childContainerList);
217 }
218 }
219 } finally {
220 unlockTypeLinks();
221 }
222
223 if (childContainer != null) {
224 childContainer.setChildren(childContainerList);
225 containerList.add(childContainer);
226 }
227 }
228 }
229
230 @Override
231 public TypeDefinition createType(String repositoryId, TypeDefinition type, ExtensionsData extension) {
232 if (type == null) {
233 throw new CmisInvalidArgumentException("Type definition must be set!");
234 }
235
236 String parentId = type.getParentTypeId();
237 if (parentId == null) {
238 throw new CmisInvalidArgumentException("Type definition has no parent type ID!");
239 }
240
241
242 String link = loadTypeLink(repositoryId, parentId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
243
244 if (link == null) {
245 throw new CmisObjectNotFoundException("Unknown repository or parent type!");
246 }
247
248
249 final AtomEntryWriter entryWriter = new AtomEntryWriter(type, getCmisVersion(repositoryId));
250
251
252 Response resp = post(new UrlBuilder(link), Constants.MEDIATYPE_ENTRY, new Output() {
253 @Override
254 public void write(OutputStream out) throws XMLStreamException, IOException {
255 entryWriter.write(out);
256 }
257 });
258
259
260 AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
261
262
263 if (entry.getId() == null) {
264 throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
265 }
266
267 lockTypeLinks();
268 TypeDefinition result = null;
269 try {
270
271 removeTypeLinks(repositoryId, entry.getId());
272
273
274 for (AtomElement element : entry.getElements()) {
275 if (element.getObject() instanceof AtomLink) {
276 addTypeLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
277 } else if (element.getObject() instanceof TypeDefinition) {
278 result = (TypeDefinition) element.getObject();
279 }
280 }
281 } finally {
282 unlockTypeLinks();
283 }
284
285 return result;
286 }
287
288 @Override
289 public TypeDefinition updateType(String repositoryId, TypeDefinition type, ExtensionsData extension) {
290 if (type == null) {
291 throw new CmisInvalidArgumentException("Type definition must be set!");
292 }
293
294 String typeId = type.getId();
295 if (typeId == null) {
296 throw new CmisInvalidArgumentException("Type definition has no type ID!");
297 }
298
299
300 Map<String, Object> parameters = new HashMap<String, Object>();
301 parameters.put(Constants.PARAM_ID, typeId);
302
303 String link = loadTemplateLink(repositoryId, Constants.TEMPLATE_TYPE_BY_ID, parameters);
304 if (link == null) {
305 throw new CmisObjectNotFoundException("Unknown repository or type!");
306 }
307
308
309 final AtomEntryWriter entryWriter = new AtomEntryWriter(type, getCmisVersion(repositoryId));
310
311
312 Response resp = put(new UrlBuilder(link), Constants.MEDIATYPE_ENTRY, new Output() {
313 @Override
314 public void write(OutputStream out) throws XMLStreamException, IOException {
315 entryWriter.write(out);
316 }
317 });
318
319
320 AtomEntry entry = parse(resp.getStream(), AtomEntry.class);
321
322
323 if (entry.getId() == null) {
324 throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
325 }
326
327 lockTypeLinks();
328 TypeDefinition result = null;
329 try {
330
331 removeTypeLinks(repositoryId, entry.getId());
332
333
334 for (AtomElement element : entry.getElements()) {
335 if (element.getObject() instanceof AtomLink) {
336 addTypeLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
337 } else if (element.getObject() instanceof TypeDefinition) {
338 result = (TypeDefinition) element.getObject();
339 }
340 }
341 } finally {
342 unlockTypeLinks();
343 }
344
345 return result;
346 }
347
348 @Override
349 public void deleteType(String repositoryId, String typeId, ExtensionsData extension) {
350 Map<String, Object> parameters = new HashMap<String, Object>();
351 parameters.put(Constants.PARAM_ID, typeId);
352
353 String link = loadTemplateLink(repositoryId, Constants.TEMPLATE_TYPE_BY_ID, parameters);
354 if (link == null) {
355 throw new CmisObjectNotFoundException("Unknown repository!");
356 }
357
358 delete(new UrlBuilder(link));
359 }
360 }