Java tutorial
/* * Copyright (c) 2008-2016 Haulmont. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.haulmont.cuba.core.app; import com.haulmont.chile.core.model.MetaClass; import com.haulmont.cuba.core.EntityManager; import com.haulmont.cuba.core.Persistence; import com.haulmont.cuba.core.Transaction; import com.haulmont.cuba.core.TypedQuery; import com.haulmont.cuba.core.entity.AppFolder; import com.haulmont.cuba.core.entity.BaseGenericIdEntity; import com.haulmont.cuba.core.entity.Folder; import com.haulmont.cuba.core.global.*; import com.haulmont.cuba.core.sys.CubaXStream; import com.haulmont.cuba.security.entity.EntityOp; import com.haulmont.cuba.security.entity.PermissionType; import com.haulmont.cuba.security.entity.SearchFolder; import com.haulmont.cuba.security.entity.User; import com.haulmont.cuba.security.global.UserSession; import com.thoughtworks.xstream.XStream; import groovy.lang.Binding; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.perf4j.StopWatch; import org.perf4j.slf4j.Slf4JStopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.inject.Inject; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Iterator; import java.util.List; import java.util.zip.CRC32; @Service(FoldersService.NAME) public class FoldersServiceBean implements FoldersService { private final Logger log = LoggerFactory.getLogger(FoldersServiceBean.class); @Inject protected UserSessionSource userSessionSource; @Inject protected Metadata metadata; @Inject protected Persistence persistence; @Inject protected Scripting scripting; @Inject protected Resources resources; @Inject protected Security security; @Inject protected TimeSource timeSource; @Override public List<AppFolder> loadAppFolders() { log.debug("Loading AppFolders"); StopWatch stopWatch = new Slf4JStopWatch("AppFolders"); stopWatch.start(); List<AppFolder> resultList; try (Transaction tx = persistence.createTransaction()) { String metaClassName = metadata.getExtendedEntities().getEffectiveMetaClass(AppFolder.class).getName(); TypedQuery<AppFolder> q = persistence.getEntityManager().createQuery( "select f from " + metaClassName + " f order by f.sortOrder, f.name", AppFolder.class); resultList = q.getResultList(); // fetch parent folder resultList.forEach(Folder::getParent); tx.commit(); } finally { stopWatch.stop(); } if (CollectionUtils.isNotEmpty(resultList)) { Binding binding = new Binding(); binding.setVariable("persistence", persistence); binding.setVariable("metadata", metadata); binding.setVariable("userSession", userSessionSource.getUserSession()); Iterator<AppFolder> iterator = resultList.iterator(); while (iterator.hasNext()) { AppFolder folder = iterator.next(); try (Transaction tx = persistence.createTransaction()) { boolean evaluatedVisibilityScript = true; try { if (!StringUtils.isBlank(folder.getVisibilityScript())) { binding.setVariable("folder", folder); Boolean visible = runScript(folder.getVisibilityScript(), binding); if (BooleanUtils.isFalse(visible)) { iterator.remove(); continue; } } } catch (Exception e) { log.warn("Unable to evaluate AppFolder visibility script for folder: id: {} name: {}", folder.getId(), folder.getName(), e); // because EclipseLink Query marks transaction as rollback-only on JPQL syntax errors evaluatedVisibilityScript = false; } boolean evaluatedQuantityScript = loadFolderQuantity(binding, folder); if (evaluatedVisibilityScript && evaluatedQuantityScript) { tx.commit(); } } } } return resultList; } protected <T> T runScript(String script, Binding binding) { script = StringUtils.trim(script); if (script.endsWith(".groovy")) { script = resources.getResourceAsString(script); } Object result = scripting.evaluateGroovy(script, binding); //noinspection unchecked return (T) result; } @Override public List<AppFolder> reloadAppFolders(List<AppFolder> folders) { log.debug("Reloading AppFolders {}", folders); StopWatch stopWatch = new Slf4JStopWatch("AppFolders"); stopWatch.start(); try { if (!folders.isEmpty()) { Binding binding = new Binding(); binding.setVariable("persistence", persistence); binding.setVariable("metadata", metadata); binding.setProperty("userSession", userSessionSource.getUserSession()); for (AppFolder folder : folders) { Transaction tx = persistence.createTransaction(); try { if (loadFolderQuantity(binding, folder)) { tx.commit(); } } finally { tx.end(); } } } return folders; } finally { stopWatch.stop(); } } protected boolean loadFolderQuantity(Binding binding, AppFolder folder) { if (!StringUtils.isBlank(folder.getQuantityScript())) { binding.setVariable("folder", folder); String styleVariable = "style"; binding.setVariable(styleVariable, null); try { Number qty = runScript(folder.getQuantityScript(), binding); folder.setItemStyle((String) binding.getVariable(styleVariable)); folder.setQuantity(qty == null ? null : qty.intValue()); } catch (Exception e) { log.warn("Unable to evaluate AppFolder quantity script for folder: id: {} , name: {}", folder.getId(), folder.getName(), e); return false; } } return true; } @Override public List<SearchFolder> loadSearchFolders() { log.debug("Loading SearchFolders"); StopWatch stopWatch = new Slf4JStopWatch("SearchFolders"); stopWatch.start(); Transaction tx = persistence.createTransaction(); try { EntityManager em = persistence.getEntityManager(); MetaClass effectiveMetaClass = metadata.getExtendedEntities().getEffectiveMetaClass(SearchFolder.class); TypedQuery<SearchFolder> q = em.createQuery( "select f from " + effectiveMetaClass.getName() + " f " + "left join fetch f.user u on u.id = ?1 " + "left join fetch f.presentation " + "where (u.id = ?1 or u is null) " + "order by f.sortOrder, f.name", SearchFolder.class); q.setParameter(1, userSessionSource.currentOrSubstitutedUserId()); List<SearchFolder> list = q.getResultList(); // fetch parents for (SearchFolder folder : list) { folder.getParent(); } tx.commit(); return list; } finally { tx.end(); stopWatch.stop(); } } @Override public byte[] exportFolder(Folder folder) throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(byteArrayOutputStream); zipOutputStream.setMethod(ZipArchiveOutputStream.STORED); zipOutputStream.setEncoding(StandardCharsets.UTF_8.name()); String xml = createXStream().toXML(folder); byte[] xmlBytes = xml.getBytes(StandardCharsets.UTF_8); ArchiveEntry zipEntryDesign = newStoredEntry("folder.xml", xmlBytes); zipOutputStream.putArchiveEntry(zipEntryDesign); zipOutputStream.write(xmlBytes); try { zipOutputStream.closeArchiveEntry(); } catch (Exception ex) { throw new RuntimeException( String.format("Exception occurred while exporting folder %s.", folder.getName())); } zipOutputStream.close(); return byteArrayOutputStream.toByteArray(); } @Override public Folder importFolder(Folder parentFolder, byte[] bytes) throws IOException { if (!security.isEntityOpPermitted(Folder.class, EntityOp.CREATE)) { throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); } Folder folder = null; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); ZipArchiveInputStream archiveReader; archiveReader = new ZipArchiveInputStream(byteArrayInputStream); ZipArchiveEntry archiveEntry; while (((archiveEntry = archiveReader.getNextZipEntry()) != null) && (folder == null)) { if (archiveEntry.getName().equals("folder.xml")) { String xml = new String(IOUtils.toByteArray(archiveReader), StandardCharsets.UTF_8); folder = (Folder) createXStream().fromXML(xml); } } byteArrayInputStream.close(); if (folder != null) { checkImportPermissions(folder); folder.setParent(parentFolder); Transaction tx = persistence.createTransaction(); try { EntityManager em = persistence.getEntityManager(); em.setSoftDeletion(false); Folder existingFolder = em.find(Folder.class, folder.getId()); if (existingFolder != null) { checkImportPermissions(existingFolder); folder.setVersion(existingFolder.getVersion()); folder.setCreateTs(existingFolder.getCreateTs()); folder.setCreatedBy(existingFolder.getCreatedBy()); } else { User user = userSessionSource.getUserSession().getUser(); folder.setCreatedBy(user.getLoginLowerCase()); folder.setCreateTs(timeSource.currentTimestamp()); folder.setUpdatedBy(null); folder.setUpdateTs(null); folder.setVersion(0); } em.merge(folder); tx.commit(); } finally { tx.end(); } } return folder; } protected void checkImportPermissions(Folder folder) { UserSession userSession = userSessionSource.getUserSession(); if (folder instanceof SearchFolder) { SearchFolder searchFolder = (SearchFolder) folder; User currentUser = userSession.getCurrentOrSubstitutedUser(); if (searchFolder.getUser() != null && !currentUser.equals(searchFolder.getUser())) { throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); } if (searchFolder.getUser() == null && !userSession.isSpecificPermitted("cuba.gui.searchFolder.global")) { throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); } } if (folder instanceof AppFolder) { if (!userSession.isSpecificPermitted("cuba.gui.appFolder.global")) { throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); } } } protected XStream createXStream() { XStream xStream = new CubaXStream(); //createTs and createdBy removed from BaseGenericIdEntity, //and import from old versions (platform 6.2) is performed with errors //so omit field processing xStream.omitField(BaseGenericIdEntity.class, "createTs"); xStream.omitField(BaseGenericIdEntity.class, "createdBy"); return xStream; } protected ArchiveEntry newStoredEntry(String name, byte[] data) { ZipArchiveEntry zipEntry = new ZipArchiveEntry(name); zipEntry.setSize(data.length); zipEntry.setCompressedSize(zipEntry.getSize()); CRC32 crc32 = new CRC32(); crc32.update(data); zipEntry.setCrc(crc32.getValue()); return zipEntry; } }