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