@Override public void run() { log.info("start of thread " + Thread.currentThread().getName()); try { TransactionHelper.startTransaction(); CoreSession s = null; try { s = openSessionAs(SecurityConstants.ADMINISTRATOR); Thread.sleep(sleepMillis); } finally { try { if (s != null) { closeSession(s); } } finally { TransactionHelper.commitOrRollbackTransaction(); } } } catch (Exception e) { if (threadException == null) { threadException = e; } } log.info("end of thread " + Thread.currentThread().getName()); }
protected void triggerReloadWithNewTransaction(String id) { if (TransactionHelper.isTransactionMarkedRollback()) { throw new AssertionError("The calling transaction is marked rollback"); } else if (TransactionHelper.isTransactionActive()) { // should flush // the calling // transaction TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); } try { try { triggerReload(id); } catch (RuntimeException cause) { TransactionHelper.setTransactionRollbackOnly(); throw cause; } } finally { if (TransactionHelper.isTransactionActiveOrMarkedRollback()) { boolean wasRollbacked = TransactionHelper.isTransactionMarkedRollback(); TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); if (wasRollbacked) { TransactionHelper.setTransactionRollbackOnly(); } } } }
@Override public void undeployBundle(String bundleName) throws BundleException { if (bundleName == null) { // ignore return; } log.info( String.format( "Before undeploy bundle with name '%s'.\n" + "%s", bundleName, getRuntimeStatus())); BundleContext ctx = getBundleContext(); ServiceReference ref = ctx.getServiceReference(PackageAdmin.class.getName()); PackageAdmin srv = (PackageAdmin) ctx.getService(ref); try { for (Bundle b : srv.getBundles(bundleName, null)) { if (b != null && b.getState() == Bundle.ACTIVE) { Transaction tx = TransactionHelper.suspendTransaction(); try { b.stop(); b.uninstall(); } finally { TransactionHelper.resumeTransaction(tx); } } } } finally { ctx.ungetService(ref); } log.info(String.format("Undeploy done.\n" + "%s", getRuntimeStatus())); }
@GET public Blob convert( @QueryParam("converter") String converter, @QueryParam("type") String type, @QueryParam("format") String format, @Context UriInfo uriInfo) { BlobHolder bh = getBlobHolderToConvert(); boolean txWasActive = false; try { if (TransactionHelper.isTransactionActive()) { txWasActive = true; TransactionHelper.commitOrRollbackTransaction(); } if (StringUtils.isNotBlank(converter)) { return convertWithConverter(bh, converter, uriInfo); } else if (StringUtils.isNotBlank(type)) { return convertWithMimeType(bh, type, uriInfo); } else if (StringUtils.isNotBlank(format)) { return convertWithFormat(bh, format, uriInfo); } else { throw new IllegalParameterException("No converter, type or format parameter specified"); } } finally { if (txWasActive && !TransactionHelper.isTransactionActiveOrMarkedRollback()) { TransactionHelper.startTransaction(); } } }
protected void awaitCollectionWorks() throws InterruptedException { TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); workManager.awaitCompletion( CollectionConstants.COLLECTION_QUEUE_ID, WORK_TIME_OUT_MS, TimeUnit.MILLISECONDS); assertEquals(0, workManager.getQueueSize(CollectionConstants.COLLECTION_QUEUE_ID, null)); }
@Test public void doesntLeakWithoutTx() { TransactionHelper.commitOrRollbackTransaction(); try { checkSessionLeak(); } finally { TransactionHelper.startTransaction(); } }
protected void setPermission( DocumentModel doc, String userName, String permission, boolean isGranted) { ACP acp = session.getACP(doc.getRef()); ACL localACL = acp.getOrCreateACL(ACL.LOCAL_ACL); localACL.add(new ACE(userName, permission, isGranted)); session.setACP(doc.getRef(), acp, true); TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); }
public void startTransaction() { if (syncMode) { ElasticSearchInlineListener.useSyncIndexing.set(true); } if (!TransactionHelper.isTransactionActive()) { TransactionHelper.startTransaction(); } Assert.assertEquals(0, esa.getPendingWorkerCount()); commandProcessed = esa.getTotalCommandProcessed(); }
@Test public void shouldDenyAccessOnUnsupportedACL() throws Exception { assumeTrue(session.isNegativeAclAllowed()); buildAndIndexTree(); DocumentModelList docs = ess.query(new NxQueryBuilder(session).nxql("select * from Document")); Assert.assertEquals(10, docs.totalSize()); // check for user with no rights CoreSession restrictedSession = getRestrictedSession("toto"); try { docs = ess.query(new NxQueryBuilder(restrictedSession).nxql("select * from Document")); Assert.assertEquals(0, docs.totalSize()); // add READ rights and check that user now has access DocumentRef ref = new PathRef("/folder0/folder1/folder2"); ACP acp = new ACPImpl(); ACL acl = ACPImpl.newACL(ACL.LOCAL_ACL); acl.add(new ACE("toto", SecurityConstants.READ, true)); acp.addACL(acl); session.setACP(ref, acp, true); TransactionHelper.commitOrRollbackTransaction(); waitForCompletion(); startTransaction(); docs = ess.query( new NxQueryBuilder(restrictedSession) .nxql("select * from Document order by dc:title")); Assert.assertEquals(8, docs.totalSize()); // Add an unsupported negative ACL ref = new PathRef("/folder0/folder1/folder2/folder3/folder4/folder5"); acp = new ACPImpl(); acl = ACPImpl.newACL(ACL.LOCAL_ACL); acl.add(new ACE("bob", SecurityConstants.EVERYTHING, false)); acp.addACL(acl); session.setACP(ref, acp, true); session.save(); TransactionHelper.commitOrRollbackTransaction(); waitForCompletion(); startTransaction(); docs = ess.query( new NxQueryBuilder(restrictedSession) .nxql("select * from Document order by dc:title")); // can view folder2, folder3 and folder4 Assert.assertEquals(3, docs.totalSize()); } finally { restrictedSession.close(); } }
@Test public void shouldStoreOnlyEffectiveACEs() throws Exception { buildAndIndexTree(); DocumentModelList docs = ess.query(new NxQueryBuilder(session).nxql("select * from Document")); Assert.assertEquals(10, docs.totalSize()); CoreSession restrictedSession = getRestrictedSession("toto"); try { docs = ess.query(new NxQueryBuilder(restrictedSession).nxql("select * from Document")); Assert.assertEquals(0, docs.totalSize()); DocumentRef ref = new PathRef("/folder0"); ACP acp = new ACPImpl(); ACL acl = ACPImpl.newACL(ACL.LOCAL_ACL); acl.add(ACE.builder("toto", SecurityConstants.READ).build()); acp.addACL(acl); session.setACP(ref, acp, true); TransactionHelper.commitOrRollbackTransaction(); waitForCompletion(); startTransaction(); docs = ess.query( new NxQueryBuilder(restrictedSession) .nxql("select * from Document order by dc:title")); Assert.assertEquals(10, docs.totalSize()); acp = new ACPImpl(); acl = ACPImpl.newACL(ACL.LOCAL_ACL); // make the ACE archived Date now = new Date(); Calendar begin = new GregorianCalendar(); begin.setTimeInMillis(now.toInstant().minus(10, ChronoUnit.DAYS).toEpochMilli()); Calendar end = new GregorianCalendar(); end.setTimeInMillis(now.toInstant().minus(2, ChronoUnit.DAYS).toEpochMilli()); acl.add(ACE.builder("toto", SecurityConstants.READ).begin(begin).end(end).build()); acp.addACL(acl); session.setACP(ref, acp, true); TransactionHelper.commitOrRollbackTransaction(); waitForCompletion(); startTransaction(); docs = ess.query( new NxQueryBuilder(restrictedSession) .nxql("select * from Document order by dc:title")); Assert.assertEquals(0, docs.totalSize()); } finally { restrictedSession.close(); } }
protected void resetPermissions(DocumentRef docRef, String userName) { ACP acp = session.getACP(docRef); ACL localACL = acp.getOrCreateACL(ACL.LOCAL_ACL); Iterator<ACE> localACLIt = localACL.iterator(); while (localACLIt.hasNext()) { ACE ace = localACLIt.next(); if (userName.equals(ace.getUsername())) { localACLIt.remove(); } } session.setACP(docRef, acp, true); TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); }
@Test public void shouldUnIndexSubTree() throws Exception { buildAndIndexTree(); DocumentRef ref = new PathRef("/folder0/folder1/folder2"); Assert.assertTrue(session.exists(ref)); startTransaction(); session.removeDocument(ref); TransactionHelper.commitOrRollbackTransaction(); waitForCompletion(); assertNumberOfCommandProcessed(1); startTransaction(); SearchResponse searchResponse = esa.getClient() .prepareSearch(IDX_NAME) .setTypes(TYPE_NAME) .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setFrom(0) .setSize(60) .execute() .actionGet(); Assert.assertEquals(2, searchResponse.getHits().getTotalHits()); }
@Test public void shouldFilterLogEntriesOnEventCategories() throws Exception { DocumentModel doc = RestServerInit.getFile(1, session); List<LogEntry> logEntries = new ArrayList<>(); LogEntry logEntry = auditLogger.newLogEntry(); logEntry.setDocUUID(doc.getRef()); logEntry.setCategory("One"); logEntry.setEventId("firstEvent"); logEntries.add(logEntry); logEntry = auditLogger.newLogEntry(); logEntry.setDocUUID(doc.getRef()); logEntry.setCategory("One"); logEntry.setEventId("secondEvent"); logEntries.add(logEntry); logEntry = auditLogger.newLogEntry(); logEntry.setDocUUID(doc.getRef()); logEntry.setCategory("Two"); logEntry.setEventId("firstEvent"); logEntries.add(logEntry); auditLogger.addLogEntries(logEntries); TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("category", "One"); queryParams.add("category", "Two"); ClientResponse response = getResponse( BaseTest.RequestType.GET, "id/" + doc.getId() + "/@" + AuditAdapter.NAME, queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); List<JsonNode> nodes = getLogEntries(node); assertEquals(3, nodes.size()); queryParams = new MultivaluedMapImpl(); queryParams.add("category", "Two"); response = getResponse( BaseTest.RequestType.GET, "id/" + doc.getId() + "/@" + AuditAdapter.NAME, queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); node = mapper.readTree(response.getEntityInputStream()); nodes = getLogEntries(node); assertEquals(1, nodes.size()); }
protected void commit(boolean force) { uploadedFiles++; if (uploadedFiles % 10 == 0) { GenericMultiThreadedImporter.addCreatedDoc(taskId, uploadedFiles); } if (uploadedFiles % batchSize == 0 || force) { Stopwatch stopwatch = SimonManager.getStopwatch("org.nuxeo.ecm.platform.importer.session_save"); Split split = stopwatch.start(); fslog("Committing Core Session after " + uploadedFiles + " files", true); session.save(); TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(transactionTimeout); split.stop(); } }
protected void doTestMultipleRepositoriesPerTransaction(CoreSession session2) throws Exception { assertEquals(database.getRepositoryName(), session.getRepositoryName()); assertEquals(database.getRepositoryName() + "2", session2.getRepositoryName()); assertTrue(TransactionHelper.isTransactionActive()); assertNotSame( "Sessions from two different repos", session.getRootDocument().getId(), session2.getRootDocument().getId()); }
@Override public String deployBundle(File file, boolean reloadResourceClasspath) throws BundleException { String name = getOSGIBundleName(file); if (name == null) { log.error( String.format( "No Bundle-SymbolicName found in MANIFEST for jar at '%s'", file.getAbsolutePath())); return null; } String path = file.getAbsolutePath(); log.info( String.format("Before deploy bundle for file at '%s'\n" + "%s", path, getRuntimeStatus())); if (reloadResourceClasspath) { URL url; try { url = new File(path).toURI().toURL(); } catch (MalformedURLException e) { throw new RuntimeException(e); } Framework.reloadResourceLoader(Arrays.asList(url), null); } // check if this is a bundle first Bundle newBundle = getBundleContext().installBundle(path); if (newBundle == null) { throw new IllegalArgumentException("Could not find a valid bundle at path: " + path); } Transaction tx = TransactionHelper.suspendTransaction(); try { newBundle.start(); } finally { TransactionHelper.resumeTransaction(tx); } log.info( String.format( "Deploy done for bundle with name '%s'.\n" + "%s", newBundle.getSymbolicName(), getRuntimeStatus())); return newBundle.getSymbolicName(); }
protected void flushAndSync() throws Exception { TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); Assert.assertTrue(Framework.getLocalService(AuditLogger.class).await(10, TimeUnit.SECONDS)); esa.getClient() .admin() .indices() .prepareFlush(esa.getIndexNameForType(ElasticSearchConstants.ENTRY_TYPE)) .execute() .actionGet(); esa.getClient() .admin() .indices() .prepareRefresh(esa.getIndexNameForType(ElasticSearchConstants.ENTRY_TYPE)) .execute() .actionGet(); }
public static CoreSession wrap(CoreSession session) { try { TransactionHelper.lookupTransactionManager(); } catch (NamingException e) { // no transactions, do not wrap return session; } ClassLoader cl = session.getClass().getClassLoader(); return (CoreSession) Proxy.newProxyInstance(cl, INTERFACES, new TransactionalCoreSessionWrapper(session)); }
public synchronized void run() { TransactionHelper.startTransaction(transactionTimeout); synchronized (this) { if (isRunning) { throw new IllegalStateException("Task already running"); } isRunning = true; // versions have no path, target document can be null if (rootSource == null) { isRunning = false; throw new IllegalArgumentException("source node must be specified"); } } try { session = CoreInstance.openCoreSessionSystem(repositoryName); log.info("Starting new import task"); if (rootDoc != null) { // reopen the root to be sure the session is valid rootDoc = session.getDocument(rootDoc.getRef()); } recursiveCreateDocumentFromNode(rootDoc, rootSource); session.save(); GenericMultiThreadedImporter.addCreatedDoc(taskId, uploadedFiles); TransactionHelper.commitOrRollbackTransaction(); } catch (Exception e) { // deals with interrupt below log.error("Error during import", e); ExceptionUtils.checkInterrupt(e); notifyImportError(); } finally { log.info("End of task"); if (session != null) { session.close(); session = null; } synchronized (this) { isRunning = false; } } }
/** Creates the session. It will be destroyed by calling {@link #destroy}. */ protected SessionInfo createSession() { RepositoryService repositoryService = Framework.getLocalService(RepositoryService.class); Session session = repositoryService.getSession(repositoryName); TransactionHelper.registerSynchronization(this); SessionInfo si = new SessionInfo(session); sessionHolder.set(si); allSessions.add(si); if (log.isDebugEnabled()) { log.debug( "Adding thread " + Thread.currentThread().getName() + " for CoreSession: " + sessionId); } return si; }
@Override public void handleEvent(Event event) { if (!Framework.isDevModeSet()) { log.info("Do not flush the directory caches: dev mode is not set"); return; } if (!ReloadEventNames.RELOAD_EVENT_ID.equals(event.getId())) { return; } try { RepositoryManager rm = Framework.getService(RepositoryManager.class); // Transaction management final boolean txStarted = !TransactionHelper.isTransactionActive() && TransactionHelper.startTransaction(); boolean txSucceed = false; try { new UnrestrictedSessionRunner(rm.getDefaultRepositoryName()) { @Override public void run() { DocumentRoutingService service = Framework.getLocalService(DocumentRoutingService.class); service.importAllRouteModels(session); } }.runUnrestricted(); txSucceed = true; } finally { if (txStarted) { if (!txSucceed) { TransactionHelper.setTransactionRollbackOnly(); log.warn("Rollbacking import of route models"); } TransactionHelper.commitOrRollbackTransaction(); } } } catch (NuxeoException e) { log.error("Error while reloading the route models", e); } }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Transaction main = threadBound.get(); if (main == null) { // first call in thread try { main = TransactionHelper.lookupTransactionManager().getTransaction(); if (main != null) { if (main.getStatus() != Status.STATUS_MARKED_ROLLBACK) { main.registerSynchronization(this); session.afterBegin(); threadBound.set(main); } } } catch (NamingException e) { // no transaction manager, ignore } catch (Exception e) { log.error("Error on transaction synchronizer registration", e); } checkTxActiveRequired(method); } try { return method.invoke(session, args); } catch (Throwable t) { if (TransactionHelper.isTransactionActive() && needsRollback(method, t)) { TransactionHelper.setTransactionRollbackOnly(); } if (t instanceof InvocationTargetException) { Throwable tt = ((InvocationTargetException) t).getTargetException(); if (tt != null) { throw tt; } } throw t; } }
@Test public void doesntReleaseBeforeCommit() { TransactionHelper.commitOrRollbackTransaction(); assertEquals(0, activeConnectionCount()); assertEquals(0, threadAllocatedConnectionsCount()); closeSession(); TransactionHelper.startTransaction(); try { try (CoreSession first = openSessionAs("jdoe")) { assertEquals(1, threadAllocatedConnectionsCount()); assertEquals(1, activeConnectionCount()); try (CoreSession second = openSessionAs("jdoe")) { assertEquals(2, threadAllocatedConnectionsCount()); assertEquals(1, activeConnectionCount()); TransactionHelper.commitOrRollbackTransaction(); assertEquals(0, threadAllocatedConnectionsCount()); assertEquals(0, activeConnectionCount()); } } assertEquals(0, threadAllocatedConnectionsCount()); } finally { TransactionHelper.commitOrRollbackTransaction(); } }
@Test public void shouldIndexOnCopy() throws Exception { buildAndIndexTree(); DocumentRef src = new PathRef("/folder0/folder1/folder2"); DocumentRef dst = new PathRef("/folder0"); session.copy(src, dst, "folder2-copy"); TransactionHelper.commitOrRollbackTransaction(); waitForCompletion(); startTransaction(); DocumentModelList docs = ess.query(new NxQueryBuilder(session).nxql("select * from Document")); Assert.assertEquals(18, docs.totalSize()); }
@Override public Session getSession() { SessionInfo si = sessionHolder.get(); if (si == null || !si.session.isLive()) { // close old one, previously completed closeInThisThread(); if (!TransactionHelper.isTransactionActive()) { throw new LocalException("No transaction active, cannot reconnect: " + sessionId); } if (log.isDebugEnabled()) { log.debug("Reconnecting CoreSession: " + sessionId); } si = createSession(); } return si.session; }
@Test public void canLogMultipleLifecycleTransitionsInSameTx() throws ClientException { // generate events DocumentModel doc = repo.createDocumentModel("/", "a-file", "File"); doc = repo.createDocument(doc); String initialLifeCycle = doc.getCurrentLifeCycleState(); doc.followTransition(LifeCycleConstants.DELETE_TRANSITION); String deletedLifeCycle = doc.getCurrentLifeCycleState(); doc.followTransition(LifeCycleConstants.UNDELETE_TRANSITION); String undeletedLifeCycle = doc.getCurrentLifeCycleState(); TransactionHelper.commitOrRollbackTransaction(); Framework.getLocalService(EventService.class).waitForAsyncCompletion(); // test audit trail AuditReader reader = Framework.getLocalService(AuditReader.class); List<LogEntry> trail = reader.getLogEntriesFor(doc.getId()); assertThat(trail, notNullValue()); assertThat(trail.size(), is(3)); boolean seenDocCreated = false; boolean seenDocDeleted = false; boolean seenDocUndeleted = false; for (LogEntry entry : trail) { String lifeCycle = entry.getDocLifeCycle(); String id = entry.getEventId(); if (DocumentEventTypes.DOCUMENT_CREATED.equals(id)) { if (initialLifeCycle.equals(lifeCycle)) { seenDocCreated = true; } } else if (LifeCycleConstants.TRANSITION_EVENT.equals(id)) { if (undeletedLifeCycle.equals(lifeCycle)) { seenDocUndeleted = true; } else if (deletedLifeCycle.equals(lifeCycle)) { seenDocDeleted = true; } } } assertThat(seenDocUndeleted, is(true)); assertThat(seenDocDeleted, is(true)); assertThat(seenDocCreated, is(true)); }
protected void buildAndIndexTree() throws Exception { startTransaction(); buildTree(); TransactionHelper.commitOrRollbackTransaction(); waitForCompletion(); assertNumberOfCommandProcessed(10); startTransaction(); // check indexing at ES level SearchResponse searchResponse = esa.getClient() .prepareSearch(IDX_NAME) .setTypes(TYPE_NAME) .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setFrom(0) .setSize(60) .execute() .actionGet(); Assert.assertEquals(10, searchResponse.getHits().getTotalHits()); }
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { initIfNeeded(); if (request instanceof HttpServletRequest) { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; PathDescriptor pd = engine.getRequestConfiguration().getMatchingConfiguration(req); Config config = new Config(req, pd); AbstractWebContext ctx = initRequest(config, req, resp); if (config.txStarted) { resp = new BufferingHttpServletResponse(resp); } boolean completedAbruptly = true; try { preRequest(req, resp); chain.doFilter(request, resp); postRequest(req, resp); completedAbruptly = false; } finally { if (completedAbruptly) { TransactionHelper.setTransactionRollbackOnly(); } try { cleanup(config, ctx, req, resp); } catch (TransactionRuntimeException e) { // commit failed, report this to the client before stopping buffering resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); throw e; } finally { if (config.txStarted) { ((BufferingHttpServletResponse) resp).stopBuffering(); } } } } else { chain.doFilter(request, response); } }
@Override public void afterCompletion(int status) { Transaction current = null; try { current = TransactionHelper.lookupTransactionManager().getTransaction(); } catch (Exception e) { throw new Error("no tx", e); } Transaction main = threadBound.get(); if (main.equals(current)) { threadBound.remove(); } boolean committed; if (status == Status.STATUS_COMMITTED) { committed = true; } else if (status == Status.STATUS_ROLLEDBACK) { committed = false; } else { log.error("Unexpected status after completion: " + status); return; } session.afterCompletion(committed); }
@Test public void shouldReindexSubTreeInTrash() throws Exception { buildAndIndexTree(); startTransaction(); DocumentRef ref = new PathRef("/folder0/folder1/folder2"); Assert.assertTrue(session.exists(ref)); session.followTransition(ref, "delete"); TransactionHelper.commitOrRollbackTransaction(); // let the bulkLifeCycleChangeListener do its work waitForCompletion(); assertNumberOfCommandProcessed(8); startTransaction(); DocumentModelList docs = ess.query( new NxQueryBuilder(session) .nxql("select * from Document where ecm:currentLifeCycleState != 'deleted'")); // for (DocumentModel doc : docs) { // System.out.println(doc.getPathAsString()); // } Assert.assertEquals(2, docs.totalSize()); }