1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.server.impl.atompub;
20
21 import org.apache.chemistry.opencmis.commons.data.RepositoryCapabilities;
22 import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
23 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
24 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
25 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList;
26 import org.apache.chemistry.opencmis.commons.enums.CapabilityChanges;
27 import org.apache.chemistry.opencmis.commons.enums.CapabilityQuery;
28 import org.apache.chemistry.opencmis.commons.impl.Constants;
29 import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
30 import org.apache.chemistry.opencmis.commons.server.CallContext;
31 import org.apache.chemistry.opencmis.commons.server.CmisService;
32 import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
33 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.PAGE_SIZE;
34 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHANGES;
35 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHECKEDOUT;
36 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHILDREN;
37 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_DESCENDANTS;
38 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_FOLDERTREE;
39 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_OBJECTBYID;
40 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_OBJECTBYPATH;
41 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_QUERY;
42 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_TYPE;
43 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_TYPES;
44 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_TYPESDESC;
45 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_UNFILED;
46 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.TYPE_AUTHOR;
47 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.compileBaseUrl;
48 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.compileUrl;
49 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.compileUrlBuilder;
50 import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.writeTypeEntry;
51 import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBigIntegerParameter;
52 import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBooleanParameter;
53 import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
54
55 import java.math.BigInteger;
56
57 import java.util.Collections;
58 import java.util.GregorianCalendar;
59 import java.util.List;
60
61 import javax.servlet.http.HttpServletRequest;
62 import javax.servlet.http.HttpServletResponse;
63
64
65
66
67
68 public final class RepositoryService
69 {
70
71
72
73 private RepositoryService( )
74 {
75 }
76
77
78
79
80 public static void getRepositories( CallContext context, CmisService service, HttpServletRequest request,
81 HttpServletResponse response ) throws Exception
82 {
83
84 String repositoryId = getStringParameter( request, Constants.PARAM_REPOSITORY_ID );
85
86
87 List<RepositoryInfo> infoDataList = null;
88
89 if ( repositoryId == null )
90 {
91 infoDataList = service.getRepositoryInfos( null );
92 }
93 else
94 {
95 infoDataList = Collections.singletonList( service.getRepositoryInfo( repositoryId, null ) );
96
97 if ( context instanceof CallContextImpl )
98 {
99 ( (CallContextImpl) context ).put( CallContext.REPOSITORY_ID, repositoryId );
100 }
101 }
102
103
104 response.setStatus( HttpServletResponse.SC_OK );
105 response.setContentType( Constants.MEDIATYPE_SERVICE );
106
107
108 ServiceDocument serviceDoc = new ServiceDocument( );
109
110 serviceDoc.startDocument( response.getOutputStream( ) );
111 serviceDoc.startServiceDocument( );
112
113 if ( infoDataList != null )
114 {
115 for ( RepositoryInfo infoData : infoDataList )
116 {
117 if ( infoData == null )
118 {
119 continue;
120 }
121
122 String repId = infoData.getId( );
123 UrlBuilder baseUrl = compileBaseUrl( request, repId );
124
125 boolean supportsQuery = false;
126 boolean supportsUnFiling = false;
127 boolean supportsMultifiling = false;
128 boolean supportsFolderTree = false;
129 boolean supportsRootDescendants = false;
130 boolean supportsChanges = false;
131
132 if ( infoData.getCapabilities( ) != null )
133 {
134 RepositoryCapabilities cap = infoData.getCapabilities( );
135
136 if ( cap.getQueryCapability( ) != null )
137 {
138 supportsQuery = ( cap.getQueryCapability( ) != CapabilityQuery.NONE );
139 }
140
141 if ( cap.isUnfilingSupported( ) != null )
142 {
143 supportsUnFiling = cap.isUnfilingSupported( );
144 }
145
146 if ( cap.isMultifilingSupported( ) != null )
147 {
148 supportsMultifiling = cap.isMultifilingSupported( );
149 }
150
151 if ( cap.isGetFolderTreeSupported( ) != null )
152 {
153 supportsFolderTree = cap.isGetFolderTreeSupported( );
154 }
155
156 if ( cap.isGetDescendantsSupported( ) != null )
157 {
158 supportsRootDescendants = cap.isGetDescendantsSupported( );
159 }
160
161 if ( cap.getChangesCapability( ) != null )
162 {
163 supportsChanges = ( cap.getChangesCapability( ) != CapabilityChanges.NONE );
164 }
165 }
166
167 serviceDoc.startWorkspace( infoData.getId( ) );
168
169
170
171
172 serviceDoc.writeCollection( compileUrl( baseUrl, RESOURCE_CHILDREN, infoData.getRootFolderId( ) ),
173 Constants.COLLECTION_ROOT, "Root Collection", Constants.MEDIATYPE_ENTRY,
174 Constants.MEDIATYPE_CMISATOM );
175
176
177 serviceDoc.writeCollection( compileUrl( baseUrl, RESOURCE_TYPES, null ), Constants.COLLECTION_TYPES,
178 "Types Collection", "" );
179
180
181 if ( supportsQuery )
182 {
183 serviceDoc.writeCollection( compileUrl( baseUrl, RESOURCE_QUERY, null ),
184 Constants.COLLECTION_QUERY, "Query Collection", Constants.MEDIATYPE_QUERY );
185 }
186
187
188 serviceDoc.writeCollection( compileUrl( baseUrl, RESOURCE_CHECKEDOUT, null ),
189 Constants.COLLECTION_CHECKEDOUT, "Checked Out Collection", Constants.MEDIATYPE_CMISATOM );
190
191
192 if ( supportsUnFiling || supportsMultifiling )
193 {
194 serviceDoc.writeCollection( compileUrl( baseUrl, RESOURCE_UNFILED, null ),
195 Constants.COLLECTION_UNFILED, "Unfiled Collection", Constants.MEDIATYPE_CMISATOM );
196 }
197
198
199 serviceDoc.writeRepositoryInfo( infoData );
200
201
202
203
204 serviceDoc.writeLink( Constants.REP_REL_TYPEDESC, compileUrl( baseUrl, RESOURCE_TYPESDESC, null ),
205 Constants.MEDIATYPE_FEED, null );
206
207
208 if ( supportsFolderTree )
209 {
210 serviceDoc.writeLink( Constants.REP_REL_FOLDERTREE,
211 compileUrl( baseUrl, RESOURCE_FOLDERTREE, infoData.getRootFolderId( ) ),
212 Constants.MEDIATYPE_DESCENDANTS, null );
213 }
214
215
216 if ( supportsRootDescendants )
217 {
218 serviceDoc.writeLink( Constants.REP_REL_ROOTDESC,
219 compileUrl( baseUrl, RESOURCE_DESCENDANTS, infoData.getRootFolderId( ) ),
220 Constants.MEDIATYPE_DESCENDANTS, infoData.getRootFolderId( ) );
221 }
222
223
224 if ( supportsChanges )
225 {
226 serviceDoc.writeLink( Constants.REP_REL_CHANGES, compileUrl( baseUrl, RESOURCE_CHANGES, null ),
227 Constants.MEDIATYPE_FEED, null );
228 }
229
230
231
232
233 String url = compileUrl( baseUrl, RESOURCE_OBJECTBYID, null ) +
234 "?id={id}&filter={filter}&includeAllowableActions={includeAllowableActions}&includeACL={includeACL}&includePolicyIds={includePolicyIds}&includeRelationships={includeRelationships}&renditionFilter={renditionFilter}";
235 serviceDoc.writeUriTemplate( url, Constants.TEMPLATE_OBJECT_BY_ID, Constants.MEDIATYPE_ENTRY );
236
237
238 url = compileUrl( baseUrl, RESOURCE_OBJECTBYPATH, null ) +
239 "?path={path}&filter={filter}&includeAllowableActions={includeAllowableActions}&includeACL={includeACL}&includePolicyIds={includePolicyIds}&includeRelationships={includeRelationships}&renditionFilter={renditionFilter}";
240 serviceDoc.writeUriTemplate( url, Constants.TEMPLATE_OBJECT_BY_PATH, Constants.MEDIATYPE_ENTRY );
241
242
243 url = compileUrl( baseUrl, RESOURCE_TYPE, null ) + "?id={id}";
244 serviceDoc.writeUriTemplate( url, Constants.TEMPLATE_TYPE_BY_ID, Constants.MEDIATYPE_ENTRY );
245
246
247 if ( supportsQuery )
248 {
249 url = compileUrl( baseUrl, RESOURCE_QUERY, null ) +
250 "?q={q}&searchAllVersions={searchAllVersions}&includeAllowableActions={includeAllowableActions}&includeRelationships={includeRelationships}&maxItems={maxItems}&skipCount={skipCount}";
251 serviceDoc.writeUriTemplate( url, Constants.TEMPLATE_QUERY, Constants.MEDIATYPE_FEED );
252 }
253
254 serviceDoc.endWorkspace( );
255 }
256 }
257
258 serviceDoc.endServiceDocument( );
259 serviceDoc.endDocument( );
260 }
261
262
263
264
265 public static void getTypeChildren( CallContext context, CmisService service, String repositoryId,
266 HttpServletRequest request, HttpServletResponse response )
267 throws Exception
268 {
269
270 String typeId = getStringParameter( request, Constants.PARAM_TYPE_ID );
271 boolean includePropertyDefinitions = getBooleanParameter( request, Constants.PARAM_PROPERTY_DEFINITIONS, false );
272 BigInteger maxItems = getBigIntegerParameter( request, Constants.PARAM_MAX_ITEMS );
273 BigInteger skipCount = getBigIntegerParameter( request, Constants.PARAM_SKIP_COUNT );
274
275
276 TypeDefinitionList typeList = service.getTypeChildren( repositoryId, typeId, includePropertyDefinitions,
277 maxItems, skipCount, null );
278
279 BigInteger numItems = ( ( typeList == null ) ? null : typeList.getNumItems( ) );
280 Boolean hasMoreItems = ( ( typeList == null ) ? null : typeList.hasMoreItems( ) );
281
282 String parentTypeId = null;
283 String typeName = "Type Children";
284
285
286
287 if ( typeId != null )
288 {
289 TypeDefinition typeDefinition = service.getTypeDefinition( repositoryId, typeId, null );
290
291 parentTypeId = ( ( typeDefinition == null ) ? null : typeDefinition.getParentTypeId( ) );
292 typeName = ( ( typeDefinition == null ) ? typeId : typeDefinition.getDisplayName( ) );
293 }
294
295
296 response.setStatus( HttpServletResponse.SC_OK );
297 response.setContentType( Constants.MEDIATYPE_FEED );
298
299 AtomFeed feed = new AtomFeed( );
300 feed.startDocument( response.getOutputStream( ) );
301 feed.startFeed( true );
302
303
304 feed.writeFeedElements( typeId, TYPE_AUTHOR, typeName, new GregorianCalendar( ), null, numItems );
305
306
307 UrlBuilder baseUrl = compileBaseUrl( request, repositoryId );
308
309 feed.writeServiceLink( baseUrl.toString( ), repositoryId );
310
311 UrlBuilder selfLink = compileUrlBuilder( baseUrl, RESOURCE_TYPES, null );
312 selfLink.addParameter( Constants.PARAM_TYPE_ID, typeId );
313 selfLink.addParameter( Constants.PARAM_PROPERTY_DEFINITIONS, includePropertyDefinitions );
314 feed.writeSelfLink( selfLink.toString( ), typeId );
315
316 feed.writeViaLink( compileUrl( baseUrl, RESOURCE_TYPE, typeId ) );
317
318 UrlBuilder downLink = compileUrlBuilder( baseUrl, RESOURCE_TYPESDESC, null );
319 downLink.addParameter( Constants.PARAM_TYPE_ID, typeId );
320 feed.writeDownLink( downLink.toString( ), Constants.MEDIATYPE_DESCENDANTS );
321
322 if ( parentTypeId != null )
323 {
324 feed.writeUpLink( compileUrl( baseUrl, RESOURCE_TYPE, parentTypeId ), Constants.MEDIATYPE_ENTRY );
325 }
326
327
328 UrlBuilder pagingUrl = compileUrlBuilder( baseUrl, RESOURCE_TYPES, null );
329 pagingUrl.addParameter( Constants.PARAM_TYPE_ID, typeId );
330 pagingUrl.addParameter( Constants.PARAM_PROPERTY_DEFINITIONS, includePropertyDefinitions );
331 feed.writePagingLinks( pagingUrl, maxItems, skipCount, numItems, hasMoreItems, PAGE_SIZE );
332
333
334 UrlBuilder collectionUrl = compileUrlBuilder( baseUrl, RESOURCE_TYPES, null );
335 collectionUrl.addParameter( Constants.PARAM_TYPE_ID, typeId );
336 feed.writeCollection( collectionUrl.toString( ), null, "Types Collection", "" );
337
338
339 if ( ( typeList != null ) && ( typeList.getList( ) != null ) )
340 {
341 AtomEntry entry = new AtomEntry( feed.getWriter( ) );
342
343 for ( TypeDefinition type : typeList.getList( ) )
344 {
345 writeTypeEntry( entry, type, null, repositoryId, baseUrl, false );
346 }
347 }
348
349
350 feed.endFeed( );
351 feed.endDocument( );
352 }
353
354
355
356
357 public static void getTypeDescendants( CallContext context, CmisService service, String repositoryId,
358 HttpServletRequest request, HttpServletResponse response )
359 throws Exception
360 {
361
362 String typeId = getStringParameter( request, Constants.PARAM_TYPE_ID );
363 BigInteger depth = getBigIntegerParameter( request, Constants.PARAM_DEPTH );
364 boolean includePropertyDefinitions = getBooleanParameter( request, Constants.PARAM_PROPERTY_DEFINITIONS, false );
365
366
367 List<TypeDefinitionContainer> typeTree = service.getTypeDescendants( repositoryId, typeId, depth,
368 includePropertyDefinitions, null );
369
370 String parentTypeId = null;
371 String typeName = "Type Children";
372
373
374
375 if ( typeId != null )
376 {
377 TypeDefinition typeDefinition = service.getTypeDefinition( repositoryId, typeId, null );
378
379 parentTypeId = ( ( typeDefinition == null ) ? null : typeDefinition.getParentTypeId( ) );
380 typeName = ( ( typeDefinition == null ) ? typeId : typeDefinition.getDisplayName( ) );
381 }
382
383
384 response.setStatus( HttpServletResponse.SC_OK );
385 response.setContentType( Constants.MEDIATYPE_FEED );
386
387 AtomFeed feed = new AtomFeed( );
388 feed.startDocument( response.getOutputStream( ) );
389 feed.startFeed( true );
390
391
392 feed.writeFeedElements( typeId, TYPE_AUTHOR, typeName, new GregorianCalendar( ), null, null );
393
394
395 UrlBuilder baseUrl = compileBaseUrl( request, repositoryId );
396
397 feed.writeServiceLink( baseUrl.toString( ), repositoryId );
398
399 UrlBuilder selfLink = compileUrlBuilder( baseUrl, RESOURCE_TYPESDESC, null );
400 selfLink.addParameter( Constants.PARAM_TYPE_ID, typeId );
401 selfLink.addParameter( Constants.PARAM_DEPTH, depth );
402 selfLink.addParameter( Constants.PARAM_PROPERTY_DEFINITIONS, includePropertyDefinitions );
403 feed.writeSelfLink( selfLink.toString( ), typeId );
404
405 feed.writeViaLink( compileUrl( baseUrl, RESOURCE_TYPE, typeId ) );
406
407 UrlBuilder downLink = compileUrlBuilder( baseUrl, RESOURCE_TYPES, null );
408 downLink.addParameter( Constants.PARAM_TYPE_ID, typeId );
409 feed.writeDownLink( downLink.toString( ), Constants.MEDIATYPE_FEED );
410
411 if ( parentTypeId != null )
412 {
413 feed.writeUpLink( compileUrl( baseUrl, RESOURCE_TYPE, parentTypeId ), Constants.MEDIATYPE_ENTRY );
414 }
415
416
417 if ( typeTree != null )
418 {
419 AtomEntry entry = new AtomEntry( feed.getWriter( ) );
420
421 for ( TypeDefinitionContainer container : typeTree )
422 {
423 if ( ( container != null ) && ( container.getTypeDefinition( ) != null ) )
424 {
425 writeTypeEntry( entry, container.getTypeDefinition( ), container.getChildren( ), repositoryId,
426 baseUrl, false );
427 }
428 }
429 }
430
431
432 feed.endFeed( );
433 feed.endDocument( );
434 }
435
436
437
438
439 public static void getTypeDefinition( CallContext context, CmisService service, String repositoryId,
440 HttpServletRequest request, HttpServletResponse response )
441 throws Exception
442 {
443
444 String typeId = getStringParameter( request, Constants.PARAM_ID );
445
446
447 TypeDefinition type = service.getTypeDefinition( repositoryId, typeId, null );
448
449
450 response.setStatus( HttpServletResponse.SC_OK );
451 response.setContentType( Constants.MEDIATYPE_ENTRY );
452
453 AtomEntry entry = new AtomEntry( );
454 entry.startDocument( response.getOutputStream( ) );
455 writeTypeEntry( entry, type, null, repositoryId, compileBaseUrl( request, repositoryId ), true );
456 entry.endDocument( );
457 }
458 }