001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.workplace.administration;
029
030import org.opencms.file.CmsResource;
031import org.opencms.jsp.CmsJspActionElement;
032import org.opencms.main.CmsException;
033import org.opencms.main.CmsIllegalArgumentException;
034import org.opencms.main.OpenCms;
035import org.opencms.util.CmsRfsException;
036import org.opencms.util.CmsStringUtil;
037import org.opencms.workplace.CmsDialog;
038import org.opencms.workplace.CmsWorkplaceSettings;
039
040import java.io.File;
041import java.io.FileNotFoundException;
042import java.io.FileOutputStream;
043import java.io.IOException;
044import java.io.OutputStream;
045import java.util.Iterator;
046
047import javax.servlet.ServletException;
048import javax.servlet.http.HttpServletRequest;
049import javax.servlet.http.HttpServletResponse;
050import javax.servlet.jsp.JspException;
051import javax.servlet.jsp.JspWriter;
052import javax.servlet.jsp.PageContext;
053
054import org.apache.commons.fileupload.FileItem;
055
056/**
057 * Abstract class to upload a zip file containing VFS resources with HTTP upload.<p>
058 *
059 * @since 6.0.0
060 */
061public abstract class A_CmsImportFromHttp extends CmsDialog {
062
063    /** The dialog type. */
064    public static final String DIALOG_TYPE = "ImportHttp";
065
066    /** Import file request parameter. */
067    public static final String PARAM_IMPORTFILE = "importfile";
068
069    /** The exception thrown if an error occurs. */
070    private CmsException m_exception;
071
072    /** The import file name that is uploaded. */
073    private String m_paramImportfile;
074
075    /**
076     * Public constructor with JSP action element.<p>
077     *
078     * @param jsp an initialized JSP action element
079     */
080    public A_CmsImportFromHttp(CmsJspActionElement jsp) {
081
082        super(jsp);
083    }
084
085    /**
086     * Public constructor with JSP variables.<p>
087     *
088     * @param context the JSP page context
089     * @param req the JSP request
090     * @param res the JSP response
091     */
092    public A_CmsImportFromHttp(PageContext context, HttpServletRequest req, HttpServletResponse res) {
093
094        this(new CmsJspActionElement(context, req, res));
095    }
096
097    /**
098     * Performs the import operation after "OK" has been pressed.<p>
099     *
100     * @throws IOException in case of errors forwarding to the required result page
101     * @throws ServletException in case of errors forwarding to the required result page
102     */
103    public abstract void actionCommit() throws IOException, ServletException;
104
105    /**
106     * Performs the dialog actions depending on the initialized action and displays the dialog form.<p>
107     *
108     * @throws JspException if dialog actions fail
109     * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page
110     * @throws ServletException in case of errors forwarding to the required result page
111     */
112    public void displayDialog() throws IOException, JspException, ServletException {
113
114        switch (getAction()) {
115
116            case ACTION_CANCEL:
117                // ACTION: cancel button pressed
118                actionCloseDialog();
119                break;
120
121            case ACTION_OK:
122                // ACTION: ok button pressed
123                setParamAction(DIALOG_OK);
124                actionCommit();
125                if (getException() == null) {
126                    // file successfully copied to server
127                    break;
128                }
129
130                //$FALL-THROUGH$
131            case ACTION_DEFAULT:
132            default:
133                // ACTION: show dialog (default)
134                setParamAction(DIALOG_OK);
135                JspWriter out = getJsp().getJspContext().getOut();
136                out.print(defaultActionHtml());
137        }
138    }
139
140    /**
141     * Gets the return uri for this dialog.<p>
142     *
143     * @return return uri for this dialog
144     */
145    public abstract String getDialogReturnUri();
146
147    /**
148     * Gets the localized import message text for the input form.<p>
149     *
150     * @return localized import message text  for the input form
151     */
152    public abstract String getImportMessage();
153
154    /**
155     * Returns the import file name that is uploaded.<p>
156     *
157     * @return the import file name that is uploaded
158     */
159    public String getParamImportfile() {
160
161        return m_paramImportfile;
162    }
163
164    /**
165     * Gets the localized start text for the input form.<p>
166     *
167     * @return localized start text for the input form
168     */
169    public abstract String getStarttext();
170
171    /**
172     * Sets the import file name that is uploaded.<p>
173     *
174     * @param importfile the import file name that is uploaded
175     */
176    public void setParamImportfile(String importfile) {
177
178        m_paramImportfile = importfile;
179    }
180
181    /**
182     * Html code for the additional parameters.<p>
183     *
184     * @return html code
185     */
186    protected String getAdditionalParameters() {
187
188        // do nothing
189        return "";
190    }
191
192    /**
193     * Gets a database import file from the client and copies it to the server.<p>
194     *
195     * @param destination the destination of the file on the server
196     *
197     * @return the name of the file or null if something went wrong when importing the file
198     *
199     * @throws CmsIllegalArgumentException if the specified file name is invalid
200     * @throws CmsRfsException if generating folders or files on the server fails
201     */
202    protected String copyFileToServer(String destination) throws CmsIllegalArgumentException, CmsRfsException {
203
204        // get the file item from the multipart request
205        Iterator<FileItem> i = getMultiPartFileItems().iterator();
206        FileItem fi = null;
207        while (i.hasNext()) {
208            fi = i.next();
209            if (fi.getName() != null) {
210                // found the file object, leave iteration
211                break;
212            } else {
213                // this is no file object, check next item
214                continue;
215            }
216        }
217
218        String fileName = null;
219
220        if ((fi != null) && CmsStringUtil.isNotEmptyOrWhitespaceOnly(fi.getName())) {
221            // file name has been specified, upload the file
222            fileName = fi.getName();
223            byte[] content = fi.get();
224            fi.delete();
225            // get the file name without folder information
226            fileName = CmsResource.getName(fileName.replace('\\', '/'));
227            // first create the folder if it does not exist
228            File discFolder = new File(
229                OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf(
230                    OpenCms.getSystemInfo().getPackagesRfsPath() + File.separator));
231            if (!discFolder.exists()) {
232                if (!discFolder.mkdir()) {
233                    throw new CmsRfsException(Messages.get().container(Messages.ERR_FOLDER_NOT_CREATED_0));
234                }
235            }
236            // write the file into the packages folder of the OpenCms server
237            File discFile = new File(
238                OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf(destination + File.separator + fileName));
239            try {
240                // write the new file to disk
241                OutputStream s = new FileOutputStream(discFile);
242                s.write(content);
243                s.close();
244            } catch (FileNotFoundException e) {
245                throw new CmsRfsException(Messages.get().container(Messages.ERR_FILE_NOT_FOUND_1, fileName, e));
246            } catch (IOException e) {
247                throw new CmsRfsException(Messages.get().container(Messages.ERR_FILE_NOT_WRITTEN_0, e));
248            }
249        } else {
250            // no file name has been specified, throw exception
251            throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_FILE_NOT_SPECIFIED_0));
252        }
253        // set the request parameter to the name of the import file
254        setParamImportfile(fileName);
255        return fileName;
256    }
257
258    /**
259     * Creates the HTML for the error message if validation errors were found.<p>
260     *
261     * @return the HTML for the error message if validation errors were found
262     */
263    protected String createDialogErrorMessage() {
264
265        if (getException() != null) {
266            StringBuffer result = new StringBuffer(8);
267            result.append(dialogBlockStart(""));
268            result.append("<table border=\"0\">\n");
269            result.append("<tr><td><img src=\"");
270            result.append(getSkinUri()).append("commons/");
271            result.append("error.png");
272            result.append("\" border=\"0\" alt=\"\"></td><td class=\"xmlTdError maxwidth\">");
273            Throwable t = getException();
274            while (t != null) {
275                result.append(t.getLocalizedMessage());
276                t = t.getCause();
277                if (t != null) {
278                    result.append("<br>");
279                }
280            }
281            result.append("</table>\n");
282            result.append(dialogBlockEnd());
283            return result.toString();
284        }
285        return "";
286    }
287
288    /**
289     * Returns the HTML to build the input form of the upload dialog.<p>
290     *
291     * @return the HTML to build the input form of the upload dialog
292     */
293    protected String defaultActionHtml() {
294
295        StringBuffer result = new StringBuffer(32);
296
297        result.append(htmlStart());
298        result.append(bodyStart(null));
299        result.append(dialogStart());
300        result.append(dialogContentStart(""));
301        result.append("<form name=\"main\" class=\"nomargin\" action=\"");
302        result.append(getJsp().link(getDialogReturnUri()));
303        result.append("\" method=\"post\" onsubmit=\"submitAction('");
304        result.append(DIALOG_OK);
305        result.append("', null, 'main');\" enctype=\"multipart/form-data\">\n");
306        result.append(paramsAsHidden());
307        if (getParamFramename() == null) {
308            result.append("<input type=\"hidden\" name=\"");
309            result.append(PARAM_FRAMENAME);
310            result.append("\" value=\"\">");
311        }
312        result.append(createDialogErrorMessage());
313        result.append(dialogBlockStart(getStarttext()));
314        result.append("<table border=\"0\" width=\"100%\">\n");
315        result.append("<tr>\n\t<td style=\"white-space: nowrap;\" unselectable=\"on\">");
316        result.append(getImportMessage());
317        result.append(":</td>\n");
318        result.append("\t<td class=\"maxwidth\">");
319        result.append("<input type=\"file\" name=\"");
320        result.append(PARAM_IMPORTFILE);
321        result.append("\" class=\"maxwidth\" accept=\"application/zip\">");
322        result.append("</td>\n</tr>");
323        result.append(getAdditionalParameters());
324        result.append("</table>\n");
325        result.append(dialogBlockEnd());
326
327        result.append(dialogContentEnd());
328        result.append(dialogButtonsOkCancel());
329        result.append("</form>\n");
330        result.append(dialogEnd());
331        result.append(bodyEnd());
332        result.append(htmlEnd());
333        return result.toString();
334    }
335
336    /**
337     * Returns the dialog exception.<p>
338     *
339     * @return the dialog exception
340     */
341    protected CmsException getException() {
342
343        return m_exception;
344    }
345
346    /**
347     * @see org.opencms.workplace.CmsWorkplace#initMessages()
348     */
349    @Override
350    protected abstract void initMessages();
351
352    /**
353     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
354     */
355    @Override
356    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
357
358        // set the dialog type
359        setParamDialogtype(getClass().getName());
360
361        // fill the parameter values in the get/set methods
362        fillParamValues(request);
363
364        // set the action for the JSP switch
365        if (DIALOG_OK.equals(getParamAction())) {
366            // ok button pressed
367            setAction(ACTION_OK);
368        } else if (DIALOG_CANCEL.equals(getParamAction())) {
369            // cancel button pressed
370            setAction(ACTION_CANCEL);
371        } else {
372            // first dialog call, set the default action
373            setAction(ACTION_DEFAULT);
374        }
375    }
376
377    /**
378     * Sets the dialog exception.<p>
379     *
380     * @param exception the dialog exception
381     */
382    protected void setException(CmsException exception) {
383
384        m_exception = exception;
385    }
386}