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 DocumentModel newDocument = documentManager.createDocumentModel("Workspace"); 074 String title = "Test document"; 075 newDocument.setProperty("dublincore", "title", "Test document"); 076 String parentDocumentPath = "/default-domain/workspaces"; 077 String name = IdUtils.generateId(title, "-", true, 24); 078 newDocument.setPathInfo(parentDocumentPath, name); 079 080 newDocument = documentManager.createDocument(newDocument); 081 documentManager.save(); 082 } 083 084 public void checkedErrorAfterCreation() { 085 createNewDocument(); 086 throw new NuxeoException("Checked exception after document creation"); 087 } 088 089 public void uncheckedErrorAfterCreation() { 090 try { 091 createNewDocument(); 092 } catch (NuxeoException e) { 093 log.error("********** Unexpected exception while testing error handling ***********"); 094 } 095 throw new NullPointerException("Unchecked exception after document creation"); 096 } 097 098 public String getCheckedError() { 099 throw new NuxeoException("Checked error on getter"); 100 } 101 102 public String getUncheckedError() { 103 throw new NullPointerException("Unchecked error on getter"); 104 } 105 106 public String getSecurityError() throws DocumentSecurityException { 107 throw new DocumentSecurityException("Security error on getter"); 108 } 109 110 @Factory(value = "checkedErrorFactoryEvent", scope = EVENT) 111 public String getCheckedErrorFactoryEvent() { 112 throw new NuxeoException("Checked error on factory, scope event"); 113 } 114 115 @Factory(value = "uncheckedErrorFactoryEvent", scope = EVENT) 116 public String getUncheckedErrorFactoryEvent() { 117 throw new NullPointerException("Unchecked error on factory, scope event"); 118 } 119 120 @Factory(value = "securityErrorFactoryEvent", scope = EVENT) 121 public String getSecurityErrorFactoryEvent() throws DocumentSecurityException { 122 throw new DocumentSecurityException("Security error on factory, scope event"); 123 } 124 125 public String performCheckedError() { 126 throw new NuxeoException("Checked error on action"); 127 } 128 129 public String performUncheckedError() { 130 throw new NullPointerException("Unchecked error on action"); 131 } 132 133 public String performSecurityError() throws DocumentSecurityException { 134 throw new DocumentSecurityException("Security error on action"); 135 } 136 137 /** 138 * @since 5.8 139 */ 140 public String performRecoverableClientException() throws RecoverableClientException { 141 throw new RecoverableClientException("Application validation failed, rollingback", 142 "Application validation failed, rollingback", null); 143 } 144 145 /** 146 * @since 5.8 147 */ 148 public String performPureRollback() { 149 TransactionHelper.setTransactionRollbackOnly(); 150 return null; 151 } 152 153 /** 154 * @since 5.9.5 155 */ 156 public void performDistributedRollback() { 157 createDummyUser(); 158 createDummyLogEntry(); 159 createDummyDoc(); 160 TransactionHelper.setTransactionRollbackOnly(); 161 } 162 163 /** 164 * @since 5.9.5 165 */ 166 public void clearDistributedRollbackEnv() { 167 clearDummyUser(); 168 clearDummyDoc(); 169 clearDummyLogEntries(); 170 } 171 172 protected DocumentModel createDummyUser() { 173 DirectoryService directories = Framework.getService(DirectoryService.class); 174 try (Session userDir = directories.getDirectory("userDirectory").getSession()) { 175 Map<String, Object> user = new HashMap<>(); 176 user.put("username", "dummy"); 177 user.put("password", "dummy"); 178 user.put("firstName", "dummy"); 179 user.put("lastName", "dummy"); 180 return userDir.createEntry(user); 181 } 182 } 183 184 protected void clearDummyUser() throws DirectoryException { 185 DirectoryService directories = Framework.getService(DirectoryService.class); 186 try (Session userDir = directories.open("userDirectory")) { 187 userDir.deleteEntry("dummy"); 188 } 189 } 190 191 /** 192 * @since 5.9.5 193 */ 194 @Factory(scope = ScopeType.EVENT) 195 public boolean isDummyUserExists() throws DirectoryException { 196 DirectoryService directories = Framework.getService(DirectoryService.class); 197 try (Session userDir = directories.getDirectory("userDirectory").getSession()) { 198 DocumentModel user = userDir.getEntry("dummy"); 199 return user != null; 200 } catch (DirectoryException cause) { 201 return false; 202 } 203 } 204 205 protected LogEntry createDummyLogEntry() { 206 Logs logs = Framework.getService(Logs.class); 207 LogEntry entry = logs.newLogEntry(); 208 entry.setEventId("dummy"); 209 entry.setDocUUID("dummy"); 210 entry.setCategory("dummy"); 211 entry.setComment("dummy"); 212 logs.addLogEntries(Collections.singletonList(entry)); 213 return entry; 214 } 215 216 /** 217 * @since 5.9.5 218 */ 219 public void clearDummyLogEntries() { 220 PersistenceProviderFactory pf = Framework.getService(PersistenceProviderFactory.class); 221 EntityManager em = pf.newProvider("nxaudit-logs").acquireEntityManager(); 222 LogEntryProvider provider = LogEntryProvider.createProvider(em); 223 provider.removeEntries("dummy", null); 224 } 225 226 /** 227 * @since 5.9.5 228 */ 229 @Factory(scope = ScopeType.EVENT) 230 public boolean isDummyAuditExists() { 231 AuditReader reader = Framework.getService(AuditReader.class); 232 List<LogEntry> entries = reader.getLogEntriesFor("dummy"); 233 return !entries.isEmpty(); 234 } 235 236 protected DocumentModel createDummyDoc() { 237 DocumentModel doc = documentManager.createDocumentModel("/", "dummy", "Document"); 238 doc = documentManager.createDocument(doc); 239 documentManager.save(); 240 return doc; 241 } 242 243 /** 244 * @since 5.9.5 245 */ 246 public void clearDummyDoc() { 247 PathRef ref = new PathRef("/dummy"); 248 if (documentManager.exists(ref)) { 249 documentManager.removeDocument(ref); 250 } 251 } 252 253 /** 254 * @since 5.9.5 255 */ 256 @Factory(scope = ScopeType.EVENT) 257 public boolean isDummyDocExists() { 258 return documentManager.exists(new PathRef("/dummy")); 259 } 260 261 // methods to test concurrency issues 262 263 protected int counter = 0; 264 265 /** 266 * @since 5.8 267 */ 268 public String performConcurrentRequestTimeoutException() throws Exception { 269 Thread.sleep(15 * 1000); 270 counter++; 271 return null; 272 } 273 274 public int getCounterValue() { 275 return counter; 276 } 277 278}