CasStorageServiceImpl implements CasStorageService { @Override public CAS readOrCreateCas(SourceDocument aDocument, String aUsername, CasUpgradeMode aUpgradeMode, CasProvider aSupplier, CasAccessMode aAccessMode) throws IOException, CasSessionException { CasStorageSession session = CasStorageSession.get(); Optional<SessionManagedCas> mCas = session.getManagedState(aDocument.getId(), aUsername); if (mCas.isPresent() && mCas.get().getMode().alsoPermits(aAccessMode)) { return mCas.get().getCas(); } CasHolder casHolder; if (EXCLUSIVE_WRITE_ACCESS.equals(aAccessMode)) { CasKey key = null; CasHolder holder = null; try { log.trace("CAS storage session [{}]: borrowing CAS [{}]@[{}]({})", session.hashCode(), aUsername, aDocument.getName(), aDocument.getId()); key = new CasKey(aDocument, aUsername); holder = borrowCas(key); if (!holder.isCasSet()) { CasKey finalKey = key; CasHolder finalHolder = holder; CAS cas = readOrCreateUnmanagedCas(aDocument, aUsername, aSupplier, aUpgradeMode); holder.setCas(cas); ((CASImpl) getRealCas(cas)) .setOwner(_cas -> returnBorrowedCas(_cas, finalKey, finalHolder)); log.trace( "CAS storage session [{}]: borrowed CAS [{}] for [{}]@[{}]({}) loaded from storage", session.hashCode(), holder.getCasHashCode(), aUsername, aDocument.getName(), aDocument.getId()); } else { log.trace( "CAS storage session [{}]: borrowed CAS [{}] for [{}]@[{}]({}) was already in memory", session.hashCode(), holder.getCasHashCode(), aUsername, aDocument.getName(), aDocument.getId()); transferCasOwnershipToCurrentThread(holder.getCas()); repairAndUpgradeCasIfRequired(aDocument, aUsername, holder.getCas(), aUpgradeMode, ISOLATED_SESSION); } casHolder = holder; } catch (Exception e) { if (key != null && holder != null) { log.trace( "CAS storage session [{}]: returning borrowed CAS [{}] for [{}]@[{}]({}) after failure to load CAS", session.hashCode(), holder.getCasHashCode(), aUsername, aDocument.getName(), aDocument.getId()); try { exclusiveAccessPool.returnObject(key, holder); logExclusiveAccessHolders(); } catch (Exception e1) { log.error("Unable to return CAS to exclusive access pool", e1); } } casHolder = new CasHolder(key, e); } } else if (SHARED_READ_ONLY_ACCESS.equals(aAccessMode)) { if (!AUTO_CAS_UPGRADE.equals(aUpgradeMode)) { throw new IllegalArgumentException("When requsting a shared read-only CAS, the " + "access mode must be " + AUTO_CAS_UPGRADE); } casHolder = sharedAccessCache.get(new CasKey(aDocument, aUsername), (key) -> CasHolder.of(key, () -> getRealCas(readOrCreateUnmanagedCas(aDocument, aUsername, aSupplier, aUpgradeMode)))); } else if (UNMANAGED_ACCESS.equals(aAccessMode)) { casHolder = CasHolder.of(new CasKey(aDocument, aUsername), () -> readOrCreateUnmanagedCas(aDocument, aUsername, aSupplier, aUpgradeMode)); } else if (UNMANAGED_NON_INITIALIZING_ACCESS.equals(aAccessMode)) { casHolder = CasHolder.of(new CasKey(aDocument, aUsername), () -> readUnmanagedCas(aDocument, aUsername)); } else { throw new IllegalArgumentException("Unknown CAS access mode [" + aAccessMode + "]"); } if (casHolder.getException() != null) { if (casHolder.getException() instanceof IOException) { throw (IOException) casHolder.getException(); } throw new IOException(casHolder.getException()); } CAS cas = casHolder.getCas(); if (aAccessMode.isSessionManaged()) { session.add(aDocument.getId(), aUsername, aAccessMode, cas).incrementReadCount(); } return cas; } CasStorageServiceImpl(
            @Autowired(required = false) CasDoctor aCasDoctor,
            @Autowired(required = false) AnnotationSchemaService aSchemaService,
            @Autowired RepositoryProperties aRepositoryProperties,
            @Autowired BackupProperties aBackupProperties); @Override void writeCas(SourceDocument aDocument, CAS aCas, String aUserName); @Override CAS readCas(SourceDocument aDocument, String aUsername); @Override CAS readCas(SourceDocument aDocument, String aUsername, CasAccessMode aAccessMode); @Override CAS readOrCreateCas(SourceDocument aDocument, String aUsername,
            CasUpgradeMode aUpgradeMode, CasProvider aSupplier, CasAccessMode aAccessMode); @Override boolean deleteCas(SourceDocument aDocument, String aUsername); @Override void analyzeAndRepair(SourceDocument aDocument, String aUsername, CAS aCas); @Override File getCasFile(SourceDocument aDocument, String aUser); File getCasFile(long aProjectId, long aDocumentId, String aUser); @Override void upgradeCas(SourceDocument aDocument, String aUser); @Override boolean existsCas(SourceDocument aDocument, String aUser); @Override Optional<Long> getCasTimestamp(SourceDocument aDocument, String aUser); @Override File getAnnotationFolder(SourceDocument aDocument); File getAnnotationFolder(long aProjectId, long aDocumentId); @TransactionalEventListener(fallbackExecution = true) @Transactional void beforeLayerConfigurationChanged(LayerConfigurationChangedEvent aEvent);  }
@Test public void testReadOrCreateCas() throws Exception { SourceDocument doc = makeSourceDocument(2l, 2l); String user = "test"; String text = "This is a test"; createCasFile(doc, user, text); JCas cas = sut.readCas(doc, user).getJCas(); assertThat(cas.getDocumentText()).isEqualTo(text); sut.deleteCas(doc, user); assertThat(sut.getCasFile(doc, user)).doesNotExist(); assertThat(sut.existsCas(doc, user)).isFalse(); }