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 @Override 073 public void startProgress( final ProgressItem pi, final String id ) { 074 LOG.debug( "Adding " + id + " to progress queue" ); 075 m_progressingTasks.put( id, pi ); 076 pi.setState( ProgressItem.STARTED ); 077 } 078 079 /** 080 * Call this method to remove your ProgressItem from the queue (after which getProgress() will no longer find it. 081 * The ProgressItem will be moved to state STOPPED. 082 * 083 * @param id The progress identifier 084 */ 085 @Override 086 public void stopProgress( final String id ) { 087 LOG.debug( "Removed " + id + " from progress queue" ); 088 final ProgressItem pi = m_progressingTasks.remove( id ); 089 if( pi != null ) { 090 pi.setState( ProgressItem.STOPPED ); 091 } 092 } 093 094 /** 095 * Get the progress in percents. 096 * 097 * @param id The progress identifier. 098 * @return a value between 0 to 100 indicating the progress 099 * @throws IllegalArgumentException If no such progress item exists. 100 */ 101 @Override 102 public int getProgress( final String id ) throws IllegalArgumentException { 103 final ProgressItem pi = m_progressingTasks.get( id ); 104 if( pi != null ) { 105 return pi.getProgress(); 106 } 107 108 throw new IllegalArgumentException( "No such id was found" ); 109 } 110 111 /** 112 * Provides access to a progress indicator, assuming you know the ID. Progress of zero (0) means that the progress has just started, 113 * and a progress of 100 means that it is complete. 114 */ 115 public class JSONTracker implements WikiAjaxServlet { 116 /** 117 * Returns upload progress in percents so far. 118 * 119 * @param progressId The string representation of the progress ID that you want to know the progress of. 120 * @return a value between 0 to 100 indicating the progress 121 */ 122 public int getProgress( final String progressId ) 123 { 124 return DefaultProgressManager.this.getProgress( progressId ); 125 } 126 127 @Override 128 public String getServletMapping() { 129 return JSON_PROGRESSTRACKER; 130 } 131 132 @Override 133 public void service( final HttpServletRequest req, 134 final HttpServletResponse resp, 135 final String actionName, 136 final List< String > params ) throws IOException { 137 LOG.debug( "ProgressManager.doGet() START" ); 138 if( params.isEmpty() ) { 139 return; 140 } 141 final String progressId = params.get(0); 142 LOG.debug( "progressId=" + progressId ); 143 String progressString = ""; 144 try { 145 progressString = Integer.toString( getProgress( progressId ) ); 146 } catch( final IllegalArgumentException e ) { // ignore 147 LOG.debug( "progressId " + progressId + " is no longer valid" ); 148 } 149 LOG.debug( "progressString=" + progressString ); 150 resp.getWriter().write( progressString ); 151 LOG.debug( "ProgressManager.doGet() DONE" ); 152 } 153 154 } 155 156}