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.ade.publish; 029 030import org.opencms.ade.publish.shared.CmsPublishOptions; 031import org.opencms.ade.publish.shared.CmsPublishResource; 032import org.opencms.ade.publish.shared.CmsPublishResourceInfo; 033import org.opencms.db.CmsPublishList; 034import org.opencms.db.CmsResourceState; 035import org.opencms.file.CmsObject; 036import org.opencms.file.CmsResource; 037import org.opencms.file.CmsResourceFilter; 038import org.opencms.file.types.CmsResourceTypePlain; 039import org.opencms.gwt.CmsIconUtil; 040import org.opencms.gwt.CmsVfsService; 041import org.opencms.gwt.shared.CmsPermissionInfo; 042import org.opencms.main.CmsException; 043import org.opencms.main.CmsLog; 044import org.opencms.main.OpenCms; 045import org.opencms.publish.CmsPublishManager; 046import org.opencms.relations.CmsRelation; 047import org.opencms.relations.CmsRelationPublishValidator; 048import org.opencms.relations.CmsRelationValidatorInfoEntry; 049import org.opencms.report.CmsWorkplaceReport; 050import org.opencms.report.I_CmsReport; 051import org.opencms.security.CmsOrganizationalUnit; 052import org.opencms.ui.components.CmsResourceIcon; 053import org.opencms.util.CmsStringUtil; 054import org.opencms.util.CmsUUID; 055import org.opencms.workplace.explorer.CmsResourceUtil; 056 057import java.util.ArrayList; 058import java.util.Collection; 059import java.util.HashMap; 060import java.util.HashSet; 061import java.util.List; 062import java.util.Locale; 063import java.util.Map; 064import java.util.Set; 065 066import org.apache.commons.logging.Log; 067 068/** 069 * ADE publishing features.<p> 070 * 071 * @since 8.0.0 072 */ 073public class CmsPublish { 074 075 /** 076 * Just for passing around resources and their related together but not mixed up.<p> 077 */ 078 public class ResourcesAndRelated { 079 080 /** The related resources. */ 081 private Set<CmsResource> m_relatedResources = new HashSet<CmsResource>(); 082 083 /** The resources. */ 084 private Set<CmsResource> m_resources = new HashSet<CmsResource>(); 085 086 /** 087 * Constructor.<p> 088 */ 089 public ResourcesAndRelated() { 090 091 // empty 092 } 093 094 /** 095 * Checks if the given resource is present in at least one of the sets.<p> 096 * 097 * @param resource the resource to test 098 * 099 * @return <code>true</code> if the given resource is present in at least one of the sets 100 */ 101 public boolean contains(CmsResource resource) { 102 103 return m_resources.contains(resource) || m_relatedResources.contains(resource); 104 } 105 106 /** 107 * Returns the related resources.<p> 108 * 109 * @return the related resources 110 */ 111 public Set<CmsResource> getRelatedResources() { 112 113 return m_relatedResources; 114 } 115 116 /** 117 * Returns the resources.<p> 118 * 119 * @return the resources 120 */ 121 public Set<CmsResource> getResources() { 122 123 return m_resources; 124 } 125 } 126 127 /** The number of day groups. */ 128 protected static final int GROUP_DAYS_NUMBER = 3; 129 130 /** The gap between session groups. */ 131 protected static final int GROUP_SESSIONS_GAP = 8 * 60 * 60 * 1000; 132 133 /** The number of session groups. */ 134 protected static final int GROUP_SESSIONS_NUMBER = 2; 135 136 /** The log object for this class. */ 137 private static final Log LOG = CmsLog.getLog(CmsPublish.class); 138 139 /** The current cms context. */ 140 protected final CmsObject m_cms; 141 142 /** The options. */ 143 protected final CmsPublishOptions m_options; 144 145 /** The current user workplace locale. */ 146 protected final Locale m_workplaceLocale; 147 148 /** The relation validator instance. */ 149 private CmsRelationPublishValidator m_relationValidator; 150 151 /** 152 * Creates a new instance.<p> 153 * 154 * @param cms the CMS context to use 155 */ 156 public CmsPublish(CmsObject cms) { 157 158 this(cms, new HashMap<String, String>()); 159 } 160 161 /** 162 * Constructor with options.<p> 163 * 164 * @param cms the current cms context 165 * @param options the options to use 166 */ 167 public CmsPublish(CmsObject cms, CmsPublishOptions options) { 168 169 m_cms = cms; 170 m_workplaceLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms); 171 m_options = options; 172 } 173 174 /** 175 * Constructor with default options.<p> 176 * 177 * @param cms the current cms context 178 * @param params the additional publish parameters 179 */ 180 public CmsPublish(CmsObject cms, Map<String, String> params) { 181 182 this(cms, new CmsPublishOptions(params)); 183 } 184 185 /** 186 * Returns the simple name if the ou is the same as the current user's ou.<p> 187 * 188 * @param cms the CMS context 189 * @param name the fully qualified name to check 190 * 191 * @return the simple name if the ou is the same as the current user's ou 192 */ 193 protected static String getOuAwareName(CmsObject cms, String name) { 194 195 String ou = CmsOrganizationalUnit.getParentFqn(name); 196 if (ou.equals(cms.getRequestContext().getCurrentUser().getOuFqn())) { 197 return CmsOrganizationalUnit.getSimpleName(name); 198 } 199 return CmsOrganizationalUnit.SEPARATOR + name; 200 } 201 202 /** 203 * Checks for possible broken links when the given list of resources would be published.<p> 204 * 205 * @param pubResources list of resources to be published 206 * 207 * @return a list of resources that would produce broken links when published 208 */ 209 public List<CmsPublishResource> getBrokenResources(List<CmsResource> pubResources) { 210 211 List<CmsPublishResource> resources = new ArrayList<CmsPublishResource>(); 212 CmsPublishManager publishManager = OpenCms.getPublishManager(); 213 214 CmsPublishList publishList; 215 try { 216 publishList = OpenCms.getPublishManager().getPublishListAll( 217 m_cms, 218 pubResources, 219 m_options.isIncludeSiblings(), 220 true); 221 if (m_options.isIncludeRelated()) { 222 CmsPublishList related = publishManager.getRelatedResourcesToPublish(m_cms, publishList); 223 publishList = publishManager.mergePublishLists(m_cms, publishList, related); 224 } 225 226 } catch (CmsException e) { 227 // should never happen 228 LOG.error(e.getLocalizedMessage(), e); 229 return resources; 230 } 231 232 CmsRelationPublishValidator validator = new CmsRelationPublishValidator(m_cms, publishList); 233 m_relationValidator = validator; 234 for (String resourceName : validator.keySet()) { 235 CmsRelationValidatorInfoEntry infoEntry = validator.getInfoEntry(resourceName); 236 try { 237 CmsResource resource = m_cms.readResource( 238 m_cms.getRequestContext().removeSiteRoot(resourceName), 239 CmsResourceFilter.ALL); 240 if (resource.getState().isDeleted()) { 241 for (CmsRelation relation : infoEntry.getRelations()) { 242 try { 243 CmsResource theResource = relation.getSource(m_cms, CmsResourceFilter.ALL); 244 CmsPublishResourceInfo info = new CmsPublishResourceInfo( 245 Messages.get().getBundle(m_workplaceLocale).key(Messages.GUI_BROKEN_LINK_ONLINE_0), 246 CmsPublishResourceInfo.Type.BROKENLINK); 247 // HACK: GWT serialization does not like unmodifiable collections :( 248 // Collections.singletonList(resourceToBean(resource, info, false, null))); 249 ArrayList<CmsPublishResource> relatedList = new ArrayList<CmsPublishResource>(); 250 relatedList.add(resourceToBean(resource, info, false, null)); 251 CmsPublishResource pubRes = resourceToBean(theResource, null, false, relatedList); 252 resources.add(pubRes); 253 } catch (CmsException e) { 254 // should never happen 255 LOG.error(e.getLocalizedMessage(), e); 256 } 257 } 258 } else { 259 try { 260 List<CmsPublishResource> related = new ArrayList<CmsPublishResource>(); 261 for (CmsRelation relation : infoEntry.getRelations()) { 262 try { 263 CmsResource theResource = relation.getTarget(m_cms, CmsResourceFilter.ALL); 264 CmsPublishResource pubRes = resourceToBean(theResource, null, false, null); 265 related.add(pubRes); 266 } catch (CmsException e) { 267 CmsPublishResource pubRes = relationToBean(relation); 268 related.add(pubRes); 269 LOG.warn(e.getLocalizedMessage(), e); 270 } 271 } 272 CmsPublishResourceInfo info = new CmsPublishResourceInfo( 273 Messages.get().getBundle(m_workplaceLocale).key(Messages.GUI_RESOURCE_MISSING_ONLINE_0), 274 CmsPublishResourceInfo.Type.MISSING); 275 CmsPublishResource pubRes = resourceToBean(resource, info, false, related); 276 resources.add(pubRes); 277 } catch (Exception e) { 278 // should never happen 279 LOG.error(e.getLocalizedMessage(), e); 280 } 281 } 282 } catch (CmsException e) { 283 // should never happen 284 LOG.error(e.getLocalizedMessage(), e); 285 } 286 } 287 288 return resources; 289 } 290 291 /** 292 * Gets the relation validator instance.<p> 293 * 294 * @return the relation validator 295 */ 296 public CmsRelationPublishValidator getRelationValidator() { 297 298 return m_relationValidator; 299 } 300 301 /** 302 * Publishes the given list of resources.<p> 303 * 304 * @param resources list of resources to publish 305 * 306 * @throws CmsException if something goes wrong 307 */ 308 public void publishResources(List<CmsResource> resources) throws CmsException { 309 310 CmsObject cms = m_cms; 311 I_CmsReport report = new CmsWorkplaceReport( 312 cms.getRequestContext().getLocale(), 313 cms.getRequestContext().getSiteRoot(), 314 null); 315 CmsPublishManager publishManager = OpenCms.getPublishManager(); 316 CmsPublishList publishList = publishManager.getPublishListAll(m_cms, resources, false, true); 317 OpenCms.getPublishManager().publishProject(m_cms, report, publishList); 318 } 319 320 /** 321 * Creates a publish resource bean from the target information of a relation object.<p> 322 * 323 * @param relation the relation to use 324 * 325 * @return the publish resource bean for the relation target 326 */ 327 public CmsPublishResource relationToBean(CmsRelation relation) { 328 329 CmsPermissionInfo permissionInfo = new CmsPermissionInfo(true, false, ""); 330 CmsPublishResource bean = new CmsPublishResource( 331 relation.getTargetId(), 332 relation.getTargetPath(), 333 relation.getTargetPath(), 334 CmsResourceTypePlain.getStaticTypeName(), 335 CmsResourceState.STATE_UNCHANGED, 336 permissionInfo, 337 0, 338 null, 339 null, 340 false, 341 null, 342 null); 343 bean.setBigIconClasses(CmsIconUtil.getIconClasses(CmsResourceTypePlain.getStaticTypeName(), null, false)); 344 return bean; 345 } 346 347 /** 348 * Removes the given resources from the user's publish list.<p> 349 * 350 * @param idsToRemove list of structure ids identifying the resources to be removed 351 * 352 * @throws CmsException if something goes wrong 353 */ 354 public void removeResourcesFromPublishList(Collection<CmsUUID> idsToRemove) throws CmsException { 355 356 OpenCms.getPublishManager().removeResourceFromUsersPubList(m_cms, idsToRemove); 357 } 358 359 /** 360 * Creates a publish resource bean instance from the given parameters.<p> 361 * 362 * @param resource the resource 363 * @param info the publish information, if any 364 * @param removable if removable 365 * @param related the list of related resources 366 * 367 * @return the publish resource bean 368 * 369 * @throws CmsException if something goes wrong 370 */ 371 protected CmsPublishResource resourceToBean( 372 CmsResource resource, 373 CmsPublishResourceInfo info, 374 boolean removable, 375 List<CmsPublishResource> related) 376 throws CmsException { 377 378 CmsResourceUtil resUtil = new CmsResourceUtil(m_cms, resource); 379 CmsPermissionInfo permissionInfo = OpenCms.getADEManager().getPermissionInfo(m_cms, resource, null); 380 381 String typeName = CmsIconUtil.getDisplayType(m_cms, resource); 382 String detailTypeName = null; 383 detailTypeName = CmsResourceIcon.getDefaultFileOrDetailType(m_cms, resource); 384 385 CmsPublishResource pubResource = new CmsPublishResource( 386 resource.getStructureId(), 387 resUtil.getFullPath(), 388 resUtil.getTitle(), 389 typeName, 390 resource.getState(), 391 permissionInfo, 392 resource.getDateLastModified(), 393 resUtil.getUserLastModified(), 394 CmsVfsService.formatDateTime(m_cms, resource.getDateLastModified()), 395 removable, 396 info, 397 related); 398 pubResource.setBigIconClasses(CmsIconUtil.getIconClasses(typeName, null, false)); 399 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(detailTypeName)) { 400 pubResource.setSmallIconClasses(CmsIconUtil.getIconClasses(detailTypeName, null, true)); 401 } 402 return pubResource; 403 } 404 405}