Newer
Older
package uws.service;
/*
* This file is part of UWSLibrary.
*
* UWSLibrary is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UWSLibrary is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with UWSLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import uws.AcceptHeader;
import uws.UWSException;
import uws.UWSToolBox;
import uws.job.JobList;
import uws.job.JobThread;
import uws.job.serializer.JSONSerializer;
import uws.job.serializer.UWSSerializer;
import uws.job.serializer.XMLSerializer;
import uws.job.user.JobOwner;
import uws.service.actions.AddJob;
import uws.service.actions.DestroyJob;
import uws.service.actions.GetJobParam;
import uws.service.actions.JobSummary;
import uws.service.actions.ListJobs;
import uws.service.actions.SetJobParam;
import uws.service.actions.SetUWSParameter;
import uws.service.actions.ShowHomePage;
import uws.service.actions.UWSAction;
import uws.service.backup.UWSBackupManager;
import uws.service.error.DefaultUWSErrorWriter;
import uws.service.error.ServiceErrorWriter;
import uws.service.file.UWSFileManager;
import uws.service.log.DefaultUWSLog;
import uws.service.log.UWSLog;
import uws.service.log.UWSLog.LogLevel;
import uws.service.request.RequestParser;
* <p>This class implements directly the interface {@link UWS} and so, it represents the core of a UWS service.</p>
* <p>
* Using this class is very simple! An instance must be created by providing at a factory - {@link UWSFactory} - and a file manager - {@link UWSFileManager}.
* This creation must be done in the init() function of a {@link HttpServlet}. Then, still in init(), at least one job list must be created.
* Finally, in order to ensure that all requests are interpreted by the UWS service, they must be sent to the created {@link UWSService} in the function
* {@link #executeRequest(HttpServletRequest, HttpServletResponse)}.
* </p>
* <p>Here is an example of what should look like the servlet class:</p>
* <pre>
* public class MyUWSService extends HttpServlet {
* private UWS uws;
* public void init(ServletConfig config) throws ServletException {
* try{
* // Create the UWS service:
* uws = new UWSService(new MyUWSFactory(), new LocalUWSFileManager(new File(config.getServletContext().getRealPath("UWSFiles"))));
* // Create at least one job list (otherwise no job can be started):
* uws.addJobList("jobList");
* }catch(UWSException ue){
* throw new ServletException("Can not initialize the UWS service!", ue);
* }
* }
* public void destroy(){
* if (uws != null)
* uws.destroy();
* }
* public void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException{
* try{
* service.executeRequest(request, response);
* }catch(UWSException ue){
* response.sendError(ue.getHttpErrorCode(), ue.getMessage());
* }
* }
* }
* </pre>
*
* <h3>UWS actions</h3>
*
* <p>
* All standard UWS actions are already implemented in this class. However, it is still possible to modify their implementation and/or to
* add or remove some actions.
* </p>
* <p>
* A UWS action is actually implemented here by a class extending the abstract class {@link UWSAction}. Here is the full list of all
* the available and already implemented actions:
* </p>
* <li>{@link AddJob}</li>
* <li>{@link DestroyJob}</li>
* <li>{@link JobSummary}</li>
* <li>{@link GetJobParam}</li>
* <li>{@link SetJobParam}</li>
* <li>{@link ListJobs}</li>
* </ul>
* <p>
* To add an action, you should use the function {@link #addUWSAction(UWSAction)}, to remove one {@link #removeUWSAction(int)} or {@link #removeUWSAction(String)}.
* Note that this last function takes a String parameter. This parameter is the name of the UWS action to remove. Indeed, each UWS action must have an internal
* name representing the action. Thus, it is possible to replace a UWS action implementation by using the function {@link #replaceUWSAction(UWSAction)} ; this
* function will replace the action having the same name as the given action.
* <p>
* In addition of all the actions listed above, a last action is automatically added: {@link ShowHomePage}. This is the action which will display the home page of
* the UWS service. It is called when the root resource of the web service is asked. To change it, you can either overwrite this action
* (see {@link #replaceUWSAction(UWSAction)}) or set an home page URL with the function {@link #setHomePage(String)} <i>(the parameter is a URI pointing on either
* a local or a remote resource)</i> or {@link #setHomePage(URL, boolean)}.
* @author Grégory Mantelet (CDS;ARI)
* @version 4.2 (09/2017)
*/
public class UWSService implements UWS {
/** Name of this UWS. */
protected String name = null;
/** Description of this UWS. */
protected String description = null;
/** List of all managed jobs lists. <i>(it is a LinkedHashMap so that jobs lists are ordered by insertion)</i> */
gmantele
committed
protected final Map<String,JobList> mapJobLists;
/** The "interpreter" of UWS URLs. */
protected UWSUrl urlInterpreter = null;
/** List of available serializers. */
gmantele
committed
protected final Map<String,UWSSerializer> serializers;
/** The MIME type of the default serialization format. */
protected String defaultSerializer = null;
/** The serializer chosen during the last call of {@link #executeRequest(HttpServletRequest, HttpServletResponse)}. */
protected UWSSerializer choosenSerializer = null;
/** URL of the home page. (<i>NULL if there is no home page</i>) */
protected String homePage = null;
/** Indicates whether the home page must be a copy or a redirection to the given URL. */
protected boolean homeRedirection = false;
/** MIME type of the custom home page. By default, it is "text/html".
* @since 4.2 */
protected String homePageMimeType = "text/html";
/** List of UWS actions (i.e. to list jobs, to get a job, to set a job parameter, etc...). */
protected final Vector<UWSAction> uwsActions;
/** The action executed during the last call of {@link #executeRequest(HttpServletRequest, HttpServletResponse)}. */
protected UWSAction executedAction = null;
/** The object to use to extract the user ID from the received request. */
protected UserIdentifier userIdentifier = null;
/** Factory which lets creating the UWS jobs and their thread. */
protected final UWSFactory factory;
/** Lets managing all UWS files (i.e. log, result, backup, ...). */
protected final UWSFileManager fileManager;
/** Lets saving and/or restoring the whole UWS. */
protected UWSBackupManager backupManager;
/** Lets logging info/debug/warnings/errors about this UWS. */
protected UWSLog logger;
/** Lets extract all parameters from an HTTP request, whatever is its content-type.
* @since 4.1*/
protected final RequestParser requestParser;
/** Lets writing/formatting any exception/throwable in a HttpServletResponse. */
protected ServiceErrorWriter errorWriter;
/** Last generated request ID. If the next generated request ID is equivalent to this one,
* a new one will generate in order to ensure the unicity.
* @since 4.1 */
protected static String lastRequestID = null;
/* ************ */
/* CONSTRUCTORS */
/* ************ */
/**
* <p>Builds a UWS (the base URI will be extracted at the first request directly from the request itself).</p>
*
* <p>
* By default, this UWS has 2 serialization formats: XML ({@link XMLSerializer}) and JSON ({@link JSONSerializer}).
* All the default actions of a UWS are also already implemented.
* However, you still have to create at least one job list !
* </p>
*
* <p><i><u>note:</u> since no logger is provided, a default one is set automatically (see {@link DefaultUWSLog}).</i></p>
*
* @param jobFactory Object which lets creating the UWS jobs managed by this UWS and their thread/task.
* @param fileManager Object which lets managing all files managed by this UWS (i.e. log, result, backup, error, ...).
*
* @throws NullPointerException If at least one of the parameters is <i>null</i>.
* @throws UWSException If unable to create a request parser using the factory (see {@link UWSFactory#createRequestParser(UWSFileManager)}).
*
* @see #UWSService(UWSFactory, UWSFileManager, UWSLog)
*/
public UWSService(final UWSFactory jobFactory, final UWSFileManager fileManager) throws UWSException{
this(jobFactory, fileManager, (UWSLog)null);
}
gmantele
committed
/**
* <p>Builds a UWS (the base URI will be extracted at the first request directly from the request itself).</p>
*
* <p>
* By default, this UWS has 2 serialization formats: XML ({@link XMLSerializer}) and JSON ({@link JSONSerializer}).
* All the default actions of a UWS are also already implemented.
* However, you still have to create at least one job list !
* </p>
*
* @param jobFactory Object which lets creating the UWS jobs managed by this UWS and their thread/task.
* @param fileManager Object which lets managing all files managed by this UWS (i.e. log, result, backup, error, ...).
* @param logger Object which lets printing any message (error, info, debug, warning).
*
* @throws NullPointerException If at least one of the parameters is <i>null</i>.
* @throws UWSException If unable to create a request parser using the factory (see {@link UWSFactory#createRequestParser(UWSFileManager)}).
public UWSService(final UWSFactory jobFactory, final UWSFileManager fileManager, final UWSLog logger) throws UWSException{
if (jobFactory == null)
throw new NullPointerException("Missing UWS factory! Can not create a UWSService.");
factory = jobFactory;
if (fileManager == null)
throw new NullPointerException("Missing UWS file manager! Can not create a UWSService.");
this.fileManager = fileManager;
this.logger = (logger == null) ? new DefaultUWSLog(this) : logger;
requestParser = jobFactory.createRequestParser(fileManager);
errorWriter = new DefaultUWSErrorWriter(this.logger);
// Initialize the list of jobs:
gmantele
committed
mapJobLists = new LinkedHashMap<String,JobList>();
// Initialize the list of available serializers:
gmantele
committed
serializers = new HashMap<String,UWSSerializer>();
addSerializer(new XMLSerializer());
addSerializer(new JSONSerializer());
// Initialize the list of UWS actions:
uwsActions = new Vector<UWSAction>();
// Load the default UWS actions:
uwsActions.add(new ShowHomePage(this));
uwsActions.add(new ListJobs(this));
uwsActions.add(new AddJob(this));
uwsActions.add(new SetUWSParameter(this));
uwsActions.add(new DestroyJob(this));
uwsActions.add(new JobSummary(this));
uwsActions.add(new GetJobParam(this));
uwsActions.add(new SetJobParam(this));
}
/**
* <p>Builds a UWS with its base UWS URI.</p>
*
* <p><i><u>note:</u> since no logger is provided, a default one is set automatically (see {@link DefaultUWSLog}).</i></p>
*
* @param jobFactory Object which lets creating the UWS jobs managed by this UWS and their thread/task.
* @param fileManager Object which lets managing all files managed by this UWS (i.e. log, result, backup, error, ...).
* @param baseURI Base UWS URI.
*
* @throws UWSException If the given URI is <i>null</i> or empty.
*
* @see #UWSService(UWSFactory, UWSFileManager, UWSLog, String)
*/
gmantele
committed
public UWSService(final UWSFactory jobFactory, final UWSFileManager fileManager, final String baseURI) throws UWSException{
this(jobFactory, fileManager, null, baseURI);
}
/**
* Builds a UWS with its base UWS URI.
*
* @param jobFactory Object which lets creating the UWS jobs managed by this UWS and their thread/task.
* @param fileManager Object which lets managing all files managed by this UWS (i.e. log, result, backup, error, ...).
* @param logger Object which lets printing any message (error, info, debug, warning).
* @param baseURI Base UWS URI.
*
* @throws UWSException If the given URI is <i>null</i> or empty.
*
* @see UWSUrl#UWSUrl(String)
*/
gmantele
committed
public UWSService(final UWSFactory jobFactory, final UWSFileManager fileManager, final UWSLog logger, final String baseURI) throws UWSException{
this(jobFactory, fileManager, logger);
// Extract the name of the UWS:
try{
// Set the URL interpreter:
urlInterpreter = new UWSUrl(baseURI);
// ...and the name of this service:
name = urlInterpreter.getUWSName();
// Log the successful initialization:
logger.logUWS(LogLevel.INFO, this, "INIT", "UWS successfully initialized!", null);
}catch(NullPointerException ex){
// Log the exception:
// (since the first constructor has already been called successfully, the logger is now NOT NULL):
logger.logUWS(LogLevel.FATAL, null, "INIT", "Invalid base UWS URI: " + baseURI + "! You should check the configuration of the service.", ex);
// Throw a new UWSException with a more understandable message:
throw new UWSException(UWSException.BAD_REQUEST, ex, "Invalid base UWS URI (" + baseURI + ")!");
}
}
/**
* <p>Builds a UWS with the given UWS URL interpreter.</p>
*
* <p><i><u>note:</u> since no logger is provided, a default one is set automatically (see {@link DefaultUWSLog}).</i></p>
*
* @param jobFactory Object which lets creating the UWS jobs managed by this UWS and their thread/task.
* @param fileManager Object which lets managing all files managed by this UWS (i.e. log, result, backup, error, ...).
* @param urlInterpreter The UWS URL interpreter to use in this UWS.
*
* @throws UWSException If unable to create a request parser using the factory (see {@link UWSFactory#createRequestParser(UWSFileManager)}).
*
* @see #UWSService(UWSFactory, UWSFileManager, UWSLog, UWSUrl)
*/
public UWSService(final UWSFactory jobFactory, final UWSFileManager fileManager, final UWSUrl urlInterpreter) throws UWSException{
this(jobFactory, fileManager, null, urlInterpreter);
}
/**
* Builds a UWS with the given UWS URL interpreter.
*
* @param jobFactory Object which lets creating the UWS jobs managed by this UWS and their thread/task.
* @param fileManager Object which lets managing all files managed by this UWS (i.e. log, result, backup, error, ...).
* @param logger Object which lets printing any message (error, info, debug, warning).
* @param urlInterpreter The UWS URL interpreter to use in this UWS.
*
* @throws UWSException If unable to create a request parser using the factory (see {@link UWSFactory#createRequestParser(UWSFileManager)}).
public UWSService(final UWSFactory jobFactory, final UWSFileManager fileManager, final UWSLog logger, final UWSUrl urlInterpreter) throws UWSException{
this(jobFactory, fileManager, logger);
setUrlInterpreter(urlInterpreter);
if (this.urlInterpreter != null)
logger.logUWS(LogLevel.INFO, this, "INIT", "UWS successfully initialized.", null);
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
@Override
public void destroy(){
// Backup all jobs:
/* Jobs are backuped now so that running jobs are set back to the PENDING phase in the backup.
* Indeed, the "stopAll" operation of the ExecutionManager may fail and would set the phase to ERROR
* for the wrong reason. */
if (backupManager != null){
// save all jobs:
backupManager.setEnabled(true);
backupManager.saveAll();
// stop the automatic backup, if there is one:
backupManager.setEnabled(false);
}
// Stop all jobs and stop watching for the jobs' destruction:
for(JobList jl : mapJobLists.values()){
jl.getExecutionManager().stopAll();
jl.getDestructionManager().stop();
}
// Just in case that previous clean "stop"s did not work, try again an interruption for all running threads:
/* note: timers are not part of this ThreadGroup and so, they won't be affected by this function call. */
JobThread.tg.interrupt();
// Log the service is stopped:
if (logger != null)
logger.logUWS(LogLevel.INFO, this, "STOP", "UWS Service \"" + getName() + "\" stopped!", null);
}
/* ************** */
/* LOG MANAGEMENT */
/* ************** */
@Override
public UWSLog getLogger(){
return logger;
}
/**
* Gets the object used to write/format any error in a HttpServletResponse.
*
* @return The error writer/formatter.
*/
gmantele
committed
public final ServiceErrorWriter getErrorWriter(){
return errorWriter;
}
/**
* <p>Sets the object used to write/format any error in a HttpServletResponse.</p>
*
* <p><i><u>Note:</u> Nothing is done if the given writer is NULL !</i></p>
*
* @param errorWriter The new error writer/formatter.
*/
gmantele
committed
public final void setErrorWriter(ServiceErrorWriter errorWriter){
if (errorWriter != null)
this.errorWriter = errorWriter;
}
/* ***************** */
/* GETTERS & SETTERS */
/* ***************** */
@Override
gmantele
committed
public final String getName(){
return name;
}
/**
* Sets the name of this UWS.
*
* @param name Its new name.
*/
public final void setName(String name){
this.name = name;
}
@Override
gmantele
committed
public final String getDescription(){
return description;
}
/**
* Sets the description of this UWS.
*
* @param description Its new description.
*/
gmantele
committed
public final void setDescription(String description){
this.description = description;
}
/**
* Gets the base UWS URL.
*
* @return The base UWS URL.
*
* @see UWSUrl#getBaseURI()
*/
public final String getBaseURI(){
return (urlInterpreter == null) ? null : urlInterpreter.getBaseURI();
}
@Override
public final UWSUrl getUrlInterpreter(){
return urlInterpreter;
}
/**
* Sets the UWS URL interpreter to use in this UWS.
*
* @param urlInterpreter Its new UWS URL interpreter (may be <i>null</i>. In this case, it will be created from the next request ; see {@link #executeRequest(HttpServletRequest, HttpServletResponse)}).
*/
public final void setUrlInterpreter(UWSUrl urlInterpreter){
this.urlInterpreter = urlInterpreter;
if (name == null && urlInterpreter != null)
name = urlInterpreter.getUWSName();
if (this.urlInterpreter != null)
this.urlInterpreter.setUwsURI(null);
}
/**
* <p>Gets the object which lets extracting the user ID from a HTTP request.</p>
* <p><i><u>note:</u>If the returned user identifier is NULL, no job should have an owner.</i></p>
*
* @return The used UserIdentifier (MAY BE NULL).
*/
@Override
public final UserIdentifier getUserIdentifier(){
return userIdentifier;
}
/**
* Sets the object which lets extracting the use ID from a received request.
*
* @param identifier The UserIdentifier to use (may be <i>null</i>).
*/
public final void setUserIdentifier(UserIdentifier identifier){
userIdentifier = identifier;
}
@Override
public final UWSFactory getFactory(){
return factory;
}
@Override
public final UWSFileManager getFileManager(){
return fileManager;
}
@Override
gmantele
committed
public final UWSBackupManager getBackupManager(){
return backupManager;
}
/**
* <p>
* Sets its backup manager.
* This manager will be called at each user action to save only its own jobs list by calling {@link UWSBackupManager#saveOwner(JobOwner)}.
* </p>
*
* @param backupManager Its new backup manager.
*/
gmantele
committed
public final void setBackupManager(final UWSBackupManager backupManager){
this.backupManager = backupManager;
}
@Override
public final RequestParser getRequestParser(){
return requestParser;
}
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
/* ******************** */
/* HOME PAGE MANAGEMENT */
/* ******************** */
/**
* Gets the URL of the resource which must be used as home page of this UWS.
*
* @return The URL of the home page.
*/
public final String getHomePage(){
return homePage;
}
/**
* Tells whether a redirection to the specified home page must be done or not.
*
* @return <i>true</i> if a redirection to the specified resource must be done
* or <i>false</i> to copy it.
*/
public final boolean isHomePageRedirection(){
return homeRedirection;
}
/**
* Sets the URL of the resource which must be used as home page of this UWS.
*
* @param homePageUrl The URL of the home page (may be <i>null</i>).
* @param redirect <i>true</i> if a redirection to the specified resource must be done
* or <i>false</i> to copy it.
*/
public final void setHomePage(URL homePageUrl, boolean redirect){
homePage = homePageUrl.toString();
homeRedirection = redirect;
}
/**
* <p>Sets the URI of the resource which must be used as home page of this UWS.</p>
* <i>A redirection will always be done on the specified resource.</i>
*
* @param homePageURI The URL of the home page.
*/
public final void setHomePage(String homePageURI){
homePage = homePageURI;
homeRedirection = true;
}
/**
* Indicates whether the current home page is the default one (the UWS serialization)
* or if it has been specified manually using {@link UWSService#setHomePage(URL, boolean)}.
*
* @return <i>true</i> if it is the default home page, <i>false</i> otherwise.
*/
public final boolean isDefaultHomePage(){
return homePage == null;
}
/**
* Forgets the home page specified by using {@link UWSService#setHomePage(URL, boolean)} - if any -
* and go back to the default home page (XML format).
*/
public final void setDefaultHomePage(){
homePage = null;
homeRedirection = false;
}
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
/**
* <p>Get the MIME type of the custom home page.</p>
*
* <p>By default, it is the same as the default home page: "text/html".</p>
*
* <p><i>Note:
* This function has a sense only if the HOME PAGE resource of this UWS service
* is still the default home page (i.e. {@link ShowHomePage}).
* </i></p>
*
* @return MIME type of the custom home page.
*
* @since 4.2
*/
public final String getHomePageMimeType(){
return homePageMimeType;
}
/**
* <p>Set the MIME type of the custom home page.</p>
*
* <p>A NULL value will be considered as "text/html".</p>
*
* <p><i>Note:
* This function has a sense only if the HOME PAGE resource of this UWS service
* is still the default home page (i.e. {@link ShowHomePage}).
* </i></p>
*
* @param mime MIME type of the custom home page.
*
* @since 4.2
*/
public final void setHomePageMimeType(final String mime){
homePageMimeType = (mime == null || mime.trim().length() == 0) ? "text/html" : mime.trim();
}
/* ********************** */
/* SERIALIZERS MANAGEMENT */
/* ********************** */
/**
* Gets the MIME type of the serializer to use by default.
*
* @return The MIME type of the default serializer.
*/
public final String getDefaultSerializer(){
return defaultSerializer;
}
/**
* Sets the MIME of the serializer to use by default.
*
* @param mimeType The MIME type (only one).
*
* @throws UWSException If there is no serializer with this MIME type available in this UWS.
*/
gmantele
committed
public final void setDefaultSerializer(String mimeType) throws UWSException{
if (serializers.containsKey(mimeType))
defaultSerializer = mimeType;
else
throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, "Missing UWS serializer for the MIME types: " + mimeType + "! The default serializer won't be set.");
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
}
/**
* <p>Adds a serializer to this UWS</p>
* <p><b><u>WARNING:</u> If there is already a serializer with the same MIME type (see {@link UWSSerializer#getMimeType()}) in this UWS ,
* it should be replaced by the given one !</b></p>
*
* @param serializer The serializer to add.
* @return <i>true</i> if the serializer has been successfully added, <i>false</i> otherwise.
*/
public final boolean addSerializer(UWSSerializer serializer){
if (serializer != null){
serializers.put(serializer.getMimeType(), serializer);
if (serializers.size() == 1)
defaultSerializer = serializer.getMimeType();
return true;
}
return false;
}
/**
* Tells whether this UWS has already a serializer with the given MIME type.
*
* @param mimeType A MIME type (only one).
*
* @return <i>true</i> if a serializer exists with the given MIME type, <i>false</i> otherwise.
*/
public final boolean hasSerializerFor(String mimeType){
return serializers.containsKey(mimeType);
}
/**
* Gets the total number of serializers available in this UWS.
*
* @return The number of its serializers.
*/
public final int getNbSerializers(){
return serializers.size();
}
/**
* Gets an iterator of the list of all serializers available in this UWS.
*
* @return An iterator on its serializers.
*/
public final Iterator<UWSSerializer> getSerializers(){
return serializers.values().iterator();
}
@Override
gmantele
committed
public final UWSSerializer getSerializer(String mimeTypes) throws UWSException{
choosenSerializer = null;
if (mimeTypes != null){
// Parse the given MIME types list:
AcceptHeader accept = new AcceptHeader(mimeTypes);
List<String> lstMimeTypes = accept.getOrderedMimeTypes();
// Try each of them and stop at the first which match with an existing serializer:
gmantele
committed
for(int i = 0; choosenSerializer == null && i < lstMimeTypes.size(); i++)
choosenSerializer = serializers.get(lstMimeTypes.get(i));
}
// If no serializer has been found for each given mime type, return the default one:
if (choosenSerializer == null){
choosenSerializer = serializers.get(defaultSerializer);
if (choosenSerializer == null)
gmantele
committed
throw new UWSException(UWSException.INTERNAL_SERVER_ERROR, "No UWS Serializer available neither for \"" + mimeTypes + "\" (given MIME types) nor \"" + defaultSerializer + "\" (default serializer MIME type) !");
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
}
return choosenSerializer;
}
/**
* Gets the serializer choosen during the last call of {@link #getSerializer(String)}.
*
* @return The last used serializer.
*/
public final UWSSerializer getChoosenSerializer(){
return choosenSerializer;
}
/**
* Removes the serializer whose the MIME type is the same as the given one.
*
* @param mimeType MIME type of the serializer to remove.
* @return The removed serializer
* or <i>null</i> if no corresponding serializer has been found.
*/
public final UWSSerializer removeSerializer(String mimeType){
return serializers.remove(mimeType);
}
/**
* Gets the URL of the XSLT style-sheet that the XML serializer of this UWS is using.
*
* @return The used XSLT URL.
*/
public final String getXsltURL(){
XMLSerializer serializer = (XMLSerializer)serializers.get(UWSSerializer.MIME_TYPE_XML);
if (serializer != null)
return serializer.getXSLTPath();
return null;
}
/**
* Sets the URL of the XSLT style-sheet that the XML serializer of this UWS must use.
*
* @param xsltPath The new XSLT URL.
*
* @return <i>true</i> if the given path/url has been successfully set, <i>false</i> otherwise.
*/
public final boolean setXsltURL(String xsltPath){
XMLSerializer serializer = (XMLSerializer)serializers.get(UWSSerializer.MIME_TYPE_XML);
if (serializer != null){
serializer.setXSLTPath(xsltPath);
return true;
}
return false;
}
/* ********************* */
/* JOBS LISTS MANAGEMENT */
/* ********************* */
/**
* An iterator on the jobs lists list.
*
* @see java.lang.Iterable#iterator()
*/
@Override
public final Iterator<JobList> iterator(){
return mapJobLists.values().iterator();
}
@Override
public final JobList getJobList(String name){
return mapJobLists.get(name);
}
@Override
public final int getNbJobList(){
return mapJobLists.size();
}
/**
* Adds a jobs list to this UWS.
*
* @param jl The jobs list to add.
*
* @return <i>true</i> if the jobs list has been successfully added,
* <i>false</i> if the given jobs list is <i>null</i> or if a jobs list with this name already exists
* or if a UWS is already associated with another UWS.
*
* @see JobList#setUWS(UWS)
* @see UWS#addJobList(JobList)
*/
@Override
public final boolean addJobList(JobList jl){
if (jl == null)
return false;
else if (mapJobLists.containsKey(jl.getName()))
return false;
try{
jl.setUWS(this);
mapJobLists.put(jl.getName(), jl);
gmantele
committed
}catch(IllegalStateException ise){
logger.logUWS(LogLevel.ERROR, jl, "ADD_JOB_LIST", "The jobs list \"" + jl.getName() + "\" can not be added into the UWS " + getName() + ": it may already be associated with one!", ise);
return false;
}
return true;
}
@Override
public final boolean destroyJobList(String name){
return destroyJobList(mapJobLists.get(name));
}
/**
* Destroys the given jobs list.
*
* @param jl The jobs list to destroy.
*
* @return <i>true</i> if the given jobs list has been destroyed, <i>false</i> otherwise.
*
* @see JobList#clear()
* @see JobList#setUWS(UWS)
gmantele
committed
public boolean destroyJobList(JobList jl){
if (jl == null)
return false;
jl = mapJobLists.remove(jl.getName());
if (jl != null){
try{
jl.clear();
jl.setUWS(null);
}catch(IllegalStateException ise){
logger.logUWS(LogLevel.WARNING, jl, "DESTROY_JOB_LIST", "Impossible to erase completely the association between the jobs list \"" + jl.getName() + "\" and the UWS \"" + getName() + "\"!", ise);
}
}
return jl != null;
}
/**
* Destroys all managed jobs lists.
*
* @see #destroyJobList(String)
*/
public final void destroyAllJobLists(){
ArrayList<String> jlNames = new ArrayList<String>(mapJobLists.keySet());
for(String jlName : jlNames)
destroyJobList(jlName);
}
/* ********************** */
/* UWS ACTIONS MANAGEMENT */
/* ********************** */
/**
* <p>Lets adding the given action to this UWS.</p>
*
* <p><b><u>WARNING:</u> The action will be added at the end of the actions list of this UWS. That means, it will be evaluated (call of
* the method {@link UWSAction#match(UWSUrl, JobOwner, HttpServletRequest)}) lastly !</b></p>
*
* @param action The UWS action to add.
*
* @return <i>true</i> if the given action has been successfully added, <i>false</i> otherwise.
*/
public final boolean addUWSAction(UWSAction action){
if (!uwsActions.contains(action))
return uwsActions.add(action);
else
return false;
}
/**
* <p>Lets inserting the given action at the given position in the actions list of this UWS.</p>
*
* @param indAction The index where the given action must be inserted.
* @param action The action to add.
*
* @return <i>true</i> if the given action has been successfully added, <i>false</i> otherwise.
*
* @throws ArrayIndexOutOfBoundsException If the given index is incorrect (index < 0 || index >= uwsActions.size()).
*/
gmantele
committed
public final boolean addUWSAction(int indAction, UWSAction action) throws ArrayIndexOutOfBoundsException{
if (!uwsActions.contains(action)){
uwsActions.add(indAction, action);
return true;
}
return false;
}
/**
* Replaces the specified action by the given action.
*
* @param indAction Index of the action to replace.
* @param action The replacer.
*
* @return <i>true</i> if the replacement has been a success, <i>false</i> otherwise.
*
* @throws ArrayIndexOutOfBoundsException If the index is incorrect (index < 0 || index >= uwsActions.size()).
*/
gmantele
committed
public final boolean setUWSAction(int indAction, UWSAction action) throws ArrayIndexOutOfBoundsException{
if (!uwsActions.contains(action)){
uwsActions.set(indAction, action);
return true;
}
return false;
}
/**
* Replaces the action which has the same name that the given action.
*
* @param action The replacer.
*
* @return The replaced action
* or <i>null</i> if the given action is <i>null</i>
* or if there is no action with the same name (in this case, the given action is not added).
*/
public final UWSAction replaceUWSAction(UWSAction action){
if (action == null)
return null;
else{
gmantele
committed
for(int i = 0; i < uwsActions.size(); i++){
if (uwsActions.get(i).equals(action))
return uwsActions.set(i, action);
}
return null;
}
}
/**
* Gets the number of actions this UWS has.
*
* @return The number of its actions.
*/
public final int getNbUWSActions(){
return uwsActions.size();
}
/**
* Gets the action of this UWS which has the same name as the given one.
*
* @param actionName The name of the searched action.
*
* @return The corresponding action
* or <i>null</i> if there is no corresponding action.
*/
public final UWSAction getUWSAction(String actionName){
gmantele
committed
for(int i = 0; i < uwsActions.size(); i++){
if (uwsActions.get(i).getName().equals(actionName))
return uwsActions.get(i);
}
return null;
}
/**
* Gets all actions of this UWS.
*
* @return An iterator on its actions.
*/
public final Iterator<UWSAction> getUWSActions(){
return uwsActions.iterator();
}
/**
* Gets the UWS action executed during the last call of {@link #executeRequest(HttpServletRequest, HttpServletResponse)}.
*
* @return The last used UWS action.
*/