001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.webwork.components;
006:
007: import java.io.Serializable;
008:
009: import javax.servlet.http.HttpServletRequest;
010: import javax.servlet.http.HttpServletResponse;
011:
012: import org.apache.commons.logging.Log;
013: import org.apache.commons.logging.LogFactory;
014:
015: import com.opensymphony.webwork.interceptor.ServletRequestAware;
016: import com.opensymphony.webwork.interceptor.ServletResponseAware;
017: import com.opensymphony.xwork.ActionContext;
018: import com.opensymphony.xwork.ActionSupport;
019:
020: /**
021: * <!-- START SNIPPET: javadoc -->
022: *
023: * An abstract class to be extended in order for the Rich text editor to perform server-side
024: * browsing and uploading.
025: *
026: * <!-- END SNIPPET: javadoc -->
027: *
028: * <pre>
029: * <!-- START SNIPPET: example -->
030: *
031: * <package name="richtexteditor-browse" extends="webwork-default" namespace="/webwork/richtexteditor/editor/filemanager/browser/default/connectors/jsp">
032: * <action name="connector" class="com.opensymphony.webwork.components.DefaultRichtexteditorConnector" method="browse">
033: * <result name="getFolders" type="richtexteditorGetFolders" />
034: * <result name="getFoldersAndFiles" type="richtexteditorGetFoldersAndFiles" />
035: * <result name="createFolder" type="richtexteditorCreateFolder" />
036: * <result name="fileUpload" type="richtexteditorFileUpload" />
037: * </action>
038: * </package>
039: *
040: * <package name="richtexteditor-upload" extends="webwork-default" namespace="/webwork/richtexteditor/editor/filemanager/upload">
041: * <action name="uploader" class="com.opensymphony.webwork.components.DefaultRichtexteditorConnector" method="upload">
042: * <result name="richtexteditorFileUpload" />
043: * </action>
044: * </package>
045: *
046: * <!-- END SNIPPET: example -->
047: * </pre>
048: *
049: *
050: * @author tm_jee
051: * @version $Date: 2006-03-08 21:22:35 +0100 (Wed, 08 Mar 2006) $ $Id: AbstractRichtexteditorConnector.java 2338 2006-03-08 20:22:35Z rainerh $
052: * @see com.opensymphony.webwork.components.DefaultRichtexteditorConnector
053: */
054: public abstract class AbstractRichtexteditorConnector extends
055: ActionSupport implements ServletRequestAware,
056: ServletResponseAware {
057:
058: private static final Log _log = LogFactory
059: .getLog(AbstractRichtexteditorConnector.class);
060:
061: public static String GET_FOLDERS = "getFolders";
062: public static String GET_FOLDERS_AND_FILES = "getFoldersAndFiles";
063: public static String CREATE_FOLDER = "createFolder";
064: public static String FILE_UPLOAD = "fileUpload";
065:
066: protected HttpServletRequest _request;
067: protected HttpServletResponse _response;
068:
069: protected java.io.File _newFile;
070: protected String _newFileFileName;
071: protected String _newFileContentType;
072:
073: protected String _type;
074: protected String _command;
075: protected String _currentFolder;
076: protected String _serverPath = "/webwork/richtexteditor/data/";
077: protected String _newFolderName;
078:
079: /**
080: * <!-- START SNIPPET: browse -->
081: *
082: * The method that does the functionality when the richtexteditor 'browse' command is
083: * issued.
084: *
085: * <p/>
086: *
087: * Following are the result name that gets returned depending on the actual 'browse'
088: * command.
089: *
090: * <table border=1>
091: * <tr>
092: * <td>Browse Command</td>
093: * <td>Result Name</td>
094: * </tr>
095: * <tr>
096: * <td>GetFolders</td>
097: * <td>getFolders</td>
098: * </tr>
099: * <tr>
100: * <td>GetFoldersAndFiles</td>
101: * <td>getFoldersAndFiles</td>
102: * </tr>
103: * <tr>
104: * <td>CreateFolder</td>
105: * <td>createFolder</td>
106: * </tr>
107: * <tr>
108: * <td>FileUpload</td>
109: * <td>fileUpload</td>
110: * </tr>
111: * </table>
112: *
113: * <!-- END SNIPPET: browse -->
114: *
115: * @return result name
116: * @throws Exception
117: */
118: public String browse() throws Exception {
119:
120: if ("GetFolders".equals(getCommand())) {
121: _log.debug("Command " + getCommand()
122: + " detected \n\t type=" + getType()
123: + "\n\t folderPath=" + getCurrentFolder());
124:
125: ActionContext.getContext().put("__richtexteditorCommand",
126: getCommand());
127: ActionContext.getContext().put("__richtexteditorType",
128: getType());
129: ActionContext.getContext().put(
130: "__richtexteditorFolderPath", getCurrentFolder());
131: ActionContext.getContext().put(
132: "__richtexteditorServerPath",
133: calculateServerPath(getServerPath(),
134: getCurrentFolder(), getType()));
135:
136: Folder[] folders = getFolders(getCurrentFolder(), getType());
137:
138: ActionContext.getContext().put(
139: "__richtexteditorGetFolders", folders);
140:
141: return GET_FOLDERS;
142: } else if ("GetFoldersAndFiles".equals(getCommand())) {
143: _log.debug("Command " + getCommand()
144: + " detected \n\t type=" + getType()
145: + "\n\t folderPath=" + getCurrentFolder());
146:
147: ActionContext.getContext().put("__richtexteditorCommand",
148: getCommand());
149: ActionContext.getContext().put("__richtexteditorType",
150: getType());
151: ActionContext.getContext().put(
152: "__richtexteditorFolderPath", getCurrentFolder());
153: ActionContext.getContext().put(
154: "__richtexteditorServerPath",
155: calculateServerPath(getServerPath(),
156: getCurrentFolder(), getType()));
157:
158: FoldersAndFiles folderAndFiles = getFoldersAndFiles(
159: getCurrentFolder(), getType());
160:
161: ActionContext.getContext().put(
162: "__richtexteditorGetFoldersAndFiles",
163: folderAndFiles);
164:
165: return GET_FOLDERS_AND_FILES;
166: } else if ("CreateFolder".equals(getCommand())) {
167: _log.debug("Command " + getCommand()
168: + " detected \n\t type=" + getType()
169: + "\n\t folderPath=" + getCurrentFolder()
170: + "\n\t newFolderName=" + getNewFolderName());
171:
172: ActionContext.getContext().put("__richtexteditorCommand",
173: getCommand());
174: ActionContext.getContext().put("__richtexteditorType",
175: getType());
176: ActionContext.getContext().put(
177: "__richtexteditorFolderPath", getCurrentFolder());
178: ActionContext.getContext().put(
179: "__richtexteditorServerPath",
180: calculateServerPath(getServerPath(),
181: getCurrentFolder(), getType()));
182:
183: CreateFolderResult createFolderResult = createFolder(
184: getCurrentFolder(), getType(), getNewFolderName());
185:
186: ActionContext.getContext().put(
187: "__richtexteditorCreateFolder", createFolderResult);
188:
189: return CREATE_FOLDER;
190: } else if ("FileUpload".equals(getCommand())) {
191: _log.debug("Command " + getCommand()
192: + " detected \n\t type=" + getType()
193: + "\n\t folderPath=" + getCurrentFolder()
194: + "\n\t newFileFileName=" + getNewFileFileName()
195: + "\n\t newFileContentType="
196: + getNewFileContentType() + "\n\t newFile="
197: + getNewFile());
198:
199: ActionContext.getContext().put("__richtexteditorCommand",
200: getCommand());
201:
202: FileUploadResult fileUploadResult = fileUpload(
203: getCurrentFolder(), getType(),
204: getNewFileFileName(), getNewFileContentType(),
205: getNewFile());
206:
207: ActionContext.getContext().put(
208: "__richtexteditorFileUpload", fileUploadResult);
209:
210: return FILE_UPLOAD;
211: } else {
212: _log.debug("Unknown Command " + getCommand()
213: + " detected \n\t type=" + getType()
214: + "\n\t folderPath=" + getCurrentFolder());
215:
216: unknownCommand(getCommand(), getCurrentFolder(), getType(),
217: getNewFileFileName(), getNewFileContentType(),
218: getNewFile());
219:
220: return ERROR;
221: }
222: }
223:
224: /**
225: * <!-- START SNIPPET: upload -->
226: *
227: * The method that does the functionality when the richtexteditor 'upload' command is '/webwork/richtexteditor/data/'
228: * issued.
229: *
230: * <p/>
231: *
232: * It return a result name of 'fileUpload'.
233: *
234: * <!-- END SNIPPET: upload -->
235: *
236: * @return result name
237: * @throws Exception
238: */
239: public String upload() throws Exception {
240: _log.debug("Upload detected \n\t type=" + getType()
241: + "\n\t newFileFileName=" + getNewFileFileName()
242: + "\n\t newFileContentType=" + getNewFileContentType()
243: + "\n\t newFile=" + getNewFile());
244:
245: FileUploadResult fileUploadResult = fileUpload("/", getType(),
246: getNewFileFileName(), getNewFileContentType(),
247: getNewFile());
248:
249: ActionContext.getContext().put("__richtexteditorFileUpload",
250: fileUploadResult);
251:
252: return FILE_UPLOAD;
253: }
254:
255: /**
256: * <!-- START SNIPPET: calculateServerPath -->
257: *
258: * This method should return the url that could be used to access the server-side
259: * object. For example, if this methods return '/aaa/bbb/ccc', the say, server-side image
260: * selected is myImage.gif, then the image tag generated might be something like
261: *
262: * <pre>
263: * <img src='/aaa/bbb/ccc/myImage.gif' .... /<
264: * </pre>
265: *
266: * For example, if the folderPath is '/folder1' and the type is 'Image', the
267: * calculated server path might be '/aaa/bbb/ccc/Image/folder1/' such that if the
268: * image is 'myImage.gif' the src attribute of the image tag might be
269: * '/aaa/bbb/ccc/Image/folder1/myImage.gif'.
270: *
271: * <!-- END SNIPPET: calculateServerPath -->
272: *
273: * @param serverPath the server path provided through setServerPath (by default it is
274: * @param folderPath the current folder path requested
275: * @param type the type (Image, Link or Flash)
276: * @return calculated server path
277: * @throws Exception
278: */
279: protected abstract String calculateServerPath(String serverPath,
280: String folderPath, String type) throws Exception;
281:
282: /**
283: * <!-- START SNIPPET: getFolders -->
284: *
285: * Method that gets called when a 'GetFolders' command is issued by the rich text editor.
286: * This method should search the server-side and return an Folder[] that the server side has.
287: *
288: * <p/>
289: *
290: * The folder path queried by the rich text editor is <code>folderPath</code>. While the
291: * type of could be one of 'Image', 'Link' or 'Flash'.
292: *
293: * <!-- END SNIPPET: getFolders -->
294: *
295: * @param virtualFolderPath
296: * @param type
297: * @return An array of Folders
298: * @throws Exception
299: */
300: protected abstract Folder[] getFolders(String virtualFolderPath,
301: String type) throws Exception;
302:
303: /**
304: * <!-- START SNIPPET: getFoldersAndFiles -->
305: *
306: * Method that gets called when a 'GetFoldersAndFiles' command is issued by the rich text
307: * editor. This method should typically search the server-side for files and folders under the
308: * provided virtualFolderPath and return a FoldersAndFiles object.
309: *
310: * <p/>
311: *
312: * The folder path queried by the richtexted editor is <code>virtualFolderPath</code>.
313: * While the type could be one of 'Image', 'Link' or 'Flash'.
314: *
315: * <!-- END SNIPPET: getFoldersAndFiles -->
316: *
317: * @param virtualFolderPath
318: * @param type
319: * @return FoldersAndFiles
320: * @throws Exception
321: */
322: protected abstract FoldersAndFiles getFoldersAndFiles(
323: String virtualFolderPath, String type) throws Exception;
324:
325: /**
326: * <!-- START SNIPPET: createFolder -->
327: *
328: * Method that gets called when a 'CreateFolder' command is issued by the rich text
329: * editor. This method would typically create a folder in the server-side if it is
330: * allowed to do so and return the result through CreateFolderResult object. CreateFolderResult
331: * contains static methods to return the available results.
332: *
333: * <p/>
334: *
335: * The folder path queried by the richtexted editor is <code>virtualFolderPath</code>.
336: * While the type could be one of 'Image', 'Link' or 'Flash'. The new folder name
337: * to be created is <code>newFolderName</code>.
338: *
339: * <!-- END SNIPPET: createFolder -->
340: *
341: *
342: * @param virtualFolderPath
343: * @param type
344: * @param newFolderName
345: * @return CreateFolderResult
346: * @throws Exception
347: */
348: protected abstract CreateFolderResult createFolder(
349: String virtualFolderPath, String type, String newFolderName)
350: throws Exception;
351:
352: /**
353: * <!-- START SNIPPET: fileUpload -->
354: *
355: * Method that gets called when a 'FileUpload' command is issued by the rich text
356: * editor. This method would typically handle the file upload and return a
357: * FileUploadResult object. FileUploadResult contains only static methods that
358: * could create the available results.
359: *
360: * <p/>
361: *
362: * The folder path queried by the richtexted editor is <code>virtualFolderPath</code>.
363: * While the type could be one of 'Image', 'Link' or 'Flash'. The upload file name
364: * is <code>filename</code> while its content type is <code>conetnType</code> and
365: * its content could be read off the <code>newFile</code> object.
366: *
367: * <!-- END SNIPPET: fileUpload -->
368: *
369: * @param virtualFolderPath
370: * @param type
371: * @param filename
372: * @param contentType
373: * @param newFile
374: * @return FileUploadResult
375: * @throws Exception
376: */
377: protected abstract FileUploadResult fileUpload(
378: String virtualFolderPath, String type, String filename,
379: String contentType, java.io.File newFile) throws Exception;
380:
381: /**
382: * <!-- START SNIPPET: unknownCommand -->
383: *
384: * Methods that get called when an unrecognized command is issued. Typical usage would
385: * be to log an error message.
386: *
387: * <!-- END SNIPPET: unknownCommand -->
388: *
389: * @param command
390: * @param virtualFolderPath
391: * @param type
392: * @param filename
393: * @param contentType
394: * @param newFile
395: * @throws Exception
396: */
397: protected abstract void unknownCommand(String command,
398: String virtualFolderPath, String type, String filename,
399: String contentType, java.io.File newFile) throws Exception;
400:
401: // === FileUpload Details ======
402: public java.io.File getNewFile() {
403: return _newFile;
404: }
405:
406: public void setNewFile(java.io.File newFile) {
407: _newFile = newFile;
408: }
409:
410: public String getNewFileFileName() {
411: return _newFileFileName;
412: }
413:
414: public void setNewFileFileName(String newFileFileName) {
415: _newFileFileName = newFileFileName;
416: }
417:
418: public String getNewFileContentType() {
419: return _newFileContentType;
420: }
421:
422: public void setNewFileContentType(String newFileContentType) {
423: _newFileContentType = newFileContentType;
424: }
425:
426: // === Browse / Upload details
427: public String getCommand() {
428: return _command;
429: }
430:
431: public void setCommand(String command) {
432: _command = command;
433: }
434:
435: public String getType() {
436: return _type;
437: }
438:
439: public void setType(String type) {
440: _type = type;
441: }
442:
443: public String getCurrentFolder() {
444: return _currentFolder;
445: }
446:
447: public void setCurrentFolder(String currentFolder) {
448: _currentFolder = currentFolder;
449: }
450:
451: public String getNewFolderName() {
452: return _newFolderName;
453: }
454:
455: public void setNewFolderName(String newFolderName) {
456: _newFolderName = newFolderName;
457: }
458:
459: public String getServerPath() {
460: return _serverPath;
461: }
462:
463: public void setServerPath(String serverPath) {
464: _serverPath = serverPath;
465: }
466:
467: public void setServletRequest(HttpServletRequest request) {
468: _request = request;
469: }
470:
471: public void setServletResponse(HttpServletResponse response) {
472: _response = response;
473: }
474:
475: // ============================================================
476: // === inner class ( Folder ) =================================
477: // ============================================================
478:
479: /**
480: * <!-- START SNIPPET: folder -->
481: *
482: * Class represents a Folder in the server side.
483: *
484: * <!-- START SNIPPET: folder -->
485: *
486: * @author tm_jee
487: * @version $Date: 2006-03-08 21:22:35 +0100 (Wed, 08 Mar 2006) $ $Id: AbstractRichtexteditorConnector.java 2338 2006-03-08 20:22:35Z rainerh $
488: * @see AbstractRichtexteditorConnector#getFolders(String, String)
489: * @see AbstractRichtexteditorConnector#getFoldersAndFiles(String, String)
490: * @see AbstractRichtexteditorConnector.FoldersAndFiles
491: */
492: public static class Folder implements Serializable {
493: private String foldername;
494:
495: public Folder(String foldername) {
496: assert (foldername != null);
497: this .foldername = foldername;
498: }
499:
500: public String getFoldername() {
501: return this .foldername;
502: }
503: }
504:
505: // ============================================================
506: // === inner class ( File ) ===================================
507: // ============================================================
508:
509: /**
510: * <!-- START SNIPPET: File -->
511: *
512: * Class represens a File in the server side.
513: *
514: * <!-- END SNIPPET: File -->
515: *
516: * @author tm_jee
517: * @version $Date: 2006-03-08 21:22:35 +0100 (Wed, 08 Mar 2006) $ $Id: AbstractRichtexteditorConnector.java 2338 2006-03-08 20:22:35Z rainerh $
518: * @see AbstractRichtexteditorConnector#getFoldersAndFiles(String, String)
519: * @see AbstractRichtexteditorConnector.FoldersAndFiles
520: */
521: public static class File implements Serializable {
522: private String filename;
523: private long sizeInKb;
524:
525: public File(String filename, long sizeInKb) {
526: assert (filename != null);
527: this .filename = filename;
528: this .sizeInKb = sizeInKb;
529: }
530:
531: public String getFilename() {
532: return this .filename;
533: }
534:
535: public long getSizeInKb() {
536: return this .sizeInKb;
537: }
538: }
539:
540: // ============================================================
541: // === inner class (FolderAndFiles) ===========================
542: // ============================================================
543:
544: /**
545: * <!-- START SNIPPET: foldersandfiles -->
546: *
547: * Represents the files and folders to be returned from the server-side.
548: *
549: * <!-- END SNIPPET: foldersandfiles -->
550: *
551: * @author tm_jee
552: * @version $Date: 2006-03-08 21:22:35 +0100 (Wed, 08 Mar 2006) $ $Id: AbstractRichtexteditorConnector.java 2338 2006-03-08 20:22:35Z rainerh $
553: * @see AbstractRichtexteditorConnector#getFoldersAndFiles(String, String)
554: * @see AbstractRichtexteditorConnector.File
555: * @see AbstractRichtexteditorConnector.Folder
556: */
557: public static class FoldersAndFiles implements Serializable {
558: private Folder[] folders;
559: private File[] files;
560:
561: public FoldersAndFiles(Folder[] folders, File[] files) {
562: this .folders = folders;
563: this .files = files;
564: }
565:
566: public Folder[] getFolders() {
567: return this .folders;
568: }
569:
570: public File[] getFiles() {
571: return this .files;
572: }
573: }
574:
575: // ===========================================================
576: // ==== inner class (CreateFolderResult) =====================
577: // ===========================================================
578:
579: /**
580: * <!-- START SNIPPET: createfolderresult -->
581: *
582: * Represensts the result of a server-side 'CreateFolder' command call. It
583: * acts like a static factory containing only static methods to create the
584: * possible results which are:
585: *
586: * <ul>
587: * <li>no errors</li>
588: * <li>folder already exists</li>
589: * <li>invalidFolderName</li>
590: * <li>no permission</li>
591: * <li>unknown error</li>
592: * </ul>
593: *
594: * <!-- END SNIPPET: createfolderresult -->
595: *
596: * @author tm_jee
597: * @version $Date: 2006-03-08 21:22:35 +0100 (Wed, 08 Mar 2006) $ $Id: AbstractRichtexteditorConnector.java 2338 2006-03-08 20:22:35Z rainerh $
598: * @see AbstractRichtexteditorConnector#createFolder(String, String, String)
599: */
600: public static class CreateFolderResult implements Serializable {
601: public static final CreateFolderResult NO_ERRORS = new CreateFolderResult(
602: "0");
603: public static final CreateFolderResult FOLDER_ALREADY_EXISTS = new CreateFolderResult(
604: "101");
605: public static final CreateFolderResult INVALID_FOLDER_NAME = new CreateFolderResult(
606: "102");
607: public static final CreateFolderResult NO_PERMISSION = new CreateFolderResult(
608: "103");
609: public static final CreateFolderResult UNKNOWN_ERROR = new CreateFolderResult(
610: "110");
611:
612: private String code;
613:
614: private CreateFolderResult(String code) {
615: this .code = code;
616: }
617:
618: public String getCode() {
619: return this .code;
620: }
621:
622: public static CreateFolderResult noErrors() {
623: return NO_ERRORS;
624: }
625:
626: public static CreateFolderResult folderAlreadyExists() {
627: return FOLDER_ALREADY_EXISTS;
628: }
629:
630: public static CreateFolderResult invalidFolderName() {
631: return INVALID_FOLDER_NAME;
632: }
633:
634: public static CreateFolderResult noPermission() {
635: return NO_PERMISSION;
636: }
637:
638: public static CreateFolderResult unknownError() {
639: return UNKNOWN_ERROR;
640: }
641: }
642:
643: // =============================================================
644: // === inner class (FileUploadResult) ==========================
645: // =============================================================
646:
647: /**
648: * <!-- START SNIPPET: fileuploadresult -->
649: *
650: * Represents the result of a server-side 'FileUpload' command call. It
651: * acts like a static factory containing only static methods to create the possible
652: * results which are:
653: *
654: * <ul>
655: * <li>upload complete</li>
656: * <li>invalid file </li>
657: * <li>upload complete with file name changed</li>
658: * </ul>
659: *
660: * <!-- END SNIPPET: fileuploadresult -->
661: *
662: * @author tm_jee
663: * @version $Date: 2006-03-08 21:22:35 +0100 (Wed, 08 Mar 2006) $ $Id: AbstractRichtexteditorConnector.java 2338 2006-03-08 20:22:35Z rainerh $
664: * @see AbstractRichtexteditorConnector#fileUpload(String, String, String, String, java.io.File)
665: */
666: public static class FileUploadResult implements Serializable {
667: private static final FileUploadResult UPLOAD_COMPLETED = new FileUploadResult(
668: "0");
669: private static final FileUploadResult INVALID_FILE = new FileUploadResult(
670: "202");
671:
672: private String code;
673: private String filename;
674:
675: private FileUploadResult(String code) {
676: this (code, null);
677: }
678:
679: private FileUploadResult(String code, String newFilename) {
680: this .code = code;
681: filename = newFilename;
682: }
683:
684: public String getCode() {
685: return code;
686: }
687:
688: public String getFilename() {
689: return filename;
690: }
691:
692: public static FileUploadResult uploadComplete() {
693: return UPLOAD_COMPLETED;
694: }
695:
696: public static FileUploadResult invalidFile() {
697: return INVALID_FILE;
698: }
699:
700: public static FileUploadResult uploadCompleteWithFilenamChanged(
701: String newFilename) {
702: assert (newFilename != null);
703: return new FileUploadResult("201", newFilename);
704: }
705: }
706:
707: }
|