Package org.atomojo.www.app.edit.upload

Source Code of org.atomojo.www.app.edit.upload.UploadApplication$UploadForm

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package org.atomojo.www.app.edit.upload;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import org.atomojo.app.client.Entry;
import org.atomojo.www.app.edit.APPProxy;
import org.atomojo.www.app.edit.ClassResourceFinder;
import org.infoset.xml.Document;
import org.infoset.xml.DocumentLoader;
import org.infoset.xml.sax.SAXDocumentLoader;
import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.Uniform;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.Cookie;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.restlet.representation.InputRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ServerResource;
import org.restlet.routing.Router;
import org.restlet.routing.Template;
import org.restlet.util.Resolver;

/**
*
* @author alex
*/
public class UploadApplication extends Application {

   static long ONE_DAY = 24*3600*1000;
  
   static class UploadProgress {
      long timestamp;
      String id;
      String submit;
      String cancel;
      String entryId;
      int status;
      boolean update;
      long length;
      UploadSource source;
      UploadActor actor;
      boolean cancelled;
      UploadProgress(String id,boolean update,String submit,String cancel) {
         this.id = id;
         this.update = update;
         this.submit = submit;
         this.cancel = cancel;
         this.length = 0;
         this.timestamp = System.currentTimeMillis();
         this.source = null;
         this.status = -1;
         this.entryId = null;
         this.actor = null;
         this.cancelled = false;
      }
      public void cancel() {
         this.cancelled = true;
         if (this.actor!=null) {
            this.actor.cancel();
         }
      }
   }
  
   interface UploadActor {
      void cancel();
   }
  

   static String toString(Reader r)
      throws IOException
   {
      StringBuilder builder = new StringBuilder();
      char [] buffer = new char[1024];
      int len;
      while ((len=r.read(buffer))>0) {
         builder.append(buffer,0,len);
      }
      return builder.toString();
   }

   static public class StartUpload extends ServerResource {
      public StartUpload()
      {
         setNegotiated(false);
      }
      public Representation post(Representation entity) {
         Form form = new Form(entity);
         String submit = form.getFirstValue("submit");
         String cancel = form.getFirstValue("cancel");
         String update = form.getFirstValue("update");
         if (submit==null) {
            submit = "Upload";
         }
         if (cancel==null) {
            cancel = "Cancel";
         }
         UploadApplication app = (UploadApplication)getContext().getAttributes().get("upload.app");
         UploadProgress progress = app.newUpload("true".equals(update),submit,cancel);
         getResponse().setStatus(Status.SUCCESS_CREATED);
         getResponse().setLocationRef(new Reference(getRequest().getResourceRef().getParentRef().toString()+progress.id+"/"));
         return new StringRepresentation("<context id='"+progress.id+"'/>",MediaType.APPLICATION_XML);
      }
   }
   static public class UploadForm extends ServerResource {
      public UploadForm()
      {
         setNegotiated(false);
      }
     
      public Representation get() {
         UploadApplication app = (UploadApplication)getContext().getAttributes().get("upload.app");
         String id = getRequest().getAttributes().get("upload.id").toString();
         final UploadProgress progress = app.getUpload(id);
         if (progress==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            return null;
         }
         try {
            InputStream is = UploadApplication.class.getResourceAsStream("upload.html");
            Reader r = new InputStreamReader(is,"UTF-8");
            Template template = new Template(UploadApplication.toString(r));
            String result = template.format(new Resolver<String>() {
               public String resolve(String name) {
                  if (name.equals("action")) {
                     return getRequest().getResourceRef().getPath();
                  } else if (name.equals("submit")) {
                     return progress.submit;
                  } else if (name.equals("cancel")) {
                     return progress.cancel;
                  } else {
                     return "";
                  }
               }
            });
            getResponse().setStatus(Status.SUCCESS_OK);
            return new StringRepresentation(result,MediaType.TEXT_HTML);
         } catch (IOException ex) {
            getLogger().log(Level.SEVERE,"Cannot get upload.html resource.",ex);
            getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
            return null;
         }
        
      }
      public Representation post(Representation entity) {
         UploadApplication app = (UploadApplication)getContext().getAttributes().get("upload.app");
         String id = getRequest().getAttributes().get("upload.id").toString();
         String baseURL = app.getAttribute(getRequest(),"app.url");
         String appUsername = app.getAttribute(getRequest(),"app.username");
         String appPassword = app.getAttribute(getRequest(),"app.password");
         final UploadProgress progress = app.getUpload(id);
         if (progress==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            return null;
         }
         progress.length = entity.getSize();
         getLogger().info("Upload Size: "+progress.length);

         InputStream is = null;
         final AtomicBoolean cancellation = new AtomicBoolean(false);
         Reference appRef = new Reference(baseURL+getRequest().getResourceRef().getRemainingPart());
         getLogger().info("Upload to: "+appRef);
         try {
            progress.source = new UploadSource(getLogger(),entity.getStream());
            progress.actor = new UploadActor() {
               public void cancel() {
                  cancellation.set(true);
                  progress.source.cancel();
               }
            };
            Map<String,String> headers = progress.source.setup();
            Map<String,String> disposition = UploadSource.parseParameters(headers.get("Content-Disposition"));
            String filename = disposition.get("filename");
            is = progress.source.getInputStream();

            Uniform client = getContext().getClientDispatcher();
            //Client client = new Client(getContext().createChildContext(),appRef.getSchemeProtocol());
            Request appRequest = new Request(progress.update ? Method.PUT : Method.POST,appRef);
            appRequest.setRootRef(getRequest().getRootRef());
           
            if (appUsername!=null) {
               getLogger().info("Using username "+appUsername+" for authentication for APP target.");
               appRequest.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_BASIC,appUsername,appPassword));
            } else if (getRequest().getChallengeResponse()!=null) {
                // pass along authentication
               getLogger().info("Passing along authentication to APP target.");
               appRequest.setChallengeResponse(getRequest().getChallengeResponse());
            }
            Cookie cookie = getRequest().getCookies().getFirst("I");
            if (cookie!=null) {
               appRequest.getCookies().add(cookie);
            }
           
            // add header for slug if new upload
            if (!progress.update && filename!=null) {
               getLogger().info("Upload filename: "+filename);
               Form appHeaders = new Form();
               appHeaders.add("slug",filename);
               appRequest.getAttributes().put("org.restlet.http.headers",appHeaders);
            }
           
            // setup body
            appRequest.setEntity(new InputRepresentation(is,MediaType.valueOf(headers.get("Content-Type"))));
           
            // make request
            Response appResponse = new Response(appRequest);
            client.handle(appRequest,appResponse);

            if (appResponse.getStatus().isSuccess()) {
               if (progress.update) {
                  progress.status = appResponse.getStatus().getCode();
               } else {
                  try {
                     Reader r = appResponse.getEntity().getReader();
                     DocumentLoader loader = new SAXDocumentLoader();
                     Document entryDoc = loader.load(r);
                     Entry entry = new Entry(entryDoc);
                     entry.index();
                     progress.entryId = entry.getId();
                     progress.status = appResponse.getStatus().getCode();
                     getLogger().info("Entry: "+progress.entryId+", status="+progress.status);
                  } catch (Exception ex) {
                     getLogger().log(Level.SEVERE,"Cannot parse response to upload to "+appRef,ex);
                     progress.status = appResponse.getStatus().getCode();
                  }
               }
            } else {
               if (cancellation.get()) {
                  progress.status = 0;
                  getLogger().severe("Upload to "+appRef+" cancelled.");
               } else {
                  progress.status = appResponse.getStatus().getCode();
                  getLogger().severe("Upload to "+appRef+" failed with status "+appResponse.getStatus().getCode());
               }
            }
            getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
         } catch (IOException ex) {
            if (cancellation.get()) {
               getLogger().info("Upload to "+appRef+" cancelled by user.");
               getResponse().setStatus(Status.SUCCESS_PARTIAL_CONTENT);
            } else {
               getLogger().warning("I/O error during upload, canceling: "+ex.getMessage());
            }
            // forget the error
         } finally {
            if (is!=null) {
               try {
                  is.close();
               } catch (IOException ex) {
               }
            }
         }
         return null;
      }
   }
  
   static public class UploadStatus extends ServerResource {
      public UploadStatus()
      {
         setNegotiated(false);
      }
      public Representation get() {
         UploadApplication app = (UploadApplication)getContext().getAttributes().get("upload.app");
         String id = getRequest().getAttributes().get("upload.id").toString();
         UploadProgress progress = app.getUpload(id);
         if (progress==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            return null;
         }
         Representation rep = null;
         if (progress.cancelled) {
            app.removeUpload(progress.id);
            rep = new StringRepresentation("<status id='"+progress.id+"' cancelled='true' status='0' size='"+progress.length+"' progress='"+(progress.source==null ? 0 : progress.source.getBytesRead())+"'/>",MediaType.APPLICATION_XML);
         } else if (progress.status>0) {
            app.removeUpload(progress.id);
            rep = new StringRepresentation("<status id='"+progress.id+"' status='"+progress.status+"'"+(progress.entryId==null ? "" : " entry-id='"+progress.entryId+"'")+" size='"+progress.length+"' progress='"+(progress.source==null ? 0 : progress.source.getBytesRead())+"'/>",MediaType.APPLICATION_XML);
         } else {
            rep = new StringRepresentation("<status id='"+progress.id+"' size='"+progress.length+"' progress='"+(progress.source==null ? 0 : progress.source.getBytesRead())+"'/>",MediaType.APPLICATION_XML);
         }
         rep.setTransient(true);
         rep.setExpirationDate(new Date(0));
         Form headers = new Form();
         headers.add("Cache-Control","no-cache");
         headers.add("Pragma","no-cache");
         getResponse().getAttributes().put("org.restlet.http.headers",headers);
         return rep;
      }
   }
  
   static public class UploadCancel extends ServerResource {
      public UploadCancel()
      {
         setNegotiated(false);
      }
      public Representation get() {
         UploadApplication app = (UploadApplication)getContext().getAttributes().get("upload.app");
         String id = getRequest().getAttributes().get("upload.id").toString();
         UploadProgress progress = app.getUpload(id);
         if (progress==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            return null;
         }
         progress.cancel();
         getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
         return null;
      }
   }

   Map<String,UploadProgress> inProgress = new TreeMap<String,UploadProgress>();
   Restlet appProxy;
  
   public UploadApplication(Context context) {
      this(context,null);
   }

   public UploadApplication(Context context, Restlet appProxy) {
      super(context.createChildContext());
      this.appProxy = appProxy;
      if (this.appProxy==null) {
         this.appProxy = new APPProxy(getContext());
      }
      getContext().getAttributes().put("upload.app", this);
      getContext().getAttributes().put("hostnameVerifier", org.apache.commons.ssl.HostnameVerifier.DEFAULT);
      getTunnelService().setEnabled(false);

      for (String name : context.getParameters().getNames()) {
         String value = context.getParameters().getFirstValue(name);
         getLogger().info(UploadApplication.class+" parameter "+name+" -> "+value);
         getContext().getParameters().set(name,value,false);
      }
   }

   public String getAttribute(Request request,String name) {
      Object requestBase = request.getAttributes().get(name);
      return requestBase==null ? getContext().getParameters().getFirstValue(name) : requestBase.toString();
   }
  
   public UploadProgress newUpload(boolean update,String submit,String cancel)
   {
      String id = UUID.randomUUID().toString();
      UploadProgress progress = new UploadProgress(id,update,submit,cancel);
      inProgress.put(id,progress);
      cleanup();
      return progress;
   }
  
   public UploadProgress getUpload(String id)
   {
      return inProgress.get(id);
   }
  
   public UploadProgress removeUpload(String id)
   {
      return inProgress.remove(id);
   }
  
   public void cleanup() {
      Set<String> keys = new TreeSet<String>();
      keys.addAll(inProgress.keySet());
      for (String id : keys) {
         UploadProgress upload = inProgress.get(id);
         if ((System.currentTimeMillis()-upload.timestamp)>=ONE_DAY) {
            inProgress.remove(id);
         }
      }
   }
  
   public Restlet createRoot() {
      Router router = new Router(getContext());
      router.setDefaultMatchingMode(Template.MODE_STARTS_WITH);
      router.attach("/",new ClassResourceFinder(getContext(),UploadApplication.class.getClassLoader(),UploadApplication.class));
      router.attach("/start/",StartUpload.class);
      router.attach("/{upload.id}/upload/",UploadForm.class);
      router.attach("/{upload.id}/status/",UploadStatus.class);
      router.attach("/{upload.id}/cancel/",UploadCancel.class);
      router.attach("/app",this.appProxy);
      return router;
   }
}
TOP

Related Classes of org.atomojo.www.app.edit.upload.UploadApplication$UploadForm

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.