001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 * Thierry Delprat 019 */ 020package org.nuxeo.ecm.automation.jaxrs.io.documents; 021 022import static org.apache.commons.lang.StringUtils.isBlank; 023 024import java.io.IOException; 025import java.io.OutputStream; 026import java.lang.annotation.Annotation; 027import java.lang.reflect.Type; 028import java.util.HashMap; 029import java.util.List; 030import java.util.Map; 031 032import javax.servlet.ServletRequest; 033import javax.servlet.http.HttpServletRequest; 034import javax.ws.rs.Produces; 035import javax.ws.rs.WebApplicationException; 036import javax.ws.rs.core.Context; 037import javax.ws.rs.core.HttpHeaders; 038import javax.ws.rs.core.MediaType; 039import javax.ws.rs.core.MultivaluedMap; 040import javax.ws.rs.ext.Provider; 041 042import org.apache.commons.logging.Log; 043import org.apache.commons.logging.LogFactory; 044import org.codehaus.jackson.JsonEncoding; 045import org.codehaus.jackson.JsonFactory; 046import org.codehaus.jackson.JsonGenerator; 047import org.nuxeo.common.utils.StringUtils; 048import org.nuxeo.ecm.automation.core.util.PaginableDocumentModelList; 049import org.nuxeo.ecm.automation.jaxrs.io.EntityListWriter; 050import org.nuxeo.ecm.core.api.DocumentLocation; 051import org.nuxeo.ecm.core.api.DocumentModel; 052import org.nuxeo.ecm.core.api.DocumentModelList; 053import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl; 054import org.nuxeo.ecm.core.io.marshallers.json.document.DocumentModelListJsonWriter; 055import org.nuxeo.ecm.directory.api.DirectoryEntry; 056import org.nuxeo.ecm.platform.types.adapter.TypeInfo; 057import org.nuxeo.ecm.platform.url.DocumentViewImpl; 058import org.nuxeo.ecm.platform.url.api.DocumentView; 059import org.nuxeo.ecm.platform.url.api.DocumentViewCodecManager; 060import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper; 061import org.nuxeo.ecm.webengine.jaxrs.coreiodelegate.JsonCoreIODelegate; 062import org.nuxeo.runtime.api.Framework; 063 064/** 065 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 066 * @deprecated since 7.10 The Nuxeo JSON marshalling was migrated to nuxeo-core-io. This class is replaced by 067 * {@link DocumentModelListJsonWriter} which is registered by default and available to marshal 068 * {@link DirectoryEntry} from the Nuxeo Rest API thanks to the JAX-RS marshaller {@link JsonCoreIODelegate} 069 */ 070@Deprecated 071@Provider 072@Produces({ "application/json+nxentity", "application/json" }) 073public class JsonDocumentListWriter extends EntityListWriter<DocumentModel> { 074 075 private static final Log log = LogFactory.getLog(JsonDocumentListWriter.class); 076 077 @Context 078 JsonFactory factory; 079 080 @Context 081 protected HttpHeaders headers; 082 083 @Context 084 protected HttpServletRequest request; 085 086 @Override 087 protected String getEntityType() { 088 return "documents"; 089 } 090 091 @Override 092 protected void writeItem(JsonGenerator jg, DocumentModel item) throws IOException { 093 // do nothing, everything is done in #writeTo 094 } 095 096 @Override 097 public boolean isWriteable(Class<?> arg0, Type arg1, Annotation[] arg2, MediaType arg3) { 098 return DocumentModelList.class.isAssignableFrom(arg0); 099 } 100 101 @Override 102 public void writeTo(List<DocumentModel> docs, Class<?> type, Type genericType, Annotation[] annotations, 103 MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) 104 throws IOException, WebApplicationException { 105 try { 106 List<String> props = headers.getRequestHeader(JsonDocumentWriter.DOCUMENT_PROPERTIES_HEADER); 107 String[] schemas = null; 108 if (props != null && !props.isEmpty()) { 109 schemas = StringUtils.split(props.get(0), ',', true); 110 } 111 writeDocuments(entityStream, docs, schemas, headers); 112 } catch (IOException e) { 113 log.error("Failed to serialize document list", e); 114 throw new WebApplicationException(500); 115 } 116 } 117 118 public void writeDocuments(OutputStream out, List<DocumentModel> docs, String[] schemas) throws IOException { 119 writeDocuments(factory.createJsonGenerator(out, JsonEncoding.UTF8), docs, schemas, request); 120 } 121 122 /** 123 * @since 5.9.5 124 */ 125 public void writeDocuments(OutputStream out, List<DocumentModel> docs, String[] schemas, HttpHeaders headers) 126 throws IOException { 127 writeDocuments(factory.createJsonGenerator(out, JsonEncoding.UTF8), docs, schemas, headers, request); 128 } 129 130 public static void writeDocuments(JsonGenerator jg, List<DocumentModel> docs, String[] schemas, 131 ServletRequest request) throws IOException { 132 writeDocuments(jg, docs, schemas, null, request); 133 } 134 135 /** 136 * @since 5.9.5 137 */ 138 public static void writeDocuments(JsonGenerator jg, List<DocumentModel> docs, String[] schemas, 139 HttpHeaders headers, ServletRequest request) throws IOException { 140 jg.writeStartObject(); 141 jg.writeStringField("entity-type", "documents"); 142 143 if (docs instanceof PaginableDocumentModelList) { 144 PaginableDocumentModelList provider = (PaginableDocumentModelList) docs; 145 jg.writeBooleanField("isPaginable", true); 146 jg.writeNumberField("resultsCount", provider.getResultsCount()); 147 jg.writeNumberField("pageSize", provider.getPageSize()); 148 jg.writeNumberField("maxPageSize", provider.getMaxPageSize()); 149 jg.writeNumberField("currentPageSize", provider.getCurrentPageSize()); 150 jg.writeNumberField("currentPageIndex", provider.getCurrentPageIndex()); 151 jg.writeNumberField("numberOfPages", provider.getNumberOfPages()); 152 jg.writeBooleanField("isPreviousPageAvailable", provider.isPreviousPageAvailable()); 153 jg.writeBooleanField("isNextPageAvailable", provider.isNextPageAvailable()); 154 jg.writeBooleanField("isLastPageAvailable", provider.isLastPageAvailable()); 155 jg.writeBooleanField("isSortable", provider.isSortable()); 156 jg.writeBooleanField("hasError", provider.hasError()); 157 jg.writeStringField("errorMessage", provider.getErrorMessage()); 158 159 // compat fields 160 jg.writeNumberField("totalSize", provider.totalSize()); 161 jg.writeNumberField("pageIndex", provider.getCurrentPageIndex()); 162 jg.writeNumberField("pageCount", provider.getNumberOfPages()); 163 164 DocumentViewCodecManager documentViewCodecManager = Framework.getLocalService(DocumentViewCodecManager.class); 165 String codecName = null; 166 if (documentViewCodecManager == null) { 167 log.warn("Service 'DocumentViewCodecManager' not available : documentUrl won't be generated"); 168 } else { 169 String documentLinkBuilder = provider.getDocumentLinkBuilder(); 170 codecName = isBlank(documentLinkBuilder) ? documentViewCodecManager.getDefaultCodecName() 171 : documentLinkBuilder; 172 } 173 174 jg.writeArrayFieldStart("entries"); 175 for (DocumentModel doc : docs) { 176 DocumentLocation docLoc = new DocumentLocationImpl(doc); 177 Map<String, String> contextParameters = new HashMap<String, String>(); 178 if (documentViewCodecManager != null) { 179 DocumentView docView = new DocumentViewImpl(docLoc, doc.getAdapter(TypeInfo.class).getDefaultView()); 180 String documentURL = VirtualHostHelper.getContextPathProperty() + "/" 181 + documentViewCodecManager.getUrlFromDocumentView(codecName, docView, false, null); 182 contextParameters.put("documentURL", documentURL); 183 } 184 JsonDocumentWriter.writeDocument(jg, doc, schemas, contextParameters, headers, request); 185 } 186 jg.writeEndArray(); 187 if (provider.hasAggregateSupport() && provider.getAggregates() != null 188 && !provider.getAggregates().isEmpty()) { 189 jg.writeObjectField("aggregations", provider.getAggregates()); 190 } 191 } else { 192 jg.writeArrayFieldStart("entries"); 193 for (DocumentModel doc : docs) { 194 JsonDocumentWriter.writeDocument(jg, doc, schemas, new HashMap<String, String>(), headers, request); 195 } 196 jg.writeEndArray(); 197 } 198 199 jg.writeEndObject(); 200 jg.flush(); 201 } 202 203}