View Javadoc

1   /*
2    * Copyright (c) 2007, Ounce Labs, Inc.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    *     * Redistributions of source code must retain the above copyright
8    *       notice, this list of conditions and the following disclaimer.
9    *     * Redistributions in binary form must reproduce the above copyright
10   *       notice, this list of conditions and the following disclaimer in the
11   *       documentation and/or other materials provided with the distribution.
12   *     * Neither the name of the <organization> nor the
13   *       names of its contributors may be used to endorse or promote products
14   *       derived from this software without specific prior written permission.
15   *
16   * THIS SOFTWARE IS PROVIDED BY OUNCE LABS, INC. ``AS IS'' AND ANY
17   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   * DISCLAIMED. IN NO EVENT SHALL OUNCE LABS, INC. BE LIABLE FOR ANY
20   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   */
27  package org.codehaus.mojo.ounce.core;
28  
29  import java.io.BufferedReader;
30  import java.io.File;
31  import java.io.IOException;
32  import java.io.InputStreamReader;
33  import java.util.ArrayList;
34  import java.util.Collections;
35  import java.util.Comparator;
36  import java.util.Enumeration;
37  import java.util.HashMap;
38  import java.util.Iterator;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.Properties;
42  import java.util.Set;
43  
44  import javax.xml.parsers.DocumentBuilder;
45  import javax.xml.parsers.DocumentBuilderFactory;
46  
47  import org.apache.maven.plugin.logging.Log;
48  import org.apache.xerces.dom.DocumentImpl;
49  import org.codehaus.plexus.util.StringUtils;
50  import org.w3c.dom.Document;
51  import org.w3c.dom.Element;
52  import org.w3c.dom.NamedNodeMap;
53  import org.w3c.dom.Node;
54  import org.w3c.dom.NodeList;
55  
56  /**
57   * @author <a href="mailto:sam.headrick@ouncelabs.com">Sam Headrick</a>
58   * @plexus.component role="org.codehaus.mojo.ounce.core.OunceCore" role-hint="ouncexml"
59   */
60  public class OunceCoreXmlSerializer
61      implements OunceCore
62  {
63  
64      private HashMap m_existingProjectAttributes;
65  
66      public void createApplication( String baseDir, String theName, String applicationRoot, List theProjects,
67                                     Map options, Log log )
68          throws OunceCoreException
69      {
70          // sort them to avoid implementation details messing
71          // up the order for testing.
72          Collections.sort( theProjects );
73  
74          log.info( "OunceCoreXmlSerializer: Writing Application parameters to xml." );
75  
76          try
77          {
78              m_existingProjectAttributes = new HashMap();
79  
80              // need to read the Application in first if it exists
81              // create the XML Document
82              Document xmlDoc;
83              Element root = null;
84              String filePath = baseDir + File.separator + theName + ".paf";
85              File pafFile = new File( filePath );
86              if ( pafFile.exists() )
87              {
88                  // load up the PAF
89                  DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
90                  log.info( "Reading paf: '" + filePath + "'..." );
91                  xmlDoc = builder.parse( pafFile );
92  
93                  NodeList nodes = xmlDoc.getChildNodes();
94                  for ( int i = 0; i < nodes.getLength(); i++ )
95                  {
96                      Node node = nodes.item( i );
97                      String name = node.getNodeName();
98  
99                      if ( name.equals( "Application" ) )
100                     {
101                         root = (Element) node;
102 
103                         NodeList applicationChildren = node.getChildNodes();
104                         for ( int j = 0; j < applicationChildren.getLength(); j++ )
105                         {
106                             Node child = applicationChildren.item( j );
107                             String childName = child.getNodeName();
108                             // don't preserve Projects, everything else should be left alone
109                             if ( childName.equals( "Project" ) )
110                             {
111                                 NamedNodeMap attributes = child.getAttributes();
112                                 String projectPath = attributes.getNamedItem( "path" ).getNodeValue();
113                                 m_existingProjectAttributes.put( projectPath, attributes );
114                                 node.removeChild( child );
115                             }
116                         }
117 
118                         // now add the new projects so they come first
119                         insertChildProjects( xmlDoc, root, theProjects );
120                     }
121                 }
122                 if ( root == null )
123                 {
124                     // every paf should have an Application element
125                     throw new OunceCoreException( "The existing application file '" + filePath
126                         + "' is not in a valid format and cannot be updated." );
127                 }
128             }
129             else
130             {
131                 log.info( "Creating new paf: '" + filePath + "'..." );
132                 xmlDoc = new DocumentImpl();
133                 root = xmlDoc.createElement( "Application" );
134                 root.setAttribute( "name", theName );
135                 xmlDoc.appendChild( root );
136                 insertChildProjects( xmlDoc, root, theProjects );
137             }
138 
139             // write out the XML
140             XmlWriter writer = new XmlWriter( true );
141             writer.setWriteEmptyValues( false );
142             writer.setDefaultToAttributesOnSameLine( true );
143             writer.saveXmlFile( filePath, xmlDoc );
144         }
145         catch ( Exception ex )
146         {
147             log.error( ex );
148         }
149     }
150 
151     private void insertChildProjects( Document xmlDoc, Element root, List theProjects )
152     {
153         // sort the projects by file path (in reverse order because they are written in reverse)
154         Collections.sort( theProjects, new Comparator()
155         {
156             public int compare( Object arg0, Object arg1 )
157             {
158                 OunceProjectBean project1 = (OunceProjectBean) arg0;
159                 OunceProjectBean project2 = (OunceProjectBean) arg1;
160                 String projectPath1 = project1.getPath() + File.separator + project1.name + ".ppf";
161                 String projectPath2 = project2.getPath() + File.separator + project2.name + ".ppf";
162                 return projectPath2.compareTo( projectPath1 );
163             }
164         } );
165 
166         for ( int i = 0; i < theProjects.size(); i++ )
167         {
168             OunceProjectBean projectBean = (OunceProjectBean) theProjects.get( i );
169             String projectPath = projectBean.getPath() + File.separator + projectBean.name + ".ppf";
170 
171             Element project = xmlDoc.createElementNS( null, "Project" );
172 
173             NamedNodeMap existingAttribs = (NamedNodeMap) m_existingProjectAttributes.get( projectPath );
174 
175             if ( existingAttribs != null )
176             {
177                 existingAttribs.removeNamedItem( "path" );
178                 existingAttribs.removeNamedItem( "language_type" );
179             }
180 
181             String fullPath = projectPath;
182             if ( !fullPath.startsWith( "./" ) )
183             {
184                 fullPath = "./" + projectPath;
185             }
186             project.setAttributeNS( null, "path", fullPath );
187             project.setAttributeNS( null, "language_type", "2" );
188 
189             if ( existingAttribs != null )
190             {
191                 for ( int j = 0; j < existingAttribs.getLength(); j++ )
192                 {
193                     Node node = existingAttribs.item( j );
194                     String name = node.getNodeName();
195                     String nodeValue = node.getNodeValue();
196                     project.setAttributeNS( null, name, nodeValue );
197                 }
198             }
199 
200             // if this a fresh XML doc or do we need to worry about making sure the projects come first?
201             NodeList childNodes = root.getChildNodes();
202             boolean hasChildren = childNodes.getLength() > 0;
203             if ( hasChildren )
204             {
205                 // there are other nodes
206                 Node child = childNodes.item( 0 );
207                 root.insertBefore( project, child );
208             }
209             else
210             {
211                 root.appendChild( project );
212             }
213         }
214     }
215 
216     public void createProject( String baseDir, String theName, String projectRoot, List theSourceRoots,
217                                String theWebRoot, String theClassPath, String theJdkName, String compilerOptions,
218                                String packaging, Map options,
219                                boolean analyzeStrutsFramework, boolean importStrutsValidation, Log log )
220         throws OunceCoreException
221     {
222         log.info( "OunceCoreXmlSerializer: Writing Project parameters to xml." );
223 
224         // place all of the Project properties into a property bundle
225         Properties projectProperties = new Properties();
226 
227         // set the dynamic values
228         projectProperties.setProperty( "name", theName );
229 
230         // set the constant values
231         projectProperties.setProperty( "language_type", "2" );
232         projectProperties.setProperty( "default_configuration_name", "Configuration 1" );
233 
234         if ( options != null )
235         {
236             Set keys = options.keySet();
237             Iterator it = keys.iterator();
238             while ( it.hasNext() )
239             {
240                 String key = (String) it.next();
241                 String value = (String) options.get( key );
242                 projectProperties.setProperty( key, value );
243             }
244         }
245 
246         if ( !StringUtils.isEmpty( theWebRoot ) && ( !StringUtils.isEmpty( packaging ) && packaging.equals( "war" ) ) )
247         {
248             projectProperties.setProperty( "web_context_root_path", theWebRoot.trim() );
249         }
250         else
251         {
252             theWebRoot = null;
253         }
254 
255         if ( !StringUtils.isEmpty( compilerOptions ) )
256         {
257             projectProperties.setProperty( "compiler_options", compilerOptions );
258         }
259         
260         if ( analyzeStrutsFramework != false ) {
261         	projectProperties.setProperty( "analyze_struts_framework", "true" );
262         } 
263         
264         if ( importStrutsValidation != false ) {
265         	projectProperties.setProperty( "import_struts_validation", "true" );
266         }
267 
268         try
269         {
270             HashMap existingConfigurationAttribs = new HashMap();
271             HashMap existingSourceAttribs = new HashMap();
272             ArrayList excludedSources = new ArrayList();
273 
274             Document xmlDoc;
275             Element root = null;
276             String filePath = baseDir + File.separator + theName + ".ppf";
277             File ppfFile = new File( filePath );
278             if ( ppfFile.exists() )
279             {
280                 // need to preserve information that could be in the ppf (Project validation routines, etc.)
281                 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
282                 log.info( "Reading ppf: '" + filePath + "'..." );
283                 xmlDoc = builder.parse( ppfFile );
284                 NodeList nodes = xmlDoc.getChildNodes();
285                 for ( int i = 0; i < nodes.getLength(); i++ )
286                 {
287                     Node node = nodes.item( i );
288                     String name = node.getNodeName();
289                     // Project should be the only top-level node -- others can be ignored
290                     if ( name.equals( "Project" ) )
291                     {
292                         root = (Element) node;
293                         NodeList projectChildren = node.getChildNodes();
294                         for ( int j = 0; j < projectChildren.getLength(); j++ )
295                         {
296                             Node child = projectChildren.item( j );
297                             String childName = child.getNodeName();
298 
299                             NamedNodeMap attributes = child.getAttributes();
300 
301                             // Don't preserve Configuration and Source (but remember their attributes for
302                             // later). Everything else should be left alone.
303                             if ( childName.equals( "Configuration" ) )
304                             {
305                                 String configurationName = attributes.getNamedItem( "name" ).getNodeValue();
306                                 existingConfigurationAttribs.put( configurationName, attributes );
307                                 node.removeChild( child );
308                             }
309                             else if ( childName.equals( "Source" ) )
310                             {
311                                 String sourcePath = attributes.getNamedItem( "path" ).getNodeValue();
312                                 String excludedStr = attributes.getNamedItem( "exclude" ).getNodeValue();
313                                 if ( excludedStr.equals( "true" ) )
314                                 {
315                                     excludedSources.add( child );
316                                 }
317                                 existingSourceAttribs.put( sourcePath, attributes );
318                                 node.removeChild( child );
319                             }
320                             // shouldn't need to handle SourceFile here because they come after Source
321                         }
322                     }
323                 }
324                 if ( root == null )
325                 {
326                     // every ppf should have a Project element
327                     throw new OunceCoreException( "The existing project file '" + filePath
328                         + "' is not in a valid format and cannot be updated." );
329                 }
330             }
331             else
332             {
333                 log.info( "Creating new Document..." );
334                 // create a new XML Document
335                 xmlDoc = new DocumentImpl();
336                 root = xmlDoc.createElement( "Project" );
337                 xmlDoc.appendChild( root );
338             }
339 
340             // enumerate over the Project properties and set them as attributes on the Project node
341             Enumeration propertyNames = projectProperties.propertyNames();
342             while ( propertyNames.hasMoreElements() )
343             {
344                 Object propertyNameObject = propertyNames.nextElement();
345                 String name = (String) propertyNameObject;
346                 String value = projectProperties.getProperty( name );
347                 root.setAttribute( name, value );
348             }
349 
350             insertSources( xmlDoc, root, baseDir, theSourceRoots, theWebRoot, existingSourceAttribs, excludedSources );
351             insertConfigurations( xmlDoc, root, theClassPath, theJdkName, existingConfigurationAttribs );
352 
353             // write out the XML
354             XmlWriter writer = new XmlWriter( true );
355             writer.setWriteEmptyValues( false );
356             writer.setDefaultToAttributesOnSameLine( true );
357             writer.saveXmlFile( filePath, xmlDoc );
358         }
359         catch ( Exception ex )
360         {
361             log.error( ex );
362         }
363     }
364 
365     private void insertConfigurations( Document xmlDoc, Element root, String theClassPath, String theJdkName,
366                                        HashMap existingConfigurationAttribs )
367     {
368         // place all of the Configuration properties into a property bundle
369         Properties configProperties = new Properties();
370         String configurationName = "Configuration 1";
371 
372         configProperties.setProperty( "name", configurationName );
373         configProperties.setProperty( "class_path", theClassPath );
374         if ( !StringUtils.isEmpty( theJdkName ) )
375         {
376             configProperties.setProperty( "jdk_name", theJdkName.trim() );
377         }
378 
379         // add the Configuration element to Project. Java Projects always have exactly one Configuration
380         Element configuration = xmlDoc.createElementNS( null, "Configuration" );
381         NamedNodeMap existingConfigAttribs = (NamedNodeMap) existingConfigurationAttribs.get( configurationName );
382 
383         // give the Configuration all its attributes
384         Enumeration propertyNames = configProperties.propertyNames();
385         while ( propertyNames.hasMoreElements() )
386         {
387             Object propertyNameObject = propertyNames.nextElement();
388             String name = (String) propertyNameObject;
389             String value = configProperties.getProperty( name );
390             configuration.setAttributeNS( null, name, value );
391             if ( existingConfigAttribs != null )
392             {
393                 existingConfigAttribs.removeNamedItem( name );
394             }
395         }
396 
397         if ( existingConfigAttribs != null )
398         {
399             for ( int j = 0; j < existingConfigAttribs.getLength(); j++ )
400             {
401                 Node node = existingConfigAttribs.item( j );
402                 String name = node.getNodeName();
403                 String value = node.getNodeValue();
404                 configuration.setAttributeNS( null, name, value );
405             }
406         }
407 
408         NodeList childNodes = root.getChildNodes();
409         boolean hasChildren = childNodes.getLength() > 0;
410         if ( hasChildren )
411         {
412             Node child = childNodes.item( 0 );
413             root.insertBefore( configuration, child );
414         }
415         else
416         {
417             root.appendChild( configuration );
418         }
419     }
420 
421     private void insertSources( Document xmlDoc, Element root, String baseDir, List theSourceRoots, String webRoot,
422                                 HashMap existingSourceAttribs, ArrayList excludedSources )
423     {
424         Collections.sort( theSourceRoots, new Comparator()
425         {
426 
427             public int compare( Object arg0, Object arg1 )
428             {
429                 String root1 = (String) arg0;
430                 String root2 = (String) arg1;
431                 return root2.compareTo( root1 );
432             }
433 
434         } );
435 
436         for ( int i = 0; i < theSourceRoots.size(); i++ )
437         {
438             String sourceRoot = (String) theSourceRoots.get( i );
439 
440             if ( !pathAlreadyInNodeList( excludedSources, sourceRoot ) )
441             {
442                 addSourceElement( xmlDoc, root, sourceRoot, "false", false, existingSourceAttribs );
443             }
444         }
445 
446         // now re-add any excluded sources created in the UI
447         for ( int i = 0; i < excludedSources.size(); i++ )
448         {
449             Node node = (Node) excludedSources.get( i );
450             NamedNodeMap attributes = node.getAttributes();
451             String path = attributes.getNamedItem( "path" ).getNodeValue();
452             if ( new File( baseDir + File.separator + path ).exists() )
453             {
454                 NodeList childNodes = root.getChildNodes();
455                 boolean hasChildren = childNodes.getLength() > 0;
456                 if ( hasChildren )
457                 {
458                     Node child = childNodes.item( 0 );
459                     root.insertBefore( node, child );
460                 }
461                 else
462                 {
463                     root.appendChild( node );
464                 }
465             }
466         }
467 
468         // add web context root if it exists
469         if ( webRoot != null )
470         {
471             addSourceElement( xmlDoc, root, webRoot, "true", true, existingSourceAttribs );
472         }
473     }
474 
475     private void addSourceElement( Document xmlDoc, Element root, String sourceRoot, String defaultWeb,
476                                    boolean forceWeb, HashMap existingSourceAttribs )
477     {
478         Element source = xmlDoc.createElementNS( null, "Source" );
479         NamedNodeMap existingAttribs = (NamedNodeMap) existingSourceAttribs.get( sourceRoot );
480 
481         if ( existingAttribs != null )
482         {
483             existingAttribs.removeNamedItem( "path" );
484         }
485         String fullSourceRoot = sourceRoot;
486         if ( !fullSourceRoot.startsWith( "./" ) )
487         {
488             fullSourceRoot = "./" + sourceRoot;
489         }
490         source.setAttributeNS( null, "path", fullSourceRoot );
491 
492         if ( existingAttribs == null || existingAttribs.getNamedItem( "exclude" ) == null )
493         {
494             source.setAttributeNS( null, "exclude", "false" );
495         }
496         if ( forceWeb )
497         {
498             if ( existingAttribs != null )
499             {
500                 existingAttribs.removeNamedItem( "web" );
501             }
502             source.setAttributeNS( null, "web", defaultWeb );
503 
504         }
505         else if ( existingAttribs == null || existingAttribs.getNamedItem( "web" ) == null )
506         {
507             source.setAttributeNS( null, "web", defaultWeb );
508         }
509 
510         if ( existingAttribs != null )
511         {
512             for ( int j = 0; j < existingAttribs.getLength(); j++ )
513             {
514                 Node node = existingAttribs.item( j );
515                 String name = node.getNodeName();
516                 String value = node.getNodeValue();
517                 source.setAttributeNS( null, name, value );
518             }
519         }
520 
521         NodeList childNodes = root.getChildNodes();
522         boolean hasChildren = childNodes.getLength() > 0;
523         if ( hasChildren )
524         {
525             Node child = childNodes.item( 0 );
526             root.insertBefore( source, child );
527         }
528         else
529         {
530             root.appendChild( source );
531         }
532     }
533 
534     private boolean pathAlreadyInNodeList( ArrayList list, String relPath )
535     {
536         for ( int i = 0; i < list.size(); i++ )
537         {
538             Node node = (Node) list.get( i );
539             NamedNodeMap attributes = node.getAttributes();
540             String path = attributes.getNamedItem( "path" ).getNodeValue();
541             if ( !relPath.startsWith( "./" ) )
542             {
543                 relPath = "./" + relPath;
544             }
545             if ( relPath.equals( path ) )
546             {
547                 return true;
548             }
549         }
550         return false;
551     }
552 
553     public OunceCoreApplication readApplication( String path, Log log )
554         throws OunceCoreException
555     {
556         try
557         {
558             Document xmlDoc;
559             File pafFile = new File( path );
560             if ( pafFile.exists() )
561             {
562                 String parentDir = pafFile.getParent();
563                 String applicationName = null;
564                 String applicationRoot = null;
565                 List projects = new ArrayList();
566                 Map options = new HashMap();
567 
568                 // load up the PAF
569                 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
570                 if ( log != null )
571                 {
572                     log.info( "Reading paf: '" + path + "'..." );
573                 }
574                 xmlDoc = builder.parse( pafFile );
575 
576                 NodeList nodes = xmlDoc.getChildNodes();
577                 for ( int i = 0; i < nodes.getLength(); i++ )
578                 {
579                     Node node = nodes.item( i );
580                     String name = node.getNodeName();
581 
582                     if ( name.equals( "Application" ) )
583                     {
584                         NamedNodeMap applicationAttribs = node.getAttributes();
585                         applicationName = applicationAttribs.getNamedItem( "name" ).getNodeValue();
586 
587                         NodeList applicationChildren = node.getChildNodes();
588                         for ( int j = 0; j < applicationChildren.getLength(); j++ )
589                         {
590                             Node child = applicationChildren.item( j );
591                             String childName = child.getNodeName();
592                             if ( childName.equals( "Project" ) )
593                             {
594                                 String projectPath =
595                                     parentDir + File.separator
596                                         + child.getAttributes().getNamedItem( "path" ).getNodeValue();
597                                 OunceCoreProject project = readProject( projectPath, log );
598                                 projects.add( project );
599                             }
600                         }
601                     }
602                 }
603 
604                 OunceCoreApplication application =
605                     new OunceCoreApplication( applicationName, applicationRoot, projects, options );
606                 return application;
607             }
608         }
609         catch ( Exception ex )
610         {
611             if ( log != null )
612             {
613                 log.error( ex );
614             }
615         }
616 
617         return null;
618     }
619 
620     public OunceCoreProject readProject( String path, Log log )
621         throws OunceCoreException
622     {
623 
624         try
625         {
626             Document xmlDoc;
627             File ppfFile = new File( path );
628             if ( ppfFile.exists() )
629             {
630                 String projectRoot = ppfFile.getParent();
631                 String projectName = null;
632                 String jdkName = null;
633                 String classPath = null;
634                 String webRoot = null;
635                 String optionsStr = null;
636                 List sourceRoots = new ArrayList();
637                 Map options = new HashMap();
638 
639                 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
640                 if ( log != null )
641                 {
642                     log.info( "Reading ppf: '" + path + "'..." );
643                 }
644                 xmlDoc = builder.parse( ppfFile );
645                 NodeList nodes = xmlDoc.getChildNodes();
646                 for ( int i = 0; i < nodes.getLength(); i++ )
647                 {
648                     Node node = nodes.item( i );
649                     String name = node.getNodeName();
650 
651                     // Project should be the only top-level node -- others can be ignored
652                     if ( name.equals( "Project" ) )
653                     {
654                         NamedNodeMap projectAttribs = node.getAttributes();
655                         for ( int j = 0; j < projectAttribs.getLength(); j++ )
656                         {
657                             Node attribNode = projectAttribs.item( j );
658                             String nodeName = attribNode.getNodeName();
659                             String nodeValue = attribNode.getNodeValue();
660                             if ( !nodeName.equals( "name" ) && !nodeName.equals( "web_context_root_path" ) )
661                             {
662                                 options.put( nodeName, nodeValue );
663                             }
664                         }
665 
666                         if ( projectAttribs.getNamedItem( "web_context_root_path" ) != null )
667                         {
668                             webRoot = projectAttribs.getNamedItem( "web_context_root_path" ).getNodeValue();
669                         }
670 
671                         projectName = projectAttribs.getNamedItem( "name" ).getNodeValue();
672                         NodeList projectChildren = node.getChildNodes();
673                         for ( int j = 0; j < projectChildren.getLength(); j++ )
674                         {
675                             Node child = projectChildren.item( j );
676                             String childName = child.getNodeName();
677 
678                             NamedNodeMap attribs = child.getAttributes();
679 
680                             if ( childName.equals( "Configuration" ) )
681                             {
682                                 // attribs have name, jdk_name
683                                 if ( attribs.getNamedItem( "jdk_name" ) != null )
684                                 {
685                                     jdkName = attribs.getNamedItem( "jdk_name" ).getNodeValue();
686                                 }
687                                 if ( attribs.getNamedItem( "class_path" ) != null )
688                                 {
689                                     classPath = attribs.getNamedItem( "class_path" ).getNodeValue();
690                                 }
691                                 if ( attribs.getNamedItem( "compiler_options" ) != null )
692                                 {
693                                     optionsStr = attribs.getNamedItem( "compiler_options" ).getNodeValue();
694                                 }
695                             }
696                             else if ( childName.equals( "Source" ) )
697                             {
698                                 String sourcePath = attribs.getNamedItem( "path" ).getNodeValue();
699                                 String webStr = attribs.getNamedItem( "web" ).getNodeValue();
700                                 // add any non-web roots
701                                 if ( webStr == null || ( webStr != null && !webStr.equals( "true" ) ) )
702                                 {
703                                     sourceRoots.add( sourcePath );
704                                 }
705                             }
706                         }
707                     }
708                 }
709                 String packaging = null;
710                 if ( webRoot != null )
711                 {
712                     packaging = "war";
713                 }
714 
715                 OunceCoreProject project =
716                     new OunceCoreProject( projectName, projectRoot, sourceRoots, webRoot, classPath, jdkName,
717                                           packaging, optionsStr, options );
718                 return project;
719             }
720             else
721             {
722                 throw new OunceCoreException( "The file '" + ppfFile.getPath() + "' does not exist." );
723             }
724         }
725         catch ( Exception ex )
726         {
727             if ( log != null )
728             {
729                 log.error( ex );
730             }
731         }
732 
733         return null;
734     }
735 
736     public void scan( String applicationFile, String assessmentName, String assessmentOutput, String caller,
737                       String reportType, String reportOutputType, String reportOutputLocation, boolean publish,
738                       Map ounceOptions, String installDir, boolean wait, Log log )
739         throws OunceCoreException
740     {
741 
742         String command;
743         if ( installDir == null )
744         {
745             // just assume it's on the path
746             command = "ounceauto";
747         }
748         else
749         {
750             command = installDir + File.separator + "bin" + File.separator + "ounceauto";
751         }
752 
753         String existingAssessment = null;
754         int includeSrcBefore = -1;
755         int includeSrcAfter = -1;
756 
757         if ( ounceOptions != null )
758         {
759             if ( ounceOptions.get( "existingAssessmentFile" ) != null )
760             {
761                 existingAssessment = (String) ounceOptions.get( "existingAssessmentFile" );
762             }
763             if ( ounceOptions.get( "includeSrcBefore" ) != null )
764             {
765                 includeSrcBefore = ( (Integer) ounceOptions.get( "includeSrcBefore" ) ).intValue();
766             }
767             if ( ounceOptions.get( "includeSrcAfter" ) != null )
768             {
769                 includeSrcAfter = ( (Integer) ounceOptions.get( "includeSrcAfter" ) ).intValue();
770             }
771         }
772 
773         try
774         {
775             if ( existingAssessment == null )
776             {
777                 command += " scanapplication";
778                 if ( !StringUtils.isEmpty( applicationFile ) )
779                 {
780                     command += " -application_file \"" + applicationFile + "\"";
781                 }
782                 if ( !StringUtils.isEmpty( assessmentName ) )
783                 {
784                     command += " -name \"" + assessmentName + "\"";
785                 }
786                 if ( !StringUtils.isEmpty( assessmentOutput ) )
787                 {
788                     command += " -save \"" + assessmentOutput + "\"";
789                 }
790                 if ( !StringUtils.isEmpty( reportType ) )
791                 {
792                     command +=
793                         " -report \"" + reportType + "\" \"" + reportOutputType + "\" " + "\"" + reportOutputLocation
794                             + "\"";
795                 }
796                 if ( publish )
797                 {
798                     command += " -publish";
799                 }
800             }
801             else
802             {
803                 // just generate a report for an existing saved assessment
804                 command += " generatereport -assessment \"" + existingAssessment + "\"";
805                 if ( !StringUtils.isEmpty( reportType ) )
806                 {
807                     command +=
808                         " -type \"" + reportType + "\" -output \"" + reportOutputType + "\" -file \""
809                             + reportOutputLocation + "\"";
810                 }
811             }
812             if ( !StringUtils.isEmpty( caller ) )
813             {
814                 command += " -caller \"" + caller + "\"";
815             }
816             if ( includeSrcBefore != -1 )
817             {
818                 command += " -includeSrcBefore " + includeSrcBefore;
819             }
820             if ( includeSrcAfter != -1 )
821             {
822                 command += " -includeSrcAfter " + includeSrcAfter;
823             }
824 
825             System.out.println( command );
826 
827             int requestId = executeCommand( command, log );
828 
829             System.out.println( "requestId: " + requestId );
830             if ( wait )
831             {
832                 if ( installDir == null )
833                 {
834                     // just assume it's on the path
835                     command = "ounceauto";
836                 }
837                 else
838                 {
839                     command = installDir + File.separator + "bin" + File.separator + "ounceauto";
840                 }
841                 command += " wait -requestid " + requestId;
842                 System.out.println( command );
843                 executeCommand( command, log );
844             }
845         }
846         catch ( Exception ex )
847         {
848             throw new OunceCoreException( ex );
849         }
850     }
851 
852     public void createPathVariables( Map pathVariableMap, String installDir, Log log )
853         throws OunceCoreException
854     {
855         String command;
856         if ( installDir == null )
857         {
858             // just assume it's on the path
859             command = "ounceauto";
860         }
861         else
862         {
863             command = installDir + File.separator + "bin" + File.separator + "ounceauto";
864         }
865 
866         try
867         {
868             command += " setvars";
869             if ( pathVariableMap != null )
870             {
871                 Set keys = pathVariableMap.keySet();
872                 Iterator it = keys.iterator();
873                 while ( it.hasNext() )
874                 {
875                     String key = (String) it.next();
876                     String value = (String) pathVariableMap.get( key );
877 
878                     // TODO: need to put quotes around the key and value
879                     command += " -" + key + " " + value;
880                 }
881                 System.out.println( command );
882                 executeCommand( command, log );
883             }
884         }
885         catch ( Exception ex )
886         {
887             // drop this problem on the floor, it is not an issue to fail the build
888         }
889     }
890 
891     private int executeCommand( String command, Log log )
892         throws IOException, InterruptedException
893     {
894         Process p = Runtime.getRuntime().exec( command );
895         BufferedReader input = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
896         String line;
897         while ( ( line = input.readLine() ) != null )
898         {
899             if ( log != null )
900             {
901                 log.info( "ounceauto: " + line );
902             }
903             else
904             {
905                 System.out.println( "ounceauto: " + line );
906             }
907         }
908 
909         input.close();
910         return p.waitFor();
911     }
912 }