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.commons;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsProperty;
032import org.opencms.file.CmsPropertyDefinition;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsResourceFilter;
035import org.opencms.file.types.CmsResourceTypePlain;
036import org.opencms.file.types.I_CmsResourceType;
037import org.opencms.jsp.CmsJspActionElement;
038import org.opencms.loader.CmsLoaderException;
039import org.opencms.main.CmsException;
040import org.opencms.main.OpenCms;
041import org.opencms.security.CmsPermissionSet;
042import org.opencms.security.CmsRole;
043import org.opencms.util.CmsStringUtil;
044import org.opencms.workplace.CmsWorkplace;
045import org.opencms.workplace.CmsWorkplaceSettings;
046import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
047import org.opencms.workplace.explorer.CmsNewResource;
048import org.opencms.workplace.list.A_CmsListResourceTypeDialog;
049import org.opencms.workplace.list.CmsListItem;
050import org.opencms.workplace.list.CmsListOrderEnum;
051
052import java.io.IOException;
053import java.util.ArrayList;
054import java.util.List;
055
056import javax.servlet.ServletException;
057import javax.servlet.http.HttpServletRequest;
058import javax.servlet.http.HttpServletResponse;
059import javax.servlet.jsp.JspException;
060import javax.servlet.jsp.PageContext;
061
062/**
063 * The change resource type dialog handles the change of a resource type of a single VFS file.<p>
064 *
065 * The following files use this class:
066 * <ul>
067 * <li>/commons/chtype.jsp
068 * </ul>
069 * <p>
070 *
071 * @since 6.0.0
072 */
073public class CmsChtype extends A_CmsListResourceTypeDialog {
074
075    /** Dialog action: show advanced list (for workplace VFS managers). */
076    public static final int ACTION_ADVANCED = 555;
077
078    /** The dialog type.<p> */
079    public static final String DIALOG_TYPE = "chtype";
080
081    /** Session attribute to store advanced mode. */
082    public static final String SESSION_ATTR_ADVANCED = "ocms_chtype_adv";
083
084    /** Flag indicating if dialog is in advanced mode. */
085    private boolean m_advancedMode;
086
087    /** The available resource types as String, if set. */
088    private String m_availableResTypes;
089
090    /** Flag indicating if resource types to select are limited. */
091    private boolean m_limitedRestypes;
092
093    /**
094     * Public constructor with JSP action element.<p>
095     *
096     * @param jsp an initialized JSP action element
097     */
098    public CmsChtype(CmsJspActionElement jsp) {
099
100        super(
101            jsp,
102            A_CmsListResourceTypeDialog.LIST_ID,
103            Messages.get().container(Messages.GUI_CHTYPE_PLEASE_SELECT_0),
104            A_CmsListResourceTypeDialog.LIST_COLUMN_NAME,
105            CmsListOrderEnum.ORDER_ASCENDING,
106            null);
107    }
108
109    /**
110     * Public constructor with JSP variables.<p>
111     *
112     * @param context the JSP page context
113     * @param req the JSP request
114     * @param res the JSP response
115     */
116    public CmsChtype(PageContext context, HttpServletRequest req, HttpServletResponse res) {
117
118        this(new CmsJspActionElement(context, req, res));
119    }
120
121    /**
122     * Uploads the specified file and replaces the VFS file.<p>
123     *
124     * @throws JspException if inclusion of error dialog fails
125     */
126    public void actionChtype() throws JspException {
127
128        int plainId;
129        try {
130            plainId = OpenCms.getResourceManager().getResourceType(
131                CmsResourceTypePlain.getStaticTypeName()).getTypeId();
132        } catch (CmsLoaderException e) {
133            // this should really never happen
134            plainId = CmsResourceTypePlain.getStaticTypeId();
135        }
136        try {
137            int newType = plainId;
138            try {
139                // get new resource type id from request
140                newType = Integer.parseInt(getParamSelectedType());
141            } catch (NumberFormatException nf) {
142                throw new CmsException(Messages.get().container(Messages.ERR_GET_RESTYPE_1, getParamSelectedType()));
143            }
144            // check the resource lock state
145            checkLock(getParamResource());
146            // change the resource type
147            getCms().chtype(getParamResource(), newType);
148            // close the dialog window
149            actionCloseDialog();
150        } catch (Throwable e) {
151            // error changing resource type, show error dialog
152            includeErrorpage(this, e);
153        }
154    }
155
156    /**
157     * @see org.opencms.workplace.list.A_CmsListDialog#actionDialog()
158     */
159    @Override
160    public void actionDialog() throws JspException, ServletException, IOException {
161
162        if (getAction() == ACTION_OK) {
163            actionChtype();
164            return;
165        } else if (getAction() == ACTION_ADVANCED) {
166            refreshList();
167            return;
168        }
169
170        super.actionDialog();
171    }
172
173    /**
174     * Builds a default button row with a continue and cancel button.<p>
175     *
176     * Override this to have special buttons for your dialog.<p>
177     *
178     * @return the button row
179     */
180    @Override
181    public String dialogButtons() {
182
183        return dialogButtonsOkAdvancedCancel(
184            " onclick=\"submitChtype(form);\"",
185            " onclick=\"submitAdvanced(form);\"",
186            null);
187    }
188
189    /**
190     * Builds a button row with an optional "ok", "advanced" and a "cancel" button.<p>
191     *
192     * @param okAttrs optional attributes for the ok button
193     * @param advancedAttrs optional attributes for the advanced button
194     * @param cancelAttrs optional attributes for the cancel button
195     * @return the button row
196     */
197    public String dialogButtonsOkAdvancedCancel(String okAttrs, String advancedAttrs, String cancelAttrs) {
198
199        if (!m_advancedMode && m_limitedRestypes && OpenCms.getRoleManager().hasRole(getCms(), CmsRole.VFS_MANAGER)) {
200            return dialogButtons(
201                new int[] {BUTTON_OK, BUTTON_ADVANCED, BUTTON_CANCEL},
202                new String[] {okAttrs, advancedAttrs, cancelAttrs});
203        } else {
204            return dialogButtonsOkCancel(okAttrs, cancelAttrs);
205        }
206    }
207
208    /**
209     * @see org.opencms.workplace.list.A_CmsListResourceTypeDialog#getParamSelectedType()
210     */
211    @Override
212    public String getParamSelectedType() {
213
214        String item = super.getParamSelectedType();
215        if (CmsStringUtil.isEmptyOrWhitespaceOnly(item)) {
216
217            // determine resource type id of resource to change
218            try {
219                CmsResource res = getCms().readResource(getParamResource(), CmsResourceFilter.ALL);
220                return Integer.toString(res.getTypeId());
221            } catch (CmsException e) {
222                // do nothing
223            }
224        }
225
226        return item;
227    }
228
229    /**
230     * Returns the html code to add directly before the list inside the form element.<p>
231     *
232     * @return the html code to add directly before the list inside the form element
233     */
234    @Override
235    protected String customHtmlBeforeList() {
236
237        StringBuffer result = new StringBuffer(256);
238
239        result.append(dialogBlockStart(null));
240        result.append(key(Messages.GUI_LABEL_TITLE_0));
241        result.append(": ");
242        result.append(getJsp().property("Title", getParamResource(), ""));
243        result.append("<br>");
244        result.append(key(Messages.GUI_LABEL_STATE_0));
245        result.append(": ");
246        try {
247            result.append(getState());
248        } catch (CmsException e) {
249            // not so important ... just go on
250        }
251        result.append("<br>");
252        result.append(key(Messages.GUI_LABEL_PERMALINK_0));
253        result.append(": ");
254        result.append(OpenCms.getLinkManager().getPermalink(getCms(), getParamResource()));
255        result.append(dialogBlockEnd());
256        result.append(dialogSpacer());
257
258        return result.toString();
259    }
260
261    /**
262     * @see org.opencms.workplace.list.A_CmsListDialog#customHtmlStart()
263     */
264    @Override
265    protected String customHtmlStart() {
266
267        StringBuffer result = new StringBuffer(256);
268        result.append(super.customHtmlStart());
269
270        result.append("<script >\n");
271
272        result.append("function submitAdvanced(theForm) {\n");
273        result.append("\ttheForm.action.value = \"" + CmsNewResource.DIALOG_ADVANCED + "\";\n");
274        result.append("\ttheForm.submit();\n");
275        result.append("}\n\n");
276
277        result.append("function submitChtype(theForm) {\n");
278        result.append("\ttheForm.action.value = \"" + DIALOG_OK + "\";\n");
279        result.append("\ttheForm.submit();\n");
280        result.append("}\n\n");
281
282        result.append("</script>");
283
284        return result.toString();
285    }
286
287    /**
288     * @see org.opencms.workplace.list.A_CmsListDialog#getListItems()
289     */
290    @Override
291    protected List<CmsListItem> getListItems() throws CmsException {
292
293        List<CmsListItem> ret = new ArrayList<CmsListItem>();
294
295        // fill the list with available resource types if they are limited
296        List<String> availableResTypes = new ArrayList<String>();
297        if (!m_advancedMode && m_limitedRestypes) {
298            if (m_availableResTypes.indexOf(CmsNewResource.DELIM_PROPERTYVALUES) > -1) {
299                availableResTypes = CmsStringUtil.splitAsList(
300                    m_availableResTypes,
301                    CmsNewResource.DELIM_PROPERTYVALUES,
302                    true);
303            } else {
304                availableResTypes = CmsStringUtil.splitAsList(
305                    m_availableResTypes,
306                    CmsProperty.VALUE_LIST_DELIMITER,
307                    true);
308            }
309        }
310
311        // get current Cms object
312        CmsObject cms = getCms();
313
314        // determine resource type id of resource to change
315        CmsResource res = cms.readResource(getParamResource(), CmsResourceFilter.ALL);
316
317        // get all available explorer type settings
318        List<CmsExplorerTypeSettings> resTypes = OpenCms.getWorkplaceManager().getExplorerTypeSettings();
319        boolean isFolder = res.isFolder();
320
321        // loop through all visible resource types
322        for (int i = 0; i < resTypes.size(); i++) {
323            boolean changeable = false;
324
325            // get explorer type settings for current resource type
326            CmsExplorerTypeSettings settings = resTypes.get(i);
327
328            // only if settings is a real resource type
329            boolean isResourceType;
330            I_CmsResourceType type = new CmsResourceTypePlain();
331            try {
332                type = OpenCms.getResourceManager().getResourceType(settings.getName());
333                isResourceType = true;
334            } catch (CmsLoaderException e) {
335                isResourceType = false;
336            }
337
338            if (isResourceType) {
339                // first check if types are limited
340                if (!m_advancedMode && m_limitedRestypes && (availableResTypes.indexOf(type.getTypeName()) == -1)) {
341                    // this resource type is not in the list of available types, skip it
342                    continue;
343                }
344
345                int resTypeId = OpenCms.getResourceManager().getResourceType(settings.getName()).getTypeId();
346                // determine if this resTypeId is changeable by currentResTypeId
347
348                // changeable is true if current resource is a folder and this resource type also
349                if (isFolder && OpenCms.getResourceManager().getResourceType(resTypeId).isFolder()) {
350                    changeable = true;
351                } else if (!isFolder && !OpenCms.getResourceManager().getResourceType(resTypeId).isFolder()) {
352
353                    // changeable is true if current resource is NOT a folder and this resource type also NOT
354                    changeable = true;
355                }
356
357                if (changeable) {
358
359                    // determine if this resource type is editable for the current user
360                    CmsPermissionSet permissions = settings.getAccess().getPermissions(cms, res);
361                    if (!permissions.requiresWritePermission() || !permissions.requiresControlPermission()) {
362
363                        // skip resource types without required write or create permissions
364                        continue;
365                    }
366
367                    // add found setting to list
368                    CmsListItem item = getList().newItem(Integer.toString(resTypeId));
369                    item.set(LIST_COLUMN_NAME, key(settings.getKey()));
370                    item.set(
371                        LIST_COLUMN_ICON,
372                        "<img src=\""
373                            + getSkinUri()
374                            + CmsWorkplace.RES_PATH_FILETYPES
375                            + settings.getIcon()
376                            + "\" style=\"width: 16px; height: 16px;\" />");
377                    ret.add(item);
378                }
379            }
380        }
381
382        return ret;
383    }
384
385    /**
386     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
387     */
388    @Override
389    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
390
391        // first call of dialog
392        setAction(ACTION_DEFAULT);
393
394        super.initWorkplaceRequestValues(settings, request);
395
396        // check the required permissions to change the resource type
397        if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) {
398            // no write permissions for the resource, set cancel action to close dialog
399            setParamAction(DIALOG_CANCEL);
400        }
401
402        // set the dialog type
403        setParamDialogtype(DIALOG_TYPE);
404        // set the action for the JSP switch
405        if (DIALOG_OK.equals(getParamAction())) {
406            // ok button pressed, change file type
407            setAction(ACTION_OK);
408            getJsp().getRequest().getSession(true).removeAttribute(SESSION_ATTR_ADVANCED);
409        } else if (DIALOG_LOCKS_CONFIRMED.equals(getParamAction())) {
410            setAction(ACTION_LOCKS_CONFIRMED);
411        } else if (DIALOG_CANCEL.equals(getParamAction())) {
412            // cancel button pressed
413            setAction(ACTION_CANCEL);
414            getJsp().getRequest().getSession(true).removeAttribute(SESSION_ATTR_ADVANCED);
415        } else {
416            // build title for change file type dialog
417            setParamTitle(key(Messages.GUI_CHTYPE_1, new Object[] {CmsResource.getName(getParamResource())}));
418        }
419
420        // get session attribute storing if we are in advanced mode
421        String sessionAttr = (String)request.getSession(true).getAttribute(SESSION_ATTR_ADVANCED);
422        if (CmsNewResource.DIALOG_ADVANCED.equals(getParamAction()) || (sessionAttr != null)) {
423            // advanced mode to display all possible resource types
424            if (sessionAttr == null) {
425                // set attribute that we are in advanced mode
426                request.getSession(true).setAttribute(SESSION_ATTR_ADVANCED, "true");
427                setAction(ACTION_ADVANCED);
428            }
429            m_advancedMode = true;
430        } else {
431            // check for presence of property limiting the new resource types to create
432            String newResTypesProperty = "";
433            try {
434                newResTypesProperty = getCms().readPropertyObject(
435                    getParamResource(),
436                    CmsPropertyDefinition.PROPERTY_RESTYPES_AVAILABLE,
437                    true).getValue();
438            } catch (CmsException e) {
439                // ignore this exception, this is a minor issue
440            }
441            if (CmsStringUtil.isNotEmpty(newResTypesProperty)
442                && !newResTypesProperty.equals(CmsNewResource.VALUE_DEFAULT)) {
443                m_limitedRestypes = true;
444                m_availableResTypes = newResTypesProperty;
445            }
446        }
447    }
448
449}