001/* 002 * (C) Copyright 2009 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Anahide Tchertchian 016 */ 017package org.nuxeo.ecm.platform.error.web; 018 019import static org.jboss.seam.ScopeType.EVENT; 020 021import java.io.Serializable; 022import java.util.Collections; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import javax.persistence.EntityManager; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.jboss.seam.ScopeType; 032import org.jboss.seam.annotations.Factory; 033import org.jboss.seam.annotations.In; 034import org.jboss.seam.annotations.Name; 035import org.jboss.seam.annotations.Scope; 036import org.nuxeo.common.utils.IdUtils; 037import org.nuxeo.ecm.core.api.CoreSession; 038import org.nuxeo.ecm.core.api.DocumentModel; 039import org.nuxeo.ecm.core.api.DocumentSecurityException; 040import org.nuxeo.ecm.core.api.NuxeoException; 041import org.nuxeo.ecm.core.api.PathRef; 042import org.nuxeo.ecm.core.api.RecoverableClientException; 043import org.nuxeo.ecm.core.persistence.PersistenceProviderFactory; 044import org.nuxeo.ecm.directory.DirectoryException; 045import org.nuxeo.ecm.directory.Session; 046import org.nuxeo.ecm.directory.api.DirectoryService; 047import org.nuxeo.ecm.platform.audit.api.AuditReader; 048import org.nuxeo.ecm.platform.audit.api.LogEntry; 049import org.nuxeo.ecm.platform.audit.api.Logs; 050import org.nuxeo.ecm.platform.audit.service.LogEntryProvider; 051import org.nuxeo.runtime.api.Framework; 052import org.nuxeo.runtime.transaction.TransactionHelper; 053 054/** 055 * Seam component performing errors 056 * 057 * @author Anahide Tchertchian 058 */ 059@Name("errorSeamComponent") 060@Scope(ScopeType.CONVERSATION) 061public class SeamErrorComponent implements Serializable { 062 063 private static final long serialVersionUID = 1L; 064 065 private static final Log log = LogFactory.getLog(SeamErrorComponent.class); 066 067 @In(create = true, required = false) 068 protected transient CoreSession documentManager; 069 070 protected void createNewDocument() { 071 if (documentManager == null) { 072 log.error("********** Unexpected exception while testing " 073 + "error handling: documentManager is null ***********"); 074 } 075 DocumentModel newDocument = documentManager.createDocumentModel("Workspace"); 076 String title = "Test document"; 077 newDocument.setProperty("dublincore", "title", "Test document"); 078 String parentDocumentPath = "/default-domain/workspaces"; 079 String name = IdUtils.generateId(title, "-", true, 24); 080 newDocument.setPathInfo(parentDocumentPath, name); 081 082 newDocument = documentManager.createDocument(newDocument); 083 documentManager.save(); 084 } 085 086 public void checkedErrorAfterCreation() { 087 createNewDocument(); 088 throw new NuxeoException("Checked exception after document creation"); 089 } 090 091 public void uncheckedErrorAfterCreation() { 092 try { 093 createNewDocument(); 094 } catch (NuxeoException e) { 095 log.error("********** Unexpected exception while testing error handling ***********"); 096 } 097 throw new NullPointerException("Unchecked exception after document creation"); 098 } 099 100 public String getCheckedError() { 101 throw new NuxeoException("Checked error on getter"); 102 } 103 104 public String getUncheckedError() { 105 throw new NullPointerException("Unchecked error on getter"); 106 } 107 108 public String getSecurityError() throws DocumentSecurityException { 109 throw new DocumentSecurityException("Security error on getter"); 110 } 111 112 @Factory(value = "checkedErrorFactoryEvent", scope = EVENT) 113 public String getCheckedErrorFactoryEvent() { 114 throw new NuxeoException("Checked error on factory, scope event"); 115 } 116 117 @Factory(value = "uncheckedErrorFactoryEvent", scope = EVENT) 118 public String getUncheckedErrorFactoryEvent() { 119 throw new NullPointerException("Unchecked error on factory, scope event"); 120 } 121 122 @Factory(value = "securityErrorFactoryEvent", scope = EVENT) 123 public String getSecurityErrorFactoryEvent() throws DocumentSecurityException { 124 throw new DocumentSecurityException("Security error on factory, scope event"); 125 } 126 127 public String performCheckedError() { 128 throw new NuxeoException("Checked error on action"); 129 } 130 131 public String performUncheckedError() { 132 throw new NullPointerException("Unchecked error on action"); 133 } 134 135 public String performSecurityError() throws DocumentSecurityException { 136 throw new DocumentSecurityException("Security error on action"); 137 } 138 139 /** 140 * @since 5.8 141 */ 142 public String performRecoverableClientException() throws RecoverableClientException { 143 throw new RecoverableClientException("Application validation failed, rollingback", 144 "Application validation failed, rollingback", null); 145 } 146 147 /** 148 * @since 5.8 149 */ 150 public String performPureRollback() { 151 TransactionHelper.setTransactionRollbackOnly(); 152 return null; 153 } 154 155 /** 156 * @since 5.9.5 157 */ 158 public void performDistributedRollback() { 159 createDummyUser(); 160 createDummyLogEntry(); 161 createDummyDoc(); 162 TransactionHelper.setTransactionRollbackOnly(); 163 } 164 165 /** 166 * @since 5.9.5 167 */ 168 public void clearDistributedRollbackEnv() { 169 clearDummyUser(); 170 clearDummyDoc(); 171 clearDummyLogEntries(); 172 } 173 174 protected DocumentModel createDummyUser() { 175 DirectoryService directories = Framework.getLocalService(DirectoryService.class); 176 try (Session userDir = directories.getDirectory("userDirectory").getSession()) { 177 Map<String, Object> user = new HashMap<>(); 178 user.put("username", "dummy"); 179 user.put("password", "dummy"); 180 user.put("firstName", "dummy"); 181 user.put("lastName", "dummy"); 182 return userDir.createEntry(user); 183 } 184 } 185 186 protected void clearDummyUser() throws DirectoryException { 187 DirectoryService directories = Framework.getLocalService(DirectoryService.class); 188 try (Session userDir = directories.open("userDirectory")) { 189 userDir.deleteEntry("dummy"); 190 } 191 } 192 193 /** 194 * @since 5.9.5 195 */ 196 @Factory(scope = ScopeType.EVENT) 197 public boolean isDummyUserExists() throws DirectoryException { 198 DirectoryService directories = Framework.getLocalService(DirectoryService.class); 199 try (Session userDir = directories.getDirectory("userDirectory").getSession()) { 200 DocumentModel user = userDir.getEntry("dummy"); 201 return user != null; 202 } catch (DirectoryException cause) { 203 return false; 204 } 205 } 206 207 protected LogEntry createDummyLogEntry() { 208 Logs logs = Framework.getLocalService(Logs.class); 209 LogEntry entry = logs.newLogEntry(); 210 entry.setEventId("dummy"); 211 entry.setDocUUID("dummy"); 212 entry.setCategory("dummy"); 213 entry.setComment("dummy"); 214 logs.addLogEntries(Collections.singletonList(entry)); 215 return entry; 216 } 217 218 /** 219 * @since 5.9.5 220 */ 221 public void clearDummyLogEntries() { 222 PersistenceProviderFactory pf = Framework.getService(PersistenceProviderFactory.class); 223 EntityManager em = pf.newProvider("nxaudit-logs").acquireEntityManager(); 224 LogEntryProvider provider = LogEntryProvider.createProvider(em); 225 provider.removeEntries("dummy", null); 226 } 227 228 /** 229 * @since 5.9.5 230 */ 231 @Factory(scope = ScopeType.EVENT) 232 public boolean isDummyAuditExists() { 233 AuditReader reader = Framework.getLocalService(AuditReader.class); 234 List<LogEntry> entries = reader.getLogEntriesFor("dummy"); 235 return !entries.isEmpty(); 236 } 237 238 protected DocumentModel createDummyDoc() { 239 DocumentModel doc = documentManager.createDocumentModel("/", "dummy", "Document"); 240 doc = documentManager.createDocument(doc); 241 documentManager.save(); 242 return doc; 243 } 244 245 /** 246 * @since 5.9.5 247 */ 248 public void clearDummyDoc() { 249 PathRef ref = new PathRef("/dummy"); 250 if (documentManager.exists(ref)) { 251 documentManager.removeDocument(ref); 252 } 253 } 254 255 /** 256 * @since 5.9.5 257 */ 258 @Factory(scope = ScopeType.EVENT) 259 public boolean isDummyDocExists() { 260 return documentManager.exists(new PathRef("/dummy")); 261 } 262 263 // methods to test concurrency issues 264 265 protected int counter = 0; 266 267 /** 268 * @since 5.8 269 */ 270 public String performConcurrentRequestTimeoutException() throws Exception { 271 Thread.sleep(15 * 1000); 272 counter++; 273 return null; 274 } 275 276 public int getCounterValue() { 277 return counter; 278 } 279 280}