/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2014, MPL CodeInside http://codeinside.ru */ package ru.codeinside.adm; import commons.Streams; import org.codehaus.jackson.map.ObjectMapper; import ru.codeinside.adm.database.ExternalGlue; import ru.codeinside.adm.database.HttpLog; import ru.codeinside.adm.database.SmevLog; import ru.codeinside.adm.database.SoapPacket; import ru.codeinside.gses.API; import ru.codeinside.gses.webui.osgi.LogCustomizer; import ru.codeinside.gws.log.format.Metadata; import ru.codeinside.gws.log.format.Pack; import javax.ejb.DependsOn; import javax.ejb.Lock; import javax.ejb.LockType; import javax.ejb.Singleton; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionManagement; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import static javax.ejb.TransactionAttributeType.REQUIRES_NEW; @TransactionManagement @Singleton @Lock(LockType.READ) @DependsOn("BaseBean") public class LogConverter { @PersistenceContext(unitName = "myPU") EntityManager em; final Logger logger = Logger.getLogger(getClass().getName()); String dirPath; Storage storage; // test support public interface Storage { String getLazyDirPath(); SmevLog findLogEntry(String marker); void store(SmevLog smevLog); } public void setStorage(Storage storage) { this.storage = storage; } @TransactionAttribute(REQUIRES_NEW) public boolean logToBd() { if (storage == null) { storage = new Storage() { @Override public String getLazyDirPath() { return LogCustomizer.getStoragePath(); } @Override public SmevLog findLogEntry(String marker) { List<SmevLog> rs = em. createQuery("select l from SmevLog l where l.marker = :marker", SmevLog.class) .setMaxResults(1) .setParameter("marker", marker) .getResultList(); return rs.isEmpty() ? null : rs.get(0); } @Override public void store(SmevLog smevLog) { em.persist(smevLog); } }; } String pathInfo = getDirPath(); if (isEmpty(pathInfo)) { return false; } final File logPackage = listLowDirs(new File(pathInfo)); if (logPackage == null) { return false; } try { SmevLog log = getOepLog(logPackage.getName()); File[] logFiles = logPackage.listFiles(); if (logFiles != null) { for (File logFile : logFiles) { String name = logFile.getName(); if (Metadata.HTTP_RECEIVE.equals(name)) { log.setReceiveHttp(new HttpLog(Streams.toBytes(logFile))); } else if (Metadata.HTTP_SEND.equals(name)) { log.setSendHttp(new HttpLog(Streams.toBytes(logFile))); } else if (Metadata.METADATA.equals(name)) { ObjectMapper objectMapper = new ObjectMapper(); Metadata metadata = objectMapper.readValue(logFile, Metadata.class); log.setClient(metadata.client); log.setError(metadata.error); log.setLogDate(metadata.date); log.setComponent(limitLength(metadata.componentName, 255)); if (metadata.bid != null) { log.setBidId(metadata.bid); } if (metadata.send != null) { log.setSendPacket(getSoapPacket(metadata.send)); } if (metadata.receive != null) { log.setReceivePacket(getSoapPacket(metadata.receive)); } // в сущности нет processInstanceId } deleteFile(logFile); } if (log.getBidId() == null && !log.isClient()) { ExternalGlue glue = getExternalGlue(log); if (glue != null) { log.setBidId(glue.getId()); } } if (isEmpty(log.getInfoSystem())) { String infoSystem = null; if (log.isClient()) { SoapPacket sendPacket = log.getSendPacket(); if (sendPacket != null) { infoSystem = sendPacket.getRecipient(); } } else { SoapPacket receivePacket = log.getReceivePacket(); if (receivePacket != null) { infoSystem = receivePacket.getSender(); } } log.setInfoSystem(infoSystem); } storage.store(log); } deleteFile(logPackage); } catch (Exception e) { logger.log(Level.WARNING, "failure", e); return false; } return true; } @TransactionAttribute(REQUIRES_NEW) public boolean logToZip() { Date edgeDate = calcEdge(); Number count = em.createQuery("select count(o) from SmevLog o where o.logDate is null or o.logDate < :date", Number.class) .setParameter("date", edgeDate) .getSingleResult(); if (count == null || count.intValue() == 0) { return false; } ZipOutputStream zip = null; try { zip = new ZipOutputStream(new FileOutputStream(createZipFileName(edgeDate))); for (int i = 0; i < 100; i++) { List<SmevLog> logs = em.createQuery("select o from SmevLog o where o.logDate is null or o.logDate < :date", SmevLog.class) .setParameter("date", edgeDate) .setMaxResults(1) .getResultList(); if (logs.isEmpty()) { return false; } for (SmevLog log : logs) { final long packageTime = log.getLogDate() == null ? log.getDate().getTime() : log.getLogDate().getTime(); final String packagePath; { final String logId; if (log.getMarker() == null || log.getMarker().length() < 2) { logId = String.valueOf(Math.round(Math.random() * 100000.0)); } else { logId = log.getMarker(); } int mlen = logId.length(); String d1 = logId.substring(mlen - 2, mlen - 1); String d2 = logId.substring(mlen - 1); packagePath = d1 + "/" + d2 + "/" + logId + "/"; ZipEntry logPackage = new ZipEntry(packagePath); logPackage.setTime(packageTime); zip.putNextEntry(logPackage); } if (log.getSendHttp() != null && log.getSendHttp().getData() != null) { ZipEntry httpSend = new ZipEntry(packagePath + Metadata.HTTP_SEND); httpSend.setTime(packageTime); zip.putNextEntry(httpSend); zip.write(log.getSendHttp().getData()); zip.closeEntry(); } if (log.getReceiveHttp() != null && log.getReceiveHttp().getData() != null) { ZipEntry httpReceive = new ZipEntry(packagePath + Metadata.HTTP_RECEIVE); httpReceive.setTime(packageTime); zip.putNextEntry(httpReceive); zip.write(log.getReceiveHttp().getData()); zip.closeEntry(); } ObjectMapper objectMapper = new ObjectMapper(); Metadata metadata = new Metadata(); metadata.client = log.isClient(); metadata.error = log.getError(); metadata.date = log.getLogDate(); metadata.componentName = log.getComponent(); Long bidId = log.getBidId(); if (bidId != null) { metadata.bid = bidId; List<String> ids = em.createQuery("select b.processInstanceId from Bid b where b.id = :id", String.class) .setParameter("id", bidId).getResultList(); if (!ids.isEmpty()) { metadata.processInstanceId = ids.get(0); } } metadata.send = getPack(log.getSendPacket()); metadata.receive = getPack(log.getReceivePacket()); ZipEntry logMetadata = new ZipEntry(packagePath + Metadata.METADATA); logMetadata.setTime(packageTime); zip.putNextEntry(logMetadata); zip.write(objectMapper.writeValueAsBytes(metadata)); zip.closeEntry(); em.remove(log); em.flush(); } } zip.flush(); } catch (IOException e) { logger.log(Level.WARNING, "io error", e); } finally { Streams.close(zip); } return true; } // ---- internals ---- private SmevLog getOepLog(String marker) { SmevLog entry = storage.findLogEntry(marker); if (entry == null) { entry = new SmevLog(); entry.setDate(new Date()); entry.setMarker(marker); } return entry; } private String getDirPath() { if (dirPath == null) { dirPath = storage.getLazyDirPath(); } return dirPath; } private ExternalGlue getExternalGlue(SmevLog log) { ExternalGlue externalGlue = getExternalGlue(log.getReceivePacket()); if (externalGlue != null) { return externalGlue; } return getExternalGlue(log.getSendPacket()); } private ExternalGlue getExternalGlue(SoapPacket soapPacket) { if (em == null || soapPacket == null) { return null; } String[] idRefs = {soapPacket.getOriginRequestIdRef(), soapPacket.getRequestIdRef()}; for (String idRef : idRefs) { if (!isEmpty(idRef)) { List resultList = em.createQuery("select g from ExternalGlue g where g.requestIdRef = :requestIdRef") .setParameter("requestIdRef", idRef).getResultList(); if (!resultList.isEmpty()) { return (ExternalGlue) resultList.get(0); } } } return null; } private SoapPacket getSoapPacket(Pack packet) { SoapPacket result = new SoapPacket(); result.setSender(packet.sender); result.setRecipient(packet.recipient); result.setOriginator(packet.originator); result.setService(packet.serviceName); result.setTypeCode(packet.typeCode); result.setStatus(packet.status); result.setDate(packet.date); result.setRequestIdRef(packet.requestIdRef); result.setOriginRequestIdRef(packet.originRequestIdRef); result.setServiceCode(packet.serviceCode); result.setCaseNumber(packet.caseNumber); result.setExchangeType(packet.exchangeType); return result; } private Pack getPack(SoapPacket packet) { if (packet == null) { return null; } Pack result = new Pack(); result.sender = packet.getSender(); result.recipient = packet.getRecipient(); result.originator = packet.getOriginator(); result.serviceName = packet.getService(); result.typeCode = packet.getTypeCode(); result.status = packet.getStatus(); result.date = packet.getDate(); result.requestIdRef = packet.getRequestIdRef(); result.originRequestIdRef = packet.getOriginRequestIdRef(); result.serviceCode = packet.getServiceCode(); result.caseNumber = packet.getCaseNumber(); result.exchangeType = packet.getExchangeType(); return result; } private String getZipPath() { String instanceRoot = System.getProperty("com.sun.aas.instanceRoot"); File file; if (instanceRoot != null) { file = new File(new File(new File(instanceRoot), "logs"), "zip"); } else { file = new File("/var/", "zip"); } if (!file.exists()) { file.mkdirs(); } return file.getAbsolutePath(); } private boolean isEmpty(String str) { return str == null || str.length() == 0; } private File listLowDirs(File root) { File[] files = root.listFiles(); if (files != null) { Arrays.sort(files); for (File file : files) { if (file.isDirectory()) { File file1 = listLowDirs(file); if (file1 != null) { return file1; } } else { return root; } } } return null; } private void setInfoSystem(SmevLog log, String sender) { if (isEmpty(log.getInfoSystem()) && !isEmpty(sender)) { log.setInfoSystem(sender); } } private void deleteFile(File file) { if (!file.delete()) { logger.info("can't delete " + file); } } private String limitLength(String src, int maxLen) { if (src == null || src.length() <= maxLen) { return src; } return src.substring(0, maxLen); } private Date calcEdge() { int depth = -1; String depthConfig = AdminServiceProvider.get().getSystemProperty(API.LOG_DEPTH); if (depthConfig != null) { try { depth = Integer.parseInt(depthConfig); } catch (NumberFormatException e) { } } if (depth <= 0) { depth = API.DEFAULT_LOG_DEPTH; } Calendar cal = Calendar.getInstance(getTimeZone()); cal.add(Calendar.DATE, -depth); return cal.getTime(); } private TimeZone getTimeZone() { return TimeZone.getTimeZone("Europe/Moscow"); } private File createZipFileName(Date edge) { SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyyMMdd-HHmmssSSS"); dateTimeFormat.setTimeZone(getTimeZone()); return new File(getZipPath(), dateTimeFormat.format(edge) + ".zip"); } }