001    package org.trails.component.blob;
002    
003    import org.apache.commons.logging.Log;
004    import org.apache.commons.logging.LogFactory;
005    import org.apache.hivemind.util.Defense;
006    import org.apache.tapestry.IRequestCycle;
007    import org.apache.tapestry.engine.IEngineService;
008    import org.apache.tapestry.engine.ILink;
009    import org.apache.tapestry.services.DataSqueezer;
010    import org.apache.tapestry.services.LinkFactory;
011    import org.apache.tapestry.util.ContentType;
012    import org.apache.tapestry.web.WebResponse;
013    import org.trails.descriptor.IPropertyDescriptor;
014    import org.trails.descriptor.extension.BlobDescriptorExtension;
015    import org.trails.persistence.PersistenceService;
016    
017    import java.io.IOException;
018    import java.io.OutputStream;
019    import java.io.Serializable;
020    import java.util.HashMap;
021    import java.util.Map;
022    
023    public class BlobDownloadService implements IEngineService
024    {
025    
026            private static final Log LOG = LogFactory.getLog(BlobDownloadService.class);
027    
028            public static final String SERVICE_NAME = "download";
029    
030            private LinkFactory _linkFactory;
031    
032            private WebResponse _response;
033    
034            private PersistenceService persistenceService;
035    
036            private IFilePersister filePersister;
037    
038            DataSqueezer dataSqueezer;
039    
040            private static final String BLOBID_PARAMETER_NAME = "id";
041    
042            private static final String PROP_DESC_PARAMETER_NAME = "propDesc";
043    
044            public ILink getLink(boolean post, Object parameter)
045            {
046    
047                    Defense.isAssignable(((Object[]) parameter)[0], TrailsBlobAsset.class, "parameter");
048    
049                    TrailsBlobAsset asset = (TrailsBlobAsset) ((Object[]) parameter)[0];
050    
051                    Map<String, String> parameters = new HashMap<String, String>();
052    
053                    parameters.put(PROP_DESC_PARAMETER_NAME, dataSqueezer.squeeze(asset.getPropertyDescriptor()));
054                    parameters.put(BLOBID_PARAMETER_NAME, dataSqueezer.squeeze(asset.getId()));
055    
056                    return _linkFactory.constructLink(this, false, parameters, true);
057    
058            }
059    
060            public void service(IRequestCycle cycle) throws IOException
061            {
062                    String blobID = cycle.getParameter(BLOBID_PARAMETER_NAME);
063                    String bytesProp = cycle.getParameter(PROP_DESC_PARAMETER_NAME);
064    
065                    IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) dataSqueezer.unsqueeze(bytesProp);
066                    BlobDescriptorExtension blobDescriptor = propertyDescriptor.getExtension(BlobDescriptorExtension.class);
067    
068                    if (blobDescriptor != null && blobID != null && !"".equals(blobID))
069                    {
070                            Object model = persistenceService
071                                            .getInstance(propertyDescriptor.getBeanType(), (Serializable) dataSqueezer.unsqueeze(blobID));
072    
073                            if (model != null)
074                            {
075                                    String fileName = filePersister.getFileName(propertyDescriptor, model);
076                                    String contentType = filePersister.getContentType(propertyDescriptor, model);
077                                    byte[] bytes = filePersister.getData(propertyDescriptor, model);
078    
079                                    if (bytes.length > 0)
080                                    {
081                                            _response.setHeader("Expires", "0");
082                                            _response.setHeader("Cache-Control", "must-revalidate, post-check=0,pre-check=0");
083                                            _response.setHeader("Pragma", "public");
084                                            _response.setHeader("Content-Disposition",
085                                                            blobDescriptor.getContentDisposition().getValue() +
086                                                                            (fileName != null ? "; filename=" + fileName : ""));
087                                            _response.setContentLength(bytes.length);
088    
089                                            OutputStream output = null;
090                                            try
091                                            {
092                                                    output = _response.getOutputStream(
093                                                                    contentType != null ? new ContentType(contentType) : new ContentType());
094                                                    output.write(bytes);
095                                            } finally
096                                            {
097                                                    try
098                                                    {
099                                                            if (output != null)
100                                                            {
101                                                                    output.flush();
102                                                                    output.close();
103                                                            }
104                                                    } catch (Throwable t)
105                                                    {
106                                                            // do nothing;
107                                                    }
108                                            }
109                                    } else
110                                    {
111                                            String errorText = "BlobDownloadServcie: entityName->" +
112                                                            propertyDescriptor.getBeanType().getName() + ", blobID ->" + blobID +
113                                                            " : has not been ingested yet";
114                                            LOG.info(errorText);
115    //                                                       muted kwc - throw new TrailsRuntimeException(errorText);
116                                    }
117                            }
118    
119                    } else
120                    {
121                            String errorText = "BlobDownloadServcie: entityName->" + propertyDescriptor.getBeanType().getName() +
122                                            ", blobID ->" + blobID +
123                                            " : has not been ingested yet";
124                            LOG.info(errorText);
125                            // muted kwc - throw new TrailsRuntimeException(errorText);
126                    }
127            }
128    
129            public String getName()
130            {
131                    return SERVICE_NAME;
132            }
133    
134            public void setLinkFactory(LinkFactory linkFactory)
135            {
136                    _linkFactory = linkFactory;
137            }
138    
139            public void setResponse(WebResponse response)
140            {
141                    _response = response;
142            }
143    
144            public void setPersistenceService(PersistenceService persistenceService)
145            {
146                    this.persistenceService = persistenceService;
147            }
148    
149            public void setFilePersister(IFilePersister filePersister)
150            {
151                    this.filePersister = filePersister;
152            }
153    
154            public void setDataSqueezer(DataSqueezer dataSqueezer)
155            {
156                    this.dataSqueezer = dataSqueezer;
157            }
158    }