For chaincode/contract implementations please use java.util.logging or your own framework. All the Hyperledger + * Fabric code here is logged in loggers with names starting org.hyperledger * - * Control of this is via the environment variables - * 'CORE_CHAINCODE_LOGGING_LEVEL' this takes a string that matches the following - * Java.util.logging levels (case insensitive) - * - * CRITICAL, ERROR == Level.SEVERE, WARNING == Level.WARNING, INFO == Level.INFO - * NOTICE == Level.CONFIG, DEBUG == Level.FINEST + *
Control of this is via the environment variables 'CORE_CHAINCODE_LOGGING_LEVEL' this takes a string that matches + * the following Java.util.logging levels (case insensitive) * + *
CRITICAL, ERROR == Level.SEVERE, WARNING == Level.WARNING, INFO == Level.INFO NOTICE == Level.CONFIG, DEBUG ==
+ * Level.FINEST
*/
public final class Logging {
- /**
- * Name of the Performance logger.
- */
+ /** Name of the Performance logger. */
public static final String PERFLOGGER = "org.hyperledger.Performance";
- /** Private Constructor.
- *
- */
- private Logging() {
-
- }
+ /** Private Constructor. */
+ private Logging() {}
/**
* Formats a Throwable to a string with details of all the causes.
@@ -59,11 +51,10 @@ public static String formatError(final Throwable throwable) {
final Throwable cause = throwable.getCause();
if (cause != null) {
buffer.append(".. caused by ..").append(System.lineSeparator());
- buffer.append(Logging.formatError(cause));
+ buffer.append(formatError(cause));
}
return buffer.toString();
-
}
/**
@@ -77,32 +68,35 @@ public static void setLogLevel(final String newLevel) {
final LogManager logManager = LogManager.getLogManager();
// slightly cumbersome approach - but the loggers don't have a 'get children'
// so find those that have the correct stem.
- final ArrayList
- * Applications can implement their own versions if they wish to add
- * functionality. All subclasses MUST implement a constructor, for example
- *
- * Applications can implement their own versions if they wish to add functionality. All subclasses MUST implement a
+ * constructor, for example
*
+ *
- * All methods on this interface have default implementations; for
- * many contracts it may not be needed to sub-class these.
- *
- * Each method on the Contract that is marked with the {@link org.hyperledger.fabric.contract.annotation.Transaction}
- * annotation is considered a Transaction Function. This is eligible for
- * calling. Each transaction function is supplied with its first parameter
- * being a {@link org.hyperledger.fabric.contract.Context}. The other parameters
- * are supplied at the developer's discretion.
- *
- * The sequence of calls is
+ *
+ * All methods on this interface have default implementations; for many contracts it may not be needed to sub-class
+ * these.
+ *
+ * Each method on the Contract that is marked with the {@link org.hyperledger.fabric.contract.annotation.Transaction}
+ * annotation is considered a Transaction Function. This is eligible for calling. Each transaction function is supplied
+ * with its first parameter being a {@link org.hyperledger.fabric.contract.Context}. The other parameters are supplied
+ * at the developer's discretion.
+ *
+ * The sequence of calls is
*
*
- * If any of these functions throws an exception it is considered an error case
- * and the whole transaction is failed. The
- * {@link org.hyperledger.fabric.contract.Context} is a very important object as
- * it provides transactional context for access to current transaction id,
- * ledger state, etc.
- *
- * Note on Threading
- *
- * All code should be 'Thread Friendly'. Each method must not rely on instance
- * fields or class side variables for storage. Nor should they use any
- * ThreadLocal Storage. Ledger data is stored via the ledger api available via
- * the {@link Context}.
- *
- * If information needs to be passed from
- * {@link #beforeTransaction(Context)} to
- * {@link #afterTransaction(Context, Object)} or between separate transaction
- * functions when called directly then a subclass of the {@link Context}
- * should be provided.
+ *
+ * If any of these functions throws an exception it is considered an error case and the whole transaction is failed.
+ * The {@link org.hyperledger.fabric.contract.Context} is a very important object as it provides transactional context
+ * for access to current transaction id, ledger state, etc.
+ *
+ * Note on Threading
+ *
+ * All code should be 'Thread Friendly'. Each method must not rely on instance fields or class side variables for
+ * storage. Nor should they use any ThreadLocal Storage. Ledger data is stored via the ledger api available via the
+ * {@link Context}.
+ *
+ * If information needs to be passed from {@link #beforeTransaction(Context)} to {@link #afterTransaction(Context,
+ * Object)} or between separate transaction functions when called directly then a subclass of the {@link Context} should
+ * be provided.
*/
public interface ContractInterface {
/**
* Create context from {@link ChaincodeStub}.
*
- * Default impl provided, but can be
- * overwritten by contract
+ * Default impl provided, but can be overwritten by contract
*
* @param stub Instance of the ChaincodeStub to use for this transaction
- * @return instance of the context to use for the current transaction being
- * executed
+ * @return instance of the context to use for the current transaction being executed
*/
default Context createContext(final ChaincodeStub stub) {
return ContextFactory.getInstance().createContext(stub);
@@ -66,9 +58,8 @@ default Context createContext(final ChaincodeStub stub) {
/**
* Invoked for any transaction that does not exist.
*
- * This will throw an exception. If you wish to alter the exception thrown or if
- * you wish to consider requests for transactions that don't exist as not an
- * error, subclass this method.
+ * This will throw an exception. If you wish to alter the exception thrown or if you wish to consider requests
+ * for transactions that don't exist as not an error, subclass this method.
*
* @param ctx the context as created by {@link #createContext(ChaincodeStub)}.
*/
@@ -79,25 +70,25 @@ default void unknownTransaction(final Context ctx) {
/**
* Invoked once before each transaction.
*
- * Any exceptions thrown will fail the transaction, and neither the required
- * transaction or the {@link #afterTransaction(Context, Object)} will be called
+ * Any exceptions thrown will fail the transaction, and neither the required transaction or the
+ * {@link #afterTransaction(Context, Object)} will be called
*
* @param ctx the context as created by {@link #createContext(ChaincodeStub)}.
*/
default void beforeTransaction(final Context ctx) {
+ // Nothing by default
}
/**
* Invoked once after each transaction.
*
- * Any exceptions thrown will fail the transaction.
+ * Any exceptions thrown will fail the transaction.
*
- * @param ctx the context as created by
- * {@link #createContext(ChaincodeStub)}.
- * @param result The object returned from the transaction function if any. As
- * this is a Java object and therefore pass-by-reference it is
- * possible to modify this object.
+ * @param ctx the context as created by {@link #createContext(ChaincodeStub)}.
+ * @param result The object returned from the transaction function if any. As this is a Java object and therefore
+ * pass-by-reference it is possible to modify this object.
*/
default void afterTransaction(final Context ctx, final Object result) {
+ // Nothing by default
}
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRouter.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRouter.java
index 510f14988..d7b6f9e5d 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRouter.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRouter.java
@@ -6,6 +6,9 @@
package org.hyperledger.fabric.contract;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.logging.Logger;
import org.hyperledger.fabric.Logging;
import org.hyperledger.fabric.contract.execution.ExecutionFactory;
import org.hyperledger.fabric.contract.execution.ExecutionService;
@@ -25,18 +28,14 @@
import org.hyperledger.fabric.shim.ResponseUtils;
import org.hyperledger.fabric.traces.Traces;
-import java.io.IOException;
-import java.util.Properties;
-import java.util.logging.Logger;
-
/**
- * Router class routes Init/Invoke requests to contracts. Implements
- * {@link org.hyperledger.fabric.shim.Chaincode} interface.
+ * Router class routes Init/Invoke requests to contracts. Implements {@link org.hyperledger.fabric.shim.Chaincode}
+ * interface.
*
* @see ContractInterface
*/
public final class ContractRouter extends ChaincodeBase {
- private static Logger logger = Logger.getLogger(ContractRouter.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(ContractRouter.class.getName());
private final RoutingRegistry registry;
private final TypeRegistry typeRegistry;
@@ -47,14 +46,14 @@ public final class ContractRouter extends ChaincodeBase {
private final ExecutionService executor;
/**
- * Take the arguments from the cli, and initiate processing of cli options and
- * environment variables.
+ * Take the arguments from the cli, and initiate processing of cli options and environment variables.
*
- * Create the Contract scanner, and the Execution service
+ * Create the Contract scanner, and the Execution service
*
* @param args
*/
public ContractRouter(final String[] args) {
+ super();
super.initializeLogging();
super.processEnvironmentOptions();
super.processCommandLineOptions(args);
@@ -64,7 +63,7 @@ public ContractRouter(final String[] args) {
Metrics.initialize(props);
Traces.initialize(props);
- logger.fine("ContractRouter This will send the initial flow back to the peer
*
* @throws Exception
*/
+ @SuppressWarnings("PMD.AvoidCatchingGenericException")
void startRouting() {
try {
super.connectToPeer();
} catch (final Exception e) {
- logger.severe(() -> Logging.formatError(e));
- final ContractRuntimeException cre = new ContractRuntimeException("Unable to start routing", e);
- throw cre;
+ LOGGER.severe(() -> Logging.formatError(e));
+ throw new ContractRuntimeException("Unable to start routing", e);
}
}
+ @SuppressWarnings("PMD.AvoidCatchingThrowable")
private Response processRequest(final ChaincodeStub stub) {
- logger.info(() -> "Got invoke routing request");
+ LOGGER.info(() -> "Got invoke routing request");
try {
- if (stub.getStringArgs().size() > 0) {
- logger.info(() -> "Got the invoke request for:" + stub.getFunction() + " " + stub.getParameters());
- final InvocationRequest request = ExecutionFactory.getInstance().createRequest(stub);
- final TxFunction txFn = getRouting(request);
- logger.info(() -> "Got routing:" + txFn.getRouting());
- return executor.executeRequest(txFn, request, stub);
- } else {
+ if (stub.getStringArgs().isEmpty()) {
return ResponseUtils.newSuccessResponse();
}
+
+ LOGGER.info(() -> "Got the invoke request for:" + stub.getFunction() + " " + stub.getParameters());
+ final InvocationRequest request = ExecutionFactory.getInstance().createRequest(stub);
+ final TxFunction txFn = getRouting(request);
+ LOGGER.info(() -> "Got routing:" + txFn.getRouting());
+ return executor.executeRequest(txFn, request, stub);
} catch (final Throwable throwable) {
return ResponseUtils.newErrorResponse(throwable);
}
@@ -143,7 +141,7 @@ TxFunction getRouting(final InvocationRequest request) {
if (registry.containsRoute(request)) {
return registry.getTxFn(request);
} else {
- logger.fine(() -> "Namespace is " + request);
+ LOGGER.fine(() -> "Namespace is " + request);
final ContractDefinition contract = registry.getContract(request.getNamespace());
return contract.getUnknownRoute();
}
@@ -154,35 +152,35 @@ TxFunction getRouting(final InvocationRequest request) {
*
* @param args
*/
+ @SuppressWarnings("PMD.SignatureDeclareThrowsException")
public static void main(final String[] args) throws Exception {
final ContractRouter cfc = new ContractRouter(args);
cfc.findAllContracts();
- logger.fine(cfc.getRoutingRegistry().toString());
+ LOGGER.fine(() -> cfc.getRoutingRegistry().toString());
// Create the Metadata ahead of time rather than have to produce every
// time
MetadataBuilder.initialize(cfc.getRoutingRegistry(), cfc.getTypeRegistry());
- logger.info(() -> "Metadata follows:" + MetadataBuilder.debugString());
+ LOGGER.info(() -> "Metadata follows:" + MetadataBuilder.debugString());
// check if this should be running in client or server mode
if (cfc.isServer()) {
- logger.info("Starting chaincode as server");
- ChaincodeServer chaincodeServer = new NettyChaincodeServer(cfc,
- cfc.getChaincodeServerConfig());
+ LOGGER.info("Starting chaincode as server");
+ ChaincodeServer chaincodeServer = new NettyChaincodeServer(cfc, cfc.getChaincodeServerConfig());
chaincodeServer.start();
} else {
- logger.info("Starting chaincode as client");
+ LOGGER.info("Starting chaincode as client");
cfc.startRouting();
}
}
- protected TypeRegistry getTypeRegistry() {
+ TypeRegistry getTypeRegistry() {
return this.typeRegistry;
}
- protected RoutingRegistry getRoutingRegistry() {
+ RoutingRegistry getRoutingRegistry() {
return this.registry;
}
@@ -194,12 +192,11 @@ protected RoutingRegistry getRoutingRegistry() {
public void startRouterWithChaincodeServer(final ChaincodeServer chaincodeServer)
throws IOException, InterruptedException {
findAllContracts();
- logger.fine(getRoutingRegistry().toString());
+ LOGGER.fine(() -> getRoutingRegistry().toString());
MetadataBuilder.initialize(getRoutingRegistry(), getTypeRegistry());
- logger.info(() -> "Metadata follows:" + MetadataBuilder.debugString());
+ LOGGER.info(() -> "Metadata follows:" + MetadataBuilder.debugString());
chaincodeServer.start();
}
-
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRuntimeException.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRuntimeException.java
index 0fca449fd..78d559a26 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRuntimeException.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRuntimeException.java
@@ -8,25 +8,21 @@
import org.hyperledger.fabric.shim.ChaincodeException;
/**
- * Specific RuntimeException for events that occur in the calling and handling
- * of the Contracts, NOT within the contract logic itself.
- *
- * FUTURE At some future point we wish to add more diagnostic information
- * into this, for example current tx id
+ * Specific RuntimeException for events that occur in the calling and handling of the Contracts, NOT within the contract
+ * logic itself.
*
+ * FUTURE At some future point we wish to add more diagnostic information into this, for example current tx id
*/
public class ContractRuntimeException extends ChaincodeException {
+ /** Generated serial version id. */
+ private static final long serialVersionUID = -884373036398750450L;
- /**
- *
- * @param string
- */
+ /** @param string */
public ContractRuntimeException(final String string) {
super(string);
}
/**
- *
* @param string
* @param cause
*/
@@ -34,17 +30,8 @@ public ContractRuntimeException(final String string, final Throwable cause) {
super(string, cause);
}
- /**
- *
- * @param cause
- */
+ /** @param cause */
public ContractRuntimeException(final Throwable cause) {
super(cause);
}
-
- /**
- * Generated serial version id.
- */
- private static final long serialVersionUID = -884373036398750450L;
-
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contact.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contact.java
index c344b37b3..fb3e2fc9a 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contact.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contact.java
@@ -12,27 +12,19 @@
import java.lang.annotation.Target;
/**
- * Class level annotation that identifies this class as being a contact. Can be
- * populated with email, name and url fields.
- *
+ * Class level annotation that identifies this class as being a contact. Can be populated with email, name and url
+ * fields.
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface Contact {
- /**
- * @return String
- */
+ /** @return String */
String email() default "";
- /**
- * @return String
- */
+ /** @return String */
String name() default "";
- /**
- * @return String
- */
+ /** @return String */
String url() default "";
-
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contract.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contract.java
index d28987b26..8114170ec 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contract.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contract.java
@@ -12,19 +12,17 @@
import java.lang.annotation.Target;
/**
- * Class level annotation that identifies this class as being a contract. Can
- * supply information and an alternative name for the contract rather than the
- * classname
+ * Class level annotation that identifies this class as being a contract. Can supply information and an alternative name
+ * for the contract rather than the classname
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface Contract {
/**
- * The Info object can be supplied to provide additional information about the
- * contract.
+ * The Info object can be supplied to provide additional information about the contract.
*
- * Including title, description, version and license
+ * Including title, description, version and license
*
* @return Info object
*/
@@ -33,8 +31,8 @@
/**
* Contract name.
*
- * Normally the name of the class is used to refer to the contract (name without
- * package). This can be altered if wished.
+ * Normally the name of the class is used to refer to the contract (name without package). This can be altered if
+ * wished.
*
* @return Name of the contract to be used instead of the Classname
*/
@@ -43,14 +41,12 @@
/**
* Transaction Serializer Classname.
*
- * Fully Qualified Classname of the TRANSACTION serializer that should be used
- * with this contract.
+ * Fully Qualified Classname of the TRANSACTION serializer that should be used with this contract.
*
- * This is the serializer that is used to parse incoming transaction request
- * parameters and convert the return type
+ * This is the serializer that is used to parse incoming transaction request parameters and convert the return
+ * type
*
* @return Default serializer classname
*/
String transactionSerializer() default "org.hyperledger.fabric.contract.execution.JSONTransactionSerializer";
-
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/DataType.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/DataType.java
index 8799198d6..a671fcf0a 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/DataType.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/DataType.java
@@ -12,18 +12,15 @@
import java.lang.annotation.Target;
/**
- * Class level annotation indicating this class represents one of the complex
- * types that can be returned or passed to the transaction functions.
- *
- * These datatypes are used (within the current implementation) for determining
- * the data flow protocol from the Contracts to the SDK and for permitting a
- * fully formed Interface Definition to be created for the contract.
- *
- * Complex types can appear within this definition, and these are identified
- * using this annotation.
- *
- * FUTURE To take these annotations are also utilize them for leverage
- * storage
+ * Class level annotation indicating this class represents one of the complex types that can be returned or passed to
+ * the transaction functions.
+ *
+ * These datatypes are used (within the current implementation) for determining the data flow protocol from the
+ * Contracts to the SDK and for permitting a fully formed Interface Definition to be created for the contract.
+ *
+ * Complex types can appear within this definition, and these are identified using this annotation.
+ *
+ * FUTURE To take these annotations are also utilize them for leverage storage
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Default.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Default.java
index 683ba6686..f289e56ac 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Default.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Default.java
@@ -14,11 +14,9 @@
/**
* Default Contract.
*
- * Class level annotation that defines the contract that is the default
- * contract, and as such invoke of the transaction functions does not need to be
- * qualified by the contract name
+ * Class level annotation that defines the contract that is the default contract, and as such invoke of the
+ * transaction functions does not need to be qualified by the contract name
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
-public @interface Default {
-}
+public @interface Default {}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Info.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Info.java
index 8b1d05fdb..17d02e16c 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Info.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Info.java
@@ -15,41 +15,29 @@
/**
* Info Details
*
- *
- * Class level annotation that identifies this class as being an info object.
- * Can supply additional information about the contract, including title,
- * description, version, license and contact information.
- *
+ * Class level annotation that identifies this class as being an info object. Can supply additional information about
+ * the contract, including title, description, version, license and contact information.
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface Info {
- /**
- * @return String
- */
+ /** @return String */
String title() default "";
- /**
- * @return String
- */
+ /** @return String */
String description() default "";
- /**
- * @return String
- */
+ /** @return String */
String version() default "";
- /**
- * @return String
- */
+ /** @return String */
String termsOfService() default "";
/**
* License object that can be populated to include name and url.
*
* @return License object
- *
*/
License license() default @License();
@@ -57,8 +45,6 @@
* Contact object that can be populated with email, name and url fields.
*
* @return Contact object
- *
*/
Contact contact() default @Contact();
-
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/License.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/License.java
index 88989f022..a585f634e 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/License.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/License.java
@@ -12,24 +12,16 @@
import java.lang.annotation.Target;
/**
- * Class level annotation that identifies this class as being a license object.
- * Can be populated to include name and url.
- *
+ * Class level annotation that identifies this class as being a license object. Can be populated to include name and
+ * url.
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface License {
- /**
- *
- * @return String
- */
+ /** @return String */
String name() default "";
- /**
- *
- * @return String
- */
+ /** @return String */
String url() default "";
-
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Property.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Property.java
index 1b75fffbd..5a94e8dcc 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Property.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Property.java
@@ -14,10 +14,9 @@
/**
* Field and parameter level annotation defining a property of the class.
*
- * (identified by {@link DataType}) Can also be used on the parameters of
- * transaction functions
- *
- * Example of using this annotation
+ * (identified by {@link DataType}) Can also be used on the parameters of transaction functions
+ *
+ * Example of using this annotation
*
* This should annotate a class that implements the Serializer interface This should annotate a class that implements the Serializer interface
*/
@Retention(RUNTIME)
@Target({ElementType.TYPE, ElementType.TYPE_USE})
public @interface Serializer {
- /**
- * What is this serializer able to target?
- *
- */
+ /** What is this serializer able to target? */
enum TARGET {
- /**
- * Target transaction functions.
- */
+ /** Target transaction functions. */
TRANSACTION,
- /**
- * Target all elements.
- */
+ /** Target all elements. */
ALL
}
- /**
- *
- * @return Target of the serializer
- */
+ /** @return Target of the serializer */
TARGET target() default Serializer.TARGET.ALL;
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Transaction.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Transaction.java
index c9180ca46..3f41e3fbc 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Transaction.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Transaction.java
@@ -12,44 +12,35 @@
import java.lang.annotation.Target;
/**
- * Method level annotation indicating the method to be a callable transaction
- * function.
- *
- * These functions are called in client SDKs by the combination of
+ * Method level annotation indicating the method to be a callable transaction function.
+ *
+ * These functions are called in client SDKs by the combination of
*
* TRUE indicates that this function is intended to be called with the 'submit'
- * semantics TRUE indicates that this function is intended to be called with the 'submit' semantics
*
- * FALSE indicates that this is intended to be called with the evaluate
- * semantics FALSE indicates that this is intended to be called with the evaluate semantics
*
* @return boolean, default is true
* @deprecated Please use intent
@@ -59,19 +50,20 @@ enum TYPE {
/**
* What are submit semantics for this transaction.
+ *
* Service that executes {@link InvocationRequest} (wrapped Init/Invoke + extra data) using routing information
*/
public interface ExecutionService {
/**
- *
* @param txFn
* @param req
* @param stub
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/InvocationRequest.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/InvocationRequest.java
index 6978e0378..92c478c16 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/InvocationRequest.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/InvocationRequest.java
@@ -11,33 +11,21 @@
/**
* Invocation Request.
*
- * All information needed to find
- * {@link org.hyperledger.fabric.contract.annotation.Contract} and invoke the
- * request.
+ * All information needed to find {@link org.hyperledger.fabric.contract.annotation.Contract} and invoke the request.
*/
public interface InvocationRequest {
- /**
- *
- */
+ /** */
String DEFAULT_NAMESPACE = "default";
- /**
- * @return Namespace
- */
+ /** @return Namespace */
String getNamespace();
- /**
- * @return Method
- */
+ /** @return Method */
String getMethod();
- /**
- * @return Args as byte array
- */
+ /** @return Args as byte array */
List We need to take the JSON array, and if there are complex datatypes within it ensure that they don't get
+ * spurious JSON properties appearing
*
- * This method needs to be general so has to copy with nested arrays and with
- * primitive and Object types
+ * This method needs to be general so has to copy with nested arrays and with primitive and Object types
*
* @param jsonArray incoming array
- * @param ts Schema to normalise to
+ * @param ts Schema to normalise to
* @return JSONArray
*/
+ @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
private JSONArray normalizeArray(final JSONArray jsonArray, final TypeSchema ts) {
JSONArray normalizedArray;
@@ -119,22 +109,12 @@ private JSONArray normalizeArray(final JSONArray jsonArray, final TypeSchema ts)
final TypeSchema items = ts.getItems();
final String type = items.getType();
- if (type != null && type != "array") {
- // primitive - can return this directly
- normalizedArray = jsonArray;
- } else if (type != null && type == "array") {
- // nested arrays, get the type of what it makes up
- // Need to loop over all elements and normalize each one
- normalizedArray = new JSONArray();
- for (int i = 0; i < jsonArray.length(); i++) {
- normalizedArray.put(i, normalizeArray(jsonArray.getJSONArray(i), items));
- }
- } else {
+ if (null == type) {
// get the permitted propeties in the type,
// then loop over the array and ensure they are correct
final DataTypeDefinition dtd = this.typeRegistry.getDataType(items);
final Set For other types the parameter is passed directly back
*
* @param primitive class for the primitive
* @return Class for the Object variant
*/
private Class> mapPrimitive(final Class> primitive) {
- String primitiveType;
- final boolean isArray = primitive.isArray();
- if (isArray) {
- primitiveType = primitive.getComponentType().getName();
- } else {
- primitiveType = primitive.getName();
+ if (primitive.isArray()) {
+ return mapArrayPrimitive(primitive);
}
- switch (primitiveType) {
- case "int":
- return isArray ? Integer[].class : Integer.class;
- case "long":
- return isArray ? Long[].class : Long.class;
- case "float":
- return isArray ? Float[].class : Float.class;
- case "double":
- return isArray ? Double[].class : Double.class;
- case "short":
- return isArray ? Short[].class : Short.class;
- case "byte":
- return isArray ? Byte[].class : Byte.class;
- case "char":
- return isArray ? Character[].class : Character.class;
- case "boolean":
- return isArray ? Boolean[].class : Boolean.class;
- default:
- return primitive;
+ return mapBasicPrimitive(primitive);
+ }
+
+ private Class> mapArrayPrimitive(final Class> primitive) {
+ switch (primitive.getComponentType().getName()) {
+ case "int":
+ return Integer[].class;
+ case "long":
+ return Long[].class;
+ case "float":
+ return Float[].class;
+ case "double":
+ return Double[].class;
+ case "short":
+ return Short[].class;
+ case "byte":
+ return Byte[].class;
+ case "char":
+ return Character[].class;
+ case "boolean":
+ return Boolean[].class;
+ default:
+ return primitive;
}
}
- /*
- * Internal method to do the conversion
- */
- private Object convert(final String stringData, final TypeSchema ts) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
- logger.debug(() -> "Schema to convert is " + ts);
+ private Class> mapBasicPrimitive(final Class> primitive) {
+ switch (primitive.getName()) {
+ case "int":
+ return Integer.class;
+ case "long":
+ return Long.class;
+ case "float":
+ return Float.class;
+ case "double":
+ return Double.class;
+ case "short":
+ return Short.class;
+ case "byte":
+ return Byte.class;
+ case "char":
+ return Character.class;
+ case "boolean":
+ return Boolean.class;
+ default:
+ return primitive;
+ }
+ }
+
+ /** Internal method to do the conversion */
+ private Object convert(final String stringData, final TypeSchema ts)
+ throws IllegalAccessException, InstantiationException {
+ LOGGER.debug(() -> "Schema to convert is " + ts);
+
String type = ts.getType();
+
String format = null;
- Object value = null;
if (type == null) {
type = "object";
final String ref = ts.getRef();
- format = ref.substring(ref.lastIndexOf("/") + 1);
+ format = ref.substring(ref.lastIndexOf('/') + 1);
}
- if (type.contentEquals("string")) {
- final String strformat = ts.getFormat();
- if (strformat != null && strformat.contentEquals("uint16")) {
- value = stringData.charAt(0);
- } else {
- value = stringData;
- }
- } else if (type.contentEquals("integer")) {
- final String intFormat = ts.getFormat();
- switch (intFormat) {
+ switch (type) {
+ case "string":
+ return convertString(stringData, ts);
+ case "integer":
+ return convertInteger(stringData, ts);
+ case "number":
+ return convertNumber(stringData, ts);
+ case "boolean":
+ return Boolean.parseBoolean(stringData);
+ case "object":
+ return createComponentInstance(format, stringData, ts);
+ case "array":
+ return convertArray(stringData, ts);
+ default:
+ return null;
+ }
+ }
+
+ private Object convertArray(final String stringData, final TypeSchema ts)
+ throws IllegalAccessException, InstantiationException {
+ final JSONArray jsonArray = new JSONArray(stringData);
+ final TypeSchema itemSchema = ts.getItems();
+
+ // note here that the type has to be converted in the case of primitives
+ final Object[] data = (Object[])
+ Array.newInstance(mapPrimitive(itemSchema.getTypeClass(this.typeRegistry)), jsonArray.length());
+ for (int i = 0; i < jsonArray.length(); i++) {
+ final Object convertedData = convert(jsonArray.get(i).toString(), itemSchema);
+ data[i] = convertedData;
+ }
+
+ return data;
+ }
+
+ private Object convertNumber(final String stringData, final TypeSchema ts) {
+ if ("float".equals(ts.getFormat())) {
+ return Float.parseFloat(stringData);
+ }
+
+ return Double.parseDouble(stringData);
+ }
+
+ private Object convertInteger(final String stringData, final TypeSchema ts) {
+ switch (ts.getFormat()) {
case "int32":
- value = Integer.parseInt(stringData);
- break;
+ return Integer.parseInt(stringData);
case "int8":
- value = Byte.parseByte(stringData);
- break;
+ return Byte.parseByte(stringData);
case "int16":
- value = Short.parseShort(stringData);
- break;
+ return Short.parseShort(stringData);
case "int64":
- value = Long.parseLong(stringData);
- break;
+ return Long.parseLong(stringData);
default:
- throw new RuntimeException("Unknown format for integer " + intFormat);
- }
-
- } else if (type.contentEquals("number")) {
- final String numFormat = ts.getFormat();
- if (numFormat.contentEquals("float")) {
- value = Float.parseFloat(stringData);
- } else {
- value = Double.parseDouble(stringData);
- }
- } else if (type.contentEquals("boolean")) {
- value = Boolean.parseBoolean(stringData);
- } else if (type.contentEquals("object")) {
- value = createComponentInstance(format, stringData, ts);
- } else if (type.contentEquals("array")) {
- final JSONArray jsonArray = new JSONArray(stringData);
- final TypeSchema itemSchema = ts.getItems();
-
- // note here that the type has to be converted in the case of primitives
- final Object[] data = (Object[]) Array.newInstance(mapPrimitive(itemSchema.getTypeClass(this.typeRegistry)), jsonArray.length());
- for (int i = 0; i < jsonArray.length(); i++) {
- final Object convertedData = convert(jsonArray.get(i).toString(), itemSchema);
- data[i] = convertedData;
- }
- value = data;
+ throw new IllegalArgumentException("Unknown format for integer " + ts.getFormat());
+ }
+ }
+ private Object convertString(final String stringData, final TypeSchema ts) {
+ if ("uint16".equals(ts.getFormat())) {
+ return stringData.charAt(0);
}
- return value;
+
+ return stringData;
}
/**
* Create new instance of the specificied object from the supplied JSON String.
*
- * @param format Details of the format needed
+ * @param format Details of the format needed
* @param jsonString JSON string
- * @param ts TypeSchema
+ * @param ts TypeSchema
* @return new object
*/
+ @SuppressWarnings("PMD.AvoidAccessibilityAlteration")
Object createComponentInstance(final String format, final String jsonString, final TypeSchema ts) {
final DataTypeDefinition dtd = this.typeRegistry.getDataType(format);
Object obj;
try {
obj = dtd.getTypeClass().getDeclaredConstructor().newInstance();
- } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e1) {
+ } catch (IllegalAccessException
+ | InstantiationException
+ | InvocationTargetException
+ | NoSuchMethodException e1) {
throw new ContractRuntimeException("Unable to to create new instance of type", e1);
}
@@ -302,20 +324,20 @@ Object createComponentInstance(final String format, final String jsonString, fin
ts.validate(json);
try {
final Map When the objects are (logically) transferred from the Client application to the Contract resulting in a
+ * transaction function being invoked. Typically this is JSON, hence a default JSON parser is provided.
*
- * The JSONTransactionSerializer can be extended if needed
+ * The JSONTransactionSerializer can be extended if needed
*/
public interface SerializerInterface {
@@ -34,10 +32,8 @@ public interface SerializerInterface {
* Take the byte buffer and return the object as required.
*
* @param buffer Byte buffer from the wire
- * @param ts TypeSchema representing the type
- *
+ * @param ts TypeSchema representing the type
* @return Object created; relies on Java auto-boxing for primitives
*/
Object fromBuffer(byte[] buffer, TypeSchema ts);
-
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/impl/ContractExecutionService.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/impl/ContractExecutionService.java
index e96111078..509f60d90 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/impl/ContractExecutionService.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/impl/ContractExecutionService.java
@@ -6,7 +6,11 @@
package org.hyperledger.fabric.contract.execution.impl;
- import org.hyperledger.fabric.contract.Context;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+import org.hyperledger.fabric.contract.Context;
import org.hyperledger.fabric.contract.ContractInterface;
import org.hyperledger.fabric.contract.ContractRuntimeException;
import org.hyperledger.fabric.contract.annotation.Serializer;
@@ -22,30 +26,22 @@
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.hyperledger.fabric.shim.ResponseUtils;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
public class ContractExecutionService implements ExecutionService {
- private static Logger logger = Logger.getLogger(ContractExecutionService.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(ContractExecutionService.class.getName());
private final SerializerRegistryImpl serializers;
- /**
- * @param serializers
- */
+ /** @param serializers */
public ContractExecutionService(final SerializerRegistryImpl serializers) {
this.serializers = serializers;
}
- /**
- *
- */
+ /** */
@Override
- public Chaincode.Response executeRequest(final TxFunction txFn, final InvocationRequest req, final ChaincodeStub stub) {
- logger.fine(() -> "Routing Request" + txFn);
+ public Chaincode.Response executeRequest(
+ final TxFunction txFn, final InvocationRequest req, final ChaincodeStub stub) {
+ LOGGER.fine(() -> "Routing Request" + txFn);
final TxFunction.Routing rd = txFn.getRouting();
Chaincode.Response response;
@@ -83,21 +79,22 @@ public Chaincode.Response executeRequest(final TxFunction txFn, final Invocation
}
private byte[] convertReturn(final Object obj, final TxFunction txFn) {
- final SerializerInterface serializer = serializers.getSerializer(
- txFn.getRouting().getSerializerName(), Serializer.TARGET.TRANSACTION);
+ final SerializerInterface serializer =
+ serializers.getSerializer(txFn.getRouting().getSerializerName(), Serializer.TARGET.TRANSACTION);
final TypeSchema ts = txFn.getReturnSchema();
return serializer.toBuffer(obj, ts);
}
private List
- * {@code
+ *
*/
public class Context {
- /**
- *
- */
+ /** */
protected ChaincodeStub stub;
- /**
- *
- */
+ /** */
protected ClientIdentity clientIdentity;
/**
@@ -60,18 +49,12 @@ public Context(final ChaincodeStub stub) {
}
}
- /**
- *
- * @return ChaincodeStub instance to use
- */
+ /** @return ChaincodeStub instance to use */
public ChaincodeStub getStub() {
return this.stub;
}
- /**
- *
- * @return ClientIdentity object to use
- */
+ /** @return ClientIdentity object to use */
public ClientIdentity getClientIdentity() {
return this.clientIdentity;
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContextFactory.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContextFactory.java
index b282dc2db..68514adb1 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContextFactory.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContextFactory.java
@@ -8,32 +8,20 @@
import org.hyperledger.fabric.shim.ChaincodeStub;
-/**
- * Factory to create {@link Context} from {@link ChaincodeStub} by wrapping stub
- * with dynamic proxy.
- */
+/** Factory to create {@link Context} from {@link ChaincodeStub} by wrapping stub with dynamic proxy. */
public final class ContextFactory {
- private static ContextFactory cf;
+ private static final ContextFactory INSTANCE = new ContextFactory();
- /**
- *
- * @return ContextFactory
- */
- public static synchronized ContextFactory getInstance() {
- if (cf == null) {
- cf = new ContextFactory();
- }
- return cf;
+ /** @return ContextFactory */
+ public static ContextFactory getInstance() {
+ return INSTANCE;
}
/**
- *
* @param stub
* @return Context
*/
public Context createContext(final ChaincodeStub stub) {
- final Context newContext = new Context(stub);
- return newContext;
+ return new Context(stub);
}
-
}
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractInterface.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractInterface.java
index 9ef0352e1..e1db9de43 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractInterface.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractInterface.java
@@ -12,52 +12,44 @@
/**
* All Contracts should implement this interface, in addition to the
* {@linkplain org.hyperledger.fabric.contract.annotation.Contract} annotation.
- * {@code
* public MyContext extends Context {
*
* public MyContext(ChaincodeStub stub) {
@@ -31,19 +26,13 @@
* }
* }
*
- *}
- *
- *
+ * }
* createContext() -> beforeTransaction() -> the transaction function -> afterTransaction()
*
- *
*
@@ -36,9 +35,8 @@
public @interface Property {
/**
- * Allows each property to be defined a detail set of rules to determine the
- * valid types of this data. The format follows the syntax of the OpenAPI Schema
- * object.
+ * Allows each property to be defined a detail set of rules to determine the valid types of this data. The format
+ * follows the syntax of the OpenAPI Schema object.
*
* @return String array of the key-value pairs of the schema
*/
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Serializer.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Serializer.java
index 10ff45d65..37d91fc9b 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Serializer.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Serializer.java
@@ -12,32 +12,22 @@
import java.lang.annotation.Target;
/**
- * Class level annotation that defines the serializer that should be used to
- * convert objects to and from the wire format.
+ * Class level annotation that defines the serializer that should be used to convert objects to and from the wire
+ * format.
*
- *
* [contractname]:[transactioname]
*
*
- * Unless specified otherwise, the contract name is the class name (without
- * package) and the transaction name is the method name.
+ * Unless specified otherwise, the contract name is the class name (without package) and the transaction name is the
+ * method name.
*/
@Retention(RUNTIME)
@Target(METHOD)
public @interface Transaction {
- /**
- * The intended invocation style for a transaction function.
- */
+ /** The intended invocation style for a transaction function. */
enum TYPE {
- /**
- * Transaction is used to submit updates to the ledger.
- */
+ /** Transaction is used to submit updates to the ledger. */
SUBMIT,
- /**
- * Transaction is evaluated to query information from the ledger.
- */
+ /** Transaction is evaluated to query information from the ledger. */
EVALUATE
}
/**
* Submit semantics.
*
- *
- *
+ *
* @return submit semantics
*/
TYPE intent() default Transaction.TYPE.SUBMIT;
/**
- * The name of the callable transaction if it should be different to the method
- * name.
+ * The name of the callable transaction if it should be different to the method name.
*
* @return the transaction name
*/
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionFactory.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionFactory.java
index 0d437c5ea..3cd7a5fcb 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionFactory.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionFactory.java
@@ -12,16 +12,11 @@
import org.hyperledger.fabric.shim.ChaincodeStub;
public class ExecutionFactory {
- private static ExecutionFactory rf;
+ private static final ExecutionFactory INSTANCE = new ExecutionFactory();
- /**
- * @return ExecutionFactory
- */
+ /** @return ExecutionFactory */
public static ExecutionFactory getInstance() {
- if (rf == null) {
- rf = new ExecutionFactory();
- }
- return rf;
+ return INSTANCE;
}
/**
diff --git a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionService.java b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionService.java
index ef0b97192..8c8596808 100644
--- a/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionService.java
+++ b/fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionService.java
@@ -13,13 +13,11 @@
/**
* ExecutionService.
*
- * Service that executes {@link InvocationRequest} (wrapped Init/Invoke + extra
- * data) using routing information
+ *