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.ObjectData;
22  import org.apache.chemistry.opencmis.commons.data.ObjectList;
23  import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
24  import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
25  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
26  import org.apache.chemistry.opencmis.commons.impl.Constants;
27  import static org.apache.chemistry.opencmis.commons.impl.Converter.convert;
28  import org.apache.chemistry.opencmis.commons.impl.JaxBHelper;
29  import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
30  import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisObjectType;
31  import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisQueryType;
32  import org.apache.chemistry.opencmis.commons.server.CallContext;
33  import org.apache.chemistry.opencmis.commons.server.CmisService;
34  import org.apache.chemistry.opencmis.commons.spi.Holder;
35  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHANGES;
36  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_QUERY;
37  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.compileBaseUrl;
38  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.compileUrlBuilder;
39  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.writeContentChangesObjectEntry;
40  import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBigIntegerParameter;
41  import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBooleanParameter;
42  import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getEnumParameter;
43  import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
44  
45  import java.math.BigInteger;
46  
47  import java.util.GregorianCalendar;
48  
49  import javax.servlet.http.HttpServletRequest;
50  import javax.servlet.http.HttpServletResponse;
51  
52  import javax.xml.bind.JAXBElement;
53  import javax.xml.bind.Unmarshaller;
54  
55  
56  
57  
58  
59  public class DiscoveryService
60  {
61      private static final String METHOD_GET = "GET";
62      private static final String METHOD_POST = "POST";
63  
64      private DiscoveryService(  )
65      {
66      }
67  
68      
69  
70  
71      public static void query( CallContext context, CmisService service, String repositoryId,
72          HttpServletRequest request, HttpServletResponse response )
73          throws Exception
74      {
75          
76          String statement = null;
77          Boolean searchAllVersions = null;
78          Boolean includeAllowableActions = null;
79          IncludeRelationships includeRelationships = null;
80          String renditionFilter = null;
81          BigInteger maxItems = null;
82          BigInteger skipCount = null;
83  
84          int statusCode = 0;
85  
86          if ( METHOD_POST.equals( request.getMethod(  ) ) )
87          {
88              
89              Object queryRequest = null;
90  
91              try
92              {
93                  Unmarshaller u = JaxBHelper.createUnmarshaller(  );
94                  queryRequest = u.unmarshal( request.getInputStream(  ) );
95              }
96              catch ( Exception e )
97              {
98                  throw new CmisInvalidArgumentException( "Invalid query request: " + e, e );
99              }
100 
101             if ( !( queryRequest instanceof JAXBElement<?> ) )
102             {
103                 throw new CmisInvalidArgumentException( "Not a query document!" );
104             }
105 
106             if ( !( ( (JAXBElement<?>) queryRequest ).getValue(  ) instanceof CmisQueryType ) )
107             {
108                 throw new CmisInvalidArgumentException( "Not a query document!" );
109             }
110 
111             CmisQueryType queryType = (CmisQueryType) ( (JAXBElement<?>) queryRequest ).getValue(  );
112 
113             statement = queryType.getStatement(  );
114             searchAllVersions = queryType.isSearchAllVersions(  );
115             includeAllowableActions = queryType.isIncludeAllowableActions(  );
116             includeRelationships = convert( IncludeRelationships.class, queryType.getIncludeRelationships(  ) );
117             renditionFilter = queryType.getRenditionFilter(  );
118             maxItems = queryType.getMaxItems(  );
119             skipCount = queryType.getSkipCount(  );
120 
121             statusCode = HttpServletResponse.SC_CREATED;
122         }
123         else if ( METHOD_GET.equals( request.getMethod(  ) ) )
124         {
125             
126             statement = getStringParameter( request, Constants.PARAM_Q );
127             searchAllVersions = getBooleanParameter( request, Constants.PARAM_SEARCH_ALL_VERSIONS );
128             includeAllowableActions = getBooleanParameter( request, Constants.PARAM_ALLOWABLE_ACTIONS );
129             includeRelationships = getEnumParameter( request, Constants.PARAM_RELATIONSHIPS, IncludeRelationships.class );
130             renditionFilter = null;
131             maxItems = getBigIntegerParameter( request, Constants.PARAM_MAX_ITEMS );
132             skipCount = getBigIntegerParameter( request, Constants.PARAM_SKIP_COUNT );
133 
134             statusCode = HttpServletResponse.SC_OK;
135         }
136         else
137         {
138             throw new CmisRuntimeException( "Invalid HTTP method!" );
139         }
140 
141         
142         ObjectList results = service.query( repositoryId, statement, searchAllVersions, includeAllowableActions,
143                 includeRelationships, renditionFilter, maxItems, skipCount, null );
144 
145         if ( results == null )
146         {
147             throw new CmisRuntimeException( "Results are null!" );
148         }
149 
150         
151         UrlBuilder baseUrl = compileBaseUrl( request, repositoryId );
152 
153         UrlBuilder pagingUrl = compileUrlBuilder( baseUrl, RESOURCE_QUERY, null );
154         pagingUrl.addParameter( Constants.PARAM_Q, statement );
155         pagingUrl.addParameter( Constants.PARAM_SEARCH_ALL_VERSIONS, searchAllVersions );
156         pagingUrl.addParameter( Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions );
157         pagingUrl.addParameter( Constants.PARAM_RELATIONSHIPS, includeRelationships );
158 
159         UrlBuilder location = new UrlBuilder( pagingUrl );
160         location.addParameter( Constants.PARAM_MAX_ITEMS, maxItems );
161         location.addParameter( Constants.PARAM_SKIP_COUNT, skipCount );
162 
163         response.setStatus( statusCode );
164         response.setContentType( Constants.MEDIATYPE_FEED );
165 
166         
167         
168         
169         
170 
171         
172         response.setHeader( "Location", location.toString(  ) );
173 
174         
175         AtomFeed feed = new AtomFeed(  );
176         feed.startDocument( response.getOutputStream(  ) );
177         feed.startFeed( true );
178 
179         
180         GregorianCalendar now = new GregorianCalendar(  );
181         feed.writeFeedElements( "query", "", "Query", now, null, results.getNumItems(  ) );
182 
183         
184         feed.writeServiceLink( baseUrl.toString(  ), repositoryId );
185 
186         feed.writePagingLinks( pagingUrl, maxItems, skipCount, results.getNumItems(  ), results.hasMoreItems(  ),
187             AtomPubUtils.PAGE_SIZE );
188 
189         if ( results.getObjects(  ) != null )
190         {
191             AtomEntry entry = new AtomEntry( feed.getWriter(  ) );
192             int idCounter = 0;
193 
194             for ( ObjectData result : results.getObjects(  ) )
195             {
196                 if ( result == null )
197                 {
198                     continue;
199                 }
200 
201                 idCounter++;
202                 writeQueryResultEntry( entry, result, "id-" + idCounter, now );
203             }
204         }
205 
206         
207         feed.endFeed(  );
208         feed.endDocument(  );
209     }
210 
211     private static void writeQueryResultEntry( AtomEntry entry, ObjectData result, String id, GregorianCalendar now )
212         throws Exception
213     {
214         CmisObjectType resultJaxb = convert( result );
215 
216         if ( resultJaxb == null )
217         {
218             return;
219         }
220 
221         
222         entry.startEntry( false );
223 
224         
225         entry.writeAuthor( "" );
226         entry.writeId( entry.generateAtomId( id ) );
227         entry.writePublished( now );
228         entry.writeTitle( "Query Result " + id );
229         entry.writeUpdated( now );
230 
231         
232         JaxBHelper.marshal( JaxBHelper.CMIS_EXTRA_OBJECT_FACTORY.createObject( resultJaxb ), entry.getWriter(  ), true );
233 
234         
235         entry.endEntry(  );
236     }
237 
238     
239 
240 
241     public static void getContentChanges( CallContext context, CmisService service, String repositoryId,
242         HttpServletRequest request, HttpServletResponse response )
243         throws Exception
244     {
245         
246         String changeLogToken = getStringParameter( request, Constants.PARAM_CHANGE_LOG_TOKEN );
247         Boolean includeProperties = getBooleanParameter( request, Constants.PARAM_PROPERTIES );
248         String filter = getStringParameter( request, Constants.PARAM_FILTER );
249         Boolean includePolicyIds = getBooleanParameter( request, Constants.PARAM_POLICY_IDS );
250         Boolean includeAcl = getBooleanParameter( request, Constants.PARAM_ACL );
251         BigInteger maxItems = getBigIntegerParameter( request, Constants.PARAM_MAX_ITEMS );
252 
253         
254         Holder<String> changeLogTokenHolder = new Holder<String>( changeLogToken );
255         ObjectList changes = service.getContentChanges( repositoryId, changeLogTokenHolder, includeProperties, filter,
256                 includePolicyIds, includeAcl, maxItems, null );
257 
258         if ( changes == null )
259         {
260             throw new CmisRuntimeException( "Changes are null!" );
261         }
262 
263         
264         response.setStatus( HttpServletResponse.SC_OK );
265         response.setContentType( Constants.MEDIATYPE_FEED );
266 
267         
268         AtomFeed feed = new AtomFeed(  );
269         feed.startDocument( response.getOutputStream(  ) );
270         feed.startFeed( true );
271 
272         
273         GregorianCalendar now = new GregorianCalendar(  );
274         feed.writeFeedElements( "contentChanges", "", "Content Change", now, null, changes.getNumItems(  ) );
275 
276         
277         UrlBuilder baseUrl = compileBaseUrl( request, repositoryId );
278 
279         feed.writeServiceLink( baseUrl.toString(  ), repositoryId );
280 
281         if ( changeLogTokenHolder.getValue(  ) != null )
282         {
283             UrlBuilder nextLink = compileUrlBuilder( baseUrl, RESOURCE_CHANGES, null );
284             nextLink.addParameter( Constants.PARAM_CHANGE_LOG_TOKEN, changeLogTokenHolder.getValue(  ) );
285             nextLink.addParameter( Constants.PARAM_PROPERTIES, includeProperties );
286             nextLink.addParameter( Constants.PARAM_FILTER, filter );
287             nextLink.addParameter( Constants.PARAM_POLICY_IDS, includePolicyIds );
288             nextLink.addParameter( Constants.PARAM_ACL, includeAcl );
289             nextLink.addParameter( Constants.PARAM_MAX_ITEMS, maxItems );
290             feed.writeNextLink( nextLink.toString(  ) );
291         }
292 
293         
294         if ( changes.getObjects(  ) != null )
295         {
296             AtomEntry entry = new AtomEntry( feed.getWriter(  ) );
297 
298             for ( ObjectData object : changes.getObjects(  ) )
299             {
300                 if ( object == null )
301                 {
302                     continue;
303                 }
304 
305                 writeContentChangesObjectEntry( service, entry, object, null, repositoryId, null, null, baseUrl, false );
306             }
307         }
308 
309         
310         feed.endFeed(  );
311         feed.endDocument(  );
312     }
313 }