github.com/defanghe/fabric@v2.1.1+incompatible/core/chaincode/platforms/java/platform.go (about)

     1  /*
     2  Copyright DTCC 2016 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package java
     8  
     9  import (
    10  	"archive/tar"
    11  	"bytes"
    12  	"compress/gzip"
    13  	"errors"
    14  	"fmt"
    15  	"io"
    16  	"net/url"
    17  	"regexp"
    18  	"strings"
    19  
    20  	pb "github.com/hyperledger/fabric-protos-go/peer"
    21  	"github.com/hyperledger/fabric/common/flogging"
    22  	"github.com/hyperledger/fabric/core/chaincode/platforms/util"
    23  )
    24  
    25  var logger = flogging.MustGetLogger("chaincode.platform.java")
    26  
    27  // Platform for java chaincodes in java
    28  type Platform struct{}
    29  
    30  // Name returns the name of this platform
    31  func (p *Platform) Name() string {
    32  	return pb.ChaincodeSpec_JAVA.String()
    33  }
    34  
    35  //ValidatePath validates the java chaincode paths
    36  func (p *Platform) ValidatePath(rawPath string) error {
    37  	path, err := url.Parse(rawPath)
    38  	if err != nil || path == nil {
    39  		logger.Errorf("invalid chaincode path %s %v", rawPath, err)
    40  		return fmt.Errorf("invalid path: %s", err)
    41  	}
    42  
    43  	return nil
    44  }
    45  
    46  func (p *Platform) ValidateCodePackage(code []byte) error {
    47  	// File to be valid should match first RegExp and not match second one.
    48  	filesToMatch := regexp.MustCompile(`^(/)?src/((src|META-INF)/.*|(build\.gradle|settings\.gradle|pom\.xml))`)
    49  	filesToIgnore := regexp.MustCompile(`.*\.class$`)
    50  	is := bytes.NewReader(code)
    51  	gr, err := gzip.NewReader(is)
    52  	if err != nil {
    53  		return fmt.Errorf("failure opening codepackage gzip stream: %s", err)
    54  	}
    55  	tr := tar.NewReader(gr)
    56  
    57  	for {
    58  		header, err := tr.Next()
    59  		if err == io.EOF {
    60  			break
    61  		}
    62  		if err != nil {
    63  			return err
    64  		}
    65  
    66  		// --------------------------------------------------------------------------------------
    67  		// Check name for conforming path
    68  		// --------------------------------------------------------------------------------------
    69  		if !filesToMatch.MatchString(header.Name) || filesToIgnore.MatchString(header.Name) {
    70  			return fmt.Errorf("illegal file detected in payload: \"%s\"", header.Name)
    71  		}
    72  
    73  		// --------------------------------------------------------------------------------------
    74  		// Check that file mode makes sense
    75  		// --------------------------------------------------------------------------------------
    76  		// Acceptable flags:
    77  		//      ISREG      == 0100000
    78  		//      -rw-rw-rw- == 0666
    79  		//
    80  		// Anything else is suspect in this context and will be rejected
    81  		// --------------------------------------------------------------------------------------
    82  		if header.Mode&^0100666 != 0 {
    83  			return fmt.Errorf("illegal file mode detected for file %s: %o", header.Name, header.Mode)
    84  		}
    85  	}
    86  	return nil
    87  }
    88  
    89  // WritePackage writes the java chaincode package
    90  func (p *Platform) GetDeploymentPayload(path string) ([]byte, error) {
    91  	logger.Debugf("Packaging java project from path %s", path)
    92  
    93  	if path == "" {
    94  		logger.Error("ChaincodeSpec's path cannot be empty")
    95  		return nil, errors.New("ChaincodeSpec's path cannot be empty")
    96  	}
    97  
    98  	// trim trailing slash if it exists
    99  	if path[len(path)-1] == '/' {
   100  		path = path[:len(path)-1]
   101  	}
   102  
   103  	buf := &bytes.Buffer{}
   104  	gw := gzip.NewWriter(buf)
   105  	tw := tar.NewWriter(gw)
   106  
   107  	excludedDirs := []string{"target", "build", "out"}
   108  	excludedFileTypes := map[string]bool{".class": true}
   109  	err := util.WriteFolderToTarPackage(tw, path, excludedDirs, nil, excludedFileTypes)
   110  	if err != nil {
   111  		logger.Errorf("Error writing java project to tar package %s", err)
   112  		return nil, fmt.Errorf("failed to create chaincode package: %s", err)
   113  	}
   114  
   115  	tw.Close()
   116  	gw.Close()
   117  
   118  	return buf.Bytes(), nil
   119  }
   120  
   121  func (p *Platform) GenerateDockerfile() (string, error) {
   122  	var buf []string
   123  
   124  	buf = append(buf, "FROM "+util.GetDockerImageFromConfig("chaincode.java.runtime"))
   125  	buf = append(buf, "ADD binpackage.tar /root/chaincode-java/chaincode")
   126  
   127  	dockerFileContents := strings.Join(buf, "\n")
   128  
   129  	return dockerFileContents, nil
   130  }
   131  
   132  func (p *Platform) DockerBuildOptions(path string) (util.DockerBuildOptions, error) {
   133  	return util.DockerBuildOptions{
   134  		Image: util.GetDockerImageFromConfig("chaincode.java.runtime"),
   135  		Cmd:   "./build.sh",
   136  	}, nil
   137  }