001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.ui.progress; 020 021import org.apache.log4j.Logger; 022import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; 023import org.apache.wiki.ajax.WikiAjaxServlet; 024 025import javax.servlet.http.HttpServletRequest; 026import javax.servlet.http.HttpServletResponse; 027import java.io.IOException; 028import java.util.List; 029import java.util.Map; 030import java.util.UUID; 031import java.util.concurrent.ConcurrentHashMap; 032 033 034/** 035 * Manages progressing items. In general this class is used whenever JSPWiki is doing something which may require a long time. 036 * In addition, this manager provides a JSON interface for finding remotely what the progress is. The JSON object name is 037 * JSON_PROGRESSTRACKER = "{@value #JSON_PROGRESSTRACKER}". 038 * 039 * @since 2.6 040 */ 041public class DefaultProgressManager implements ProgressManager { 042 043 private final Map< String,ProgressItem > m_progressingTasks = new ConcurrentHashMap<>(); 044 045 private static final Logger log = Logger.getLogger( DefaultProgressManager.class ); 046 047 /** 048 * Creates a new ProgressManager. 049 */ 050 public DefaultProgressManager() { 051 // TODO: Replace with custom annotations. See JSPWIKI-566 052 WikiAjaxDispatcherServlet.registerServlet( JSON_PROGRESSTRACKER, new JSONTracker() ); 053 } 054 055 /** 056 * You can use this to get an unique process identifier. 057 * 058 * @return A new random value 059 */ 060 public String getNewProgressIdentifier() 061 { 062 return UUID.randomUUID().toString(); 063 } 064 065 /** 066 * Call this method to get your ProgressItem into the ProgressManager queue. The ProgressItem will be moved to state STARTED. 067 * 068 * @param pi ProgressItem to start 069 * @param id The progress identifier 070 */ 071 public void startProgress( final ProgressItem pi, final String id ) { 072 log.debug( "Adding " + id + " to progress queue" ); 073 m_progressingTasks.put( id, pi ); 074 pi.setState( ProgressItem.STARTED ); 075 } 076 077 /** 078 * Call this method to remove your ProgressItem from the queue (after which getProgress() will no longer find it. 079 * The ProgressItem will be moved to state STOPPED. 080 * 081 * @param id The progress identifier 082 */ 083 public void stopProgress( final String id ) { 084 log.debug( "Removed " + id + " from progress queue" ); 085 final ProgressItem pi = m_progressingTasks.remove( id ); 086 if( pi != null ) { 087 pi.setState( ProgressItem.STOPPED ); 088 } 089 } 090 091 /** 092 * Get the progress in percents. 093 * 094 * @param id The progress identifier. 095 * @return a value between 0 to 100 indicating the progress 096 * @throws IllegalArgumentException If no such progress item exists. 097 */ 098 public int getProgress( final String id ) throws IllegalArgumentException { 099 final ProgressItem pi = m_progressingTasks.get( id ); 100 if( pi != null ) { 101 return pi.getProgress(); 102 } 103 104 throw new IllegalArgumentException( "No such id was found" ); 105 } 106 107 /** 108 * Provides access to a progress indicator, assuming you know the ID. Progress of zero (0) means that the progress has just started, 109 * and a progress of 100 means that it is complete. 110 */ 111 public class JSONTracker implements WikiAjaxServlet { 112 /** 113 * Returns upload progress in percents so far. 114 * 115 * @param progressId The string representation of the progress ID that you want to know the progress of. 116 * @return a value between 0 to 100 indicating the progress 117 */ 118 public int getProgress( final String progressId ) 119 { 120 return DefaultProgressManager.this.getProgress( progressId ); 121 } 122 123 public String getServletMapping() { 124 return JSON_PROGRESSTRACKER; 125 } 126 127 public void service( final HttpServletRequest req, 128 final HttpServletResponse resp, 129 final String actionName, 130 final List< String > params ) throws IOException { 131 log.debug( "ProgressManager.doGet() START" ); 132 if( params.size() < 1 ) { 133 return; 134 } 135 final String progressId = params.get(0); 136 log.debug( "progressId=" + progressId ); 137 String progressString = ""; 138 try { 139 progressString = Integer.toString( getProgress( progressId ) ); 140 } catch( final IllegalArgumentException e ) { // ignore 141 log.debug( "progressId " + progressId + " is no longer valid" ); 142 } 143 log.debug( "progressString=" + progressString ); 144 resp.getWriter().write( progressString ); 145 log.debug( "ProgressManager.doGet() DONE" ); 146 } 147 148 } 149 150}