1 18 package org.apache.beehive.netui.compiler.genmodel; 19 20 import org.apache.beehive.netui.compiler.CompilerUtils; 21 import org.apache.beehive.netui.compiler.FlowControllerInfo; 22 import org.apache.beehive.netui.compiler.JpfLanguageConstants; 23 import org.apache.beehive.netui.compiler.MergedControllerAnnotation; 24 import org.apache.beehive.netui.compiler.Diagnostics; 25 import org.apache.beehive.netui.compiler.FatalCompileTimeException; 26 import org.apache.beehive.netui.compiler.model.ActionModel; 27 import org.apache.beehive.netui.compiler.model.FormBeanModel; 28 import org.apache.beehive.netui.compiler.model.ForwardModel; 29 import org.apache.beehive.netui.compiler.model.MessageResourcesModel; 30 import org.apache.beehive.netui.compiler.model.StrutsApp; 31 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationInstance; 32 import org.apache.beehive.netui.compiler.typesystem.declaration.ClassDeclaration; 33 import org.apache.beehive.netui.compiler.typesystem.declaration.MethodDeclaration; 34 import org.apache.beehive.netui.compiler.typesystem.declaration.Modifier; 35 import org.apache.beehive.netui.compiler.typesystem.declaration.PackageDeclaration; 36 import org.apache.beehive.netui.compiler.typesystem.declaration.ParameterDeclaration; 37 import org.apache.beehive.netui.compiler.typesystem.declaration.TypeDeclaration; 38 import org.apache.beehive.netui.compiler.typesystem.env.AnnotationProcessorEnvironment; 39 import org.apache.beehive.netui.compiler.typesystem.type.DeclaredType; 40 import org.apache.beehive.netui.compiler.typesystem.type.TypeInstance; 41 import org.apache.beehive.netui.compiler.typesystem.type.ClassType; 42 import org.apache.xmlbeans.XmlCursor; 43 import org.apache.xmlbeans.XmlException; 44 import org.apache.xmlbeans.XmlObject; 45 46 import java.io.File ; 47 import java.io.FileNotFoundException ; 48 import java.io.FileOutputStream ; 49 import java.io.IOException ; 50 import java.io.PrintStream ; 51 import java.util.ArrayList ; 52 import java.util.Collection ; 53 import java.util.Date ; 54 import java.util.Iterator ; 55 import java.util.List ; 56 57 58 public class GenStrutsApp 59 extends StrutsApp 60 implements JpfLanguageConstants 61 { 62 private ClassDeclaration _jclass; 63 private String _containingPackage; 64 private File _strutsConfigFile; 65 private File _sourceFile; 66 private AnnotationProcessorEnvironment _env; 67 private FlowControllerInfo _fcInfo; 68 private Diagnostics _diagnostics; 69 70 protected void recalculateStrutsConfigFile() 71 throws XmlException, IOException , FatalCompileTimeException 72 { 73 _strutsConfigFile = calculateStrutsConfigFile(); } 75 76 FlowControllerInfo getFlowControllerInfo() 77 { 78 return _fcInfo; 79 } 80 81 public GenStrutsApp( File sourceFile, ClassDeclaration jclass, AnnotationProcessorEnvironment env, 82 FlowControllerInfo fcInfo, boolean checkOnly, Diagnostics diagnostics ) 83 throws XmlException, IOException , FatalCompileTimeException 84 { 85 super( jclass.getQualifiedName() ); 86 87 _jclass = jclass; 88 _containingPackage = jclass.getPackage().getQualifiedName(); 89 _sourceFile = sourceFile; 90 _env = env; 91 assert fcInfo != null; 92 _fcInfo = fcInfo; 93 _diagnostics = diagnostics; 94 95 recalculateStrutsConfigFile(); 96 97 if ( checkOnly ) return; 98 99 if ( _jclass != null ) 100 { 101 MergedControllerAnnotation mca = fcInfo.getMergedControllerAnnotation(); 102 setNestedPageFlow( mca.isNested() ); 103 setLongLivedPageFlow( mca.isLongLived() ); 104 addMessageResources( mca.getMessageResources() ); addMessageBundles( mca.getMessageBundles() ); addSimpleActions( mca.getSimpleActions() ); 107 setMultipartHandler( mca.getMultipartHandler() ); 108 GenForwardModel.addForwards( mca.getForwards(), this, _jclass, this, null ); 109 110 addForward( new ForwardModel( "_auto", "", this ) ); 112 113 GenExceptionModel.addCatches( mca.getCatches(), this, _jclass, this, this ); 114 addTilesDefinitionsConfigs( mca.getTilesDefinitionsConfigs() ); 115 setAdditionalValidatorConfigs( mca.getCustomValidatorConfigs() ); 116 117 addActionMethods(); 118 addFormBeans( _jclass ); 119 } 120 121 if ( fcInfo != null ) 122 { 123 setSharedFlows( fcInfo.getSharedFlowTypeNames() ); 124 setReturnToActionDisabled( ! fcInfo.isNavigateToActionEnabled() ); 125 setReturnToPageDisabled( ! fcInfo.isNavigateToPageEnabled() ); 126 } 127 } 128 129 private void addFormBeans( ClassDeclaration jclass ) 130 { 131 Collection innerTypes = CompilerUtils.getClassNestedTypes( jclass ); 132 133 for ( Iterator ii = innerTypes.iterator(); ii.hasNext(); ) 134 { 135 TypeDeclaration innerType = ( TypeDeclaration ) ii.next(); 136 if ( innerType instanceof ClassDeclaration ) 137 { 138 ClassDeclaration innerClass = ( ClassDeclaration ) innerType; 139 140 if ( innerType.hasModifier( Modifier.PUBLIC ) 141 && CompilerUtils.isAssignableFrom( PAGEFLOW_FORM_CLASS_NAME, innerClass, _env ) ) 142 { 143 addFormBean( innerClass, null ); 144 } 145 } 146 } 147 148 } 149 150 String addFormBean( TypeDeclaration formType, ActionModel usedByAction ) 151 { 152 String formClass = CompilerUtils.getFormClassName( formType, _env ); 153 154 String actualType = CompilerUtils.getLoadableName( formType ); 160 161 boolean usesPageFlowScopedFormBean = usedByAction != null ? usedByAction.getFormMember() != null : false; 166 List existingBeans = getFormBeansByActualType( actualType, Boolean.valueOf( usesPageFlowScopedFormBean ) ); 167 String formBeanName; 168 169 if ( existingBeans != null ) 170 { 171 assert existingBeans.size() > 0; 172 formBeanName = ( ( FormBeanModel ) existingBeans.get( 0 ) ).getName(); 173 } 174 else 175 { 176 formBeanName = getFormNameForType( actualType, usesPageFlowScopedFormBean ); 177 addFormBean( new FormBeanModel( formBeanName, formClass, actualType, usesPageFlowScopedFormBean, this ) ); 178 getMessageResourcesFromForm( formType, usedByAction ); 179 } 180 181 return formBeanName; 182 } 183 184 private void addMessageResources( Collection messageResources ) 185 { 186 if ( messageResources != null ) 187 { 188 for ( Iterator ii = messageResources.iterator(); ii.hasNext(); ) 189 { 190 AnnotationInstance ann = ( AnnotationInstance ) ii.next(); 191 addMessageResources( new GenMessageBundleModel( this, ann ) ); 192 } 193 } 194 } 195 196 private void addMessageBundles( Collection messageBundles ) 197 { 198 if ( messageBundles != null ) 199 { 200 for ( Iterator ii = messageBundles.iterator(); ii.hasNext(); ) 201 { 202 AnnotationInstance ann = ( AnnotationInstance ) ii.next(); 203 addMessageResources( new GenMessageBundleModel( this, ann ) ); 204 } 205 } 206 } 207 208 private void addSimpleActions( Collection simpleActionAnnotations ) 209 { 210 if ( simpleActionAnnotations != null ) 211 { 212 for ( Iterator ii = simpleActionAnnotations.iterator(); ii.hasNext(); ) 213 { 214 AnnotationInstance ann = ( AnnotationInstance ) ii.next(); 215 addActionMapping( new GenSimpleActionModel( ann, this, _jclass ) ); 216 } 217 } 218 } 219 220 private void setMultipartHandler( String mpHandler ) 221 { 222 if ( mpHandler != null ) 223 { 224 if ( mpHandler.equals( MULTIPART_HANDLER_MEMORY_STR ) ) 225 { 226 setMultipartHandlerClassName( MULTIPART_HANDLER_MEMORY_CLASSNAME ); 227 } 228 else if ( mpHandler.equals( MULTIPART_HANDLER_DISK_STR ) ) 229 { 230 setMultipartHandlerClassName( MULTIPART_HANDLER_DISK_CLASSNAME ); 231 } 232 else 233 { 234 assert mpHandler.equals( MULTIPART_HANDLER_DISABLED_STR ); 235 setMultipartHandlerClassName( "none" ); 236 } 237 } 238 } 239 240 private void addTilesDefinitionsConfigs( List tilesDefinitionsConfigs ) 241 { 242 if ( tilesDefinitionsConfigs == null || tilesDefinitionsConfigs.isEmpty() ) 243 { 244 return; 245 } 246 247 List paths = new ArrayList (); 248 249 for ( Iterator ii = tilesDefinitionsConfigs.iterator(); ii.hasNext(); ) 250 { 251 String definitionsConfig = ( String ) ii.next(); 252 253 if ( definitionsConfig != null && definitionsConfig.length() > 0 ) 254 { 255 paths.add( definitionsConfig ); 256 } 257 } 258 259 setTilesDefinitionsConfigs( paths ); 260 } 261 262 private void addActionMethods() 263 { 264 MethodDeclaration[] actionMethods = CompilerUtils.getClassMethods( _jclass, ACTION_TAG_NAME ); 265 266 for ( int i = 0; i < actionMethods.length; i++ ) 267 { 268 MethodDeclaration actionMethod = actionMethods[i]; 269 270 if ( ! actionMethod.hasModifier( Modifier.ABSTRACT ) ) 271 { 272 ActionModel actionModel = new GenActionModel( actionMethod, this, _jclass ); 273 addActionMapping( actionModel ); 274 ParameterDeclaration[] params = actionMethod.getParameters(); 275 276 if ( params.length > 0 ) 277 { 278 ParameterDeclaration param1 = params[0]; 279 TypeInstance paramType = param1.getType(); 280 281 if ( paramType instanceof DeclaredType ) 282 { 283 getMessageResourcesFromForm( CompilerUtils.getDeclaration( ( DeclaredType ) paramType ), actionModel ); 284 } 285 } 286 } 287 } 288 } 289 290 private void getMessageResourcesFromForm( TypeDeclaration formTypeDecl, ActionModel actionModel ) 291 { 292 if ( ! ( formTypeDecl instanceof ClassDeclaration ) ) return; 293 294 ClassDeclaration formClassDecl = ( ClassDeclaration ) formTypeDecl; 295 296 while ( true ) 297 { 298 AnnotationInstance ann = CompilerUtils.getAnnotation( formClassDecl, FORM_BEAN_TAG_NAME ); 299 300 if ( ann != null ) 301 { 302 String defaultMessageResources = CompilerUtils.getString( ann, MESSAGE_BUNDLE_ATTR, true ); 303 304 if ( defaultMessageResources != null ) 305 { 306 for ( Iterator ii = getMessageResourcesList().iterator(); ii.hasNext(); ) 307 { 308 MessageResourcesModel i = ( MessageResourcesModel ) ii.next(); 309 if ( i.getParameter().equals( defaultMessageResources ) ) return; 310 } 311 312 MessageResourcesModel mrm = new MessageResourcesModel( this ); 313 String key = "formMessages:" + CompilerUtils.getLoadableName( formClassDecl ); 314 mrm.setKey( key ); 315 mrm.setParameter( defaultMessageResources ); 316 mrm.setReturnNull( true ); 317 addMessageResources( mrm ); 318 if ( actionModel != null ) actionModel.setFormBeanMessageResourcesKey( key ); 319 } 320 } 321 322 ClassType superType = formClassDecl.getSuperclass(); 323 if ( superType == null ) break; 324 formClassDecl = superType.getClassTypeDeclaration(); 325 } 326 } 327 328 protected String getMergeFileName() 329 { 330 return getFlowControllerInfo().getMergedControllerAnnotation().getStrutsMerge(); 331 } 332 333 public void writeToFile() 334 throws FileNotFoundException , IOException , XmlException, FatalCompileTimeException 335 { 336 writeToFile( getMergeFile( getMergeFileName() ) ); 337 } 338 339 public boolean isStale() 340 throws FatalCompileTimeException 341 { 342 return isStale( getMergeFile( getMergeFileName() ) ); 343 } 344 345 protected boolean isModuleDeclaredInWebXml() 346 { 347 PackageDeclaration pkg = _jclass.getPackage(); 349 return ! isSharedFlow() && pkg == null || pkg.getQualifiedName().length() == 0; 350 } 351 352 String getOutputFileURI( String filePrefix ) 353 { 354 return getOutputFileURI( filePrefix, _containingPackage, false ); 355 } 356 357 String getStrutsConfigURI() 358 { 359 return getStrutsConfigURI( _containingPackage, false ); 360 } 361 362 protected String getContainingPackage() 363 { 364 return _containingPackage; 365 } 366 367 private File calculateStrutsConfigFile() 368 throws XmlException, IOException , FatalCompileTimeException 369 { 370 String webappBuildRoot = CompilerUtils.getWebBuildRoot( getEnv() ); 371 File strutsConfigFile = new File ( webappBuildRoot + getStrutsConfigURI() ); 372 373 if ( isModuleDeclaredInWebXml() ) 378 { 379 String alternateLocation = getAlternateLocation( strutsConfigFile ); 380 if ( alternateLocation != null ) return new File ( webappBuildRoot + alternateLocation ); 381 } 382 383 return strutsConfigFile; 384 } 385 386 390 public boolean isStale( File mergeFile ) 391 { 392 if ( isModuleDeclaredInWebXml() ) 398 { 399 return true; 400 } 401 402 if ( ! _strutsConfigFile.exists() ) 406 { 407 return true; 408 } 409 410 long lastWrite = _strutsConfigFile.lastModified(); 411 412 if ( mergeFile != null && mergeFile.exists() && mergeFile.lastModified() > lastWrite ) 413 { 414 return true; 415 } 416 417 if ( _sourceFile.lastModified() > lastWrite ) 418 { 419 return true; 420 } 421 422 return false; 423 } 424 429 public boolean canWrite() 430 { 431 if ( ! _strutsConfigFile.canWrite() ) 432 { 433 return false; 434 } 435 436 try 437 { 438 new FileOutputStream ( _strutsConfigFile, true ).close(); 444 } 445 catch ( FileNotFoundException e ) 446 { 447 return false; 448 } 449 catch ( IOException e ) 450 { 451 return false; 452 } 453 454 return true; 455 } 456 457 458 public void writeToFile( File strutsMergeFile ) 459 throws FileNotFoundException , IOException , XmlException, FatalCompileTimeException 460 { 461 _strutsConfigFile.getParentFile().mkdirs(); 462 PrintStream out = new PrintStream ( new FileOutputStream ( _strutsConfigFile ) ); 463 writeXml( out, strutsMergeFile, CompilerUtils.getWebBuildRoot( getEnv() ) ); 464 out.close(); 465 } 466 467 public File getStrutsConfigFile() 468 { 469 return _strutsConfigFile; 470 } 471 472 private static boolean isAtElement( XmlCursor curs, String localName ) 473 { 474 return curs.getName().getLocalPart().equals( localName ); 475 } 476 477 482 private String getAlternateLocation( File strutsConfigFile ) 483 throws XmlException, IOException , FatalCompileTimeException 484 { 485 String webappContentRoot = CompilerUtils.getWebContentRoot( getEnv() ); 486 File webXmlFile = new File ( webappContentRoot + '/' + StrutsApp.WEBINF_DIR_NAME + "/web.xml" ); 487 488 if ( ! webXmlFile.canRead() ) 489 { 490 _diagnostics.addWarning( _jclass, "warning.could-not-read-web-xml", webappContentRoot ); 491 return null; 492 } 493 494 String strutsConfigFileName = strutsConfigFile.getName(); 495 496 XmlObject webXmlDoc = XmlObject.Factory.parse( webXmlFile ); 511 XmlCursor curs = webXmlDoc.newCursor(); 512 if ( curs.toFirstChild() && curs.toFirstChild() ) 513 { 514 do 515 { 516 if ( isAtElement( curs, "servlet" ) ) 517 { 518 XmlCursor i = curs.newCursor(); 519 i.toFirstChild(); 520 do 521 { 522 if ( isAtElement( i, "servlet-name" ) && i.getTextValue().equals( "action" ) ) 523 { 524 XmlCursor j = curs.newCursor(); 525 j.toFirstChild(); 526 527 do 528 { 529 if ( isAtElement( j, "init-param" ) ) 530 { 531 XmlCursor k = j.newCursor(); 532 k.toFirstChild(); 533 boolean isConfig = false; 534 String alternateLocation = null; 535 536 do 537 { 538 if ( isAtElement( k, "param-name" ) && k.getTextValue().startsWith( "config" ) ) 539 { 540 isConfig = true; 541 } 542 else if ( isAtElement( k, "param-value" ) ) 543 { 544 alternateLocation = 545 parseAlternateLocation( k.getTextValue(), strutsConfigFileName ); 546 } 547 } while ( k.toNextSibling() ); 548 549 if ( isConfig && alternateLocation != null ) 550 { 551 return alternateLocation; 552 } 553 } 554 } while ( j.toNextSibling() ); 555 556 return null; 561 } 562 } while ( i.toNextSibling() ); 563 } 564 } while ( curs.toNextSibling() ); 565 } 566 567 return null; 568 } 569 570 private static String parseAlternateLocation( String paramValue, String strutsConfigFileName ) 571 { 572 if ( paramValue.indexOf( strutsConfigFileName ) != -1 ) 578 { 579 if ( paramValue.indexOf( "," ) != -1 ) 583 { 584 String [] files = paramValue.split( "," ); 585 for ( int k = 0; k < files.length; ++k ) 586 { 587 if ( files[k].indexOf( strutsConfigFileName ) != -1 ) 588 { 589 return files[k].trim(); 590 } 591 } 592 } 593 else 594 { 595 return paramValue; 596 } 597 } 598 599 return null; 600 } 601 602 public File getMergeFile( String mergeFileName ) 603 throws FatalCompileTimeException 604 { 605 if ( mergeFileName != null ) 606 { 607 return CompilerUtils.getFileRelativeToSourceFile( _jclass, mergeFileName, getEnv() ); 608 } 609 610 return null; 611 } 612 613 protected String getHeaderComment( File mergeFile ) 614 throws FatalCompileTimeException 615 { 616 StringBuffer comment = new StringBuffer ( " Generated from " ); 617 comment.append( getWebappRelativePath( _sourceFile ) ); 618 if ( mergeFile != null ) 619 { 620 comment.append( " and " ).append( getWebappRelativePath( mergeFile ) ); 621 } 622 comment.append( " on " ).append( new Date ().toString() ).append( ' ' ); 623 return comment.toString(); 624 } 625 626 private String getWebappRelativePath( File file ) 627 throws FatalCompileTimeException 628 { 629 String filePath = file.getAbsoluteFile().getPath(); 630 String [] sourceRoots = CompilerUtils.getWebSourceRoots( _env ); 631 632 for ( int i = 0; i < sourceRoots.length; i++ ) 636 { 637 String sourceRoot = sourceRoots[i]; 638 639 if ( filePath.startsWith( sourceRoot ) ) 640 { 641 return file.toString().substring( sourceRoot.length() ).replace( '\\', '/' ); 642 } 643 } 644 645 String webContentRoot = CompilerUtils.getWebContentRoot( getEnv() ); 649 650 if ( filePath.startsWith( webContentRoot ) ) 651 { 652 return file.toString().substring( webContentRoot.length() ).replace( '\\', '/' ); 653 } 654 655 assert false : "could not calculate webapp-relative file from " + file; 656 return file.toString(); 657 } 658 659 AnnotationProcessorEnvironment getEnv() 660 { 661 return _env; 662 } 663 } 664 | Popular Tags |