001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 */ 012package org.nuxeo.ecm.automation.client.jaxrs.spi; 013 014import static org.nuxeo.ecm.automation.client.Constants.CTYPE_AUTOMATION; 015import static org.nuxeo.ecm.automation.client.Constants.CTYPE_ENTITY; 016import static org.nuxeo.ecm.automation.client.Constants.CTYPE_MULTIPART_MIXED; 017 018import java.io.File; 019import java.io.FileInputStream; 020import java.io.IOException; 021import java.io.InputStream; 022import java.util.HashMap; 023import java.util.regex.Matcher; 024import java.util.regex.Pattern; 025 026import javax.mail.BodyPart; 027import javax.mail.MessagingException; 028import javax.mail.internet.MimeMultipart; 029 030import org.nuxeo.ecm.automation.client.RemoteException; 031import org.nuxeo.ecm.automation.client.jaxrs.spi.marshallers.ExceptionMarshaller; 032import org.nuxeo.ecm.automation.client.jaxrs.util.IOUtils; 033import org.nuxeo.ecm.automation.client.jaxrs.util.InputStreamDataSource; 034import org.nuxeo.ecm.automation.client.model.Blob; 035import org.nuxeo.ecm.automation.client.model.Blobs; 036import org.nuxeo.ecm.automation.client.model.FileBlob; 037 038/** 039 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 040 */ 041public class Request extends HashMap<String, String> { 042 043 public static final int GET = 0; 044 045 public static final int POST = 1; 046 047 private static final long serialVersionUID = 1L; 048 049 protected static Pattern ATTR_PATTERN = Pattern.compile(";?\\s*filename\\s*=\\s*([^;]+)\\s*", 050 Pattern.CASE_INSENSITIVE); 051 052 protected final int method; 053 054 protected final String url; 055 056 protected final boolean isMultiPart; 057 058 protected Object entity; 059 060 public Request(int method, String url) { 061 this.method = method; 062 this.url = url; 063 isMultiPart = false; 064 } 065 066 public Request(int method, String url, MimeMultipart entity) { 067 this.method = method; 068 this.url = url; 069 this.entity = entity; 070 isMultiPart = true; 071 } 072 073 public Request(int method, String url, String entity) { 074 this.method = method; 075 this.url = url; 076 this.entity = entity; 077 isMultiPart = false; 078 } 079 080 public int getMethod() { 081 return method; 082 } 083 084 public String getUrl() { 085 return url; 086 } 087 088 public Object getEntity() { 089 return entity; 090 } 091 092 public final boolean isMultiPart() { 093 return isMultiPart; 094 } 095 096 public MimeMultipart asMultiPartEntity() { 097 return isMultiPart ? (MimeMultipart) entity : null; 098 } 099 100 public String asStringEntity() { 101 return isMultiPart ? null : (String) entity; 102 } 103 104 /** 105 * Must read the object from the server response and return it or throw a {@link RemoteException} if server sent an 106 * error. 107 */ 108 public Object handleResult(int status, String ctype, String disp, InputStream stream) throws RemoteException, 109 IOException { 110 if (status == 204) { // no content 111 return null; 112 } else if (status >= 400) { 113 handleException(status, ctype, stream); 114 } 115 String lctype = ctype.toLowerCase(); 116 if (lctype.startsWith(CTYPE_ENTITY)) { 117 return JsonMarshalling.readEntity(IOUtils.read(stream)); 118 } else if (lctype.startsWith(CTYPE_AUTOMATION)) { 119 return JsonMarshalling.readRegistry(IOUtils.read(stream)); 120 } else if (lctype.startsWith(CTYPE_MULTIPART_MIXED)) { // list of 121 // blobs 122 return readBlobs(ctype, stream); 123 } else { // a blob? 124 String fname = null; 125 if (disp != null) { 126 fname = getFileName(disp); 127 } 128 return readBlob(ctype, fname, stream); 129 } 130 } 131 132 protected static Blobs readBlobs(String ctype, InputStream in) throws IOException { 133 Blobs files = new Blobs(); 134 // save the stream to a temporary file 135 File file = IOUtils.copyToTempFile(in); 136 FileInputStream fin = new FileInputStream(file); 137 try { 138 MimeMultipart mp = new MimeMultipart(new InputStreamDataSource(fin, ctype)); 139 int size = mp.getCount(); 140 for (int i = 0; i < size; i++) { 141 BodyPart part = mp.getBodyPart(i); 142 String fname = part.getFileName(); 143 files.add(readBlob(part.getContentType(), fname, part.getInputStream())); 144 } 145 } catch (MessagingException e) { 146 throw new IOException(e); 147 } finally { 148 try { 149 fin.close(); 150 } catch (IOException e) { 151 } 152 file.delete(); 153 } 154 return files; 155 } 156 157 protected static Blob readBlob(String ctype, String fileName, InputStream in) throws IOException { 158 File file = IOUtils.copyToTempFile(in); 159 FileBlob blob = new FileBlob(file); 160 blob.setMimeType(ctype); 161 if (fileName != null) { 162 blob.setFileName(fileName); 163 } 164 return blob; 165 } 166 167 protected static String getFileName(String ctype) { 168 Matcher m = ATTR_PATTERN.matcher(ctype); 169 if (m.find()) { 170 return m.group(1); 171 } 172 return null; 173 } 174 175 protected void handleException(int status, String ctype, InputStream stream) throws RemoteException, IOException { 176 if (CTYPE_ENTITY.equalsIgnoreCase(ctype)) { 177 String content = IOUtils.read(stream); 178 RemoteException e = null; 179 try { 180 e = ExceptionMarshaller.readException(content); 181 } catch (IOException t) { 182 throw new RemoteException(status, "ServerError", "Server Error", content); 183 } 184 throw e; 185 } else { 186 throw new RemoteException(status, "ServerError", "Server Error", IOUtils.read(stream)); 187 } 188 } 189 190}