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.logging.log4j.LogManager; 022import org.apache.logging.log4j.Logger; 023import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; 024import org.apache.wiki.ajax.WikiAjaxServlet; 025 026import javax.servlet.http.HttpServletRequest; 027import javax.servlet.http.HttpServletResponse; 028import java.io.IOException; 029import java.util.List; 030import java.util.Map; 031import java.util.UUID; 032import java.util.concurrent.ConcurrentHashMap; 033 034 035/** 036 * Manages progressing items. In general this class is used whenever JSPWiki is doing something which may require a long time. 037 * In addition, this manager provides a JSON interface for finding remotely what the progress is. The JSON object name is 038 * JSON_PROGRESSTRACKER = "{@value #JSON_PROGRESSTRACKER}". 039 * 040 * @since 2.6 041 */ 042public class DefaultProgressManager implements ProgressManager { 043 044 private final Map< String,ProgressItem > m_progressingTasks = new ConcurrentHashMap<>(); 045 046 private static final Logger log = LogManager.getLogger( DefaultProgressManager.class ); 047 048 /** 049 * Creates a new ProgressManager. 050 */ 051 public DefaultProgressManager() { 052 // TODO: Replace with custom annotations. See JSPWIKI-566 053 WikiAjaxDispatcherServlet.registerServlet( JSON_PROGRESSTRACKER, new JSONTracker() ); 054 } 055 056 /** 057 * You can use this to get an unique process identifier. 058 * 059 * @return A new random value 060 */ 061 public String getNewProgressIdentifier() 062 { 063 return UUID.randomUUID().toString(); 064 } 065 066 /** 067 * Call this method to get your ProgressItem into the ProgressManager queue. The ProgressItem will be moved to state STARTED. 068 * 069 * @param pi ProgressItem to start 070 * @param id The progress identifier 071 */ 072 public void startProgress( final ProgressItem pi, final String id ) { 073 log.debug( "Adding " + id + " to progress queue" ); 074 m_progressingTasks.put( id, pi ); 075 pi.setState( ProgressItem.STARTED ); 076 } 077 078 /** 079 * Call this method to remove your ProgressItem from the queue (after which getProgress() will no longer find it. 080 * The ProgressItem will be moved to state STOPPED. 081 * 082 * @param id The progress identifier 083 */ 084 public void stopProgress( final String id ) { 085 log.debug( "Removed " + id + " from progress queue" ); 086 final ProgressItem pi = m_progressingTasks.remove( id ); 087 if( pi != null ) { 088 pi.setState( ProgressItem.STOPPED ); 089 } 090 } 091 092 /** 093 * Get the progress in percents. 094 * 095 * @param id The progress identifier. 096 * @return a value between 0 to 100 indicating the progress 097 * @throws IllegalArgumentException If no such progress item exists. 098 */ 099 public int getProgress( final String id ) throws IllegalArgumentException { 100 final ProgressItem pi = m_progressingTasks.get( id ); 101 if( pi != null ) { 102 return pi.getProgress(); 103 } 104 105 throw new IllegalArgumentException( "No such id was found" ); 106 } 107 108 /** 109 * Provides access to a progress indicator, assuming you know the ID. Progress of zero (0) means that the progress has just started, 110 * and a progress of 100 means that it is complete. 111 */ 112 public class JSONTracker implements WikiAjaxServlet { 113 /** 114 * Returns upload progress in percents so far. 115 * 116 * @param progressId The string representation of the progress ID that you want to know the progress of. 117 * @return a value between 0 to 100 indicating the progress 118 */ 119 public int getProgress( final String progressId ) 120 { 121 return DefaultProgressManager.this.getProgress( progressId ); 122 } 123 124 public String getServletMapping() { 125 return JSON_PROGRESSTRACKER; 126 } 127 128 public void service( final HttpServletRequest req, 129 final HttpServletResponse resp, 130 final String actionName, 131 final List< String > params ) throws IOException { 132 log.debug( "ProgressManager.doGet() START" ); 133 if( params.size() < 1 ) { 134 return; 135 } 136 final String progressId = params.get(0); 137 log.debug( "progressId=" + progressId ); 138 String progressString = ""; 139 try { 140 progressString = Integer.toString( getProgress( progressId ) ); 141 } catch( final IllegalArgumentException e ) { // ignore 142 log.debug( "progressId " + progressId + " is no longer valid" ); 143 } 144 log.debug( "progressString=" + progressString ); 145 resp.getWriter().write( progressString ); 146 log.debug( "ProgressManager.doGet() DONE" ); 147 } 148 149 } 150 151}