/*
* Name: GenericController
* Authors: Richard Rodger
*
* Copyright (c) 2004-2006 Richard Rodger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
// package
package org.jostraca.process;
// import
import org.jostraca.Property;
import org.jostraca.Template;
import org.jostraca.UserText;
import org.jostraca.Constants;
import org.jostraca.util.Standard;
import org.jostraca.util.StandardException;
import org.jostraca.util.PropertySet;
import org.jostraca.util.TextUtil;
import org.jostraca.util.ArgUtil;
import org.jostraca.util.ErrorUtil;
import org.jostraca.util.BuildResource;
import org.jostraca.util.FileBuildResource;
import org.jostraca.util.RootBuildResource;
import org.jostraca.util.BasicWayPoint;
import org.jostraca.util.WayPointRecorder;
import org.jostraca.util.CommandRunner;
import org.jostraca.util.RegExp;
import org.jostraca.util.RegExpMatch;
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;
import java.util.HashMap;
import java.io.File;
import java.io.StringWriter;
/** Processing class for executing <code>CodeWriters</code> externally.
*/
public class GenericController extends TemplateHandlerSupport {
public GenericController() {
// do nothing
}
public void process( Template pTemplate ) {
Template template = pTemplate;
PropertySet tmps = template.getMergedPropertySet();
// FIX: need to elaborate on this!
boolean execute = !tmps.isNo( Property.main_ExecuteCodeWriter );
if( execute ) {
super.process( pTemplate );
PropertySet ps = pTemplate.getPropertySet( Constants.CONF_override );
List sf = pTemplate.getSavedFiles();
ps.set( Property.jostraca_GeneratedFiles, TextUtil.array2text( sf.toArray(new String[sf.size()]), Standard.COMMA ) );
recordBuildResources( pTemplate );
MetaUtil.saveMetaData( pTemplate );
}
}
protected void processImpl( Template pTemplate ) {
Template template = pTemplate;
PropertySet tmps = template.getMergedPropertySet();
File codeWriterPath = template.getCodeWriterPath();
String codeWriterSource = template.getCodeWriterSource();
try {
String externalController = makeExternalController( tmps );
String externalControllerOptions = tmps.get( Property.main_ExternalControllerOptions );
String absoluteCodeWriterPath = TextUtil.quote(getCodeWriterPath( tmps ));
String codeWriterOptions = makeCodeWriterOptions( tmps, template );
// FIX: why use absolute controller path since compile does not?
String cmd = Standard.EMPTY;
boolean cwic = tmps.isYes( Property.main_CodeWriterIsController );
cmd += ( externalController + Standard.SPACE + externalControllerOptions + Standard.SPACE );
if( !cwic ) {
cmd += absoluteCodeWriterPath;
}
cmd += Standard.SPACE + codeWriterOptions;
boolean successful = executeGeneratingCmd( cmd, template );
WayPointRecorder.add( BasicWayPoint.ExecutingCodeWriter.make( template.getCodeWriterPath().getAbsolutePath() ) );
}
catch( StandardException se ) {
throw se;
}
catch( Exception e ) {
// FIX: needs more info
throw new ProcessException( e );
}
}
protected void completeImpl( List pTemplateList ) {
// do nothing
}
public String getCodeWriterPath( PropertySet pPropertySet ) {
String fullCodeWriter
= pPropertySet.get( Property.main_CodeWriterPrefix )
+ pPropertySet.get( Property.main_CodeWriter )
+ pPropertySet.get( Property.main_CodeWriterSuffix );
String workFolder = pPropertySet.get(Property.main_WorkFolder);
File cwp = new File(workFolder,fullCodeWriter);
// DO NOT QUOTE - code writer path may not be sent to shell, e.g InternalJavaController
return cwp.toString();
}
protected String makeExternalController( PropertySet pPropertySet ) {
String externalController = pPropertySet.get( Property.main_ExternalController );
externalController = TextUtil.quote( externalController );
return externalController;
}
protected String makeCodeWriterOptions( PropertySet pPropertySet, Template pTemplate ) {
String cwo = Standard.SPACE;
// set output folder if necessary
if( pPropertySet.isDefined( Property.main_OutputFolder ) ) {
cwo += TextUtil.quote( ARG_ControlPrefix
+ "o="
+ pPropertySet.get( Property.main_OutputFolder ).replace('\\','/') );
cwo += Standard.SPACE;
}
if( pPropertySet.isYes( Property.main_EnableMeta )
&& pTemplate.hasMetaFile() )
{
cwo
+= TextUtil.quote( ARG_ControlPrefix
+ "p="
+ makeMetaPath( pTemplate, pPropertySet ) );
cwo += Standard.SPACE;
}
// set backup status
if( pPropertySet.isNo( Property.main_MakeBackup ) ) {
cwo += TextUtil.quote( ARG_ControlPrefix
+ "B" );
cwo += Standard.SPACE;
}
// set backup folder otherwise
else if( pPropertySet.isDefined( Property.main_BackupFolder ) ) {
cwo += TextUtil.quote( ARG_ControlPrefix
+ "b="
+ pPropertySet.get( Property.main_BackupFolder ).replace('\\','/') );
cwo += Standard.SPACE;
}
cwo += pPropertySet.get( Property.main_CodeWriterOptions );
//t.track( "CodeWriterOptions", cwo );
return cwo;
}
/** Execute the code writer using Threads. */
protected boolean executeGeneratingCmd( String pCmd, Template pTemplate ) throws Exception {
String[] cmd = ArgUtil.splitQuoted( pCmd );
// FIX: control always quote param with a property?
String cmdstr = TextUtil.array2text( TextUtil.quoteCmdArgs( cmd, false ) );
iUserMessageHandler.debug( UserText.get(UserText.TXT_generating), cmdstr );
if( quoteAllArgs() ) {
cmd = TextUtil.quoteAll( cmd );
}
StringWriter out = new StringWriter();
StringWriter err = new StringWriter();
CommandRunner.exec( cmd, out, err );
String outResult = out.toString();
if( null != outResult && 0 < outResult.trim().length() ) {
parseOutResult( outResult, pTemplate );
iUserMessageHandler.info( outResult );
}
String errResult = err.toString();
if( null != errResult && 0 < errResult.trim().length() ) {
iUserMessageHandler.error( errResult );
}
return true;
}
protected void parseOutResult( String pOutResult, Template pTemplate ) {
Vector savedFilesV = new Vector();
try {
RegExp savedFileRE = RegExp.make( "Saved\\s+file:\\s*(.*?)\r?\n" );
RegExpMatch[] mA = savedFileRE.matchAll( pOutResult );
int numM = mA.length;
for( int mI = 0; mI < numM; mI++ ) {
RegExpMatch m = mA[mI];
String savedFile = m.matchSub(1);
savedFilesV.addElement( savedFile );
}
}
catch( Exception e ) {
ErrorUtil.nonFatalMsg( e.getMessage() );
}
pTemplate.setSavedFiles( savedFilesV );
}
protected String makeMetaPath( Template pTemplate, PropertySet pPropertySet ) {
String mp = ( pPropertySet.isYes( Property.main_FullMetaPath )
? pTemplate.getMetaFile().getAbsolutePath() : pTemplate.getMetaFile().toString() ).replace('\\','/');
return mp;
}
protected boolean quoteAllArgs() {
return false;
}
private void recordBuildResources( Template pTemplate ) {
try {
RootBuildResource rbr = (RootBuildResource) pTemplate.getBuildResource();
//t.track( "recordBuildResources.PrefixOperatorFiles", pPropertySet.get( Property.jostraca_PrefixOperatorFiles ) );
PropertySet ps = pTemplate.getMergedPropertySet();
// handle PrefixOperatorPSM files
String[] psmfiles = ps.getList( Property.jostraca_PrefixOperatorFiles, Standard.COMMA );
int numPF = psmfiles.length;
String[] genfiles = ps.getList( Property.jostraca_GeneratedFiles, Standard.COMMA );
int numGF = genfiles.length;
for( int pfI = 0; pfI < numPF; pfI++ ) {
for( int gfI = 0; gfI < numGF; gfI++ ) {
FileBuildResource fbr = new FileBuildResource( new File( psmfiles[pfI] ), new File( genfiles[gfI] ) );
rbr.add( fbr );
}
}
recordBuildResources( pTemplate, rbr, new HashMap() );
//t.track( "recordBuildResources.FileBuildResources", pPropertySet.get( Property.jostraca_FileBuildResources ) );
}
catch( Exception e ) {
ErrorUtil.nonFatalMsg( e.getMessage() );
}
}
private void recordBuildResources( Template pTemplate, RootBuildResource pRootBuildResource, HashMap pPreviouslySeen ) {
try {
ArrayList brL = pRootBuildResource.list();
int numBR = brL.size();
for( int brI = 0; brI < numBR; brI++ ) {
BuildResource br = (BuildResource) brL.get( brI );
if( br instanceof RootBuildResource ) {
recordBuildResources( pTemplate, (RootBuildResource)br, pPreviouslySeen );
}
else if( br instanceof FileBuildResource ) {
PropertySet ps = pTemplate.getMergedPropertySet();
FileBuildResource fbr = (FileBuildResource) br;
String existing_fbr = ps.get( Property.jostraca_FileBuildResources );
String file = fbr.getEarlier().getAbsolutePath();
if( !pPreviouslySeen.containsKey( file ) ) {
PropertySet ops = pTemplate.getPropertySet( Constants.CONF_override );
ops.set( Property.jostraca_FileBuildResources,
existing_fbr + (Standard.EMPTY.equals(existing_fbr) ? Standard.EMPTY : Standard.COMMA) + file );
pPreviouslySeen.put( file, file );
}
}
}
}
catch( Exception e ) {
ErrorUtil.nonFatalException( e );
}
}
}