001    /*
002     * $RCSfile: RDLHandler.java,v $ 
003     *
004     * Created on Dec 2 2004, 16:39 PM
005     *
006     * This file is part of the STAR Scheduler.
007     * Copyright (c) 2004-2006 STAR Collaboration - Brookhaven National Laboratory
008     *
009     * STAR Scheduler is free software; you can redistribute it and/or modify
010     * it under the terms of the GNU General Public License as published by
011     * the Free Software Foundation; either version 2 of the License, or
012     * (at your option) any later version.
013     *
014     * STAR Scheduler is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017     * GNU General Public License for more details.
018     *
019     * You should have received a copy of the GNU General Public License
020     * along with STAR Scheduler; if not, write to the Free Software
021     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
022     */
023    package gov.bnl.star.offline.scheduler.request;
024    
025    import gov.bnl.star.offline.scheduler.request.rdl.*;
026    import gov.bnl.star.offline.scheduler.CatalogQuery;
027    import gov.bnl.star.offline.scheduler.OutputFile;
028    
029    import java.util.List;
030    import java.net.URL;
031    import java.net.MalformedURLException;
032    import java.util.Hashtable;
033    import org.xml.sax.Attributes;
034    
035    /** Get RDL request parse events from SAXParser
036     *  and create a Request object
037     *
038     * @author  paulh
039     * @version $Revision: 1.8 $ $Date: 2006/11/21 00:41:31 $
040     */
041    public class RDLHandler extends RequestHandler {
042    
043        private String chars = "";
044        private String appRef;                // Request's appRef
045        private String taskRef;               // Request's taskRef
046        private String resourceRef;           // Request's resourceRef
047        private String datasetID;             // current Dataset ID
048        private String copySource = "";       // current Source elt value
049        private String copyDest = "";         // current Destination elt value
050        private String register = "";         // current Register elt value
051        private String queryName;             // current Query Name
052        private boolean catalog = false;      // true if inside Catalog elt
053        private boolean resourceSpec = false; // true if inside ResourceSpec elt
054        private Resource resource = null;     // current Resource
055        private Task task = null;             // current Task
056        // hash to store IDs of all Datasets the Request will use
057        private Hashtable datasets = new Hashtable();
058    
059      /** Parses a RDL request according to STAR scheduler RDL spec. 
060        */
061        public RDLHandler(String xmlFileName) {
062            super(xmlFileName);
063        }
064    
065      /** Receive raw character data from the parser.
066        */
067        public void characters(char[] ch, int start, int length) {
068            chars += new String(ch, start, length);
069        }
070       
071      /** Handle a Request element
072        */ 
073        private void requestElement(Attributes attrs) {
074            if (requests.size() > 0) return; // ignore add'l requests
075    
076            appRef = attrs.getValue("appRef");
077            taskRef = attrs.getValue("taskRef");
078            String datasetRef = attrs.getValue("datasetRef"); 
079            if (datasetRef != null)
080               datasets.put(datasetRef, datasetRef);
081            resourceRef = attrs.getValue("resourceRef");
082    
083            Request req = new Request(xmlFileName);
084            requests.add(req);
085        }
086    
087      /** Handle a Task element
088        */
089        private void taskElement(String qName, Attributes attrs) {
090            String taskID = attrs.getValue("ID");
091            if (taskID.equals(taskRef)) {
092                if (qName.equals("ScriptTask"))
093                    task = new ScriptTask();
094                else if (qName.equals("JavaTask"))
095                    task = new JavaTask();
096                else if (qName.equals("RootTask"))
097                    task = new RootTask();
098            }
099        }
100    
101      /** Handle an Application element
102        */
103        private void applicationElement(Attributes attrs) {
104            String ID = attrs.getValue("ID");
105    
106            if (!appRef.equals(ID)) return;
107    
108            String name = attrs.getValue("name");
109            String type = attrs.getValue("type");
110            String ver = attrs.getValue("ver");
111            Application app = new Application(type, name, ver);
112            Request req = ((Request)requests.get(requests.size() - 1));
113    
114            req.setApplication(app);
115        }
116    
117      /** Handle a Dataset element
118        */
119        private void datasetElement(Attributes attrs) {
120            datasetID = attrs.getValue("ID");
121        }
122    
123      /** Handle a ResourceSpecification element
124        */
125        private void resourceSpecElement(Attributes attrs) {
126            String ID = attrs.getValue("ID");
127    
128            if (!ID.equals(resourceRef)) return;
129    
130            resourceSpec = true;
131        }
132    
133      /** Handle Task element when it is done
134        */
135        private void endTask() {
136            if (task != null) {
137                Request req = ((Request)requests.get(requests.size() - 1));
138                req.setTask(task); 
139            }
140            task = null;
141        }
142    
143      /** Handle TaskArguments element when it is done
144        */
145        private void endTaskArguments() {
146            if (task != null)
147                task.setTaskArguments(chars);
148        }
149    
150      /** Handle Argument element when it is done
151        */
152        private void endArgument() {
153            if (task != null)
154                task.addArgument(chars);
155        }
156    
157      /** Handle OutputHandling element when it is done
158        */
159        private void endOutputHandling() {
160            List outputList = 
161                ((Request)requests.get(requests.size()-1)).getOutputList();
162            if (copySource.length() > 0 && copyDest.length() > 0) {
163                OutputFile file = new OutputFile(copySource, copyDest);
164                outputList.add(file);
165                copySource = "";
166                copyDest = "";
167            } else if (register.length() > 0) {
168                CatalogQuery query = new CatalogQuery(register);
169                outputList.add(query);
170                register = "";
171            }
172        }
173    
174      /** Handle EmbeddedScript element when it is done
175        */
176        private void endEmbeddedScript() {
177            if (task == null) return;
178    
179            ((ScriptTask)task).setScript(chars);
180        }
181    
182      /** Handle ScriptName element when it is done
183        */
184        private void endScriptName() {
185            if (task == null) return;
186    
187            ((ScriptTask)task).setScript(chars);                                    
188            ((ScriptTask)task).setEmbedded(false);
189        }
190    
191      /** Handle Macro element when it is done
192        */
193        private void endMacro() {
194            if (task == null) return;
195                                                                                    
196            ((RootTask)task).setMacro(chars);
197        }
198    
199      /** Handle ClassPath element when it is done
200        */
201        private void endClassPath() {
202            if (task == null) return;
203                                                                                    
204            ((JavaTask)task).setClassPath(chars);
205        }
206    
207      /** Handle ClassName element when it is done
208        */
209        private void endClassName() {
210            if (task == null) return;
211                                                                                    
212            ((JavaTask)task).setClassName(chars);
213        }
214    
215      /** Handle MainJar element when it is done
216        */
217        private void endMainJar() {
218            if (task == null) return;
219                                                                                    
220            ((JavaTask)task).setMainJar(chars);
221        }
222    
223      /** Handle Name element when it is done
224        */
225        private void endName() {
226            if (datasets.get(datasetID) == null)
227                return;
228    
229            if (catalog)
230                queryName = chars.trim();
231            else {
232                List input = 
233                    ((Request) requests.get(requests.size()-1)).getInputList();
234                URL inputFile;
235    
236                chars = chars.trim();
237                try {
238                    inputFile = new URL(chars);
239                } catch (MalformedURLException e) {
240                    throw new RuntimeException("Malformed Dataset Name URL: " +
241                        e.getMessage());
242                }
243                input.add(inputFile);
244            }
245        }
246    
247      /** Handle DataSetIDRef element when it is done
248        */
249        private void endDataSetIDRef() {
250            if (datasets.get(datasetID) == null)
251                return;
252    
253            String ID = chars.trim();
254            datasets.put(ID, ID);
255        }
256    
257      /** Handle Query element when it is done
258        */
259        private void endQuery() {
260            List input =
261                ((Request) requests.get(requests.size()-1)).getInputList();
262                                                                                    
263            chars = chars.trim();
264            CatalogQuery query = new CatalogQuery(queryName + "?" + chars);
265            input.add(query);
266        }
267    
268      /** Handle STDIN element when it is done
269        */
270        private void endStdin() {
271            if (task == null) return;
272    
273            URL stdin;
274            try {
275                stdin = new URL(chars.trim());
276            } catch (MalformedURLException e) {
277                throw new RuntimeException("Malformed STDIN URL: " +
278                    e.getMessage());
279            }
280            task.setStdIn(stdin);
281        }
282    
283      /** Handle STDOUT element when it is done
284        */
285        private void endStdout() {
286            if (task == null) return;
287    
288            URL stdout;
289            try {
290                stdout = new URL(chars.trim());
291            } catch (MalformedURLException e) {
292                throw new RuntimeException("Malformed STDOUT URL: " +
293                    e.getMessage());
294            }
295            task.setStdOut(stdout);
296        }
297    
298      /** Handle STDERR element when it is done
299        */
300        private void endStderr() {
301            if (task == null) return;
302    
303            URL stderr;
304            try {
305                stderr = new URL(chars.trim());
306            } catch (MalformedURLException e) {
307                throw new RuntimeException("Malformed STDERR URL: " +
308                    e.getMessage());
309            }
310            task.setStdErr(stderr);
311        }
312    
313      /** Handle MinimumUnitsRequired element when it is done
314        */
315        private void endMinUnits() {
316            if (resource == null) return;
317    
318            int min = 0;
319            try {
320                min = Integer.parseInt(chars.trim());
321            } catch (NumberFormatException e) {
322                throw new RuntimeException(
323                    "Invalid value for MininumUnitsRequired: " + chars.trim());
324            }
325            resource.setMin(min);
326        }
327    
328      /** Handle MaximumUnitsEstimated element when it is done
329        */
330        private void endMaxUnits() {
331            if (resource == null) return;
332    
333            int max = 0;
334            try {
335                max = Integer.parseInt(chars.trim());
336            } catch (NumberFormatException e) {
337                throw new RuntimeException(
338                    "Invalid value for MaximumUnitsEstimated: " + chars.trim());
339            }
340            resource.setMax(max); 
341        }
342    
343      /** Handle AverageSizeOfUnit element when it is done
344        */
345        private void endAverageSize() {
346            if (resource == null) return;
347    
348            double size = 0;
349            try {
350                size = Double.parseDouble(chars.trim());
351            } catch (NumberFormatException e) {
352                throw new RuntimeException(
353                    "Invalid value for AverageSizeOfUnit: " + chars.trim());
354            }
355            resource.setSize(size);
356        }
357    
358      /** Handle UnitsPerSeconds element when it is done
359        */
360        private void endUnitRate() {
361            if (resource == null) return;
362    
363            int rate = 0;
364            try {
365                rate = Integer.parseInt(chars.trim());
366            } catch (NumberFormatException e) {
367                throw new RuntimeException(
368                    "Invalid value for UnitsPerSeconds: " + chars.trim());
369            }
370            resource.setRate(rate);
371        }
372    
373      /** Event received when parser encounters a new element.
374        */
375        public void startElement(String namespaceURI, String sName, String qName,
376                 Attributes attrs) {
377            if (qName.equals("Request")) {
378                requestElement(attrs);
379            } else if (qName.equals("Application")) {
380                applicationElement(attrs);
381            } else if (qName.equals("GenericDataset")) {
382                datasetElement(attrs);
383            } else if (qName.equals("Catalog")) {
384                catalog = true;
385            } else if (qName.equals("ResourceSpecifications")) {
386                resourceSpecElement(attrs);
387            } else if (qName.equals("ScriptTask")
388                       || qName.equals("RootTask")
389                       || qName.equals("JavaTask")) {
390                taskElement(qName, attrs);
391            } else if (resourceSpec && resource == null) {
392                resource = new Resource(qName);
393            }
394            chars = "";
395        }
396    
397      /** Event received when parser finds the end of an element.
398        * Does most of work to add values to Request.
399        */
400        public void endElement(String uri, String localName, String qName) 
401                throws RuntimeException {
402            Request req = ((Request)requests.get(requests.size() - 1));
403    
404            if (qName.equals("RequestName")) {
405                req.setName(chars);
406            } else if (qName.equals("GenericDataset")) {
407                datasetID = "";
408            } else if (qName.equals("DataSetIDRef")) {
409                endDataSetIDRef();
410            } else if (qName.equals("TaskArguments")) {
411                endTaskArguments();
412            } else if (qName.equals("Argument")) {
413                endArgument();
414            } else if (qName.equals("EmbeddedScript")) {
415                endEmbeddedScript();
416            } else if (qName.equals("ScriptName")) {
417                endScriptName();
418            } else if (qName.equals("Macro")) {
419                endMacro();
420            } else if (qName.equals("ClassPath")) {
421                endClassPath();
422            } else if (qName.equals("ClassName")) {
423                endClassName();
424            } else if (qName.equals("MainJar")) {
425                endMainJar();
426            } else if (qName.equals("Source")) {
427                copySource = chars.trim();
428            } else if (qName.equals("Destination")) {
429                copyDest = chars.trim();
430            } else if (qName.equals("Register")) {
431                register = chars.trim();
432            } else if (qName.equals("OutputHandling")) {
433                endOutputHandling();
434            } else if (qName.equals("Name")) {
435                endName();
436            } else if (qName.equals("Query")) {
437                endQuery();
438            } else if (qName.equals("Catalog")) {
439                catalog = false;
440            } else if (qName.equals("ResourceSpecifications")) {
441                resourceSpec = false;
442            } else if (qName.equals("STDIN")) {
443                endStdin();
444            } else if (qName.equals("STDOUT")) {
445                endStdout();
446            } else if (qName.equals("STDERR")) {
447                endStderr();
448            } else if (qName.equals("MininumUnitsRequired")) {
449                endMinUnits();
450            } else if (qName.equals("MaximumUnitsEstimated")) {
451                endMaxUnits();
452            } else if (qName.equals("AverageSizeOfUnit")) {
453                endAverageSize();
454            } else if (qName.equals("UnitsPerSeconds")) {
455                endUnitRate();
456            } else if (qName.equals("ScriptTask")
457                       || qName.equals("RootTask")
458                       || qName.equals("JavaTask")) {
459                endTask();
460            } else if (resourceSpec 
461                       && resource != null
462                       && qName.equals(resource.getName())) {
463                req.addResource(resource);
464                resource = null;
465            }
466    
467            chars = "";
468        }
469        
470    }