/* * Copyright 2009 Glencoe Software, Inc. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.services.scripts; import java.io.File; import java.util.List; import ome.conditions.InternalException; import ome.model.core.OriginalFile; import ome.parameters.Parameters; import ome.services.util.Executor; import ome.system.Principal; import ome.system.Roles; import ome.system.ServiceFactory; import ome.util.checksum.ChecksumProviderFactory; import ome.util.checksum.ChecksumProviderFactoryImpl; import ome.util.checksum.ChecksumType; import omero.model.OriginalFileI; import omero.model.ScriptJob; import omero.model.ScriptJobI; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Looks up an official script based on path for internal use. * * The strategy here is to not only check for name, but also for the sha1 of the * file, meaning that if a new version is published, it will be used. * * Also provides {@link #createJob(ServiceFactory)} method in order to allow * simple creation of processors. * * @since Beta4.1 */ public abstract class ScriptFinder { protected final Logger log = LoggerFactory.getLogger(getClass()); private final Principal principal; private final Executor ex; private final Roles roles; /** * Source file to use for uploading. */ private final File source; public ScriptFinder(Roles roles, String uuid, Executor executor, File source) { this(roles, new Principal(uuid, "system", "Internal"), executor, source); } public ScriptFinder(Roles roles, Principal principal, Executor executor, File source) { this.roles = roles; this.principal = principal; this.ex = executor; this.source = source; // to permit testing, we are exiting early if the source cannot // be found at all. any exception after this point, however, will // prevent the server from stopping properly. if (!this.source.exists()) { log.error("SERVER IMPROPERLY CONFIGURED - CANNOT FIND " + source.getAbsolutePath()); return; } } /** * Subclasses should override to return the name of the file under scripts/ * which should be uploaded. */ public abstract String getName(); public OriginalFileI getFile(ServiceFactory sf) { OriginalFile file = null; ChecksumProviderFactory cpf = new ChecksumProviderFactoryImpl(); try { final byte[] buf = FileUtils.readFileToByteArray(source); final String sha1 = cpf.getProvider(ChecksumType.SHA1) .putBytes(buf).checksumAsString(); log.debug("Loading script: " + sha1); Parameters p = new Parameters(); p.addString("hash", sha1); p.addString("name", getName()); List<OriginalFile> files = loadScripts(sf, p); if (files.size() < 1) { return null; } else { if (files.size() > 1) { log.warn("Multiple scripts found: " + files); } file = files.get(0); } } catch (Exception e) { // pass in order to throw log.warn(e.toString()); // slf4j migration: toString() } if (file == null) { throw new InternalException("Failed to find script"); } else { return new OriginalFileI(file.getId(), false); } } /** * Load all scripts that match the name, hash, and format for script */ protected List<OriginalFile> loadScripts(ServiceFactory sf, Parameters p) { p.addLong("gid", roles.getUserGroupId()); List<OriginalFile> files = sf.getQueryService().findAllByQuery( "select f from OriginalFile f where f.hash = :hash " + "and f.details.group.id = :gid " + "and f.name = :name " + "and f.mimetype = 'text/x-python'", p); return files; } /** * Returns a fresh (unsaved) {@link ScriptJob} which can be passed to * acquireProcessor for background processing. */ public ScriptJob createJob(ServiceFactory sf) { ScriptJob job = new ScriptJobI(); job.linkOriginalFile(getFile(sf)); job.setDescription(omero.rtypes.rstring(getName())); return job; } }