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