2929import com .microsoft .azure .toolkit .lib .legacy .function .handlers .CommandHandlerImpl ;
3030import com .microsoft .azure .toolkit .lib .legacy .function .handlers .FunctionCoreToolsHandler ;
3131import com .microsoft .azure .toolkit .lib .legacy .function .handlers .FunctionCoreToolsHandlerImpl ;
32+
3233import lombok .extern .slf4j .Slf4j ;
3334import org .apache .commons .collections4 .SetUtils ;
3435import org .apache .commons .io .FileUtils ;
6162import java .net .URL ;
6263import java .nio .charset .Charset ;
6364import java .nio .file .Paths ;
65+ import java .text .MessageFormat ;
6466import java .util .ArrayList ;
6567import java .util .Arrays ;
6668import java .util .Collections ;
@@ -95,6 +97,7 @@ public class PackageMojo extends AbstractFunctionMojo {
9597 public static final String SAVE_FUNCTION_JSON = "Starting processing function: " ;
9698 public static final String SAVE_SUCCESS = "Successfully saved to " ;
9799 public static final String COPY_JARS = "Step 7 of 8: Copying JARs to staging directory " ;
100+ public static final String COPY_BINARY = "Step 7 of 8: Copying Binary to staging directory " ;
98101 public static final String COPY_SUCCESS = "Copied successfully." ;
99102 public static final String INSTALL_EXTENSIONS = "Step 8 of 8: Installing function extensions if needed" ;
100103 public static final String SKIP_INSTALL_EXTENSIONS_HTTP = "Skip install Function extension for HTTP Trigger Functions" ;
@@ -104,10 +107,12 @@ public class PackageMojo extends AbstractFunctionMojo {
104107 public static final String FUNCTION_JSON = "function.json" ;
105108 public static final String EXTENSION_BUNDLE = "extensionBundle" ;
106109 private static final String AZURE_FUNCTIONS_JAVA_CORE_LIBRARY = "azure-functions-java-core-library" ;
107- private static final String DEFAULT_LOCAL_SETTINGS_JSON = "{ \" IsEncrypted\" : false, \" Values\" : " +
108- "{ \" FUNCTIONS_WORKER_RUNTIME\" : \" java \" } } " ;
110+ private static final String DEFAULT_LOCAL_SETTINGS_JSON = "'{' \" IsEncrypted\" : false, \" Values\" : " +
111+ "'{' \" FUNCTIONS_WORKER_RUNTIME\" : \" {0} \" '}' '}' " ;
109112 private static final String DEFAULT_HOST_JSON = "{\" version\" :\" 2.0\" ,\" extensionBundle\" :" +
110113 "{\" id\" :\" Microsoft.Azure.Functions.ExtensionBundle\" ,\" version\" :\" [4.*, 5.0.0)\" }}\n " ;
114+ private static final String DEFAULT_CUSTOM_HOST_JSON = "'{'\" version\" :\" 2.0\" ,\" extensionBundle\" :" +
115+ "'{'\" id\" :\" Microsoft.Azure.Functions.ExtensionBundle\" ,\" version\" :\" [4.*, 5.0.0)\" '}',\" customHandler\" : '{'\" description\" : '{'\" defaultExecutablePath\" : \" {0}\" ,\" workingDirectory\" : \" \" ,\" arguments\" : [\" {1}\" ]'}',\" enableForwardingHttpRequest\" : true'}}'\n " ;
111116
112117 private static final BindingEnum [] FUNCTION_WITHOUT_FUNCTION_EXTENSION = {BindingEnum .HttpOutput , BindingEnum .HttpTrigger };
113118 private static final String EXTENSION_BUNDLE_ID = "Microsoft.Azure.Functions.ExtensionBundle" ;
@@ -170,7 +175,12 @@ protected void doExecute() throws AzureExecutionException {
170175
171176 writeFunctionJsonFiles (objectWriter , configMap );
172177
173- copyJarsToStageDirectory ();
178+ if (isNativeExecutable ()) {
179+ copyBinaryToStageDirectory ();
180+ } else {
181+ copyJarsToStageDirectory ();
182+ }
183+
174184 } catch (IOException | MojoExecutionException e ) {
175185 throw new AzureExecutionException ("Cannot perform IO operations due to error:" + e .getMessage (), e );
176186 }
@@ -184,6 +194,21 @@ protected void doExecute() throws AzureExecutionException {
184194 log .info (BUILD_SUCCESS );
185195 }
186196
197+ protected void copyBinaryToStageDirectory () throws IOException , MojoExecutionException {
198+ final File stagingDirectory = new File (getDeploymentStagingDirectoryPath ());
199+ log .info ("" );
200+ log .info (COPY_BINARY + stagingDirectory .getAbsolutePath ());
201+ final File originalArtifact = new File (getArtifact ().getParentFile (), nativeExecutablePath );
202+
203+ File destFile = new File (stagingDirectory , nativeExecutablePath );
204+ log .info ("src: {}" , originalArtifact .getAbsolutePath ());
205+ log .info ("dest: {}" , destFile .getAbsolutePath ());
206+
207+ FileUtils .copyFile (originalArtifact , destFile );
208+
209+ log .info (COPY_SUCCESS );
210+ }
211+
187212 public static void buildArtifactWithDependencies (@ Nonnull final File artifactFile , @ Nullable final Set <File > dependencies , final File target ) {
188213 AzureMessager .getMessager ().info ("Building artifact with dependencies..." );
189214 final Shader shader = new DefaultShader ();
@@ -316,6 +341,7 @@ protected void writeFunctionJsonFiles(final ObjectWriter objectWriter,
316341 final Map <String , FunctionConfiguration > configMap ) throws IOException {
317342 log .info ("" );
318343 log .info (SAVE_FUNCTION_JSONS );
344+ log .info ("Native: " +isNativeExecutable ());
319345 if (configMap .size () == 0 ) {
320346 log .info (SAVE_SKIP );
321347 } else {
@@ -330,6 +356,11 @@ protected void writeFunctionJsonFile(final ObjectWriter objectWriter, final Stri
330356 log .info (SAVE_FUNCTION_JSON + functionName );
331357 final File functionJsonFile = Paths .get (getDeploymentStagingDirectoryPath (),
332358 functionName , FUNCTION_JSON ).toFile ();
359+
360+ if (isNativeExecutable ()) {
361+ config .setEntryPoint (null );
362+ config .setScriptFile (null );
363+ }
333364 writeObjectToFile (objectWriter , config , functionJsonFile );
334365 log .info (SAVE_SUCCESS + functionJsonFile .getAbsolutePath ());
335366 }
@@ -339,7 +370,14 @@ protected void copyHostJson() throws IOException {
339370 log .info (SAVING_HOST_JSON );
340371 final File sourceHostJsonFile = getHostJsonFile ();
341372 final File destHostJsonFile = Paths .get (getDeploymentStagingDirectoryPath (), HOST_JSON ).toFile ();
342- copyFilesWithDefaultContent (sourceHostJsonFile , destHostJsonFile , DEFAULT_HOST_JSON );
373+ if (isNativeExecutable ()) {
374+ File nativeFile = new File (getNativeExecutablePath ());
375+ String newDefaultContent = MessageFormat .format (DEFAULT_CUSTOM_HOST_JSON , nativeFile .getName (), getCustomHandlerArgs ());
376+ copyFilesWithDefaultContent (sourceHostJsonFile , destHostJsonFile , newDefaultContent );
377+ } else {
378+ copyFilesWithDefaultContent (sourceHostJsonFile , destHostJsonFile , DEFAULT_HOST_JSON );
379+ }
380+
343381 log .info (SAVE_SUCCESS + destHostJsonFile .getAbsolutePath ());
344382 }
345383
@@ -348,10 +386,15 @@ protected void copyLocalSettingsJson() throws IOException {
348386 log .info (SAVING_LOCAL_SETTINGS_JSON );
349387 final File sourceLocalSettingsJsonFile = getLocalSettingsJsonFile ();
350388 final File destLocalSettingsJsonFile = Paths .get (getDeploymentStagingDirectoryPath (), LOCAL_SETTINGS_JSON ).toFile ();
351- copyFilesWithDefaultContent (sourceLocalSettingsJsonFile , destLocalSettingsJsonFile , DEFAULT_LOCAL_SETTINGS_JSON );
389+ String defaultContent = MessageFormat .format (DEFAULT_LOCAL_SETTINGS_JSON , getWorkerRuntime ());
390+ copyFilesWithDefaultContent (sourceLocalSettingsJsonFile , destLocalSettingsJsonFile , defaultContent );
352391 log .info (SAVE_SUCCESS + destLocalSettingsJsonFile .getAbsolutePath ());
353392 }
354393
394+ private String getWorkerRuntime () {
395+ return isNativeExecutable ()? "custom" : "java" ;
396+ }
397+
355398 private static void copyFilesWithDefaultContent (File source , File dest , String defaultContent )
356399 throws IOException {
357400 if (source != null && source .exists ()) {
0 commit comments