Package railo.runtime.tag

Source Code of railo.runtime.tag.Zip

package railo.runtime.tag;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import railo.commons.io.IOUtil;
import railo.commons.io.compress.ZipUtil;
import railo.commons.io.res.Resource;
import railo.commons.io.res.filter.DirectoryResourceFilter;
import railo.commons.io.res.filter.FileResourceFilter;
import railo.commons.io.res.filter.OrResourceFilter;
import railo.commons.io.res.filter.ResourceFilter;
import railo.commons.io.res.util.FileWrapper;
import railo.commons.io.res.util.ResourceUtil;
import railo.commons.io.res.util.WildcardPatternFilter;
import railo.commons.lang.StringUtil;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.ext.tag.BodyTagImpl;
import railo.runtime.op.Caster;
import railo.runtime.op.Decision;
import railo.runtime.type.QueryImpl;
import railo.runtime.type.dt.DateTimeImpl;

public final class Zip extends BodyTagImpl {

  private String action="zip";
  private String charset;
  private Resource destination;
  private String entryPath;
  private Resource file;
  private WildcardPatternFilter filter;
  private String name;
  private boolean overwrite;
  private String prefix;
  private boolean recurse=true;
  private boolean showDirectory;
  private boolean storePath=true;
  private String variable;
  private List<ZipParamAbstr> params;
  private Set<String> alreadyUsed;
  private Resource source;
  private static int id=0;
 
 
    @Override
    public void release()   {
        super.release();
        action="zip";
      charset=null;
      destination=null;
      entryPath=null;
      file=null;
      filter=null;
      name=null;
      overwrite=false;
      prefix=null;
      recurse=true;
      showDirectory=false;
      source=null;
      storePath=true;
      variable=null;

      if(params!=null)params.clear();
      if(alreadyUsed!=null)alreadyUsed.clear();
    }
 
   
   
    /**
   * @param action the action to set
   */
  public void setAction(String action) {
    this.action = action.trim().toLowerCase();
  }



  /**
   * @param charset the charset to set
   */
  public void setCharset(String charset) {
    this.charset = charset;
  }



  /**
   * @param destination the destination to set
   * @throws ExpressionException
   * @throws PageException
   */
  public void setDestination(String strDestination) throws PageException {
    this.destination = ResourceUtil.toResourceExistingParent(pageContext, strDestination);
    if(!destination.exists())destination.mkdirs();
   
    if(!destination.isDirectory())
      throw new ApplicationException("destination ["+strDestination+"] is not a existing directory");
   
   
  }



  /**
   * @param entryPath the entryPath to set
   */
  public void setEntrypath(String entryPath) {
    if(StringUtil.isEmpty(entryPath,true)) return;

    entryPath=entryPath.trim();
    entryPath=entryPath.replace('\\','/');
   
    if(StringUtil.startsWith(entryPath,'/'))entryPath=entryPath.substring(1);
    if(StringUtil.endsWith(entryPath,'/'))entryPath=entryPath.substring(0,entryPath.length()-1);
    this.entryPath = entryPath;
  }



  /**
   * @param file the file to set
   * @throws ExpressionException
   */
  public void setFile(String file) {
    this.file = ResourceUtil.toResourceNotExisting(pageContext, file);
  }

  /**
   * @param filter the filter to set
   */
  public void setFilter(String filter) {
   
    if ( !filter.isEmpty() )
      this.filter = new WildcardPatternFilter( filter );
  }



  /**
   * @param name the name to set
   */
  public void setName(String name) {
    this.name = name;
  }



  /**
   * @param overwrite the overwrite to set
   */
  public void setOverwrite(boolean overwrite) {
    this.overwrite = overwrite;
  }



  /**
   * @param prefix the prefix to set
   */
  public void setPrefix(String prefix) {
    this.prefix = prefix;
  }



  /**
   * @param recurse the recurse to set
   */
  public void setRecurse(boolean recurse) {
    this.recurse = recurse;
  }



  /**
   * @param showDirectory the showDirectory to set
   */
  public void setShowdirectory(boolean showDirectory) {
    this.showDirectory = showDirectory;
  }



  /**
   * @param source the source to set
   * @throws PageException
   */
  public void setSource(String strSource) throws PageException {
    source = ResourceUtil.toResourceExisting(pageContext, strSource);
   
  }



  /**
   * @param storePath the storePath to set
   */
  public void setStorepath(boolean storePath) {
    this.storePath = storePath;
  }



  /**
   * @param variable the variable to set
   */
  public void setVariable(String variable) {
    this.variable = variable;
  }



  @Override
  public int doStartTag() throws PageException  {
    return EVAL_BODY_INCLUDE;
  }

  private void actionDelete() throws ApplicationException, IOException {
    required("file",file,true);
   

    Resource existing = pageContext.getConfig().getTempDirectory().getRealResource(getTempName());
    IOUtil.copy(file, existing);
   
    ZipInputStream zis = null
    ZipOutputStream zos = null;
    try {
      zis = new ZipInputStream( IOUtil.toBufferedInputStream(existing.getInputStream()) )
      zos = new ZipOutputStream(IOUtil.toBufferedOutputStream(file.getOutputStream()));
     
          ZipEntry entry;
          String path,name;
          int index;
          boolean accept;
         
          if(filter==null && recurse && entryPath==null)
            throw new ApplicationException("define at least one restriction, can't delete all the entries from a zip file");
         
          while ( ( entry = zis.getNextEntry()) != null ) {
            accept=false;
            path = entry.getName().replace('\\', '/');
              index=path.lastIndexOf('/');
             
            if(!recurse && index>0) accept=true;
           
            //dir=index==-1?"":path.substring(0,index);
              name=path.substring(index+1);
             
              if(filter!=null && !filter.accept(name)) accept=true;
              if(!entryPathMatch(path)) accept=true;
           
              if(!accept) continue;
           
            add(zos, entry, zis, false);
            zis.closeEntry();
          }
    }
    finally {
      IOUtil.closeEL(zis);
      IOUtil.closeEL(zos);
      existing.delete();
    }
   
  }



  private void actionList() throws PageException, IOException {
    required("file",file,true);
    required("name",name);
   
   
   
   
    railo.runtime.type.Query query=new QueryImpl(
                new String[]{"name","size","type","dateLastModified","directory","crc","compressedSize","comment"},
                0,"query");
    pageContext.setVariable(name, query);
       
    ZipFile zip = getZip(file);
    Enumeration entries = zip.entries();
   
        try {
          String path,name,dir;
            ZipEntry ze;
            int row=0,index;
            while(entries.hasMoreElements()) {
              ze = (ZipEntry)entries.nextElement();
              if(!showDirectory && ze.isDirectory()) continue;
             
                path = ze.getName().replace('\\', '/');
              index=path.lastIndexOf('/');
              if(!recurse && index>0) continue;
             
              dir=index==-1?"":path.substring(0,index);
              name=path.substring(index+1);
                           
              if(filter!=null && !filter.accept(null, name)) continue;
             
             
              if(!entryPathMatch(dir)) continue;
              //if(entryPath!=null && !(dir.equalsIgnoreCase(entryPath) || StringUtil.startsWithIgnoreCase(dir,entryPath+"/"))) ;///continue;
             
              row++;
              query.addRow();
              query.setAt("name", row, path);
              query.setAt("size", row, Caster.toDouble(ze.getSize()));
              query.setAt("type", row, ze.isDirectory()?"Directory":"File");
              query.setAt("dateLastModified", row, new DateTimeImpl(pageContext,ze.getTime(),false));
              query.setAt("crc", row, Caster.toDouble(ze.getCrc()));
              query.setAt("compressedSize", row, Caster.toDouble(ze.getCompressedSize()));
              query.setAt("comment", row, ze.getComment());
              query.setAt("directory", row, dir);
              //zis.closeEntry();
               
            }
        }
        finally {
          IOUtil.closeEL(zip);
        }  
  }

  private boolean entryPathMatch(String dir) {
    if(entryPath==null) return true;
   
    return dir.equalsIgnoreCase(entryPath) || StringUtil.startsWithIgnoreCase(dir,entryPath+"/");
  }



  private void actionRead(boolean binary) throws ZipException, IOException, PageException {
    required("file",file,true);
    required("variable",variable);
    required("entrypath",variable);
    ZipFile zip = getZip(file);
   
    try {
      ZipEntry ze = zip.getEntry(entryPath);
      if(ze==null)ze = zip.getEntry(entryPath+"/");
      if(ze==null) throw new ApplicationException("zip file ["+file+"] has no entry with name ["+entryPath+"]");
     
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
     
      InputStream is = zip.getInputStream(ze);
      IOUtil.copy(is, baos,true,false);
      zip.close();
     
      if(binary)
        pageContext.setVariable(variable, baos.toByteArray());
      else {
        if(charset==null)charset=pageContext.getConfig().getResourceCharset();
        pageContext.setVariable(variable, new String(baos.toByteArray(),charset));
      }
    }
    finally {
      IOUtil.closeEL(zip);
    }
   
  }



  private void actionUnzip() throws ApplicationException, IOException {
    required("file",file,true);
    required("destination",destination,false);

    ZipInputStream zis=null;
    String path;
    Resource target,parent;
    int index;
        try {
         
          zis = new ZipInputStream( IOUtil.toBufferedInputStream(file.getInputStream()) ) ;    
          ZipEntry entry;
          while ( ( entry = zis.getNextEntry()) != null ) {
           
            path = entry.getName().replace('\\', '/');
              index=path.lastIndexOf('/');
             
              // recurse
              if(!recurse && index!=-1) {
                zis.closeEntry();
                continue;
              }
              // filter
              if(filter!=null && !filter.accept(path.substring(index+1))) {
                zis.closeEntry();
                continue;
              }
              // entrypath
              if(!entryPathMatch(path)) {
                zis.closeEntry();
                continue;
              }
            target=destination.getRealResource(entry.getName());
            if(!storePath) target=destination.getRealResource(target.getName());
              if(entry.isDirectory()) {
                  target.mkdirs();
              }
              else {
                if(storePath){
                  parent=target.getParentResource();
                  if(!parent.exists())parent.mkdirs();
                }
                  if(overwrite || !target.exists())IOUtil.copy(zis,target,false);
              }
              target.setLastModified(entry.getTime());
              zis.closeEntry() ;
          }
        }
        finally {
          IOUtil.closeEL(zis);
        }
    }



  private void actionZip() throws PageException, IOException {
    required("file",file,false);
    Resource dir = file.getParentResource();
   
    if(!dir.exists()) {
      throw new ApplicationException("directory ["+dir.toString()+"] doesn't exist");
    }
   
   
   
    if((params==null || params.isEmpty()) && source!=null) {
      setParam(new ZipParamSource(source,entryPath,filter,prefix,recurse));
    }

    if((params==null || params.isEmpty())) {
      throw new ApplicationException("No source/content specified");
    }
   
   
   
   
    ZipOutputStream zos=null;
    Resource existing=null;
    try {
     
      // existing
      if(!overwrite && file.exists()) {
        existing = pageContext.getConfig().getTempDirectory().getRealResource(getTempName());
        IOUtil.copy(file, existing);
      }
     
        zos = new ZipOutputStream(IOUtil.toBufferedOutputStream(file.getOutputStream()));

      Object[] arr = params.toArray();
      for(int i=arr.length-1;i>=0;i--) {
        if(arr[i] instanceof ZipParamSource)
          actionZip(zos,(ZipParamSource)arr[i]);
        else if(arr[i] instanceof ZipParamContent)
          actionZip(zos,(ZipParamContent)arr[i]);
      }

      if(existing!=null) {
        ZipInputStream zis = new ZipInputStream( IOUtil.toBufferedInputStream(existing.getInputStream()) )
        try {
              ZipEntry entry;
              while ( ( entry = zis.getNextEntry()) != null ) {
                add(zos, entry, zis, false);
                zis.closeEntry();
              }
        }
        finally {
          zis.close();
        }
      }
    }
    finally {
      ZipUtil.close(zos);
      if(existing!=null)existing.delete();
     
    }
   
  }



  private String getTempName() {
    return "tmp-"+(id++)+".zip";
  }



  private void actionZip(ZipOutputStream zos, ZipParamContent zpc) throws PageException, IOException {
    Object content = zpc.getContent();
    if(Decision.isBinary(content)) {
      add(zos, new ByteArrayInputStream(Caster.toBinary(content)), zpc.getEntryPath(), System.currentTimeMillis(), true);
     
    }
    else {
      String charset=zpc.getCharset();
      if(StringUtil.isEmpty(charset))charset=pageContext.getConfig().getResourceCharset();
      add(zos, new ByteArrayInputStream(content.toString().getBytes(charset)), zpc.getEntryPath(), System.currentTimeMillis(), true);
    }
  }



  private void actionZip(ZipOutputStream zos, ZipParamSource zps) throws IOException {
    // prefix
    String p=zps.getPrefix();
    if(StringUtil.isEmpty(p))
      p=this.prefix;
   
    if(!StringUtil.isEmpty(p)){
      if(!StringUtil.endsWith(p, '/'))p+="/";
    }
    else
      p="";
   
   
   
    if(zps.getSource().isFile()){
     
      String ep = zps.getEntryPath();
      if(ep==null)ep=zps.getSource().getName();
      if(!StringUtil.isEmpty(p)) ep=p+ep;
     
      add(zos,zps.getSource().getInputStream(),ep,zps.getSource().lastModified(),true);
   
    else {
     
     
     
      // filter
      ResourceFilter f = zps.getFilter();
      if(f==null)f=this.filter;
      if(zps.isRecurse()) {
        if(f!=null)f=new OrResourceFilter(new ResourceFilter[]{DirectoryResourceFilter.FILTER,f});
      }
      else {
        if(f==null)f=FileResourceFilter.FILTER;
      }
     
      addDir(zos,zps.getSource(),p,f);
    }
  }



  private void addDir(ZipOutputStream zos, Resource dir, String parent, ResourceFilter filter) throws IOException {
    Resource[] children = filter==null?dir.listResources():dir.listResources(filter);
   
    for(int i=0;i<children.length;i++) {
     
     
      if(children[i].isDirectory()) addDir(zos, children[i], parent+children[i].getName()+"/",filter);
      else {
        add(zos, children[i].getInputStream(), parent+children[i].getName(), children[i].lastModified(), true);
      }
    }
  }



  private void add(ZipOutputStream zos, InputStream is, String path, long lastMod, boolean closeInput) throws IOException {
    ZipEntry ze=new ZipEntry(path);
    ze.setTime(lastMod);
    add(zos, ze, is, closeInput);
  }
 
  private void add(ZipOutputStream zos, ZipEntry entry,InputStream is, boolean closeInput) throws IOException {
    if(alreadyUsed==null)alreadyUsed=new HashSet<String>();
    else if(alreadyUsed.contains(entry.getName())) return;
    zos.putNextEntry(entry);
        try {
            IOUtil.copy(is,zos,closeInput,false);
        }
        finally {
            zos.closeEntry();
        }
    alreadyUsed.add(entry.getName());
  }



  @Override
  public void doInitBody()  {
   
  }

  @Override
  public int doAfterBody()  {
    return SKIP_BODY;
  }
   
    @Override
  public int doEndTag() throws PageException  {//print.out("doEndTag"+doCaching+"-"+body);
    try {
      if(action.equals("delete")) actionDelete();
      else if(action.equals("list")) actionList();
      else if(action.equals("read")) actionRead(false);
      else if(action.equals("readbinary")) actionRead(true);
      else if(action.equals("unzip")) actionUnzip();
      else if(action.equals("zip")) actionZip();
          else
        throw new ApplicationException("invalid value ["+action+"] for attribute action","values for attribute action are:info,move,rename,copy,delete,read,readbinary,write,append,upload");
    }
    catch(IOException ioe) {
      throw Caster.toPageException(ioe);
    }
   
    return EVAL_PAGE;
  }

  /**
     * sets if tag has a body or not
     * @param hasBody
     */
    public void hasBody(boolean hasBody) {
       ///this.hasBody=hasBody;
    }

    private ZipFile getZip(Resource file) throws ZipException, IOException {
    return new ZipFile(FileWrapper.toFile(file));
  }
   
    /**
   * throw a error if the value is empty (null)
     * @param attributeName
     * @param atttributValue
   * @throws ApplicationException
     */
    private void required(String attributeName, String attributValue) throws ApplicationException {
        if(StringUtil.isEmpty(attributValue))
            throw new ApplicationException(
                    "invalid attribute constellation for the tag zip",
                    "attribute ["+attributeName+"] is required, if action is ["+action+"]");
    }

    /**
   * throw a error if the value is empty (null)
     * @param attributeName
     * @param atttributValue
   * @throws ApplicationException
     */
    private void required(String attributeName, Resource attributValue, boolean exists) throws ApplicationException {
        if(attributValue==null)
            throw new ApplicationException(
                    "invalid attribute constellation for the tag zip",
                    "attribute ["+attributeName+"] is required, if action is ["+action+"]");
       
        if(exists && !attributValue.exists())
          throw new ApplicationException(attributeName+" resource ["+attributValue+"] doesn't exist");
        else if(exists && !attributValue.canRead())
      throw new ApplicationException("no access to "+attributeName+" resource ["+attributValue+"]");
   
       
    }




  public void setParam(ZipParamAbstr param) {
    if(params==null) {
      params=new ArrayList<ZipParamAbstr>();
      alreadyUsed=new HashSet<String>();
    }
    params.add(param);
  }



  /**
   * @return the source
   */
  public Resource getSource() {
    return source;
  }
   
   
}
TOP

Related Classes of railo.runtime.tag.Zip

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.