001/* 002 * (C) Copyright 2006-2009 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo 016 */ 017 018package org.nuxeo.ecm.platform.publisher.remoting.marshaling; 019 020import org.dom4j.Document; 021import org.dom4j.DocumentException; 022import org.dom4j.DocumentFactory; 023import org.dom4j.DocumentHelper; 024import org.dom4j.QName; 025import org.nuxeo.ecm.core.api.CoreSession; 026import org.nuxeo.ecm.core.api.DocumentLocation; 027import org.nuxeo.ecm.core.api.DocumentModel; 028import org.nuxeo.ecm.core.api.NuxeoException; 029import org.nuxeo.ecm.platform.publisher.api.PublicationNode; 030import org.nuxeo.ecm.platform.publisher.api.PublishedDocument; 031import org.nuxeo.ecm.platform.publisher.remoting.marshaling.interfaces.DocumentLocationMarshaler; 032import org.nuxeo.ecm.platform.publisher.remoting.marshaling.interfaces.DocumentModelMarshaler; 033import org.nuxeo.ecm.platform.publisher.remoting.marshaling.interfaces.PublicationNodeMarshaler; 034import org.nuxeo.ecm.platform.publisher.remoting.marshaling.interfaces.PublishedDocumentMarshaler; 035import org.nuxeo.ecm.platform.publisher.remoting.marshaling.interfaces.RemotePublisherMarshaler; 036 037import java.util.ArrayList; 038import java.util.HashMap; 039import java.util.Iterator; 040import java.util.List; 041import java.util.Map; 042 043/** 044 * Default marshaler for RPC calls between 2 servers 045 * 046 * @author tiry 047 */ 048public class DefaultMarshaler extends AbstractDefaultXMLMarshaler implements RemotePublisherMarshaler { 049 050 private static final String PARAM_PATTERN = "$PARAM"; 051 052 private static final String RESULT_PATTERN = "$RESULT$"; 053 054 protected PublicationNodeMarshaler nodeMarshaler; 055 056 protected PublishedDocumentMarshaler publishedDocumentMarshaler; 057 058 protected DocumentModelMarshaler documentModelMarshaler; 059 060 protected DocumentLocationMarshaler docLocMarshaler; 061 062 protected Map<String, String> params = new HashMap<String, String>(); 063 064 protected static QName rootParametersTag = DocumentFactory.getInstance().createQName("parameters", 065 publisherSerializerNSPrefix, publisherSerializerNS); 066 067 protected static QName parameterTag = DocumentFactory.getInstance().createQName("parameter", 068 publisherSerializerNSPrefix, publisherSerializerNS); 069 070 protected static QName rootResultTag = DocumentFactory.getInstance().createQName("result", 071 publisherSerializerNSPrefix, publisherSerializerNS); 072 073 protected CoreSession session; 074 075 public DefaultMarshaler() { 076 this(null); 077 } 078 079 public DefaultMarshaler(CoreSession session) { 080 this.nodeMarshaler = new DefaultPublicationNodeMarshaler(); 081 this.publishedDocumentMarshaler = new DefaultPublishedDocumentMarshaler(); 082 this.documentModelMarshaler = new CoreIODocumentModelMarshaler(); 083 this.docLocMarshaler = new DefaultDocumentLocationMarshaler(); 084 this.session = session; 085 } 086 087 public String marshallParameters(List<Object> params) { 088 089 if (params == null) { 090 return "null"; 091 } 092 String env = buildParameterEnvelope(params.size()); 093 int idx = 1; 094 for (Object param : params) { 095 String strParam = marshalSingleObject(param); 096 env = env.replace(PARAM_PATTERN + idx + "$", strParam); 097 idx += 1; 098 } 099 return env; 100 } 101 102 public String marshallResult(Object result) { 103 String res = buildResultEnvelope(); 104 String strResult = marshalSingleObject(result); 105 res = res.replace(RESULT_PATTERN, strResult); 106 return res; 107 } 108 109 public List<Object> unMarshallParameters(String data) { 110 return unMarshallParameters(data, session); 111 } 112 113 protected List<Object> unMarshallParameters(String data, CoreSession session) { 114 115 List<Object> params = new ArrayList<Object>(); 116 117 Document document; 118 try { 119 document = DocumentHelper.parseText(data); 120 org.dom4j.Element rootElem = document.getRootElement(); 121 for (Iterator i = rootElem.elementIterator(parameterTag); i.hasNext();) { 122 org.dom4j.Element param = (org.dom4j.Element) i.next(); 123 if (param.elements().size() > 0) { 124 String xmlParam = ((org.dom4j.Element) param.elements().get(0)).asXML(); 125 params.add(unMarshalSingleObject(xmlParam, session)); 126 } else { 127 String value = param.getText(); 128 if ("null".equals(value)) { 129 value = null; 130 } 131 params.add(value); 132 } 133 } 134 } catch (DocumentException e) { 135 throw new NuxeoException("Error during unmarshaling of parameters", e); 136 } 137 return params; 138 } 139 140 public Object unMarshallResult(String data) { 141 return unMarshallResult(data, session); 142 } 143 144 protected Object unMarshallResult(String data, CoreSession coreSession) { 145 Document document; 146 try { 147 document = DocumentHelper.parseText(data); 148 org.dom4j.Element rootElem = document.getRootElement(); 149 150 if (rootElem.elements().size() == 0) { 151 return rootElem.getText(); 152 } else { 153 return unMarshalSingleObject(((org.dom4j.Element) rootElem.elements().get(0)).asXML(), coreSession); 154 } 155 } catch (DocumentException e) { 156 throw new NuxeoException("Error during unmarshaling Result", e); 157 } 158 } 159 160 protected String buildParameterEnvelope(int nbParams) { 161 162 org.dom4j.Element rootElem = DocumentFactory.getInstance().createElement(rootParametersTag); 163 rootElem.addNamespace(publisherSerializerNSPrefix, publisherSerializerNS); 164 org.dom4j.Document rootDoc = DocumentFactory.getInstance().createDocument(rootElem); 165 166 for (int i = 1; i <= nbParams; i++) { 167 org.dom4j.Element pathElem = rootElem.addElement(parameterTag); 168 pathElem.setText(PARAM_PATTERN + i + "$"); 169 } 170 return rootDoc.asXML(); 171 } 172 173 protected String buildResultEnvelope() { 174 175 org.dom4j.Element rootElem = DocumentFactory.getInstance().createElement(rootResultTag); 176 rootElem.addNamespace(publisherSerializerNSPrefix, publisherSerializerNS); 177 org.dom4j.Document rootDoc = DocumentFactory.getInstance().createDocument(rootElem); 178 rootElem.setText(RESULT_PATTERN); 179 return rootDoc.asXML(); 180 } 181 182 protected Object unMarshalSingleObject(String xml, CoreSession coreSession) { 183 Document document; 184 try { 185 document = DocumentHelper.parseText(xml); 186 } catch (DocumentException e) { 187 throw new NuxeoException("Error during unmarshaling", e); 188 } 189 org.dom4j.Element rootElem = document.getRootElement(); 190 191 QName qname = rootElem.getQName(); 192 String name = rootElem.getName(); 193 194 if (name.equals("publicationNode")) { 195 return nodeMarshaler.unMarshalPublicationNode(xml); 196 } else if (name.equals("publishedDocument")) { 197 return publishedDocumentMarshaler.unMarshalPublishedDocument(xml); 198 } else if (name.equals("document")) { 199 return documentModelMarshaler.unMarshalDocument(xml, coreSession); 200 } else if (name.equals("documentLocation")) { 201 return docLocMarshaler.unMarshalDocumentLocation(xml); 202 } else if (name.equals("list")) { 203 List<Object> lst = new ArrayList<Object>(); 204 for (Iterator i = rootElem.elementIterator("listitem"); i.hasNext();) { 205 org.dom4j.Element el = (org.dom4j.Element) i.next(); 206 if (el.elements().size() == 0) { 207 lst.add(el.getText()); 208 } else { 209 lst.add(unMarshalSingleObject(((org.dom4j.Element) el.elements().get(0)).asXML(), coreSession)); 210 } 211 } 212 return lst; 213 } else if (name.equals("map")) { 214 Map map = new HashMap(); 215 for (Iterator i = rootElem.elementIterator("mapitem"); i.hasNext();) { 216 org.dom4j.Element el = (org.dom4j.Element) i.next(); 217 218 Object value = null; 219 if (el.elements().size() > 0) { 220 value = unMarshalSingleObject(((org.dom4j.Element) (el).elements().get(0)).asXML(), coreSession); 221 } else { 222 value = el.getText(); 223 } 224 String key = el.attributeValue("name"); 225 map.put(key, value); 226 } 227 return map; 228 } 229 230 throw new NuxeoException("Unable to unmarshal data"); 231 232 } 233 234 protected String marshalSingleObject(Object ob) { 235 if (ob == null) { 236 return "null"; 237 } else if (ob instanceof String) { 238 return (String) ob; 239 } else if (ob instanceof DocumentModel) { 240 return cleanUpXml(documentModelMarshaler.marshalDocument((DocumentModel) ob)); 241 } else if (ob instanceof PublicationNode) { 242 return nodeMarshaler.marshalPublicationNode((PublicationNode) ob); 243 } else if (ob instanceof PublishedDocument) { 244 return publishedDocumentMarshaler.marshalPublishedDocument((PublishedDocument) ob); 245 } else if (ob instanceof DocumentLocation) { 246 return docLocMarshaler.marshalDocumentLocation((DocumentLocation) ob); 247 } else if (ob instanceof List) { 248 StringBuffer sb = new StringBuffer(); 249 sb.append("<list>"); 250 251 List list = (List) ob; 252 for (Object itemOb : list) { 253 sb.append("<listitem>"); 254 sb.append(marshalSingleObject(itemOb)); 255 sb.append("</listitem>"); 256 } 257 sb.append("</list>"); 258 return sb.toString(); 259 } else if (ob instanceof Map) { 260 StringBuffer sb = new StringBuffer(); 261 sb.append("<map>"); 262 Map map = (Map) ob; 263 for (Object key : map.keySet()) { 264 sb.append("<mapitem "); 265 sb.append("name=\""); 266 sb.append((String) key); 267 sb.append("\">"); 268 sb.append(marshalSingleObject(map.get(key))); 269 sb.append("</mapitem>"); 270 } 271 sb.append("</map>"); 272 return sb.toString(); 273 } 274 throw new NuxeoException("unable to marshal object of class " + ob.getClass().getName()); 275 } 276 277 public void setAssociatedCoreSession(CoreSession session) { 278 this.session = session; 279 } 280 281 public void setParameters(Map<String, String> params) { 282 this.params.putAll(params); 283 docLocMarshaler.setOriginatingServer(params.get("originalServer")); 284 documentModelMarshaler.setOriginatingServer(params.get("originalServer")); 285 } 286}