View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.portals.gems.file;
18  
19  import java.io.File;
20  import java.io.FileInputStream;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.OutputStream;
24  import java.util.Iterator;
25  import java.util.LinkedList;
26  import java.util.List;
27  
28  import javax.portlet.PortletConfig;
29  import javax.portlet.PortletException;
30  import javax.portlet.PortletPreferences;
31  import javax.portlet.PortletRequest;
32  import javax.portlet.RenderRequest;
33  import javax.portlet.RenderResponse;
34  import javax.servlet.http.HttpServletRequest;
35  
36  import org.apache.jetspeed.PortalReservedParameters;
37  import org.apache.jetspeed.om.folder.Folder;
38  import org.apache.jetspeed.request.RequestContext;
39  import org.apache.portals.bridges.common.GenericServletPortlet;
40  
41  /***
42   * FilePortlet
43   * 
44   * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
45   * @version $Id: FilePortlet.java 601037 2007-12-04 18:50:55Z taylor $
46   */
47  public class FilePortlet extends GenericServletPortlet
48  {
49      public static final String PARAM_USE_LANGUAGE = "use-language";
50      /***
51       * Name of portlet preference for source file url
52       */
53      public static final String PARAM_SOURCE_FILE = "file";
54  
55      /***
56       * Name of portlet preference for source file url
57       */
58      public static final String PARAM_SOURCE_BASE_PATH = "basepath";
59  
60      /***
61       * Name of portlet preference for source file url
62       */
63      public static final String PARAM_SOURCE_FILE_PATH = "filepath";
64  
65      /***
66       * Is the file stored in the webapp or outside of the webapp? valid values
67       * "webapp" and "filesystem", defaults to webapp
68       */
69      public static final String PARAM_LOCATION = "location";
70  
71      private boolean webappLocation = true;
72  
73      /***
74       * Default URL for the source file
75       */
76      private String defaultSourceFile = null;
77  
78      /***
79       * Default base URL for the source file
80       */
81      private String defaultSourceBasePath = null;
82  
83      private boolean useLanguage = false;
84      
85      public void init(PortletConfig config) throws PortletException
86      {
87          super.init(config);
88          String use = config.getInitParameter(PARAM_USE_LANGUAGE);
89          if (use != null && use.equalsIgnoreCase("true"))
90              this.useLanguage = true;
91          this.defaultSourceFile = config.getInitParameter(PARAM_SOURCE_FILE);
92          this.defaultSourceBasePath = config
93                  .getInitParameter(PARAM_SOURCE_BASE_PATH);
94          String location = config.getInitParameter(PARAM_LOCATION);
95          if (location != null && location.equals("filesystem"))
96              webappLocation = false;
97          else
98              webappLocation = true;
99      }
100 
101     private RequestContext getRequestContext(PortletRequest request)
102     {
103         return (RequestContext) request
104                 .getAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE);
105 
106     }
107 
108     private HttpServletRequest getHttpServletRequest(PortletRequest pRequest)
109     {
110         return getRequestContext(pRequest).getRequest();
111 
112     }
113 
114     public void doView(RenderRequest request, RenderResponse response)
115             throws PortletException, IOException
116     {
117         // NOTE: this is Jetspeed specific
118         HttpServletRequest req = getHttpServletRequest(request);
119         String fileName = (String) req.getSession().getAttribute("file");
120         if (fileName != null && !fileName.equals(""))
121         {
122             InputStream is = null;
123             try
124             {
125                 fileName = getFilePath(fileName);
126                 is = new FileInputStream(fileName);
127                 if (is == null)
128                 {
129                     byte[] bytes = ("File " + fileName + " not found.")
130                             .getBytes();
131                     response.getPortletOutputStream().write(bytes);
132                     return;
133                 }
134                 setContentType(fileName, response);
135                 drain(is, response.getPortletOutputStream());
136                 response.getPortletOutputStream().flush();
137                 is.close();
138                 req.getSession().removeAttribute("file");
139             } catch (Exception e)
140             {
141                 if (is != null) is.close();
142                 byte[] bytes = ("File " + fileName + " not found.").getBytes();
143                 req.getSession().removeAttribute("file");
144                 response.setContentType("text/html");
145                 response.getPortletOutputStream().write(bytes);
146                 return;
147             }
148         } 
149         else
150         {
151             String path = (String) request.getAttribute(PortalReservedParameters.PATH_ATTRIBUTE);
152             if (null == path)
153             {
154                 PortletPreferences prefs = request.getPreferences();
155                 path = prefs.getValue(PARAM_SOURCE_FILE, this.defaultSourceFile);
156             }
157             else
158             {
159                 if (path.endsWith(".css"))
160                     path = null;
161             }
162             if (null == path && this.defaultSourceBasePath != null)
163             {
164                 String filepath = request.getParameter(PARAM_SOURCE_FILE_PATH);
165                 if (filepath == null)
166                 {
167                     filepath = (String) request
168                             .getAttribute(PARAM_SOURCE_FILE_PATH);
169                 }
170 
171                 if (filepath != null)
172                 {
173                     path = ((this.defaultSourceBasePath.length() > 0) ? (this.defaultSourceBasePath + "/")
174                             : "")
175                             + filepath;
176                 }
177             }
178 
179             if (null == path)
180             {
181                 response.setContentType("text/html");
182                 response.getWriter().println("Could not find source document.");
183             } 
184             else
185             {
186                 setContentType(path, response);                
187                 List paths = fallback(path, request.getLocale().getLanguage());
188                 renderFile(response, paths);
189             }
190         }
191     }
192 
193     protected List fallback(String path, String language)
194     {
195         List paths = new LinkedList();
196         if (this.useLanguage)
197         {
198             if (webappLocation)
199             {
200                 path = concatenatePaths("/WEB-INF/", path);                
201             }            
202             String fallbackPath = path;
203             File temp = new File(path);
204             String parentPath = temp.getParent();
205             String name = temp.getName();
206             path = concatenatePaths(parentPath, language);
207             path = concatenatePaths(path, name);
208             paths.add(path);
209             paths.add(fallbackPath);
210         }
211         else
212         {
213             if (webappLocation)
214             {
215                 path = concatenatePaths("/WEB-INF/", path);                
216             }                        
217             paths.add(path);
218         }
219         return paths;
220     }
221     
222     protected void setContentType(String path, RenderResponse response)
223     {
224         // Note these content types need to be added to the portlet.xml
225         if (path.endsWith(".html"))
226         {
227             response.setContentType("text/html");
228         } else if (path.endsWith(".pdf"))
229         {
230             response.setContentType("application/pdf");
231         } else if (path.endsWith(".zip"))
232         {
233             response.setContentType("application/zip");
234         } else if (path.endsWith(".csv"))
235         {
236             response.setContentType("text/csv");
237         } else if (path.endsWith(".xml") || path.endsWith(".xsl"))
238         {
239             response.setContentType("text/xml");
240         } else if (path.endsWith(".psml") || path.endsWith(".link"))
241         {
242             response.setContentType("text/xml");
243         } else
244         {
245             response.setContentType("text/html");
246         }
247     }
248 
249     protected void renderFile(RenderResponse response, List paths)
250             throws PortletException, IOException
251     {
252         boolean drained = false;
253         Iterator it = paths.iterator();
254         while (it.hasNext())
255         {
256             String fileName = (String)it.next();
257             InputStream is = null;
258             try
259             {
260                 if (this.webappLocation)
261                 {
262                     is = this.getPortletContext().getResourceAsStream(fileName);
263                 } else
264                 {
265                     is = new FileInputStream(fileName);
266                 }
267                 if (is != null)
268                 {
269                     drain(is, response.getPortletOutputStream());
270                     response.getPortletOutputStream().flush();
271                     is.close();
272                     drained = true;
273                     break;
274                 }
275             }
276             catch (Exception e)
277             {
278                 // do nothing, find next file
279             }
280         }
281         if (!drained)
282         {
283             String fileName = (String)paths.get(0);
284             byte[] bytes = ("File " + fileName + " not found.").getBytes();
285             response.getPortletOutputStream().write(bytes);
286             return;            
287         }
288     }
289 
290     static final int BLOCK_SIZE = 4096;
291 
292     public static void drain(InputStream r, OutputStream w) throws IOException
293     {
294         byte[] bytes = new byte[BLOCK_SIZE];
295         try
296         {
297             int length = r.read(bytes);
298             while (length != -1)
299             {
300                 if (length != 0)
301                 {
302                     w.write(bytes, 0, length);
303                 }
304                 length = r.read(bytes);
305             }
306         } finally
307         {
308             bytes = null;
309         }
310     }
311 
312     private String getFilePath(String path)
313     {
314         String pageRoot = System.getProperty("java.io.tmpdir");
315         String sep = System.getProperty("file.separator");
316         if (sep == null || sep.equals("")) sep = "/";
317 
318         String ar[] = path.split("_");
319         if (ar.length == 1) return pageRoot + sep + path;
320         return pageRoot + sep + ar[0] + sep + ar[1];
321     }
322     
323     protected static String concatenatePaths(String base, String path)
324     {
325         String result = "";
326         if (base == null)
327         {
328             if (path == null)
329             {
330                 return result;
331             }
332             return path;
333         }
334         else
335         {
336             if (path == null)
337             {
338                 return base;
339             }
340         }
341         if (base.endsWith(Folder.PATH_SEPARATOR)) 
342         {
343             if (path.startsWith(Folder.PATH_SEPARATOR))
344             {
345                 result = base.concat(path.substring(1));
346                 return result;
347             }
348         
349         }
350         else
351         {
352             if (!path.startsWith(Folder.PATH_SEPARATOR)) 
353             {
354                 result = base.concat(Folder.PATH_SEPARATOR).concat(path);
355                 return result;
356             }
357         }
358         return base.concat(path);
359     }
360     
361 }