This repository has been archived by the owner on Jul 26, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 214
Coding Style
Philipp C. Heckel edited this page Aug 13, 2014
·
6 revisions
If you work in a group, it's important to follow a few shared concept and rules when it comes to coding style. We tried to assemble a few here. If in doubt, use the Eclipse auto format functionality using Ctrl+Shift+F.
- Use tabs, not spaces
-
else
/else if
/try
/catch
/finally
-statements should be in their own line - Before and after
else
/else if
/try
/catch
/finally
-statements, add an empty line - Before and after curly brackets (
{
and}
), add an empty line - Better more new lines than fewer new lines
- Long lines are okay (150 chars)
- Methods should be <= 20 lines
- All
if
/for
/while
-statements need curly brackets (no one-liners), so instead ofif (hasConflict) return;
, writeif (hasConflict) {\n return;\n }\n
- Avoid
?:
-syntax unless the statement is really easy - Avoid dependencies to other packages
- Avoid using Singletons
- Use understandable method/variable names, long method names are okay:
public void go() { ... // Bad! public void findFirstConflictingDatabaseVersionHeader() { ... // Good! int dbvidx = ...; // Bad int databaseVersionHeaderIndex = ...; // Good
- Avoid long
boolean
expressions inif
-statements; use understandable variables instead:boolean existingAndWritableDirectory = ...; if (existingAndWritableDirectory) { ...
- JavaDoc should exist for all classes and important methods
- JavaDoc can contain HTML tags, lists should use
<ul>
/<ol>
- JavaDoc
{@link SomeClass}
references should be used, but only if they do not need newimport
s -
TODO
/FIXME
markers should be used with a relevance marker:TODO [low|medium|high]
return "syncany://storage/1/" + ...; // TODO [low] Move syncany://-link to to constant
This code is taken from the InitOperation.
/*
* Syncany, www.syncany.org
* Copyright (C) 2011-2013 Philipp C. Heckel <[email protected]>
*
* (...)
*/
package org.syncany.operations;
import java.io.ByteArrayInputStream;
// (...)
/**
* The init operation initializes a new repository at a given remote storage
* location. Its responsibilities include:
*
* <ul>
* <li>Generating a master key from the user password (if encryption is enabled)
* using the {@link CipherUtil#createMasterKey(String) createMasterKey()} method</li>
* <li>Creating the local Syncany folder structure in the local directory (.syncany
* folder and the sub-structure).</li>
* <li>Initializing the remote storage (creating folder-structure, if necessary)
* using the transfer manager's {@link TransferManager#init()} method.</li>
* <li>Creating a new repo and master file using {@link RepoTO} and {@link MasterTO},
* saving them locally and uploading them to the remote repository.</li>
* </ul>
*
* @author Philipp C. Heckel <[email protected]>
*/
public class InitOperation extends AbstractInitOperation {
private static final Logger logger = Logger.getLogger(InitOperation.class.getSimpleName());
private InitOperationOptions options;
private InitOperationListener listener;
private TransferManager transferManager;
public InitOperation(InitOperationOptions options, InitOperationListener listener) {
super(null);
this.options = options;
this.listener = listener;
}
@Override
public InitOperationResult execute() throws Exception {
logger.log(Level.INFO, "");
logger.log(Level.INFO, "Running 'Init'");
logger.log(Level.INFO, "--------------------------------------------");
transferManager = createTransferManager(options.getConfigTO().getConnectionTO());
if (repoFileExistsOnRemoteStorage(transferManager)) {
throw new Exception("Repo already exists. Use 'connect' command to connect to existing repository.");
}
// Create local .syncany directory
File appDir = createAppDirs(options.getLocalDir());
File configFile = new File(appDir + "/" + Config.FILE_CONFIG);
File repoFile = new File(appDir + "/" + Config.FILE_REPO);
File masterFile = new File(appDir + "/" + Config.FILE_MASTER);
// Save config.xml and repo file
String shareLink = null;
boolean shareLinkEncrypted = false;
if (options.isEncryptionEnabled()) {
SaltedSecretKey masterKey = createMasterKeyFromPassword(options.getPassword()); // This takes looong!
options.getConfigTO().setMasterKey(masterKey);
writeXmlFile(new MasterTO(masterKey.getSalt()), masterFile);
writeEncryptedXmlFile(options.getRepoTO(), repoFile, options.getCipherSpecs(), masterKey);
shareLink = getEncryptedLink(options.getConfigTO().getConnectionTO(), options.getCipherSpecs(), masterKey);
shareLinkEncrypted = true;
}
else {
writeXmlFile(options.getRepoTO(), repoFile);
shareLink = getPlaintextLink(options.getConfigTO().getConnectionTO());
shareLinkEncrypted = false;
}
writeXmlFile(options.getConfigTO(), configFile);
writeXmlFile(options.getRepoTO(), new File(repoFile + "-NOT-USED.xml")); // TODO [low] Remove this, not used
// Make remote changes
transferManager.init();
if (masterFile.exists()) {
uploadMasterFile(masterFile, transferManager);
}
uploadRepoFile(repoFile, transferManager);
return new InitOperationResult(shareLink, shareLinkEncrypted);
}
private SaltedSecretKey createMasterKeyFromPassword(String masterPassword) throws Exception {
if (listener != null) {
listener.notifyGenerateMasterKey();
}
SaltedSecretKey masterKey = CipherUtil.createMasterKey(masterPassword);
return masterKey;
}
protected boolean repoFileExistsOnRemoteStorage(TransferManager transferManager) throws Exception {
try {
Map<String, RepoRemoteFile> repoFileList = transferManager.list(RepoRemoteFile.class);
if (repoFileList.containsKey("repo")) {
return true;
}
else {
return false;
}
}
catch (Exception e) {
throw new Exception("Unable to connect to repository.", e);
}
}
private void uploadMasterFile(File masterFile, TransferManager transferManager) throws Exception {
transferManager.upload(masterFile, new MasterRemoteFile());
}
private void uploadRepoFile(File repoFile, TransferManager transferManager) throws Exception {
transferManager.upload(repoFile, new RepoRemoteFile());
}
private String getEncryptedLink(ConnectionTO connectionTO, List<CipherSpec> cipherSuites, SaltedSecretKey masterKey) throws Exception {
ByteArrayOutputStream plaintextOutputStream = new ByteArrayOutputStream();
Serializer serializer = new Persister();
serializer.write(connectionTO, plaintextOutputStream);
byte[] masterKeySalt = masterKey.getSalt();
String masterKeySaltEncodedStr = new String(Base64.encodeBase64(masterKeySalt, false));
byte[] encryptedConnectionBytes = CipherUtil.encrypt(new ByteArrayInputStream(plaintextOutputStream.toByteArray()), cipherSuites, masterKey);
String encryptedEncodedStorageXml = new String(Base64.encodeBase64(encryptedConnectionBytes, false));
return "syncany://storage/1/" + masterKeySaltEncodedStr + "-" + encryptedEncodedStorageXml; // TODO [low] Move to constant
}
private String getPlaintextLink(ConnectionTO connectionTO) throws Exception {
ByteArrayOutputStream plaintextOutputStream = new ByteArrayOutputStream();
Serializer serializer = new Persister();
serializer.write(connectionTO, plaintextOutputStream);
byte[] plaintextStorageXml = plaintextOutputStream.toByteArray();
String plaintextEncodedStorageXml = new String(Base64.encodeBase64(plaintextStorageXml, false));
return "syncany://storage/1/not-encrypted/" + plaintextEncodedStorageXml; // TODO [low] Move to constant
}
public static interface InitOperationListener {
public void notifyGenerateMasterKey();
}
public static class InitOperationOptions implements OperationOptions {
private File localDir;
private ConfigTO configTO;
private RepoTO repoTO;
private boolean encryptionEnabled;
private List<CipherSpec> cipherSpecs;
private String password;
public File getLocalDir() {
return localDir;
}
// (...)
}
public class InitOperationResult implements OperationResult {
private String shareLink;
private boolean shareLinkEncrypted;
// (...)
}
}