This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit b045295a159709b7db20180cf4a2c004760bd0ba
Author: nferraro <ni.ferr...@gmail.com>
AuthorDate: Fri Sep 7 17:52:49 2018 +0200

    Refactor maven builder into its own module
---
 Sample.java                      |   2 +-
 build/Makefile                   |   7 +-
 pkg/build/local/local_builder.go | 235 ++++++-----------------------------
 pkg/client/cmd/run/run.go        |  14 ++-
 pkg/util/maven/maven.go          | 256 +++++++++++++++++++++++++++++++++++++++
 pkg/util/maven/types.go          |  34 ++++++
 6 files changed, 349 insertions(+), 199 deletions(-)

diff --git a/Sample.java b/Sample.java
index 47f59e9..2d73b92 100644
--- a/Sample.java
+++ b/Sample.java
@@ -7,7 +7,7 @@ public class Routes extends RouteBuilder {
   @Override
   public void configure() throws Exception {
          from("timer:tick")
-               .setBody(constant("Hello Kamel!!!"))
+               .setBody(constant("Hello! Camel K rocks!!!"))
                .to("log:info");
   }
 
diff --git a/build/Makefile b/build/Makefile
index 2d2aee8..d8d2b7a 100644
--- a/build/Makefile
+++ b/build/Makefile
@@ -14,9 +14,14 @@ build-runtime:
 codegen:
        ./tmp/codegen/update-generated.sh
 
-images:
+images: images-build
+
+images-build:
        operator-sdk build docker.io/apache/camel-k:$(VERSION)
 
+images-push:
+       docker push docker.io/apache/camel-k:$(VERSION)
+
 test: check
 check:
        go test ./...
diff --git a/pkg/build/local/local_builder.go b/pkg/build/local/local_builder.go
index 478a810..e5f85ba 100644
--- a/pkg/build/local/local_builder.go
+++ b/pkg/build/local/local_builder.go
@@ -22,12 +22,7 @@ import (
        "github.com/sirupsen/logrus"
        "time"
        "io/ioutil"
-       "path"
-       "os"
-       "os/exec"
        "github.com/pkg/errors"
-       "archive/tar"
-       "io"
        buildv1 "github.com/openshift/api/build/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/api/core/v1"
@@ -43,28 +38,29 @@ import (
        build "github.com/apache/camel-k/pkg/build/api"
        "github.com/apache/camel-k/pkg/util/kubernetes"
        "github.com/apache/camel-k/version"
+       "github.com/apache/camel-k/pkg/util/maven"
 )
 
 type localBuilder struct {
-       buffer     chan buildOperation
-       namespace  string
+       buffer    chan buildOperation
+       namespace string
 }
 
 type buildOperation struct {
-       source  build.BuildSource
-       output  chan build.BuildResult
+       source build.BuildSource
+       output chan build.BuildResult
 }
 
 func NewLocalBuilder(ctx context.Context, namespace string) build.Builder {
        builder := localBuilder{
-               buffer: make(chan buildOperation, 100),
+               buffer:    make(chan buildOperation, 100),
                namespace: namespace,
        }
        go builder.buildCycle(ctx)
        return &builder
 }
 
-func (b *localBuilder) Build(source build.BuildSource) <- chan 
build.BuildResult {
+func (b *localBuilder) Build(source build.BuildSource) <-chan 
build.BuildResult {
        res := make(chan build.BuildResult, 1)
        op := buildOperation{
                source: source,
@@ -77,10 +73,10 @@ func (b *localBuilder) Build(source build.BuildSource) <- 
chan build.BuildResult
 func (b *localBuilder) buildCycle(ctx context.Context) {
        for {
                select {
-               case <- ctx.Done():
+               case <-ctx.Done():
                        b.buffer = nil
                        return
-               case op := <- b.buffer:
+               case op := <-b.buffer:
                        now := time.Now()
                        logrus.Info("Starting new build")
                        image, err := b.execute(op.source)
@@ -95,13 +91,13 @@ func (b *localBuilder) buildCycle(ctx context.Context) {
                                op.output <- build.BuildResult{
                                        Source: &op.source,
                                        Status: build.BuildStatusError,
-                                       Error: err,
+                                       Error:  err,
                                }
                        } else {
                                op.output <- build.BuildResult{
                                        Source: &op.source,
                                        Status: build.BuildStatusCompleted,
-                                       Image: image,
+                                       Image:  image,
                                }
                        }
 
@@ -110,15 +106,28 @@ func (b *localBuilder) buildCycle(ctx context.Context) {
 }
 
 func (b *localBuilder) execute(source build.BuildSource) (string, error) {
-       buildDir, err := ioutil.TempDir("", "camel-k-")
-       if err != nil {
-               return "", errors.Wrap(err, "could not create temporary dir for 
maven artifacts")
-       }
-       //defer os.RemoveAll(buildDir)
 
-       logrus.Info("Using build dir : ", buildDir)
+       project := maven.Project{
+               GroupId:    "org.apache.camel.k.integration",
+               ArtifactId: "camel-k-integration",
+               Version:    "1.0.0",
+               JavaSources: map[string]string{
+                       "kamel/Routes.java": source.Code,
+               },
+               Env: map[string]string{
+                       "JAVA_MAIN_CLASS": "org.apache.camel.k.jvm.Application",
+                       "KAMEL_CLASS":     "kamel.Routes",
+               },
+               Dependencies: []maven.Dependency{
+                       {
+                               GroupId:    "org.apache.camel.k",
+                               ArtifactId: "camel-k-runtime-jvm",
+                               Version:    version.Version,
+                       },
+               },
+       }
 
-       tarFileName, err := b.createTar(buildDir, source)
+       tarFileName, err := maven.Build(project)
        if err != nil {
                return "", err
        }
@@ -137,10 +146,10 @@ func (b *localBuilder) publish(tarFile string, source 
build.BuildSource) (string
        bc := buildv1.BuildConfig{
                TypeMeta: metav1.TypeMeta{
                        APIVersion: buildv1.SchemeGroupVersion.String(),
-                       Kind: "BuildConfig",
+                       Kind:       "BuildConfig",
                },
                ObjectMeta: metav1.ObjectMeta{
-                       Name: "camel-k-" + source.Identifier.Name,
+                       Name:      "camel-k-" + source.Identifier.Name,
                        Namespace: b.namespace,
                },
                Spec: buildv1.BuildConfigSpec{
@@ -175,10 +184,10 @@ func (b *localBuilder) publish(tarFile string, source 
build.BuildSource) (string
        is := imagev1.ImageStream{
                TypeMeta: metav1.TypeMeta{
                        APIVersion: imagev1.SchemeGroupVersion.String(),
-                       Kind: "ImageStream",
+                       Kind:       "ImageStream",
                },
                ObjectMeta: metav1.ObjectMeta{
-                       Name: "camel-k-" + source.Identifier.Name,
+                       Name:      "camel-k-" + source.Identifier.Name,
                        Namespace: b.namespace,
                },
                Spec: imagev1.ImageStreamSpec{
@@ -197,7 +206,7 @@ func (b *localBuilder) publish(tarFile string, source 
build.BuildSource) (string
        inConfig := k8sclient.GetKubeConfig()
        config := rest.CopyConfig(inConfig)
        config.GroupVersion = &schema.GroupVersion{
-               Group: "build.openshift.io",
+               Group:   "build.openshift.io",
                Version: "v1",
        }
        config.APIPath = "/apis"
@@ -217,7 +226,7 @@ func (b *localBuilder) publish(tarFile string, source 
build.BuildSource) (string
 
        resource, err := ioutil.ReadFile(tarFile)
        if err != nil {
-               return "", errors.Wrap(err, "cannot fully read tar file " + 
tarFile)
+               return "", errors.Wrap(err, "cannot fully read tar file 
"+tarFile)
        }
 
        result := restClient.
@@ -249,7 +258,7 @@ func (b *localBuilder) publish(tarFile string, source 
build.BuildSource) (string
                return "", err
        }
 
-       err = kubernetes.WaitCondition(ocbuild, func(obj interface{})(bool, 
error) {
+       err = kubernetes.WaitCondition(ocbuild, func(obj interface{}) (bool, 
error) {
                if val, ok := obj.(*buildv1.Build); ok {
                        if val.Status.Phase == buildv1.BuildPhaseComplete {
                                return true, nil
@@ -260,7 +269,7 @@ func (b *localBuilder) publish(tarFile string, source 
build.BuildSource) (string
                        }
                }
                return false, nil
-       }, 5 * time.Minute)
+       }, 5*time.Minute)
 
        err = sdk.Get(&is)
        if err != nil {
@@ -272,169 +281,3 @@ func (b *localBuilder) publish(tarFile string, source 
build.BuildSource) (string
        }
        return is.Status.DockerImageRepository + ":" + 
source.Identifier.Digest, nil
 }
-
-func (b *localBuilder) createTar(buildDir string, source build.BuildSource) 
(string, error) {
-       dir, err := b.createMavenStructure(buildDir, source)
-       if err != nil {
-               return "", err
-       }
-
-       mavenBuild := exec.Command("mvn", "clean", "install", "-DskipTests")
-       mavenBuild.Dir = dir
-       logrus.Info("Starting maven build: mvn clean install -DskipTests")
-       err = mavenBuild.Run()
-       if err != nil {
-               return "", errors.Wrap(err, "failure while executing maven 
build")
-       }
-
-       mavenDep := exec.Command("mvn", "dependency:copy-dependencies")
-       mavenDep.Dir = dir
-       logrus.Info("Copying maven dependencies: mvn 
dependency:copy-dependencies")
-       err = mavenDep.Run()
-       if err != nil {
-               return "", errors.Wrap(err, "failure while extracting maven 
dependencies")
-       }
-       logrus.Info("Maven build completed successfully")
-
-       tarFileName := path.Join(buildDir, "camel-k-integration.tar")
-       tarFile, err := os.Create(tarFileName)
-       if err != nil {
-               return "", errors.Wrap(err, "cannot create tar file")
-       }
-       defer tarFile.Close()
-
-       writer := tar.NewWriter(tarFile)
-       err = b.appendToTar(path.Join(buildDir, "target", 
"camel-k-integration-1.0.0.jar"), "", writer)
-       if err != nil {
-               return "", err
-       }
-
-       err = b.appendToTar(path.Join(buildDir, "environment"), ".s2i", writer)
-       if err != nil {
-               return "", err
-       }
-
-       dependenciesDir := path.Join(buildDir, "target", "dependency")
-       dependencies, err := ioutil.ReadDir(dependenciesDir)
-       if err != nil {
-               return "", err
-       }
-
-       for _, dep := range dependencies {
-               err = b.appendToTar(path.Join(dependenciesDir, dep.Name()), "", 
writer)
-               if err != nil {
-                       return "", err
-               }
-       }
-
-       writer.Close()
-
-       return tarFileName, nil
-}
-
-func (b *localBuilder) appendToTar(filePath string, tarPath string, writer 
*tar.Writer) error {
-       info, err := os.Stat(filePath)
-       if err != nil {
-               return err
-       }
-       _, fileName := path.Split(filePath)
-       if tarPath != "" {
-               fileName = path.Join(tarPath, fileName)
-       }
-
-       writer.WriteHeader(&tar.Header{
-               Name: fileName,
-               Size: info.Size(),
-               Mode: int64(info.Mode()),
-               ModTime: info.ModTime(),
-       })
-
-       file, err := os.Open(filePath)
-       if err != nil {
-               return err
-       }
-       defer file.Close()
-
-       _, err = io.Copy(writer, file)
-       if err != nil {
-               return errors.Wrap(err, "cannot add file to the tar archive")
-       }
-       return nil
-}
-
-func (b *localBuilder) createMavenStructure(buildDir string, source 
build.BuildSource) (string, error) {
-       pomFileName := path.Join(buildDir, "pom.xml")
-       pom, err := os.Create(pomFileName)
-       if err != nil {
-               return "", err
-       }
-       defer pom.Close()
-
-       _, err = pom.WriteString(b.createPom())
-       if err != nil {
-               return "", err
-       }
-
-       packageDir := path.Join(buildDir, "src", "main", "java", "kamel")
-       err = os.MkdirAll(packageDir, 0777)
-       if err != nil {
-               return "", err
-       }
-
-       sourceFileName := path.Join(packageDir, "Routes.java")
-       sourceFile, err := os.Create(sourceFileName)
-       if err != nil {
-               return "", err
-       }
-       defer sourceFile.Close()
-
-       _, err = sourceFile.WriteString(source.Code)
-       if err != nil {
-               return "", err
-       }
-
-       envFileName := path.Join(buildDir, "environment")
-       envFile, err := os.Create(envFileName)
-       if err != nil {
-               return "", err
-       }
-       defer envFile.Close()
-
-       _, err = envFile.WriteString(b.createEnvFile())
-       if err != nil {
-               return "", err
-       }
-
-       return buildDir, nil
-}
-
-func (b *localBuilder) createEnvFile() string {
-       return `
-JAVA_MAIN_CLASS=org.apache.camel.k.jvm.Application
-KAMEL_CLASS=kamel.Routes
-`
-}
-
-
-func (b *localBuilder) createPom() string {
-       return `<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0";
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
-  <modelVersion>4.0.0</modelVersion>
-
-  <groupId>org.apache.camel.k.integration</groupId>
-  <artifactId>camel-k-integration</artifactId>
-  <version>1.0.0</version>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.camel.k</groupId>
-      <artifactId>camel-k-runtime-jvm</artifactId>
-      <version>` + version.Version + `</version>
-    </dependency>
-  </dependencies>
-
-</project>
-`
-}
\ No newline at end of file
diff --git a/pkg/client/cmd/run/run.go b/pkg/client/cmd/run/run.go
index 3237f80..fd6df53 100644
--- a/pkg/client/cmd/run/run.go
+++ b/pkg/client/cmd/run/run.go
@@ -28,6 +28,7 @@ import (
        "io/ioutil"
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
        "github.com/apache/camel-k/pkg/util/kubernetes"
+       "fmt"
 )
 
 type runCmdFlags struct {
@@ -89,8 +90,10 @@ func run(cmd *cobra.Command, args []string) error {
                },
        }
 
+       existed := false
        err = sdk.Create(&integration)
        if err != nil && k8serrors.IsAlreadyExists(err) {
+               existed = true
                clone := integration.DeepCopy()
                err = sdk.Get(clone)
                if err != nil {
@@ -100,7 +103,16 @@ func run(cmd *cobra.Command, args []string) error {
                err = sdk.Update(&integration)
        }
 
-       return err
+       if err != nil {
+               return err
+       }
+
+       if !existed {
+               fmt.Printf("integration \"%s\" created\n", name)
+       } else {
+               fmt.Printf("integration \"%s\" updated\n", name)
+       }
+       return nil
 }
 
 func loadCode(fileName string) (string, error) {
diff --git a/pkg/util/maven/maven.go b/pkg/util/maven/maven.go
new file mode 100644
index 0000000..08864ac
--- /dev/null
+++ b/pkg/util/maven/maven.go
@@ -0,0 +1,256 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package maven
+
+import (
+       "io/ioutil"
+       "os"
+       "archive/tar"
+       "github.com/sirupsen/logrus"
+       "io"
+       "github.com/pkg/errors"
+       "path"
+       "strings"
+       "os/exec"
+)
+
+
+const (
+       buildDirPrefix = "maven-"
+       artifactDirPrefix = "maven-bin-"
+)
+
+// Takes a project description and returns a binary tar with the built 
artifacts
+func Build(project Project) (string, error) {
+       buildDir, err := ioutil.TempDir("", buildDirPrefix)
+       if err != nil {
+               return "", errors.Wrap(err, "could not create temporary dir for 
maven source files")
+       }
+       defer os.RemoveAll(buildDir)
+
+       err = createMavenStructure(buildDir, project)
+       if err != nil {
+               return "", errors.Wrap(err, "could not write maven source 
files")
+       }
+       err = runMavenBuild(buildDir)
+       if err != nil {
+               return "", err
+       }
+       tarfile, err := createTar(buildDir, project)
+       if err != nil {
+               return "", err
+       }
+       return tarfile, nil
+}
+
+func runMavenBuild(buildDir string) error {
+       mavenBuild := exec.Command("mvn", "clean", "install", "-DskipTests")
+       mavenBuild.Dir = buildDir
+       logrus.Info("Starting maven build: mvn clean install -DskipTests")
+       err := mavenBuild.Run()
+       if err != nil {
+               return errors.Wrap(err, "failure while executing maven build")
+       }
+
+       mavenDep := exec.Command("mvn", "dependency:copy-dependencies")
+       mavenDep.Dir = buildDir
+       logrus.Info("Copying maven dependencies: mvn 
dependency:copy-dependencies")
+       err = mavenDep.Run()
+       if err != nil {
+               return errors.Wrap(err, "failure while extracting maven 
dependencies")
+       }
+       logrus.Info("Maven build completed successfully")
+       return nil
+}
+
+func createTar(buildDir string, project Project) (string, error) {
+       artifactDir, err := ioutil.TempDir("", artifactDirPrefix)
+       if err != nil {
+               return "", errors.Wrap(err, "could not create temporary dir for 
maven artifacts")
+       }
+
+       tarFileName := path.Join(artifactDir, project.ArtifactId + ".tar")
+       tarFile, err := os.Create(tarFileName)
+       if err != nil {
+               return "", errors.Wrap(err, "cannot create tar file " + 
tarFileName)
+       }
+       defer tarFile.Close()
+
+       writer := tar.NewWriter(tarFile)
+       err = appendToTar(path.Join(buildDir, "target", project.ArtifactId + 
"-" + project.Version + ".jar"), "", writer)
+       if err != nil {
+               return "", err
+       }
+
+       // Environment variables
+       if project.Env != nil {
+               err = writeFile(buildDir, "run-env.sh", 
envFileContent(project.Env))
+               if err != nil {
+                       return "", err
+               }
+               err = appendToTar(path.Join(buildDir, "run-env.sh"), "", writer)
+               if err != nil {
+                       return "", err
+               }
+       }
+
+       dependenciesDir := path.Join(buildDir, "target", "dependency")
+       dependencies, err := ioutil.ReadDir(dependenciesDir)
+       if err != nil {
+               return "", err
+       }
+
+       for _, dep := range dependencies {
+               err = appendToTar(path.Join(dependenciesDir, dep.Name()), "", 
writer)
+               if err != nil {
+                       return "", err
+               }
+       }
+
+       writer.Close()
+
+       return tarFileName, nil
+}
+
+func appendToTar(filePath string, tarPath string, writer *tar.Writer) error {
+       info, err := os.Stat(filePath)
+       if err != nil {
+               return err
+       }
+       _, fileName := path.Split(filePath)
+       if tarPath != "" {
+               fileName = path.Join(tarPath, fileName)
+       }
+
+       writer.WriteHeader(&tar.Header{
+               Name: fileName,
+               Size: info.Size(),
+               Mode: int64(info.Mode()),
+               ModTime: info.ModTime(),
+       })
+
+       file, err := os.Open(filePath)
+       if err != nil {
+               return err
+       }
+       defer file.Close()
+
+       _, err = io.Copy(writer, file)
+       if err != nil {
+               return errors.Wrap(err, "cannot add file to the tar archive")
+       }
+       return nil
+}
+
+func createMavenStructure(buildDir string, project Project) error {
+       err := writeFile(buildDir, "pom.xml", pomFileContent(project))
+       if err != nil {
+               return err
+       }
+       err = writeFiles(path.Join(buildDir, "src", "main", "java"), 
project.JavaSources)
+       if err != nil {
+               return err
+       }
+       err = writeFiles(path.Join(buildDir, "src", "main", "resources"), 
project.Resources)
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+func writeFiles(buildDir string, files map[string]string) error {
+       if files == nil {
+               return nil
+       }
+       for fileName, fileContent := range files {
+               err := writeFile(buildDir, fileName, fileContent)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func writeFile(buildDir string, relativePath string, content string) error {
+       filePath := path.Join(buildDir, relativePath)
+       fileDir := path.Dir(filePath)
+       // Create dir if not present
+       err := os.MkdirAll(fileDir, 0777)
+       if err != nil {
+               return errors.Wrap(err, "could not create dir for file " + 
relativePath)
+       }
+       // Create file
+       file, err := os.Create(filePath)
+       if err != nil {
+               return errors.Wrap(err, "could not create file " + relativePath)
+       }
+       defer file.Close()
+
+       _, err = file.WriteString(content)
+       if err != nil {
+               errors.Wrap(err, "could not write to file " + relativePath)
+       }
+       return nil
+}
+
+
+func envFileContent(env map[string]string) string {
+       if env == nil {
+               return ""
+       }
+       content := ""
+       for k,v := range env {
+               content = content + "export " + k + "=" + v + "\n"
+       }
+       return content
+}
+
+
+func pomFileContent(project Project) string {
+       basePom := `<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>` + project.GroupId + `</groupId>
+  <artifactId>` + project.ArtifactId + `</artifactId>
+  <version>` + project.Version + `</version>
+
+  <dependencies>
+    #dependencies#
+  </dependencies>
+
+</project>
+`
+       depStr := ""
+       for _, dep := range project.Dependencies {
+               depStr += "\t\t<dependency>"
+               depStr += "\t\t\t<groupId>" + dep.GroupId + "</groupId>"
+               depStr += "\t\t\t<artifactId>" + dep.ArtifactId + 
"</artifactId>"
+               if dep.Version != "" {
+                       depStr += "\t\t\t<version>" + dep.Version + "</version>"
+               }
+               depStr += "\t\t</dependency>"
+               depStr += "\n"
+       }
+
+       pom := strings.Replace(basePom, "#dependencies#", depStr, 1)
+       return pom
+}
\ No newline at end of file
diff --git a/pkg/util/maven/types.go b/pkg/util/maven/types.go
new file mode 100644
index 0000000..c34bb84
--- /dev/null
+++ b/pkg/util/maven/types.go
@@ -0,0 +1,34 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package maven
+
+type Project struct {
+       GroupId      string
+       ArtifactId   string
+       Version      string
+       Dependencies []Dependency
+       JavaSources  map[string]string
+       Resources    map[string]string
+       Env          map[string]string
+}
+
+type Dependency struct {
+       GroupId      string
+       ArtifactId   string
+       Version      string
+}
\ No newline at end of file

Reply via email to