/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * For further information about Alkacon Software, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.gwt; import org.opencms.db.CmsResourceState; import org.opencms.file.CmsObject; import org.opencms.file.CmsProject; import org.opencms.file.CmsProperty; import org.opencms.file.CmsPropertyDefinition; import org.opencms.file.CmsResource; import org.opencms.file.CmsResourceFilter; import org.opencms.file.CmsUser; import org.opencms.file.CmsVfsResourceNotFoundException; import org.opencms.flex.CmsFlexController; import org.opencms.gwt.shared.CmsAvailabilityInfoBean; import org.opencms.gwt.shared.CmsCategoryTreeEntry; import org.opencms.gwt.shared.CmsContextMenuEntryBean; import org.opencms.gwt.shared.CmsCoreData; import org.opencms.gwt.shared.CmsCoreData.AdeContext; import org.opencms.gwt.shared.CmsLockInfo; import org.opencms.gwt.shared.CmsReturnLinkInfo; import org.opencms.gwt.shared.CmsValidationQuery; import org.opencms.gwt.shared.CmsValidationResult; import org.opencms.gwt.shared.rpc.I_CmsCoreService; import org.opencms.i18n.CmsEncoder; import org.opencms.i18n.CmsMessages; import org.opencms.lock.CmsLock; import org.opencms.main.CmsContextInfo; import org.opencms.main.CmsException; import org.opencms.main.CmsIllegalArgumentException; import org.opencms.main.CmsRuntimeException; import org.opencms.main.OpenCms; import org.opencms.module.CmsModule; import org.opencms.relations.CmsCategory; import org.opencms.relations.CmsCategoryService; import org.opencms.scheduler.CmsScheduledJobInfo; import org.opencms.scheduler.jobs.CmsPublishScheduledJob; import org.opencms.security.CmsPermissionSet; import org.opencms.security.CmsRole; import org.opencms.util.CmsDateUtil; import org.opencms.util.CmsStringUtil; import org.opencms.util.CmsUUID; import org.opencms.workplace.CmsWorkplace; import org.opencms.workplace.CmsWorkplaceAction; import org.opencms.workplace.CmsWorkplaceManager; import org.opencms.workplace.explorer.CmsExplorer; import org.opencms.workplace.explorer.CmsExplorerContextMenu; import org.opencms.workplace.explorer.CmsExplorerContextMenuItem; import org.opencms.workplace.explorer.CmsExplorerTypeSettings; import org.opencms.workplace.explorer.CmsResourceUtil; import org.opencms.workplace.explorer.menu.A_CmsMenuItemRule; import org.opencms.workplace.explorer.menu.CmsMenuItemVisibilityMode; import org.opencms.workplace.explorer.menu.CmsMenuRule; import org.opencms.workplace.explorer.menu.I_CmsMenuItemRule; import org.opencms.xml.containerpage.CmsADESessionCache; import java.text.DateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.servlet.http.HttpServletRequest; /** * Provides general core services.<p> * * @since 8.0.0 * * @see org.opencms.gwt.CmsCoreService * @see org.opencms.gwt.shared.rpc.I_CmsCoreService * @see org.opencms.gwt.shared.rpc.I_CmsCoreServiceAsync */ public class CmsCoreService extends CmsGwtService implements I_CmsCoreService { /** The default login URL. */ private static final String DEFAULT_LOGIN_URL = "/system/login/index.html"; /** The editor back-link URI. */ private static final String EDITOR_BACKLINK_URI = "/system/modules/org.opencms.gwt/editor-backlink.html"; /** The uri used for deleting. */ private static final String EDITOR_DELETE_URI = "/system/workplace/commons/delete.jsp"; /** The xml-content editor URI. */ private static final String EDITOR_URI = "/system/workplace/editors/editor.jsp"; /** Serialization uid. */ private static final long serialVersionUID = 5915848952948986278L; /** The session cache. */ private CmsADESessionCache m_sessionCache; /** * Internal helper method for getting a validation service.<p> * * @param name the class name of the validation service * * @return the validation service * * @throws CmsException if something goes wrong */ public static I_CmsValidationService getValidationService(String name) throws CmsException { try { Class<?> cls = Class.forName(name, false, I_CmsValidationService.class.getClassLoader()); if (!I_CmsValidationService.class.isAssignableFrom(cls)) { throw new CmsIllegalArgumentException(Messages.get().container( Messages.ERR_VALIDATOR_INCORRECT_TYPE_1, name)); } return (I_CmsValidationService)cls.newInstance(); } catch (ClassNotFoundException e) { throw new CmsException(Messages.get().container(Messages.ERR_VALIDATOR_INSTANTIATION_FAILED_1, name), e); } catch (InstantiationException e) { throw new CmsException(Messages.get().container(Messages.ERR_VALIDATOR_INSTANTIATION_FAILED_1, name), e); } catch (IllegalAccessException e) { throw new CmsException(Messages.get().container(Messages.ERR_VALIDATOR_INSTANTIATION_FAILED_1, name), e); } } /** * Instantiates a class given its name using its default constructor.<p> * * Also checks whether the class with the given name is the subclass of another class/interface.<p> * * * @param <T> the type of the interface/class passed as a parameter * * @param anInterface the interface or class against which the class should be checked * @param className the name of the class * @return a new instance of the class * * @throws CmsException if the instantiation fails */ public static <T> T instantiate(Class<T> anInterface, String className) throws CmsException { try { Class<?> cls = Class.forName(className, false, anInterface.getClassLoader()); if (!anInterface.isAssignableFrom(cls)) { // class was found, but does not implement the interface throw new CmsIllegalArgumentException(Messages.get().container( Messages.ERR_INSTANTIATION_INCORRECT_TYPE_2, className, anInterface.getName())); } // we use another variable so we don't have to put the @SuppressWarnings on the method itself @SuppressWarnings("unchecked") Class<T> typedClass = (Class<T>)cls; return typedClass.newInstance(); } catch (ClassNotFoundException e) { throw new CmsException(Messages.get().container(Messages.ERR_INSTANTIATION_FAILED_1, className), e); } catch (InstantiationException e) { throw new CmsException(Messages.get().container(Messages.ERR_INSTANTIATION_FAILED_1, className), e); } catch (IllegalAccessException e) { throw new CmsException(Messages.get().container(Messages.ERR_INSTANTIATION_FAILED_1, className), e); } } /** * Returns a new configured service instance.<p> * * @param request the current request * * @return a new service instance */ public static CmsCoreService newInstance(HttpServletRequest request) { CmsCoreService srv = new CmsCoreService(); srv.setCms(CmsFlexController.getCmsObject(request)); srv.setRequest(request); return srv; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#createUUID() */ public CmsUUID createUUID() { return new CmsUUID(); } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getCategories(java.lang.String, boolean, java.util.List) */ public List<CmsCategoryTreeEntry> getCategories(String fromPath, boolean includeSubCats, List<String> refPaths) throws CmsRpcException { CmsObject cms = getCmsObject(); CmsCategoryService catService = CmsCategoryService.getInstance(); List<String> repositories = new ArrayList<String>(); if ((refPaths != null) && !refPaths.isEmpty()) { for (String refPath : refPaths) { repositories.addAll(catService.getCategoryRepositories(getCmsObject(), refPath)); } } else { repositories.add(CmsCategoryService.CENTRALIZED_REPOSITORY); } List<CmsCategoryTreeEntry> result = null; try { // get the categories List<CmsCategory> categories = catService.readCategoriesForRepositories( cms, fromPath, includeSubCats, repositories); result = buildCategoryTree(categories); } catch (Throwable e) { error(e); } return result; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getCategoriesForSitePath(java.lang.String) */ public List<CmsCategoryTreeEntry> getCategoriesForSitePath(String sitePath) throws CmsRpcException { CmsCategoryService catService = CmsCategoryService.getInstance(); List<CmsCategoryTreeEntry> result = null; try { // get the categories List<CmsCategory> categories = catService.readCategories(getCmsObject(), "", true, sitePath); result = buildCategoryTree(categories); } catch (Throwable e) { error(e); } return result; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getContextMenuEntries(org.opencms.util.CmsUUID, org.opencms.gwt.shared.CmsCoreData.AdeContext) */ public List<CmsContextMenuEntryBean> getContextMenuEntries(CmsUUID structureId, AdeContext context) throws CmsRpcException { List<CmsContextMenuEntryBean> result = null; CmsObject cms = getCmsObject(); switch (context) { case containerpage: cms.getRequestContext().setAttribute( I_CmsMenuItemRule.ATTR_CONTEXT_INFO, I_CmsCoreService.CONTEXT_CONTAINERPAGE); break; case sitemap: cms.getRequestContext().setAttribute( I_CmsMenuItemRule.ATTR_CONTEXT_INFO, I_CmsCoreService.CONTEXT_SITEMAP); break; default: // nothing to do here } try { CmsResourceUtil[] resUtil = new CmsResourceUtil[1]; resUtil[0] = new CmsResourceUtil(cms, cms.readResource(structureId)); // the explorer type settings CmsExplorerTypeSettings settings = null; // get the context menu configuration for the given selection mode CmsExplorerContextMenu contextMenu; // get the explorer type setting for the first resource try { settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(resUtil[0].getResourceTypeName()); } catch (Throwable e) { error(e); } if ((settings == null) || !isEditable(cms, resUtil[0].getResource())) { // the user has no access to this resource type // could be configured in the opencms-vfs.xml or in the opencms-modules.xml return Collections.<CmsContextMenuEntryBean> emptyList(); } // get the context menu contextMenu = settings.getContextMenu(); // transform the context menu into beans List<CmsContextMenuEntryBean> allEntries = transformToMenuEntries(contextMenu.getAllEntries(), resUtil); // filter the result result = filterEntries(allEntries); } catch (Throwable e) { error(e); } return result; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getLinkForReturnCode(java.lang.String) */ public CmsReturnLinkInfo getLinkForReturnCode(String returnCode) throws CmsRpcException { try { return internalGetLinkForReturnCode(returnCode); } catch (Throwable e) { error(e); return null; } } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getResourceState(org.opencms.util.CmsUUID) */ public CmsResourceState getResourceState(CmsUUID structureId) throws CmsRpcException { CmsObject cms = getCmsObject(); CmsResourceState result = null; try { try { CmsResource res = cms.readResource(structureId); result = res.getState(); } catch (CmsVfsResourceNotFoundException e) { result = CmsResourceState.STATE_DELETED; } } catch (CmsException e) { error(e); } return result; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getUniqueFileName(java.lang.String, java.lang.String) */ public String getUniqueFileName(String parentFolder, String baseName) { return OpenCms.getResourceManager().getNameGenerator().getUniqueFileName(getCmsObject(), parentFolder, baseName); } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getWorkplaceLink(org.opencms.util.CmsUUID) */ public String getWorkplaceLink(CmsUUID structureId) throws CmsRpcException { String result = null; try { String resourceRootFolder = CmsResource.getFolderPath(getCmsObject().readResource(structureId).getRootPath()); result = CmsExplorer.getWorkplaceExplorerLink(getCmsObject(), resourceRootFolder); } catch (Throwable e) { error(e); } return result; } /** * Implementation method for getting the link for a given return code.<p> * * @param returnCode the return code * @return the link for the return code * * @throws CmsException if something goes wrong */ public CmsReturnLinkInfo internalGetLinkForReturnCode(String returnCode) throws CmsException { CmsObject cms = getCmsObject(); if (CmsUUID.isValidUUID(returnCode)) { try { CmsResource pageRes = cms.readResource(new CmsUUID(returnCode)); return new CmsReturnLinkInfo(CmsStringUtil.joinPaths( OpenCms.getSystemInfo().getOpenCmsContext(), cms.getSitePath(pageRes)), CmsReturnLinkInfo.Status.ok); } catch (CmsVfsResourceNotFoundException e) { return new CmsReturnLinkInfo(null, CmsReturnLinkInfo.Status.notfound); } } else { int colonIndex = returnCode.indexOf(':'); if (colonIndex >= 0) { String before = returnCode.substring(0, colonIndex); String after = returnCode.substring(colonIndex + 1); if (CmsUUID.isValidUUID(before) && CmsUUID.isValidUUID(after)) { try { CmsUUID pageId = new CmsUUID(before); CmsUUID detailId = new CmsUUID(after); CmsResource pageRes = cms.readResource(pageId); String pagePath = CmsResource.getFolderPath(cms.getSitePath(pageRes)); CmsResource detailRes = cms.readResource(detailId); String detailName = cms.getDetailName( detailRes, cms.getRequestContext().getLocale(), OpenCms.getLocaleManager().getDefaultLocales()); String uri = CmsStringUtil.joinPaths(pagePath, detailName); return new CmsReturnLinkInfo(CmsStringUtil.joinPaths( OpenCms.getSystemInfo().getOpenCmsContext(), uri), CmsReturnLinkInfo.Status.ok); } catch (CmsVfsResourceNotFoundException e) { return new CmsReturnLinkInfo(null, CmsReturnLinkInfo.Status.notfound); } } } throw new IllegalArgumentException("return code has wrong format"); } } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#lockTemp(org.opencms.util.CmsUUID) */ public String lockTemp(CmsUUID structureId) throws CmsRpcException { CmsObject cms = getCmsObject(); try { ensureLock(structureId); } catch (CmsException e) { return e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)); } catch (Throwable e) { error(e); } return null; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#lockTempAndCheckModification(org.opencms.util.CmsUUID, long) */ public CmsLockInfo lockTempAndCheckModification(CmsUUID structureId, long modification) throws CmsRpcException { CmsObject cms = getCmsObject(); try { CmsResource resource = cms.readResource(structureId); if (resource.getDateLastModified() != modification) { CmsUser user = cms.readUser(resource.getUserLastModified()); return CmsLockInfo.forChangedResource(user.getFullName()); } } catch (Throwable e) { error(e); } try { return getLock(structureId); } catch (CmsException e) { return CmsLockInfo.forError(e.getLocalizedMessage()); } } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#ping() */ public void ping() { // do nothing } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#prefetch() */ public CmsCoreData prefetch() { CmsObject cms = getCmsObject(); String navigationUri = cms.getRequestContext().getUri(); boolean toolbarVisible = getSessionCache().isToolbarVisible(); CmsUUID structureId = null; try { CmsResource requestedResource = cms.readResource(cms.getRequestContext().getUri()); structureId = requestedResource.getStructureId(); } catch (CmsException e) { throw new CmsRuntimeException(e.getMessageContainer(), e); } String loginUrl = DEFAULT_LOGIN_URL; try { loginUrl = cms.readPropertyObject( cms.getRequestContext().getUri(), CmsPropertyDefinition.PROPERTY_LOGIN_FORM, true).getValue(DEFAULT_LOGIN_URL); } catch (CmsException e) { log(e.getLocalizedMessage(), e); } Map<String, String> gwtBuildIds = getBuildIds(); CmsCoreData data = new CmsCoreData( EDITOR_URI, EDITOR_BACKLINK_URI, EDITOR_DELETE_URI, loginUrl, OpenCms.getStaticExportManager().getVfsPrefix(), cms.getRequestContext().getSiteRoot(), cms.getRequestContext().getLocale().toString(), OpenCms.getWorkplaceManager().getWorkplaceLocale(cms).toString(), cms.getRequestContext().getUri(), navigationUri, structureId, new HashMap<String, String>(OpenCms.getResourceManager().getExtensionMapping()), System.currentTimeMillis(), toolbarVisible, gwtBuildIds); return data; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#setAvailabilityInfo(org.opencms.util.CmsUUID, org.opencms.gwt.shared.CmsAvailabilityInfoBean) */ public void setAvailabilityInfo(CmsUUID structureId, CmsAvailabilityInfoBean bean) throws CmsRpcException { try { CmsResource res = getCmsObject().readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION); setAvailabilityInfo(res, bean); } catch (CmsException e) { error(e); } } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#setAvailabilityInfo(java.lang.String, org.opencms.gwt.shared.CmsAvailabilityInfoBean) */ public void setAvailabilityInfo(String uri, CmsAvailabilityInfoBean bean) throws CmsRpcException { try { String sitePath = getCmsObject().getRequestContext().removeSiteRoot(uri); CmsResource resource = getCmsObject().readResource(sitePath); setAvailabilityInfo(resource, bean); } catch (CmsException e) { error(e); } } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#setToolbarVisible(boolean) */ public void setToolbarVisible(boolean visible) throws CmsRpcException { try { ensureSession(); getSessionCache().setToolbarVisible(visible); } catch (Throwable e) { error(e); } } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#unlock(org.opencms.util.CmsUUID) */ public String unlock(CmsUUID structureId) throws CmsRpcException { CmsObject cms = getCmsObject(); try { CmsResource resource = cms.readResource(structureId); tryUnlock(resource); } catch (CmsException e) { return e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)); } catch (Throwable e) { error(e); } return null; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#validate(java.util.Map) */ public Map<String, CmsValidationResult> validate(Map<String, CmsValidationQuery> validationQueries) throws CmsRpcException { try { Map<String, CmsValidationResult> result = new HashMap<String, CmsValidationResult>(); for (Map.Entry<String, CmsValidationQuery> queryEntry : validationQueries.entrySet()) { String fieldName = queryEntry.getKey(); CmsValidationQuery query = queryEntry.getValue(); result.put(fieldName, validate(query.getValidatorId(), query.getValue(), query.getConfig())); } return result; } catch (Throwable e) { error(e); } return null; } /** * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#validate(java.lang.String, java.util.Map, java.util.Map, java.lang.String) */ public Map<String, CmsValidationResult> validate( String formValidatorClass, Map<String, CmsValidationQuery> validationQueries, Map<String, String> values, String config) throws CmsRpcException { try { I_CmsFormValidator formValidator = instantiate(I_CmsFormValidator.class, formValidatorClass); return formValidator.validate(getCmsObject(), validationQueries, values, config); } catch (Throwable e) { error(e); } return null; } /** * Collect GWT build ids from the different ADE modules.<p> * * @return the map of GWT build ids */ protected Map<String, String> getBuildIds() { List<CmsModule> modules = OpenCms.getModuleManager().getAllInstalledModules(); Map<String, String> result = new HashMap<String, String>(); for (CmsModule module : modules) { String buildid = module.getParameter(CmsCoreData.KEY_GWT_BUILDID); if (buildid != null) { result.put(module.getName(), buildid); } } return result; } /** * Helper method for locking a resource which returns some information on whether the locking * failed, and why.<p> * * @param structureId the structure id of the resource * @return the locking information * * @throws CmsException if something went wrong */ protected CmsLockInfo getLock(CmsUUID structureId) throws CmsException { CmsResource res = getCmsObject().readResource(structureId); return getLock(getCmsObject().getSitePath(res)); } /** * Helper method for locking a resource which returns some information on whether the locking * failed, and why.<p> * * @param sitepath the site path of the resource to lock * @return the locking information * * @throws CmsException if something went wrong */ protected CmsLockInfo getLock(String sitepath) throws CmsException { CmsObject cms = getCmsObject(); CmsUser user = cms.getRequestContext().getCurrentUser(); CmsLock lock = cms.getLock(sitepath); if (lock.isOwnedBy(user)) { return CmsLockInfo.forSuccess(); } if (lock.getUserId().isNullUUID()) { cms.lockResourceTemporary(sitepath); return CmsLockInfo.forSuccess(); } CmsUser owner = cms.readUser(lock.getUserId()); return CmsLockInfo.forLockedResource(owner.getName()); } /** * Builds the tree structure for the given categories.<p> * * @param categories the categories * * @return the tree root element * * @throws Exception if something goes wrong */ private List<CmsCategoryTreeEntry> buildCategoryTree(List<CmsCategory> categories) throws Exception { List<CmsCategoryTreeEntry> result = new ArrayList<CmsCategoryTreeEntry>(); for (CmsCategory category : categories) { CmsCategoryTreeEntry current = new CmsCategoryTreeEntry(category); String parentPath = CmsResource.getParentFolder(current.getPath()); CmsCategoryTreeEntry parent = null; parent = findCategory(result, parentPath); if (parent != null) { parent.addChild(current); } else { result.add(current); } } return result; } /** * Filters the collection of menu entry beans.<p> * * <ul> * <li>removes unnecessary separators</li> * <li>filters sub menus also</li> * <li>adds visible entries to the result</li> * </ul> * * @see org.opencms.gwt.shared.CmsContextMenuEntryBean * * @param allEntries the entries to filter * * @return the filtered list of menu entries */ private List<CmsContextMenuEntryBean> filterEntries(List<CmsContextMenuEntryBean> allEntries) { // the resulting list List<CmsContextMenuEntryBean> result = new ArrayList<CmsContextMenuEntryBean>(); CmsContextMenuEntryBean lastBean = null; // iterate over the list of collected menu entries to do the filtering for (CmsContextMenuEntryBean entry : allEntries) { if (entry.isVisible()) { // only if the entry is enabled if (entry.isSeparator()) { if (!result.isEmpty()) { // the entry is a separator and it isn't the first entry in the menu if ((lastBean != null) && !lastBean.isSeparator()) { // and there are no two separators behind each other // add the separator result.add(entry); } } } else if ((entry.getSubMenu() != null) && !entry.getSubMenu().isEmpty()) { // the entry has a sub menu, so filter the entries of the sub menu entry.setSubMenu(filterEntries(entry.getSubMenu())); // add the entry with sub menu result.add(entry); } else { // it's a common entry, so add it result.add(entry); } // store the last entry to check the separator lastBean = entry; } } // after the filtering is finished, remove the last separator if it is existent if (result.size() > 1) { if (result.get(result.size() - 1).isSeparator()) { result.remove(result.size() - 1); } } return result; } /** * FInds a category in the given tree.<p> * * @param tree the the tree to search in * @param path the path to search for * * @return the category with the given path or <code>null</code> if not found */ private CmsCategoryTreeEntry findCategory(List<CmsCategoryTreeEntry> tree, String path) { if (path == null) { return null; } // we assume that the category to find is descendant of tree List<CmsCategoryTreeEntry> children = tree; boolean found = true; while (found) { if (children == null) { return null; } // since the categories are sorted it is faster to go backwards found = false; for (int i = children.size() - 1; i >= 0; i--) { CmsCategoryTreeEntry child = children.get(i); if (path.equals(child.getPath())) { return child; } if (path.startsWith(child.getPath())) { children = child.getChildren(); found = true; break; } } } return null; } /** * Returns the session cache.<p> * * @return the session cache */ private CmsADESessionCache getSessionCache() { if (m_sessionCache == null) { m_sessionCache = (CmsADESessionCache)getRequest().getSession().getAttribute( CmsADESessionCache.SESSION_ATTR_ADE_CACHE); if (m_sessionCache == null) { m_sessionCache = new CmsADESessionCache(getCmsObject()); getRequest().getSession().setAttribute(CmsADESessionCache.SESSION_ATTR_ADE_CACHE, m_sessionCache); } } return m_sessionCache; } /** * Collects the matching rules of all sub items of a parent context menu entry.<p> * * @param item the context menu item to check the sub items for * @param itemRules the collected rules for the sub items * @param resourceUtil the resources to be checked against the rules */ private void getSubItemRules( CmsExplorerContextMenuItem item, List<I_CmsMenuItemRule> itemRules, CmsResourceUtil[] resourceUtil) { for (CmsExplorerContextMenuItem subItem : item.getSubItems()) { if (subItem.isParentItem()) { // this is a parent item, recurse into sub items getSubItemRules(subItem, itemRules, resourceUtil); } else if (CmsExplorerContextMenuItem.TYPE_ENTRY.equals(subItem.getType())) { // this is a standard entry, get the matching rule to add to the list String subItemRuleName = subItem.getRule(); CmsMenuRule subItemRule = OpenCms.getWorkplaceManager().getMenuRule(subItemRuleName); if (subItemRule != null) { I_CmsMenuItemRule rule = subItemRule.getMatchingRule(getCmsObject(), resourceUtil); if (rule != null) { itemRules.add(rule); } } } } } /** * Checks if the current user has write permissions on the given resource.<p> * * @param cms the current cms context * @param resource the resource to check * * @return <code>true</code> if the current user has write permissions on the given resource */ private boolean isEditable(CmsObject cms, CmsResource resource) { try { return cms.hasPermissions(resource, CmsPermissionSet.ACCESS_WRITE, false, CmsResourceFilter.ALL); } catch (CmsException e) { return false; } } /** * Modifies the availability of the given resource.<p> * * @param resource the resource whose availability should be modified * @param dateReleased the date released * @param dateExpired the date expired * * @throws CmsException if something goes wrong */ private void modifyAvailability(CmsResource resource, long dateReleased, long dateExpired) throws CmsException { // modify release and expire date of the resource if needed getCmsObject().setDateReleased(resource, dateReleased, false); getCmsObject().setDateExpired(resource, dateExpired, false); } /** * Modifies the notification properties of the given resource.<p> * * @param resource the resource whose notification properties should be modified * @param notificationInterval the modification interval * @param notificationEnabled signals whether the notification is enabled or disabled * @param modifySiblings signals whether siblings should be also modified * * @throws CmsException if something goes wrong */ private void modifyNotification( CmsResource resource, int notificationInterval, boolean notificationEnabled, boolean modifySiblings) throws CmsException { List<CmsResource> resources = new ArrayList<CmsResource>(); if (modifySiblings) { // modify all siblings of a resource resources = getCmsObject().readSiblings(resource, CmsResourceFilter.IGNORE_EXPIRATION); } else { // modify only resource without siblings resources.add(resource); } for (CmsResource curResource : resources) { String resourcePath = getCmsObject().getRequestContext().removeSiteRoot(curResource.getRootPath()); // write notification settings writeProperty( resourcePath, CmsPropertyDefinition.PROPERTY_NOTIFICATION_INTERVAL, String.valueOf(notificationInterval)); writeProperty( resourcePath, CmsPropertyDefinition.PROPERTY_ENABLE_NOTIFICATION, String.valueOf(notificationEnabled)); } } /** * Modifies the publish scheduled.<p> * * Creates a temporary project and adds the given resource to it. Afterwards a scheduled job is created * and the project is assigned to it. Then the publish job is enqueued.<p> * * @param resource the resource which should be scheduled for publishing * @param pubDate the date when the resource should be published * * @throws CmsException if something goes wrong */ private void modifyPublishScheduled(CmsResource resource, long pubDate) throws CmsException { if (pubDate != CmsAvailabilityInfoBean.DATE_PUBLISH_SCHEDULED_DEFAULT) { CmsObject cms = getCmsObject(); CmsUser user = getCmsObject().getRequestContext().getCurrentUser(); Locale locale = getCmsObject().getRequestContext().getLocale(); Date date = new Date(pubDate); // make copies from the admin cmsobject and the user cmsobject // get the admin cms object CmsWorkplaceAction action = CmsWorkplaceAction.getInstance(); CmsObject cmsAdmin = action.getCmsAdminObject(); // get the user cms object // set the current user site to the admin cms object cmsAdmin.getRequestContext().setSiteRoot(cms.getRequestContext().getSiteRoot()); // create the temporary project, which is deleted after publishing // the publish scheduled date in project name String dateTime = CmsDateUtil.getDateTime(date, DateFormat.SHORT, locale); CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(locale); String projectName = messages.key( org.opencms.workplace.commons.Messages.GUI_PUBLISH_SCHEDULED_PROJECT_NAME_2, new Object[] {resource.getName(), dateTime}); // the HTML encoding for slashes is necessary because of the slashes in english date time format // in project names slahes are not allowed, because these are separators for organizaional units projectName = projectName.replace("/", "/"); // create the project CmsProject tmpProject = cmsAdmin.createProject( projectName, "", CmsRole.WORKPLACE_USER.getGroupName(), CmsRole.PROJECT_MANAGER.getGroupName(), CmsProject.PROJECT_TYPE_TEMPORARY); // make the project invisible for all users tmpProject.setHidden(true); // write the project to the database cmsAdmin.writeProject(tmpProject); // set project as current project cmsAdmin.getRequestContext().setCurrentProject(tmpProject); cms.getRequestContext().setCurrentProject(tmpProject); // copy the resource to the project cmsAdmin.copyResourceToProject(resource); // create a new scheduled job CmsScheduledJobInfo job = new CmsScheduledJobInfo(); // the job name String jobName = projectName; // set the job parameters job.setJobName(jobName); job.setClassName("org.opencms.scheduler.jobs.CmsPublishScheduledJob"); // create the cron expression Calendar calendar = Calendar.getInstance(); calendar.setTime(date); String cronExpr = "" + calendar.get(Calendar.SECOND) + " " + calendar.get(Calendar.MINUTE) + " " + calendar.get(Calendar.HOUR_OF_DAY) + " " + calendar.get(Calendar.DAY_OF_MONTH) + " " + (calendar.get(Calendar.MONTH) + 1) + " " + "?" + " " + calendar.get(Calendar.YEAR); // set the cron expression job.setCronExpression(cronExpr); // set the job active job.setActive(true); // create the context info CmsContextInfo contextInfo = new CmsContextInfo(); contextInfo.setProjectName(projectName); contextInfo.setUserName(cmsAdmin.getRequestContext().getCurrentUser().getName()); // create the job schedule parameter SortedMap<String, String> params = new TreeMap<String, String>(); // the user to send mail to params.put(CmsPublishScheduledJob.PARAM_USER, user.getName()); // the job name params.put(CmsPublishScheduledJob.PARAM_JOBNAME, jobName); // the link check params.put(CmsPublishScheduledJob.PARAM_LINKCHECK, "true"); // add the job schedule parameter job.setParameters(params); // add the context info to the scheduled job job.setContextInfo(contextInfo); // add the job to the scheduled job list OpenCms.getScheduleManager().scheduleJob(cmsAdmin, job); } } /** * Sets the availability of a resource by modifying the date release, date expired, * setting a scheduled publish job according to the info bean.<p> * * Will also modify the notification settings of the resource.<p> * * @param resource the resource to modify * @param bean the bean with the information of the dialog * * @throws CmsException if something goes wrong */ private void setAvailabilityInfo(CmsResource resource, CmsAvailabilityInfoBean bean) throws CmsException { ensureLock(resource); modifyPublishScheduled(resource, bean.getDatePubScheduled()); modifyAvailability(resource, bean.getDateReleased(), bean.getDateExpired()); modifyNotification( resource, bean.getNotificationInterval(), bean.isNotificationEnabled(), bean.isModifySiblings()); tryUnlock(resource); } /** * Returns a list of menu entry beans.<p> * * Takes the given List of explorer context menu items and converts them to context menu entry beans.<p> * * @see org.opencms.gwt.shared.CmsContextMenuEntryBean * @see org.opencms.workplace.explorer.CmsExplorerContextMenuItem * * @param items the menu items * @param resUtil a resource utility array * * @return a list of menu entries */ private List<CmsContextMenuEntryBean> transformToMenuEntries( List<CmsExplorerContextMenuItem> items, CmsResourceUtil[] resUtil) { // the resulting list List<CmsContextMenuEntryBean> result = new ArrayList<CmsContextMenuEntryBean>(); // get the workplace manager CmsWorkplaceManager wpManager = OpenCms.getWorkplaceManager(); // get the workplace message bundle CmsMessages messages = wpManager.getMessages(wpManager.getWorkplaceLocale(getCmsObject())); for (CmsExplorerContextMenuItem item : items) { CmsContextMenuEntryBean bean = new CmsContextMenuEntryBean(); if (!CmsExplorerContextMenuItem.TYPE_SEPARATOR.equals(item.getType())) { // this item is no separator (common entry or sub menu entry) // set the label to the bean if (item.getKey() != null) { bean.setLabel(messages.key(item.getKey())); } // get the mode and set the bean CmsMenuItemVisibilityMode mode = CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE; String itemRuleName = item.getRule(); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(itemRuleName)) { CmsMenuRule rule = wpManager.getMenuRule(itemRuleName); if (rule != null) { // get the first matching rule to apply for visibility I_CmsMenuItemRule itemRule = rule.getMatchingRule(getCmsObject(), resUtil); if (itemRule != null) { if (item.isParentItem()) { // get the rules for the sub items List<I_CmsMenuItemRule> itemRules = new ArrayList<I_CmsMenuItemRule>( item.getSubItems().size()); getSubItemRules(item, itemRules, resUtil); I_CmsMenuItemRule[] itemRulesArray = new I_CmsMenuItemRule[itemRules.size()]; // determine the visibility for the parent item mode = itemRule.getVisibility( getCmsObject(), resUtil, itemRules.toArray(itemRulesArray)); } else { if (itemRule instanceof A_CmsMenuItemRule) { mode = ((A_CmsMenuItemRule)itemRule).getVisibility(getCmsObject(), resUtil, item); } else { mode = itemRule.getVisibility(getCmsObject(), resUtil); } } } } } // set the visibility to the bean bean.setVisible(!mode.isInVisible()); // set the activate info to the bean if (item.isParentItem()) { // parent entries that have visible sub entries are always active bean.setActive(true); } else { // common entries can be activated or de-activated bean.setActive(mode.isActive()); if (CmsStringUtil.isNotEmpty(mode.getMessageKey())) { bean.setReason(messages.key(CmsEncoder.escapeXml(mode.getMessageKey()))); } } // get the JSP-URI and set it to the bean String jspPath = item.getUri(); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(jspPath)) { if (item.getUri().startsWith("/")) { jspPath = OpenCms.getLinkManager().substituteLink(getCmsObject(), item.getUri()); } else { jspPath = OpenCms.getLinkManager().substituteLink( getCmsObject(), CmsWorkplace.PATH_WORKPLACE + item.getUri()); } } bean.setJspPath(jspPath); String params = item.getParams(); if (params != null) { params = CmsVfsService.prepareFileNameForEditor(getCmsObject(), resUtil[0].getResource(), params); bean.setParams(CmsStringUtil.splitAsMap(params, "|", "=")); } // get the name of the item and set it to the bean bean.setName(item.getName()); // get the image-URI and set it to the bean String imagePath = item.getIcon(); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(imagePath)) { if (item.getIcon().startsWith("/")) { imagePath = OpenCms.getLinkManager().substituteLink(getCmsObject(), item.getIcon()); } else { imagePath = OpenCms.getLinkManager().substituteLink( getCmsObject(), CmsWorkplace.PATH_WORKPLACE + item.getIcon()); } } bean.setImagePath(imagePath); } if (item.isParentItem()) { // this item has a sub menu bean.setSubMenu(transformToMenuEntries(item.getSubItems(), resUtil)); } if (CmsExplorerContextMenuItem.TYPE_SEPARATOR.equals(item.getType())) { // this item is a separator bean.setVisible(true); bean.setSeparator(true); } result.add(bean); } return result; } /** * Internal helper method for validating a single value.<p> * * @param validator the class name of the validation service * @param value the value to validate * @param config the configuration for the validation service * * @return the result of the validation * * @throws Exception if something goes wrong */ private CmsValidationResult validate(String validator, String value, String config) throws Exception { I_CmsValidationService validationService = getValidationService(validator); return validationService.validate(getCmsObject(), value, config); } /** * Writes a property value for a resource.<p> * * @param resourcePath the path of the resource * @param propertyName the name of the property * @param propertyValue the new value of the property * * @throws CmsException if something goes wrong */ private void writeProperty(String resourcePath, String propertyName, String propertyValue) throws CmsException { if (CmsStringUtil.isEmpty(propertyValue)) { propertyValue = CmsProperty.DELETE_VALUE; } CmsProperty newProp = new CmsProperty(); newProp.setName(propertyName); CmsProperty oldProp = getCmsObject().readPropertyObject(resourcePath, propertyName, false); if (oldProp.isNullProperty()) { // property value was not already set if (OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) { newProp.setStructureValue(propertyValue); } else { newProp.setResourceValue(propertyValue); } } else { if (oldProp.getStructureValue() != null) { newProp.setStructureValue(propertyValue); newProp.setResourceValue(oldProp.getResourceValue()); } else { newProp.setResourceValue(propertyValue); } } newProp.setAutoCreatePropertyDefinition(true); String oldStructureValue = oldProp.getStructureValue(); String newStructureValue = newProp.getStructureValue(); if (CmsStringUtil.isEmpty(oldStructureValue)) { oldStructureValue = CmsProperty.DELETE_VALUE; } if (CmsStringUtil.isEmpty(newStructureValue)) { newStructureValue = CmsProperty.DELETE_VALUE; } String oldResourceValue = oldProp.getResourceValue(); String newResourceValue = newProp.getResourceValue(); if (CmsStringUtil.isEmpty(oldResourceValue)) { oldResourceValue = CmsProperty.DELETE_VALUE; } if (CmsStringUtil.isEmpty(newResourceValue)) { newResourceValue = CmsProperty.DELETE_VALUE; } // change property only if it has been changed if (!oldResourceValue.equals(newResourceValue) || !oldStructureValue.equals(newStructureValue)) { getCmsObject().writePropertyObject(resourcePath, newProp); } } }