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.tools.modules;
029
030import org.opencms.configuration.CmsConfigurationException;
031import org.opencms.jsp.CmsJspActionElement;
032import org.opencms.main.CmsRuntimeException;
033import org.opencms.main.OpenCms;
034import org.opencms.module.CmsModule;
035import org.opencms.module.CmsModuleDependency;
036import org.opencms.module.CmsModuleImportExportHandler;
037import org.opencms.module.CmsModuleManager;
038import org.opencms.widgets.CmsDisplayWidget;
039import org.opencms.widgets.CmsSelectWidget;
040import org.opencms.widgets.CmsSelectWidgetOption;
041import org.opencms.workplace.CmsWidgetDialog;
042import org.opencms.workplace.CmsWidgetDialogParameter;
043import org.opencms.workplace.CmsWorkplaceSettings;
044import org.opencms.workplace.tools.CmsToolDialog;
045import org.opencms.workplace.tools.CmsToolManager;
046
047import java.io.File;
048import java.io.IOException;
049import java.text.Collator;
050import java.util.ArrayList;
051import java.util.Collections;
052import java.util.Comparator;
053import java.util.HashMap;
054import java.util.List;
055import java.util.Map;
056
057import javax.servlet.ServletException;
058import javax.servlet.http.HttpServletRequest;
059import javax.servlet.http.HttpServletResponse;
060import javax.servlet.jsp.PageContext;
061
062/**
063 * Class to upload a module from the server.<p>
064 *
065 * @since 6.0.0
066 */
067public class CmsModulesUploadFromServer extends CmsWidgetDialog {
068
069    /**
070     * A <code>{@link Comparator}</code> for <code>{@link CmsSelectWidgetOption}</code> instances.<p>
071     *
072     * @since 7.0.3
073     *
074     */
075    protected class ComparatorSelectWidgetOption implements Comparator {
076
077        /** Collator used / wrapped. */
078        private Collator m_collator = Collator.getInstance(getLocale());
079
080        /**
081         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
082         */
083        public int compare(Object arg0, Object arg1) {
084
085            CmsSelectWidgetOption o1 = (CmsSelectWidgetOption)arg0;
086            CmsSelectWidgetOption o2 = (CmsSelectWidgetOption)arg1;
087            return m_collator.compare(o1.getOption(), o2.getOption());
088        }
089
090    }
091
092    /** The dialog type. */
093    public static final String DIALOG_TYPE = "ModulesUploadServer";
094
095    /** The import action. */
096    protected static final String IMPORT_ACTION_REPORT = "/system/workplace/admin/modules/reports/import.jsp";
097
098    /** Defines which pages are valid for this dialog. */
099    public static final String[] PAGES = {"page1"};
100
101    /** Modulename parameter. */
102    public static final String PARAM_MODULENAME = "modulename";
103
104    /** The replace action. */
105    protected static final String REPLACE_ACTION_REPORT = "/system/workplace/admin/modules/reports/replace.jsp";
106
107    /** Modulename. */
108    private String m_moduleupload;
109
110    /**
111     * Public constructor with JSP action element.<p>
112     *
113     * @param jsp an initialized JSP action element
114     */
115    public CmsModulesUploadFromServer(CmsJspActionElement jsp) {
116
117        super(jsp);
118    }
119
120    /**
121     * Public constructor with JSP variables.<p>
122     *
123     * @param context the JSP page context
124     * @param req the JSP request
125     * @param res the JSP response
126     */
127    public CmsModulesUploadFromServer(PageContext context, HttpServletRequest req, HttpServletResponse res) {
128
129        this(new CmsJspActionElement(context, req, res));
130    }
131
132    /**
133     * @see org.opencms.workplace.CmsWidgetDialog#actionCommit()
134     */
135    @Override
136    public void actionCommit() throws IOException, ServletException {
137
138        List errors = new ArrayList();
139        CmsModule module = null;
140        try {
141            String importpath = OpenCms.getSystemInfo().getPackagesRfsPath();
142            importpath = OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf(
143                importpath + "modules/" + m_moduleupload);
144            module = CmsModuleImportExportHandler.readModuleFromImport(importpath);
145
146            // check if all dependencies are fulfilled
147            List dependencies = OpenCms.getModuleManager().checkDependencies(
148                module,
149                CmsModuleManager.DEPENDENCY_MODE_IMPORT);
150            if (!dependencies.isEmpty()) {
151                StringBuffer dep = new StringBuffer(32);
152                for (int i = 0; i < dependencies.size(); i++) {
153                    CmsModuleDependency dependency = (CmsModuleDependency)dependencies.get(i);
154                    dep.append("\n - ");
155                    dep.append(dependency.getName());
156                    dep.append(" (Version: ");
157                    dep.append(dependency.getVersion());
158                    dep.append(")");
159                }
160                errors.add(
161                    new CmsRuntimeException(
162                        Messages.get().container(
163                            Messages.ERR_ACTION_MODULE_DEPENDENCY_2,
164                            m_moduleupload,
165                            new String(dep))));
166            }
167
168        } catch (CmsConfigurationException e) {
169            errors.add(
170                new CmsRuntimeException(
171                    Messages.get().container(Messages.ERR_ACTION_MODULE_UPLOAD_1, m_moduleupload),
172                    e));
173        }
174
175        if ((module != null) && errors.isEmpty()) {
176
177            // refresh the list
178            Map objects = (Map)getSettings().getListObject();
179            if (objects != null) {
180                objects.remove(CmsModulesList.class.getName());
181            }
182
183            // redirect
184            Map param = new HashMap();
185            param.put(CmsModulesList.PARAM_MODULE, m_moduleupload);
186            param.put(PARAM_STYLE, CmsToolDialog.STYLE_NEW);
187            param.put(PARAM_CLOSELINK, CmsToolManager.linkForToolPath(getJsp(), "/modules"));
188            if (OpenCms.getModuleManager().hasModule(module.getName())) {
189                param.put(PARAM_MODULENAME, module.getName());
190                getToolManager().jspForwardPage(this, REPLACE_ACTION_REPORT, param);
191            } else {
192                getToolManager().jspForwardPage(this, IMPORT_ACTION_REPORT, param);
193            }
194        }
195
196        // set the list of errors to display when saving failed
197        setCommitErrors(errors);
198    }
199
200    /**
201     * Creates the dialog HTML for all defined widgets of the named dialog (page).<p>
202     *
203     * @param dialog the dialog (page) to get the HTML for
204     * @return the dialog HTML for all defined widgets of the named dialog (page)
205     */
206    @Override
207    protected String createDialogHtml(String dialog) {
208
209        StringBuffer result = new StringBuffer(1024);
210
211        // create table
212        result.append(createWidgetTableStart());
213
214        // show error header once if there were validation errors
215        result.append(createWidgetErrorHeader());
216
217        if (dialog.equals(PAGES[0])) {
218            result.append(dialogBlockStart(key("label.uploadfromserver")));
219            result.append(createWidgetTableStart());
220            result.append(createDialogRowsHtml(0, 0));
221            result.append(createWidgetTableEnd());
222            result.append(dialogBlockEnd());
223        }
224
225        // close table
226        result.append(createWidgetTableEnd());
227
228        return result.toString();
229    }
230
231    /**
232     * Creates the list of widgets for this dialog.<p>
233     */
234    @Override
235    protected void defineWidgets() {
236
237        List selectOptions = getModulesFromServer();
238
239        if (selectOptions.isEmpty()) {
240            // no import modules available, display message
241            addWidget(
242                new CmsWidgetDialogParameter(
243                    this,
244                    "moduleupload",
245                    PAGES[0],
246                    new CmsDisplayWidget(key(Messages.GUI_MODULES_IMPORT_NOT_AVAILABLE_0))));
247        } else {
248            // add the file select box widget
249            addWidget(new CmsWidgetDialogParameter(this, "moduleupload", PAGES[0], new CmsSelectWidget(selectOptions)));
250        }
251    }
252
253    /**
254     * Returns the list of all modules available on the server in prepared CmsSelectWidgetOption objects.<p>
255     *
256     * @return List of module names in CmsSelectWidgetOption objects
257     */
258    private List getModulesFromServer() {
259
260        List result = new ArrayList();
261
262        // get the systems-exportpath
263        String exportpath = OpenCms.getSystemInfo().getPackagesRfsPath();
264        exportpath = OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf(exportpath + "modules");
265        File folder = new File(exportpath);
266
267        // get a list of all files
268        String[] list = folder.list();
269        for (int i = 0; i < list.length; i++) {
270            try {
271                File diskFile = new File(exportpath, list[i]);
272                // check if it is a file and ends with zip -> this is a module
273                if (diskFile.isFile() && diskFile.getName().endsWith(".zip")) {
274                    result.add(new CmsSelectWidgetOption(diskFile.getName()));
275                } else
276                    if (diskFile.isDirectory() && ((new File(diskFile + File.separator + "manifest.xml")).exists())) {
277                    // this is a folder with manifest file -> this a module
278                    result.add(new CmsSelectWidgetOption(diskFile.getName()));
279                }
280            } catch (Throwable t) {
281                // ignore and continue
282            }
283        }
284
285        Collections.sort(result, new ComparatorSelectWidgetOption());
286        return result;
287    }
288
289    /**
290     * Gets the module parameter.<p>
291     *
292     * @return the module parameter
293     */
294    public String getModuleupload() {
295
296        return m_moduleupload;
297    }
298
299    /**
300     * @see org.opencms.workplace.CmsWidgetDialog#getPageArray()
301     */
302    @Override
303    protected String[] getPageArray() {
304
305        return PAGES;
306    }
307
308    /**
309     * @see org.opencms.workplace.CmsWorkplace#initMessages()
310     */
311    @Override
312    protected void initMessages() {
313
314        // add specific dialog resource bundle
315        addMessages(Messages.get().getBundleName());
316        // add default resource bundles
317        super.initMessages();
318    }
319
320    /**
321     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
322     */
323    @Override
324    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
325
326        // set the dialog type
327        setParamDialogtype(DIALOG_TYPE);
328
329        super.initWorkplaceRequestValues(settings, request);
330
331        // save the current state of the job (may be changed because of the widget values)
332        setDialogObject(m_moduleupload);
333    }
334
335    /**
336     * Sets the module parameter.<p>
337     * @param module the module parameter
338     */
339    public void setModuleupload(String module) {
340
341        m_moduleupload = module;
342    }
343
344}