KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > htmleditors > fckeditor > FCKeditorWebDAVConnector


1 package org.jahia.services.htmleditors.fckeditor;
2
3 import java.io.File JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.io.PrintWriter JavaDoc;
6 import java.text.Collator JavaDoc;
7 import java.util.Collections JavaDoc;
8 import java.util.Iterator JavaDoc;
9 import java.util.LinkedList JavaDoc;
10 import java.util.List JavaDoc;
11
12 import javax.servlet.ServletException JavaDoc;
13 import javax.servlet.http.HttpServletRequest JavaDoc;
14 import javax.servlet.http.HttpServletResponse JavaDoc;
15 import javax.transaction.Status JavaDoc;
16
17 import org.apache.commons.fileupload.DiskFileUpload;
18 import org.apache.commons.fileupload.FileItem;
19 import org.apache.commons.fileupload.FileUploadException;
20 import org.apache.commons.lang.StringEscapeUtils;
21 import org.jahia.params.ParamBean;
22 import org.jahia.services.webdav.DAVFileAccess;
23 import org.jahia.services.webdav.JahiaWebdavBaseService;
24
25 /**
26  * FCKeditor file browser integration for Jahia WebDAV resources.<br/>
27  * This servlet accepts 5 commands used to retrieve and create files and folders
28  * from a server directory. The allowed commands are:
29  * <ul>
30  * <li>GetStartFolders: Obtain the root folder and start folder according to
31  * the currently selected resource
32  * <li>GetFolders: Retrive the list of WebDAV folders under the current folder
33  * <li>GetFoldersAndFiles: Retrive the list of files and directory under the
34  * current folder
35  * <li>CreateFolder: Create a new directory under the current folder
36  * <li>FileUpload: uploads a new file to the WebDAV (must be sent with a POST)
37  * </ul>
38  * <br/>
39  * The implementation is based on the code of JSP Integration Pack ver 2.3
40  * (http://wiki.fckeditor.net/Developer%27s_Guide/Integration/Java).
41  *
42  * @author Sergiy Shyrkov
43  */

44
45 public class FCKeditorWebDAVConnector extends FCKeditorBaseConnector
46 {
47   private static class FileEntry implements Comparable JavaDoc
48   {
49     String JavaDoc name;
50     int size;
51
52     FileEntry(String JavaDoc fileName, int fileSize)
53     {
54       name = fileName;
55       size = fileSize;
56     }
57
58     /*
59      * (non-Javadoc)
60      *
61      * @see java.lang.Comparable#compareTo(java.lang.Object)
62      */

63     public int compareTo(Object JavaDoc theO)
64     {
65       return COLLATOR.compare(name, ((FileEntry)theO).name);
66     }
67
68   }
69
70   private static class UploadResult
71   {
72     String JavaDoc newFileName;
73     String JavaDoc returnValue;
74
75     UploadResult(String JavaDoc retValue, String JavaDoc newName)
76     {
77       returnValue = retValue;
78       newFileName = newName;
79     }
80
81   }
82
83   static final Collator JavaDoc COLLATOR = Collator.getInstance();
84
85   protected static String JavaDoc getExtension(String JavaDoc fileName)
86   {
87     return fileName.lastIndexOf(".") != -1 ? fileName.substring(fileName
88       .lastIndexOf(".") + 1) : "";
89   }
90
91   protected static String JavaDoc getNameWithoutExtension(String JavaDoc fileName)
92   {
93     return fileName.lastIndexOf(".") != -1 ? fileName.substring(0, fileName
94       .lastIndexOf(".")) : fileName;
95   }
96
97   protected String JavaDoc createFolder(DAVFileAccess fileAccess,
98     String JavaDoc currentFolderStr, HttpServletRequest JavaDoc request, ParamBean jParams)
99   {
100     String JavaDoc retValue = "110"; // unknown error
101
if (fileAccess.hasPermission(DAVFileAccess.WRITE)
102       && fileAccess.isWriteable())
103     {
104       String JavaDoc newFolderStr = request.getParameter("NewFolderName");
105       String JavaDoc normalizedName = DAVFileAccess.normalizeDirName(newFolderStr);
106       DAVFileAccess existingDir = JahiaWebdavBaseService.getInstance()
107         .getDAVFileAccess(jParams, currentFolderStr + "/" + normalizedName);
108       if (existingDir != null && existingDir.isValid())
109       {
110         retValue = existingDir.isCollection() ? "101" // already exists
111
: "102"; // is a file --> invalid folder name
112

113       }
114       else
115       {
116         retValue = fileAccess.createCollection(newFolderStr) != null ? "0"
117           : "110";
118       }
119     }
120     else
121     {
122       retValue = "103"; // no permissions
123
}
124
125     return retValue;
126   }
127
128   /**
129    * Manage the Get requests (GetStartFolder, GetFolders, GetFoldersAndFiles,
130    * CreateFolder).<br/>
131    * The servlet accepts commands sent in the following format:<br/>
132    * connector?Command=CommandName&Type=ResourceType&CurrentFolder=FolderPath<br/>
133    * <br/>
134    * It execute the command and then return the results to the client in XML
135    * format.
136    */

137   public void doGet(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
138     throws ServletException JavaDoc, IOException JavaDoc
139   {
140     ParamBean jParams = getJahiaParamBean(request, response);
141     String JavaDoc rootUrl = getRootPathForSite(jParams);
142     String JavaDoc rootFolder = getRootFolderName(jParams);
143
144     String JavaDoc command = request.getParameter("Command");
145     String JavaDoc type = request.getParameter("Type");
146     String JavaDoc currentFolder = request.getParameter("CurrentFolder");
147     String JavaDoc currentResource = request.getParameter("CurrentResource");
148
149     if (logger.isDebugEnabled())
150       logger.debug("Start performing FCKeditor command " + command
151         + " for resource type " + type + " and current folder " + currentFolder
152         + " and current resource " + currentResource);
153
154     StringBuffer JavaDoc outBuffer = new StringBuffer JavaDoc(1024);
155     outBuffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
156
157     try
158     {
159       if ("GetStartFolders".equals(command))
160       {
161         // try to find first existing folder in the path, specified by the
162
// current resource
163
currentFolder = getStartFolder(rootUrl, rootFolder, currentResource,
164           jParams);
165       }
166
167       DAVFileAccess fileAccess = JahiaWebdavBaseService.getInstance()
168         .getDAVFileAccess(jParams, currentFolder);
169
170       boolean doRollback = false;
171
172       if (fileAccess != null
173         && fileAccess.getTransactionStatus() == Status.STATUS_NO_TRANSACTION)
174         fileAccess.beginTransaction();
175
176       while (!fileAccess.isValid() && currentFolder.length() > 1
177         && currentFolder.lastIndexOf('/', currentFolder.length() - 2) > 0)
178       {
179         currentFolder = currentFolder.substring(0, currentFolder.lastIndexOf(
180           '/', currentFolder.length() - 2))
181           + "/";
182
183         fileAccess = JahiaWebdavBaseService.getInstance().getDAVFileAccess(
184           jParams, currentFolder);
185       }
186
187       outBuffer.append("<Connector command=\"").append(command).append(
188         "\" resourceType=\"").append(type).append("\">").append(
189         "<RootFolder path=\"").append(StringEscapeUtils.escapeXml(rootFolder))
190         .append("\"/>").append("<CurrentFolder path=\"").append(
191           StringEscapeUtils.escapeXml(currentFolder)).append("\" url=\"")
192         .append(StringEscapeUtils.escapeXml(rootUrl + currentFolder)).append(
193           "\" root=\"").append(StringEscapeUtils.escapeXml(rootFolder)).append(
194           "\"/>");
195
196       if ("GetFolders".equals(command))
197       {
198         List JavaDoc resourceList = fileAccess != null
199           && fileAccess.hasPermission(DAVFileAccess.READ) ? fileAccess
200           .getChildren() : Collections.EMPTY_LIST;
201
202         getFolders(resourceList, rootFolder, jParams, outBuffer);
203       }
204       else if ("GetFoldersAndFiles".equals(command))
205       {
206         List JavaDoc resourceList = fileAccess != null
207           && fileAccess.hasPermission(DAVFileAccess.READ) ? fileAccess
208           .getChildren() : Collections.EMPTY_LIST;
209
210         getFolders(resourceList, rootFolder, jParams, outBuffer);
211         getFiles(resourceList, type, rootFolder, jParams, outBuffer);
212       }
213       else if ("CreateFolder".equals(command))
214       {
215         String JavaDoc retValue = createFolder(fileAccess, currentFolder, request,
216           jParams);
217
218         outBuffer.append("<Error number=\"").append(retValue).append("\"/>");
219
220         if ("110".equals(retValue))
221           doRollback = true;
222       }
223
224       outBuffer.append("</Connector>");
225
226       if (doRollback)
227         fileAccess.rollbackTransaction();
228       else
229         fileAccess.commitTransaction();
230     }
231     catch (Exception JavaDoc ex)
232     {
233       logger.error("Error executing FCKeditor command " + command, ex);
234     }
235     finally
236     {
237       releaseResources();
238     }
239
240     if (logger.isDebugEnabled())
241       logger.debug("FCKeditor command result: " + outBuffer.toString());
242
243     response.setContentType("text/xml; charset=UTF-8");
244     response.setHeader("Cache-Control", "no-cache");
245     PrintWriter JavaDoc out = response.getWriter();
246     out.print(outBuffer.toString());
247     out.flush();
248     out.close();
249   }
250
251   /**
252    * Manage the Post requests (FileUpload).<br/>
253    * The servlet accepts commands sent in the following format:<br/>
254    * connector?Command=FileUpload&Type=ResourceType&CurrentFolder=FolderPath<br/>
255    * <br/>
256    * It store the file (renaming it in case a file with the same name exists)
257    * and then return an HTML file with a javascript command in it.
258    */

259   public void doPost(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
260     throws ServletException JavaDoc, IOException JavaDoc
261   {
262     String JavaDoc commandStr = request.getParameter("Command");
263     String JavaDoc typeStr = request.getParameter("Type");
264     String JavaDoc currentFolderStr = request.getParameter("CurrentFolder");
265
266     if (logger.isDebugEnabled())
267       logger.debug("Start performing FCKeditor command " + commandStr
268         + " for resource type " + typeStr + " and current folder "
269         + currentFolderStr);
270
271     String JavaDoc retVal = "0";
272     String JavaDoc newName = "";
273
274     if (!commandStr.equals("FileUpload"))
275     {
276       retVal = "203";
277     }
278     else
279     {
280       ParamBean jParams = getJahiaParamBean(request, response);
281       DAVFileAccess fileAccess = JahiaWebdavBaseService.getInstance()
282         .getDAVFileAccess(jParams, currentFolderStr);
283
284       if (fileAccess != null
285         && fileAccess.getTransactionStatus() == Status.STATUS_NO_TRANSACTION)
286         fileAccess.beginTransaction();
287
288       try
289       {
290         UploadResult result = uploadFile(fileAccess, request, jParams);
291         retVal = result.returnValue;
292         newName = result.newFileName;
293
294         fileAccess.commitTransaction();
295       }
296       catch (Exception JavaDoc ex)
297       {
298         logger
299           .error(
300             "Error while uploading file. Failed to process FCKeditor FileUpload command",
301             ex);
302         retVal = "203";
303
304         if (fileAccess != null)
305           fileAccess.rollbackTransaction();
306       }
307       finally
308       {
309         releaseResources();
310       }
311     }
312     if (logger.isDebugEnabled())
313       logger.debug("FCKeditor command result: " + retVal);
314
315     response.setContentType("text/html; charset=UTF-8");
316     response.setHeader("Cache-Control", "no-cache");
317     PrintWriter JavaDoc out = response.getWriter();
318     out.print("<script type=\"text/javascript\">");
319     out.print("window.parent.frames['frmUpload'].OnUploadCompleted(");
320     out.print(retVal);
321     out.print(",'");
322     out.print(newName.length() > 0 ? newName.replaceAll("\'", "\\\\'") : "");
323     out.print("');");
324     out.print("</script>");
325     out.flush();
326     out.close();
327   }
328
329   protected void getFiles(List JavaDoc resourceList, String JavaDoc typeStr, String JavaDoc rootFolder,
330     ParamBean jParams, StringBuffer JavaDoc buffer)
331   {
332     buffer.append("<Files>");
333     List JavaDoc fileList = new LinkedList JavaDoc();
334
335     // get list of file names
336
for (Iterator JavaDoc iter = resourceList.iterator(); iter.hasNext();)
337     {
338       DAVFileAccess currentElement = (DAVFileAccess)iter.next();
339       if (!currentElement.isCollection()
340         && currentElement.hasPermission(DAVFileAccess.READ)
341         && resourceTypeMatches(currentElement, typeStr)
342         && !skipFile(currentElement, rootFolder, jParams))
343       {
344         fileList.add(new FileEntry(currentElement.getName(),
345           (int)(currentElement.getContentLength() / 1024)));
346       }
347     }
348
349     // sort list alphabetically
350
if (fileList.size() > 0)
351       Collections.sort(fileList);
352
353     // create XML structure
354
for (Iterator JavaDoc iter = fileList.iterator(); iter.hasNext();)
355     {
356       FileEntry currentElement = (FileEntry)iter.next();
357       buffer.append("<File name=\"").append(
358         StringEscapeUtils.escapeXml(currentElement.name)).append("\" size=\"")
359         .append(currentElement.size).append("\"/>");
360     }
361
362     buffer.append("</Files>");
363   }
364
365   protected void getFolders(List JavaDoc resourceList, String JavaDoc rootFolder,
366     ParamBean jParams, StringBuffer JavaDoc buffer)
367   {
368     buffer.append("<Folders>");
369     List JavaDoc folderNames = new LinkedList JavaDoc();
370
371     // get list of folder names
372
for (Iterator JavaDoc iter = resourceList.iterator(); iter.hasNext();)
373     {
374       DAVFileAccess currentElement = (DAVFileAccess)iter.next();
375       if (currentElement.isCollection()
376         && currentElement.hasPermission(DAVFileAccess.READ)
377         && !skipFolder(currentElement, rootFolder, jParams))
378       {
379         folderNames.add(currentElement.getName());
380       }
381     }
382
383     // sort list alphabetically
384
if (folderNames.size() > 0)
385       Collections.sort(folderNames, COLLATOR);
386
387     // create XML structure
388
for (Iterator JavaDoc iter = folderNames.iterator(); iter.hasNext();)
389     {
390       buffer.append("<Folder name=\"").append(
391         StringEscapeUtils.escapeXml((String JavaDoc)iter.next())).append("\"/>");
392     }
393
394     buffer.append("</Folders>");
395   }
396
397   protected String JavaDoc getRootFolderName(ParamBean jParams)
398   {
399     return "/";
400   }
401
402   protected String JavaDoc getRootPathForSite(ParamBean jParams)
403   {
404     return new StringBuffer JavaDoc(32).append(jParams.getRequest().getContextPath())
405       .append("/webdav/site/").append(jParams.getSiteKey()).toString();
406   }
407
408   protected String JavaDoc getStartFolder(String JavaDoc rootPath, String JavaDoc rootFolder,
409     String JavaDoc currentResource, ParamBean jParams)
410   {
411     String JavaDoc currentFolder = rootFolder;
412
413     // try to find first existing folder in the path, specified by the
414
// current resource
415
if (currentResource != null)
416     {
417       currentResource = currentResource.trim();
418       if (currentResource.startsWith(rootPath + rootFolder))
419       {
420         String JavaDoc relativeResource = currentResource
421           .substring((rootPath + rootFolder).length());
422
423         if (relativeResource.charAt(relativeResource.length() - 1) != '/')
424         {
425           if (relativeResource.lastIndexOf('/') > 0)
426           {
427             relativeResource = relativeResource.substring(0, relativeResource
428               .lastIndexOf('/'))
429               + "/";
430           }
431           else
432           {
433             relativeResource = "";
434           }
435         }
436
437         currentFolder = rootFolder + relativeResource;
438       }
439     }
440
441     return currentFolder;
442   }
443
444   protected boolean resourceTypeMatches(DAVFileAccess resource,
445     String JavaDoc resourceType)
446   {
447     boolean matches = true;
448     if (resourceType != null && resourceType.length() > 0)
449     {
450       matches = false;
451       String JavaDoc contentType = resource.getContentType();
452       if (contentType != null)
453       {
454         if ("Image".equals(resourceType))
455         {
456           // show only images
457
matches = contentType.regionMatches(true, 0, "image/", 0, "image/"
458             .length());
459         }
460         else if ("File".equals(resourceType))
461         {
462           // filter images out
463
matches = !contentType.regionMatches(true, 0, "image/", 0, "image/"
464             .length());
465         }
466         else if ("Flash".equals(resourceType))
467         {
468           // show only flash files
469
matches = contentType.regionMatches(true, 0,
470             "application/x-shockwave-flash", 0, "application/x-shockwave-flash"
471               .length());
472         }
473         else
474           matches = true;
475       }
476     }
477
478     return matches;
479   }
480
481   /**
482    * Returns <code>true</code> if the file should not be included in the
483    * result list.
484    *
485    * @param file the WebDAV resource
486    * @param rootFolder current WebDAV root folder
487    * @param jParams current Jahia ParamBean
488    * @return <code>true</code> if the file should not be included in the
489    * result list
490    */

491   protected boolean skipFile(DAVFileAccess file, String JavaDoc rootFolder,
492     ParamBean jParams)
493   {
494     return false;
495   }
496
497   /**
498    * Returns <code>true</code> if the folder should not be included in the
499    * result list.
500    *
501    * @param folder the WebDAV resource
502    * @param rootFolder current WebDAV root folder
503    * @param jParams current Jahia ParamBean
504    * @return <code>true</code> if the folder should not be included in the
505    * result list
506    */

507   protected boolean skipFolder(DAVFileAccess folder, String JavaDoc rootFolder,
508     ParamBean jParams)
509   {
510     return false;
511   }
512
513   protected UploadResult uploadFile(DAVFileAccess currentDavDir,
514     HttpServletRequest JavaDoc request, ParamBean jParams)
515     throws FileUploadException, IOException JavaDoc
516   {
517     String JavaDoc retVal = "0";
518     String JavaDoc newName = "";
519
520     // we will use Commons Fileupload
521
DiskFileUpload upload = new DiskFileUpload();
522
523     // obtain TMP dir from Jahia settings
524
File JavaDoc tmpDir = new File JavaDoc(jParams.settings().getTmpContentDiskPath());
525     if (!tmpDir.exists())
526       tmpDir.mkdir();
527
528     upload.setRepositoryPath(tmpDir.getPath());
529     // set max upload file size from Jahia settings
530
upload.setSizeMax(jParams.settings().getJahiaFileUploadMaxSize());
531     // handle headers (filenames) properly
532
upload.setHeaderEncoding("UTF-8");
533
534     // parse uploaded file
535
List JavaDoc items = upload.parseRequest(request);
536     FileItem uploadedFile = null;
537
538     // uploaded file is contained in the filed named NewFile
539
Iterator JavaDoc iter = items.iterator();
540     while (iter.hasNext())
541     {
542       FileItem item = (FileItem)iter.next();
543       if (!item.isFormField() && "NewFile".equals(item.getFieldName()))
544       {
545         uploadedFile = item;
546         break;
547       }
548     }
549
550     if (uploadedFile.getSize() == 0)
551     {
552       // invalid or empty file
553
return new UploadResult("202", "");
554     }
555
556     // obtain the file name (Opera submits the full file path, instead of
557
// filename)
558
String JavaDoc[] pathParts = uploadedFile.getName().replace('\\', '/').split("/");
559     String JavaDoc fileName = pathParts[pathParts.length - 1];
560     String JavaDoc fileNameWithoutExt = getNameWithoutExtension(fileName);
561     String JavaDoc fileExtension = getExtension(fileName);
562     // normalize name
563
String JavaDoc normalizedName = DAVFileAccess.normalizeFileName(fileName);
564     DAVFileAccess existingFile = JahiaWebdavBaseService
565       .getInstance()
566       .getDAVFileAccess(jParams, currentDavDir.getPath() + "/" + normalizedName);
567     int counter = 1;
568     // if the file with this name exists, add (<counter>) to the file name and
569
// try it out; the filename will look like myFile(1).jpg
570
while (existingFile != null && existingFile.isValid())
571     {
572       newName = new StringBuffer JavaDoc(32).append(fileNameWithoutExt).append("(")
573         .append(counter).append(")").append(".").append(fileExtension)
574         .toString();
575       normalizedName = DAVFileAccess.normalizeFileName(newName);
576       retVal = "201";
577       existingFile = JahiaWebdavBaseService.getInstance().getDAVFileAccess(
578         jParams, currentDavDir.getPath() + "/" + normalizedName);
579       counter++;
580     }
581
582     // obtain the content type of the uploaded file: either submitted or
583
// determine by extension
584
String JavaDoc contentType = uploadedFile.getContentType() != null ? uploadedFile
585       .getContentType() : getServletContext().getMimeType(fileName);
586
587     // upload file to WebDAV
588
currentDavDir
589       .uploadFile(newName.length() > 0 ? newName : fileName, uploadedFile
590         .getInputStream(), contentType, uploadedFile.getSize(), false);
591
592     // delete temporary file
593
uploadedFile.delete();
594
595     return new UploadResult(retVal, newName);
596   }
597
598 }
599
Popular Tags