├── .gitignore ├── README.md ├── aa ├── db-diagram.png ├── examples └── mc-vfs-gettingstarted │ ├── nbactions.xml │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── com │ │ └── gettingstarted │ │ └── web │ │ └── VfsController.java │ ├── resources │ ├── database.xml │ ├── default.properties │ ├── ehcache.xml │ ├── log4j.properties │ ├── milton.license.properties │ ├── milton.license.sig │ ├── miltonContext.xml │ └── rootContext.xml │ └── webapp │ ├── WEB-INF │ └── web.xml │ └── templates │ └── directory.jsp ├── milton-cloud-sync-app ├── application │ ├── nb-configuration.xml │ ├── pom.xml │ ├── src │ │ └── test │ │ │ └── java │ │ │ └── io │ │ │ └── milton │ │ │ └── ApplicationTest.java │ └── ~ │ │ └── syncdb.h2.db ├── branding │ ├── pom.xml │ └── src │ │ └── main │ │ ├── nbm-branding │ │ ├── core │ │ │ └── core.jar │ │ │ │ └── org │ │ │ │ └── netbeans │ │ │ │ └── core │ │ │ │ └── startup │ │ │ │ ├── Bundle.properties │ │ │ │ ├── frame.gif │ │ │ │ ├── frame32.gif │ │ │ │ ├── frame48.gif │ │ │ │ └── splash.gif │ │ └── modules │ │ │ ├── org-netbeans-core-windows.jar │ │ │ └── org │ │ │ │ └── netbeans │ │ │ │ └── core │ │ │ │ └── windows │ │ │ │ ├── Bundle.properties │ │ │ │ └── view │ │ │ │ └── ui │ │ │ │ └── Bundle.properties │ │ │ └── org-netbeans-core.jar │ │ │ └── org │ │ │ └── netbeans │ │ │ └── core │ │ │ └── ui │ │ │ └── Bundle.properties │ │ ├── nbm │ │ └── manifest.mf │ │ └── resources │ │ └── io │ │ └── milton │ │ └── branding │ │ └── Bundle.properties ├── milton-cloud-tool │ ├── pom.xml │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── guiTool │ │ │ │ ├── Helper.java │ │ │ │ ├── SyncToolTopComponent.form │ │ │ │ ├── SyncToolTopComponent.java │ │ │ │ ├── addJob.form │ │ │ │ ├── addJob.java │ │ │ │ ├── base.java │ │ │ │ ├── updateJob.form │ │ │ │ └── updateJob.java │ │ │ ├── nbm │ │ │ └── manifest.mf │ │ │ └── resources │ │ │ ├── Bundle.properties │ │ │ └── images │ │ │ ├── logo-dark.png │ │ │ └── upload.png │ └── ~ │ │ ├── syncdb.h2.db │ │ └── syncdb.trace.db └── pom.xml ├── milton-cloud-sync ├── Key ├── nbactions.xml ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ ├── com │ │ │ │ ├── bradmcevoy │ │ │ │ │ ├── io │ │ │ │ │ │ ├── Base64Coder.java │ │ │ │ │ │ ├── ChunkStore.java │ │ │ │ │ │ ├── ChunkWriter.java │ │ │ │ │ │ ├── ChunkingInputStream.java │ │ │ │ │ │ ├── ChunkingOutputStream.java │ │ │ │ │ │ ├── ReadingException.java │ │ │ │ │ │ ├── StreamToStream.java │ │ │ │ │ │ └── WritingException.java │ │ │ │ │ ├── utils │ │ │ │ │ │ ├── DateUtils.java │ │ │ │ │ │ ├── ElementList.java │ │ │ │ │ │ ├── FileUtils.java │ │ │ │ │ │ ├── IntegerUtils.java │ │ │ │ │ │ ├── StreamReader.java │ │ │ │ │ │ ├── StreamWriter.java │ │ │ │ │ │ ├── StringUtils.java │ │ │ │ │ │ ├── TypeUtils.java │ │ │ │ │ │ ├── With.java │ │ │ │ │ │ └── entities.properties │ │ │ │ │ └── version │ │ │ │ │ │ ├── Block.java │ │ │ │ │ │ ├── BlockStore.java │ │ │ │ │ │ └── VersioningOutputStream.java │ │ │ │ └── ettrema │ │ │ │ │ ├── common │ │ │ │ │ ├── Service.java │ │ │ │ │ └── Withee.java │ │ │ │ │ ├── config │ │ │ │ │ ├── CatalogConfigurator.java │ │ │ │ │ └── ConfigurationException.java │ │ │ │ │ ├── context │ │ │ │ │ ├── Accessor.java │ │ │ │ │ ├── BeanFactory.java │ │ │ │ │ ├── BeanLocator.java │ │ │ │ │ ├── BeanWrapper.java │ │ │ │ │ ├── ClassBeanLocator.java │ │ │ │ │ ├── ClassNotInContextException.java │ │ │ │ │ ├── Context.java │ │ │ │ │ ├── Contextual.java │ │ │ │ │ ├── CtxJdbcConnectionFactory.java │ │ │ │ │ ├── CtxRootFolderFactory.java │ │ │ │ │ ├── Dependent.java │ │ │ │ │ ├── Executable.java │ │ │ │ │ ├── Executable2.java │ │ │ │ │ ├── Factory.java │ │ │ │ │ ├── FactoryCatalog.java │ │ │ │ │ ├── ListFactory.java │ │ │ │ │ ├── PostgresUtils.java │ │ │ │ │ ├── ReferenceBeanLocator.java │ │ │ │ │ ├── Registration.java │ │ │ │ │ ├── RemovalCallback.java │ │ │ │ │ ├── RequestContext.java │ │ │ │ │ ├── RootContext.java │ │ │ │ │ ├── RootContextLocator.java │ │ │ │ │ ├── SimpleBeanLocator.java │ │ │ │ │ ├── SingletonFactory.java │ │ │ │ │ ├── SpringContextFactory.java │ │ │ │ │ ├── SpringFactory.java │ │ │ │ │ └── date │ │ │ │ │ │ └── CtxDateFormatFactory.java │ │ │ │ │ └── db │ │ │ │ │ ├── SqlBuilder.java │ │ │ │ │ ├── Table.java │ │ │ │ │ ├── TableCreatorService.java │ │ │ │ │ ├── TableDefinitionSource.java │ │ │ │ │ ├── TableXmlHelper.java │ │ │ │ │ ├── UseConnection.java │ │ │ │ │ ├── dialects │ │ │ │ │ ├── Dialect.java │ │ │ │ │ ├── H2Dialect.java │ │ │ │ │ ├── HqlDialect.java │ │ │ │ │ └── PostgresDialect.java │ │ │ │ │ └── types │ │ │ │ │ ├── BinaryType.java │ │ │ │ │ ├── CharacterType.java │ │ │ │ │ ├── CharacterVaryingType.java │ │ │ │ │ ├── FieldType.java │ │ │ │ │ ├── FieldTypes.java │ │ │ │ │ ├── Float8Type.java │ │ │ │ │ ├── IntegerType.java │ │ │ │ │ ├── LongType.java │ │ │ │ │ └── TimestampType.java │ │ │ └── io │ │ │ │ └── milton │ │ │ │ └── sync │ │ │ │ ├── Archiver.java │ │ │ │ ├── DbInitialiser.java │ │ │ │ ├── DeltaListener.java │ │ │ │ ├── DirWalker.java │ │ │ │ ├── HttpBlobStore.java │ │ │ │ ├── HttpBloomFilterHashCache.java │ │ │ │ ├── HttpHashStore.java │ │ │ │ ├── HttpUtils.java │ │ │ │ ├── JdbcHashCache.java │ │ │ │ ├── JdbcSyncStatusStore.java │ │ │ │ ├── MemoryHashCache.java │ │ │ │ ├── MinimalPutsBlobStore.java │ │ │ │ ├── MinimalPutsHashStore.java │ │ │ │ ├── SpliffySync.java │ │ │ │ ├── SwingConflictResolver.java │ │ │ │ ├── SyncCommand.java │ │ │ │ ├── SyncJob.java │ │ │ │ ├── SyncStatusStore.java │ │ │ │ ├── Syncer.java │ │ │ │ ├── SyncingDeltaListener.java │ │ │ │ ├── Utils.java │ │ │ │ ├── WriteThroughBlobStore.java │ │ │ │ ├── WriteThroughHashStore.java │ │ │ │ ├── event │ │ │ │ ├── DownloadSyncEvent.java │ │ │ │ ├── EventUtils.java │ │ │ │ ├── FileChangedEvent.java │ │ │ │ ├── FinishedSyncEvent.java │ │ │ │ ├── ScanEvent.java │ │ │ │ ├── TransferProgressEvent.java │ │ │ │ └── UploadSyncEvent.java │ │ │ │ └── triplets │ │ │ │ ├── BerkeleyDbFileHashCache.java │ │ │ │ ├── BlobDao.java │ │ │ │ ├── BlobUtils.java │ │ │ │ ├── BlockingBlobStore.java │ │ │ │ ├── BlockingHashStore.java │ │ │ │ ├── CrcDao.java │ │ │ │ ├── DeltaGenerator.java │ │ │ │ ├── DirWalker.java │ │ │ │ ├── FastParser.java │ │ │ │ ├── FileSystemWatchingService.java │ │ │ │ ├── FileUpdatingMergingDeltaListener.java │ │ │ │ ├── HttpTripletStore.java │ │ │ │ ├── JdbcLocalTripletStore.java │ │ │ │ ├── MemoryLocalTripletStore.java │ │ │ │ ├── MemorySyncHashCache.java │ │ │ │ ├── OneWayMergingDeltaListener.java │ │ │ │ ├── ParentHashAwareTripletStore.java │ │ │ │ ├── PausableTripletStore.java │ │ │ │ ├── SyncHashCache.java │ │ │ │ └── TripletStore.java │ │ └── resources │ │ │ ├── Images │ │ │ ├── logo-dark.png │ │ │ └── upload.png │ │ │ └── log4j.properties │ └── test │ │ ├── java │ │ └── io │ │ │ └── milton │ │ │ └── sync │ │ │ └── triplets │ │ │ └── DeltaGeneratorTest.java │ │ └── resources │ │ ├── branch1 │ │ ├── a │ │ │ ├── a-changed.txt │ │ │ ├── a-deleted.txt │ │ │ └── a-not-changed.txt │ │ └── c │ │ │ └── c-not-changed.txt │ │ ├── branch2 │ │ ├── a │ │ │ ├── a-changed.txt │ │ │ ├── a-new1.txt │ │ │ └── a-not-changed.txt │ │ └── c │ │ │ └── c-not-changed.txt │ │ └── branch3 │ │ └── a │ │ ├── a-changed.txt │ │ ├── a-deleted.txt │ │ └── a-not-changed.txt └── ~ │ ├── syncdb.h2.db │ └── syncdb.trace.db ├── milton-cloud-vfs ├── mem.h2.db ├── nb-configuration.xml ├── nbactions.xml ├── pom.xml └── src │ ├── main │ └── java │ │ └── io │ │ └── milton │ │ ├── cloud │ │ ├── common │ │ │ ├── CurrentDateService.java │ │ │ ├── DefaultCurrentDateService.java │ │ │ ├── MutableCurrentDateService.java │ │ │ └── With.java │ │ └── process │ │ │ ├── AbstractRule.java │ │ │ ├── ActionHandler.java │ │ │ ├── AndRule.java │ │ │ ├── BeanPropertyExpression.java │ │ │ ├── ComparisonRule.java │ │ │ ├── ConstantExpression.java │ │ │ ├── ContainsRule.java │ │ │ ├── Expression.java │ │ │ ├── ListFilterExpression.java │ │ │ ├── OrRule.java │ │ │ ├── ProcessContext.java │ │ │ ├── ProcessImpl.java │ │ │ ├── ProcessInstance.java │ │ │ ├── Rule.java │ │ │ ├── State.java │ │ │ ├── StateImpl.java │ │ │ ├── StateProcess.java │ │ │ ├── StateProcessBuilder.java │ │ │ ├── TimeDependentRule.java │ │ │ ├── TimerService.java │ │ │ ├── Transition.java │ │ │ ├── TransitionImpl.java │ │ │ ├── Transitions.java │ │ │ └── TrueRule.java │ │ └── vfs │ │ ├── content │ │ └── DbHashStore.java │ │ ├── data │ │ ├── DataSession.java │ │ └── NodesChangedEvent.java │ │ └── db │ │ ├── AbstractVfsVisitor.java │ │ ├── AddressBook.java │ │ ├── AttendeeRequest.java │ │ ├── BaseEntity.java │ │ ├── BaseProcess.java │ │ ├── BlobHash.java │ │ ├── Branch.java │ │ ├── CalEvent.java │ │ ├── CalEventProcess.java │ │ ├── Calendar.java │ │ ├── Commit.java │ │ ├── Contact.java │ │ ├── ContactExtendedProperty.java │ │ ├── Credential.java │ │ ├── FanoutEntry.java │ │ ├── FanoutHash.java │ │ ├── Group.java │ │ ├── GroupFolder.java │ │ ├── GroupInWebsite.java │ │ ├── GroupMembership.java │ │ ├── GroupRole.java │ │ ├── ImprovedImplicitNamingStrategy.java │ │ ├── ImprovedPhysicalNamingStrategy.java │ │ ├── MembershipProcess.java │ │ ├── NvPair.java │ │ ├── NvSet.java │ │ ├── OrgType.java │ │ ├── Organisation.java │ │ ├── PasswordCredential.java │ │ ├── Profile.java │ │ ├── Reminder.java │ │ ├── Repository.java │ │ ├── SubOrg.java │ │ ├── Subordinate.java │ │ ├── VfsAcceptor.java │ │ ├── VfsVisitor.java │ │ ├── Website.java │ │ └── utils │ │ ├── DbUtils.java │ │ └── SessionManager.java │ └── test │ ├── java │ └── ConflictTest.java │ └── resources │ ├── database.xml │ └── log4j.properties ├── nb-configuration.xml ├── nbactions.xml ├── pom.xml ├── v2 └── velocity.log /.gitignore: -------------------------------------------------------------------------------- 1 | /spliffy-sync-app/branding/target/userdir/var/cache/netigso/org.eclipse.core.runtime/.manager/ 2 | /spliffy-sync-app/branding/target/userdir/var/cache/netigso/org.eclipse.equinox.app/.manager/ 3 | /spliffy-sync-app/branding/target/userdir/var/cache/netigso/org.eclipse.osgi/.manager/ 4 | /spliffy-sync-app/module/target/userdir/var/cache/netigso/org.eclipse.core.runtime/.manager/ 5 | /spliffy-sync-app/module/target/userdir/var/cache/netigso/org.eclipse.equinox.app/.manager/ 6 | /spliffy-sync-app/module/target/userdir/var/cache/netigso/org.eclipse.osgi/.manager/ 7 | /milton-cloud-lib/target/ 8 | /milton-cloud-server/target/ 9 | /milton-cloud-sync/target/ 10 | /milton-cloud-sync-app/application/target/ 11 | /milton-cloud-sync-app/branding/target/ 12 | /milton-cloud-sync-app/module/target/ 13 | /milton-cloud-vfs/target/ 14 | /milton-cloud-server/velocity.log 15 | /milton-cloud-server-api/target/ 16 | /external/ckeditor/target/ 17 | /external/jstree/target/ 18 | /external/colorpicker/target/ 19 | /milton-cloud-blobby/target/ 20 | /.idea 21 | *.iml 22 | /milton-cloud-server/src/test/resources/milton.license.properties 23 | /milton-cloud-server/src/test/resources/milton.license.sig 24 | /examples/mc-vfs-gettingstarted/target/ 25 | .project 26 | .settings/ 27 | milton-cloud-sync/.classpath 28 | milton-cloud-sync/.project 29 | milton-cloud-sync/.settings/ 30 | milton-cloud-vfs/.classpath 31 | milton-cloud-vfs/.project 32 | milton-cloud-vfs/.settings/ 33 | /sync-tool/sync-gui/target/ 34 | /sync-tool/sync-tool-gui/target/ 35 | /sync-tool/branding/target/ 36 | /sync-tool/application/target/ 37 | /SyncTool/SyncTool/branding/target/ 38 | /SyncTool/SyncTool/SyncToolGui/target/ 39 | /SyncTool/SyncTool/application/target/ 40 | /SyncTool/SyncTool/target/ 41 | /milton-cloud-tool/branding/target/ 42 | /milton-cloud-tool/application/target/ 43 | /milton-cloud-tool/milton-cloud-tool-gui/target/ 44 | /milton-cloud/milton-cloud/milton-cloud-tool/target/ 45 | /milton-cloud/milton-cloud/branding/target/ 46 | /milton-cloud/milton-cloud/application/target/ 47 | /milton-cloud-sync-app/milton-cloud-tool/target/ -------------------------------------------------------------------------------- /aa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/aa -------------------------------------------------------------------------------- /db-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/db-diagram.png -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CUSTOM-jetty:run 5 | jetty:run 6 | 7 | jetty:run 8 | 9 | 10 | 11 | CUSTOM-jetty:stop jetty:run 12 | jetty:stop jetty:run 13 | 14 | jetty:stop 15 | jetty:run 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/src/main/resources/default.properties: -------------------------------------------------------------------------------- 1 | # DATABASE 2 | 3 | hibernate.dialect=org.hibernate.dialect.H2Dialect 4 | hibernate.show_sql=false 5 | jdbc.driverClassName=org.h2.Driver 6 | jdbc.url=jdbc:h2:file:target/db;MVCC=TRUE 7 | jdbc.username=sa 8 | jdbc.password= 9 | -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Set root logger level to DEBUG and its only appender to A1. 2 | log4j.rootLogger=INFO, A1 3 | 4 | # A1 is set to be a ConsoleAppender. 5 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 6 | 7 | # A1 uses PatternLayout. 8 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.A1.layout.ConversionPattern=%-5p %c %x - %m%n 10 | 11 | log4j.logger.net.sf.json.JSONObject=WARN 12 | 13 | log4j.logger.io.milton=INFO 14 | log4j.logger.io.milton.http.AuthenticationService=INFO 15 | log4j.logger.io.milton.http.annotated=INFO 16 | log4j.logger.io.milton.http.entity=INFO 17 | log4j.logger.io.milton.http.webdav.PropFindPropertyBuilder=INFO 18 | log4j.logger.io.milton.property.BeanPropertySource=INFO 19 | log4j.logger.io.milton.http.http11.auth=INFO 20 | -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/src/main/resources/milton.license.properties: -------------------------------------------------------------------------------- 1 | #Wed Feb 13 11:57:32 NZDT 2013 2 | CompanyName=McEvoy Software Ltd 3 | Help=If you need any help please get in touch\! http\://milton.io/contact 4 | License=Limited time trial commercial 5 | Expires=2013-05-14 6 | 7 | -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/src/main/resources/milton.license.sig: -------------------------------------------------------------------------------- 1 | MC0CFQCKjzQGTR7G5G6BEc3IQrh1AEyaVAIUDT5prlSyb3Df5ChYjXT8DPtqpp8= -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/src/main/resources/miltonContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/src/main/resources/rootContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | classpath:default.properties 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | contextConfigLocation 9 | classpath:rootContext.xml 10 | 11 | 12 | org.springframework.web.context.ContextLoaderListener 13 | 14 | 15 | 16 | openSessionInViewFilter 17 | 18 | org.springframework.orm.hibernate3.support.OpenSessionInViewFilter 19 | 20 | 21 | singleSession 22 | true 23 | 24 | 25 | 26 | 27 | openSessionInViewFilter 28 | /* 29 | 30 | 31 | 32 | miltonFilter 33 | io.milton.servlet.SpringMiltonFilter 34 | 35 | milton.exclude.paths 36 | /static,/templates 37 | 38 | 39 | contextConfigLocation 40 | classpath:miltonContext.xml 41 | 42 | 43 | 44 | 45 | miltonFilter 46 | /* 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /examples/mc-vfs-gettingstarted/src/main/webapp/templates/directory.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 | <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |

Directory: ${model.directory.name}/

11 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/application/nb-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | JDK_1.8u65 17 | 18 | 19 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/application/src/test/java/io/milton/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package io.milton; 2 | 3 | import junit.framework.Test; 4 | import org.netbeans.junit.NbModuleSuite; 5 | import org.netbeans.junit.NbTestCase; 6 | 7 | public class ApplicationTest extends NbTestCase { 8 | 9 | public static Test suite() { 10 | return NbModuleSuite.createConfiguration(ApplicationTest.class). 11 | gui(false). 12 | // failOnMessage(Level.WARNING). // works at least in RELEASE71 13 | // failOnException(Level.INFO). 14 | enableClasspathModules(false). 15 | clusters(".*"). 16 | suite(); // RELEASE71+, else use NbModuleSuite.create(NbModuleSuite.createConfiguration(...)) 17 | } 18 | 19 | public ApplicationTest(String n) { 20 | super(n); 21 | } 22 | 23 | public void testApplication() { 24 | // pass if there are merely no warnings/exceptions 25 | /* Example of using Jelly Tools (additional test dependencies required) with gui(true): 26 | new ActionNoBlock("Help|About", null).performMenu(); 27 | new NbDialogOperator("About").closeByButton(); 28 | */ 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/application/~/syncdb.h2.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/application/~/syncdb.h2.db -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | io.milton 7 | milton-cloud-sync-app-parent 8 | 1.2.1 9 | 10 | 11 | milton-cloud-branding 12 | nbm 13 | 14 | milton-cloud-branding 15 | 16 | 17 | UTF-8 18 | 19 | 20 | 21 | 22 | org.netbeans.api 23 | org-netbeans-api-annotations-common 24 | ${netbeans.version} 25 | 26 | 27 | 28 | 29 | 30 | 31 | org.codehaus.mojo 32 | nbm-maven-plugin 33 | 34 | 35 | org.apache.maven.plugins 36 | maven-jar-plugin 37 | 38 | 39 | true 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/Bundle.properties: -------------------------------------------------------------------------------- 1 | currentVersion=milton-cloud {0} 2 | LBL_splash_window_title=Starting milton-cloud 3 | SPLASH_HEIGHT=100 4 | SPLASH_WIDTH=126 5 | SplashProgressBarBounds=0,83,126,6 6 | SplashRunningTextBounds=2,78,119,3 7 | SplashRunningTextFontSize=6 8 | SplashShowProgressBar=false 9 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.gif -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.gif -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.gif -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/splash.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/splash.gif -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm-branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/Bundle.properties: -------------------------------------------------------------------------------- 1 | Mode.Editor.DragAndDrop.Enabled=false 2 | Mode.Sliding.Enabled=false 3 | Mode.View.DragAndDrop.Enabled=false 4 | TopComponent.DragAndDrop.Enabled=false 5 | TopComponent.Sliding.Enabled=false 6 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm-branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties: -------------------------------------------------------------------------------- 1 | CTL_MainWindow_Title=milton-cloud {0} 2 | CTL_MainWindow_Title_No_Project=milton-cloud {0} 3 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm-branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties: -------------------------------------------------------------------------------- 1 | LBL_ProductInformation=milton-cloud 2 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/nbm/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | OpenIDE-Module-Localizing-Bundle: io/milton/branding/Bundle.properties 3 | AutoUpdate-Essential-Module: true 4 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/branding/src/main/resources/io/milton/branding/Bundle.properties: -------------------------------------------------------------------------------- 1 | # Localized module labels. Defaults taken from POM (, , ) if unset. 2 | #OpenIDE-Module-Name= 3 | #OpenIDE-Module-Short-Description= 4 | #OpenIDE-Module-Long-Description= 5 | #OpenIDE-Module-Display-Category= 6 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/milton-cloud-tool/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.milton 6 | milton-cloud-sync-app-parent 7 | 1.2.1 8 | 9 | milton-cloud-tool 10 | nbm 11 | 12 | 13 | 14 | org.codehaus.mojo 15 | nbm-maven-plugin 16 | true 17 | 18 | 19 | org.apache.maven.plugins 20 | maven-jar-plugin 21 | 22 | true 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.netbeans.api 30 | org-netbeans-api-annotations-common 31 | ${netbeans.version} 32 | 33 | 34 | ${project.groupId} 35 | milton-cloud-sync 36 | 1.2.4 37 | 38 | 39 | org.netbeans.api 40 | org-openide-windows 41 | ${netbeans.version} 42 | 43 | 44 | org.netbeans.api 45 | org-openide-util 46 | ${netbeans.version} 47 | 48 | 49 | org.netbeans.api 50 | org-openide-util-ui 51 | ${netbeans.version} 52 | 53 | 54 | org.netbeans.api 55 | org-openide-util-lookup 56 | ${netbeans.version} 57 | 58 | 59 | org.netbeans.api 60 | org-openide-awt 61 | ${netbeans.version} 62 | 63 | 64 | org.netbeans.api 65 | org-netbeans-modules-settings 66 | ${netbeans.version} 67 | 68 | 69 | org.json 70 | json 71 | 20160810 72 | jar 73 | 74 | 75 | 76 | 77 | UTF-8 78 | 79 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/milton-cloud-tool/src/main/java/guiTool/Helper.java: -------------------------------------------------------------------------------- 1 | package guiTool; 2 | 3 | /* 4 | * To change this license header, choose License Headers in Project Properties. 5 | * To change this template file, choose Tools | Templates 6 | * and open the template in the editor. 7 | */ 8 | 9 | 10 | import java.io.BufferedReader; 11 | import java.io.InputStreamReader; 12 | import java.net.Authenticator; 13 | import java.net.InetSocketAddress; 14 | import java.net.PasswordAuthentication; 15 | import java.net.Socket; 16 | import java.net.URL; 17 | import java.util.ArrayList; 18 | import javax.swing.JOptionPane; 19 | import org.json.JSONArray; 20 | import org.json.JSONException; 21 | import org.json.JSONObject; 22 | 23 | /** 24 | * 25 | * @author ibraheem 26 | */ 27 | public class Helper { 28 | 29 | public static final boolean checkInternet() { 30 | 31 | try { 32 | Socket socket = new Socket(); 33 | InetSocketAddress add = new InetSocketAddress("www.google.com", 80); 34 | socket.connect(add, 3000); 35 | return true; 36 | } catch (Exception e) { 37 | JOptionPane.showMessageDialog(null, "The server or your internet connection could be down.", "connection test", JOptionPane.ERROR_MESSAGE); 38 | return false; 39 | } 40 | 41 | } 42 | 43 | public static String readUrl(String urlString, final String userid, final String password) throws Exception { 44 | 45 | BufferedReader reader = null; 46 | StringBuilder buffer = null; 47 | try { 48 | URL url = new URL(urlString); 49 | 50 | Authenticator.setDefault(new Authenticator() { 51 | @Override 52 | protected PasswordAuthentication getPasswordAuthentication() { 53 | return new PasswordAuthentication(userid, password.toCharArray()); 54 | } 55 | }); 56 | InputStreamReader s = new InputStreamReader(url.openStream()); 57 | // System.out.println("getEncoding " + s.getEncoding()); 58 | reader = new BufferedReader(s); 59 | 60 | buffer = new StringBuilder(); 61 | int read; 62 | char[] chars = new char[1024]; 63 | while ((read = reader.read(chars)) != -1) { 64 | buffer.append(chars, 0, read); 65 | } 66 | 67 | } catch (Exception e) { 68 | System.out.println("Exception " +e.getMessage()); 69 | // JOptionPane.showMessageDialog(null, "The server or your internet connection could be down.", "connection test", JOptionPane.ERROR_MESSAGE); 70 | 71 | } finally { 72 | if (reader != null) { 73 | reader.close(); 74 | } 75 | } 76 | return buffer.toString(); 77 | } 78 | 79 | public static ArrayList getDataFromJson(String json) { 80 | ArrayList list = new ArrayList<>(); 81 | 82 | try { 83 | JSONArray array = new JSONArray(json); 84 | JSONObject jSONObject; 85 | for (int i = 0; i < array.length(); i++) { 86 | jSONObject = new JSONObject(array.get(i).toString()); 87 | list.add((String) jSONObject.get("name")); 88 | 89 | } 90 | } catch (JSONException ex) { 91 | System.out.println(ex.getMessage()); 92 | } 93 | return list; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/milton-cloud-tool/src/main/java/guiTool/base.java: -------------------------------------------------------------------------------- 1 | package guiTool; 2 | 3 | /* 4 | * To change this template, choose Tools | Templates 5 | * and open the template in the editor. 6 | */ 7 | 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.io.RandomAccessFile; 12 | import java.nio.channels.FileChannel; 13 | import java.nio.channels.FileLock; 14 | 15 | /** 16 | * 17 | * @author ibraheem 18 | */ 19 | public class base { 20 | 21 | SyncToolTopComponent main = new SyncToolTopComponent(); 22 | 23 | public void run() { 24 | main.setVisible(true); 25 | } 26 | 27 | public static File file; 28 | /* */ public static FileChannel filechannel; 29 | /* */ public static FileLock fileLock; 30 | 31 | public static void main(String args[]) { 32 | 33 | try { 34 | file = new File("Key"); 35 | 36 | if (file.exists()) { 37 | file.delete(); 38 | } 39 | 40 | filechannel = new RandomAccessFile(file, "rw").getChannel(); 41 | fileLock = filechannel.tryLock(); 42 | 43 | if (fileLock == null) { 44 | filechannel.close(); 45 | throw new RuntimeException("errr"); 46 | } 47 | Thread shut = new Thread(new Runnable() { 48 | 49 | @Override 50 | public void run() { 51 | 52 | } 53 | 54 | }); 55 | 56 | Runtime.getRuntime().addShutdownHook(shut); 57 | 58 | protect(); 59 | } catch (IOException | RuntimeException e) { 60 | System.out.println(e.getMessage()); 61 | 62 | System.exit(0); 63 | 64 | } 65 | } 66 | 67 | public static void unlock() { 68 | try { 69 | if (fileLock != null) { 70 | fileLock.release(); 71 | filechannel.close(); 72 | file.delete(); 73 | } 74 | } catch (Exception e) { 75 | } 76 | } 77 | 78 | //will prevent copy 79 | private static void protect() { 80 | try { 81 | javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); 82 | 83 | } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { 84 | ex.printStackTrace(); 85 | } 86 | base b = new base(); 87 | b.run(); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/milton-cloud-tool/src/main/nbm/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | OpenIDE-Module-Localizing-Bundle: /Bundle.properties 3 | OpenIDE-Module-Requires: org.openide.windows.WindowManager 4 | 5 | -------------------------------------------------------------------------------- /milton-cloud-sync-app/milton-cloud-tool/src/main/resources/Bundle.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/milton-cloud-tool/src/main/resources/Bundle.properties -------------------------------------------------------------------------------- /milton-cloud-sync-app/milton-cloud-tool/src/main/resources/images/logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/milton-cloud-tool/src/main/resources/images/logo-dark.png -------------------------------------------------------------------------------- /milton-cloud-sync-app/milton-cloud-tool/src/main/resources/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/milton-cloud-tool/src/main/resources/images/upload.png -------------------------------------------------------------------------------- /milton-cloud-sync-app/milton-cloud-tool/~/syncdb.h2.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync-app/milton-cloud-tool/~/syncdb.h2.db -------------------------------------------------------------------------------- /milton-cloud-sync-app/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | io.milton 7 | milton-cloud-sync-app-parent 8 | 1.2.1 9 | pom 10 | 11 | milton-cloud-sync-app-parent 12 | 13 | 14 | 19 | 20 | netbeans 21 | NetBeans 22 | http://bits.netbeans.org/nexus/content/groups/netbeans/ 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.codehaus.mojo 31 | nbm-maven-plugin 32 | 3.13 33 | true 34 | 35 | ${brandingToken} 36 | ${brandingToken} 37 | 38 | 39 | 40 | 41 | org.apache.maven.plugins 42 | maven-compiler-plugin 43 | 2.5.1 44 | 45 | 1.7 46 | 1.7 47 | 48 | 49 | 50 | org.apache.maven.plugins 51 | maven-jar-plugin 52 | 2.4 53 | 54 | 55 | 56 | 57 | 58 | 59 | branding 60 | application 61 | milton-cloud-tool 62 | 63 | 64 | 65 | RELEASE81 66 | miltoncloud 67 | 68 | 69 | -------------------------------------------------------------------------------- /milton-cloud-sync/Key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync/Key -------------------------------------------------------------------------------- /milton-cloud-sync/nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run 5 | 6 | process-classes 7 | org.codehaus.mojo:exec-maven-plugin:1.2:exec 8 | 9 | 10 | -classpath %classpath GUISync.base 11 | java 12 | runtime 13 | 14 | 15 | 16 | debug 17 | 18 | process-classes 19 | org.codehaus.mojo:exec-maven-plugin:1.2:exec 20 | 21 | 22 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath GUISync.base 23 | java 24 | runtime 25 | true 26 | 27 | 28 | 29 | profile 30 | 31 | process-classes 32 | org.codehaus.mojo:exec-maven-plugin:1.2:exec 33 | 34 | 35 | -classpath %classpath GUISync.base 36 | ${profiler.java} 37 | profile 38 | 39 | 40 | 41 | CUSTOM-deploy 42 | deploy 43 | 44 | deploy 45 | 46 | 47 | 48 | CUSTOM-dependency:list 49 | dependency:list 50 | 51 | dependency:list 52 | 53 | 54 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/io/ChunkStore.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.io; 2 | 3 | public interface ChunkStore extends ChunkWriter{ 4 | 5 | /** retrieve the chunk at position i (zero indexed) 6 | */ 7 | byte[] getChunk(int i); 8 | 9 | /** 10 | * delete any chunks which might exist 11 | */ 12 | void deleteChunks(); 13 | } 14 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/io/ChunkWriter.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.io; 2 | 3 | public interface ChunkWriter { 4 | /** create a new chunk at position i (zero indexed) with the entire 5 | * byte array in data 6 | */ 7 | void newChunk(int i, byte[] data); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/io/ChunkingInputStream.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.io; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | public class ChunkingInputStream extends InputStream{ 10 | private static final Logger log = LoggerFactory.getLogger(ChunkingInputStream.class); 11 | final ChunkStore store; 12 | 13 | private int chunkNum; 14 | private int pos = -1; 15 | private byte[] currentChunk; 16 | 17 | public ChunkingInputStream(ChunkStore store) { 18 | this.store = store; 19 | this.currentChunk = store.getChunk(chunkNum++); 20 | } 21 | 22 | @Override 23 | public int read() throws IOException { 24 | if( currentChunk == null ) return -1; 25 | pos++; 26 | if( pos >= currentChunk.length ) { // if first, or have exhausted current, get next chunk 27 | currentChunk = store.getChunk(chunkNum++); 28 | if( currentChunk == null ) return -1; // EOF. no more data 29 | pos = 0; 30 | } 31 | int i = currentChunk[pos] & 0xff; 32 | return i; 33 | } 34 | 35 | public void writeTo(OutputStream out) throws IOException { 36 | long t = System.currentTimeMillis(); 37 | boolean done = (currentChunk == null || currentChunk.length==0); 38 | while( !done ) { 39 | out.write(currentChunk); 40 | log.debug("chunk: " + chunkNum + " - " + currentChunk.length); 41 | 42 | currentChunk = store.getChunk(chunkNum++); 43 | done = (currentChunk == null || currentChunk.length==0); 44 | } 45 | t = System.currentTimeMillis() - t; 46 | log.debug("transmission time: " + t + "ms"); 47 | } 48 | // public synchronized int read(byte b[], int off, int len) { 49 | // log.debug("read-" + off + " - " + len); 50 | // log.debug(" chunk: " + chunkNum + " size:" + currentChunk.length); 51 | // if (b == null) { 52 | // throw new NullPointerException(); 53 | // } else if (off < 0 || len < 0 || len > b.length - off) { 54 | // throw new IndexOutOfBoundsException(); 55 | // } 56 | // 57 | // int nextLen = 0; 58 | // int thisLen = len; 59 | // if( thisLen+off > currentChunk.length-1 ) { 60 | // nextLen = off + thisLen - currentChunk.length - 1; 61 | // thisLen = currentChunk.length - off; 62 | // log.debug(" nextLen: " + nextLen); 63 | // log.debug(" thisLen: " + thisLen); 64 | // } 65 | // log.debug("arraycopy " + currentChunk.length + "," + pos + "," + b.length + "," + off + "," + thisLen); 66 | // System.arraycopy(currentChunk, pos, b, off, thisLen); 67 | // pos += thisLen; 68 | // int nextBytes = 0; 69 | // if( nextLen > 0 ) { 70 | // nextBytes = read(b,off+thisLen,nextLen); 71 | // } 72 | // return len; 73 | // } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/io/ChunkingOutputStream.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.io; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.OutputStream; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class ChunkingOutputStream extends OutputStream { 11 | 12 | private static final Logger log = LoggerFactory.getLogger( ChunkingOutputStream.class ); 13 | final ChunkWriter chunkWriter; 14 | final ByteArrayOutputStream chunkInProgress; 15 | final int chunkSize; 16 | private long count; 17 | private int currentChunk; 18 | 19 | public ChunkingOutputStream( ChunkWriter chunkWriter, int chunkSize ) { 20 | this.chunkWriter = chunkWriter; 21 | this.chunkSize = chunkSize; 22 | this.chunkInProgress = new ByteArrayOutputStream( chunkSize ); 23 | } 24 | 25 | @Override 26 | public void write( byte[] b ) throws IOException { 27 | count += b.length; 28 | if( chunkInProgress.size() >= chunkSize ) { 29 | flushChunk(); 30 | } 31 | 32 | chunkInProgress.write( b ); 33 | } 34 | 35 | @Override 36 | public void write( int b ) throws IOException { 37 | count++; 38 | if( chunkInProgress.size() >= chunkSize ) { 39 | flushChunk(); 40 | } 41 | chunkInProgress.write( b ); 42 | } 43 | 44 | @Override 45 | public void write( byte[] b, int off, int len ) throws IOException { 46 | if( chunkInProgress.size() >= chunkSize ) { 47 | flushChunk(); 48 | } 49 | count += len; 50 | chunkInProgress.write( b, off, len ); 51 | } 52 | 53 | private void flushChunk() { 54 | if( chunkInProgress.size() == 0 ) { 55 | return; 56 | } 57 | byte[] arr = chunkInProgress.toByteArray(); 58 | chunkWriter.newChunk( currentChunk++, arr ); 59 | chunkInProgress.reset(); 60 | } 61 | 62 | @Override 63 | public void flush() throws IOException { 64 | flushChunk(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/io/ReadingException.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.io; 2 | 3 | import java.io.IOException; 4 | 5 | public class ReadingException extends IOException{ 6 | public ReadingException(IOException cause) { 7 | super(cause); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/io/WritingException.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.io; 2 | 3 | import java.io.IOException; 4 | 5 | public class WritingException extends IOException{ 6 | public WritingException(IOException cause) { 7 | super(cause); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/utils/ElementList.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.utils; 2 | 3 | import java.util.ArrayList; 4 | import org.w3c.dom.Element; 5 | import org.w3c.dom.Node; 6 | import org.w3c.dom.NodeList; 7 | 8 | public class ElementList extends ArrayList { 9 | 10 | public ElementList(NodeList nodes) { 11 | for (int i = 0; i < nodes.getLength(); i++) { 12 | Node n = nodes.item(i); 13 | if( n instanceof Element ) { 14 | add( (Element)n ); 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/utils/IntegerUtils.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.utils; 2 | 3 | public class IntegerUtils { 4 | 5 | public IntegerUtils() { 6 | } 7 | 8 | /** Returns true if the specified value exists in the array 9 | */ 10 | public static boolean isInArray( int[] array, int valueToCheck) { 11 | for( int i=0; i { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/utils/StreamWriter.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.utils; 2 | 3 | import java.io.OutputStream; 4 | 5 | public interface StreamWriter extends With{ 6 | 7 | } 8 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/utils/TypeUtils.java: -------------------------------------------------------------------------------- 1 | 2 | package com.bradmcevoy.utils; 3 | 4 | public class TypeUtils { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/utils/With.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.utils; 2 | 3 | public interface With { 4 | O use(T t) throws Exception; 5 | } 6 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/utils/entities.properties: -------------------------------------------------------------------------------- 1 |  =  2 | ¡=¡ 3 | ¤=¤ 4 | ¢=¢ 5 | £=£ 6 | ¥=¥ 7 | ¦=¦ 8 | §=§ 9 | ¨=¨ 10 | ©=© 11 | ª=ª 12 | «=« 13 | ¬=¬ 14 | ­=­ 15 | ®=® 16 | ™=™ 17 | ¯=¯ 18 | °=° 19 | ±=± 20 | ²=² 21 | ³=³ 22 | ´=´ 23 | µ=µ 24 | ¶=¶ 25 | ·=· 26 | ¸=¸ 27 | ¹=¹ 28 | º=º 29 | »=» 30 | ¼=¼ 31 | ½=½ 32 | ¾=¾ 33 | ¿=¿ 34 | ×=× 35 | ÷=÷ 36 | À=À 37 | Á=Á 38 | Â= 39 | Ã=à 40 | Ä=Ä 41 | Å=Å 42 | Æ=Æ 43 | Ç=Ç 44 | È=È 45 | É=É 46 | Ê=Ê 47 | Ë=Ë 48 | Ì=Ì 49 | Í=Í 50 | Î=Î 51 | Ï=Ï 52 | Ð=Ð 53 | Ñ=Ñ 54 | Ò=Ò 55 | Ó=Ó 56 | Ô=Ô 57 | Õ=Õ 58 | Ö=Ö 59 | Ø=Ø 60 | Ù=Ù 61 | Ú=Ú 62 | Û=Û 63 | Ü=Ü 64 | Ý=Ý 65 | Þ=Þ 66 | ß=ß 67 | à=à 68 | á=á 69 | â=â 70 | ã=ã 71 | ä=ä 72 | å=å 73 | æ=æ 74 | ç=ç 75 | è=è 76 | é=é 77 | ê=ê 78 | ë=ë 79 | ì=ì 80 | í=í 81 | î=î 82 | ï=ï 83 | ð=ð 84 | ñ=ñ 85 | ò=ò 86 | ó=ó 87 | ô=ô 88 | õ=õ 89 | ö=ö 90 | ø=ø 91 | ù=ù 92 | ú=ú 93 | û=û 94 | ü=ü 95 | ý=ý 96 | þ=þ 97 | ÿ=ÿ 98 | Œ=Œ 99 | œ=œ 100 | Š=Š 101 | š=š 102 | Ÿ=Ÿ 103 | ˆ=ˆ 104 | ˜=˜ 105 |  =  106 |  =  107 |  =  108 | ‌=‌ 109 | ‍=‍ 110 | ‎=‎ 111 | ‏=‏ 112 | –=– 113 | —=— 114 | ‘=‘ 115 | ’=’ 116 | ‚=‚ 117 | “=“ 118 | ”=” 119 | „=„ 120 | †=† 121 | ‡=‡ 122 | …=… 123 | ‰=‰ 124 | ‹=‹ 125 | ›=› 126 | €=€ 127 | 128 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/version/Block.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.version; 2 | 3 | /** 4 | * Represents a block of data in a versioned file's block map 5 | * 6 | * @author brad 7 | */ 8 | public interface Block { 9 | long getBlockSize(); 10 | 11 | int getChecksum(); 12 | } 13 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/version/BlockStore.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.version; 2 | 3 | /** 4 | * Represents a means of accessing blocks of data for a file. 5 | * 6 | * @author brad 7 | */ 8 | public interface BlockStore { 9 | Block firstBlock(); 10 | Block nextBlock(Block block); 11 | } 12 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/bradmcevoy/version/VersioningOutputStream.java: -------------------------------------------------------------------------------- 1 | package com.bradmcevoy.version; 2 | 3 | import com.bradmcevoy.io.*; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class VersioningOutputStream extends OutputStream{ 11 | 12 | private static final Logger log = LoggerFactory.getLogger(VersioningOutputStream.class); 13 | 14 | final ChunkWriter chunkWriter; 15 | final ByteArrayOutputStream chunkInProgress; 16 | final int chunkSize; 17 | 18 | private long count; 19 | private int currentChunk; 20 | 21 | public VersioningOutputStream(ChunkWriter chunkWriter, int chunkSize) { 22 | this.chunkWriter = chunkWriter; 23 | this.chunkSize = chunkSize; 24 | this.chunkInProgress = new ByteArrayOutputStream(chunkSize); 25 | } 26 | 27 | 28 | 29 | @Override 30 | public void write( byte[] b ) throws IOException { 31 | count+=b.length; 32 | if( chunkInProgress.size() >= chunkSize ) { 33 | flushChunk(); 34 | } 35 | 36 | chunkInProgress.write(b); 37 | } 38 | 39 | 40 | public void write(int b) throws IOException { 41 | count++; 42 | if( chunkInProgress.size() >= chunkSize ) { 43 | flushChunk(); 44 | } 45 | chunkInProgress.write(b); 46 | } 47 | 48 | @Override 49 | public void write(byte[] b, int off, int len) throws IOException { 50 | if( chunkInProgress.size() >= chunkSize ) { 51 | flushChunk(); 52 | } 53 | count+=len; 54 | chunkInProgress.write(b, off, len); 55 | } 56 | 57 | 58 | 59 | private void flushChunk() { 60 | if( chunkInProgress.size() == 0 ) { 61 | return ; 62 | } 63 | byte[] arr = chunkInProgress.toByteArray(); 64 | chunkWriter.newChunk(currentChunk++,arr); 65 | chunkInProgress.reset(); 66 | } 67 | 68 | @Override 69 | public void flush() throws IOException { 70 | flushChunk(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/common/Service.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.common; 2 | 3 | /** 4 | * Represents some service which can be controlled (ie started and stopped) 5 | * 6 | * @author brad 7 | */ 8 | public interface Service { 9 | /** 10 | * Start the service. Until this is called the service should not be functional 11 | */ 12 | void start(); 13 | 14 | /** 15 | * The service should be made unavailable, however it should be able to 16 | * be starte again 17 | * 18 | */ 19 | void stop(); 20 | } 21 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/common/Withee.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.common; 2 | 3 | /** 4 | * General purpose interface for consuming a callback for some type. Typically 5 | * used in "with" style blocks: 6 | * 7 | * someRsourceProvider.with(new Withee() { 8 | * public void with(Resource r) { 9 | * ... do something with the resource 10 | * } 11 | * } 12 | * 13 | * @author bradm 14 | */ 15 | public interface Withee { 16 | void with(T t) throws Exception; 17 | } 18 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/config/ConfigurationException.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.config; 2 | 3 | 4 | public class ConfigurationException extends Exception { 5 | private static final long serialVersionUID = 1L; 6 | 7 | public ConfigurationException(String msg) { 8 | super(msg); 9 | } 10 | 11 | public ConfigurationException(String context, Exception cause) { 12 | super(context,cause); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/Accessor.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | public interface Accessor extends Dependent{ 4 | public void preExecute( Context context ); 5 | public void postExecute( Context context ); 6 | } 7 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/BeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 8 | */ 9 | public class BeanFactory implements Factory { 10 | 11 | public static final String SCOPE_APP = "app"; 12 | public static final String SCOPE_REQUEST = "request"; 13 | 14 | private Class beanClass; 15 | private Class[] keyClasses; 16 | private String scope = SCOPE_APP; 17 | 18 | public Class[] keyClasses() { 19 | return keyClasses; 20 | } 21 | 22 | public String[] keyIds() { 23 | return null; 24 | } 25 | 26 | public Registration insert(RootContext context, Context requestContext) { 27 | Object o = instantiateBean(); 28 | if( isRequestScope() ) { 29 | return requestContext.put(o); 30 | } else { 31 | return context.put(o); 32 | } 33 | } 34 | 35 | public void init(RootContext context) { 36 | 37 | } 38 | 39 | public void destroy() { 40 | 41 | } 42 | 43 | public void onRemove(Object item) { 44 | 45 | } 46 | 47 | public String getBeanClass() { 48 | return beanClass.getCanonicalName(); 49 | } 50 | 51 | public void setBeanClass(String beanClass) { 52 | try { 53 | this.beanClass = Class.forName(beanClass); 54 | } catch (ClassNotFoundException ex) { 55 | throw new RuntimeException(beanClass, ex); 56 | } 57 | if( this.keyClasses == null ) this.keyClasses = this.beanClass.getInterfaces(); 58 | } 59 | 60 | public String getKeyClasses() { 61 | String s = ""; 62 | for( Class c : keyClasses ) { 63 | s = s + c.getCanonicalName() + ","; 64 | } 65 | return s; 66 | } 67 | 68 | public void setKeyClasses(String keyClasses) { 69 | String[] arr = keyClasses.split(","); 70 | List list = new ArrayList(); 71 | for( String s : arr) { 72 | try { 73 | Class i = Class.forName(s); 74 | list.add(i); 75 | } catch (ClassNotFoundException ex) { 76 | throw new RuntimeException(s, ex); 77 | } 78 | } 79 | this.keyClasses = new Class[list.size()]; 80 | list.toArray(this.keyClasses); 81 | } 82 | 83 | public String getScope() { 84 | return scope; 85 | } 86 | 87 | public void setScope(String scope) { 88 | if( scope.equals(SCOPE_APP) || scope.equals(SCOPE_REQUEST)) { 89 | this.scope = scope; 90 | } else { 91 | throw new RuntimeException("Scope attribute on BeanFactory must be " + SCOPE_APP + " or " + SCOPE_REQUEST + " not: " + scope); 92 | } 93 | } 94 | 95 | private Object instantiateBean() { 96 | try { 97 | return beanClass.newInstance(); 98 | } catch (InstantiationException ex) { 99 | throw new RuntimeException(ex); 100 | } catch (IllegalAccessException ex) { 101 | throw new RuntimeException(ex); 102 | } 103 | } 104 | 105 | private boolean isRequestScope() { 106 | return scope.equals(SCOPE_REQUEST); 107 | } 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/BeanLocator.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | /** 4 | * 5 | */ 6 | public interface BeanLocator { 7 | Object locateBean(Context context); 8 | } 9 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/BeanWrapper.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | /** 4 | * 5 | * @author brad 6 | */ 7 | public class BeanWrapper implements Factory { 8 | 9 | private Object bean; 10 | 11 | public Class[] keyClasses() { 12 | return null; 13 | } 14 | 15 | public String[] keyIds() { 16 | return null; 17 | } 18 | 19 | public Registration insert(RootContext context, Context requestContext) { 20 | throw new UnsupportedOperationException( "should already be in context"); 21 | } 22 | 23 | public void init(RootContext context) { 24 | context.put( bean); 25 | } 26 | 27 | public void destroy() { 28 | 29 | } 30 | 31 | public void onRemove(Object item) { 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/ClassBeanLocator.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | /** 4 | * 5 | */ 6 | public class ClassBeanLocator implements BeanLocator{ 7 | 8 | final Class classToFind; 9 | 10 | public ClassBeanLocator(Class classToFind) { 11 | this.classToFind = classToFind; 12 | } 13 | 14 | public Object locateBean(Context context) { 15 | return context.get(classToFind); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/ClassNotInContextException.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | /** 4 | * Represents a missing class 5 | * 6 | * @author brad 7 | */ 8 | public class ClassNotInContextException extends RuntimeException{ 9 | private static final long serialVersionUID = 1L; 10 | private final Class missing; 11 | 12 | public ClassNotInContextException( Class missing ) { 13 | super("The requested class is not in context: " + missing.getCanonicalName()); 14 | this.missing = missing; 15 | } 16 | 17 | public Class getMissing() { 18 | return missing; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/Contextual.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | /** This interface represents those classes which contain context 4 | */ 5 | public interface Contextual { 6 | public T get(String id); 7 | 8 | public T get(Class c); 9 | } 10 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/CtxRootFolderFactory.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.Properties; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class CtxRootFolderFactory implements Factory { 13 | private static final Logger log = LoggerFactory.getLogger(CtxRootFolderFactory.class); 14 | private File file; 15 | private static String[] keys = {"rootFolder"}; 16 | 17 | public static final String KEY_ROOT_FOLDER = "rootFolder"; 18 | 19 | public CtxRootFolderFactory() { 20 | log.debug("Created: CtxRootFolderFactory"); 21 | } 22 | 23 | public Class[] keyClasses() { 24 | return null; 25 | } 26 | 27 | public String[] keyIds() { 28 | return keys; 29 | } 30 | 31 | public Registration insert(RootContext context, Context requestContext) { 32 | Registration reg = (Registration)context.put(file,this); 33 | return reg; 34 | } 35 | 36 | public void init(RootContext context) { 37 | log.debug("CtxRootFolderFactory.init"); 38 | File configFile = (File)context.get("configFile"); 39 | if( configFile == null ) throw new RuntimeException("Could not find config file in context. Should have been added earlier"); 40 | log.debug( "configFile: " + configFile.getAbsolutePath()); 41 | file = configFile.getParentFile(); 42 | context.put("rootFolder",file); 43 | File propsFile = new File(file, "environment.properties"); 44 | loadEnvironmentProperties(context,propsFile); 45 | } 46 | 47 | private void loadEnvironmentProperties(RootContext context, final File propsFile) throws RuntimeException { 48 | log.debug("loadEnvironmentProperties"); 49 | if( !propsFile.exists() ) { 50 | log.warn("properties file does not exist: " + propsFile.getAbsolutePath()); 51 | return ; 52 | } 53 | final Properties props = new Properties(); 54 | FileInputStream fin = null; 55 | try { 56 | fin = new FileInputStream(propsFile); 57 | props.load(fin); 58 | } catch (FileNotFoundException ex) { 59 | throw new RuntimeException(ex); 60 | } catch (Exception ex) { 61 | throw new RuntimeException(ex); 62 | } finally { 63 | close(fin); 64 | } 65 | for( String s : props.stringPropertyNames() ) { 66 | String v = props.getProperty(s); 67 | // debug("Registering property: " + s + " = " + v ); 68 | context.put(s, v); 69 | } 70 | } 71 | 72 | private void close(InputStream in) { 73 | if( in == null ) return ; 74 | try { 75 | in.close(); 76 | } catch (IOException ex) { 77 | log.warn("exception closing stream",ex); 78 | } 79 | } 80 | 81 | 82 | public void destroy() { 83 | } 84 | 85 | public void onRemove(File item) { 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/Dependent.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | public interface Dependent { 4 | public Class[] getDependencies(); 5 | } 6 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/Executable.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | public interface Executable { 4 | public T execute( Context context ); 5 | } 6 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/Executable2.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | public interface Executable2 { 4 | public void execute( Context context ); 5 | } 6 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/Factory.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | public interface Factory extends RemovalCallback { 4 | public Class[] keyClasses(); 5 | public String[] keyIds(); 6 | public Registration insert(RootContext context, Context requestContext); 7 | public void init( RootContext context); 8 | void destroy(); 9 | } 10 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/ListFactory.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 8 | */ 9 | public class ListFactory implements Factory{ 10 | 11 | final String[] ids; 12 | final List beanLocators; 13 | 14 | public ListFactory(String id, List beanLocators) { 15 | ids = new String[] {id}; 16 | this.beanLocators = beanLocators; 17 | } 18 | 19 | public Class[] keyClasses() { 20 | return null; // only key by id 21 | } 22 | 23 | public String[] keyIds() { 24 | throw new UnsupportedOperationException("Not supported yet."); 25 | } 26 | 27 | public Registration insert(RootContext context, Context requestContext) { 28 | List list = new ArrayList(); 29 | for( BeanLocator bl : beanLocators ) { 30 | Object o = bl.locateBean(requestContext); 31 | list.add(o); 32 | } 33 | Registration reg = new Registration(list, null, context); 34 | return reg; 35 | } 36 | 37 | public void init(RootContext context) { 38 | 39 | } 40 | 41 | public void destroy() { 42 | 43 | } 44 | 45 | public void onRemove(List item) { 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/PostgresUtils.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | import com.ettrema.context.RequestContext; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.sql.Connection; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.List; 12 | 13 | 14 | /** 15 | * 16 | * @author brad 17 | */ 18 | public class PostgresUtils { 19 | 20 | 21 | public static Connection con() { 22 | return requestContext().get( Connection.class ); 23 | } 24 | 25 | public static RequestContext requestContext() { 26 | return RequestContext.getCurrent(); 27 | } 28 | 29 | public static void close( InputStream in ) { 30 | if( in == null ) return; 31 | try { 32 | in.close(); 33 | } catch( IOException ex ) { 34 | throw new RuntimeException( ex ); 35 | } 36 | } 37 | 38 | public static void close( OutputStream out ) { 39 | if( out == null ) return; 40 | 41 | try { 42 | out.close(); 43 | } catch( IOException ex ) { 44 | throw new RuntimeException( ex ); 45 | } 46 | } 47 | 48 | public static void close( ResultSet rs ) { 49 | if( rs == null ) { 50 | return; 51 | } 52 | try { 53 | rs.close(); 54 | } catch( SQLException ex ) { 55 | throw new RuntimeException( ex ); 56 | } 57 | } 58 | 59 | 60 | static boolean isEmpty( List roots ) { 61 | return roots == null || roots.size()==0; 62 | } 63 | 64 | public static void close( PreparedStatement stmt ) { 65 | if( stmt == null ) { 66 | return ; 67 | } else { 68 | try { 69 | stmt.close(); 70 | } catch( SQLException ex ) { 71 | 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/ReferenceBeanLocator.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | /** 4 | * 5 | */ 6 | public class ReferenceBeanLocator implements BeanLocator { 7 | final String id; 8 | 9 | public ReferenceBeanLocator(String id) { 10 | this.id = id; 11 | } 12 | 13 | public Object locateBean(Context context) { 14 | return context.get(id); 15 | } 16 | 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/Registration.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | import java.lang.ref.WeakReference; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Stack; 7 | 8 | public class Registration { 9 | public final T item; 10 | public final RemovalCallback callBack; 11 | public List dependents; 12 | private List keyIds; 13 | private List keyClasses; 14 | private boolean removing; 15 | private WeakReference refParent; 16 | 17 | public Registration(T o,RemovalCallback callBack, Context parent ) { 18 | item = o; 19 | this.callBack = callBack; 20 | refParent = new WeakReference(parent); 21 | } 22 | 23 | private Context context() { 24 | return refParent.get(); 25 | } 26 | 27 | public void addDependent(Registration rm) { 28 | if( dependents == null ) dependents = new Stack(); 29 | dependents.add( 0,rm ); 30 | } 31 | 32 | public void addKey(String id) { 33 | if( keyIds == null ) keyIds = new ArrayList(); 34 | keyIds.add(id); 35 | } 36 | 37 | public void addKey(Class c ) { 38 | if( keyClasses == null ) keyClasses = new ArrayList(); 39 | keyClasses.add(c); 40 | } 41 | 42 | public boolean contains(Class c) { 43 | if( keyClasses == null ) return false; 44 | return keyClasses.contains(c); 45 | } 46 | 47 | public void remove() { 48 | if( removing ) return; 49 | removing = true; 50 | 51 | // Do dependents (ie child objects first) 52 | if( dependents != null ) { 53 | for( Registration rm : dependents) { 54 | rm.remove(); 55 | } 56 | dependents = null; 57 | } 58 | 59 | 60 | if( callBack != null ) { 61 | callBack.onRemove(item); 62 | } 63 | if( keyIds != null ) { 64 | for( String id : keyIds ) { 65 | context().itemByName.remove(id); 66 | } 67 | keyIds = null; 68 | } 69 | if( keyClasses != null ) { 70 | for( Class c : keyClasses ) { 71 | context().itemByClass.remove(c); 72 | } 73 | keyClasses = null; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/RemovalCallback.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | public interface RemovalCallback { 4 | public void onRemove( T item ); 5 | } 6 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/RootContextLocator.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | /** 4 | * 5 | * @author brad 6 | */ 7 | public class RootContextLocator { 8 | private RootContext rootContext; 9 | 10 | public RootContext getRootContext() { 11 | return rootContext; 12 | } 13 | 14 | public void setRootContext( RootContext rootContext ) { 15 | this.rootContext = rootContext; 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/SimpleBeanLocator.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | /** 4 | * 5 | */ 6 | public class SimpleBeanLocator implements BeanLocator{ 7 | 8 | final Object bean; 9 | 10 | public SimpleBeanLocator(Object bean) { 11 | this.bean = bean; 12 | } 13 | 14 | 15 | public Object locateBean(Context context) { 16 | return bean; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/SingletonFactory.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | 11 | /** 12 | * 13 | * @author brad 14 | */ 15 | public class SingletonFactory implements Factory{ 16 | 17 | private static final Logger log = LoggerFactory.getLogger(SingletonFactory.class); 18 | 19 | private Object bean; 20 | private Class[] keyClasses; 21 | 22 | @Override 23 | public Class[] keyClasses() { 24 | return keyClasses; 25 | } 26 | 27 | @Override 28 | public String[] keyIds() { 29 | return null; 30 | } 31 | 32 | @Override 33 | public Registration insert(RootContext context, Context requestContext) { 34 | return context.put(bean); 35 | } 36 | 37 | @Override 38 | public void init(RootContext context) { 39 | 40 | } 41 | 42 | @Override 43 | public void destroy() { 44 | if( bean instanceof Closeable) { 45 | log.warn( "closing: " + bean.getClass()); 46 | Closeable c = (Closeable) bean; 47 | try { 48 | c.close(); 49 | } catch( IOException ex ) { 50 | log.error("Exception closing: " + bean.getClass(), ex); 51 | } 52 | } else { 53 | log.warn( "not closing: " + bean.getClass()); 54 | } 55 | } 56 | 57 | @Override 58 | public void onRemove(Object item) { 59 | 60 | } 61 | 62 | public String getBeanClass() { 63 | return bean.getClass().getCanonicalName(); 64 | } 65 | 66 | public String getKeyClasses() { 67 | String s = ""; 68 | for( Class c : keyClasses ) { 69 | s = s + c.getCanonicalName() + ","; 70 | } 71 | return s; 72 | } 73 | 74 | public void setBean( Object bean ) { 75 | this.bean = bean; 76 | List list = new ArrayList(); 77 | list.add( bean.getClass()); 78 | log.debug("setBean: " + bean.getClass().getCanonicalName()); 79 | for(Class c : this.bean.getClass().getInterfaces() ) { 80 | list.add( c ); 81 | log.debug(" - add interface: " + c.getCanonicalName()); 82 | } 83 | Class superClass = this.bean.getClass().getSuperclass(); 84 | while( superClass != null ) { 85 | list.add(superClass); 86 | superClass = superClass.getSuperclass(); 87 | } 88 | 89 | this.keyClasses = new Class[list.size()]; 90 | list.toArray( keyClasses ); 91 | } 92 | 93 | public Object getBean() { 94 | return bean; 95 | } 96 | 97 | @Override 98 | public String toString() { 99 | if( bean != null ) { 100 | return "SingletonFactory(" + bean.getClass() + ")"; 101 | } else { 102 | return super.toString(); 103 | } 104 | } 105 | 106 | 107 | 108 | 109 | } 110 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/SpringContextFactory.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | import java.io.File; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.support.FileSystemXmlApplicationContext; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | 10 | /** 11 | * 12 | */ 13 | public class SpringContextFactory implements Factory{ 14 | 15 | private static final Logger log = LoggerFactory.getLogger(CtxRootFolderFactory.class); 16 | 17 | private String appContext; 18 | private ApplicationContext springContext; 19 | Class[] classes = new Class[]{ApplicationContext.class}; 20 | 21 | @Override 22 | public Class[] keyClasses() { 23 | return classes; 24 | } 25 | 26 | @Override 27 | public String[] keyIds() { 28 | return null; 29 | } 30 | 31 | @Override 32 | public Registration insert(RootContext context, Context requestContext) { 33 | Registration reg = context.put(springContext, this); 34 | return reg; 35 | } 36 | 37 | @Override 38 | public void init(RootContext context) { 39 | log.debug("app context is configured at: " + appContext); 40 | File fXml; 41 | if( appContext.startsWith("/") || appContext.contains(":")) { 42 | log.debug("app context path looks like an absolute path"); 43 | fXml = new File(appContext); 44 | } else { 45 | log.debug("app context path looks relative, so resolving from rootFolder"); 46 | File root = context.get("rootFolder"); 47 | fXml = new File(root,appContext); 48 | } 49 | log.debug("absolute path: " + fXml.getAbsolutePath()); 50 | springContext = new FileSystemXmlApplicationContext(appContext); 51 | } 52 | 53 | @Override 54 | public void destroy() { 55 | springContext = null; 56 | } 57 | 58 | @Override 59 | public void onRemove(ApplicationContext item) { 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/SpringFactory.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.springframework.context.ApplicationContext; 6 | 7 | /** 8 | * 9 | */ 10 | public class SpringFactory implements Factory { 11 | private Class[] classes; 12 | private String id; 13 | 14 | public Class[] keyClasses() { 15 | return classes; 16 | } 17 | 18 | public String[] keyIds() { 19 | return new String[] {id}; 20 | } 21 | 22 | public Registration insert(RootContext context, Context requestContext) { 23 | ApplicationContext appContext = requestContext.get(ApplicationContext.class); 24 | Object o = appContext.getBean(id); 25 | return context.put(o); 26 | } 27 | 28 | public void init(RootContext context) { 29 | } 30 | 31 | public void destroy() { 32 | } 33 | 34 | public void onRemove(Object item) { 35 | } 36 | 37 | 38 | /** 39 | * @return the classes 40 | */ 41 | public String getClasses() { 42 | String s = ""; 43 | for(Class clazz : classes ) { 44 | s = s +"," + clazz.getCanonicalName(); 45 | } 46 | return s; 47 | } 48 | 49 | /** 50 | * @param classes the classes to set 51 | */ 52 | public void setClasses(String classes) { 53 | String[] classNames = classes.split(","); 54 | List list = new ArrayList(); 55 | for( String className : classNames ) { 56 | Class clazz; 57 | try { 58 | clazz = Class.forName(className); 59 | } catch (ClassNotFoundException ex) { 60 | throw new RuntimeException(className, ex); 61 | } 62 | list.add(clazz); 63 | } 64 | this.classes = new Class[list.size()]; 65 | list.toArray(this.classes); 66 | } 67 | 68 | /** 69 | * @return the ids 70 | */ 71 | public String getId() { 72 | return id; 73 | } 74 | 75 | /** 76 | * @param ids the ids to set 77 | */ 78 | public void setIds(String id) { 79 | this.id = id; 80 | } 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/context/date/CtxDateFormatFactory.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.context.date; 2 | 3 | import com.ettrema.context.Context; 4 | import com.ettrema.context.Factory; 5 | import com.ettrema.context.Registration; 6 | import com.ettrema.context.RootContext; 7 | import java.text.DateFormat; 8 | 9 | public class CtxDateFormatFactory implements Factory { 10 | 11 | public static Class[] classes = {DateFormat.class}; 12 | 13 | public CtxDateFormatFactory() { 14 | } 15 | 16 | public Class[] keyClasses() { 17 | return classes; 18 | } 19 | 20 | public String[] keyIds() { 21 | return null; 22 | } 23 | 24 | public Registration insert(RootContext context, Context requestContext) { 25 | DateFormat d = DateFormat.getDateInstance(DateFormat.SHORT); 26 | Registration reg = requestContext.put(d,this); 27 | return reg; 28 | } 29 | 30 | public void init(RootContext context) { 31 | } 32 | 33 | public void destroy() { 34 | } 35 | 36 | public void onRemove(DateFormat item) { 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/TableCreatorService.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db; 2 | 3 | import com.ettrema.db.dialects.Dialect; 4 | import com.ettrema.common.Service; 5 | import com.ettrema.context.Context; 6 | import com.ettrema.context.Executable2; 7 | import com.ettrema.context.RootContext; 8 | import com.ettrema.context.PostgresUtils; 9 | import java.sql.Connection; 10 | import java.sql.SQLException; 11 | import java.util.List; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | /** 16 | * 17 | * @author brad 18 | */ 19 | public class TableCreatorService implements Service { 20 | 21 | private static final Logger log = LoggerFactory.getLogger(TableCreatorService.class); 22 | private final RootContext rootContext; 23 | private final Dialect dialect; 24 | protected List definitionSources; 25 | 26 | public TableCreatorService(RootContext rootContext, List definitionSources, Dialect dialect) { 27 | this.rootContext = rootContext; 28 | this.definitionSources = definitionSources; 29 | this.dialect = dialect; 30 | } 31 | 32 | @Override 33 | public void start() { 34 | rootContext.execute(new Executable2() { 35 | 36 | @Override 37 | public void execute(Context context) { 38 | log.warn("doing check and create of tables. Tables which do not exist will be created"); 39 | try { 40 | Connection con = PostgresUtils.con(); 41 | processTableDefinitions(con); 42 | } catch (Exception e) { 43 | log.error("Exception checking table definitions, will continue anyway...", e); 44 | } 45 | } 46 | }); 47 | } 48 | 49 | public void processTableDefinitions(Connection con) { 50 | for (TableDefinitionSource source : definitionSources) { 51 | for (Table t : source.getTableDefinitions()) { 52 | checkAndCreate(t, con, source); 53 | } 54 | } 55 | 56 | } 57 | 58 | private void checkAndCreate(Table table, Connection con, TableDefinitionSource source) { 59 | if (!dialect.tableExists(table.tableName, con)) { 60 | log.warn("create table: " + table.tableName); 61 | dialect.createTable(table, con); 62 | source.onCreate(table, con); 63 | commit(con); 64 | } 65 | } 66 | 67 | private void commit(Connection con) { 68 | try { 69 | con.commit(); 70 | } catch (SQLException ex) { 71 | throw new RuntimeException(ex); 72 | } 73 | } 74 | 75 | @Override 76 | public void stop() { 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/TableDefinitionSource.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db; 2 | 3 | import java.sql.Connection; 4 | import java.util.List; 5 | 6 | /** 7 | * 8 | * @author brad 9 | */ 10 | public interface TableDefinitionSource { 11 | List getTableDefinitions(); 12 | 13 | void onCreate(Table t, Connection con); 14 | } 15 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/UseConnection.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db; 2 | 3 | import com.bradmcevoy.utils.With; 4 | import java.sql.Connection; 5 | import java.sql.PreparedStatement; 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import javax.sql.DataSource; 9 | 10 | /** 11 | * 12 | * @author brad 13 | */ 14 | public class UseConnection { 15 | 16 | 17 | 18 | private final DataSource ds; 19 | 20 | public UseConnection( DataSource ds ) { 21 | this.ds = ds; 22 | } 23 | 24 | public O use( With with ) { 25 | Connection con = null; 26 | try { 27 | con = ds.getConnection(); 28 | O o = with.use( con ); 29 | commit( con ); 30 | return o; 31 | } catch( Exception ex ) { 32 | rollback(con); 33 | throw new RuntimeException( ex ); 34 | } finally { 35 | close( con ); 36 | } 37 | } 38 | 39 | private void commit(Connection con) throws SQLException { 40 | con.commit(); 41 | } 42 | 43 | private void rollback( Connection con ) { 44 | if( con != null ) { 45 | try { 46 | con.rollback(); 47 | } catch( SQLException ex ) { 48 | 49 | } 50 | } 51 | } 52 | 53 | public static void close( Connection con ) { 54 | if( con != null ) { 55 | try { 56 | con.close(); 57 | } catch( SQLException ex ) { 58 | } 59 | } 60 | } 61 | 62 | public static void close( ResultSet rs ) { 63 | if( rs != null ) { 64 | try { 65 | rs.close(); 66 | } catch( SQLException ex ) { 67 | } 68 | } 69 | } 70 | 71 | public static void close( PreparedStatement stmt ) { 72 | if( stmt != null ) { 73 | try { 74 | stmt.close(); 75 | } catch( SQLException ex ) { 76 | } 77 | } 78 | 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/dialects/Dialect.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.dialects; 2 | 3 | import com.ettrema.db.Table; 4 | import com.ettrema.db.types.FieldType; 5 | import java.sql.Connection; 6 | 7 | /** 8 | * 9 | * @author brad 10 | */ 11 | public interface Dialect { 12 | boolean tableExists(String name, Connection con); 13 | 14 | void createTable( Table table, Connection con ); 15 | 16 | String getTypeName(FieldType type); 17 | } 18 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/dialects/H2Dialect.java: -------------------------------------------------------------------------------- 1 | 2 | package com.ettrema.db.dialects; 3 | 4 | import com.ettrema.db.Table; 5 | import com.ettrema.db.types.BinaryType; 6 | import com.ettrema.db.types.FieldType; 7 | import java.sql.Connection; 8 | import java.sql.ResultSet; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | /** 13 | * Mostly the same as postgres, but need to uppercase table names 14 | * 15 | * @author brad 16 | */ 17 | public class H2Dialect implements Dialect{ 18 | 19 | private static final Logger log = LoggerFactory.getLogger(H2Dialect.class); 20 | 21 | 22 | private String catalog; 23 | 24 | private String schemaPattern; 25 | 26 | @Override 27 | public boolean tableExists( String name, Connection con ) { 28 | try { 29 | // ** make table name uppercase ** 30 | ResultSet tables = con.getMetaData().getTables( catalog, schemaPattern, name.toUpperCase(), null ); 31 | boolean b = tables.next(); 32 | log.warn( "does table exist: " + name + " = " + b); 33 | return b; 34 | } catch(Exception e) { 35 | throw new RuntimeException( "Exception looking for tables: catalog:" + catalog + " schema:" + schemaPattern, e); 36 | } 37 | } 38 | 39 | @Override 40 | public void createTable( Table table, Connection con ) { 41 | table.createTable( con, this ); 42 | } 43 | 44 | public String getCatalog() { 45 | return catalog; 46 | } 47 | 48 | public void setCatalog( String catalog ) { 49 | this.catalog = catalog; 50 | } 51 | 52 | public String getSchemaPattern() { 53 | return schemaPattern; 54 | } 55 | 56 | public void setSchemaPattern( String schemaPattern ) { 57 | this.schemaPattern = schemaPattern; 58 | } 59 | 60 | @Override 61 | public String getTypeName( FieldType type ) { 62 | if( type instanceof BinaryType) { 63 | return "bytea"; 64 | } else { 65 | return type.toString().toLowerCase(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/dialects/HqlDialect.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.dialects; 2 | 3 | import com.ettrema.db.Table; 4 | import com.ettrema.db.types.FieldType; 5 | import java.sql.Connection; 6 | import java.sql.ResultSet; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * 12 | * @author brad 13 | */ 14 | public class HqlDialect implements Dialect{ 15 | 16 | private static final Logger log = LoggerFactory.getLogger(HqlDialect.class); 17 | 18 | 19 | private String catalog; 20 | 21 | private String schemaPattern; 22 | 23 | @Override 24 | public boolean tableExists( String name, Connection con ) { 25 | try { 26 | ResultSet tables = con.getMetaData().getTables( catalog, schemaPattern, name.toUpperCase(), null ); 27 | boolean b = tables.next(); 28 | log.warn( "does table exist: " + name + " = " + b); 29 | return b; 30 | } catch(Exception e) { 31 | throw new RuntimeException( "Exception looking for tables: catalog:" + catalog + " schema:" + schemaPattern, e); 32 | } 33 | } 34 | 35 | @Override 36 | public void createTable( Table table, Connection con ) { 37 | table.createTable( con, this ); 38 | } 39 | 40 | public String getCatalog() { 41 | return catalog; 42 | } 43 | 44 | public void setCatalog( String catalog ) { 45 | this.catalog = catalog; 46 | } 47 | 48 | public String getSchemaPattern() { 49 | return schemaPattern; 50 | } 51 | 52 | public void setSchemaPattern( String schemaPattern ) { 53 | this.schemaPattern = schemaPattern; 54 | } 55 | 56 | @Override 57 | public String getTypeName( FieldType type ) { 58 | return type.toString().toLowerCase(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/dialects/PostgresDialect.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.dialects; 2 | 3 | import com.ettrema.db.Table; 4 | import com.ettrema.db.types.BinaryType; 5 | import com.ettrema.db.types.FieldType; 6 | import java.sql.Connection; 7 | import java.sql.ResultSet; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | /** 12 | * 13 | * @author brad 14 | */ 15 | public class PostgresDialect implements Dialect { 16 | 17 | private static final Logger log = LoggerFactory.getLogger(PostgresDialect.class); 18 | 19 | 20 | private String catalog; 21 | 22 | private String schemaPattern; 23 | 24 | @Override 25 | public boolean tableExists( String name, Connection con ) { 26 | try { 27 | ResultSet tables = con.getMetaData().getTables( catalog, schemaPattern, name, null ); 28 | boolean b = tables.next(); 29 | log.warn( "does table exist: " + name + " = " + b); 30 | return b; 31 | } catch(Exception e) { 32 | throw new RuntimeException( "Exception looking for tables: catalog:" + catalog + " schema:" + schemaPattern, e); 33 | } 34 | } 35 | 36 | @Override 37 | public void createTable( Table table, Connection con ) { 38 | table.createTable( con, this ); 39 | } 40 | 41 | public String getCatalog() { 42 | return catalog; 43 | } 44 | 45 | public void setCatalog( String catalog ) { 46 | this.catalog = catalog; 47 | } 48 | 49 | public String getSchemaPattern() { 50 | return schemaPattern; 51 | } 52 | 53 | public void setSchemaPattern( String schemaPattern ) { 54 | this.schemaPattern = schemaPattern; 55 | } 56 | 57 | @Override 58 | public String getTypeName( FieldType type ) { 59 | if( type instanceof BinaryType) { 60 | return "bytea"; 61 | } else { 62 | return type.toString().toLowerCase(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/BinaryType.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | import java.io.Serializable; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | 8 | public class BinaryType implements FieldType, Serializable { 9 | 10 | private static final long serialVersionUID = 1L; 11 | 12 | @Override 13 | public String toString() { 14 | return "binary"; 15 | } 16 | 17 | @Override 18 | public byte[] get(String name, ResultSet rs) throws SQLException { 19 | return rs.getBytes(name); 20 | } 21 | 22 | @Override 23 | public void set(PreparedStatement stmt, int index, byte[] value) throws SQLException { 24 | if (value == null) { 25 | stmt.setNull(index, java.sql.Types.VARBINARY); 26 | } else { 27 | stmt.setBytes(index, value); 28 | } 29 | } 30 | 31 | @Override 32 | public byte[] parse(Object v) { 33 | if (v instanceof byte[]) { 34 | return (byte[]) v; 35 | } else { 36 | throw new RuntimeException("Cant parse type of: " + v.getClass()); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/CharacterType.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | import java.io.Serializable; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | import java.sql.Types; 8 | 9 | public class CharacterType implements FieldType, Serializable { 10 | 11 | private static final long serialVersionUID = 1L; 12 | private final int length; 13 | 14 | public CharacterType(int length) { 15 | this.length = length; 16 | } 17 | 18 | public int getLength() { 19 | return length; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "character(" + length + ")"; 25 | } 26 | 27 | @Override 28 | public String get(String name, ResultSet rs) throws SQLException { 29 | return rs.getString(name); 30 | } 31 | 32 | @Override 33 | public void set(PreparedStatement stmt, int index, String value) throws SQLException { 34 | if (value == null) { 35 | stmt.setNull(index, Types.VARCHAR); 36 | } else { 37 | stmt.setString(index, value); 38 | } 39 | } 40 | 41 | @Override 42 | public String parse(Object v) { 43 | if (v instanceof String) { 44 | return (String) v; 45 | } else { 46 | return v.toString(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/CharacterVaryingType.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | import java.io.Serializable; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | import java.sql.Types; 8 | 9 | public class CharacterVaryingType implements FieldType, Serializable { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | @Override 14 | public String toString() { 15 | return "character varying"; 16 | } 17 | 18 | @Override 19 | public String get(String name, ResultSet rs) throws SQLException { 20 | return rs.getString(name); 21 | } 22 | 23 | @Override 24 | public void set(PreparedStatement stmt, int index, String value) throws SQLException { 25 | if (value == null) { 26 | stmt.setNull(index, Types.VARCHAR); 27 | } else { 28 | stmt.setString(index, value); 29 | } 30 | } 31 | 32 | @Override 33 | public String parse(Object v) { 34 | if (v instanceof String) { 35 | return (String) v; 36 | } else { 37 | return v.toString(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/FieldType.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | import java.sql.PreparedStatement; 4 | import java.sql.ResultSet; 5 | import java.sql.SQLException; 6 | 7 | public interface FieldType { 8 | 9 | T get(String name, ResultSet rs) throws SQLException; 10 | 11 | void set(PreparedStatement stmt, int index, T value) throws SQLException; 12 | 13 | /** 14 | * Attempt to parse whatever object is given to the actual value. Should handle 15 | * strings and similar types. Eg Integer should handle long, date should 16 | * handle timestamp, etc 17 | * 18 | * @param v 19 | * @return 20 | */ 21 | T parse(Object v); 22 | } 23 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/FieldTypes.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | /** 4 | * 5 | * @author brad 6 | */ 7 | public class FieldTypes { 8 | 9 | public final static CharacterVaryingType CHARACTER_VARYING = new CharacterVaryingType(); 10 | public final static BinaryType BINARY = new BinaryType(); 11 | public final static IntegerType INTEGER = new IntegerType(); 12 | public final static LongType LONG = new LongType(); 13 | public final static TimestampType TIMESTAMP = new TimestampType(); 14 | public final static Float8Type FLOAT8 = new Float8Type(); 15 | public final static FieldType[] allTypes = { 16 | CHARACTER_VARYING, 17 | BINARY, 18 | INTEGER, 19 | LONG, 20 | TIMESTAMP, 21 | FLOAT8 22 | }; 23 | 24 | public static CharacterType character(int length) { 25 | return new CharacterType(length); 26 | } 27 | 28 | public static FieldType fromName(String name) { 29 | for (FieldType type : allTypes) { 30 | if (type.toString().equals(name)) { 31 | return type; 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/Float8Type.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | import java.io.Serializable; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | import java.sql.Types; 8 | 9 | /** 10 | * 11 | * @author brad 12 | */ 13 | public class Float8Type implements FieldType, Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | @Override 18 | public String toString() { 19 | return "double precision"; 20 | } 21 | 22 | @Override 23 | public Float get(String name, ResultSet rs) throws SQLException { 24 | return rs.getFloat(name); 25 | } 26 | 27 | @Override 28 | public void set(PreparedStatement stmt, int index, Float value) throws SQLException { 29 | if (value == null) { 30 | stmt.setNull(index, Types.REAL); 31 | } else { 32 | stmt.setFloat(index, value); 33 | } 34 | 35 | } 36 | 37 | @Override 38 | public Float parse(Object v) { 39 | if (v instanceof Float) { 40 | return (Float) v; 41 | } else if (v instanceof Double) { 42 | Double d = (Double) v; 43 | return d.floatValue(); 44 | } else if (v instanceof String) { 45 | String s = (String) v; 46 | return Float.parseFloat(s); 47 | } else { 48 | throw new RuntimeException("Cant convert type: " + v.getClass()); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/IntegerType.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | import java.io.Serializable; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | import java.sql.Types; 8 | 9 | public class IntegerType implements FieldType, Serializable { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | @Override 14 | public String toString() { 15 | return "integer"; 16 | } 17 | 18 | @Override 19 | public Integer get(String name, ResultSet rs) throws SQLException { 20 | return rs.getInt(name); 21 | } 22 | 23 | @Override 24 | public void set(PreparedStatement stmt, int index, Integer value) throws SQLException { 25 | if (value == null) { 26 | stmt.setNull(index, Types.INTEGER); 27 | } else { 28 | stmt.setInt(index, value); 29 | } 30 | 31 | } 32 | 33 | @Override 34 | public Integer parse(Object v) { 35 | if (v instanceof Integer) { 36 | return (Integer) v; 37 | } else if (v instanceof Long) { 38 | Long d = (Long) v; 39 | return d.intValue(); 40 | } else if (v instanceof String) { 41 | String s = (String) v; 42 | return Integer.parseInt(s); 43 | } else { 44 | throw new RuntimeException("Cant convert type: " + v.getClass()); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/LongType.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | import java.io.Serializable; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | 8 | /** 9 | * 10 | * @author brad 11 | */ 12 | public class LongType implements FieldType, Serializable { 13 | 14 | private static final long serialVersionUID = 1L; 15 | 16 | @Override 17 | public String toString() { 18 | return "long"; 19 | } 20 | 21 | @Override 22 | public Long get(String name, ResultSet rs) throws SQLException { 23 | Object oLong = rs.getObject(name); 24 | if( oLong == null ) { 25 | return null; 26 | } else { 27 | return (Long)oLong; 28 | } 29 | } 30 | 31 | @Override 32 | public void set(PreparedStatement stmt, int index, Long value) throws SQLException { 33 | if (value == null) { 34 | stmt.setNull(index, java.sql.Types.BIGINT); 35 | } else { 36 | stmt.setLong(index, value); 37 | } 38 | } 39 | 40 | @Override 41 | public Long parse(Object v) { 42 | if (v instanceof Long) { 43 | return (Long) v; 44 | } else if (v instanceof Integer) { 45 | Integer d = (Integer) v; 46 | return d.longValue(); 47 | } else if (v instanceof String) { 48 | String s = (String) v; 49 | return Long.parseLong(s); 50 | } else { 51 | throw new RuntimeException("Cant convert type: " + v.getClass()); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/com/ettrema/db/types/TimestampType.java: -------------------------------------------------------------------------------- 1 | package com.ettrema.db.types; 2 | 3 | import java.io.Serializable; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | import java.sql.Timestamp; 8 | import java.sql.Types; 9 | 10 | /** 11 | * 12 | * @author brad 13 | */ 14 | public class TimestampType implements FieldType, Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | @Override 19 | public String toString() { 20 | return "timestamp"; 21 | } 22 | 23 | @Override 24 | public java.sql.Timestamp get(String name, ResultSet rs) throws SQLException { 25 | return rs.getTimestamp(name); 26 | } 27 | 28 | @Override 29 | public void set(PreparedStatement stmt, int index, Timestamp value) throws SQLException { 30 | if (value == null) { 31 | stmt.setNull(index, Types.TIMESTAMP); 32 | } else { 33 | stmt.setTimestamp(index, value); 34 | } 35 | } 36 | 37 | @Override 38 | public java.sql.Timestamp parse(Object v) { 39 | if (v instanceof java.sql.Timestamp) { 40 | return (java.sql.Timestamp) v; 41 | } else if (v instanceof String) { 42 | String s = (String) v; 43 | return java.sql.Timestamp.valueOf(s); 44 | } else { 45 | throw new RuntimeException("Cant convert type: " + v.getClass()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/Archiver.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import io.milton.common.FileUtils; 4 | import java.io.File; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * For removing old versions of local files when they're updated. 10 | * 11 | * This bit is quite sensitive, we really can't afford to eat anyone's files! 12 | * 13 | * So this implementation is very defensive, it never deletes files, just moves 14 | * them into a versions folder 15 | * 16 | * @author brad 17 | */ 18 | public class Archiver { 19 | 20 | private static final Logger log = LoggerFactory.getLogger(Archiver.class); 21 | 22 | public Archiver() { 23 | } 24 | 25 | 26 | 27 | public void archive(File f) { 28 | File versions = getVersionsDir(f); 29 | File dest = new File(versions, f.getName()); 30 | String name = FileUtils.incrementFileName(dest.getName(), true); 31 | while(dest.exists()) { 32 | name = FileUtils.incrementFileName(name, false); 33 | dest = new File(versions, name); 34 | } 35 | if( !f.renameTo(dest) ) { 36 | throw new RuntimeException("Couldnt archive old file: " + f.getAbsolutePath() + " to: " + dest.getAbsolutePath() ); 37 | } 38 | } 39 | 40 | private File getVersionsDir(File contentFile) { 41 | File hiddenDir = new File(contentFile.getParent(), ".spliffy"); 42 | if (!hiddenDir.exists()) { 43 | log.info("getVersionsDir: Creating missing hidden dir", hiddenDir.getAbsolutePath()); 44 | if (!hiddenDir.mkdirs()) { 45 | throw new RuntimeException("Couldnt create directory: " + hiddenDir.getAbsolutePath()); 46 | } 47 | } 48 | File versionsDir = new File(hiddenDir, "versions"); 49 | if( !versionsDir.exists()) { 50 | log.info("getVersionsDir: Creating missing versions dir", versionsDir.getAbsolutePath()); 51 | if(!versionsDir.mkdirs() ) { 52 | throw new RuntimeException("Couldnt create directory for old versions: " + versionsDir.getAbsolutePath()); 53 | } 54 | } 55 | return versionsDir; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/DbInitialiser.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import com.ettrema.db.UseConnection; 4 | import com.ettrema.db.dialects.Dialect; 5 | import com.ettrema.db.dialects.HqlDialect; 6 | import java.io.File; 7 | import javax.sql.DataSource; 8 | import org.apache.commons.dbcp.ConnectionFactory; 9 | import org.apache.commons.dbcp.DriverManagerConnectionFactory; 10 | import org.apache.commons.dbcp.PoolableConnectionFactory; 11 | import org.apache.commons.dbcp.PoolingDataSource; 12 | import org.apache.commons.pool.impl.GenericObjectPool; 13 | 14 | /** 15 | * Just hard codes initialisation of an embedded H2 instance 16 | * 17 | * 18 | * @author brad 19 | */ 20 | public class DbInitialiser { 21 | 22 | private final DataSource ds; 23 | private final UseConnection useConnection; 24 | private final Dialect dialect; 25 | 26 | public DbInitialiser(File dbFile) { 27 | String url = "jdbc:h2:" + dbFile.getAbsolutePath(); 28 | 29 | GenericObjectPool connectionPool = new GenericObjectPool( null ); 30 | ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( url, "sa", "sa" ); 31 | PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory( connectionFactory, connectionPool, null, null, false, true ); 32 | ds = new PoolingDataSource( connectionPool ); 33 | 34 | this.useConnection = new UseConnection( ds ); 35 | 36 | dialect = new HqlDialect(); 37 | } 38 | 39 | public UseConnection getUseConnection() { 40 | return useConnection; 41 | } 42 | 43 | public Dialect getDialect() { 44 | return dialect; 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/DeltaListener.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import io.milton.common.Path; 4 | import java.io.IOException; 5 | import org.hashsplit4j.triplets.ITriplet; 6 | 7 | /** 8 | * A "delta" here refers to some difference between the client and server 9 | * file systems. 10 | * 11 | * 12 | * @author brad 13 | */ 14 | public interface DeltaListener { 15 | 16 | 17 | void onLocalDeletion(Path path, ITriplet remoteTriplet) throws IOException; 18 | 19 | void onLocalChange(ITriplet localTriplet, Path path, ITriplet remoteTriplet) throws IOException; 20 | 21 | void onRemoteChange(ITriplet remoteTriplet, ITriplet localTriplet, Path path) throws IOException; 22 | 23 | void onRemoteDelete(ITriplet localTriplet, Path path) throws IOException; 24 | 25 | void onTreeConflict(ITriplet remoteTriplet, ITriplet localTriplet, Path path) throws IOException; 26 | 27 | void onFileConflict(ITriplet remoteTriplet, ITriplet localTriplet, Path path) throws IOException; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import io.milton.common.Path; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import org.apache.commons.io.IOUtils; 8 | import org.apache.http.HttpEntity; 9 | import org.apache.http.HttpResponse; 10 | import org.apache.http.client.methods.HttpUriRequest; 11 | 12 | /** 13 | * 14 | * @author brad 15 | */ 16 | public class HttpUtils { 17 | 18 | 19 | /** 20 | * Takes an unencoded local path (eg "/my docs") and turns it into a 21 | * percentage encoded path (eg "/my%20docs"), with the encoded rootPath 22 | * added to the front 23 | * 24 | * @param path 25 | * @return 26 | */ 27 | public static String toHref(Path basePath, Path unencodedPath) { 28 | Path p = basePath; 29 | for (String name : unencodedPath.getParts()) { 30 | p = p.child(io.milton.common.Utils.percentEncode(name)); 31 | } 32 | return p.toString(); 33 | } 34 | 35 | public static int executeHttpWithStatus(org.apache.http.client.HttpClient client, HttpUriRequest m, OutputStream out) throws IOException { 36 | HttpResponse resp = client.execute(m); 37 | HttpEntity entity = resp.getEntity(); 38 | if (entity != null) { 39 | InputStream in = null; 40 | try { 41 | in = entity.getContent(); 42 | if (out != null) { 43 | IOUtils.copy(in, out); 44 | } 45 | } finally { 46 | IOUtils.closeQuietly(in); 47 | } 48 | } 49 | return resp.getStatusLine().getStatusCode(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/MemoryHashCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.sync; 16 | 17 | import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; 18 | import java.util.concurrent.ConcurrentMap; 19 | import org.hashsplit4j.api.HashCache; 20 | 21 | /** 22 | * Uses ConcurrentLinkedHashMap to keep a LRU cache of hashes 23 | * 24 | * @author brad 25 | */ 26 | public class MemoryHashCache implements HashCache { 27 | 28 | private final ConcurrentMap cache; 29 | 30 | public MemoryHashCache() { 31 | cache = new ConcurrentLinkedHashMap.Builder() 32 | .maximumWeightedCapacity(5000) 33 | .initialCapacity(2000) 34 | .build(); 35 | } 36 | 37 | @Override 38 | public boolean hasHash(String key) { 39 | return cache.containsKey(key); 40 | } 41 | 42 | @Override 43 | public void setHash(String key) { 44 | cache.put(key, key); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/MinimalPutsBlobStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import org.hashsplit4j.api.BlobStore; 4 | 5 | /** 6 | * 7 | * @author brad 8 | */ 9 | 10 | 11 | public class MinimalPutsBlobStore implements BlobStore{ 12 | 13 | private final BlobStore wrapped; 14 | 15 | public MinimalPutsBlobStore(BlobStore wrapped) { 16 | this.wrapped = wrapped; 17 | } 18 | 19 | 20 | 21 | @Override 22 | public void setBlob(String hash, byte[] bytes) { 23 | if( !wrapped.hasBlob(hash)) { 24 | wrapped.setBlob(hash, bytes); 25 | } 26 | } 27 | 28 | @Override 29 | public byte[] getBlob(String string) { 30 | if( wrapped.hasBlob(string)) { 31 | return wrapped.getBlob(string); 32 | } 33 | return null; 34 | } 35 | 36 | @Override 37 | public boolean hasBlob(String string) { 38 | return wrapped.hasBlob(string); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/MinimalPutsHashStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import java.util.List; 4 | import org.hashsplit4j.api.Fanout; 5 | import org.hashsplit4j.api.HashStore; 6 | 7 | /** 8 | * 9 | * @author brad 10 | */ 11 | 12 | 13 | public class MinimalPutsHashStore implements HashStore{ 14 | 15 | private final HashStore wrapped; 16 | 17 | public MinimalPutsHashStore(HashStore wrapped) { 18 | this.wrapped = wrapped; 19 | } 20 | 21 | 22 | 23 | @Override 24 | public void setChunkFanout(String string, List list, long l) { 25 | if( !wrapped.hasChunk(string)) { 26 | wrapped.setChunkFanout(string, list, l); 27 | } 28 | } 29 | 30 | @Override 31 | public void setFileFanout(String string, List list, long l) { 32 | if( !wrapped.hasFile(string)) { 33 | wrapped.setFileFanout(string, list, l); 34 | } 35 | } 36 | 37 | @Override 38 | public Fanout getFileFanout(String string) { 39 | if( wrapped.hasFile(string)) { 40 | return wrapped.getFileFanout(string); 41 | } 42 | return null; 43 | } 44 | 45 | @Override 46 | public Fanout getChunkFanout(String string) { 47 | if( wrapped.hasChunk(string)) { 48 | return wrapped.getChunkFanout(string); 49 | } 50 | return null; 51 | } 52 | 53 | @Override 54 | public boolean hasChunk(String string) { 55 | return wrapped.hasChunk(string); 56 | } 57 | 58 | @Override 59 | public boolean hasFile(String string) { 60 | return wrapped.hasFile(string); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/SyncJob.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.sync; 16 | 17 | import java.io.File; 18 | import java.io.IOException; 19 | import java.io.Serializable; 20 | 21 | /** 22 | * 23 | * @author brad 24 | */ 25 | public class SyncJob implements Serializable{ 26 | private File localDir; 27 | private String remoteAddress; 28 | private String user; 29 | private String pwd; 30 | private boolean monitor; 31 | private boolean localReadonly; 32 | 33 | public SyncJob() { 34 | } 35 | 36 | 37 | public SyncJob(File localDir, String sRemoteAddress, String user, String pwd, boolean monitor, boolean readonlyLocal) { 38 | this.localDir = localDir; 39 | this.remoteAddress = sRemoteAddress; 40 | this.user = user; 41 | this.pwd = pwd; 42 | this.monitor = monitor; 43 | this.localReadonly = readonlyLocal; 44 | try { 45 | if (!localDir.exists()) { 46 | throw new RuntimeException("Sync dir does not exist: " + localDir.getCanonicalPath()); 47 | } else if (!localDir.isDirectory()) { 48 | throw new RuntimeException("Sync path is not a directory: " + localDir.getCanonicalPath()); 49 | } 50 | } catch (IOException ex) { 51 | throw new RuntimeException(ex); 52 | } 53 | } 54 | 55 | public String getPwd() { 56 | return pwd; 57 | } 58 | 59 | public void setPwd(String pwd) { 60 | this.pwd = pwd; 61 | } 62 | 63 | 64 | 65 | public String getUser() { 66 | return user; 67 | } 68 | 69 | public void setUser(String user) { 70 | this.user = user; 71 | } 72 | 73 | 74 | 75 | public File getLocalDir() { 76 | return localDir; 77 | } 78 | 79 | public void setLocalDir(File localDir) { 80 | this.localDir = localDir; 81 | } 82 | 83 | 84 | 85 | public String getRemoteAddress() { 86 | return remoteAddress; 87 | } 88 | 89 | public void setRemoteAddress(String remoteAddress) { 90 | this.remoteAddress = remoteAddress; 91 | } 92 | 93 | 94 | 95 | public boolean isMonitor() { 96 | return monitor; 97 | } 98 | 99 | public void setMonitor(boolean monitor) { 100 | this.monitor = monitor; 101 | } 102 | 103 | 104 | 105 | public boolean isLocalReadonly() { 106 | return localReadonly; 107 | } 108 | 109 | public void setLocalReadonly(boolean localReadonly) { 110 | this.localReadonly = localReadonly; 111 | } 112 | 113 | 114 | 115 | } 116 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/SyncStatusStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import io.milton.common.Path; 4 | 5 | /** 6 | * Represents a means of recording what version of a resource was last synced 7 | * 8 | * @author brad 9 | */ 10 | public interface SyncStatusStore { 11 | 12 | String findBackedUpHash(Path path); 13 | 14 | void setBackedupHash(Path path, String hash); 15 | 16 | /** 17 | * Called when the syncronisation has removed a file 18 | * 19 | * @param path 20 | */ 21 | void clearBackedupHash(Path path); 22 | } 23 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/Utils.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import io.milton.common.Path; 4 | import java.io.File; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import org.hashsplit4j.triplets.ITriplet; 9 | 10 | /** 11 | * 12 | * @author brad 13 | */ 14 | public class Utils { 15 | 16 | public static boolean ignored(File childFile) { 17 | return ignored(childFile, null); 18 | } 19 | 20 | public static boolean ignored(File childFile, List ignoredPatterns) { 21 | if( childFile.getName().equals(".ksync") ) { // usually ignore resources starting with a dot, but special case for .mil directory 22 | return true; 23 | } 24 | if( ignoredPatterns != null ) { 25 | for( String s : ignoredPatterns) { 26 | if( childFile.getName().equals(s) || childFile.getName().matches(s)) { 27 | return true; 28 | } 29 | } 30 | } 31 | return childFile.isHidden() || childFile.getName().startsWith("."); 32 | } 33 | 34 | public static boolean ignored(String name) { 35 | if( name == null ) { 36 | return false; //indicates the root of Path 37 | } 38 | if( name.equals(".mil") ) { // usually ignore resources starting with a dot, but special case for .mil directory 39 | return false; 40 | } 41 | return name.startsWith("."); 42 | } 43 | 44 | public static boolean ignored(Path p) { 45 | while (p != null && p.getName() != null ) { 46 | if (Utils.ignored(p.getName())) { 47 | return true; 48 | } 49 | p = p.getParent(); 50 | } 51 | return false; 52 | } 53 | 54 | public static Map toMap(File[] files) { 55 | Map map = new HashMap<>(); 56 | if (files != null) { 57 | for (File r : files) { 58 | map.put(r.getName(), r); 59 | } 60 | } 61 | return map; 62 | } 63 | 64 | public static Map toMap(List triplets) { 65 | Map map = new HashMap<>(); 66 | if (triplets != null) { 67 | for (ITriplet r : triplets) { 68 | map.put(r.getName(), r); 69 | } 70 | } 71 | return map; 72 | } 73 | 74 | public static File toFile(File root, Path path) { 75 | File f = root; 76 | for (String fname : path.getParts()) { 77 | f = new File(f, fname); 78 | } 79 | return f; 80 | } 81 | 82 | public static String toType(File child) { 83 | return child.isDirectory() ? "d" : "f"; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/WriteThroughBlobStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import org.hashsplit4j.api.BlobStore; 4 | 5 | /** 6 | * Always write to both 7 | * 8 | * getBlob reads from primary only 9 | * 10 | * hasBlob reads from secondary only 11 | * 12 | * @author brad 13 | */ 14 | public class WriteThroughBlobStore implements BlobStore { 15 | private final BlobStore primary; 16 | private final BlobStore secondary; 17 | 18 | public WriteThroughBlobStore(BlobStore primary, BlobStore secondary) { 19 | this.primary = primary; 20 | this.secondary = secondary; 21 | } 22 | 23 | @Override 24 | public void setBlob(String hash, byte[] bytes) { 25 | primary.setBlob(hash, bytes); 26 | secondary.setBlob(hash, bytes); 27 | } 28 | 29 | @Override 30 | public byte[] getBlob(String hash) { 31 | byte[] arr = primary.getBlob(hash); 32 | if( arr == null ) { 33 | arr = secondary.getBlob(hash); 34 | } 35 | return arr; 36 | } 37 | 38 | @Override 39 | public boolean hasBlob(String hash) { 40 | return secondary.hasBlob(hash); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/WriteThroughHashStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync; 2 | 3 | import java.util.List; 4 | import org.hashsplit4j.api.Fanout; 5 | import org.hashsplit4j.api.HashStore; 6 | 7 | /** 8 | * 9 | * @author brad 10 | */ 11 | public class WriteThroughHashStore implements HashStore{ 12 | private final HashStore primary; 13 | private final HashStore secondary; 14 | 15 | public WriteThroughHashStore(HashStore primary, HashStore secondary) { 16 | this.primary = primary; 17 | this.secondary = secondary; 18 | } 19 | 20 | @Override 21 | public void setChunkFanout(String hash, List blobHashes, long actualContentLength) { 22 | primary.setChunkFanout(hash, blobHashes, actualContentLength); 23 | secondary.setChunkFanout(hash, blobHashes, actualContentLength); 24 | } 25 | 26 | @Override 27 | public void setFileFanout(String hash, List fanoutHashes, long actualContentLength) { 28 | primary.setFileFanout(hash, fanoutHashes, actualContentLength); 29 | secondary.setFileFanout(hash, fanoutHashes, actualContentLength); 30 | } 31 | 32 | @Override 33 | public Fanout getFileFanout(String fileHash) { 34 | Fanout f = primary.getFileFanout(fileHash); 35 | return f; 36 | } 37 | 38 | @Override 39 | public Fanout getChunkFanout(String fanoutHash) { 40 | return primary.getChunkFanout(fanoutHash); 41 | } 42 | 43 | @Override 44 | public boolean hasChunk(String fanoutHash) { 45 | return secondary.hasChunk(fanoutHash); 46 | } 47 | 48 | @Override 49 | public boolean hasFile(String fileHash) { 50 | return secondary.hasFile(fileHash); 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/event/DownloadSyncEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.sync.event; 18 | 19 | import io.milton.event.Event; 20 | import java.io.File; 21 | 22 | 23 | /** 24 | * 25 | * @author brad 26 | */ 27 | public class DownloadSyncEvent implements Event{ 28 | private final File localFile; 29 | 30 | public DownloadSyncEvent(File localFile) { 31 | this.localFile = localFile; 32 | } 33 | 34 | public File getLocalFile() { 35 | return localFile; 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/event/EventUtils.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.event; 2 | 3 | import io.milton.event.Event; 4 | import io.milton.event.EventManager; 5 | import io.milton.http.exceptions.BadRequestException; 6 | import io.milton.http.exceptions.ConflictException; 7 | import io.milton.http.exceptions.NotAuthorizedException; 8 | 9 | /** 10 | * 11 | * @author brad 12 | */ 13 | public class EventUtils { 14 | 15 | public static void fireQuietly(EventManager eventManager, Event e) { 16 | try { 17 | eventManager.fireEvent( e ); 18 | } catch( ConflictException | BadRequestException | NotAuthorizedException ex ) { 19 | throw new RuntimeException( ex ); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/event/FileChangedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.sync.event; 18 | 19 | import io.milton.event.Event; 20 | import java.io.File; 21 | 22 | 23 | /** 24 | * Fired when one or more changed files are detected in the file system. 25 | * 26 | * This will usually inform the sync program after local triplet store has been updated. 27 | * The sync client will then scan the local triplet store against the remote. 28 | * 29 | * @author brad 30 | */ 31 | public class FileChangedEvent implements Event{ 32 | private final File root; 33 | private final String rootHash; 34 | 35 | 36 | public FileChangedEvent(File root, String rootHash) { 37 | this.root = root; 38 | this.rootHash = rootHash; 39 | } 40 | 41 | public File getRoot() { 42 | return root; 43 | } 44 | 45 | public String getRootHash() { 46 | return rootHash; 47 | } 48 | 49 | 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/event/FinishedSyncEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.sync.event; 18 | 19 | import io.milton.event.Event; 20 | 21 | 22 | /** 23 | * 24 | * @author brad 25 | */ 26 | public class FinishedSyncEvent implements Event{ 27 | 28 | } 29 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/event/ScanEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.sync.event; 18 | 19 | import io.milton.event.Event; 20 | 21 | 22 | /** 23 | * 24 | * @author brad 25 | */ 26 | public class ScanEvent implements Event{ 27 | 28 | } 29 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/event/TransferProgressEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.sync.event; 16 | 17 | import io.milton.event.Event; 18 | 19 | /** 20 | * 21 | * @author brad 22 | */ 23 | public class TransferProgressEvent implements Event { 24 | 25 | private final long bytesRead; 26 | private final Long totalBytes; 27 | private final String fileName; 28 | 29 | public TransferProgressEvent(long bytesRead, Long totalBytes, String fileName) { 30 | this.bytesRead = bytesRead; 31 | this.totalBytes = totalBytes; 32 | this.fileName = fileName; 33 | } 34 | 35 | public long getBytesRead() { 36 | return bytesRead; 37 | } 38 | 39 | public String getFileName() { 40 | return fileName; 41 | } 42 | 43 | public long getTotalBytes() { 44 | return totalBytes; 45 | } 46 | 47 | public int getPercent() { 48 | if (totalBytes > 0) { 49 | return (int)(bytesRead * 100 / totalBytes); 50 | } else { 51 | return 0; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/event/UploadSyncEvent.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.event; 2 | 3 | import io.milton.event.Event; 4 | import java.io.File; 5 | 6 | 7 | /** 8 | * 9 | * @author brad 10 | */ 11 | 12 | 13 | public class UploadSyncEvent implements Event{ 14 | private final File localFile; 15 | 16 | public UploadSyncEvent(File localFile) { 17 | this.localFile = localFile; 18 | } 19 | 20 | public File getLocalFile() { 21 | return localFile; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/BlobUtils.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.io.RandomAccessFile; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import org.apache.commons.io.IOUtils; 10 | import io.milton.sync.Utils; 11 | import org.hashsplit4j.store.FileBlobStore; 12 | import org.hashsplit4j.triplets.ITriplet; 13 | import org.hashsplit4j.triplets.Triplet; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | /** 18 | * Just moving random stuff out of JdbcLocalTripletStore to make it tidier 19 | * 20 | * @author brad 21 | */ 22 | public class BlobUtils { 23 | 24 | private static final Logger log = LoggerFactory.getLogger(BlobUtils.class); 25 | 26 | public static List toTriplets(File parent, List records) { 27 | List list = new ArrayList<>(); 28 | for (CrcDao.CrcRecord r : records) { 29 | File child = new File(parent, r.name); 30 | if (!child.exists()) { 31 | // cached information is out of date 32 | // TODO: should regenerate triplets, but should rarely happen 33 | log.warn("Stale triplet information. Child does not exist: " + child.getAbsolutePath()); 34 | } else { 35 | Triplet t = new Triplet(); 36 | t.setHash(r.crc); 37 | t.setName(r.name); 38 | t.setType(Utils.toType(child)); 39 | list.add(t); 40 | } 41 | } 42 | return list; 43 | } 44 | 45 | public static byte[] loadAndVerify(File currentScanFile, BlobDao.BlobVector v) throws FileNotFoundException, IOException { 46 | RandomAccessFile raf = null; 47 | try { 48 | raf = new RandomAccessFile(currentScanFile, "r"); 49 | return FileBlobStore.readBytes(raf, v.offset, v.length, v.crc); // implicitly verifies against given crc, will throw IOException if not valid 50 | } finally { 51 | IOUtils.closeQuietly(raf); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/BlockingBlobStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | import org.hashsplit4j.api.BlobStore; 4 | 5 | /** 6 | * 7 | * @author brad 8 | */ 9 | public interface BlockingBlobStore extends BlobStore{ 10 | /** 11 | * Implementations may block here to wait for async operations to complete 12 | * 13 | */ 14 | void checkComplete() throws Exception; 15 | } 16 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/BlockingHashStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | import org.hashsplit4j.api.HashStore; 4 | 5 | /** 6 | * 7 | * @author brad 8 | */ 9 | public interface BlockingHashStore extends HashStore{ 10 | /** 11 | * Implementations may block here to wait for async operations to complete 12 | * 13 | */ 14 | void checkComplete() throws Exception; 15 | } 16 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/HttpTripletStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | import io.milton.common.Path; 4 | import java.io.ByteArrayInputStream; 5 | import java.io.IOException; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import io.milton.httpclient.Host; 10 | import org.hashsplit4j.triplets.HashCalc; 11 | import org.hashsplit4j.triplets.ITriplet; 12 | 13 | /** 14 | * Loads triplets from a remote server over HTTP. Can lookup triplets by path 15 | * or by parent directory hash 16 | * 17 | * @author brad 18 | */ 19 | public class HttpTripletStore implements ParentHashAwareTripletStore { 20 | private final Host host; 21 | private final Path rootPath; 22 | private final HashCalc hashCalc = HashCalc.getInstance(); 23 | 24 | /** 25 | * 26 | * @param httpClient 27 | * @param rootPath 28 | */ 29 | public HttpTripletStore(Host httpClient, Path rootPath) { 30 | this.host = httpClient; 31 | this.rootPath = rootPath; 32 | } 33 | 34 | @Override 35 | public List getTriplets(Path path) { 36 | Path p = rootPath.add(path); 37 | p = p.child("_triplets"); 38 | try { 39 | byte[] arrRemoteTriplets = host.doGet(p); 40 | List triplets = hashCalc.parseTriplets(new ByteArrayInputStream(arrRemoteTriplets)); 41 | return triplets; 42 | } catch (IOException ex) { 43 | throw new RuntimeException(p.toString(), ex); 44 | } catch(Throwable e) { 45 | throw new RuntimeException(p.toString(), e); 46 | } 47 | } 48 | 49 | @Override 50 | public List getTriplets(String hash) { 51 | Path p = Path.root.child("_hashes").child("dirhashes").child(hash+""); 52 | Map params = new HashMap<>(); 53 | 54 | try { 55 | byte[] arrRemoteTriplets = host.doGet(p, params); 56 | List triplets = hashCalc.parseTriplets(new ByteArrayInputStream(arrRemoteTriplets)); 57 | return triplets; 58 | } catch (IOException ex) { 59 | throw new RuntimeException(p.toString(), ex); 60 | } catch(Throwable e) { 61 | throw new RuntimeException(p.toString(), e); 62 | } 63 | } 64 | 65 | @Override 66 | public String refreshDir(Path path) { 67 | throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/MemorySyncHashCache.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | import java.io.File; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * 9 | * @author brad 10 | */ 11 | 12 | 13 | public class MemorySyncHashCache implements SyncHashCache { 14 | 15 | private final Map mapOfHashes = new HashMap<>(); 16 | 17 | @Override 18 | public String get(File file) { 19 | String key = getKey(file); 20 | return mapOfHashes.get(key); 21 | } 22 | 23 | @Override 24 | public void put(File file, String hash) { 25 | String key = getKey(file); 26 | mapOfHashes.put(key, hash); 27 | } 28 | 29 | private String getKey(File file) { 30 | String key = file.getAbsolutePath() + "-" + file.length() + "-" + file.lastModified(); 31 | return key; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/ParentHashAwareTripletStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | 4 | import java.util.List; 5 | import org.hashsplit4j.triplets.ITriplet; 6 | 7 | /** 8 | * 9 | * @author brad 10 | */ 11 | 12 | 13 | public interface ParentHashAwareTripletStore extends TripletStore { 14 | /** 15 | * Get the list of triplets when the directory hash is known 16 | * 17 | * @param hash 18 | * @return 19 | */ 20 | List getTriplets(String hash); 21 | } 22 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/PausableTripletStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | /** 4 | * 5 | * @author brad 6 | */ 7 | 8 | 9 | public interface PausableTripletStore extends TripletStore { 10 | void setPaused(boolean b); 11 | } 12 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/SyncHashCache.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * 7 | * @author brad 8 | */ 9 | 10 | 11 | public interface SyncHashCache { 12 | public String get(File file); 13 | public void put(File file, String hash); 14 | } 15 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/java/io/milton/sync/triplets/TripletStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.sync.triplets; 2 | 3 | import io.milton.common.Path; 4 | import java.util.List; 5 | import org.hashsplit4j.triplets.ITriplet; 6 | 7 | /** 8 | * A Triplet describes a member within a directory/collection, but its 9 | * name, hash, and type (and metaId, but lets ignore that because it 10 | * makes it a Quadlet which sounds crap) 11 | * 12 | * A list of Triplets defines the state of a directory/collection 13 | * 14 | * This interface defines a means of getting a list of triplets for a local 15 | * or remote directory 16 | * 17 | * @author brad 18 | */ 19 | public interface TripletStore { 20 | /** 21 | * Return the list of triplets for the given path (which might be 22 | * relative to a root location) 23 | * 24 | * @param path 25 | * @return - the list of triplets defining the state of the directory, or null 26 | * if the directory was not found 27 | */ 28 | List getTriplets(Path path); 29 | 30 | /** 31 | * Re-calc the directory hash and persist it 32 | * 33 | * @param path 34 | * @return 35 | */ 36 | String refreshDir(Path path); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/resources/Images/logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync/src/main/resources/Images/logo-dark.png -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/resources/Images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync/src/main/resources/Images/upload.png -------------------------------------------------------------------------------- /milton-cloud-sync/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Set root logger level to DEBUG and its only appender to A1. 2 | log4j.rootLogger=INFO, A1 3 | 4 | # A1 is set to be a ConsoleAppender. 5 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 6 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 7 | log4j.appender.A1.layout.ConversionPattern=%-5p %c %x - %m%n 8 | 9 | log4j.logger.io.milton=INFO 10 | log4j.logger.io.milton.event=INFO 11 | log4j.logger.io.milton.http.HttpManager=INFO 12 | log4j.logger.io.milton.http.webdav2=INFO 13 | log4j.logger.io.milton.http.fs=INFO 14 | log4j.logger.io.milton.http.json=INFO 15 | log4j.logger.io.milton.http.http11.auth=INFO 16 | log4j.logger.io.milton.http.http11.auth.CookieAuthenticationHandler=INFO 17 | log4j.logger.io.milton.cloud.server.web.SpliffySecurityManager=INFO 18 | log4j.logger.io.milton.cloud.server.web.SpliffyResourceFactory=INFO 19 | log4j.logger.com.fuselms.apps.learning.LearningApp=INFO 20 | log4j.logger.io.milton.cloud.server.apps.content.ContentApp=INFO 21 | log4j.logger.io.milton.cloud.server.apps.orgs.OrgIdsCsv=INFO 22 | 23 | log4j.logger.org.hibernate.cache.ehcache=INFO 24 | log4j.logger.org.hashsplit4j.api.Parser=INFO 25 | log4j.logger.org.springframework=WARN 26 | log4j.logger.org.hibernate=INFO 27 | log4j.logger.org.hibernate.event.def.AbstractFlushingEventListener=INFO 28 | log4j.logger.org.hibernate.SQL=INFO 29 | log4j.logger.org.apache=INFO 30 | log4j.logger.net.fortuna.ical4j=INFO 31 | log4j.logger.org.mortbay.log=INFO 32 | log4j.logger.eu.medsea=INFO 33 | log4j.logger.net.sf.ehcache=INFO 34 | log4j.logger.net.sf.json=WARN 35 | -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch1/a/a-changed.txt: -------------------------------------------------------------------------------- 1 | hello -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch1/a/a-deleted.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch1/a/a-not-changed.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch1/c/c-not-changed.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch2/a/a-changed.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch2/a/a-new1.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch2/a/a-not-changed.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch2/c/c-not-changed.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch3/a/a-changed.txt: -------------------------------------------------------------------------------- 1 | hello -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch3/a/a-deleted.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/src/test/resources/branch3/a/a-not-changed.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /milton-cloud-sync/~/syncdb.h2.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-sync/~/syncdb.h2.db -------------------------------------------------------------------------------- /milton-cloud-sync/~/syncdb.trace.db: -------------------------------------------------------------------------------- 1 | 08-22 01:08:52 jdbc[2]: Connection not closed 2 | java.lang.Exception: Stack Trace 3 | at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:121) 4 | at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:94) 5 | at org.h2.Driver.connect(Driver.java:72) 6 | at java.sql.DriverManager.getConnection(DriverManager.java:664) 7 | at java.sql.DriverManager.getConnection(DriverManager.java:247) 8 | at org.apache.commons.dbcp.DriverManagerConnectionFactory.createConnection(DriverManagerConnectionFactory.java:75) 9 | at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:582) 10 | at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1148) 11 | at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106) 12 | at com.ettrema.db.UseConnection.use(UseConnection.java:28) 13 | at io.milton.sync.JdbcHashCache.(JdbcHashCache.java:54) 14 | at io.milton.sync.SyncCommand.start(SyncCommand.java:76) 15 | at GUISync.MainPage.updateJobList(MainPage.java:488) 16 | at GUISync.MainPage.(MainPage.java:65) 17 | at GUISync.base.(base.java:22) 18 | at GUISync.base.protect(base.java:87) 19 | at GUISync.base.main(base.java:59) 20 | -------------------------------------------------------------------------------- /milton-cloud-vfs/mem.h2.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/milton-cloud-vfs/mem.h2.db -------------------------------------------------------------------------------- /milton-cloud-vfs/nb-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | all 17 | 18 | 19 | -------------------------------------------------------------------------------- /milton-cloud-vfs/nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CUSTOM-install skip tests 5 | install skip tests 6 | 7 | install 8 | 9 | 10 | true 11 | 12 | 13 | 14 | CUSTOM-deploy 15 | deploy 16 | 17 | deploy 18 | 19 | 20 | 21 | debug 22 | 23 | jar 24 | 25 | 26 | jetty:run 27 | 28 | 29 | true 30 | maven 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/common/CurrentDateService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.cloud.common; 18 | 19 | import static io.milton.context.RequestContext.C; 20 | import io.milton.http.DateUtils; 21 | import java.util.Date; 22 | 23 | /** 24 | * Simple interface to allow externalising the current date, ie for testing 25 | * 26 | * @author brad 27 | */ 28 | public interface CurrentDateService { 29 | 30 | public static Date now() { 31 | Date now = C(CurrentDateService.class).getNow(); 32 | return now; 33 | } 34 | 35 | Date getNow(); 36 | 37 | /** 38 | * Should apply localisation per user 39 | * 40 | * @param s 41 | * @return 42 | * @throws io.milton.http.DateUtils.DateParseException 43 | */ 44 | Date parseDate(String s) throws DateUtils.DateParseException; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/common/MutableCurrentDateService.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.common; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * Allows modification of the "current" date for testing purposes 7 | * 8 | * @author brad 9 | */ 10 | public class MutableCurrentDateService extends DefaultCurrentDateService implements CurrentDateService { 11 | 12 | private Date artificalDate = null; 13 | private Long dateOffset = null; 14 | 15 | @Override 16 | public Date getNow() { 17 | if (artificalDate != null) { 18 | return artificalDate; 19 | } else if (dateOffset != null) { 20 | long tm = System.currentTimeMillis() + dateOffset; 21 | return new Date(tm); 22 | } else { 23 | return new Date(); 24 | } 25 | 26 | } 27 | 28 | public Date getArtificalDate() { 29 | return artificalDate; 30 | } 31 | 32 | public void setArtificalDate(Date artificalDate) { 33 | this.artificalDate = artificalDate; 34 | } 35 | 36 | /** 37 | * Number of milliseconds to offset the actual datetime by 38 | * 39 | * @return 40 | */ 41 | public Long getDateOffset() { 42 | return dateOffset; 43 | } 44 | 45 | public void setDateOffset(Long dateOffset) { 46 | this.dateOffset = dateOffset; 47 | } 48 | 49 | public void addHours(long d) { 50 | setDateOffset(1000 * 60 * 60 * d); 51 | } 52 | 53 | /** 54 | * Set the current date offset to 1 day 55 | */ 56 | public void addDay() { 57 | setDateOffset(1000 * 60 * 60 * 24l); 58 | } 59 | 60 | public void addDays(long d) { 61 | setDateOffset(1000 * 60 * 60 * 24 * d); 62 | } 63 | 64 | /** 65 | * Set the current date offset to 1 week 66 | */ 67 | public void addWeek() { 68 | setDateOffset(1000 * 60 * 60 * 24 * 7l); 69 | } 70 | 71 | public void addWeeks(long i) { 72 | setDateOffset(1000 * 60 * 60 * 24 * 7 * i); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/common/With.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.common; 2 | 3 | /** 4 | * General purpose callback interface 5 | * 6 | * @author brad 7 | */ 8 | public interface With { 9 | O use(T t) throws Exception; 10 | } -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/AbstractRule.java: -------------------------------------------------------------------------------- 1 | 2 | package io.milton.cloud.process; 3 | 4 | import java.io.Serializable; 5 | 6 | public abstract class AbstractRule implements Rule, Serializable { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | public boolean toBool(Object o) { 11 | if (o == null) { 12 | return false; 13 | } else if (o instanceof Boolean) { 14 | return (Boolean) o; 15 | } else if (o instanceof Integer) { 16 | Integer i = (Integer) o; 17 | return i.intValue() == 0; 18 | } else if (o instanceof String) { 19 | String s = (String) o; 20 | s = s.toLowerCase(); 21 | return s.equals("true") || s.equals("yes"); 22 | } else { 23 | throw new RuntimeException("Unsupported boolean type: " + o.getClass()); 24 | } 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/ActionHandler.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | /** 4 | * Instances of this are fired on various events, such as entering or leaving states 5 | * 6 | * Must have a contructor (Element el) 7 | * 8 | * @author brad 9 | */ 10 | public interface ActionHandler { 11 | 12 | /** 13 | * Perform the action 14 | * 15 | * @param context 16 | */ 17 | void process(ProcessContext context); 18 | } 19 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/AndRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.cloud.process; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 21 | * @author brad 22 | */ 23 | public class AndRule implements Rule { 24 | 25 | private List rules; 26 | 27 | public AndRule(List rules) { 28 | this.rules = rules; 29 | } 30 | 31 | 32 | 33 | @Override 34 | public Boolean eval(ProcessContext context) { 35 | for( Rule r : rules ) { 36 | boolean result = r.eval(context); 37 | if( !result ) { 38 | return false; 39 | } 40 | } 41 | return true; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/BeanPropertyExpression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.cloud.process; 16 | 17 | import java.lang.reflect.InvocationTargetException; 18 | import org.apache.commons.beanutils.PropertyUtils; 19 | 20 | /** 21 | * 22 | * @author brad 23 | */ 24 | public class BeanPropertyExpression implements Expression { 25 | 26 | private String beanPath; 27 | 28 | public BeanPropertyExpression(String beanPath) { 29 | this.beanPath = beanPath; 30 | } 31 | 32 | @Override 33 | public Object eval(ProcessContext context) { 34 | Object val = null; 35 | try { 36 | val = PropertyUtils.getProperty(context, beanPath); 37 | } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) { 38 | throw new RuntimeException(beanPath, ex); 39 | } 40 | return val; 41 | } 42 | 43 | public String getBeanPath() { 44 | return beanPath; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/ConstantExpression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.cloud.process; 16 | 17 | /** 18 | * 19 | * @author brad 20 | */ 21 | public class ConstantExpression implements Expression { 22 | 23 | private Object value; 24 | 25 | public ConstantExpression(Object value) { 26 | this.value = value; 27 | } 28 | 29 | 30 | @Override 31 | public Object eval(ProcessContext context) { 32 | return value; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/ContainsRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | */ 3 | package io.milton.cloud.process; 4 | 5 | import io.milton.context.Registration; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import org.apache.commons.beanutils.BeanUtils; 10 | 11 | /** 12 | * Returns true if the given List contains at least 1 item which has a property 13 | * that matches the given value 14 | * 15 | * @author brad 16 | */ 17 | public class ContainsRule implements Rule { 18 | 19 | private String propertyName; 20 | private String value; 21 | 22 | public ContainsRule(String propertyName, String value) { 23 | this.propertyName = propertyName; 24 | this.value = value; 25 | } 26 | 27 | 28 | @Override 29 | public Boolean eval(ProcessContext context) { 30 | try { 31 | List arg = context.get(List.class); 32 | if (arg == null) { 33 | return false; 34 | } 35 | for (Object o : arg) { 36 | String propVal = BeanUtils.getProperty(o, propertyName); 37 | if( propVal != null && propVal.equals(value)) { 38 | return true; 39 | } 40 | } 41 | return false; 42 | } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { 43 | throw new RuntimeException(e); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/Expression.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 7 | * @author brad 8 | */ 9 | public interface Expression extends Serializable { 10 | 11 | 12 | /** 13 | * Evaluate this rule on the given context 14 | * 15 | * @param context 16 | * @return - true to indicate this rule is satisfied 17 | */ 18 | T eval(ProcessContext context); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/ListFilterExpression.java: -------------------------------------------------------------------------------- 1 | /* 2 | */ 3 | package io.milton.cloud.process; 4 | 5 | import io.milton.context.Registration; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import org.apache.commons.beanutils.BeanUtils; 10 | 11 | /** 12 | * Filter out elements of a list which do not match the bean property expression 13 | * 14 | * Can take a child expression, in which case it is passed the filtered list 15 | * and returns the child's result 16 | * 17 | * @author brad 18 | */ 19 | public class ListFilterExpression implements Expression { 20 | 21 | private String propertyName; 22 | private String value; 23 | private Expression child; 24 | 25 | public ListFilterExpression(String propertyName, String value, Expression child) { 26 | this.propertyName = propertyName; 27 | this.value = value; 28 | this.child = child; 29 | } 30 | 31 | 32 | @Override 33 | public Object eval(ProcessContext context) { 34 | try { 35 | List arg = context.get(List.class); 36 | if (arg == null) { 37 | return arg; 38 | } 39 | List newList = new ArrayList(); 40 | for (Object o : arg) { 41 | String propVal = BeanUtils.getProperty(o, propertyName); 42 | if( propVal != null && propVal.equals(value)) { 43 | newList.add(o); 44 | } 45 | } 46 | if( child == null ) { 47 | return newList; 48 | } else { 49 | Registration reg = context.put(newList); 50 | try { 51 | return child.eval(context); 52 | } finally { 53 | reg.remove(); 54 | } 55 | } 56 | } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { 57 | throw new RuntimeException(e); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/OrRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.cloud.process; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 21 | * @author brad 22 | */ 23 | public class OrRule implements Rule { 24 | 25 | private List rules; 26 | 27 | public OrRule(List rules) { 28 | this.rules = rules; 29 | } 30 | 31 | 32 | 33 | @Override 34 | public Boolean eval(ProcessContext context) { 35 | for( Rule r : rules ) { 36 | boolean result = r.eval(context); 37 | if( result ) { 38 | return true; 39 | } 40 | } 41 | return false; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/ProcessImpl.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | import io.milton.context.RootContext; 4 | import java.io.Serializable; 5 | import java.util.Collection; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class ProcessImpl implements Serializable, StateProcess { 12 | 13 | private static final Logger log = LoggerFactory.getLogger(ProcessImpl.class); 14 | private static final long serialVersionUID = 1L; 15 | private State startState; 16 | final Map statesMap = new HashMap<>(); 17 | final private String name; 18 | 19 | public ProcessImpl(String name) { 20 | this.name = name; 21 | } 22 | 23 | 24 | @Override 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | @Override 30 | public State createState(String stateName) { 31 | return new StateImpl(this, stateName); 32 | } 33 | 34 | public Collection getStates() { 35 | return statesMap.values(); 36 | } 37 | 38 | @Override 39 | public State getState(String stateName) { 40 | if (stateName == null) { 41 | throw new IllegalArgumentException("stateName is null"); 42 | } 43 | return statesMap.get(stateName); 44 | } 45 | 46 | @Override 47 | public void setStartState(State start) { 48 | this.startState = start; 49 | } 50 | 51 | @Override 52 | public State getStartState() { 53 | return startState; 54 | } 55 | 56 | @Override 57 | public Transition createTransition(String transitionName, State fromState, State toState, Rule rule) { 58 | Transition t = new TransitionImpl(this, transitionName, fromState, toState, rule); 59 | return t; 60 | } 61 | 62 | @Override 63 | public void walkStates() { 64 | statesMap.clear(); 65 | if( startState == null ) { 66 | throw new RuntimeException("Start state is not set"); 67 | } 68 | State s = this.startState; 69 | walkStates(s); 70 | } 71 | 72 | private void walkStates(State s) { 73 | log.debug("walkState: " + s.getName()); 74 | if (this.statesMap.containsValue(s)) { 75 | return; 76 | } 77 | if (this.statesMap.containsKey(s.getName())) { 78 | throw new RuntimeException("Duplicate state: " + s.getName()); 79 | } 80 | 81 | this.statesMap.put(s.getName(), s); 82 | 83 | log.debug(".. transitions: " + s.getTransitions().size()); 84 | for (Transition t : s.getTransitions()) { 85 | log.debug(".. ..transition: " + t.getName()); 86 | walkStates(t.getToState()); 87 | } 88 | } 89 | 90 | public void add(State s) { 91 | this.statesMap.put(s.getName(), s); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/ProcessInstance.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * 7 | * @author brad 8 | */ 9 | public interface ProcessInstance { 10 | 11 | void setTimeEntered(Date dateTime); 12 | 13 | String getProcessName(); 14 | 15 | String getStateName(); 16 | 17 | void setStateName(String name); 18 | 19 | Date getTimeEntered(); 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/Rule.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 7 | * @author brad 8 | */ 9 | public interface Rule extends Expression { 10 | 11 | 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/State.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | /** 7 | * A state is a definition for a state that a process instance may be in. 8 | * 9 | * Note that a state exists only within a process definition. 10 | * 11 | * A state may be time dependent. This means that the rules within the state 12 | * need to be evaluated periodically to check for transitions. This time dependence 13 | * is represented by the presence of a time dependent interval value, which will 14 | * specify the interval that the state should be polled for changed. 15 | * 16 | * @author brad 17 | */ 18 | public interface State { 19 | 20 | public enum TimeDependentInterval { 21 | NONE, 22 | MINUTE, 23 | HOUR, 24 | DAY, 25 | WEEK 26 | } 27 | 28 | String getName(); 29 | 30 | List getOnEnterHandlers(); 31 | 32 | List getOnExitHandlers(); 33 | 34 | StateProcess getProcess(); 35 | 36 | Map getSubProcesses(); 37 | 38 | Transitions getTransitions(); 39 | 40 | TimeDependentInterval getInterval(); 41 | 42 | void setInterval(TimeDependentInterval interval); 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/StateImpl.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public class StateImpl implements Serializable, State { 9 | 10 | private static final long serialVersionUID = 1L; 11 | private String name; 12 | private Map subProcesses; 13 | private StateProcess process; 14 | private TimeDependentInterval interval; 15 | final Transitions transitions = new Transitions(this); 16 | final List onEnterHandlers = new ArrayList<>(); 17 | final List onExitHandlers = new ArrayList<>(); 18 | 19 | public StateImpl(StateProcess process, String name) { 20 | if (process == null) { 21 | throw new IllegalArgumentException("process cannot be null"); 22 | } 23 | if (name == null) { 24 | throw new IllegalArgumentException("state name cannot be null"); 25 | } 26 | if (!name.trim().equals(name)) { 27 | throw new IllegalArgumentException("state name cannot begin or end with white space"); 28 | } 29 | if (name.length() == 0) { 30 | throw new IllegalArgumentException("state name cannot be blank"); 31 | } 32 | this.name = name; 33 | this.process = process; 34 | } 35 | 36 | @Override 37 | public Transitions getTransitions() { 38 | return transitions; 39 | } 40 | 41 | @Override 42 | public Map getSubProcesses() { 43 | return subProcesses; 44 | } 45 | 46 | @Override 47 | public String getName() { 48 | return name; 49 | } 50 | 51 | @Override 52 | public StateProcess getProcess() { 53 | return process; 54 | } 55 | 56 | @Override 57 | public List getOnEnterHandlers() { 58 | return onEnterHandlers; 59 | } 60 | 61 | @Override 62 | public List getOnExitHandlers() { 63 | return onExitHandlers; 64 | } 65 | 66 | @Override 67 | public TimeDependentInterval getInterval() { 68 | return interval; 69 | } 70 | 71 | 72 | @Override 73 | public void setInterval(TimeDependentInterval interval) { 74 | this.interval = interval; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/StateProcess.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | 4 | /** 5 | * 6 | * @author brad 7 | */ 8 | public interface StateProcess { 9 | 10 | /** 11 | * The name of this process 12 | * 13 | * @return 14 | */ 15 | String getName(); 16 | 17 | /** 18 | * Create a new state, initially disconnected from the graph 19 | * 20 | * @param stateName 21 | * @return 22 | */ 23 | State createState(String stateName); 24 | 25 | Transition createTransition(String transitionName, State from, State to, Rule rule); 26 | 27 | /** 28 | * Locate the named state 29 | */ 30 | State getState(String stateName); 31 | 32 | /** 33 | * Return the initial state for new process instances 34 | * 35 | * @return 36 | */ 37 | State getStartState(); 38 | 39 | /** 40 | * Set the start state for new process instances 41 | * 42 | * @param start 43 | */ 44 | void setStartState(State start); 45 | 46 | 47 | /** 48 | * Must call this after adding states programmatically. Automatically called 49 | * when loading xml 50 | */ 51 | void walkStates(); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/TimeDependentRule.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | /** 4 | * Extension to Rule which has hooks for activating and de-activating timers 5 | * 6 | * @author brad 7 | */ 8 | public interface TimeDependentRule extends Rule { 9 | /** 10 | * Called when a token enters the state which contains this rule 11 | * 12 | * @param context 13 | */ 14 | void arm(ProcessContext context); 15 | 16 | /* Called when a token leaves the state which contains this rule 17 | */ 18 | void disarm(ProcessContext context); 19 | } 20 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/TimerService.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | /** 4 | * Used to record time dependent states of process instances 5 | * 6 | * Note that implementations must correctly check for previous state when 7 | * registering and unregistering. Eg if registering, its possible that the 8 | * process has already been registered in which case it should do nothing. And 9 | * same for unregistering - ie there might not be anything to unregister 10 | * 11 | * @author brad 12 | */ 13 | public interface TimerService { 14 | /** 15 | * Ensure the given process instance is registered for timer scanning. Note that the instance 16 | * may already be registered 17 | * 18 | * @param context 19 | */ 20 | public void registerTimer(ProcessContext context); 21 | 22 | /** 23 | * Ensure that the process instance is not registered for timer scanning. It 24 | * might already not be registered 25 | * 26 | * @param context 27 | */ 28 | public void unRegisterTimer(ProcessContext context); 29 | } 30 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/Transition.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | import java.util.List; 4 | 5 | 6 | /** 7 | * 8 | * @author brad 9 | */ 10 | public interface Transition { 11 | 12 | void setFromState(State fromState); 13 | 14 | State getFromState(); 15 | 16 | String getName(); 17 | 18 | Rule getRule(); 19 | 20 | State getToState(); 21 | 22 | void setToState(State to); 23 | 24 | void setRule(Rule rule); 25 | 26 | List getOnTransitionHandlers(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/TransitionImpl.java: -------------------------------------------------------------------------------- 1 | 2 | package io.milton.cloud.process; 3 | 4 | import java.io.Serializable; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * A connection from one state to another. Defines criteria for how the transition 10 | * can occur 11 | * 12 | * @author brad 13 | */ 14 | public class TransitionImpl implements Serializable, Transition{ 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | private StateProcess process; 19 | private String name; 20 | private State fromState; 21 | private State toState; 22 | private Rule rule; 23 | 24 | private List onTransitionHandlers = new ArrayList<>(); 25 | 26 | public TransitionImpl(StateProcess process, String name) { 27 | this.process = process; 28 | this.name = name; 29 | } 30 | 31 | public TransitionImpl(StateProcess process, String name, State fromState, State toState, Rule rule) { 32 | this(process,name); 33 | this.fromState = fromState; 34 | this.toState = toState; 35 | this.rule = rule; 36 | } 37 | 38 | 39 | 40 | @Override 41 | public State getToState() { 42 | return toState; 43 | } 44 | 45 | @Override 46 | public void setToState(State toState) { 47 | this.toState = toState; 48 | } 49 | 50 | 51 | @Override 52 | public void setRule(Rule rule) { 53 | this.rule = rule; 54 | } 55 | 56 | @Override 57 | public Rule getRule() { 58 | return rule; 59 | } 60 | 61 | @Override 62 | public String getName() { 63 | return name; 64 | } 65 | 66 | @Override 67 | public State getFromState() { 68 | return fromState; 69 | } 70 | 71 | @Override 72 | public void setFromState(State fromState) { 73 | this.fromState = fromState; 74 | } 75 | 76 | @Override 77 | public List getOnTransitionHandlers() { 78 | return onTransitionHandlers; 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/Transitions.java: -------------------------------------------------------------------------------- 1 | package io.milton.cloud.process; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Transitions extends ArrayList { 6 | 7 | private static final long serialVersionUID = 3707385917870101891L; 8 | 9 | private final State fromState; 10 | 11 | public Transitions(State state) { 12 | super(); 13 | this.fromState = state; 14 | } 15 | 16 | @Override 17 | public boolean add(Transition t) { 18 | if( get(t.getName()) != null ) throw new IllegalArgumentException("State " + fromState.getName() + " already contains transition: " + t.getName()); 19 | return super.add(t); 20 | } 21 | 22 | 23 | public Transition get(String name) { 24 | for( Transition t : this ) { 25 | if( t.getName().equals(name)) return t; 26 | } 27 | return null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/cloud/process/TrueRule.java: -------------------------------------------------------------------------------- 1 | 2 | package io.milton.cloud.process; 3 | 4 | public class TrueRule extends AbstractRule { 5 | 6 | private static final long serialVersionUID = 1L; 7 | 8 | public TrueRule() { 9 | } 10 | 11 | @Override 12 | public Boolean eval(ProcessContext context) { 13 | return true; 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/content/DbHashStore.java: -------------------------------------------------------------------------------- 1 | package io.milton.vfs.content; 2 | 3 | import java.util.List; 4 | import org.hashsplit4j.api.Fanout; 5 | import org.hashsplit4j.api.HashStore; 6 | import io.milton.vfs.db.FanoutHash; 7 | import io.milton.vfs.db.utils.SessionManager; 8 | 9 | /** 10 | * 11 | * @author brad 12 | */ 13 | public class DbHashStore implements HashStore{ 14 | 15 | 16 | @Override 17 | public void setChunkFanout(String hash, List childCrcs, long actualContentLength) { 18 | if( hasChunk(hash)) { 19 | return ; 20 | } 21 | FanoutHash.insertFanout("c", hash, childCrcs, actualContentLength, SessionManager.session()); 22 | } 23 | 24 | @Override 25 | public Fanout getChunkFanout(String hash) { 26 | return getFanout(hash, "c"); 27 | } 28 | 29 | @Override 30 | public boolean hasChunk(String hash) { 31 | return getFanout(hash, "c") != null; 32 | } 33 | 34 | 35 | @Override 36 | public void setFileFanout(String hash, List fanoutHashes, long actualContentLength) { 37 | if( hasFile(hash)) { 38 | return ; 39 | } 40 | FanoutHash.insertFanout("f", hash, fanoutHashes, actualContentLength, SessionManager.session()); 41 | } 42 | 43 | @Override 44 | public Fanout getFileFanout(String fileHash) { 45 | return getFanout(fileHash, "f"); 46 | } 47 | 48 | @Override 49 | public boolean hasFile(String fileHash) { 50 | return getFileFanout(fileHash) != null; 51 | } 52 | 53 | private Fanout getFanout(String hash, String type) { 54 | return FanoutHash.findByHashAndType(hash, type, SessionManager.session()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/data/NodesChangedEvent.java: -------------------------------------------------------------------------------- 1 | package io.milton.vfs.data; 2 | 3 | import io.milton.event.Event; 4 | import java.util.List; 5 | 6 | /** 7 | * 8 | * 9 | * @author brad 10 | */ 11 | public class NodesChangedEvent implements Event{ 12 | private final DataSession sourceSession; 13 | private final List directoryNodes; 14 | 15 | public NodesChangedEvent(DataSession sourceSession, List directoryNodes) { 16 | this.sourceSession = sourceSession; 17 | this.directoryNodes = directoryNodes; 18 | } 19 | 20 | public List getDirectoryNodes() { 21 | return directoryNodes; 22 | } 23 | 24 | public DataSession getSourceSession() { 25 | return sourceSession; 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/AbstractVfsVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.vfs.db; 16 | 17 | /** 18 | * 19 | * @author brad 20 | */ 21 | public abstract class AbstractVfsVisitor implements VfsVisitor { 22 | 23 | @Override 24 | public void visit(Website c) { 25 | } 26 | 27 | @Override 28 | public void visit(Organisation p) { 29 | } 30 | 31 | @Override 32 | public void visit(Profile r) { 33 | } 34 | 35 | @Override 36 | public void visit(Branch r) { 37 | } 38 | 39 | @Override 40 | public void visit(BaseEntity r) { 41 | 42 | } 43 | 44 | @Override 45 | public void visit(Group r) { 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/AddressBook.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.vfs.db; 18 | 19 | import java.io.Serializable; 20 | import java.util.Date; 21 | import java.util.List; 22 | import javax.persistence.*; 23 | import org.hibernate.Session; 24 | import org.hibernate.annotations.Cache; 25 | import org.hibernate.annotations.CacheConcurrencyStrategy; 26 | 27 | /** 28 | * An AddressBook is a Repository which can have linked contact records. 29 | * 30 | * The contact records provide a search optimised view of the CARDDAV data held 31 | * in the repository 32 | * 33 | * @author brad 34 | */ 35 | @Entity 36 | @DiscriminatorValue("AB") 37 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 38 | public class AddressBook extends Repository { 39 | 40 | private List contacts; 41 | 42 | @Override 43 | @Transient 44 | public String getRepoType() { 45 | return "AB"; 46 | } 47 | 48 | 49 | 50 | @OneToMany(mappedBy = "addressBook") 51 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 52 | public List getContacts() { 53 | return contacts; 54 | } 55 | 56 | public void setContacts(List contacts) { 57 | this.contacts = contacts; 58 | } 59 | 60 | @Override 61 | public void delete(Session session) { 62 | if (getContacts() != null) { 63 | for (Contact c : getContacts()) { 64 | session.delete(c); 65 | } 66 | setContacts(null); 67 | } 68 | super.delete(session); 69 | } 70 | 71 | public Contact contact(String name) { 72 | if (getContacts() != null) { 73 | for (Contact c : getContacts()) { 74 | if (c.getName().equals(name)) { 75 | return c; 76 | } 77 | } 78 | } 79 | return null; 80 | } 81 | 82 | @Override 83 | public String type() { 84 | return "AB"; 85 | } 86 | 87 | public Contact add(String name) { 88 | Contact c = new Contact(); 89 | c.setAddressBook(this); 90 | c.setName(name); 91 | return c; 92 | } 93 | 94 | 95 | } 96 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/BlobHash.java: -------------------------------------------------------------------------------- 1 | package io.milton.vfs.db; 2 | 3 | import io.milton.vfs.db.utils.SessionManager; 4 | import java.io.Serializable; 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.Id; 8 | import org.hibernate.annotations.Cache; 9 | import org.hibernate.annotations.CacheConcurrencyStrategy; 10 | import org.hibernate.annotations.Index; 11 | 12 | /** 13 | * 14 | * @author brad 15 | */ 16 | @Entity 17 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 18 | public class BlobHash implements Serializable { 19 | private long blobHash; 20 | private long volumeId; 21 | 22 | public static BlobHash findByHash(long hash) { 23 | return (BlobHash) SessionManager.session().get(BlobHash.class, hash); 24 | } 25 | 26 | 27 | @Id 28 | @Index(name="ids_blobhash") 29 | public long getBlobHash() { 30 | return blobHash; 31 | } 32 | 33 | public void setBlobHash(long hash) { 34 | this.blobHash = hash; 35 | } 36 | 37 | @Column(nullable=false) 38 | public long getVolumeId() { 39 | return volumeId; 40 | } 41 | 42 | public void setVolumeId(long volumeId) { 43 | this.volumeId = volumeId; 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/CalEventProcess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.vfs.db; 16 | 17 | import javax.persistence.DiscriminatorValue; 18 | import javax.persistence.ManyToOne; 19 | import org.hibernate.annotations.Cache; 20 | import org.hibernate.annotations.CacheConcurrencyStrategy; 21 | 22 | /** 23 | * 24 | * @author brad 25 | */ 26 | 27 | @javax.persistence.Entity 28 | @DiscriminatorValue("P") 29 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 30 | public class CalEventProcess extends BaseProcess{ 31 | private CalEvent calEvent; 32 | 33 | @ManyToOne(optional=false) 34 | public CalEvent getCalEvent() { 35 | return calEvent; 36 | } 37 | 38 | public void setCalEvent(CalEvent profile) { 39 | this.calEvent = profile; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/ContactExtendedProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.vfs.db; 18 | 19 | import java.io.Serializable; 20 | import javax.persistence.*; 21 | import org.hibernate.annotations.Cache; 22 | import org.hibernate.annotations.CacheConcurrencyStrategy; 23 | 24 | /** 25 | * A NvPair is to allow data capture for entities such as users, groups and organisations 26 | * 27 | * The definition of what needs to be captured is held elsewhere. 28 | * 29 | * Values are stored in a string representation. Knowledge of the type of the data 30 | * in the data capture definition is required to parse the value 31 | * 32 | * @author brad 33 | */ 34 | @Entity 35 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 36 | public class ContactExtendedProperty implements Serializable{ 37 | private Long id; 38 | private Contact contact; 39 | private String name; 40 | private String propValue; 41 | 42 | @Id 43 | @GeneratedValue 44 | public Long getId() { 45 | return id; 46 | } 47 | 48 | public void setId(Long id) { 49 | this.id = id; 50 | } 51 | 52 | @ManyToOne(optional=false) 53 | public Contact getContact() { 54 | return contact; 55 | } 56 | 57 | public void setContact(Contact contact) { 58 | this.contact = contact; 59 | } 60 | 61 | 62 | 63 | @Column(nullable=false) 64 | public String getName() { 65 | return name; 66 | } 67 | 68 | public void setName(String name) { 69 | this.name = name; 70 | } 71 | 72 | @Column(nullable=false) 73 | public String getPropValue() { 74 | return propValue; 75 | } 76 | 77 | public void setPropValue(String propValue) { 78 | this.propValue = propValue; 79 | } 80 | 81 | 82 | 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/Credential.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.vfs.db; 18 | 19 | import java.io.Serializable; 20 | import java.util.Date; 21 | import javax.persistence.*; 22 | import org.hibernate.annotations.Cache; 23 | import org.hibernate.annotations.CacheConcurrencyStrategy; 24 | 25 | /** 26 | * A credential is a means of authenticating a user, such as a usename and password, 27 | * or a facebook account. 28 | * 29 | * A credential may be associated with multiple user profiles, but it must be 30 | * associated with only one profile within an organisation. 31 | * 32 | * Permissions are assigned to user profiles, rather then credentials, because 33 | * there may be multiple credentials to identify a user. The focal point of the 34 | * credentials is the user profile 35 | * 36 | * @author brad 37 | */ 38 | @Entity 39 | @Inheritance(strategy = InheritanceType.SINGLE_TABLE) 40 | @DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING, length = 20) 41 | @DiscriminatorValue("E") 42 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 43 | public class Credential implements Serializable{ 44 | private Profile profile; 45 | private long id; 46 | private String type; 47 | private Date createdDate; 48 | private Date modifiedDate; 49 | 50 | @Id 51 | @GeneratedValue 52 | public long getId() { 53 | return id; 54 | } 55 | 56 | public void setId(long id) { 57 | this.id = id; 58 | } 59 | 60 | @Column(insertable=false, updatable=false) 61 | public String getType() { 62 | return type; 63 | } 64 | 65 | public void setType(String type) { 66 | this.type = type; 67 | } 68 | 69 | 70 | 71 | 72 | @Column(nullable = false) 73 | @Temporal(javax.persistence.TemporalType.TIMESTAMP) 74 | public Date getCreatedDate() { 75 | return createdDate; 76 | } 77 | 78 | public void setCreatedDate(Date createdDate) { 79 | this.createdDate = createdDate; 80 | } 81 | 82 | @Column(nullable = false) 83 | @Temporal(javax.persistence.TemporalType.TIMESTAMP) 84 | public Date getModifiedDate() { 85 | return modifiedDate; 86 | } 87 | 88 | public void setModifiedDate(Date modifiedDate) { 89 | this.modifiedDate = modifiedDate; 90 | } 91 | 92 | @ManyToOne(optional=false) 93 | public Profile getProfile() { 94 | return profile; 95 | } 96 | 97 | public void setProfile(Profile profile) { 98 | this.profile = profile; 99 | } 100 | 101 | 102 | 103 | } 104 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/FanoutEntry.java: -------------------------------------------------------------------------------- 1 | package io.milton.vfs.db; 2 | 3 | import java.io.Serializable; 4 | import javax.persistence.*; 5 | import org.hibernate.annotations.Cache; 6 | import org.hibernate.annotations.CacheConcurrencyStrategy; 7 | import org.hibernate.annotations.Index; 8 | 9 | /** 10 | * 11 | * @author brad 12 | */ 13 | @Entity 14 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 15 | public class FanoutEntry implements Serializable{ 16 | private long id; 17 | private FanoutHash fanout; 18 | private String chunkHash; 19 | 20 | @Column 21 | @Index(name="ids_chunk_hash") 22 | public String getChunkHash() { 23 | return chunkHash; 24 | } 25 | 26 | public void setChunkHash(String chunkHash) { 27 | this.chunkHash = chunkHash; 28 | } 29 | 30 | @ManyToOne 31 | public FanoutHash getFanout() { 32 | return fanout; 33 | } 34 | 35 | public void setFanout(FanoutHash fanout) { 36 | this.fanout = fanout; 37 | } 38 | 39 | @Id 40 | @GeneratedValue 41 | public long getId() { 42 | return id; 43 | } 44 | 45 | public void setId(long id) { 46 | this.id = id; 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/GroupInWebsite.java: -------------------------------------------------------------------------------- 1 | package io.milton.vfs.db; 2 | 3 | import io.milton.vfs.db.utils.DbUtils; 4 | import java.io.Serializable; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import javax.persistence.*; 8 | import org.hibernate.Criteria; 9 | import org.hibernate.Session; 10 | import org.hibernate.annotations.Cache; 11 | import org.hibernate.annotations.CacheConcurrencyStrategy; 12 | import org.hibernate.criterion.Restrictions; 13 | 14 | /** 15 | * Creates a link between a program and a website, which makes that program 16 | * available on that website. Groups are given access to programs, so a user can 17 | * only access program content on a website if they are in a group which has 18 | * been given access to that program 19 | * 20 | * @author brad 21 | */ 22 | @Entity 23 | @Table(uniqueConstraints = { 24 | @UniqueConstraint(columnNames = {"user_group_id", "website_id"})}// item names must be unique within a directory 25 | ) 26 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 27 | public class GroupInWebsite implements Serializable { 28 | 29 | public static List findByWebsite(Website w, Session session) { 30 | Criteria crit = session.createCriteria(GroupInWebsite.class); 31 | crit.setCacheable(true); 32 | crit.add(Restrictions.eq("website", w)); 33 | List list = new ArrayList<>(); 34 | for( GroupInWebsite giw : DbUtils.toList(crit, GroupInWebsite.class) ) { 35 | if( !giw.getUserGroup().deleted()) { 36 | list.add(giw); 37 | } 38 | } 39 | return list; 40 | } 41 | 42 | public static List findByGroup(Group g, Session session) { 43 | Criteria crit = session.createCriteria(GroupInWebsite.class); 44 | crit.setCacheable(true); 45 | crit.add(Restrictions.eq("userGroup", g)); 46 | return DbUtils.toList(crit, GroupInWebsite.class); 47 | } 48 | 49 | 50 | private long id; 51 | private Group userGroup; 52 | private Website website; 53 | 54 | @Id 55 | @GeneratedValue 56 | public long getId() { 57 | return id; 58 | } 59 | 60 | public void setId(long id) { 61 | this.id = id; 62 | } 63 | 64 | @ManyToOne(optional=false) 65 | public Group getUserGroup() { 66 | return userGroup; 67 | } 68 | 69 | public void setUserGroup(Group g) { 70 | this.userGroup = g; 71 | } 72 | 73 | @ManyToOne(optional = false) 74 | public Website getWebsite() { 75 | return website; 76 | } 77 | 78 | public void setWebsite(Website website) { 79 | this.website = website; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/ImprovedImplicitNamingStrategy.java: -------------------------------------------------------------------------------- 1 | 2 | package io.milton.vfs.db; 3 | 4 | import org.hibernate.boot.model.naming.Identifier; 5 | import org.hibernate.boot.model.naming.ImplicitBasicColumnNameSource; 6 | import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl; 7 | import org.hibernate.boot.model.naming.ImplicitPrimaryKeyJoinColumnNameSource; 8 | 9 | /** 10 | * 11 | * @author brad 12 | */ 13 | 14 | 15 | public class ImprovedImplicitNamingStrategy extends ImplicitNamingStrategyJpaCompliantImpl{ 16 | 17 | 18 | @Override 19 | public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source) { 20 | Identifier id = super.determineBasicColumnName(source); 21 | //System.out.println("determineBasicColumnName -> " + id.getText() ); 22 | return id; 23 | } 24 | 25 | @Override 26 | public Identifier determinePrimaryKeyJoinColumnName(ImplicitPrimaryKeyJoinColumnNameSource source) { 27 | Identifier id = super.determinePrimaryKeyJoinColumnName(source); 28 | //System.out.println("determinePrimaryKeyJoinColumnName -> " + id.getText() ); 29 | return id; 30 | } 31 | 32 | 33 | 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/ImprovedPhysicalNamingStrategy.java: -------------------------------------------------------------------------------- 1 | package io.milton.vfs.db; 2 | 3 | import org.hibernate.boot.model.naming.Identifier; 4 | import org.hibernate.boot.model.naming.PhysicalNamingStrategy; 5 | import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; 6 | 7 | /** 8 | * 9 | * @author brad 10 | */ 11 | public class ImprovedPhysicalNamingStrategy implements PhysicalNamingStrategy { 12 | 13 | @Override 14 | public Identifier toPhysicalCatalogName(final Identifier identifier, final JdbcEnvironment jdbcEnv) { 15 | return convertToSnakeCase(identifier); 16 | } 17 | 18 | @Override 19 | public Identifier toPhysicalColumnName(final Identifier identifier, final JdbcEnvironment jdbcEnv) { 20 | if( identifier == null ) { 21 | return null; 22 | } 23 | String orig = identifier.getText(); 24 | Identifier newID = convertToSnakeCase(identifier); 25 | //System.out.println("toPhysicalColumnName col: " + orig + " -> " + newID.getText()); 26 | return newID; 27 | } 28 | 29 | @Override 30 | public Identifier toPhysicalSchemaName(final Identifier identifier, final JdbcEnvironment jdbcEnv) { 31 | return convertToSnakeCase(identifier); 32 | } 33 | 34 | @Override 35 | public Identifier toPhysicalSequenceName(final Identifier identifier, final JdbcEnvironment jdbcEnv) { 36 | return convertToSnakeCase(identifier); 37 | } 38 | 39 | @Override 40 | public Identifier toPhysicalTableName(final Identifier identifier, final JdbcEnvironment jdbcEnv) { 41 | return convertToSnakeCase(identifier); 42 | } 43 | 44 | private Identifier convertToSnakeCase(final Identifier identifier) { 45 | if( identifier == null ) { 46 | return null; 47 | } 48 | final String regex = "([a-z])([A-Z])"; 49 | final String replacement = "$1_$2"; 50 | final String newName = identifier.getText() 51 | .replaceAll(regex, replacement) 52 | .toLowerCase(); 53 | return Identifier.toIdentifier(newName); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/MembershipProcess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.vfs.db; 16 | 17 | import javax.persistence.DiscriminatorValue; 18 | import org.hibernate.annotations.Cache; 19 | import org.hibernate.annotations.CacheConcurrencyStrategy; 20 | 21 | /** 22 | * This process tracks a user's progress through a program; 23 | * 24 | * @author brad 25 | */ 26 | @javax.persistence.Entity 27 | @DiscriminatorValue("P") 28 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 29 | public class MembershipProcess extends BaseProcess { 30 | 31 | private GroupMembership membership; 32 | 33 | public GroupMembership getMembership() { 34 | return membership; 35 | } 36 | 37 | public void setMembership(GroupMembership membership) { 38 | this.membership = membership; 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/NvPair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.vfs.db; 16 | 17 | import java.io.Serializable; 18 | import java.util.Collections; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | import javax.persistence.*; 22 | import org.hibernate.Session; 23 | import org.hibernate.annotations.Cache; 24 | import org.hibernate.annotations.CacheConcurrencyStrategy; 25 | 26 | /** 27 | * A NvPair is to allow data capture for entities such as users, groups and organisations 28 | * 29 | * Every NvPair is associated with a NvSet. The owning entity should have a reference 30 | * to the set. NvPairs and sets should be considered immutable, so instead of updating 31 | * the value, create a new set with a new NvPair for each item, and then link 32 | * the owning entity to the set. Remember to set the previousSetId on the new 33 | * set to the previous set to allow navigating old versions 34 | * 35 | * The definition of what needs to be captured is held elsewhere. 36 | * 37 | * Values are stored in a string representation. Knowledge of the type of the data 38 | * in the data capture definition is required to parse the value 39 | * 40 | * @author brad 41 | */ 42 | @Entity 43 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 44 | public class NvPair implements Serializable{ 45 | private Long id; 46 | private NvSet nvSet; 47 | private String name; 48 | private String propValue; 49 | 50 | @Id 51 | @GeneratedValue 52 | public Long getId() { 53 | return id; 54 | } 55 | 56 | public void setId(Long id) { 57 | this.id = id; 58 | } 59 | 60 | @Column(nullable=false) 61 | public String getName() { 62 | return name; 63 | } 64 | 65 | public void setName(String name) { 66 | this.name = name; 67 | } 68 | 69 | @Column(nullable=false) 70 | public String getPropValue() { 71 | return propValue; 72 | } 73 | 74 | public void setPropValue(String propValue) { 75 | this.propValue = propValue; 76 | } 77 | 78 | @ManyToOne(optional = false) 79 | public NvSet getNvSet() { 80 | return nvSet; 81 | } 82 | 83 | public void setNvSet(NvSet nvSet) { 84 | this.nvSet = nvSet; 85 | } 86 | 87 | 88 | 89 | 90 | 91 | public void delete(Session session) { 92 | session.delete(this); 93 | } 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/PasswordCredential.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.vfs.db; 18 | 19 | import javax.persistence.Column; 20 | import javax.persistence.DiscriminatorValue; 21 | import javax.persistence.Entity; 22 | import org.hibernate.annotations.Cache; 23 | import org.hibernate.annotations.CacheConcurrencyStrategy; 24 | 25 | /** 26 | * Represents a password authentication factor, to be combined with the 27 | * username or email address of a User 28 | * 29 | * @author brad 30 | */ 31 | @Entity 32 | @DiscriminatorValue(value="P") 33 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 34 | public class PasswordCredential extends Credential{ 35 | private String password; 36 | 37 | /** 38 | * This should be nullable=false, but because we're using single-table 39 | * inheritance and other subclasses do not set password it needs to be nullable 40 | * 41 | * @return 42 | */ 43 | @Column(nullable=true) 44 | public String getPassword() { 45 | return password; 46 | } 47 | 48 | public void setPassword(String password) { 49 | this.password = password; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/VfsAcceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package io.milton.vfs.db; 16 | 17 | /** 18 | * 19 | * @author brad 20 | */ 21 | public interface VfsAcceptor { 22 | void accept(VfsVisitor visitor); 23 | } 24 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/main/java/io/milton/vfs/db/VfsVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 McEvoy Software Ltd 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package io.milton.vfs.db; 18 | 19 | /** 20 | * 21 | * @author brad 22 | */ 23 | public interface VfsVisitor { 24 | void visit(Website c); 25 | void visit(Organisation p); 26 | void visit(Profile r); 27 | void visit(Branch r); 28 | void visit(BaseEntity r); 29 | void visit(Group r); 30 | } 31 | -------------------------------------------------------------------------------- /milton-cloud-vfs/src/test/java/ConflictTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 McEvoy Software Ltd. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | import org.hibernate.Session; 17 | import org.hibernate.SessionFactory; 18 | import org.junit.After; 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | 22 | /** 23 | * 24 | * @author brad 25 | */ 26 | public class ConflictTest { 27 | 28 | SessionFactory sessionFactory; 29 | Session session; 30 | 31 | @Before 32 | public void setUp() { 33 | // 34 | // AnnotationConfiguration configuration = new AnnotationConfiguration(); 35 | // configuration.addAnnotatedClass(Repository.class) 36 | // .addAnnotatedClass(Branch.class) 37 | // .addAnnotatedClass(Commit.class) 38 | // .addAnnotatedClass(FanoutEntry.class) 39 | // .addAnnotatedClass(FanoutHash.class) 40 | // .addAnnotatedClass(BlobHash.class) 41 | // ; 42 | // configuration.setProperty("hibernate.dialect","org.hibernate.dialect.H2Dialect"); 43 | // configuration.setProperty("hibernate.connection.driver_class","org.h2.Driver"); 44 | // configuration.setProperty("hibernate.connection.url", "jdbc:h2:mem"); 45 | // configuration.setProperty("hibernate.hbm2ddl.auto", "create"); 46 | // 47 | // sessionFactory = configuration.buildSessionFactory(); 48 | // session = sessionFactory.openSession(); 49 | 50 | } 51 | 52 | @After 53 | public void tearDown() { 54 | } 55 | 56 | @Test 57 | public void hello() { 58 | System.out.println("hello"); 59 | } 60 | } -------------------------------------------------------------------------------- /milton-cloud-vfs/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Set root logger level to DEBUG and its only appender to A1. 2 | log4j.rootLogger=DEBUG, A1 3 | 4 | # A1 is set to be a ConsoleAppender. 5 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 6 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 7 | log4j.appender.A1.layout.ConversionPattern=%-5p %c %x - %m%n 8 | 9 | log4j.appender.A2=org.apache.log4j.FileAppender 10 | log4j.appender.A2.File=/a.log 11 | log4j.appender.A2.layout=org.apache.log4j.PatternLayout 12 | log4j.appender.A2.layout.ConversionPattern=%-5p %c %x - %m%n 13 | 14 | log4j.logger.org.spliffy=TRACE 15 | 16 | log4j.logger.com.ettrema=INFO 17 | log4j.logger.com.ettrema.ldap=INFO 18 | 19 | log4j.logger.com.bradmcevoy=INFO 20 | log4j.logger.com.bradmcevoy.property=INFO 21 | log4j.logger.com.bradmcevoy.http.MultipleResourceFactory=TRACE 22 | log4j.logger.com.bradmcevoy.http.webdav.PropFindPropertyBuilder=INFO 23 | log4j.logger.com.bradmcevoy.property.BeanPropertySource=INFO 24 | 25 | log4j.logger.org.springframework=WARN 26 | log4j.logger.org.hibernate=INFO 27 | log4j.logger.org.apache=INFO 28 | log4j.logger.net.fortuna.ical4j=INFO -------------------------------------------------------------------------------- /nb-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | all 17 | 18 | 19 | -------------------------------------------------------------------------------- /nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CUSTOM-deploy 6 | deploy 7 | 8 | deploy 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /v2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/v2 -------------------------------------------------------------------------------- /velocity.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kademi/milton-cloud/579f6b0e0ec211252da431ecc2c43667edb4d3a6/velocity.log --------------------------------------------------------------------------------