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.content;
029
030import org.opencms.file.CmsProperty;
031import org.opencms.file.CmsPropertyDefinition;
032import org.opencms.file.CmsResource;
033import org.opencms.file.CmsVfsException;
034import org.opencms.i18n.CmsMessages;
035import org.opencms.jsp.CmsJspActionElement;
036import org.opencms.lock.CmsLock;
037import org.opencms.main.CmsException;
038import org.opencms.main.OpenCms;
039import org.opencms.workplace.CmsDialog;
040import org.opencms.workplace.CmsWorkplace;
041import org.opencms.workplace.CmsWorkplaceSettings;
042
043import java.util.ArrayList;
044import java.util.Collections;
045import java.util.Iterator;
046import java.util.List;
047
048import javax.servlet.http.HttpServletRequest;
049import javax.servlet.http.HttpServletResponse;
050import javax.servlet.jsp.JspException;
051import javax.servlet.jsp.PageContext;
052
053/**
054 * Provides methods for the delete property definition dialog.<p>
055 *
056 * @since 6.0.0
057 */
058public class CmsPropertyDelete extends CmsDialog {
059
060    /** Value for the action: delete cascade. */
061    public static final int ACTION_DELETE_CASCADE = 100;
062
063    /** Request parameter value for the action: delete cascade. */
064    public static final String DIALOG_DELETE_CASCADE = "deletecascade";
065
066    /** The dialog type. */
067    public static final String DIALOG_TYPE = "propertydelete";
068
069    /** Request parameter name for the property name. */
070    public static final String PARAM_PROPERTYNAME = "propertyname";
071
072    private String m_paramPropertyName;
073
074    /**
075     * Public constructor with JSP action element.<p>
076     *
077     * @param jsp an initialized JSP action element
078     */
079    public CmsPropertyDelete(CmsJspActionElement jsp) {
080
081        super(jsp);
082    }
083
084    /**
085     * Public constructor with JSP variables.<p>
086     *
087     * @param context the JSP page context
088     * @param req the JSP request
089     * @param res the JSP response
090     */
091    public CmsPropertyDelete(PageContext context, HttpServletRequest req, HttpServletResponse res) {
092
093        this(new CmsJspActionElement(context, req, res));
094    }
095
096    /**
097     * Deletes the property definition.<p>
098     *
099     * @throws JspException if problems including sub-elements occur
100     */
101    public void actionDelete() throws JspException {
102
103        // save initialized instance of this class in request attribute for included sub-elements
104        getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this);
105        try {
106            getCms().deletePropertyDefinition(getParamPropertyName());
107            // close the dialog
108            actionCloseDialog();
109        } catch (Throwable e) {
110            // error while deleting property definition, show error dialog
111            includeErrorpage(this, e);
112        }
113    }
114
115    /**
116     * Deletes the property definition by cascading the properties on resources.<p>
117     *
118     * @throws JspException if problems including sub-elements occur
119     */
120    public void actionDeleteCascade() throws JspException {
121
122        // save initialized instance of this class in request attribute for included sub-elements
123        getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this);
124        try {
125            // list of all resources containing this propertydefinition
126            List resourcesWithProperty = getCms().readResourcesWithProperty(getParamPropertyName());
127            // list of all resources locked by another user, containing this propertydefinition
128            List resourcesLockedByOtherUser = getResourcesLockedByOtherUser(resourcesWithProperty);
129            // do the following operations only if all of the resources are not locked by another user
130            if (resourcesLockedByOtherUser.isEmpty()) {
131                // save the site root
132                String storedSiteRoot = getCms().getRequestContext().getSiteRoot();
133                try {
134                    // change to the root site
135                    getCms().getRequestContext().setSiteRoot("/");
136
137                    Iterator i = resourcesWithProperty.iterator();
138                    while (i.hasNext()) {
139                        CmsResource resource = (CmsResource)i.next();
140                        // read the property object
141                        CmsProperty property = getCms().readPropertyObject(
142                            resource.getRootPath(),
143                            getParamPropertyName(),
144                            false);
145                        // try to delete the property if it is not the NULL PROPERTY
146                        // if the property is the NULL PROPERTY, it only had a shared
147                        // value which was deleted at a sibling which was already processed
148                        if (!property.isNullProperty()) {
149                            CmsLock lock = getCms().getLock(resource);
150                            if (lock.isUnlocked()) {
151                                // lock the resource for the current (Admin) user
152                                getCms().lockResource(resource.getRootPath());
153                            }
154                            property.setStructureValue(CmsProperty.DELETE_VALUE);
155                            property.setResourceValue(CmsProperty.DELETE_VALUE);
156                            // write the property with the null value to the resource and cascade it from the definition
157                            getCms().writePropertyObject(resource.getRootPath(), property);
158                            // unlock the resource
159                            getCms().unlockResource(resource.getRootPath());
160                        }
161                    }
162                    // delete the property definition at last
163                    getCms().deletePropertyDefinition(getParamPropertyName());
164                } finally {
165                    // restore the siteroot
166                    getCms().getRequestContext().setSiteRoot(storedSiteRoot);
167                    // close the dialog
168                    actionCloseDialog();
169                }
170            } else {
171
172                StringBuffer reason = new StringBuffer();
173                reason.append(dialogWhiteBoxStart());
174                reason.append(buildResourceList(resourcesLockedByOtherUser, true));
175                reason.append(dialogWhiteBoxEnd());
176                throw new CmsVfsException(
177                    Messages.get().container(Messages.ERR_DEL_PROP_RESOURCES_LOCKED_1, reason.toString()));
178            }
179        } catch (Throwable e) {
180            // error while deleting property definition, show error dialog
181            includeErrorpage(this, e);
182        }
183    }
184
185    /**
186     * Builds a HTML list of Resources that use the specified property.<p>
187     *
188     * @throws CmsException if operation was not successful
189     *
190     * @return the HTML String for the Resource list
191     */
192    public String buildResourceList() throws CmsException {
193
194        List resourcesWithProperty = getCms().readResourcesWithProperty(getParamPropertyName());
195
196        return buildResourceList(resourcesWithProperty, false);
197    }
198
199    /**
200     * Builds a HTML list of Resources.<p>
201     *
202     * Columns: Type, Name, Uri, Value of the property, locked by(optional).<p>
203     *
204     * @param resourceList a list of resources
205     * @param lockInfo a boolean to decide if the locked info should be shown or not
206     * @throws CmsException if operation was not successful
207     *
208     * @return the HTML String for the Resource list
209     */
210    public String buildResourceList(List resourceList, boolean lockInfo) throws CmsException {
211
212        // reverse the resource list
213        Collections.reverse(resourceList);
214        CmsMessages messages = Messages.get().getBundle(getLocale());
215        StringBuffer result = new StringBuffer();
216        result.append("<table border=\"0\" width=\"100%\" cellpadding=\"1\" cellspacing=\"1\">\n");
217        result.append("<tr>\n");
218        // Type
219        result.append("\t<td style=\"width:5%;\" class=\"textbold\">");
220        result.append(messages.key(Messages.GUI_INPUT_TYPE_0));
221        result.append("</td>\n");
222        // Uri
223        result.append("\t<td style=\"width:40%;\" class=\"textbold\">");
224        result.append(messages.key(Messages.GUI_INPUT_ADRESS_0));
225        result.append("</td>\n");
226        // Name
227        result.append("\t<td style=\"width:25%;\" class=\"textbold\">");
228        result.append(messages.key(Messages.GUI_INPUT_TITLE_0));
229        result.append("</td>\n");
230        if (!lockInfo) {
231            // Property value
232            result.append("\t<td style=\"width:30%;\" class=\"textbold\">");
233            result.append(messages.key(Messages.GUI_INPUT_PROPERTYVALUE_0));
234            result.append("</td>\n");
235        }
236        if (lockInfo) {
237            // Property value
238            result.append("\t<td style=\"width:30%;\" class=\"textbold\">");
239            result.append(messages.key(Messages.GUI_EXPLORER_LOCKEDBY_0));
240            result.append("</td>\n");
241            result.append("</tr>\n");
242        }
243        result.append("</tr>\n");
244        result.append("<tr><td colspan=\"4\"><span style=\"height: 6px;\">&nbsp;</span></td></tr>\n");
245
246        String storedSiteRoot = getCms().getRequestContext().getSiteRoot();
247        try {
248            getCms().getRequestContext().setSiteRoot("/");
249            Iterator i = resourceList.iterator();
250            while (i.hasNext()) {
251                CmsResource resource = (CmsResource)i.next();
252                String filetype = OpenCms.getResourceManager().getResourceType(resource.getTypeId()).getTypeName();
253                result.append("<tr>\n");
254                // file type
255                result.append("\t<td>");
256                result.append("<img src=\"");
257                result.append(getSkinUri());
258                result.append(CmsWorkplace.RES_PATH_FILETYPES);
259                result.append(filetype);
260                result.append(".gif\">");
261                result.append("</td>\n");
262                // file address
263                result.append("\t<td>");
264                result.append(resource.getRootPath());
265                result.append("</td>\n");
266                // title
267                result.append("\t<td>");
268                result.append(getJsp().property(CmsPropertyDefinition.PROPERTY_TITLE, resource.getRootPath(), ""));
269                result.append("</td>\n");
270                // current value of the property
271                if (!lockInfo) {
272                    result.append("\t<td>");
273                    result.append(getJsp().property(getParamPropertyName(), resource.getRootPath()));
274                    result.append("</td>\n");
275                }
276                // locked by user
277                if (lockInfo) {
278                    CmsLock lock = getCms().getLock(resource);
279                    result.append("\t<td>");
280                    result.append(getCms().readUser(lock.getUserId()).getName());
281                    result.append("</td>\n");
282                }
283                result.append("</tr>\n");
284            }
285            result.append("</table>\n");
286        } finally {
287            getCms().getRequestContext().setSiteRoot(storedSiteRoot);
288        }
289
290        return result.toString();
291    }
292
293    /**
294     * Builds the html for the property definition select box.<p>
295     *
296     * @param attributes optional attributes for the &lt;select&gt; tag
297     * @return the html for the property definition select box
298     */
299    public String buildSelectProperty(String attributes) {
300
301        return CmsPropertyChange.buildSelectProperty(
302            getCms(),
303            Messages.get().getBundle(getLocale()).key(Messages.GUI_PLEASE_SELECT_0),
304            attributes,
305            "");
306    }
307
308    /**
309     * Returns the value of the propertyname parameter.<p>
310     *
311     * @return the value of the propertyname parameter
312     */
313    public String getParamPropertyName() {
314
315        return m_paramPropertyName;
316    }
317
318    /**
319     * Sets the value of the propertyname parameter.<p>
320     *
321     * @param paramPropertyName the value of the propertyname parameter
322     */
323    public void setParamPropertyName(String paramPropertyName) {
324
325        m_paramPropertyName = paramPropertyName;
326    }
327
328    /**
329     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
330     */
331    @Override
332    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
333
334        // fill the parameter values in the get/set methods
335        fillParamValues(request);
336        // set the dialog type
337        setParamDialogtype(DIALOG_TYPE);
338        // set the action for the JSP switch
339        if (DIALOG_OK.equals(getParamAction())) {
340            setAction(ACTION_OK);
341            setParamTitle(Messages.get().getBundle(getLocale()).key(Messages.GUI_TITLE_PROPERTYDELETE_0)
342                + ": "
343                + getParamPropertyName());
344        } else if (DIALOG_CANCEL.equals(getParamAction())) {
345            setAction(ACTION_CANCEL);
346        } else if (DIALOG_DELETE_CASCADE.equals(getParamAction())) {
347            setAction(ACTION_DELETE_CASCADE);
348        } else {
349            setAction(ACTION_DEFAULT);
350            // build title for change property value dialog
351            setParamTitle(Messages.get().getBundle(getLocale()).key(Messages.GUI_TITLE_PROPERTYDELETE_0));
352        }
353    }
354
355    /**
356     * Returns a list of resources that are locked by another user as the current user.<p>
357     *
358     * @param resourceList the list of all (mixed) resources
359     *
360     * @return a list of resources that are locked by another user as the current user
361     * @throws CmsException if the getLock operation fails
362     */
363    private List getResourcesLockedByOtherUser(List resourceList) throws CmsException {
364
365        List lockedResourcesByOtherUser = new ArrayList();
366        Iterator i = resourceList.iterator();
367        while (i.hasNext()) {
368            CmsResource resource = (CmsResource)i.next();
369            // get the lock state for the resource
370            CmsLock lock = getCms().getLock(resource);
371            // add this resource to the list if this is locked by another user
372            if (!lock.isUnlocked() && !lock.isOwnedBy(getCms().getRequestContext().getCurrentUser())) {
373                lockedResourcesByOtherUser.add(resource);
374            }
375        }
376
377        return lockedResourcesByOtherUser;
378    }
379}