Search in sources :

Example 11 with Module

use of com.serotonin.m2m2.module.Module in project ma-modules-public by infiniteautomation.

the class ModulesRestController method uploadUpgrades.

@PreAuthorize("isAdmin()")
@ApiOperation(value = "Upload upgrade zip bundle, to be installed on restart", notes = "The bundle can be downloaded from the Mango Store")
@RequestMapping(method = RequestMethod.POST, value = "/upload-upgrades")
public void uploadUpgrades(@ApiParam(value = "Restart after upload completes", required = false, defaultValue = "false", allowMultiple = false) @RequestParam(required = false, defaultValue = "false") boolean restart, MultipartHttpServletRequest multipartRequest) throws IOException {
    synchronized (UPLOAD_UPGRADE_LOCK) {
        if (UPLOAD_UPGRADE_IN_PROGRESS == null) {
            UPLOAD_UPGRADE_IN_PROGRESS = new Object();
        } else {
            throw new BadRequestException(new TranslatableMessage("rest.error.upgradeUploadInProgress"));
        }
    }
    try {
        List<MultipartFile> files = new ArrayList<>();
        MultiValueMap<String, MultipartFile> filemap = multipartRequest.getMultiFileMap();
        for (String nameField : filemap.keySet()) {
            files.addAll(filemap.get(nameField));
        }
        // Validate the zip
        if (files.size() == 0)
            throw new BadRequestException(new TranslatableMessage("rest.error.noFileProvided"));
        // Create the temp directory into which to download, if necessary.
        File tempDir = new File(Common.MA_HOME, ModuleUtils.DOWNLOAD_DIR);
        if (!tempDir.exists())
            tempDir.mkdirs();
        // Delete anything that is currently the temp directory.
        FileUtils.cleanDirectory(tempDir);
        try {
            // Save the upload(s) to the temp dir
            for (MultipartFile file : files) {
                File newFile = new File(tempDir, file.getOriginalFilename());
                try (FileOutputStream fos = new FileOutputStream(newFile)) {
                    org.springframework.util.StreamUtils.copy(file.getInputStream(), fos);
                }
            }
            String[] potentialUpgrades = tempDir.list(new FilenameFilter() {

                public boolean accept(File dir, String name) {
                    if (name.endsWith(".zip"))
                        return true;
                    else
                        return false;
                }
            });
            boolean didUpgrade = false;
            for (String potentialUpgrade : potentialUpgrades) {
                File file = new File(tempDir, potentialUpgrade);
                boolean core = false;
                boolean hasWebModules = false;
                try (FileInputStream fis = new FileInputStream(file)) {
                    // Test to see if it is a core or a bundle of only zips or many zip files
                    try (ZipInputStream is = new ZipInputStream(fis)) {
                        ZipEntry entry = is.getNextEntry();
                        if (entry == null) {
                            // Not a zip file or empty, either way we don't care
                            throw new BadRequestException(new TranslatableMessage("rest.error.badUpgradeFile"));
                        } else {
                            do {
                                if ("release.signed".equals(entry.getName())) {
                                    core = true;
                                    break;
                                } else if (entry.getName().startsWith(WEB_MODULE_PREFIX)) {
                                    hasWebModules = true;
                                }
                            } while ((entry = is.getNextEntry()) != null);
                        }
                    }
                }
                if (core) {
                    // move file to core directory
                    Files.move(file, new File(coreDir, "m2m2-core-upgrade.zip"));
                    didUpgrade = true;
                } else if (hasWebModules) {
                    // This is a zip with modules in web/modules move them all out into the MA_HOME/web/modules dir
                    try (FileInputStream fis = new FileInputStream(file)) {
                        try (ZipInputStream is = new ZipInputStream(fis)) {
                            ZipEntry entry;
                            while ((entry = is.getNextEntry()) != null) {
                                if (entry.getName().startsWith(WEB_MODULE_PREFIX)) {
                                    File newModule = new File(coreDir, entry.getName());
                                    try (FileOutputStream fos = new FileOutputStream(newModule)) {
                                        org.springframework.util.StreamUtils.copy(is, fos);
                                    }
                                    didUpgrade = true;
                                }
                            }
                        }
                    }
                } else {
                    // if its a module move it to the modules folder
                    if (potentialUpgrade.startsWith(ModuleUtils.Constants.MODULE_PREFIX)) {
                        // Its extra work but we better check that it is a module from the store:
                        didUpgrade = maybeCopyModule(file);
                    } else {
                        // Is this a zip of modules?
                        try (FileInputStream fis = new FileInputStream(file)) {
                            try (ZipInputStream is = new ZipInputStream(fis)) {
                                ZipEntry entry;
                                while ((entry = is.getNextEntry()) != null) {
                                    if (entry.getName().startsWith(ModuleUtils.Constants.MODULE_PREFIX)) {
                                        // Extract it and confirm it is a module
                                        File newModule = new File(tempDir, entry.getName());
                                        try (FileOutputStream fos = new FileOutputStream(newModule)) {
                                            org.springframework.util.StreamUtils.copy(is, fos);
                                        }
                                        didUpgrade = maybeCopyModule(newModule);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // Ensure we have some upgrades
            if (!didUpgrade)
                throw new BadRequestException(new TranslatableMessage("rest.error.invalidUpgradeFile"));
        } finally {
            FileUtils.deleteDirectory(tempDir);
        }
    } finally {
        // Release the lock
        synchronized (UPLOAD_UPGRADE_LOCK) {
            UPLOAD_UPGRADE_IN_PROGRESS = null;
        }
    }
    if (restart)
        ModulesDwr.scheduleRestart();
}
Also used : ZipEntry(java.util.zip.ZipEntry) ArrayList(java.util.ArrayList) JsonString(com.serotonin.json.type.JsonString) FileInputStream(java.io.FileInputStream) FilenameFilter(java.io.FilenameFilter) MultipartFile(org.springframework.web.multipart.MultipartFile) ZipInputStream(java.util.zip.ZipInputStream) FileOutputStream(java.io.FileOutputStream) BadRequestException(com.infiniteautomation.mango.rest.v2.exception.BadRequestException) JsonObject(com.serotonin.json.type.JsonObject) TranslatableMessage(com.serotonin.m2m2.i18n.TranslatableMessage) File(java.io.File) MultipartFile(org.springframework.web.multipart.MultipartFile) ApiOperation(com.wordnik.swagger.annotations.ApiOperation) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize) RequestMapping(org.springframework.web.bind.annotation.RequestMapping)

Example 12 with Module

use of com.serotonin.m2m2.module.Module in project ma-modules-public by infiniteautomation.

the class ModulesRestController method getUpgrades.

@ApiOperation(value = "Get Available Upgrades", notes = "Check the store for Upgrades")
@RequestMapping(method = RequestMethod.GET, value = "/upgrades-available", produces = { "application/json" })
public ResponseEntity<ModuleUpgradesModel> getUpgrades(HttpServletRequest request) {
    RestProcessResult<ModuleUpgradesModel> result = new RestProcessResult<ModuleUpgradesModel>(HttpStatus.OK);
    User user = this.checkUser(request, result);
    if (result.isOk()) {
        if (Permissions.hasAdmin(user)) {
            // Do the check
            try {
                JsonValue jsonResponse = ModulesDwr.getAvailableUpgrades();
                if (jsonResponse instanceof JsonString) {
                    result.addRestMessage(getInternalServerErrorMessage(jsonResponse.toString()));
                } else {
                    List<ModuleUpgradeModel> upgrades = new ArrayList<>();
                    List<ModuleUpgradeModel> newInstalls = new ArrayList<>();
                    ModuleUpgradesModel model = new ModuleUpgradesModel(upgrades, newInstalls);
                    JsonObject root = jsonResponse.toJsonObject();
                    JsonValue jsonUpgrades = root.get("upgrades");
                    JsonArray jsonUpgradesArray = jsonUpgrades.toJsonArray();
                    Iterator<JsonValue> it = jsonUpgradesArray.iterator();
                    while (it.hasNext()) {
                        JsonValue v = it.next();
                        if (v.getJsonValue("name") == null) {
                            it.remove();
                            continue;
                        }
                        String name = v.getJsonValue("name").toString();
                        Module module = "core".equals(name) ? ModuleRegistry.getCoreModule() : ModuleRegistry.getModule(name);
                        if (module == null) {
                            it.remove();
                            continue;
                        }
                        upgrades.add(new ModuleUpgradeModel(module, v));
                    }
                    JsonValue jsonInstalls = root.get("newInstalls");
                    JsonArray jsonInstallsArray = jsonInstalls.toJsonArray();
                    for (JsonValue v : jsonInstallsArray) {
                        newInstalls.add(new ModuleUpgradeModel(v));
                    }
                    return result.createResponseEntity(model);
                }
            } catch (SocketTimeoutException e) {
                result.addRestMessage(HttpStatus.INTERNAL_SERVER_ERROR, new TranslatableMessage("rest.error.requestTimeout", Common.envProps.getString("store.url")));
            } catch (UnknownHostException e) {
                result.addRestMessage(HttpStatus.INTERNAL_SERVER_ERROR, new TranslatableMessage("rest.error.unknownHost", Common.envProps.getString("store.url")));
            } catch (Exception e) {
                result.addRestMessage(getInternalServerErrorMessage(e.getMessage()));
            }
        } else {
            result.addRestMessage(this.getUnauthorizedMessage());
        }
    }
    return result.createResponseEntity();
}
Also used : User(com.serotonin.m2m2.vo.User) UnknownHostException(java.net.UnknownHostException) JsonValue(com.serotonin.json.type.JsonValue) ArrayList(java.util.ArrayList) JsonObject(com.serotonin.json.type.JsonObject) JsonString(com.serotonin.json.type.JsonString) BadRequestException(com.infiniteautomation.mango.rest.v2.exception.BadRequestException) GenericRestException(com.infiniteautomation.mango.rest.v2.exception.GenericRestException) FileNotFoundException(java.io.FileNotFoundException) ModuleRestV2Exception(com.infiniteautomation.mango.rest.v2.exception.ModuleRestV2Exception) SocketTimeoutException(java.net.SocketTimeoutException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) JsonArray(com.serotonin.json.type.JsonArray) RestProcessResult(com.serotonin.m2m2.web.mvc.rest.v1.message.RestProcessResult) ModuleUpgradeModel(com.serotonin.m2m2.web.mvc.rest.v1.model.modules.ModuleUpgradeModel) SocketTimeoutException(java.net.SocketTimeoutException) ModuleUpgradesModel(com.serotonin.m2m2.web.mvc.rest.v1.model.modules.ModuleUpgradesModel) JsonString(com.serotonin.json.type.JsonString) TranslatableMessage(com.serotonin.m2m2.i18n.TranslatableMessage) Module(com.serotonin.m2m2.module.Module) ApiOperation(com.wordnik.swagger.annotations.ApiOperation) RequestMapping(org.springframework.web.bind.annotation.RequestMapping)

Example 13 with Module

use of com.serotonin.m2m2.module.Module in project ma-modules-public by infiniteautomation.

the class ModulesRestController method listMissingModuleDependencies.

@ApiOperation(value = "List Current Missing Module Dependencies", notes = "List all installed")
@RequestMapping(method = RequestMethod.GET, value = "/list-missing-dependencies", produces = { "application/json" })
public ResponseEntity<Map<String, String>> listMissingModuleDependencies(HttpServletRequest request) {
    RestProcessResult<Map<String, String>> result = new RestProcessResult<>(HttpStatus.OK);
    User user = this.checkUser(request, result);
    if (result.isOk()) {
        if (Permissions.hasAdmin(user)) {
            return result.createResponseEntity(ModuleRegistry.getMissingDependencies());
        } else {
            result.addRestMessage(this.getUnauthorizedMessage());
        }
    }
    return result.createResponseEntity();
}
Also used : RestProcessResult(com.serotonin.m2m2.web.mvc.rest.v1.message.RestProcessResult) User(com.serotonin.m2m2.vo.User) Map(java.util.Map) HashMap(java.util.HashMap) MultiValueMap(org.springframework.util.MultiValueMap) ApiOperation(com.wordnik.swagger.annotations.ApiOperation) RequestMapping(org.springframework.web.bind.annotation.RequestMapping)

Example 14 with Module

use of com.serotonin.m2m2.module.Module in project ma-modules-public by infiniteautomation.

the class ModulesRestController method getUpdateLicensePayload.

@PreAuthorize("isAdmin()")
@ApiOperation(value = "Get the update license payload, to make requests to store", notes = "Admin Only")
@RequestMapping(method = RequestMethod.GET, value = "/update-license-payload")
public ResponseEntity<UpdateLicensePayloadModel> getUpdateLicensePayload(@ApiParam(value = "Set content disposition to attachment", required = false, defaultValue = "true", allowMultiple = false) @RequestParam(required = false, defaultValue = "false") boolean download, HttpServletRequest request) {
    Map<String, String> jsonModules = new HashMap<>();
    List<Module> modules = ModuleRegistry.getModules();
    Module.sortByName(modules);
    Module core = ModuleRegistry.getCoreModule();
    modules.add(0, core);
    for (Module module : modules) {
        if (!module.isMarkedForDeletion())
            jsonModules.put(module.getName(), module.getVersion().toString());
    }
    // Add in the unloaded modules so we don't re-download them if we don't have to
    for (Module module : ModuleRegistry.getUnloadedModules()) if (!module.isMarkedForDeletion())
        jsonModules.put(module.getName(), module.getVersion().toString());
    String storeUrl = Common.envProps.getString("store.url");
    int upgradeVersionState = SystemSettingsDao.getIntValue(SystemSettingsDao.UPGRADE_VERSION_STATE);
    int currentVersionState = UpgradeVersionState.DEVELOPMENT;
    Properties props = new Properties();
    File propFile = new File(Common.MA_HOME + File.separator + "release.properties");
    try {
        if (propFile.exists()) {
            InputStream in;
            in = new FileInputStream(propFile);
            try {
                props.load(in);
            } finally {
                in.close();
            }
            String versionState = props.getProperty("versionState");
            try {
                if (versionState != null)
                    currentVersionState = Integer.valueOf(versionState);
            } catch (NumberFormatException e) {
            }
        }
    } catch (IOException e1) {
    // Ignore
    }
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.set(HttpHeaders.CONTENT_DISPOSITION, download ? "attachment" : "inline");
    return new ResponseEntity<>(new UpdateLicensePayloadModel(Providers.get(ICoreLicense.class).getGuid(), SystemSettingsDao.getValue(SystemSettingsDao.INSTANCE_DESCRIPTION), Common.envProps.getString("distributor"), jsonModules, storeUrl, upgradeVersionState, currentVersionState), responseHeaders, HttpStatus.OK);
}
Also used : HttpHeaders(org.springframework.http.HttpHeaders) HashMap(java.util.HashMap) ZipInputStream(java.util.zip.ZipInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) JsonString(com.serotonin.json.type.JsonString) IOException(java.io.IOException) Properties(java.util.Properties) ICoreLicense(com.serotonin.m2m2.ICoreLicense) FileInputStream(java.io.FileInputStream) ResponseEntity(org.springframework.http.ResponseEntity) UpdateLicensePayloadModel(com.serotonin.m2m2.web.mvc.rest.v1.model.modules.UpdateLicensePayloadModel) Module(com.serotonin.m2m2.module.Module) File(java.io.File) MultipartFile(org.springframework.web.multipart.MultipartFile) ApiOperation(com.wordnik.swagger.annotations.ApiOperation) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize) RequestMapping(org.springframework.web.bind.annotation.RequestMapping)

Example 15 with Module

use of com.serotonin.m2m2.module.Module in project ma-modules-public by infiniteautomation.

the class ReportWorkItem method execute.

@Override
public void execute() {
    try {
        ReportLicenseChecker.checkLicense();
    } catch (LicenseViolatedException e) {
        LOG.error("Your core license doesn't permit you to use the reports module.");
        reportInstance.setReportStartTime(Common.timer.currentTimeMillis());
        reportInstance.setReportEndTime(Common.timer.currentTimeMillis());
        reportInstance.setRecordCount(-1);
        reportDao.saveReportInstance(reportInstance);
        return;
    }
    LOG.debug("Running report with id " + reportConfig.getId() + ", instance id " + reportInstance.getId());
    reportInstance.setRunStartTime(System.currentTimeMillis());
    reportDao.saveReportInstance(reportInstance);
    Translations translations = Common.getTranslations();
    // Create a list of DataPointVOs to which the user has permission.
    DataPointDao dataPointDao = DataPointDao.instance;
    List<ReportDao.PointInfo> points = new ArrayList<ReportDao.PointInfo>(reportConfig.getPoints().size());
    for (ReportPointVO reportPoint : reportConfig.getPoints()) {
        DataPointVO point = dataPointDao.getDataPoint(reportPoint.getPointId());
        if (point != null && Permissions.hasDataPointReadPermission(user, point)) {
            String colour = null;
            try {
                if (!StringUtils.isBlank(reportPoint.getColour()))
                    colour = ColorUtils.toHexString(reportPoint.getColour()).substring(1);
            } catch (InvalidArgumentException e) {
            // Should never happen since the colour would have been validated on save, so just let it go
            // as null.
            }
            points.add(new ReportDao.PointInfo(point, colour, reportPoint.getWeight(), reportPoint.isConsolidatedChart(), reportPoint.getPlotType()));
        }
    }
    int recordCount = 0;
    try {
        if (!points.isEmpty()) {
            if (Common.databaseProxy.getNoSQLProxy() == null)
                recordCount = reportDao.runReportSQL(reportInstance, points);
            else
                recordCount = reportDao.runReportNoSQL(reportInstance, points);
        }
    } catch (RuntimeException e) {
        recordCount = -1;
        throw e;
    } catch (Throwable e) {
        recordCount = -1;
        throw new RuntimeException("Report instance failed", e);
    } finally {
        reportInstance.setRunEndTime(System.currentTimeMillis());
        reportInstance.setRecordCount(recordCount);
        reportDao.saveReportInstance(reportInstance);
    }
    if (reportConfig.isEmail()) {
        String inlinePrefix = "R" + System.currentTimeMillis() + "-" + reportInstance.getId() + "-";
        // TODO should we create different instances of the email based upon language and timezone?
        // We are creating an email from the result. Create the content.
        final ReportChartCreator creator = new ReportChartCreator(translations, TimeZone.getDefault());
        creator.createContent(host, port, reportInstance, reportDao, inlinePrefix, reportConfig.isIncludeData());
        // Create the to list
        Set<String> addresses = MailingListDao.instance.getRecipientAddresses(reportConfig.getRecipients(), new DateTime(reportInstance.getReportStartTime()));
        String[] toAddrs = addresses.toArray(new String[0]);
        // Create the email content object.
        EmailContent emailContent = new EmailContent(null, creator.getHtml(), Common.UTF8);
        // Add the consolidated chart
        if (creator.getImageData() != null)
            emailContent.addInline(new EmailInline.ByteArrayInline(inlinePrefix + ReportChartCreator.IMAGE_CONTENT_ID, creator.getImageData(), ImageChartUtils.getContentType()));
        // Add the point charts
        for (PointStatistics pointStatistics : creator.getPointStatistics()) {
            if (pointStatistics.getImageData() != null)
                emailContent.addInline(new EmailInline.ByteArrayInline(inlinePrefix + pointStatistics.getChartName(), pointStatistics.getImageData(), ImageChartUtils.getContentType()));
        }
        // Add optional images used by the template.
        for (String s : creator.getInlineImageList()) addImage(emailContent, s);
        // Check if we need to attach the data.
        if (reportConfig.isIncludeData()) {
            addFileAttachment(emailContent, reportInstance.getName() + ".csv", creator.getExportFile());
            addFileAttachment(emailContent, reportInstance.getName() + "Events.csv", creator.getEventFile());
            addFileAttachment(emailContent, reportInstance.getName() + "Comments.csv", creator.getCommentFile());
        }
        PostEmailRunnable[] postEmail = null;
        if (reportConfig.isIncludeData()) {
            // See that the temp file(s) gets deleted after the email is sent.
            PostEmailRunnable deleteTempFile = new PostEmailRunnable() {

                @Override
                public void run() {
                    for (File file : filesToDelete) {
                        if (!file.delete())
                            LOG.warn("Temp file " + file.getPath() + " not deleted");
                    }
                }
            };
            postEmail = new PostEmailRunnable[] { deleteTempFile };
        }
        try {
            TranslatableMessage lm = new TranslatableMessage("ftl.scheduledReport", reportConfig.getName());
            String subject = creator.getSubject();
            if (subject == null)
                subject = lm.translate(translations);
            EmailWorkItem.queueEmail(toAddrs, subject, emailContent, postEmail);
        } catch (AddressException e) {
            LOG.error(e);
        }
        if (reportConfig.isSchedule()) {
            // Delete the report instance.
            reportDao.deleteReportInstance(reportInstance.getId(), user.getId());
        }
    }
    LOG.debug("Finished running report with id " + reportConfig.getId() + ", instance id " + reportInstance.getId());
}
Also used : LicenseViolatedException(com.serotonin.m2m2.LicenseViolatedException) ArrayList(java.util.ArrayList) EmailContent(com.serotonin.web.mail.EmailContent) DateTime(org.joda.time.DateTime) InvalidArgumentException(com.serotonin.InvalidArgumentException) AddressException(javax.mail.internet.AddressException) ReportPointVO(com.serotonin.m2m2.reports.vo.ReportPointVO) TranslatableMessage(com.serotonin.m2m2.i18n.TranslatableMessage) DataPointVO(com.serotonin.m2m2.vo.DataPointVO) DataPointDao(com.serotonin.m2m2.db.dao.DataPointDao) PointStatistics(com.serotonin.m2m2.reports.web.ReportChartCreator.PointStatistics) PostEmailRunnable(com.serotonin.m2m2.email.PostEmailRunnable) ReportDao(com.serotonin.m2m2.reports.ReportDao) Translations(com.serotonin.m2m2.i18n.Translations) File(java.io.File)

Aggregations

HashMap (java.util.HashMap)9 Module (com.serotonin.m2m2.module.Module)8 ApiOperation (com.wordnik.swagger.annotations.ApiOperation)7 RequestMapping (org.springframework.web.bind.annotation.RequestMapping)7 User (com.serotonin.m2m2.vo.User)6 JsonString (com.serotonin.json.type.JsonString)5 TranslatableMessage (com.serotonin.m2m2.i18n.TranslatableMessage)5 RestProcessResult (com.serotonin.m2m2.web.mvc.rest.v1.message.RestProcessResult)5 JsonObject (com.serotonin.json.type.JsonObject)4 File (java.io.File)4 ShouldNeverHappenException (com.serotonin.ShouldNeverHappenException)3 JsonWriter (com.serotonin.json.JsonWriter)3 CoreModuleModel (com.serotonin.m2m2.web.mvc.rest.v1.model.modules.CoreModuleModel)3 FileInputStream (java.io.FileInputStream)3 IOException (java.io.IOException)3 StringWriter (java.io.StringWriter)3 ArrayList (java.util.ArrayList)3 LinkedHashMap (java.util.LinkedHashMap)3 Version (com.github.zafarkhaja.semver.Version)2 BadRequestException (com.infiniteautomation.mango.rest.v2.exception.BadRequestException)2